mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-26 07:27:18 +00:00
Initial concept for CDClient rework.
Utilizes `boost::interprocess` to share a map between worlds. The master server loads the table into memory, and the worlds hook into it when they want to get an entry. This solves the issue of skill delay, but introduces the third-party library Boost. There should be a conversation about the introduction of Boost — it is a large library and adds extra steps to the installation.
This commit is contained in:
parent
485de6173a
commit
34fa43ed93
@ -331,6 +331,15 @@ target_link_libraries(dNet dDatabase)
|
|||||||
target_link_libraries(dGame dDatabase)
|
target_link_libraries(dGame dDatabase)
|
||||||
target_link_libraries(dChatFilter dDatabase)
|
target_link_libraries(dChatFilter dDatabase)
|
||||||
|
|
||||||
|
# Include Boost
|
||||||
|
find_package(Boost COMPONENTS interprocess)
|
||||||
|
|
||||||
|
if(Boost_FOUND)
|
||||||
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
target_link_libraries(dGame ${Boost_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(raknet ws2_32)
|
target_link_libraries(raknet ws2_32)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
@ -1,27 +1,35 @@
|
|||||||
#include "CDBehaviorParameterTable.h"
|
#include "CDBehaviorParameterTable.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
#include "dServer.h"
|
||||||
|
|
||||||
|
#include <boost/interprocess/managed_shared_memory.hpp>
|
||||||
|
#include <boost/interprocess/containers/map.hpp>
|
||||||
|
#include <boost/interprocess/allocators/allocator.hpp>
|
||||||
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
typedef size_t KeyType;
|
||||||
|
typedef float MappedType;
|
||||||
|
typedef std::pair<const KeyType, MappedType> ValueType;
|
||||||
|
|
||||||
|
typedef boost::interprocess::allocator<ValueType, boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator;
|
||||||
|
|
||||||
|
typedef boost::interprocess::map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> CDBehaviorParameterMap;
|
||||||
|
|
||||||
|
CDBehaviorParameterMap *table = nullptr;
|
||||||
|
|
||||||
|
CppSQLite3Statement preparedStatementSingle;
|
||||||
|
CppSQLite3Statement preparedStatementMultiple;
|
||||||
|
|
||||||
|
//#define CACHE_ALL_BEHAVIORS
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
CDBehaviorParameterTable::CDBehaviorParameterTable(void) {
|
CDBehaviorParameterTable::CDBehaviorParameterTable(void) {
|
||||||
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);
|
|
||||||
|
|
||||||
GeneralUtils::hash_combine(hash, entry.behaviorID);
|
|
||||||
GeneralUtils::hash_combine(hash, entry.parameterID);
|
|
||||||
|
|
||||||
auto it = m_Entries.find(entry.behaviorID);
|
|
||||||
m_ParametersList.insert(entry.parameterID);
|
|
||||||
m_Entries.insert(std::make_pair(hash, entry));
|
|
||||||
|
|
||||||
tableData.nextRow();
|
|
||||||
}
|
|
||||||
tableData.finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
@ -32,33 +40,78 @@ std::string CDBehaviorParameterTable::GetName(void) const {
|
|||||||
return "BehaviorParameter";
|
return "BehaviorParameter";
|
||||||
}
|
}
|
||||||
|
|
||||||
CDBehaviorParameter CDBehaviorParameterTable::GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue)
|
float 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;
|
size_t hash = 0;
|
||||||
GeneralUtils::hash_combine(hash, behaviorID);
|
GeneralUtils::hash_combine(hash, behaviorID);
|
||||||
GeneralUtils::hash_combine(hash, name);
|
GeneralUtils::hash_combine(hash, name);
|
||||||
|
|
||||||
// Search for specific parameter
|
// Search for specific parameter
|
||||||
const auto& it = m_Entries.find(hash);
|
try {
|
||||||
return it != m_Entries.end() ? it->second : returnValue;
|
boost::interprocess::managed_shared_memory segment(boost::interprocess::open_only, "CDBehaviorParameterTable");
|
||||||
|
|
||||||
|
// If the segment manager is not null, then the segment exists
|
||||||
|
// Get the table from the segment
|
||||||
|
ShmemAllocator alloc_inst (segment.get_segment_manager());
|
||||||
|
|
||||||
|
boost::interprocess::offset_ptr<CDBehaviorParameterMap> m = segment.find<CDBehaviorParameterMap>("CDBehaviorParameter").first;
|
||||||
|
|
||||||
|
if (m == nullptr) {
|
||||||
|
Game::logger->Log("CDBehaviorParameterTable", "CDBehaviorParameter segment is nullptr!\n");
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = m->find(hash);
|
||||||
|
|
||||||
|
if (it != m->end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
catch (std::exception &e) {
|
||||||
|
Game::logger->Log("CDBehaviorParameterTable", "Failed to find entry for behaviorID: %d, parameterID: %s\n%e\n", behaviorID, name.c_str(), e.what());
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) {
|
void CDBehaviorParameterTable::CreateSharedMap()
|
||||||
size_t hash;
|
{
|
||||||
std::map<std::string, float> returnInfo;
|
boost::interprocess::shared_memory_object::remove("CDBehaviorParameterTable");
|
||||||
for (auto parameterCandidate : m_ParametersList) {
|
|
||||||
|
Game::logger->Log("CDBehaviorParameterTable", "Failed to open or create shared memory segment, creating...\n");
|
||||||
|
|
||||||
|
// If the segment manager is null, then the segment does not exist
|
||||||
|
// Create the segment
|
||||||
|
boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, "CDBehaviorParameterTable", 40 * 1000 * 1000);
|
||||||
|
|
||||||
|
ShmemAllocator alloc_inst (segment.get_segment_manager());
|
||||||
|
|
||||||
|
table = segment.construct<CDBehaviorParameterMap>("CDBehaviorParameter") //object name
|
||||||
|
(std::less<KeyType>() //first ctor parameter
|
||||||
|
,alloc_inst); //second ctor parameter
|
||||||
|
|
||||||
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
|
||||||
|
|
||||||
|
size_t hash = 0;
|
||||||
|
|
||||||
|
while (!tableData.eof()) {
|
||||||
hash = 0;
|
hash = 0;
|
||||||
|
|
||||||
|
int32_t behaviorID = tableData.getIntField(0, -1);
|
||||||
|
std::string parameterID = tableData.getStringField(1, "");
|
||||||
|
|
||||||
GeneralUtils::hash_combine(hash, behaviorID);
|
GeneralUtils::hash_combine(hash, behaviorID);
|
||||||
GeneralUtils::hash_combine(hash, parameterCandidate);
|
GeneralUtils::hash_combine(hash, parameterID);
|
||||||
auto infoCandidate = m_Entries.find(hash);
|
|
||||||
if (infoCandidate != m_Entries.end()) {
|
float value = tableData.getFloatField(2, -1.0f);
|
||||||
returnInfo.insert(std::make_pair(infoCandidate->second.parameterID, infoCandidate->second.value));
|
|
||||||
|
table->insert(ValueType(hash, value));
|
||||||
|
|
||||||
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return returnInfo;
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
@ -12,17 +12,17 @@
|
|||||||
|
|
||||||
//! BehaviorParameter Entry Struct
|
//! BehaviorParameter Entry Struct
|
||||||
struct CDBehaviorParameter {
|
struct CDBehaviorParameter {
|
||||||
unsigned int behaviorID; //!< The Behavior ID
|
int32_t behaviorID; //!< The Behavior ID
|
||||||
std::string parameterID; //!< The Parameter ID
|
int32_t parameterID; //!< The Parameter ID
|
||||||
float value; //!< The value of the behavior template
|
float value; //!< The value of the behavior template
|
||||||
};
|
};
|
||||||
|
|
||||||
//! BehaviorParameter table
|
//! BehaviorParameter table
|
||||||
class CDBehaviorParameterTable : public CDTable {
|
class CDBehaviorParameterTable : public CDTable {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<size_t, CDBehaviorParameter> m_Entries;
|
std::unordered_map<size_t, float> m_Entries;
|
||||||
std::unordered_set<std::string> m_ParametersList;
|
|
||||||
public:
|
public:
|
||||||
|
static void CreateSharedMap();
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
CDBehaviorParameterTable(void);
|
CDBehaviorParameterTable(void);
|
||||||
@ -36,7 +36,5 @@ public:
|
|||||||
*/
|
*/
|
||||||
std::string GetName(void) const override;
|
std::string GetName(void) const override;
|
||||||
|
|
||||||
CDBehaviorParameter GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue = 0);
|
float GetEntry(const uint32_t behaviorID, const std::string& name, const float defaultValue = 0);
|
||||||
|
|
||||||
std::map<std::string, float> GetParametersByBehaviorID(uint32_t behaviorID);
|
|
||||||
};
|
};
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dLogger.h"
|
#include "dLogger.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
void AndBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
void AndBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch)
|
||||||
{
|
{
|
||||||
for (auto* behavior : this->m_behaviors)
|
for (auto* behavior : this->m_behaviors)
|
||||||
@ -27,15 +29,19 @@ void AndBehavior::UnCast(BehaviorContext* context, const BehaviorBranchContext b
|
|||||||
|
|
||||||
void AndBehavior::Load()
|
void AndBehavior::Load()
|
||||||
{
|
{
|
||||||
const auto parameters = GetParameterNames();
|
std::string ss = "behavior ";
|
||||||
|
|
||||||
for (const auto& parameter : parameters)
|
int i = 1;
|
||||||
{
|
|
||||||
if (parameter.first.rfind("behavior", 0) == 0)
|
|
||||||
{
|
|
||||||
auto* action = GetAction(parameter.second);
|
|
||||||
|
|
||||||
this->m_behaviors.push_back(action);
|
while (true) {
|
||||||
|
std::string s = ss + std::to_string(i);
|
||||||
|
|
||||||
|
if (GetInt(s, 0) == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_behaviors.push_back(GetAction(s));
|
||||||
|
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,7 +453,7 @@ float Behavior::GetFloat(const std::string& name, const float defaultValue) cons
|
|||||||
{
|
{
|
||||||
// Get the behavior parameter entry and return its value.
|
// Get the behavior parameter entry and return its value.
|
||||||
if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter");
|
if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter");
|
||||||
return BehaviorParameterTable->GetEntry(this->m_behaviorId, name, defaultValue).value;
|
return BehaviorParameterTable->GetEntry(this->m_behaviorId, name, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -485,10 +485,10 @@ std::map<std::string, float> Behavior::GetParameterNames() const
|
|||||||
{
|
{
|
||||||
std::map<std::string, float> templatesInDatabase;
|
std::map<std::string, float> templatesInDatabase;
|
||||||
// Find behavior template by its behavior id.
|
// Find behavior template by its behavior id.
|
||||||
if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter");
|
/*if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance()->GetTable<CDBehaviorParameterTable>("BehaviorParameter");
|
||||||
if (BehaviorParameterTable) {
|
if (BehaviorParameterTable) {
|
||||||
templatesInDatabase = BehaviorParameterTable->GetParametersByBehaviorID(this->m_behaviorId);
|
templatesInDatabase = BehaviorParameterTable->GetParametersByBehaviorID(this->m_behaviorId);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
return templatesInDatabase;
|
return templatesInDatabase;
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,19 @@ void ChainBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitSt
|
|||||||
|
|
||||||
void ChainBehavior::Load()
|
void ChainBehavior::Load()
|
||||||
{
|
{
|
||||||
const auto parameters = GetParameterNames();
|
std::string ss = "behavior ";
|
||||||
|
|
||||||
for (const auto& parameter : parameters)
|
int i = 1;
|
||||||
{
|
|
||||||
if (parameter.first.rfind("behavior", 0) == 0)
|
|
||||||
{
|
|
||||||
auto* action = GetAction(parameter.second);
|
|
||||||
|
|
||||||
this->m_behaviors.push_back(action);
|
while (true) {
|
||||||
|
std::string s = ss + std::to_string(i);
|
||||||
|
|
||||||
|
if (GetInt(s, 0) == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_behaviors.push_back(GetAction(s));
|
||||||
|
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,15 +17,19 @@ void NpcCombatSkillBehavior::Load()
|
|||||||
{
|
{
|
||||||
this->m_npcSkillTime = GetFloat("npc skill time");
|
this->m_npcSkillTime = GetFloat("npc skill time");
|
||||||
|
|
||||||
const auto parameters = GetParameterNames();
|
std::string ss = "behavior ";
|
||||||
|
|
||||||
for (const auto& parameter : parameters)
|
int i = 1;
|
||||||
{
|
|
||||||
if (parameter.first.rfind("behavior", 0) == 0)
|
|
||||||
{
|
|
||||||
auto* action = GetAction(parameter.second);
|
|
||||||
|
|
||||||
this->m_behaviors.push_back(action);
|
while (true) {
|
||||||
|
std::string s = ss + std::to_string(i);
|
||||||
|
|
||||||
|
if (GetInt(s, 0) == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_behaviors.push_back(GetAction(s));
|
||||||
|
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,6 +218,8 @@ int main(int argc, char** argv) {
|
|||||||
ObjectIDManager::Instance()->Initialize(Game::logger);
|
ObjectIDManager::Instance()->Initialize(Game::logger);
|
||||||
Game::im = new InstanceManager(Game::logger, Game::server->GetIP());
|
Game::im = new InstanceManager(Game::logger, Game::server->GetIP());
|
||||||
|
|
||||||
|
CDBehaviorParameterTable::CreateSharedMap();
|
||||||
|
|
||||||
//Depending on the config, start up servers:
|
//Depending on the config, start up servers:
|
||||||
if (config.GetValue("prestart_servers") != "" && config.GetValue("prestart_servers") == "1") {
|
if (config.GetValue("prestart_servers") != "" && config.GetValue("prestart_servers") == "1") {
|
||||||
StartChatServer();
|
StartChatServer();
|
||||||
|
Loading…
Reference in New Issue
Block a user