Skip to content

Commit

Permalink
Add engineStreamingRequestModel
Browse files Browse the repository at this point in the history
  • Loading branch information
TheNormalnij committed Jul 27, 2024
1 parent 1e21c53 commit 8f19ae3
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 1 deletion.
10 changes: 10 additions & 0 deletions Client/game_sa/CModelInfoSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,16 @@ void CModelInfoSA::Remove()
}
}

bool CModelInfoSA::UnloadUnused()
{
if (m_pInterface->usNumberOfRefs == 0 && !m_pCustomClump && !m_pCustomColModel)
{
pGame->GetStreaming()->RemoveModel(m_dwModelID);
return true;
}
return false;
}

bool CModelInfoSA::IsLoaded()
{
if (DoIsLoaded())
Expand Down
1 change: 1 addition & 0 deletions Client/game_sa/CModelInfoSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ class CModelInfoSA : public CModelInfo
BYTE GetVehicleType();
void Request(EModelRequestType requestType, const char* szTag);
void Remove();
bool UnloadUnused();
bool IsLoaded();
bool DoIsLoaded();
unsigned short GetFlags();
Expand Down
5 changes: 5 additions & 0 deletions Client/mods/deathmatch/logic/CClientModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ bool CClientModel::Deallocate()
if (!m_bAllocatedByUs)
return false;

if (m_pParentResource)
{
m_pParentResource->GetResourceModelStreamer()->FullyReleaseModel(m_iModelID);
}

SetParentResource(nullptr);

CModelInfo* pModelInfo = g_pGame->GetModelInfo(m_iModelID, true);
Expand Down
3 changes: 3 additions & 0 deletions Client/mods/deathmatch/logic/CResource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ CResource::CResource(unsigned short usNetID, const char* szResourceName, CClient

CResource::~CResource()
{
// Remove refrences from requested models
m_modelStreamer.ReleaseAll();

// Deallocate all models that this resource allocated earlier
g_pClientGame->GetManager()->GetModelManager()->DeallocateModelsAllocatedByResource(this);

Expand Down
5 changes: 5 additions & 0 deletions Client/mods/deathmatch/logic/CResource.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "CClientEntity.h"
#include "CResourceConfigItem.h"
#include "CResourceFile.h"
#include "CResourceModelStreamer.h"
#include "CElementGroup.h"
#include <list>

Expand Down Expand Up @@ -79,6 +80,8 @@ class CResource
CClientEntity* GetResourceIFPRoot() { return m_pResourceIFPRoot; };
CClientEntity* GetResourceIMGRoot() { return m_pResourceIMGRoot; };

CResourceModelStreamer* GetResourceModelStreamer() { return &m_modelStreamer; };

// This is to delete all the elements created in this resource that are created locally in this client
void DeleteClientChildren();

Expand Down Expand Up @@ -145,4 +148,6 @@ class CResource
CFastHashSet<SString> m_exportedFunctions;
CElementGroup* m_pDefaultElementGroup; // stores elements created by scripts in this resource
std::list<SNoClientCacheScript> m_NoClientCacheScriptList;

CResourceModelStreamer m_modelStreamer{};
};
115 changes: 115 additions & 0 deletions Client/mods/deathmatch/logic/CResourceModelStreamer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: mods/deathmatch/logic/CResourceModelStreamer.cpp
* PURPOSE: Resource model manager
*
* Multi Theft Auto is available from https://www.multitheftauto.com/
*
*****************************************************************************/

#include "StdInc.h"

#include "CResourceModelStreamer.h"
#include "CClientGame.h"
#include <game/CStreaming.h>

bool CResourceModelStreamer::RequestModel(uint16_t modelId, bool addRef, bool blocking)
{
CModelInfo* model = g_pGame->GetModelInfo(modelId);

if (!model)
return false;

if (addRef)
{
uint16_t refsCount = ++m_requestedModels[modelId];
if (refsCount == 1)
{
model->ModelAddRef(blocking ? EModelRequestType::BLOCKING : EModelRequestType::NON_BLOCKING, "CResourceModelStreamer::RequestModel With reference");
return true;
}
return false;
}
else
{
model->Request(blocking ? EModelRequestType::BLOCKING : EModelRequestType::NON_BLOCKING, "CResourceModelStreamer::RequestModel With out reference");
return true;
}
}

// Retrun true if model was unloaded
bool CResourceModelStreamer::ReleaseModel(uint16_t modelId, bool removeRef)
{
if (removeRef)
{
auto refs = m_requestedModels.find(modelId);
if (refs == m_requestedModels.end())
return false;

uint16_t& refsCount = (*refs).second;

if (refsCount == 0)
return false;

refsCount--;

if (refsCount != 0)
return false;

CModelInfo* model = g_pGame->GetModelInfo(modelId);

if (!model)
return false;

// Hack
// This check will update models pending references
model->IsLoaded();

// This call can unload the model
model->RemoveRef();

return !model->IsLoaded();
}
else
{
CModelInfo* model = g_pGame->GetModelInfo(modelId);

if (!model)
return false;

return model->UnloadUnused();
}
}

void CResourceModelStreamer::ReleaseAll()
{
for (const auto &modelRefs : m_requestedModels)
{
if (modelRefs.second > 0)
{
CModelInfo* model = g_pGame->GetModelInfo(modelRefs.first);
model->RemoveRef();
}
}

m_requestedModels.clear();
}

void CResourceModelStreamer::FullyReleaseModel(uint16_t modelId)
{
uint16_t &refsCount = m_requestedModels[modelId];

if (refsCount > 0)
{
refsCount = 0;

CModelInfo* model = g_pGame->GetModelInfo(modelId);

if (!model)
return;

model->RemoveRef();
}
}
30 changes: 30 additions & 0 deletions Client/mods/deathmatch/logic/CResourceModelStreamer.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: mods/deathmatch/logic/CResourceModelStreamer.h
* PURPOSE: Resource model manager
*
* Multi Theft Auto is available from https://www.multitheftauto.com/
*
*****************************************************************************/

#pragma once

#include <unordered_map>

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

bool RequestModel(uint16_t modelId, bool addRef = false, bool blocking = false);
bool ReleaseModel(uint16_t modelId, bool removeRef = false);

void ReleaseAll();
void FullyReleaseModel(uint16_t modelId);

private:
std::unordered_map<uint16_t, uint16_t> m_requestedModels;
};
2 changes: 1 addition & 1 deletion Client/mods/deathmatch/logic/lua/CLuaMain.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class CLuaMain //: public CClient

void ResetInstructionCount();

class CResource* GetResource() { return m_pResource; }
class CResource* GetResource() const { return m_pResource; }

CXMLFile* CreateXML(const char* szFilename, bool bUseIDs = true, bool bReadOnly = false);
CXMLNode* ParseString(const char* strXmlContent);
Expand Down
35 changes: 35 additions & 0 deletions Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <game/CObjectGroupPhysicalProperties.h>
#include <game/CStreaming.h>
#include <lua/CLuaFunctionParser.h>
#include "CLuaEngineDefs.h"

//! Set the CModelCacheManager limits
//! By passing `nil`/no value the original values are restored
Expand Down Expand Up @@ -135,6 +136,8 @@ void CLuaEngineDefs::LoadFunctions()
{"engineStreamingSetBufferSize", ArgumentParser<EngineStreamingSetBufferSize>},
{"engineStreamingGetBufferSize", ArgumentParser<EngineStreamingGetBufferSize>},
{"engineStreamingRestoreBufferSize", ArgumentParser<EngineStreamingRestoreBufferSize>},
{"engineStreamingRequestModel", ArgumentParser<EngineStreamingRequestModel>},
{"engineStreamingReleaseModel", ArgumentParser<EngineStreamingReleaseModel>},
{"engineRequestTXD", ArgumentParser<EngineRequestTXD>},
{"engineFreeTXD", ArgumentParser<EngineFreeTXD>},
{"engineGetPoolCapacity", ArgumentParser<EngineGetPoolCapacity>},
Expand Down Expand Up @@ -2505,3 +2508,35 @@ bool CLuaEngineDefs::EngineSetPoolCapacity(lua_State* luaVM, ePools pool, size_t
}
return true;
}

