From f4e90e4777ca0f265ba03761f03fc519af01c8a4 Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Sat, 3 Aug 2024 00:42:25 +0300 Subject: [PATCH 1/9] Add remove/restore functionality --- Client/game_sa/CBuildingsPoolSA.cpp | 16 ++----- Client/game_sa/CBuildingsPoolSA.h | 4 +- Client/game_sa/CDummyPoolSA.cpp | 72 ++++++++++++++++++++--------- Client/game_sa/CDummyPoolSA.h | 13 ++++-- Client/game_sa/CEntitySA.h | 6 +++ Client/game_sa/CGameSA.cpp | 14 ++++-- Client/sdk/game/CBuildingsPool.h | 8 ++-- Client/sdk/game/CDummyPool.h | 6 +-- Client/sdk/game/CWorld.h | 2 + Client/sdk/game/Common.h | 1 - 10 files changed, 89 insertions(+), 53 deletions(-) diff --git a/Client/game_sa/CBuildingsPoolSA.cpp b/Client/game_sa/CBuildingsPoolSA.cpp index b8363f6507f..2b55e4c92d3 100644 --- a/Client/game_sa/CBuildingsPoolSA.cpp +++ b/Client/game_sa/CBuildingsPoolSA.cpp @@ -121,18 +121,11 @@ void CBuildingsPoolSA::RemoveBuilding(CBuilding* pBuilding) --m_buildingPool.count; } -void CBuildingsPoolSA::RemoveAllBuildings() +void CBuildingsPoolSA::RemoveAllWithBackup() { 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, MAX_BUILDINGS>>(); auto pBuildsingsPool = (*m_ppBuildingPoolInterface); @@ -156,7 +149,7 @@ void CBuildingsPoolSA::RemoveAllBuildings() } } -void CBuildingsPoolSA::RestoreAllBuildings() +void CBuildingsPoolSA::RestoreBackup() { if (!m_pOriginalBuildingsBackup) return; @@ -182,10 +175,7 @@ void CBuildingsPoolSA::RemoveBuildingFromWorld(CBuildingSAInterface* pBuilding) { // Remove building from world pGame->GetWorld()->Remove(pBuilding, CBuildingPool_Destructor); - - pBuilding->DeleteRwObject(); - pBuilding->ResolveReferences(); - pBuilding->RemoveShadows(); + pBuilding->RemoveRWObjectWithReferencesCleanup(); } bool CBuildingsPoolSA::Resize(int size) diff --git a/Client/game_sa/CBuildingsPoolSA.h b/Client/game_sa/CBuildingsPoolSA.h index 5ce719bd73d..f9ea02b5a2e 100644 --- a/Client/game_sa/CBuildingsPoolSA.h +++ b/Client/game_sa/CBuildingsPoolSA.h @@ -26,8 +26,8 @@ class CBuildingsPoolSA : public CBuildingsPool void RemoveBuilding(CBuilding* pBuilding); bool HasFreeBuildingSlot(); - void RemoveAllBuildings() override; - void RestoreAllBuildings() override; + void RemoveAllWithBackup() override; + void RestoreBackup() override; bool Resize(int size) override; int GetSize() const override { return (*m_ppBuildingPoolInterface)->m_nSize; }; diff --git a/Client/game_sa/CDummyPoolSA.cpp b/Client/game_sa/CDummyPoolSA.cpp index 7f9b539a409..e8f3c7533e4 100644 --- a/Client/game_sa/CDummyPoolSA.cpp +++ b/Client/game_sa/CDummyPoolSA.cpp @@ -1,6 +1,6 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory * FILE: game_sa/CDummyPoolSA.cpp * PURPOSE: Dummy pool class @@ -13,63 +13,93 @@ #include "StdInc.h" #include "CDummyPoolSA.h" +#include "CGameSA.h" +#include + +extern CGameSA* pGame; CDummyPoolSA::CDummyPoolSA() { m_ppDummyPoolInterface = (CPoolSAInterface**)0xB744A0; } -void CDummyPoolSA::RemoveAllBuildingLods() +void CDummyPoolSA::RemoveAllWithBackup() { - if (m_pLodBackup) + if (m_pOriginalElementsBackup) return; - m_pLodBackup = std::make_unique>(); + m_pOriginalElementsBackup = std::make_unique(); - for (int i = 0; i < MAX_DUMMIES; i++) + auto pDummyPool = (*m_ppDummyPoolInterface); + for (size_t i = 0; i < MAX_DUMMIES_DEFAULT; i++) { - CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i); - (*m_pLodBackup)[i] = object->m_pLod; - object->m_pLod = nullptr; + if (pDummyPool->IsContains(i)) + { + CEntitySAInterface* building = pDummyPool->GetObject(i); + + pGame->GetWorld()->Remove(building, CDummyPool_Destructor); + building->RemoveRWObjectWithReferencesCleanup(); + + pDummyPool->Release(i); + + (*m_pOriginalElementsBackup)[i].first = true; + (*m_pOriginalElementsBackup)[i].second = *building; + } + else + { + (*m_pOriginalElementsBackup)[i].first = false; + } } } -void CDummyPoolSA::RestoreAllBuildingsLods() +void CDummyPoolSA::RestoreBackup() { - if (!m_pLodBackup) + if (!m_pOriginalElementsBackup) return; - for (int i = 0; i < MAX_DUMMIES; i++) + auto& originalData = *m_pOriginalElementsBackup; + auto pDummyPool = (*m_ppDummyPoolInterface); + for (size_t i = 0; i < MAX_DUMMIES_DEFAULT; i++) { - CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i); - object->m_pLod = (*m_pLodBackup)[i]; + if (originalData[i].first) + { + pDummyPool->AllocateAt(i); + auto pDummy = pDummyPool->GetObject(i); + *pDummy = originalData[i].second; + + pGame->GetWorld()->Add(pDummy, CDummyPool_Constructor); + } } - m_pLodBackup.release(); + m_pOriginalElementsBackup = nullptr; } void CDummyPoolSA::UpdateBuildingLods(void* oldPool, void* newPool) { - const uint32_t offset = (uint32_t)newPool - (uint32_t)oldPool; + const std::uint32_t offset = (std::uint32_t)newPool - (std::uint32_t)oldPool; - if (m_pLodBackup) + if (m_pOriginalElementsBackup) { - for (int i = 0; i < MAX_DUMMIES; i++) + for (int i = 0; i < MAX_DUMMIES_DEFAULT; i++) { - if ((*m_pLodBackup)[i] != nullptr) + if ((*m_pOriginalElementsBackup)[i].first) { - (*m_pLodBackup)[i] = (CEntitySAInterface*)((uint32_t)(*m_pLodBackup)[i] + offset); + CEntitySAInterface* object = &(*m_pOriginalElementsBackup)[i].second; + if (object->m_pLod) + { + object->m_pLod = (CEntitySAInterface*)((std::uint32_t)(object->m_pLod) + offset); + } } } } else { - for (int i = 0; i < MAX_DUMMIES; i++) + for (int i = 0; i < MAX_DUMMIES_DEFAULT; i++) { CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i); if (object->m_pLod) { - object->m_pLod = (CEntitySAInterface*)((uint32_t)object->m_pLod + offset); + object->m_pLod = (CEntitySAInterface*)((std::uint32_t)object->m_pLod + offset); } } } diff --git a/Client/game_sa/CDummyPoolSA.h b/Client/game_sa/CDummyPoolSA.h index 95d00b19f38..7971a086d6a 100644 --- a/Client/game_sa/CDummyPoolSA.h +++ b/Client/game_sa/CDummyPoolSA.h @@ -1,6 +1,6 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory * FILE: game_sa/CDummyPoolSA.h * PURPOSE: Dummy pool class @@ -16,18 +16,21 @@ #include "CPoolSAInterface.h" #include -class CDummyPoolSA : public CDummyPool +constexpr std::size_t MAX_DUMMIES_DEFAULT = 2500; + +class CDummyPoolSA final : public CDummyPool { public: CDummyPoolSA(); ~CDummyPoolSA() = default; - void RemoveAllBuildingLods(); - void RestoreAllBuildingsLods(); + void RemoveAllWithBackup() override; + void RestoreBackup() override; void UpdateBuildingLods(void* oldPool, void* newPool); private: CPoolSAInterface** m_ppDummyPoolInterface; - std::unique_ptr> m_pLodBackup; + using pool_backup_t = std::array, MAX_DUMMIES_DEFAULT>; + std::unique_ptr m_pOriginalElementsBackup; }; diff --git a/Client/game_sa/CEntitySA.h b/Client/game_sa/CEntitySA.h index 9de57edc0a8..a5a0de0dd9f 100644 --- a/Client/game_sa/CEntitySA.h +++ b/Client/game_sa/CEntitySA.h @@ -242,6 +242,12 @@ class CEntitySAInterface using vtbl_DeleteRwObject = void(__thiscall*)(CEntitySAInterface * pEntity); ((vtbl_DeleteRwObject)this->vtbl->DeleteRwObject)(this); }; + + void RemoveRWObjectWithReferencesCleanup() { + DeleteRwObject(); + ResolveReferences(); + RemoveShadows(); + } }; static_assert(sizeof(CEntitySAInterface) == 0x38, "Invalid size for CEntitySAInterface"); diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index abfb822816f..c22ce337f27 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -1009,8 +1009,14 @@ void CGameSA::RemoveAllBuildings(bool clearBuildingRemoval) { m_pIplStore->SetDynamicIplStreamingEnabled(false); - m_pPools->GetDummyPool().RemoveAllBuildingLods(); - m_pPools->GetBuildingsPool().RemoveAllBuildings(); + m_pCoverManager->RemoveAllCovers(); + m_pPlantManager->RemoveAllPlants(); + + // Remove all shadows in CStencilShadowObjects::dtorAll + ((void* (*)())0x711390)(); + + m_pPools->GetDummyPool().RemoveAllWithBackup(); + m_pPools->GetBuildingsPool().RemoveAllWithBackup(); auto pBuildingRemoval = static_cast(m_pBuildingRemoval); if (clearBuildingRemoval) @@ -1024,8 +1030,8 @@ void CGameSA::RemoveAllBuildings(bool clearBuildingRemoval) void CGameSA::RestoreGameBuildings() { - m_pPools->GetBuildingsPool().RestoreAllBuildings(); - m_pPools->GetDummyPool().RestoreAllBuildingsLods(); + m_pPools->GetBuildingsPool().RestoreBackup(); + m_pPools->GetDummyPool().RestoreBackup(); m_pIplStore->SetDynamicIplStreamingEnabled(true, [](CIplSAInterface* ipl) { return memcmp("barriers", ipl->name, 8) != 0; }); m_isBuildingsRemoved = false; diff --git a/Client/sdk/game/CBuildingsPool.h b/Client/sdk/game/CBuildingsPool.h index d490c162f79..84f5c9b67e3 100644 --- a/Client/sdk/game/CBuildingsPool.h +++ b/Client/sdk/game/CBuildingsPool.h @@ -1,6 +1,6 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory * FILE: sdk/game/CBuildingsPool.h * PURPOSE: Buildings pool interface @@ -22,12 +22,12 @@ class CBuildingsPool public: // Buildings pool - virtual CBuilding* AddBuilding(class CClientBuilding*, uint16_t modelId, CVector* vPos, CVector4D* vRot, uint8_t interior) = 0; + virtual CBuilding* AddBuilding(class CClientBuilding*, std::uint16_t modelId, CVector* vPos, CVector4D* vRot, std::uint8_t interior) = 0; virtual void RemoveBuilding(CBuilding* pObject) = 0; virtual bool HasFreeBuildingSlot() = 0; virtual bool Resize(int size) = 0; virtual int GetSize() const = 0; - virtual void RemoveAllBuildings() = 0; - virtual void RestoreAllBuildings() = 0; + virtual void RemoveAllWithBackup() = 0; + virtual void RestoreBackup() = 0; }; diff --git a/Client/sdk/game/CDummyPool.h b/Client/sdk/game/CDummyPool.h index 46308c304fa..793ae3d6f55 100644 --- a/Client/sdk/game/CDummyPool.h +++ b/Client/sdk/game/CDummyPool.h @@ -1,6 +1,6 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory * FILE: sdk/game/CDummyPool.h * PURPOSE: Dummy pool interface @@ -16,7 +16,7 @@ class CDummyPool { public: - virtual void RemoveAllBuildingLods() = 0; - virtual void RestoreAllBuildingsLods() = 0; + virtual void RemoveAllWithBackup() = 0; + virtual void RestoreBackup() = 0; virtual void UpdateBuildingLods(void* oldPool, void* newPool) = 0; }; diff --git a/Client/sdk/game/CWorld.h b/Client/sdk/game/CWorld.h index 3684172f014..d168a05dba9 100644 --- a/Client/sdk/game/CWorld.h +++ b/Client/sdk/game/CWorld.h @@ -88,6 +88,8 @@ enum eDebugCaller CBuildingPool_Constructor, CBuildingPool_Destructor, CBuilding_SetLod, + CDummyPool_Constructor, + CDummyPool_Destructor, }; enum eSurfaceProperties diff --git a/Client/sdk/game/Common.h b/Client/sdk/game/Common.h index 11e5a31554f..b5be2007ac3 100644 --- a/Client/sdk/game/Common.h +++ b/Client/sdk/game/Common.h @@ -27,7 +27,6 @@ #define MAX_PEDS ( MAX_PEDS_MTA + 30 ) // 140 #define MAX_OBJECTS ( MAX_OBJECTS_MTA + 200 ) // 1200 #define MAX_BUILDINGS 13000 -#define MAX_DUMMIES 2500 #define MAX_ENTRY_INFO_NODES ( MAX_ENTRY_INFO_NODES_MTA + 600 ) // 72600 #define MAX_POINTER_SINGLE_LINKS ( MAX_POINTER_SINGLE_LINKS_MTA + 5000 ) // 90000 #define MAX_POINTER_DOUBLE_LINKS ( MAX_POINTER_DOUBLE_LINKS_MTA + 800 ) // 74800 From aeecd9e67b924b81f02f425b934990531d63219d Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Sun, 4 Aug 2024 19:36:30 +0300 Subject: [PATCH 2/9] new functions added --- Client/game_sa/CBuildingsPoolSA.h | 4 +- Client/game_sa/CDummyPoolSA.cpp | 4 +- Client/game_sa/CGameSA.cpp | 17 +++---- Client/game_sa/CGameSA.h | 4 +- Client/game_sa/CPoolSAInterface.h | 5 +- Client/game_sa/CPoolsSA.h | 2 + .../logic/CClientBuildingManager.cpp | 50 ++++++------------- .../deathmatch/logic/CClientBuildingManager.h | 6 +-- .../logic/luadefs/CLuaBuildingDefs.cpp | 6 ++- .../logic/luadefs/CLuaWorldDefs.cpp | 29 +++++++++++ .../deathmatch/logic/luadefs/CLuaWorldDefs.h | 3 ++ Client/sdk/game/CGame.h | 4 +- 12 files changed, 72 insertions(+), 62 deletions(-) diff --git a/Client/game_sa/CBuildingsPoolSA.h b/Client/game_sa/CBuildingsPoolSA.h index f9ea02b5a2e..38e64970f18 100644 --- a/Client/game_sa/CBuildingsPoolSA.h +++ b/Client/game_sa/CBuildingsPoolSA.h @@ -40,8 +40,8 @@ class CBuildingsPoolSA : public CBuildingsPool void RemovePedsContactEnityLinks(); private: - SVectorPoolData m_buildingPool{MAX_BUILDINGS}; - CPoolSAInterface** m_ppBuildingPoolInterface; + SVectorPoolData m_buildingPool{MAX_BUILDINGS}; + CPoolSAInterface** m_ppBuildingPoolInterface; std::unique_ptr, MAX_BUILDINGS>> m_pOriginalBuildingsBackup; }; diff --git a/Client/game_sa/CDummyPoolSA.cpp b/Client/game_sa/CDummyPoolSA.cpp index e8f3c7533e4..dead250f750 100644 --- a/Client/game_sa/CDummyPoolSA.cpp +++ b/Client/game_sa/CDummyPoolSA.cpp @@ -80,7 +80,7 @@ void CDummyPoolSA::UpdateBuildingLods(void* oldPool, void* newPool) if (m_pOriginalElementsBackup) { - for (int i = 0; i < MAX_DUMMIES_DEFAULT; i++) + for (int i = 0; i < (*m_pOriginalElementsBackup).size(); i++) { if ((*m_pOriginalElementsBackup)[i].first) { @@ -94,7 +94,7 @@ void CDummyPoolSA::UpdateBuildingLods(void* oldPool, void* newPool) } else { - for (int i = 0; i < MAX_DUMMIES_DEFAULT; i++) + for (int i = 0; i < (*m_ppDummyPoolInterface)->Size(); i++) { CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i); if (object->m_pLod) diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index c22ce337f27..3dee6f1123e 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -439,7 +439,7 @@ void CGameSA::Reset() CModelInfoSA::StaticResetTextureDictionaries(); // Restore default world state - RestoreGameBuildings(); + RestoreGameWorld(); } } @@ -1005,7 +1005,7 @@ void CGameSA::GetShaderReplacementStats(SShaderReplacementStats& outStats) m_pRenderWare->GetShaderReplacementStats(outStats); } -void CGameSA::RemoveAllBuildings(bool clearBuildingRemoval) +void CGameSA::RemoveGameWorld() { m_pIplStore->SetDynamicIplStreamingEnabled(false); @@ -1018,17 +1018,12 @@ void CGameSA::RemoveAllBuildings(bool clearBuildingRemoval) m_pPools->GetDummyPool().RemoveAllWithBackup(); m_pPools->GetBuildingsPool().RemoveAllWithBackup(); - auto pBuildingRemoval = static_cast(m_pBuildingRemoval); - if (clearBuildingRemoval) - { - pBuildingRemoval->ClearRemovedBuildingLists(); - } - pBuildingRemoval->DropCaches(); + static_cast(m_pBuildingRemoval)->DropCaches(); m_isBuildingsRemoved = true; } -void CGameSA::RestoreGameBuildings() +void CGameSA::RestoreGameWorld() { m_pPools->GetBuildingsPool().RestoreBackup(); m_pPools->GetDummyPool().RestoreBackup(); @@ -1042,7 +1037,7 @@ bool CGameSA::SetBuildingPoolSize(size_t size) const bool shouldRemoveBuilding = !m_isBuildingsRemoved; if (shouldRemoveBuilding) { - RemoveAllBuildings(false); + RemoveGameWorld(); } else { @@ -1053,7 +1048,7 @@ bool CGameSA::SetBuildingPoolSize(size_t size) if (shouldRemoveBuilding) { - RestoreGameBuildings(); + RestoreGameWorld(); } return status; diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index f22b5748f71..3bdc10baf93 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -303,8 +303,8 @@ class CGameSA : public CGame PostWeaponFireHandler* m_pPostWeaponFireHandler; TaskSimpleBeHitHandler* m_pTaskSimpleBeHitHandler; - void RemoveAllBuildings(bool clearBuildingRemoval = true); - void RestoreGameBuildings(); + void RemoveGameWorld(); + void RestoreGameWorld(); bool SetBuildingPoolSize(size_t size); diff --git a/Client/game_sa/CPoolSAInterface.h b/Client/game_sa/CPoolSAInterface.h index 9f48bc63d3f..4ae1de87474 100644 --- a/Client/game_sa/CPoolSAInterface.h +++ b/Client/game_sa/CPoolSAInterface.h @@ -114,8 +114,9 @@ class CPoolSAInterface void Delete(uint index) { Release(index); } - bool IsEmpty(std::int32_t objectIndex) { return m_byteMap[objectIndex].bEmpty; } - bool IsContains(uint index) + int Size() const noexcept { return m_nSize; }; + bool IsEmpty(std::int32_t objectIndex) const { return m_byteMap[objectIndex].bEmpty; } + bool IsContains(uint index) const { if (m_nSize <= index) return false; diff --git a/Client/game_sa/CPoolsSA.h b/Client/game_sa/CPoolsSA.h index 0e6d3d96345..14ce159e997 100644 --- a/Client/game_sa/CPoolsSA.h +++ b/Client/game_sa/CPoolsSA.h @@ -22,6 +22,8 @@ #define INVALID_POOL_ARRAY_ID 0xFFFFFFFF class CClientEntity; +class CClientVehicle; +class CClientObject; class CPoolsSA : public CPools { diff --git a/Client/mods/deathmatch/logic/CClientBuildingManager.cpp b/Client/mods/deathmatch/logic/CClientBuildingManager.cpp index 243917b89f0..7a72459865f 100644 --- a/Client/mods/deathmatch/logic/CClientBuildingManager.cpp +++ b/Client/mods/deathmatch/logic/CClientBuildingManager.cpp @@ -133,6 +133,21 @@ void CClientBuildingManager::RestoreDestroyed() } } +void CClientBuildingManager::RestoreDestroyedSafe() +{ + // Resize the building pool if we need + const int currentUsed = g_pGame->GetPools()->GetNumberOfUsedSpaces(ePools::BUILDING_POOL) + m_List.size(); + const int currentCapacity = g_pGame->GetPools()->GetPoolCapacity(ePools::BUILDING_POOL); + + if (currentCapacity - currentUsed < PRESERVED_POOL_SIZE) + { + DoPoolResize(currentUsed + PRESERVED_POOL_SIZE); + } + + // Restore + RestoreDestroyed(); +} + void CClientBuildingManager::ResizePoolIfNeeds() { const int currentUsed = g_pGame->GetPools()->GetNumberOfUsedSpaces(ePools::BUILDING_POOL); @@ -164,38 +179,3 @@ bool CClientBuildingManager::DoPoolResize(size_t newCapacity) return success; } - - -void CClientBuildingManager::RemoveAllGameBuildings() -{ - // We do not want to remove scripted buildings - // But we need remove them from the buildings pool for a bit... - DestroyAllForABit(); - - // This function makes buildings backup without scripted buildings - g_pGame->RemoveAllBuildings(); - - // ... And restore here - RestoreDestroyed(); -} - -void CClientBuildingManager::RestoreAllGameBuildings() -{ - // We want to restore the game buildings to the same positions as they were before the backup. - // Remove scripted buildings for a bit - DestroyAllForABit(); - - g_pGame->RestoreGameBuildings(); - - // Resize the building pool if we need - const int currentUsed = g_pGame->GetPools()->GetNumberOfUsedSpaces(ePools::BUILDING_POOL) + m_List.size(); - const int currentCapacity = g_pGame->GetPools()->GetPoolCapacity(ePools::BUILDING_POOL); - - if (currentCapacity - currentUsed < PRESERVED_POOL_SIZE) - { - DoPoolResize(currentUsed + PRESERVED_POOL_SIZE); - } - - // Restore - RestoreDestroyed(); -} diff --git a/Client/mods/deathmatch/logic/CClientBuildingManager.h b/Client/mods/deathmatch/logic/CClientBuildingManager.h index 050cff9f96b..d44cc7d70fe 100644 --- a/Client/mods/deathmatch/logic/CClientBuildingManager.h +++ b/Client/mods/deathmatch/logic/CClientBuildingManager.h @@ -34,13 +34,11 @@ class CClientBuildingManager void ResizePoolIfNeeds(); bool SetPoolCapacity(size_t newCapacity); - void RemoveAllGameBuildings(); - void RestoreAllGameBuildings(); - -private: void DestroyAllForABit(); void RestoreDestroyed(); + void RestoreDestroyedSafe(); +private: bool DoPoolResize(size_t newCapacity); void AddToList(CClientBuilding* pBuilding) { m_List.push_back(pBuilding); } void RemoveFromList(CClientBuilding* pBuilding); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp index f45efbf09c3..be10ec459d1 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp @@ -60,12 +60,14 @@ CClientBuilding* CLuaBuildingDefs::CreateBuilding(lua_State* const luaVM, uint16 return pBuilding; } +// Deprecated void CLuaBuildingDefs::RemoveAllGameBuildings() { - m_pBuildingManager->RemoveAllGameBuildings(); + CLuaWorldDefs::RemoveGameWorld(); } +// Deprecated void CLuaBuildingDefs::RestoreGameBuildings() { - m_pBuildingManager->RestoreAllGameBuildings(); + CLuaWorldDefs::RestoreGameWorld(); } diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp index 96dd4479210..eff4ab3f5fc 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp @@ -100,9 +100,13 @@ void CLuaWorldDefs::LoadFunctions() {"setFPSLimit", SetFPSLimit}, {"setCoronaReflectionsEnabled", ArgumentParser}, {"setWorldProperty", ArgumentParser}, + + // World remove/restore functions {"removeWorldModel", RemoveWorldBuilding}, {"restoreAllWorldModels", RestoreWorldBuildings}, {"restoreWorldModel", RestoreWorldBuilding}, + {"removeGameWorld", ArgumentParser}, + {"restoreGameWorld", ArgumentParser}, // World create funcs {"createSWATRope", CreateSWATRope}, @@ -2234,3 +2238,28 @@ bool CLuaWorldDefs::ResetWorldProperty(eWorldProperty property) } return false; } + +void CLuaWorldDefs::RemoveGameWorld() +{ + // We do not want to remove scripted buildings + // But we need remove them from the buildings pool for a bit... + m_pBuildingManager->DestroyAllForABit(); + + // This function makes buildings backup without scripted buildings + g_pGame->RemoveGameWorld(); + + // ... And restore here + m_pBuildingManager->RestoreDestroyed(); +} + +void CLuaWorldDefs::RestoreGameWorld() +{ + // We want to restore the game buildings to the same positions as they were before the backup. + // Remove scripted buildings for a bit + m_pBuildingManager->DestroyAllForABit(); + + g_pGame->RestoreGameWorld(); + + // ... And restore here + m_pBuildingManager->RestoreDestroyedSafe(); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h index fc1d6bb3a1e..1352bb7f074 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h @@ -130,4 +130,7 @@ class CLuaWorldDefs : public CLuaDefs static std::variant> GetWorldProperty(eWorldProperty property); static bool SetWorldProperty(eWorldProperty property, float arg1, std::optional arg2, std::optional arg3); static bool ResetWorldProperty(eWorldProperty property); + + static void RemoveGameWorld(); + static void RestoreGameWorld(); }; diff --git a/Client/sdk/game/CGame.h b/Client/sdk/game/CGame.h index 215141ee23a..032e3ce1d61 100644 --- a/Client/sdk/game/CGame.h +++ b/Client/sdk/game/CGame.h @@ -268,8 +268,8 @@ class __declspec(novtable) CGame virtual int32_t GetBaseIDforSCM() = 0; virtual int32_t GetCountOfAllFileIDs() = 0; - virtual void RemoveAllBuildings(bool clearBuildingRemoval = true) = 0; - virtual void RestoreGameBuildings() = 0; + virtual void RemoveGameWorld() = 0; + virtual void RestoreGameWorld() = 0; virtual bool SetBuildingPoolSize(size_t size) = 0; From a20dd15da0c2af57d23d69901e33c19d9536b45f Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Sun, 4 Aug 2024 20:02:53 +0300 Subject: [PATCH 3/9] Small fixes --- Client/game_sa/CGameSA.cpp | 16 +++++----------- Client/game_sa/CGameSA.h | 2 +- Client/game_sa/CPoolSAInterface.h | 2 +- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index 3dee6f1123e..01770bf24cb 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -1020,7 +1020,7 @@ void CGameSA::RemoveGameWorld() static_cast(m_pBuildingRemoval)->DropCaches(); - m_isBuildingsRemoved = true; + m_isGameWorldRemoved = true; } void CGameSA::RestoreGameWorld() @@ -1029,27 +1029,21 @@ void CGameSA::RestoreGameWorld() m_pPools->GetDummyPool().RestoreBackup(); m_pIplStore->SetDynamicIplStreamingEnabled(true, [](CIplSAInterface* ipl) { return memcmp("barriers", ipl->name, 8) != 0; }); - m_isBuildingsRemoved = false; + m_isGameWorldRemoved = false; } bool CGameSA::SetBuildingPoolSize(size_t size) { - const bool shouldRemoveBuilding = !m_isBuildingsRemoved; - if (shouldRemoveBuilding) - { + const bool shouldRemoveWorld = !m_isGameWorldRemoved; + if (shouldRemoveWorld) RemoveGameWorld(); - } else - { static_cast(m_pBuildingRemoval)->DropCaches(); - } bool status = m_pPools->GetBuildingsPool().Resize(size); - if (shouldRemoveBuilding) - { + if (shouldRemoveWorld) RestoreGameWorld(); - } return status; } diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index 3bdc10baf93..bbfc4b9ef19 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -372,7 +372,7 @@ class CGameSA : public CGame bool m_isBurnFlippedCarsEnabled{true}; bool m_isFireballDestructEnabled{true}; bool m_isRoadSignsTextEnabled{true}; - bool m_isBuildingsRemoved{false}; + bool m_isGameWorldRemoved{false}; bool m_isExtendedWaterCannonsEnabled{false}; static unsigned int& ClumpOffset; diff --git a/Client/game_sa/CPoolSAInterface.h b/Client/game_sa/CPoolSAInterface.h index 4ae1de87474..0416b90a34f 100644 --- a/Client/game_sa/CPoolSAInterface.h +++ b/Client/game_sa/CPoolSAInterface.h @@ -114,7 +114,7 @@ class CPoolSAInterface void Delete(uint index) { Release(index); } - int Size() const noexcept { return m_nSize; }; + std::int32_t Size() const noexcept { return m_nSize; }; bool IsEmpty(std::int32_t objectIndex) const { return m_byteMap[objectIndex].bEmpty; } bool IsContains(uint index) const { From 899efd5220dceef733f8c754d271ff9f186415d8 Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Sun, 4 Aug 2024 20:10:55 +0300 Subject: [PATCH 4/9] Use auto for loop iterator --- Client/game_sa/CDummyPoolSA.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Client/game_sa/CDummyPoolSA.cpp b/Client/game_sa/CDummyPoolSA.cpp index dead250f750..5985bcfbf9d 100644 --- a/Client/game_sa/CDummyPoolSA.cpp +++ b/Client/game_sa/CDummyPoolSA.cpp @@ -31,7 +31,7 @@ void CDummyPoolSA::RemoveAllWithBackup() m_pOriginalElementsBackup = std::make_unique(); auto pDummyPool = (*m_ppDummyPoolInterface); - for (size_t i = 0; i < MAX_DUMMIES_DEFAULT; i++) + for (auto i = 0; i < MAX_DUMMIES_DEFAULT; i++) { if (pDummyPool->IsContains(i)) { @@ -59,7 +59,7 @@ void CDummyPoolSA::RestoreBackup() auto& originalData = *m_pOriginalElementsBackup; auto pDummyPool = (*m_ppDummyPoolInterface); - for (size_t i = 0; i < MAX_DUMMIES_DEFAULT; i++) + for (auto i = 0; i < MAX_DUMMIES_DEFAULT; i++) { if (originalData[i].first) { @@ -80,7 +80,7 @@ void CDummyPoolSA::UpdateBuildingLods(void* oldPool, void* newPool) if (m_pOriginalElementsBackup) { - for (int i = 0; i < (*m_pOriginalElementsBackup).size(); i++) + for (auto i = 0; i < (*m_pOriginalElementsBackup).size(); i++) { if ((*m_pOriginalElementsBackup)[i].first) { @@ -94,7 +94,7 @@ void CDummyPoolSA::UpdateBuildingLods(void* oldPool, void* newPool) } else { - for (int i = 0; i < (*m_ppDummyPoolInterface)->Size(); i++) + for (auto i = 0; i < (*m_ppDummyPoolInterface)->Size(); i++) { CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i); if (object->m_pLod) From 78d32b6bcf66228f1fa981db5a5b8f63e0a1fa30 Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Wed, 21 Aug 2024 21:47:25 +0300 Subject: [PATCH 5/9] Use method access --- Client/game_sa/CDummyPoolSA.cpp | 40 ++++++++++++++++++--------------- Client/game_sa/CDummyPoolSA.h | 4 ++++ Client/game_sa/CEntitySA.h | 3 +++ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/Client/game_sa/CDummyPoolSA.cpp b/Client/game_sa/CDummyPoolSA.cpp index 5985bcfbf9d..1b7bf87d657 100644 --- a/Client/game_sa/CDummyPoolSA.cpp +++ b/Client/game_sa/CDummyPoolSA.cpp @@ -79,28 +79,32 @@ void CDummyPoolSA::UpdateBuildingLods(void* oldPool, void* newPool) const std::uint32_t offset = (std::uint32_t)newPool - (std::uint32_t)oldPool; if (m_pOriginalElementsBackup) + UpdateBackupLodOffset(offset); + else + UpdateLodsOffestInPool(offset); +} + +void CDummyPoolSA::UpdateBackupLodOffset(const std::uint32_t offset) +{ + for (auto i = 0; i < (*m_pOriginalElementsBackup).size(); i++) { - for (auto i = 0; i < (*m_pOriginalElementsBackup).size(); i++) + if ((*m_pOriginalElementsBackup)[i].first) { - if ((*m_pOriginalElementsBackup)[i].first) - { - CEntitySAInterface* object = &(*m_pOriginalElementsBackup)[i].second; - if (object->m_pLod) - { - object->m_pLod = (CEntitySAInterface*)((std::uint32_t)(object->m_pLod) + offset); - } - } + CEntitySAInterface* object = &(*m_pOriginalElementsBackup)[i].second; + CEntitySAInterface* lod = object->GetLod(); + if (lod) + object->SetLod((CEntitySAInterface*)((std::uint32_t)lod + offset)); } } - else +} + +void CDummyPoolSA::UpdateLodsOffestInPool(const std::uint32_t offset) +{ + for (auto i = 0; i < (*m_ppDummyPoolInterface)->Size(); i++) { - for (auto i = 0; i < (*m_ppDummyPoolInterface)->Size(); i++) - { - CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i); - if (object->m_pLod) - { - object->m_pLod = (CEntitySAInterface*)((std::uint32_t)object->m_pLod + offset); - } - } + CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i); + CEntitySAInterface* lod = object->GetLod(); + if (lod) + object->SetLod((CEntitySAInterface*)((std::uint32_t)lod + offset)); } } diff --git a/Client/game_sa/CDummyPoolSA.h b/Client/game_sa/CDummyPoolSA.h index 7971a086d6a..1e65676cf7d 100644 --- a/Client/game_sa/CDummyPoolSA.h +++ b/Client/game_sa/CDummyPoolSA.h @@ -28,6 +28,10 @@ class CDummyPoolSA final : public CDummyPool void RestoreBackup() override; void UpdateBuildingLods(void* oldPool, void* newPool); +private: + void UpdateBackupLodOffset(const std::uint32_t offest); + void UpdateLodsOffestInPool(const std::uint32_t offset); + private: CPoolSAInterface** m_ppDummyPoolInterface; diff --git a/Client/game_sa/CEntitySA.h b/Client/game_sa/CEntitySA.h index a5a0de0dd9f..5a237d03756 100644 --- a/Client/game_sa/CEntitySA.h +++ b/Client/game_sa/CEntitySA.h @@ -202,6 +202,9 @@ class CEntitySAInterface // Functions to hide member variable misuse // + void SetLod(CEntitySAInterface* pLod) noexcept { m_pLod = pLod; }; + CEntitySAInterface* GetLod() const noexcept { return m_pLod; }; + // Sets void SetIsLowLodEntity() { numLodChildrenRendered = 0x40; } From 91a22d0881a9c991d28c08ca369fa22d4508c15d Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Wed, 21 Aug 2024 22:09:32 +0300 Subject: [PATCH 6/9] Use offset argument --- Client/game_sa/CBuildingsPoolSA.cpp | 4 ++-- Client/game_sa/CDummyPoolSA.cpp | 4 +--- Client/game_sa/CDummyPoolSA.h | 2 +- Client/sdk/game/CDummyPool.h | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Client/game_sa/CBuildingsPoolSA.cpp b/Client/game_sa/CBuildingsPoolSA.cpp index 2b55e4c92d3..7f4f05f1811 100644 --- a/Client/game_sa/CBuildingsPoolSA.cpp +++ b/Client/game_sa/CBuildingsPoolSA.cpp @@ -224,7 +224,7 @@ bool CBuildingsPoolSA::Resize(int size) newBytemap[i].bEmpty = true; } - const uint32_t offset = (uint32_t)newObjects - (uint32_t)oldPool; + const std::uint32_t offset = (std::uint32_t)newObjects - (std::uint32_t)oldPool; if (oldPool != nullptr) { UpdateIplEntrysPointers(offset); @@ -235,7 +235,7 @@ bool CBuildingsPoolSA::Resize(int size) UpdateBackupLodPointers(offset); } - pGame->GetPools()->GetDummyPool().UpdateBuildingLods(oldPool, newObjects); + pGame->GetPools()->GetDummyPool().UpdateBuildingLods(offset); RemoveVehicleDamageLinks(); RemovePedsContactEnityLinks(); diff --git a/Client/game_sa/CDummyPoolSA.cpp b/Client/game_sa/CDummyPoolSA.cpp index 1b7bf87d657..5a85061f109 100644 --- a/Client/game_sa/CDummyPoolSA.cpp +++ b/Client/game_sa/CDummyPoolSA.cpp @@ -74,10 +74,8 @@ void CDummyPoolSA::RestoreBackup() m_pOriginalElementsBackup = nullptr; } -void CDummyPoolSA::UpdateBuildingLods(void* oldPool, void* newPool) +void CDummyPoolSA::UpdateBuildingLods(const std::uint32_t offset) { - const std::uint32_t offset = (std::uint32_t)newPool - (std::uint32_t)oldPool; - if (m_pOriginalElementsBackup) UpdateBackupLodOffset(offset); else diff --git a/Client/game_sa/CDummyPoolSA.h b/Client/game_sa/CDummyPoolSA.h index 1e65676cf7d..8f42d98c7c1 100644 --- a/Client/game_sa/CDummyPoolSA.h +++ b/Client/game_sa/CDummyPoolSA.h @@ -26,7 +26,7 @@ class CDummyPoolSA final : public CDummyPool void RemoveAllWithBackup() override; void RestoreBackup() override; - void UpdateBuildingLods(void* oldPool, void* newPool); + void UpdateBuildingLods(const std::uint32_t offset); private: void UpdateBackupLodOffset(const std::uint32_t offest); diff --git a/Client/sdk/game/CDummyPool.h b/Client/sdk/game/CDummyPool.h index 793ae3d6f55..08ca6f7256d 100644 --- a/Client/sdk/game/CDummyPool.h +++ b/Client/sdk/game/CDummyPool.h @@ -18,5 +18,5 @@ class CDummyPool public: virtual void RemoveAllWithBackup() = 0; virtual void RestoreBackup() = 0; - virtual void UpdateBuildingLods(void* oldPool, void* newPool) = 0; + virtual void UpdateBuildingLods(const std::uint32_t offset) = 0; }; From 71d99cbd4ceb9d07a08b10ffcdbd0eb1756db540 Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Wed, 21 Aug 2024 22:54:12 +0300 Subject: [PATCH 7/9] Use range loop --- Client/game_sa/CDummyPoolSA.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Client/game_sa/CDummyPoolSA.cpp b/Client/game_sa/CDummyPoolSA.cpp index 5a85061f109..6a67cdb9000 100644 --- a/Client/game_sa/CDummyPoolSA.cpp +++ b/Client/game_sa/CDummyPoolSA.cpp @@ -84,11 +84,11 @@ void CDummyPoolSA::UpdateBuildingLods(const std::uint32_t offset) void CDummyPoolSA::UpdateBackupLodOffset(const std::uint32_t offset) { - for (auto i = 0; i < (*m_pOriginalElementsBackup).size(); i++) + for (auto& it : *m_pOriginalElementsBackup) { - if ((*m_pOriginalElementsBackup)[i].first) + if (it.first) { - CEntitySAInterface* object = &(*m_pOriginalElementsBackup)[i].second; + CEntitySAInterface* object = &it.second; CEntitySAInterface* lod = object->GetLod(); if (lod) object->SetLod((CEntitySAInterface*)((std::uint32_t)lod + offset)); From a1cae25367d4c10eb08c6c5e2803b6c4ba5b11ef Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Tue, 15 Oct 2024 04:11:32 +0300 Subject: [PATCH 8/9] fix conflict --- Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp index 2de2c8e87ac..a9c0da3ca96 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp @@ -101,7 +101,6 @@ void CLuaWorldDefs::LoadFunctions() {"setFPSLimit", SetFPSLimit}, {"setCoronaReflectionsEnabled", ArgumentParser}, {"setWorldProperty", ArgumentParser}, - {"setTimeFrozen", ArgumentParser}, // World remove/restore functions {"removeWorldModel", RemoveWorldBuilding}, From 5ae7d20033377b4f41bf4e47c77b02fc6cb62107 Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Sun, 5 Jan 2025 18:04:12 +0300 Subject: [PATCH 9/9] review --- Client/game_sa/CGameSA.cpp | 8 ++++---- Client/sdk/game/Common.h | 1 + Server/mods/deathmatch/logic/CResourceChecker.Data.h | 5 ++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index 460390e6854..744993584e5 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -1069,8 +1069,8 @@ void CGameSA::RemoveGameWorld() // Remove all shadows in CStencilShadowObjects::dtorAll ((void* (*)())0x711390)(); - m_pPools->GetDummyPool().RemoveAllWithBackup(); - m_pPools->GetBuildingsPool().RemoveAllWithBackup(); + m_Pools->GetDummyPool().RemoveAllWithBackup(); + m_Pools->GetBuildingsPool().RemoveAllWithBackup(); static_cast(m_pBuildingRemoval)->DropCaches(); @@ -1079,8 +1079,8 @@ void CGameSA::RemoveGameWorld() void CGameSA::RestoreGameWorld() { - m_pPools->GetBuildingsPool().RestoreBackup(); - m_pPools->GetDummyPool().RestoreBackup(); + m_Pools->GetBuildingsPool().RestoreBackup(); + m_Pools->GetDummyPool().RestoreBackup(); m_pIplStore->SetDynamicIplStreamingEnabled(true, [](CIplSAInterface* ipl) { return memcmp("barriers", ipl->name, 8) != 0; }); m_isGameWorldRemoved = false; diff --git a/Client/sdk/game/Common.h b/Client/sdk/game/Common.h index b5be2007ac3..11e5a31554f 100644 --- a/Client/sdk/game/Common.h +++ b/Client/sdk/game/Common.h @@ -27,6 +27,7 @@ #define MAX_PEDS ( MAX_PEDS_MTA + 30 ) // 140 #define MAX_OBJECTS ( MAX_OBJECTS_MTA + 200 ) // 1200 #define MAX_BUILDINGS 13000 +#define MAX_DUMMIES 2500 #define MAX_ENTRY_INFO_NODES ( MAX_ENTRY_INFO_NODES_MTA + 600 ) // 72600 #define MAX_POINTER_SINGLE_LINKS ( MAX_POINTER_SINGLE_LINKS_MTA + 5000 ) // 90000 #define MAX_POINTER_DOUBLE_LINKS ( MAX_POINTER_DOUBLE_LINKS_MTA + 800 ) // 74800 diff --git a/Server/mods/deathmatch/logic/CResourceChecker.Data.h b/Server/mods/deathmatch/logic/CResourceChecker.Data.h index b5ace221e1b..6c22ecff134 100644 --- a/Server/mods/deathmatch/logic/CResourceChecker.Data.h +++ b/Server/mods/deathmatch/logic/CResourceChecker.Data.h @@ -174,7 +174,10 @@ namespace {false, "getHelicopterRotorSpeed", "getVehicleRotorSpeed"}, {false, "setPedOnFire", "setElementOnFire"}, - {false, "isPedOnFire", "isElementOnFire"} + {false, "isPedOnFire", "isElementOnFire"}, + + {false, "removeAllGameBuildings", "removeGameWorld"}, + {false, "restoreAllGameBuildings", "restoreGameWorld"}, }; SDeprecatedItem serverDeprecatedList[] = {