mirror of
				https://github.com/DarkflameUniverse/DarkflameServer.git
				synced 2025-10-31 12:41:55 +00:00 
			
		
		
		
	Added caching for behavior parameter table (#621)
* Added caching for table Added caching for table Add more caching Update MasterServer.cpp grds Update CDBehaviorParameterTable.cpp Update CDBehaviorParameterTable.h Update CDBehaviorTemplateTable.cpp Update Behavior.cpp Update Behavior.cpp change to map Remove redundant query * Remove include * change to enum * Update Behavior.cpp * Use already cached table * Update Behavior.cpp
This commit is contained in:
		| @@ -8,7 +8,7 @@ void CDClientManager::Initialize(void) { | ||||
| 	tables.insert(std::make_pair("ActivityRewards", new CDActivityRewardsTable())); | ||||
| 	UNUSED(tables.insert(std::make_pair("Animations", new CDAnimationsTable()))); | ||||
| 	tables.insert(std::make_pair("BehaviorParameter", new CDBehaviorParameterTable())); | ||||
| 	UNUSED(tables.insert(std::make_pair("BehaviorTemplate", new CDBehaviorTemplateTable()))); | ||||
| 	tables.insert(std::make_pair("BehaviorTemplate", new CDBehaviorTemplateTable())); | ||||
| 	tables.insert(std::make_pair("ComponentsRegistry", new CDComponentsRegistryTable())); | ||||
| 	tables.insert(std::make_pair("CurrencyTable", new CDCurrencyTableTable())); | ||||
| 	tables.insert(std::make_pair("DestructibleComponent", new CDDestructibleComponentTable())); | ||||
|   | ||||
| @@ -3,33 +3,25 @@ | ||||
|  | ||||
| //! Constructor | ||||
| CDBehaviorParameterTable::CDBehaviorParameterTable(void) { | ||||
| #ifdef CDCLIENT_CACHE_ALL | ||||
| 	auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter"); | ||||
| 	size_t hash = 0; | ||||
| 	while (!tableData.eof()) { | ||||
| 		hash = 0; | ||||
| 		CDBehaviorParameter entry; | ||||
| 		entry.behaviorID = tableData.getIntField(0, -1); | ||||
| 		entry.parameterID = tableData.getStringField(1, ""); | ||||
| 		entry.value = tableData.getFloatField(2, -1.0f); | ||||
|  | ||||
| 		//Check if we have an entry with this ID: | ||||
| 		auto it = m_entries.find(entry.behaviorID); | ||||
| 		if (it != m_entries.end()) { | ||||
| 			it->second.insert(std::make_pair(entry.parameterID, entry.value)); | ||||
| 		} | ||||
| 		else { | ||||
| 			//Otherwise, insert it: | ||||
| 			m_entries.insert(std::make_pair(entry.behaviorID, std::map<std::string, float>())); | ||||
| 			auto jit = m_entries.find(entry.behaviorID); | ||||
| 		GeneralUtils::hash_combine(hash, entry.behaviorID); | ||||
| 		GeneralUtils::hash_combine(hash, entry.parameterID); | ||||
|  | ||||
| 			//Add our value as well: | ||||
| 			jit->second.insert(std::make_pair(entry.parameterID, entry.value)); | ||||
| 		} | ||||
| 		auto it = m_Entries.find(entry.behaviorID); | ||||
| 		m_ParametersList.insert(entry.parameterID); | ||||
| 		m_Entries.insert(std::make_pair(hash, entry)); | ||||
|  | ||||
| 		tableData.nextRow(); | ||||
| 	} | ||||
|  | ||||
| 	tableData.finalize(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| //! Destructor | ||||
| @@ -40,51 +32,33 @@ std::string CDBehaviorParameterTable::GetName(void) const { | ||||
| 	return "BehaviorParameter"; | ||||
| } | ||||
|  | ||||
| float CDBehaviorParameterTable::GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue)  | ||||
| CDBehaviorParameter CDBehaviorParameterTable::GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue)  | ||||
| { | ||||
| 	CDBehaviorParameter returnValue; | ||||
| 	returnValue.behaviorID = 0; | ||||
| 	returnValue.parameterID = ""; | ||||
| 	returnValue.value = defaultValue; | ||||
|  | ||||
| 	size_t hash = 0; | ||||
| 	GeneralUtils::hash_combine(hash, behaviorID); | ||||
| 	GeneralUtils::hash_combine(hash, name); | ||||
|  | ||||
| 	// Search for specific parameter | ||||
| 	const auto& it = m_Entries.find(hash); | ||||
| 	if (it != m_Entries.end()) { | ||||
| 		return it->second; | ||||
| 	} | ||||
|  | ||||
| 	// Check if this behavior has already been checked | ||||
| 	const auto& itChecked = m_Entries.find(behaviorID); | ||||
| 	if (itChecked != m_Entries.end()) { | ||||
| 		return defaultValue; | ||||
| 	} | ||||
|  | ||||
| #ifndef CDCLIENT_CACHE_ALL | ||||
| 	auto query = CDClientDatabase::CreatePreppedStmt( | ||||
| 		"SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = ?;"); | ||||
| 	query.bind(1, (int) behaviorID); | ||||
|  | ||||
| 	auto tableData = query.execQuery(); | ||||
|  | ||||
| 	m_Entries.insert_or_assign(behaviorID, 0); | ||||
|  | ||||
| 	while (!tableData.eof()) { | ||||
| 		const std::string parameterID = tableData.getStringField(0, ""); | ||||
| 		const float value = tableData.getFloatField(1, 0); | ||||
|  | ||||
| 		size_t parameterHash = 0; | ||||
| 		GeneralUtils::hash_combine(parameterHash, behaviorID); | ||||
| 		GeneralUtils::hash_combine(parameterHash, parameterID); | ||||
|  | ||||
| 		m_Entries.insert_or_assign(parameterHash, value); | ||||
|  | ||||
| 		tableData.nextRow(); | ||||
| 	} | ||||
|  | ||||
| 	const auto& it2 = m_Entries.find(hash); | ||||
| 	if (it2 != m_Entries.end()) { | ||||
| 		return it2->second; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	return defaultValue; | ||||
| 	return it != m_Entries.end() ? it->second : returnValue; | ||||
| } | ||||
|  | ||||
| std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) { | ||||
| 	size_t hash; | ||||
| 	std::map<std::string, float> returnInfo; | ||||
| 	for (auto parameterCandidate : m_ParametersList) { | ||||
| 		hash = 0; | ||||
| 		GeneralUtils::hash_combine(hash, behaviorID); | ||||
| 		GeneralUtils::hash_combine(hash, parameterCandidate); | ||||
| 		auto infoCandidate = m_Entries.find(hash); | ||||
| 		if (infoCandidate != m_Entries.end()) { | ||||
| 			returnInfo.insert(std::make_pair(infoCandidate->second.parameterID, infoCandidate->second.value)); | ||||
| 		} | ||||
| 	} | ||||
| 	return returnInfo; | ||||
| } | ||||
|   | ||||
| @@ -2,7 +2,8 @@ | ||||
|  | ||||
| // Custom Classes | ||||
| #include "CDTable.h" | ||||
| #include <map> | ||||
| #include <unordered_map> | ||||
| #include <unordered_set> | ||||
|  | ||||
| /*! | ||||
|  \file CDBehaviorParameterTable.hpp | ||||
| @@ -19,8 +20,8 @@ struct CDBehaviorParameter { | ||||
| //! BehaviorParameter table | ||||
| class CDBehaviorParameterTable : public CDTable { | ||||
| private: | ||||
|     std::map<size_t, float> m_Entries; | ||||
|      | ||||
| 	std::unordered_map<size_t, CDBehaviorParameter> m_Entries; | ||||
| 	std::unordered_set<std::string> m_ParametersList; | ||||
| public: | ||||
|      | ||||
|     //! Constructor | ||||
| @@ -35,5 +36,7 @@ public: | ||||
|      */ | ||||
|     std::string GetName(void) const override; | ||||
|      | ||||
| 	float GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue = 0); | ||||
| 	CDBehaviorParameter GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue = 0); | ||||
|  | ||||
| 	std::map<std::string, float> GetParametersByBehaviorID(uint32_t behaviorID); | ||||
| }; | ||||
|   | ||||
| @@ -27,6 +27,7 @@ CDBehaviorTemplateTable::CDBehaviorTemplateTable(void) { | ||||
|         entry.effectHandle = tableData.getStringField(3, ""); | ||||
|          | ||||
|         this->entries.push_back(entry); | ||||
|         this->entriesMappedByBehaviorID.insert(std::make_pair(entry.behaviorID, entry)); | ||||
|         tableData.nextRow(); | ||||
|     } | ||||
|  | ||||
| @@ -55,3 +56,15 @@ std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::Query(std::function<boo | ||||
| std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::GetEntries(void) const { | ||||
|     return this->entries; | ||||
| } | ||||
|  | ||||
| const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behaviorID) { | ||||
|     auto entry = this->entriesMappedByBehaviorID.find(behaviorID); | ||||
|     if (entry == this->entriesMappedByBehaviorID.end()) { | ||||
|         CDBehaviorTemplate entryToReturn; | ||||
|         entryToReturn.behaviorID = 0; | ||||
|         entryToReturn.effectHandle = ""; | ||||
|         return entryToReturn; | ||||
|     } else { | ||||
|         return entry->second; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| // Custom Classes | ||||
| #include "CDTable.h" | ||||
| #include <unordered_map> | ||||
|  | ||||
| /*! | ||||
|  \file CDBehaviorTemplateTable.hpp | ||||
| @@ -21,7 +22,7 @@ struct CDBehaviorTemplate { | ||||
| class CDBehaviorTemplateTable : public CDTable { | ||||
| private: | ||||
|     std::vector<CDBehaviorTemplate> entries; | ||||
|      | ||||
|     std::unordered_map<uint32_t, CDBehaviorTemplate> entriesMappedByBehaviorID; | ||||
| public: | ||||
|      | ||||
|     //! Constructor | ||||
| @@ -48,4 +49,5 @@ public: | ||||
|      */ | ||||
|     std::vector<CDBehaviorTemplate> GetEntries(void) const; | ||||
|  | ||||
|     const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID); | ||||
| }; | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
| #include "dLogger.h" | ||||
| #include "BehaviorTemplates.h" | ||||
| #include "BehaviorBranchContext.h" | ||||
| #include <unordered_map> | ||||
|  | ||||
| /* | ||||
|  * Behavior includes | ||||
| @@ -69,7 +70,7 @@ | ||||
| #include "RenderComponent.h" | ||||
| #include "DestroyableComponent.h" | ||||
|  | ||||
| std::map<uint32_t, Behavior*> Behavior::Cache = {}; | ||||
| std::unordered_map<uint32_t, Behavior*> Behavior::Cache = {}; | ||||
| CDBehaviorParameterTable* Behavior::BehaviorParameterTable = nullptr; | ||||
|  | ||||
| Behavior* Behavior::GetBehavior(const uint32_t behaviorId) | ||||
| @@ -285,28 +286,22 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) | ||||
| } | ||||
|  | ||||
| BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) { | ||||
| 	auto query = CDClientDatabase::CreatePreppedStmt( | ||||
| 		"SELECT templateID FROM BehaviorTemplate WHERE behaviorID = ?;"); | ||||
| 	query.bind(1, (int) behaviorId); | ||||
| 	auto behaviorTemplateTable = CDClientManager::Instance()->GetTable<CDBehaviorTemplateTable>("BehaviorTemplate"); | ||||
|  | ||||
| 	auto result = query.execQuery(); | ||||
|  | ||||
| 	// Make sure we do not proceed if we are trying to load an invalid behavior | ||||
| 	if (result.eof()) | ||||
| 	{ | ||||
| 		if (behaviorId != 0) | ||||
| 		{ | ||||
| 			Game::logger->Log("Behavior::GetBehaviorTemplate", "Failed to load behavior template with id (%i)!\n", behaviorId); | ||||
| 	BehaviorTemplates templateID = BehaviorTemplates::BEHAVIOR_EMPTY; | ||||
| 	// Find behavior template by its behavior id.  Default to 0. | ||||
| 	if (behaviorTemplateTable) { | ||||
| 		auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId); | ||||
| 		if (templateEntry.behaviorID == behaviorId) { | ||||
| 			templateID = static_cast<BehaviorTemplates>(templateEntry.templateID); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 		return BehaviorTemplates::BEHAVIOR_EMPTY; | ||||
| 	if (templateID == BehaviorTemplates::BEHAVIOR_EMPTY && behaviorId != 0) { | ||||
| 		Game::logger->Log("Behavior", "Failed to load behavior template with id (%i)!\n", behaviorId); | ||||
| 	} | ||||
|  | ||||
| 	const auto id = static_cast<BehaviorTemplates>(result.getIntField(0)); | ||||
|  | ||||
| 	result.finalize(); | ||||
|  | ||||
| 	return id; | ||||
| 	return templateID; | ||||
| } | ||||
|  | ||||
| // For use with enemies, to display the correct damage animations on the players | ||||
| @@ -412,6 +407,17 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID | ||||
|  | ||||
| Behavior::Behavior(const uint32_t behaviorId) | ||||
| { | ||||
| 	auto behaviorTemplateTable = CDClientManager::Instance()->GetTable<CDBehaviorTemplateTable>("BehaviorTemplate"); | ||||
|  | ||||
| 	CDBehaviorTemplate templateInDatabase; | ||||
|  | ||||
| 	if (behaviorTemplateTable) { | ||||
| 		auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId); | ||||
| 		if (templateEntry.behaviorID == behaviorId) { | ||||
| 			templateInDatabase = templateEntry; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	this->m_behaviorId = behaviorId; | ||||
|  | ||||
| 	// Add to cache | ||||
| @@ -423,14 +429,8 @@ Behavior::Behavior(const uint32_t behaviorId) | ||||
| 		this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY; | ||||
| 	} | ||||
|  | ||||
| 	auto query = CDClientDatabase::CreatePreppedStmt( | ||||
| 		"SELECT templateID, effectID, effectHandle FROM BehaviorTemplate WHERE behaviorID = ?;"); | ||||
| 	query.bind(1, (int) behaviorId); | ||||
|  | ||||
| 	auto result = query.execQuery(); | ||||
|  | ||||
| 	// Make sure we do not proceed if we are trying to load an invalid behavior | ||||
| 	if (result.eof()) | ||||
| 	if (templateInDatabase.behaviorID == 0) | ||||
| 	{ | ||||
| 		Game::logger->Log("Behavior", "Failed to load behavior with id (%i)!\n", behaviorId); | ||||
|  | ||||
| @@ -441,34 +441,19 @@ Behavior::Behavior(const uint32_t behaviorId) | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	this->m_templateId = static_cast<BehaviorTemplates>(result.getIntField(0)); | ||||
| 	this->m_templateId = static_cast<BehaviorTemplates>(templateInDatabase.templateID); | ||||
|  | ||||
| 	this->m_effectId = result.getIntField(1); | ||||
| 	this->m_effectId = templateInDatabase.effectID; | ||||
|  | ||||
| 	if (!result.fieldIsNull(2)) | ||||
| 	{ | ||||
| 		const std::string effectHandle = result.getStringField(2); | ||||
| 		if (effectHandle == "") | ||||
| 		{ | ||||
| 			this->m_effectHandle = nullptr; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			this->m_effectHandle = new std::string(effectHandle); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		this->m_effectHandle = nullptr; | ||||
| 	} | ||||
|  | ||||
| 	result.finalize(); | ||||
| 	this->m_effectHandle = templateInDatabase.effectHandle != "" ? new std::string(templateInDatabase.effectHandle) : nullptr; | ||||
| } | ||||
|  | ||||
|  | ||||
| float Behavior::GetFloat(const std::string& name, const float defaultValue) const | ||||
| { | ||||
| 	return BehaviorParameterTable->GetEntry(this->m_behaviorId, name, defaultValue); | ||||
| 	// Get the behavior parameter entry and return its value. | ||||
| 	if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter"); | ||||
| 	return BehaviorParameterTable->GetEntry(this->m_behaviorId, name, defaultValue).value; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -498,24 +483,14 @@ Behavior* Behavior::GetAction(float value) const | ||||
|  | ||||
| std::map<std::string, float> Behavior::GetParameterNames() const | ||||
| { | ||||
| 	std::map<std::string, float> parameters; | ||||
|  | ||||
| 	auto query = CDClientDatabase::CreatePreppedStmt( | ||||
| 		"SELECT parameterID, value FROM BehaviorParameter WHERE behaviorID = ?;"); | ||||
| 	query.bind(1, (int) this->m_behaviorId); | ||||
|  | ||||
| 	auto tableData = query.execQuery(); | ||||
|  | ||||
| 	while (!tableData.eof()) | ||||
| 	{ | ||||
| 		parameters.insert_or_assign(tableData.getStringField(0, ""), tableData.getFloatField(1, 0)); | ||||
|  | ||||
| 		tableData.nextRow(); | ||||
| 	std::map<std::string, float> templatesInDatabase; | ||||
| 	// Find behavior template by its behavior id. | ||||
| 	if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter"); | ||||
| 	if (BehaviorParameterTable) { | ||||
| 		templatesInDatabase = BehaviorParameterTable->GetParametersByBehaviorID(this->m_behaviorId); | ||||
| 	} | ||||
|  | ||||
| 	tableData.finalize(); | ||||
|  | ||||
| 	return parameters; | ||||
| 	return templatesInDatabase; | ||||
| } | ||||
|  | ||||
| void Behavior::Load() | ||||
|   | ||||
| @@ -19,7 +19,7 @@ public: | ||||
| 	/* | ||||
| 	 * Static | ||||
| 	 */ | ||||
| 	static std::map<uint32_t, Behavior*> Cache; | ||||
| 	static std::unordered_map<uint32_t, Behavior*> Cache; | ||||
| 	static CDBehaviorParameterTable* BehaviorParameterTable; | ||||
|  | ||||
| 	static Behavior* GetBehavior(uint32_t behaviorId); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 David Markowitz
					David Markowitz