Skip to content

Engine pool functions #3346

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3e48846
Remove/restore sa world
TheNormalnij Feb 29, 2024
eb30a35
Fix buildings crashes
TheNormalnij Mar 2, 2024
37ef379
Use using
TheNormalnij Mar 3, 2024
754b096
using + clangformat
TheNormalnij Mar 4, 2024
22bff5f
Disable barriers after restore
TheNormalnij Mar 4, 2024
87b2894
clang format
TheNormalnij Mar 4, 2024
8f05f6d
Fix typos
TheNormalnij Mar 5, 2024
a0f0965
Remove elements too
TheNormalnij Mar 15, 2024
944b762
Don't remove scripted buildings
TheNormalnij Mar 15, 2024
4c9399c
Engine pool functions
TheNormalnij Mar 18, 2024
56bb1b0
fix load crash
TheNormalnij Mar 19, 2024
cf89ee4
Fix crash
TheNormalnij Mar 19, 2024
85cd883
Add cover manager and plant manager
TheNormalnij Mar 25, 2024
4a7a5fa
Fix plant crash
TheNormalnij Mar 26, 2024
54ac9a1
Merge branch 'master' into TheNormalnij/engine_set_pool_size
TheNormalnij Apr 7, 2024
8ed4a56
Fix dummies crash
TheNormalnij Apr 10, 2024
34b22d3
Fix building
TheNormalnij Apr 14, 2024
083b448
Fix shadows
TheNormalnij Apr 14, 2024
a192fe3
Fix vehicle crash
TheNormalnij Apr 14, 2024
5d366b9
Fix more vehicle crash
TheNormalnij Apr 14, 2024
4569a72
Fix cover crashes
TheNormalnij Apr 28, 2024
17eb1a8
Fix some style
TheNormalnij Apr 28, 2024
6e39ad2
Small refactor
TheNormalnij Apr 29, 2024
c9c8dd8
Fix memory leak
TheNormalnij Apr 29, 2024
1829272
Rename SetSize to resize
TheNormalnij Apr 29, 2024
1889af3
Merge branch 'master' into TheNormalnij/engine_set_pool_size
TheNormalnij May 25, 2024
26ea3f9
Merge branch 'master' into TheNormalnij/engine_set_pool_size
TheNormalnij May 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading