diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f8981eef..f7f17bb00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -322,6 +322,15 @@ link_directories(${PROJECT_BINARY_DIR}) # Load all of our third party directories add_subdirectory(thirdparty) +# Include Boost +find_package(Boost COMPONENTS interprocess) + +if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) + + target_link_libraries(dGame ${Boost_LIBRARIES}) +endif() + # Glob together all headers that need to be precompiled file( GLOB HEADERS_DDATABASE diff --git a/dDatabase/CDAbstractProvider.h b/dDatabase/CDAbstractProvider.h new file mode 100644 index 000000000..3f263bb55 --- /dev/null +++ b/dDatabase/CDAbstractProvider.h @@ -0,0 +1,22 @@ +#pragma once + +#include "GeneralUtils.h" + +#include "Game.h" +#include "dLogger.h" +#include "dServer.h" + +#include "CDTable.h" + +template < + typename KeyType, + typename MappedType +> +class CDAbstractProvider +{ +public: + virtual void LoadClient() = 0; + virtual void LoadHost() = 0; + + virtual const MappedType& GetEntry(const KeyType& key, const MappedType& defaultValue) = 0; +}; diff --git a/dDatabase/CDAbstractSharedMemoryMap.h b/dDatabase/CDAbstractSharedMemoryMap.h new file mode 100644 index 000000000..f5642de54 --- /dev/null +++ b/dDatabase/CDAbstractSharedMemoryMap.h @@ -0,0 +1,124 @@ +#pragma once + +#include "GeneralUtils.h" + +#include "Game.h" +#include "dLogger.h" +#include "dServer.h" + +#include "CDTable.h" + +#include "CDAbstractProvider.h" + +#include +#include +#include +#include +#include +#include +#include + +template < + typename KeyType, + typename MappedType +> +class CDAbstractSharedMemoryMap : public CDAbstractProvider +{ + typedef std::pair ValueType; + + typedef boost::interprocess::allocator ShmemAllocator; + + typedef boost::interprocess::map, ShmemAllocator> Map; + +public: + std::map m_CacheMap; + + std::string m_Name; + + size_t m_Size; + + bool m_Host; + Map* m_HostEntries; + + boost::interprocess::managed_shared_memory m_ClientSegment; + ShmemAllocator* m_ClientAllocInst; + boost::interprocess::offset_ptr m_ClientEntires; + + CDAbstractSharedMemoryMap(std::string name, size_t size) + { + m_Name = name; + m_Size = size; + m_Host = false; + m_HostEntries = nullptr; + m_ClientAllocInst = nullptr; + m_ClientEntires = nullptr; + + LoadClient(); + } + + const MappedType& GetEntry(const KeyType& key, const MappedType& defaultValue) override { + const auto& cacheIt = m_CacheMap.find(key); + if (cacheIt != m_CacheMap.end()) { + return cacheIt->second; + } + + const auto& it = m_ClientEntires->find(key); + if (it == m_ClientEntires->end()) { + return defaultValue; + } + + return it->second; + } + + const void SetEntry(const KeyType& key, const MappedType& value) { + if (m_Host) { + // If we are already hosting, we cannot add to the map, throw an error + throw std::runtime_error("Can not add to a map that is already being hosted"); + } + + m_CacheMap.emplace(key, value); + } + + void LoadClient() override { + try { + m_ClientSegment = boost::interprocess::managed_shared_memory(boost::interprocess::open_read_only, m_Name.c_str()); + + m_ClientAllocInst = new ShmemAllocator(m_ClientSegment.get_segment_manager()); + + m_ClientEntires = m_ClientSegment.find(m_Name.c_str()).first; + + if (m_ClientEntires == nullptr) { + throw std::runtime_error("Could not find shared memory segment " + m_Name); + } + + } catch (std::exception &e) { + // Not open + } + } + + void LoadHost() override { + try { + boost::interprocess::shared_memory_object::remove(m_Name.c_str()); + + boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, m_Name.c_str(), m_Size); + + ShmemAllocator alloc(segment.get_segment_manager()); + + m_HostEntries = segment.construct(m_Name.c_str()) (std::less(), alloc); + + // Copy cache + for (const auto& pair : m_CacheMap) { + m_HostEntries->insert(std::make_pair(pair.first, pair.second)); + } + + m_Host = true; + + LoadClient(); + } catch (std::exception &e) { + // Make sure the smemory is removed + boost::interprocess::shared_memory_object::remove(m_Name.c_str()); + + throw e; + } + } +}; diff --git a/dDatabase/CDAbstractSharedMemoryProvider.h b/dDatabase/CDAbstractSharedMemoryProvider.h new file mode 100644 index 000000000..bce08bae5 --- /dev/null +++ b/dDatabase/CDAbstractSharedMemoryProvider.h @@ -0,0 +1,150 @@ +#pragma once + +#include "CDAbstractProvider.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +template < + typename KeyType, + typename MappedType +> +class CDAbstractSharedMemoryProvider : public CDAbstractProvider +{ + typedef std::pair ValueType; + + typedef boost::interprocess::allocator ShmemAllocator; + + typedef boost::interprocess::map, ShmemAllocator> Map; + +public: + std::string m_Name; + std::string m_MapName; + std::function m_ParseEntry; + std::function m_CalculateSize; + + bool m_Cache; + + std::unordered_map m_CacheMap; + + bool m_Host; + Map* m_HostEntries; + + boost::interprocess::managed_shared_memory m_ClientSegment; + ShmemAllocator* m_ClientAllocInst; + boost::interprocess::offset_ptr m_ClientEntires; + + CDAbstractSharedMemoryProvider(std::string name, std::function parseEntry, std::function calculateSize, bool cache) + { + m_Name = name; + m_MapName = name + "Map"; + m_ParseEntry = parseEntry; + m_CalculateSize = calculateSize; + m_Cache = cache; + m_Host = false; + m_HostEntries = nullptr; + + LoadClient(); + } + + const MappedType& GetEntry(const KeyType& key, const MappedType& defaultValue) override { + if (m_Host) { + auto it = m_HostEntries->find(key); + if (it == m_HostEntries->end()) + { + return defaultValue; + } + return it->second; + } + + if (m_Cache) { + auto it = m_CacheMap.find(key); + if (it != m_CacheMap.end()) { + return it->second; + } + } + + const auto& it = m_ClientEntires->find(key); + if (it == m_ClientEntires->end()) + { + if (m_Cache) { + m_CacheMap.emplace(key, defaultValue); + } + + return defaultValue; + } + + if (m_Cache) { + m_CacheMap.emplace(key, it->second); + } + + return it->second; + } + + void LoadClient() override { + try { + m_ClientSegment = boost::interprocess::managed_shared_memory(boost::interprocess::open_read_only, m_MapName.c_str()); + + m_ClientAllocInst = new ShmemAllocator(m_ClientSegment.get_segment_manager()); + + m_ClientEntires = m_ClientSegment.find(m_Name.c_str()).first; + + if (m_ClientEntires == nullptr) { + throw std::runtime_error("Could not find shared memory segment " + m_Name); + } + + } catch (boost::interprocess::interprocess_exception& e) { + // Not open + } + } + + void LoadHost() override { + try { + boost::interprocess::shared_memory_object::remove(m_MapName.c_str()); + + auto sizeQuery = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM " + m_Name); + + if (sizeQuery.eof()) { + throw std::runtime_error("Could not get size of table " + m_Name); + return; + } + + int32_t size = sizeQuery.getIntField(0); + + size = m_CalculateSize(size); + + boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, m_MapName.c_str(), size); + + ShmemAllocator alloc_inst (segment.get_segment_manager()); + + m_HostEntries = segment.construct(m_Name.c_str()) (std::less(), alloc_inst); + + auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM " + m_Name); + + while (!tableData.eof()) { + ValueType entry = m_ParseEntry(tableData); + + m_HostEntries->insert(entry); + + tableData.nextRow(); + } + + tableData.finalize(); + + m_Host = true; + + LoadClient(); + } catch (std::exception &e) { + // Make sure the smemory is removed + boost::interprocess::shared_memory_object::remove(m_MapName.c_str()); + + throw e; + } + } +}; diff --git a/dDatabase/CDAbstractSqliteProvider.h b/dDatabase/CDAbstractSqliteProvider.h new file mode 100644 index 000000000..b330ca5fb --- /dev/null +++ b/dDatabase/CDAbstractSqliteProvider.h @@ -0,0 +1,74 @@ +#pragma once + +#include "GeneralUtils.h" + +#include "Game.h" +#include "dLogger.h" +#include "dServer.h" + +#include "CDTable.h" + +#include "CDAbstractProvider.h" + +template < + typename KeyType, + typename MappedType +> +class CDAbstractSqliteProvider : public CDAbstractProvider +{ + typedef std::pair ValueType; + +public: + std::string m_Name; + std::function m_ParseEntry; + + std::unordered_map m_Entries; + + CDAbstractSqliteProvider(std::string name, std::function parseEntry, bool cache) + { + m_Name = name; + m_ParseEntry = parseEntry; + + LoadClient(); + } + + void LoadClient() override { + // First, get the size of the table + uint32_t size = 0; + auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM " + m_Name); + while (!tableSize.eof()) { + size = tableSize.getIntField(0, 0); + + tableSize.nextRow(); + } + + tableSize.finalize(); + + // Reserve the size + m_Entries.reserve(size); + + // Now get the data + auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM " + m_Name); + while (!tableData.eof()) { + auto entry = m_ParseEntry(tableData); + + m_Entries.insert(entry); + + tableData.nextRow(); + } + + tableData.finalize(); + } + + void LoadHost() override { + return; + } + + const MappedType& GetEntry(const KeyType& key, const MappedType& defaultValue) override { + auto it = m_Entries.find(key); + if (it != m_Entries.end()) { + return it->second; + } + return defaultValue; + } +}; diff --git a/dDatabase/CDClientManager.cpp b/dDatabase/CDClientManager.cpp index 9df6ff311..264d03e4c 100644 --- a/dDatabase/CDClientManager.cpp +++ b/dDatabase/CDClientManager.cpp @@ -78,3 +78,11 @@ CDClientManager::CDClientManager() { CDFeatureGatingTable::Instance(); CDRailActivatorComponentTable::Instance(); } + +void CDClientManager::LoadHost() { + for (auto itr = this->tables.begin(); itr != this->tables.end(); ++itr) { + itr->second->LoadHost(); + } + + CDTable::InitalizeHost(); +} diff --git a/dDatabase/CDProvider.h b/dDatabase/CDProvider.h new file mode 100644 index 000000000..e58b38692 --- /dev/null +++ b/dDatabase/CDProvider.h @@ -0,0 +1,41 @@ +#pragma once + +#include "CDAbstractProvider.h" + +/** + * Shared memory provider with CDAbstractSharedMemoryProvider + * + * Depends on the boost::interprocess library — header only + * + * Requires that CD_PROVIDER_MEMORY is defined and CD_PROVIDER_SQLITE is not defined + */ +#if defined(CD_PROVIDER_MEMORY) && !defined(CD_PROVIDER_SQLITE) + +#include "CDAbstractSharedMemoryProvider.h" + +#define CD_PROVIDER(provider, key, value) CDAbstractSharedMemoryProvider* provider; typedef key CD_KEY; typedef value CD_VALUE +#define NEW_CD_PROVIDER(provider, name, parser, size_calculator, cache) provider = new CDAbstractSharedMemoryProvider(name, parser, size_calculator, cache) + +template +using CDProvider = CDAbstractSharedMemoryProvider; + +#endif + +/** + * SQLite provider with CDAbstractSqliteProvider + * + * No extra dependencies + * + * Requires that CD_PROVIDER_SQLITE or CD_PROVIDER_MEMORY is not defined — the default option + */ +#if defined(CD_PROVIDER_SQLITE) || !defined(CD_PROVIDER_MEMORY) + +#include "CDAbstractSqliteProvider.h" + +#define CD_PROVIDER(provider, key, value) CDAbstractSqliteProvider* provider; typedef key CD_KEY; typedef value CD_VALUE +#define NEW_CD_PROVIDER(provider, name, parser, size_calculator, cache) provider = new CDAbstractSqliteProvider(name, parser, cache) + +template +using CDProvider = CDAbstractSqliteProvider; + +#endif diff --git a/dDatabase/Tables/CDBehaviorParameterTable.cpp b/dDatabase/Tables/CDBehaviorParameterTable.cpp index 0713e740d..a82e3612d 100644 --- a/dDatabase/Tables/CDBehaviorParameterTable.cpp +++ b/dDatabase/Tables/CDBehaviorParameterTable.cpp @@ -21,10 +21,7 @@ CDBehaviorParameterTable::CDBehaviorParameterTable(void) { entry.value = tableData.getFloatField("value", -1.0f); m_Entries.insert(std::make_pair(hash, entry)); - - tableData.nextRow(); } - tableData.finalize(); } float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) { diff --git a/dDatabase/Tables/CDBehaviorTemplateTable.h b/dDatabase/Tables/CDBehaviorTemplateTable.h index f9ac9a09d..0a48c835e 100644 --- a/dDatabase/Tables/CDBehaviorTemplateTable.h +++ b/dDatabase/Tables/CDBehaviorTemplateTable.h @@ -6,10 +6,10 @@ #include struct CDBehaviorTemplate { - unsigned int behaviorID; //!< The Behavior ID - unsigned int templateID; //!< The Template ID (LOT) - unsigned int effectID; //!< The Effect ID attached - std::unordered_set::iterator effectHandle; //!< The effect handle + unsigned int behaviorID; //!< The Behavior ID + unsigned int templateID; //!< The Template ID (LOT) + unsigned int effectID; //!< The Effect ID attached + size_t effectHandle; //!< The effect handle }; diff --git a/dDatabase/Tables/CDComponentsRegistryTable.cpp b/dDatabase/Tables/CDComponentsRegistryTable.cpp index 32012f6ce..112afd2ab 100644 --- a/dDatabase/Tables/CDComponentsRegistryTable.cpp +++ b/dDatabase/Tables/CDComponentsRegistryTable.cpp @@ -1,3 +1,4 @@ + #include "CDComponentsRegistryTable.h" #include "eReplicaComponentType.h" diff --git a/dDatabase/Tables/CDTable.cpp b/dDatabase/Tables/CDTable.cpp new file mode 100644 index 000000000..f33b2c9a9 --- /dev/null +++ b/dDatabase/Tables/CDTable.cpp @@ -0,0 +1,68 @@ +#include "CDTable.h" + +#if defined(CD_PROVIDER_MEMORY) + +#include "CDAbstractSharedMemoryMap.h" + +typedef boost::interprocess::allocator CharAllocator; +typedef boost::interprocess::basic_string, CharAllocator> my_string; + +CDAbstractSharedMemoryMap* CDStringMap; + +void CDTable::InitalizeHost() +{ + CDStringMap->LoadHost(); +} + +void CDTable::Initalize() +{ + CDStringMap = new CDAbstractSharedMemoryMap("CDStringMap", 10 * 1000 * 1000); +} + +std::string CDTable::GetString(size_t handle) +{ + std::string str = std::string(CDStringMap->GetEntry(handle, "").c_str()); + + return str; +} + +size_t CDTable::SetString(std::string value) +{ + size_t hash = 0; + + GeneralUtils::hash_combine(hash, value); + + CDStringMap->SetEntry(hash, boost::interprocess::string(value.c_str())); + + return hash; +} + +#else + +std::unordered_map CDStringMap; + +void CDTable::InitalizeHost() +{ +} + +void CDTable::Initalize() +{ +} + +std::string CDTable::GetString(size_t handle) +{ + return CDStringMap[handle]; +} + +size_t CDTable::SetString(std::string value) +{ + size_t hash = 0; + + GeneralUtils::hash_combine(hash, value); + + CDStringMap[hash] = value; + + return hash; +} + +#endif \ No newline at end of file diff --git a/dDatabase/Tables/CDTable.h b/dDatabase/Tables/CDTable.h index e4c11fb9a..5e10f8b81 100644 --- a/dDatabase/Tables/CDTable.h +++ b/dDatabase/Tables/CDTable.h @@ -25,8 +25,50 @@ #pragma warning (disable : 4244) //Disable double to float conversion warnings #pragma warning (disable : 4715) //Disable "not all control paths return a value" +#if defined(__unix) || defined(__APPLE__) +//For Linux: +typedef __int64_t __int64; +#endif + +/*! + \file CDTable.hpp + \brief A virtual class for CDClient Tables + */ + + //! The base class for all CD tables template class CDTable : public Singleton { +public: + + //! Returns the table's name + /*! + \return The table name + */ + virtual std::string GetName() const = 0; + + //! Loads the table into shared memory + virtual void LoadHost() {}; + + //! Initalizes the table services + static void Initalize(); + + //! Initalizes the table services as host + static void InitalizeHost(); + + //! Get a string from a handle + /*! + \param handle The handle to get the string from + \return The string + */ + static std::string GetString(size_t handle); + + //! Set a string + /*! + \param value The string to set + \return The handle to the string + */ + static size_t SetString(std::string value); + protected: virtual ~CDTable() = default; }; diff --git a/dDatabase/Tables/CMakeLists.txt b/dDatabase/Tables/CMakeLists.txt index b6a02b02d..998fc1afd 100644 --- a/dDatabase/Tables/CMakeLists.txt +++ b/dDatabase/Tables/CMakeLists.txt @@ -1,4 +1,4 @@ -set(DDATABASE_TABLES_SOURCES "CDActivitiesTable.cpp" +set(DDATABASE_TABLES_SOURCES "CDTable.cpp" "CDActivitiesTable.cpp" "CDActivityRewardsTable.cpp" "CDAnimationsTable.cpp" "CDBehaviorParameterTable.cpp" diff --git a/dGame/dBehaviors/AndBehavior.cpp b/dGame/dBehaviors/AndBehavior.cpp index 67c886791..62e140d4b 100644 --- a/dGame/dBehaviors/AndBehavior.cpp +++ b/dGame/dBehaviors/AndBehavior.cpp @@ -3,8 +3,12 @@ #include "Game.h" #include "dLogger.h" -void AndBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) { - for (auto* behavior : this->m_behaviors) { +#include + +void AndBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) +{ + for (auto* behavior : this->m_behaviors) + { behavior->Handle(context, bitStream, branch); } } @@ -21,14 +25,21 @@ void AndBehavior::UnCast(BehaviorContext* context, const BehaviorBranchContext b } } -void AndBehavior::Load() { - const auto parameters = GetParameterNames(); +void AndBehavior::Load() +{ + std::string ss = "behavior "; + + int i = 1; - for (const auto& parameter : parameters) { - if (parameter.first.rfind("behavior", 0) == 0) { - auto* action = GetAction(parameter.second); + while (true) { + std::string s = ss + std::to_string(i); - this->m_behaviors.push_back(action); + if (GetInt(s, 0) == 0) { + break; } + + m_behaviors.push_back(GetAction(s)); + + ++i; } } diff --git a/dGame/dBehaviors/Behavior.cpp b/dGame/dBehaviors/Behavior.cpp index 6fe84a9f1..5beb063f7 100644 --- a/dGame/dBehaviors/Behavior.cpp +++ b/dGame/dBehaviors/Behavior.cpp @@ -439,7 +439,7 @@ Behavior::Behavior(const uint32_t behaviorId) { this->m_effectId = templateInDatabase.effectID; - this->m_effectHandle = *templateInDatabase.effectHandle != "" ? new std::string(*templateInDatabase.effectHandle) : nullptr; + this->m_effectHandle = new std::string(CDTable::GetString(templateInDatabase.effectHandle)); } @@ -471,14 +471,8 @@ Behavior* Behavior::GetAction(float value) const { } std::map Behavior::GetParameterNames() const { - std::map templatesInDatabase; - // Find behavior template by its behavior id. if (!BehaviorParameterTable) BehaviorParameterTable = CDClientManager::Instance().GetTable(); - if (BehaviorParameterTable) { - templatesInDatabase = BehaviorParameterTable->GetParametersByBehaviorID(this->m_behaviorId); - } - - return templatesInDatabase; + return BehaviorParameterTable->GetParametersByBehaviorID(this->m_behaviorId); } void Behavior::Load() { diff --git a/dGame/dBehaviors/ChainBehavior.cpp b/dGame/dBehaviors/ChainBehavior.cpp index ec0f8969e..e56f5de00 100644 --- a/dGame/dBehaviors/ChainBehavior.cpp +++ b/dGame/dBehaviors/ChainBehavior.cpp @@ -26,14 +26,21 @@ void ChainBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitSt this->m_behaviors.at(0)->Calculate(context, bitStream, branch); } -void ChainBehavior::Load() { - const auto parameters = GetParameterNames(); +void ChainBehavior::Load() +{ + std::string ss = "behavior "; - for (const auto& parameter : parameters) { - if (parameter.first.rfind("behavior", 0) == 0) { - auto* action = GetAction(parameter.second); + int i = 1; - 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; } } diff --git a/dGame/dBehaviors/NpcCombatSkillBehavior.cpp b/dGame/dBehaviors/NpcCombatSkillBehavior.cpp index 5a8d03cf4..fbad847c1 100644 --- a/dGame/dBehaviors/NpcCombatSkillBehavior.cpp +++ b/dGame/dBehaviors/NpcCombatSkillBehavior.cpp @@ -13,14 +13,20 @@ void NpcCombatSkillBehavior::Calculate(BehaviorContext* context, RakNet::BitStre void NpcCombatSkillBehavior::Load() { this->m_npcSkillTime = GetFloat("npc skill time"); + + std::string ss = "behavior "; - const auto parameters = GetParameterNames(); + int i = 1; - for (const auto& parameter : parameters) { - if (parameter.first.rfind("behavior", 0) == 0) { - auto* action = GetAction(parameter.second); + while (true) { + std::string s = ss + std::to_string(i); - this->m_behaviors.push_back(action); + if (GetInt(s, 0) == 0) { + break; } + + m_behaviors.push_back(GetAction(s)); + + ++i; } } diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 03e3cc896..975d7be0a 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -1761,6 +1761,41 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit return; } +#ifdef __linux__ + if (chatCommand == "statm" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) + { + // Print and format the output of /proc/self/statm + std::ifstream statm("/proc/self/statm"); + + if (!statm.is_open()) + { + ChatPackets::SendSystemMessage(sysAddr, u"Failed to open /proc/self/statm"); + return; + } + + // Scan for the different fields + uint64_t size, resident, share, text, lib, data, dirty; + statm >> size >> resident >> share >> text >> lib >> data >> dirty; + + // Get the page size + size_t pageSize = sysconf(_SC_PAGESIZE); + + // Print the output + ChatPackets::SendSystemMessage( + sysAddr, + u"Size: " + GeneralUtils::to_u16string((float) ((double) size * pageSize / 1.024e6)) + + u"MB\nResident: " + GeneralUtils::to_u16string((float) ((double) resident * pageSize / 1.024e6)) + + u"MB\nShared: " + GeneralUtils::to_u16string((float) ((double) share * pageSize / 1.024e6)) + + u"MB\nText: " + GeneralUtils::to_u16string((float) ((double) text * pageSize / 1.024e6)) + + u"MB\nLibrary: " + GeneralUtils::to_u16string((float) ((double) lib * pageSize / 1.024e6)) + + u"MB\nData: " + GeneralUtils::to_u16string((float) ((double) data * pageSize / 1.024e6)) + + u"MB\nDirty: " + GeneralUtils::to_u16string((float) ((double) dirty * pageSize / 1.024e6)) + + u"MB" + ); + } +#endif + + if (chatCommand == "rollloot" && entity->GetGMLevel() >= eGameMasterLevel::OPERATOR && args.size() >= 3) { if (chatCommand == "reloadconfig" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { Game::config->ReloadConfig(); VanityUtilities::SpawnVanity(); diff --git a/dMasterServer/InstanceManager.cpp b/dMasterServer/InstanceManager.cpp index 50f55b72b..2c31d2fb9 100644 --- a/dMasterServer/InstanceManager.cpp +++ b/dMasterServer/InstanceManager.cpp @@ -69,13 +69,14 @@ Instance* InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LW } #endif - cmd.append(std::to_string(mapID)); - cmd.append(" -port "); - cmd.append(std::to_string(port)); - cmd.append(" -instance "); - cmd.append(std::to_string(m_LastInstanceID)); - cmd.append(" -maxclients "); - cmd.append(std::to_string(maxPlayers)); + cmd.append(" -zone "); + cmd.append(std::to_string(mapID)); + cmd.append(" -port "); + cmd.append(std::to_string(port)); + cmd.append(" -instance "); + cmd.append(std::to_string(m_LastInstanceID)); + cmd.append(" -maxclients "); + cmd.append(std::to_string(maxPlayers)); cmd.append(" -clone "); cmd.append(std::to_string(cloneID)); diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index ce237eacf..f4bcb78bd 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -331,6 +331,8 @@ int main(int argc, char** argv) { ObjectIDManager::Instance()->Initialize(Game::logger); Game::im = new InstanceManager(Game::logger, Game::server->GetIP()); + CDClientManager::Instance()->LoadHost(); + //Depending on the config, start up servers: if (Game::config->GetValue("prestart_servers") != "" && Game::config->GetValue("prestart_servers") == "1") { StartChatServer();