Skip to content

Commit

Permalink
Engine pool functions (#3346)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheNormalnij authored May 27, 2024
1 parent 545f54b commit bdf1221
Show file tree
Hide file tree
Showing 30 changed files with 723 additions and 51 deletions.
164 changes: 151 additions & 13 deletions Client/game_sa/CBuildingsPoolSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include <game/CWorld.h>
#include "CGameSA.h"
#include "CPtrNodeSingleListSA.h"
#include "MemSA.h"
#include "CVehicleSA.h"

extern CGameSA* pGame;

Expand Down Expand Up @@ -93,16 +95,13 @@ void CBuildingsPoolSA::RemoveBuilding(CBuilding* pBuilding)
if (dwElementIndexInPool == UINT_MAX)
return;

// Remove building from world
pGame->GetWorld()->Remove(pInterface, CBuildingPool_Destructor);

// Remove building from cover list
CPtrNodeSingleListSAInterface<CBuildingSAInterface>* coverList = reinterpret_cast<CPtrNodeSingleListSAInterface<CBuildingSAInterface>*>(0xC1A2B8);
coverList->RemoveItem(pInterface);
pGame->GetCoverManager()->RemoveCover(pInterface);

// Remove plant
using CPlantColEntry_Remove = CEntitySAInterface* (*)(CEntitySAInterface*);
((CPlantColEntry_Remove)0x5DBEF0)(pInterface);
pGame->GetPlantManager()->RemovePlant(pInterface);

RemoveBuildingFromWorld(pInterface);

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

pGame->GetCoverManager()->RemoveAllCovers();
pGame->GetPlantManager()->RemoveAllPlants();

// Remove all shadows
using CStencilShadowObjects_dtorAll = void* (*)();
((CStencilShadowObjects_dtorAll)0x711390)();

m_pOriginalBuildingsBackup = std::make_unique<std::array<std::pair<bool, CBuildingSAInterface>, MAX_BUILDINGS>>();

auto pBuildsingsPool = (*m_ppBuildingPoolInterface);
for (size_t i = 0; i < MAX_BUILDINGS; i++)
{
if (pBuildsingsPool->IsContains(i))
{
auto building = pBuildsingsPool->GetObject(i);
CBuildingSAInterface* building = pBuildsingsPool->GetObject(i);

pGame->GetWorld()->Remove(building, CBuildingPool_Destructor);
RemoveBuildingFromWorld(building);

pBuildsingsPool->Release(i);

Expand All @@ -162,14 +168,146 @@ void CBuildingsPoolSA::RestoreAllBuildings()
if (originalData[i].first)
{
pBuildsingsPool->AllocateAt(i);
auto building = pBuildsingsPool->GetObject(i);
*building = originalData[i].second;
auto pBuilding = pBuildsingsPool->GetObject(i);
*pBuilding = originalData[i].second;

pGame->GetWorld()->Add(building, CBuildingPool_Constructor);
pGame->GetWorld()->Add(pBuilding, CBuildingPool_Constructor);
}
}

m_pOriginalBuildingsBackup.release();
m_pOriginalBuildingsBackup = nullptr;
}

void CBuildingsPoolSA::RemoveBuildingFromWorld(CBuildingSAInterface* pBuilding)
{
// Remove building from world
pGame->GetWorld()->Remove(pBuilding, CBuildingPool_Destructor);

pBuilding->DeleteRwObject();
pBuilding->ResolveReferences();
pBuilding->RemoveShadows();
}

bool CBuildingsPoolSA::Resize(int size)
{
auto* pool = (*m_ppBuildingPoolInterface);
const int curretnSize = pool->m_nSize;

void* oldPool = pool->m_pObjects;

if (oldPool != nullptr)
{
MemSA::free(pool->m_pObjects);
pool->m_pObjects = nullptr;
}

if (pool->m_byteMap != nullptr)
{
MemSA::free(pool->m_byteMap);
pool->m_byteMap = nullptr;
}

CBuildingSAInterface* newObjects = MemSA::malloc_struct<CBuildingSAInterface>(size);
if (newObjects == nullptr)
{
Resize(curretnSize);
return false;
}

tPoolObjectFlags* newBytemap = MemSA::malloc_struct<tPoolObjectFlags>(size);
if (newBytemap == nullptr)
{
MemSA::free(newObjects);
Resize(curretnSize);
return false;
}

pool->m_pObjects = newObjects;
pool->m_byteMap = newBytemap;
pool->m_nSize = size;
pool->m_nFirstFree = 0;

for (auto i = 0; i < size; i++)
{
newBytemap[i].bEmpty = true;
}

const uint32_t offset = (uint32_t)newObjects - (uint32_t)oldPool;
if (oldPool != nullptr)
{
UpdateIplEntrysPointers(offset);
}

if (m_pOriginalBuildingsBackup)
{
UpdateBackupLodPointers(offset);
}

pGame->GetPools()->GetDummyPool().UpdateBuildingLods(oldPool, newObjects);

RemoveVehicleDamageLinks();

return true;
}

void CBuildingsPoolSA::UpdateIplEntrysPointers(uint32_t offset)
{
using buildings_array_t = CBuildingSAInterface* [1000];
using ipl_entry_array_t = buildings_array_t* [40];
ipl_entry_array_t* iplEntryArray = (ipl_entry_array_t*)0x8E3F08;

for (auto i = 0; i < 40; i++)
{
buildings_array_t* ppArray = (*iplEntryArray)[i];

if (ppArray == nullptr)
{
return;
}
size_t arraySize = MemSA::msize(*ppArray) / sizeof(CBuildingSAInterface*);
for (auto j = 0; j < arraySize; j++)
{
CBuildingSAInterface* object = (*ppArray)[j];

(*ppArray)[j] = (CBuildingSAInterface*)((uint32_t)object + offset);
}
}
}

void CBuildingsPoolSA::UpdateBackupLodPointers(uint32_t offset)
{
std::array<std::pair<bool, CBuildingSAInterface>, MAX_BUILDINGS> *arr = m_pOriginalBuildingsBackup.get();
for (auto i = 0; i < MAX_BUILDINGS; i++)
{
std::pair<bool, CBuildingSAInterface>* data = &(*arr)[i];
if (data->first)
{
CBuildingSAInterface* building = &data->second;
if (building->m_pLod != nullptr)
{
building->m_pLod = (CBuildingSAInterface*)((uint32_t)building->m_pLod + offset);
}
}
}
}

void CBuildingsPoolSA::RemoveVehicleDamageLinks()
{
const int count = pGame->GetPools()->GetVehicleCount();
for (int i = 0; i < count; i++)
{
auto* vehLinks = pGame->GetPools()->GetVehicle(i);
if (vehLinks->pEntity)
{
CVehicleSAInterface* vehicle = vehLinks->pEntity->GetVehicleInterface();
vehicle->m_pCollidedEntity = nullptr;
vehicle->pLastContactedEntity[0] = nullptr;
vehicle->pLastContactedEntity[1] = nullptr;
vehicle->pLastContactedEntity[2] = nullptr;
vehicle->pLastContactedEntity[3] = nullptr;
vehicle->m_ucCollisionState = 0;
}
}
}

bool CBuildingsPoolSA::HasFreeBuildingSlot()
Expand Down
14 changes: 11 additions & 3 deletions Client/game_sa/CBuildingsPoolSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*
*****************************************************************************/

#pragma once

#include <game/CBuildingsPool.h>
#include <CVector.h>
#include "CPoolSAInterface.h"
Expand All @@ -24,11 +26,17 @@ class CBuildingsPoolSA : public CBuildingsPool
void RemoveBuilding(CBuilding* pBuilding);
bool HasFreeBuildingSlot();

void RemoveAllBuildings();
void RestoreAllBuildings();
void RemoveAllBuildings() override;
void RestoreAllBuildings() override;
bool Resize(int size) override;
int GetSize() const override { return (*m_ppBuildingPoolInterface)->m_nSize; };

private:
bool AddBuildingToPool(CClientBuilding* pClientBuilding, CBuildingSA* pBuilding);
void RemoveBuildingFromWorld(CBuildingSAInterface* pBuilding);
bool AddBuildingToPool(CClientBuilding* pClientBuilding, CBuildingSA* pBuilding);
void UpdateIplEntrysPointers(uint32_t offset);
void UpdateBackupLodPointers(uint32_t offset);
void RemoveVehicleDamageLinks();

private:
SPoolData<CBuildingSA, CBuildingSAInterface, MAX_BUILDINGS> m_buildingPool;
Expand Down
41 changes: 41 additions & 0 deletions Client/game_sa/CCoverManagerSA.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CCoverManagerSA.cpp
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/

#include "StdInc.h"
#include "CCoverManagerSA.h"

CCoverManagerSA::CCoverManagerSA()
{
m_pCoverList = reinterpret_cast<CPtrNodeDoubleListSAInterface<CEntitySAInterface>*>(0xC1A2B8);
}

void CCoverManagerSA::RemoveAllCovers()
{
CPtrNodeDoubleLink<CEntitySAInterface>* pNode = m_pCoverList->m_pNode;
while (pNode)
{
RemoveCoverFromArray(pNode->pItem);
pNode = pNode->pNext;
}
m_pCoverList->RemoveAllItems();
}

void CCoverManagerSA::RemoveCover(CEntitySAInterface* entity)
{
RemoveCoverFromArray(entity);

m_pCoverList->RemoveItem(entity);
}

void CCoverManagerSA::RemoveCoverFromArray(CEntitySAInterface* entity)
{
using CCover_RemoveCoverPointsForThisEntity = char(__cdecl*)(CEntitySAInterface*);
((CCover_RemoveCoverPointsForThisEntity)0x698740)(entity);
}
30 changes: 30 additions & 0 deletions Client/game_sa/CCoverManagerSA.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CCoverManagerSA.h
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/

#pragma once

#include "CEntitySA.h"
#include "CPtrNodeDoubleListSA.h"

class CCoverManagerSA
{
public:
CCoverManagerSA();
~CCoverManagerSA() = default;

void RemoveAllCovers();
void RemoveCover(CEntitySAInterface* entity);

private:
void RemoveCoverFromArray(CEntitySAInterface* entity);

private:
CPtrNodeDoubleListSAInterface<CEntitySAInterface>* m_pCoverList;
};
76 changes: 76 additions & 0 deletions Client/game_sa/CDummyPoolSA.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CDummyPoolSA.cpp
* PURPOSE: Dummy pool class
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/

#pragma once

#include "StdInc.h"
#include "CDummyPoolSA.h"

CDummyPoolSA::CDummyPoolSA()
{
m_ppDummyPoolInterface = (CPoolSAInterface<CEntitySAInterface>**)0xB744A0;
}

void CDummyPoolSA::RemoveAllBuildingLods()
{
if (m_pLodBackup)
return;

m_pLodBackup = std::make_unique<std::array<CEntitySAInterface*, MAX_DUMMIES>>();

for (int i = 0; i < MAX_DUMMIES; i++)
{
CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i);
(*m_pLodBackup)[i] = object->m_pLod;
object->m_pLod = nullptr;
}
}

void CDummyPoolSA::RestoreAllBuildingsLods()
{
if (!m_pLodBackup)
return;

for (int i = 0; i < MAX_DUMMIES; i++)
{
CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i);
object->m_pLod = (*m_pLodBackup)[i];
}

m_pLodBackup.release();
}

void CDummyPoolSA::UpdateBuildingLods(void* oldPool, void* newPool)
{
const uint32_t offset = (uint32_t)newPool - (uint32_t)oldPool;

if (m_pLodBackup)
{
for (int i = 0; i < MAX_DUMMIES; i++)
{
if ((*m_pLodBackup)[i] != nullptr)
{
(*m_pLodBackup)[i] = (CEntitySAInterface*)((uint32_t)(*m_pLodBackup)[i] + offset);
}
}
}
else
{
for (int i = 0; i < MAX_DUMMIES; i++)
{
CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i);
if (object->m_pLod)
{
object->m_pLod = (CEntitySAInterface*)((uint32_t)object->m_pLod + offset);
}
}
}
}
Loading

0 comments on commit bdf1221

Please sign in to comment.