bool CLuaEngineDefs::EngineStreamingRequestModel(lua_State* const luaVM, uint16_t modelId, std::optional<bool> addReference, std::optional<bool> blocking)
{
// Grab the lua main and the resource belonging to this script
CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM);

CModelInfo* pModelInfo = g_pGame->GetModelInfo(modelId);

if (modelId >= 25000 || !pModelInfo)
throw std::invalid_argument("Expected a valid model ID in range [0-24999] at argument 1");

// Get the resource we belong to
CResource* pResource = pLuaMain->GetResource();

return pResource->GetResourceModelStreamer()->RequestModel(modelId, addReference.value_or(false), blocking.value_or(false));
}

bool CLuaEngineDefs::EngineStreamingReleaseModel(lua_State* const luaVM, uint16_t modelId, std::optional<bool> removeReference)
{
// Grab the lua main and the resource belonging to this script
CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM);

CModelInfo* pModelInfo = g_pGame->GetModelInfo(modelId);

if (modelId >= 25000 || !pModelInfo)
throw std::invalid_argument("Expected a valid model ID in range [0-24999] at argument 1");

// Get the resource we belong to
CResource* pResource = pLuaMain->GetResource();

return pResource->GetResourceModelStreamer()->ReleaseModel(modelId, removeReference.value_or(false));
}
3 changes: 3 additions & 0 deletions Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ class CLuaEngineDefs : public CLuaDefs
static uint EngineRequestTXD(lua_State* const luaVM, std::string strTxdName);
static bool EngineFreeTXD(uint txdID);

static bool EngineStreamingRequestModel(lua_State* const luaVM, uint16_t modelId, std::optional<bool> addReference, std::optional<bool> blocking);
static bool EngineStreamingReleaseModel(lua_State* const luaVM, uint16_t modelId, std::optional<bool> removeReference);

private:
static void AddEngineColClass(lua_State* luaVM);
static void AddEngineTxdClass(lua_State* luaVM);
Expand Down
1 change: 1 addition & 0 deletions Client/sdk/game/CModelInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class CModelInfo
virtual void RemoveRef(bool bRemoveExtraGTARef = false) = 0;
virtual int GetRefCount() = 0;
virtual bool ForceUnload() = 0;
virtual bool UnloadUnused() = 0;
virtual void DeallocateModel() = 0;

virtual float GetDistanceFromCentreOfMassToBaseOfModel() = 0;
Expand Down

0 comments on commit 8f19ae3

Please sign in to comment.