Skip to content

Commit bdf1221

Browse files
authored
Engine pool functions (#3346)
1 parent 545f54b commit bdf1221

30 files changed

+723
-51
lines changed

Client/game_sa/CBuildingsPoolSA.cpp

Lines changed: 151 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include <game/CWorld.h>
1717
#include "CGameSA.h"
1818
#include "CPtrNodeSingleListSA.h"
19+
#include "MemSA.h"
20+
#include "CVehicleSA.h"
1921

2022
extern CGameSA* pGame;
2123

@@ -93,16 +95,13 @@ void CBuildingsPoolSA::RemoveBuilding(CBuilding* pBuilding)
9395
if (dwElementIndexInPool == UINT_MAX)
9496
return;
9597

96-
// Remove building from world
97-
pGame->GetWorld()->Remove(pInterface, CBuildingPool_Destructor);
98-
9998
// Remove building from cover list
100-
CPtrNodeSingleListSAInterface<CBuildingSAInterface>* coverList = reinterpret_cast<CPtrNodeSingleListSAInterface<CBuildingSAInterface>*>(0xC1A2B8);
101-
coverList->RemoveItem(pInterface);
99+
pGame->GetCoverManager()->RemoveCover(pInterface);
102100

103101
// Remove plant
104-
using CPlantColEntry_Remove = CEntitySAInterface* (*)(CEntitySAInterface*);
105-
((CPlantColEntry_Remove)0x5DBEF0)(pInterface);
102+
pGame->GetPlantManager()->RemovePlant(pInterface);
103+
104+
RemoveBuildingFromWorld(pInterface);
106105

107106
// Remove col reference
108107
auto modelInfo = pGame->GetModelInfo(pBuilding->GetModelIndex());
@@ -127,16 +126,23 @@ void CBuildingsPoolSA::RemoveAllBuildings()
127126
if (m_pOriginalBuildingsBackup)
128127
return;
129128

129+
pGame->GetCoverManager()->RemoveAllCovers();
130+
pGame->GetPlantManager()->RemoveAllPlants();
131+
132+
// Remove all shadows
133+
using CStencilShadowObjects_dtorAll = void* (*)();
134+
((CStencilShadowObjects_dtorAll)0x711390)();
135+
130136
m_pOriginalBuildingsBackup = std::make_unique<std::array<std::pair<bool, CBuildingSAInterface>, MAX_BUILDINGS>>();
131137

132138
auto pBuildsingsPool = (*m_ppBuildingPoolInterface);
133139
for (size_t i = 0; i < MAX_BUILDINGS; i++)
134140
{
135141
if (pBuildsingsPool->IsContains(i))
136142
{
137-
auto building = pBuildsingsPool->GetObject(i);
143+
CBuildingSAInterface* building = pBuildsingsPool->GetObject(i);
138144

139-
pGame->GetWorld()->Remove(building, CBuildingPool_Destructor);
145+
RemoveBuildingFromWorld(building);
140146

141147
pBuildsingsPool->Release(i);
142148

@@ -162,14 +168,146 @@ void CBuildingsPoolSA::RestoreAllBuildings()
162168
if (originalData[i].first)
163169
{
164170
pBuildsingsPool->AllocateAt(i);
165-
auto building = pBuildsingsPool->GetObject(i);
166-
*building = originalData[i].second;
171+
auto pBuilding = pBuildsingsPool->GetObject(i);
172+
*pBuilding = originalData[i].second;
167173

168-
pGame->GetWorld()->Add(building, CBuildingPool_Constructor);
174+
pGame->GetWorld()->Add(pBuilding, CBuildingPool_Constructor);
169175
}
170176
}
171177

172-
m_pOriginalBuildingsBackup.release();
178+
m_pOriginalBuildingsBackup = nullptr;
179+
}
180+
181+
void CBuildingsPoolSA::RemoveBuildingFromWorld(CBuildingSAInterface* pBuilding)
182+
{
183+
// Remove building from world
184+
pGame->GetWorld()->Remove(pBuilding, CBuildingPool_Destructor);
185+
186+
pBuilding->DeleteRwObject();
187+
pBuilding->ResolveReferences();
188+
pBuilding->RemoveShadows();
189+
}
190+
191+
bool CBuildingsPoolSA::Resize(int size)
192+
{
193+
auto* pool = (*m_ppBuildingPoolInterface);
194+
const int curretnSize = pool->m_nSize;
195+
196+
void* oldPool = pool->m_pObjects;
197+
198+
if (oldPool != nullptr)
199+
{
200+
MemSA::free(pool->m_pObjects);
201+
pool->m_pObjects = nullptr;
202+
}
203+
204+
if (pool->m_byteMap != nullptr)
205+
{
206+
MemSA::free(pool->m_byteMap);
207+
pool->m_byteMap = nullptr;
208+
}
209+
210+
CBuildingSAInterface* newObjects = MemSA::malloc_struct<CBuildingSAInterface>(size);
211+
if (newObjects == nullptr)
212+
{
213+
Resize(curretnSize);
214+
return false;
215+
}
216+
217+
tPoolObjectFlags* newBytemap = MemSA::malloc_struct<tPoolObjectFlags>(size);
218+
if (newBytemap == nullptr)
219+
{
220+
MemSA::free(newObjects);
221+
Resize(curretnSize);
222+
return false;
223+
}
224+
225+
pool->m_pObjects = newObjects;
226+
pool->m_byteMap = newBytemap;
227+
pool->m_nSize = size;
228+
pool->m_nFirstFree = 0;
229+
230+
for (auto i = 0; i < size; i++)
231+
{
232+
newBytemap[i].bEmpty = true;
233+
}
234+
235+
const uint32_t offset = (uint32_t)newObjects - (uint32_t)oldPool;
236+
if (oldPool != nullptr)
237+
{
238+
UpdateIplEntrysPointers(offset);
239+
}
240+
241+
if (m_pOriginalBuildingsBackup)
242+
{
243+
UpdateBackupLodPointers(offset);
244+
}
245+
246+
pGame->GetPools()->GetDummyPool().UpdateBuildingLods(oldPool, newObjects);
247+
248+
RemoveVehicleDamageLinks();
249+
250+
return true;
251+
}
252+
253+
void CBuildingsPoolSA::UpdateIplEntrysPointers(uint32_t offset)
254+
{
255+
using buildings_array_t = CBuildingSAInterface* [1000];
256+
using ipl_entry_array_t = buildings_array_t* [40];
257+
ipl_entry_array_t* iplEntryArray = (ipl_entry_array_t*)0x8E3F08;
258+
259+
for (auto i = 0; i < 40; i++)
260+
{
261+
buildings_array_t* ppArray = (*iplEntryArray)[i];
262+
263+
if (ppArray == nullptr)
264+
{
265+
return;
266+
}
267+
size_t arraySize = MemSA::msize(*ppArray) / sizeof(CBuildingSAInterface*);
268+
for (auto j = 0; j < arraySize; j++)
269+
{
270+
CBuildingSAInterface* object = (*ppArray)[j];
271+
272+
(*ppArray)[j] = (CBuildingSAInterface*)((uint32_t)object + offset);
273+
}
274+
}
275+
}
276+
277+
void CBuildingsPoolSA::UpdateBackupLodPointers(uint32_t offset)
278+
{
279+
std::array<std::pair<bool, CBuildingSAInterface>, MAX_BUILDINGS> *arr = m_pOriginalBuildingsBackup.get();
280+
for (auto i = 0; i < MAX_BUILDINGS; i++)
281+
{
282+
std::pair<bool, CBuildingSAInterface>* data = &(*arr)[i];
283+
if (data->first)
284+
{
285+
CBuildingSAInterface* building = &data->second;
286+
if (building->m_pLod != nullptr)
287+
{
288+
building->m_pLod = (CBuildingSAInterface*)((uint32_t)building->m_pLod + offset);
289+
}
290+
}
291+
}
292+
}
293+
294+
void CBuildingsPoolSA::RemoveVehicleDamageLinks()
295+
{
296+
const int count = pGame->GetPools()->GetVehicleCount();
297+
for (int i = 0; i < count; i++)
298+
{
299+
auto* vehLinks = pGame->GetPools()->GetVehicle(i);
300+
if (vehLinks->pEntity)
301+
{
302+
CVehicleSAInterface* vehicle = vehLinks->pEntity->GetVehicleInterface();
303+
vehicle->m_pCollidedEntity = nullptr;
304+
vehicle->pLastContactedEntity[0] = nullptr;
305+
vehicle->pLastContactedEntity[1] = nullptr;
306+
vehicle->pLastContactedEntity[2] = nullptr;
307+
vehicle->pLastContactedEntity[3] = nullptr;
308+
vehicle->m_ucCollisionState = 0;
309+
}
310+
}
173311
}
174312

175313
bool CBuildingsPoolSA::HasFreeBuildingSlot()

Client/game_sa/CBuildingsPoolSA.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
*
1010
*****************************************************************************/
1111

12+
#pragma once
13+
1214
#include <game/CBuildingsPool.h>
1315
#include <CVector.h>
1416
#include "CPoolSAInterface.h"
@@ -24,11 +26,17 @@ class CBuildingsPoolSA : public CBuildingsPool
2426
void RemoveBuilding(CBuilding* pBuilding);
2527
bool HasFreeBuildingSlot();
2628

27-
void RemoveAllBuildings();
28-
void RestoreAllBuildings();
29+
void RemoveAllBuildings() override;
30+
void RestoreAllBuildings() override;
31+
bool Resize(int size) override;
32+
int GetSize() const override { return (*m_ppBuildingPoolInterface)->m_nSize; };
2933

3034
private:
31-
bool AddBuildingToPool(CClientBuilding* pClientBuilding, CBuildingSA* pBuilding);
35+
void RemoveBuildingFromWorld(CBuildingSAInterface* pBuilding);
36+
bool AddBuildingToPool(CClientBuilding* pClientBuilding, CBuildingSA* pBuilding);
37+
void UpdateIplEntrysPointers(uint32_t offset);
38+
void UpdateBackupLodPointers(uint32_t offset);
39+
void RemoveVehicleDamageLinks();
3240

3341
private:
3442
SPoolData<CBuildingSA, CBuildingSAInterface, MAX_BUILDINGS> m_buildingPool;

Client/game_sa/CCoverManagerSA.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*****************************************************************************
2+
*
3+
* PROJECT: Multi Theft Auto v1.0
4+
* LICENSE: See LICENSE in the top level directory
5+
* FILE: game_sa/CCoverManagerSA.cpp
6+
*
7+
* Multi Theft Auto is available from http://www.multitheftauto.com/
8+
*
9+
*****************************************************************************/
10+
11+
#include "StdInc.h"
12+
#include "CCoverManagerSA.h"
13+
14+
CCoverManagerSA::CCoverManagerSA()
15+
{
16+
m_pCoverList = reinterpret_cast<CPtrNodeDoubleListSAInterface<CEntitySAInterface>*>(0xC1A2B8);
17+
}
18+
19+
void CCoverManagerSA::RemoveAllCovers()
20+
{
21+
CPtrNodeDoubleLink<CEntitySAInterface>* pNode = m_pCoverList->m_pNode;
22+
while (pNode)
23+
{
24+
RemoveCoverFromArray(pNode->pItem);
25+
pNode = pNode->pNext;
26+
}
27+
m_pCoverList->RemoveAllItems();
28+
}
29+
30+
void CCoverManagerSA::RemoveCover(CEntitySAInterface* entity)
31+
{
32+
RemoveCoverFromArray(entity);
33+
34+
m_pCoverList->RemoveItem(entity);
35+
}
36+
37+
void CCoverManagerSA::RemoveCoverFromArray(CEntitySAInterface* entity)
38+
{
39+
using CCover_RemoveCoverPointsForThisEntity = char(__cdecl*)(CEntitySAInterface*);
40+
((CCover_RemoveCoverPointsForThisEntity)0x698740)(entity);
41+
}

Client/game_sa/CCoverManagerSA.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*****************************************************************************
2+
*
3+
* PROJECT: Multi Theft Auto v1.0
4+
* LICENSE: See LICENSE in the top level directory
5+
* FILE: game_sa/CCoverManagerSA.h
6+
*
7+
* Multi Theft Auto is available from http://www.multitheftauto.com/
8+
*
9+
*****************************************************************************/
10+
11+
#pragma once
12+
13+
#include "CEntitySA.h"
14+
#include "CPtrNodeDoubleListSA.h"
15+
16+
class CCoverManagerSA
17+
{
18+
public:
19+
CCoverManagerSA();
20+
~CCoverManagerSA() = default;
21+
22+
void RemoveAllCovers();
23+
void RemoveCover(CEntitySAInterface* entity);
24+
25+
private:
26+
void RemoveCoverFromArray(CEntitySAInterface* entity);
27+
28+
private:
29+
CPtrNodeDoubleListSAInterface<CEntitySAInterface>* m_pCoverList;
30+
};

Client/game_sa/CDummyPoolSA.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*****************************************************************************
2+
*
3+
* PROJECT: Multi Theft Auto v1.0
4+
* LICENSE: See LICENSE in the top level directory
5+
* FILE: game_sa/CDummyPoolSA.cpp
6+
* PURPOSE: Dummy pool class
7+
*
8+
* Multi Theft Auto is available from http://www.multitheftauto.com/
9+
*
10+
*****************************************************************************/
11+
12+
#pragma once
13+
14+
#include "StdInc.h"
15+
#include "CDummyPoolSA.h"
16+
17+
CDummyPoolSA::CDummyPoolSA()
18+
{
19+
m_ppDummyPoolInterface = (CPoolSAInterface<CEntitySAInterface>**)0xB744A0;
20+
}
21+
22+
void CDummyPoolSA::RemoveAllBuildingLods()
23+
{
24+
if (m_pLodBackup)
25+
return;
26+
27+
m_pLodBackup = std::make_unique<std::array<CEntitySAInterface*, MAX_DUMMIES>>();
28+
29+
for (int i = 0; i < MAX_DUMMIES; i++)
30+
{
31+
CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i);
32+
(*m_pLodBackup)[i] = object->m_pLod;
33+
object->m_pLod = nullptr;
34+
}
35+
}
36+
37+
void CDummyPoolSA::RestoreAllBuildingsLods()
38+
{
39+
if (!m_pLodBackup)
40+
return;
41+
42+
for (int i = 0; i < MAX_DUMMIES; i++)
43+
{
44+
CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i);
45+
object->m_pLod = (*m_pLodBackup)[i];
46+
}
47+
48+
m_pLodBackup.release();
49+
}
50+
51+
void CDummyPoolSA::UpdateBuildingLods(void* oldPool, void* newPool)
52+
{
53+
const uint32_t offset = (uint32_t)newPool - (uint32_t)oldPool;
54+
55+
if (m_pLodBackup)
56+
{
57+
for (int i = 0; i < MAX_DUMMIES; i++)
58+
{
59+
if ((*m_pLodBackup)[i] != nullptr)
60+
{
61+
(*m_pLodBackup)[i] = (CEntitySAInterface*)((uint32_t)(*m_pLodBackup)[i] + offset);
62+
}
63+
}
64+
}
65+
else
66+
{
67+
for (int i = 0; i < MAX_DUMMIES; i++)
68+
{
69+
CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i);
70+
if (object->m_pLod)
71+
{
72+
object->m_pLod = (CEntitySAInterface*)((uint32_t)object->m_pLod + offset);
73+
}
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)