diff --git a/src/Modules/MaterialSystem.cpp b/src/Modules/MaterialSystem.cpp index 4babd201..a820715d 100644 --- a/src/Modules/MaterialSystem.cpp +++ b/src/Modules/MaterialSystem.cpp @@ -43,6 +43,7 @@ class MemTexRegen : public ITextureRegenerator { }; REDECL(MaterialSystem::UncacheUnusedMaterials); +REDECL(MaterialSystem::CreateMaterial); DETOUR(MaterialSystem::UncacheUnusedMaterials, bool bRecomputeStateSnapshots) { auto start = std::chrono::high_resolution_clock::now(); @@ -53,12 +54,37 @@ DETOUR(MaterialSystem::UncacheUnusedMaterials, bool bRecomputeStateSnapshots) { return result; } +DETOUR_T(IMaterial *, MaterialSystem::CreateMaterial, const char *pMaterialName, void *pVMTKeyValues) { + if (sar.game->Is(SourceGame_Portal2 | SourceGame_PortalReloaded | SourceGame_PortalStoriesMel)) { + // Patched by Valve, no need for us to do it again + return MaterialSystem::CreateMaterial(thisptr, pMaterialName, pVMTKeyValues); + } + + std::string sMaterialName(pMaterialName); + std::string sMapName(engine->m_szLevelName); + std::replace(sMaterialName.begin(), sMaterialName.end(), '\\', '/'); + std::replace(sMapName.begin(), sMapName.end(), '\\', '/'); + + // Memory leak ultimate fix! -route credits to krzyhau + // apparently the game loads PeTI related materials into the memory every time you + // load the game. This simply prevents that from happening. + // Revived from the dead for mods! + bool isPetiMaterial = sMaterialName.find("props_map_editor") != std::string::npos; + bool isWhiteMaterial = sMaterialName.find("vgui/white") != std::string::npos; + bool isPetiMap = sMapName.find("puzzlemaker/") != std::string::npos; + if ((isPetiMaterial || isWhiteMaterial) && !isPetiMap) { + return 0; + } + + return MaterialSystem::CreateMaterial(thisptr, pMaterialName, pVMTKeyValues); +} + bool MaterialSystem::Init() { this->materials = Interface::Create(this->Name(), "VMaterialSystem080"); if (this->materials) { this->materials->Hook(MaterialSystem::UncacheUnusedMaterials_Hook, MaterialSystem::UncacheUnusedMaterials, Offsets::UncacheUnusedMaterials); + this->materials->Hook(MaterialSystem::CreateMaterial_Hook, MaterialSystem::CreateMaterial, Offsets::CreateMaterial); - this->CreateMaterial = this->materials->Original<_CreateMaterial>(Offsets::CreateMaterial); this->RemoveMaterial = this->materials->Original<_RemoveMaterial>(Offsets::RemoveMaterial); this->KeyValues_SetString = (_KeyValues_SetString)Memory::Scan(this->Name(), Offsets::KeyValues_SetString); diff --git a/src/Modules/MaterialSystem.hpp b/src/Modules/MaterialSystem.hpp index 46f9e154..e7c12b89 100644 --- a/src/Modules/MaterialSystem.hpp +++ b/src/Modules/MaterialSystem.hpp @@ -11,9 +11,6 @@ class MaterialSystem : public Module { public: Interface *materials = nullptr; - using _CreateMaterial = IMaterial*(__rescall*)(void* thisptr, const char *pMaterialName, void *pVMTKeyValues); - _CreateMaterial CreateMaterial = nullptr; - using _RemoveMaterial = void(__rescall*)(void* thisptr, IMaterialInternal* pMaterial); _RemoveMaterial RemoveMaterial = nullptr; @@ -22,6 +19,7 @@ class MaterialSystem : public Module { public: DECL_DETOUR(UncacheUnusedMaterials, bool bRecomputeStateSnapshots); + DECL_DETOUR_T(IMaterial *, CreateMaterial, const char *pMaterialName, void *pVMTKeyValues); bool Init() override; void Shutdown() override;