diff --git a/dMasterServer/InstanceManager.cpp b/dMasterServer/InstanceManager.cpp index be4283e7..7dba4802 100644 --- a/dMasterServer/InstanceManager.cpp +++ b/dMasterServer/InstanceManager.cpp @@ -14,24 +14,21 @@ #include "Start.h" -InstanceManager::InstanceManager(Logger* logger, const std::string& externalIP) { - mLogger = logger; - mExternalIP = externalIP; +using std::make_unique; + +namespace { + const InstancePtr g_Empty{ nullptr }; +} + +InstanceManager::InstanceManager(const std::string& externalIP) : mExternalIP{ externalIP } { m_LastPort = GeneralUtils::TryParse(Game::config->GetValue("world_port_start")).value_or(m_LastPort); m_LastInstanceID = LWOINSTANCEID_INVALID; } -InstanceManager::~InstanceManager() { - for (Instance* i : m_Instances) { - delete i; - i = nullptr; - } -} - -Instance* InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneID) { +const InstancePtr& InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneID) { LOG("Searching for an instance for mapID %i/%i", mapID, cloneID); - Instance* instance = FindInstance(mapID, isFriendTransfer, cloneID); + auto& instance = FindInstance(mapID, isFriendTransfer, cloneID); if (instance) return instance; // If we are shutting down, return a nullptr so a new instance is not created. @@ -40,7 +37,7 @@ Instance* InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LW mapID, m_LastInstanceID + 1, cloneID); - return nullptr; + return g_Empty; } //TODO: Update this so that the IP is read from a configuration file instead @@ -56,23 +53,23 @@ Instance* InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LW } uint32_t port = GetFreePort(); - instance = new Instance(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, softCap, maxPlayers); + auto newInstance = make_unique(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, softCap, maxPlayers); //Start the actual process: StartWorldServer(mapID, port, m_LastInstanceID, maxPlayers, cloneID); - m_Instances.push_back(instance); + m_Instances.push_back(std::move(newInstance)); - if (instance) { + if (m_Instances.back()) { LOG("Created new instance: %i/%i/%i with min/max %i/%i", mapID, m_LastInstanceID, cloneID, softCap, maxPlayers); - return instance; + return m_Instances.back(); } else LOG("Failed to create a new instance!"); - return nullptr; + return g_Empty; } bool InstanceManager::IsPortInUse(uint32_t port) { - for (Instance* i : m_Instances) { + for (const auto& i : m_Instances) { if (i && i->GetPort() == port) { return true; } @@ -84,7 +81,7 @@ bool InstanceManager::IsPortInUse(uint32_t port) { uint32_t InstanceManager::GetFreePort() { uint32_t port = m_LastPort; std::vector usedPorts; - for (Instance* i : m_Instances) { + for (const auto& i : m_Instances) { usedPorts.push_back(i->GetPort()); } @@ -101,7 +98,7 @@ uint32_t InstanceManager::GetFreePort() { } void InstanceManager::AddPlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINSTANCEID instanceID) { - Instance* inst = FindInstance(mapID, instanceID); + const auto& inst = FindInstance(mapID, instanceID); if (inst) { Player player; player.addr = systemAddr; @@ -111,7 +108,7 @@ void InstanceManager::AddPlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINS } void InstanceManager::RemovePlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINSTANCEID instanceID) { - Instance* inst = FindInstance(mapID, instanceID); + const auto& inst = FindInstance(mapID, instanceID); if (inst) { Player player; player.addr = systemAddr; @@ -120,25 +117,23 @@ void InstanceManager::RemovePlayer(SystemAddress systemAddr, LWOMAPID mapID, LWO } } -std::vector InstanceManager::GetInstances() const { +const std::vector& InstanceManager::GetInstances() const { return m_Instances; } -void InstanceManager::AddInstance(Instance* instance) { +void InstanceManager::AddInstance(InstancePtr& instance) { if (instance == nullptr) return; - m_Instances.push_back(instance); + m_Instances.push_back(std::move(instance)); } -void InstanceManager::RemoveInstance(Instance* instance) { +void InstanceManager::RemoveInstance(const InstancePtr& instance) { for (uint32_t i = 0; i < m_Instances.size(); ++i) { if (m_Instances[i] == instance) { instance->SetShutdownComplete(true); if (!Game::ShouldShutdown()) RedirectPendingRequests(instance); - delete m_Instances[i]; - m_Instances.erase(m_Instances.begin() + i); break; @@ -146,7 +141,7 @@ void InstanceManager::RemoveInstance(Instance* instance) { } } -void InstanceManager::ReadyInstance(Instance* instance) { +void InstanceManager::ReadyInstance(const InstancePtr& instance) { instance->SetIsReady(true); auto& pending = instance->GetPendingRequests(); @@ -172,7 +167,7 @@ void InstanceManager::ReadyInstance(Instance* instance) { pending.clear(); } -void InstanceManager::RequestAffirmation(Instance* instance, const PendingInstanceRequest& request) { +void InstanceManager::RequestAffirmation(const InstancePtr& instance, const PendingInstanceRequest& request) { instance->GetPendingAffirmations().push_back(request); CBITSTREAM; @@ -189,7 +184,7 @@ void InstanceManager::RequestAffirmation(Instance* instance, const PendingInstan ); } -void InstanceManager::AffirmTransfer(Instance* instance, const uint64_t transferID) { +void InstanceManager::AffirmTransfer(const InstancePtr& instance, const uint64_t transferID) { auto& pending = instance->GetPendingAffirmations(); for (auto i = 0u; i < pending.size(); ++i) { @@ -217,11 +212,11 @@ void InstanceManager::AffirmTransfer(Instance* instance, const uint64_t transfer } } -void InstanceManager::RedirectPendingRequests(Instance* instance) { +void InstanceManager::RedirectPendingRequests(const InstancePtr& instance) { const auto& zoneId = instance->GetZoneID(); for (const auto& request : instance->GetPendingAffirmations()) { - auto* in = Game::im->GetInstance(zoneId.GetMapID(), false, zoneId.GetCloneID()); + const auto& in = Game::im->GetInstance(zoneId.GetMapID(), false, zoneId.GetCloneID()); if (in && !in->GetIsReady()) // Instance not ready, make a pending request { @@ -234,57 +229,48 @@ void InstanceManager::RedirectPendingRequests(Instance* instance) { } } -Instance* InstanceManager::GetInstanceBySysAddr(SystemAddress& sysAddr) { - for (uint32_t i = 0; i < m_Instances.size(); ++i) { - if (m_Instances[i] && m_Instances[i]->GetSysAddr() == sysAddr) { - return m_Instances[i]; +const InstancePtr& InstanceManager::GetInstanceBySysAddr(SystemAddress& sysAddr) { + for (const auto& instance : m_Instances) { + if (instance && instance->GetSysAddr() == sysAddr) { + return instance; } } - return nullptr; + return g_Empty; } -bool InstanceManager::IsInstanceFull(Instance* instance, bool isFriendTransfer) { - if (!isFriendTransfer && instance->GetSoftCap() > instance->GetCurrentClientCount()) - return false; - else if (isFriendTransfer && instance->GetHardCap() > instance->GetCurrentClientCount()) - return false; - - return true; -} - -Instance* InstanceManager::FindInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneId) { - for (Instance* i : m_Instances) { - if (i && i->GetMapID() == mapID && i->GetCloneID() == cloneId && !IsInstanceFull(i, isFriendTransfer) && !i->GetIsPrivate() && !i->GetShutdownComplete() && !i->GetIsShuttingDown()) { +const InstancePtr& InstanceManager::FindInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneId) { + for (const auto& i : m_Instances) { + if (i && i->GetMapID() == mapID && i->GetCloneID() == cloneId && !i->IsFull(isFriendTransfer) && !i->GetIsPrivate() && !i->GetShutdownComplete() && !i->GetIsShuttingDown()) { return i; } } - return nullptr; + return g_Empty; } -Instance* InstanceManager::FindInstance(LWOMAPID mapID, LWOINSTANCEID instanceID) { - for (Instance* i : m_Instances) { +const InstancePtr& InstanceManager::FindInstance(LWOMAPID mapID, LWOINSTANCEID instanceID) { + for (const auto& i : m_Instances) { if (i && i->GetMapID() == mapID && i->GetInstanceID() == instanceID && !i->GetIsPrivate() && !i->GetShutdownComplete() && !i->GetIsShuttingDown()) { return i; } } - return nullptr; + return g_Empty; } -Instance* InstanceManager::FindInstanceWithPrivate(LWOMAPID mapID, LWOINSTANCEID instanceID) { - for (Instance* i : m_Instances) { +const InstancePtr& InstanceManager::FindInstanceWithPrivate(LWOMAPID mapID, LWOINSTANCEID instanceID) { + for (const auto& i : m_Instances) { if (i && i->GetMapID() == mapID && i->GetInstanceID() == instanceID && !i->GetShutdownComplete() && !i->GetIsShuttingDown()) { return i; } } - return nullptr; + return g_Empty; } -Instance* InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password) { - auto* instance = FindPrivateInstance(password); +const InstancePtr& InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password) { + const auto& instance = FindPrivateInstance(password); if (instance != nullptr) { return instance; @@ -295,27 +281,27 @@ Instance* InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID clon mapID, m_LastInstanceID + 1, cloneID); - return nullptr; + return g_Empty; } int maxPlayers = 999; uint32_t port = GetFreePort(); - instance = new Instance(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, maxPlayers, maxPlayers, true, password); + auto newInstance = make_unique(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, maxPlayers, maxPlayers, true, password); //Start the actual process: StartWorldServer(mapID, port, m_LastInstanceID, maxPlayers, cloneID); - m_Instances.push_back(instance); + m_Instances.push_back(std::move(newInstance)); - if (instance) return instance; + if (m_Instances.back()) return m_Instances.back(); else LOG("Failed to create a new instance!"); - return instance; + return g_Empty; } -Instance* InstanceManager::FindPrivateInstance(const std::string& password) { - for (auto* instance : m_Instances) { +const InstancePtr& InstanceManager::FindPrivateInstance(const std::string& password) { + for (const auto& instance : m_Instances) { if (!instance) continue; if (!instance->GetIsPrivate()) { @@ -329,7 +315,7 @@ Instance* InstanceManager::FindPrivateInstance(const std::string& password) { } } - return nullptr; + return g_Empty; } int InstanceManager::GetSoftCap(LWOMAPID mapID) { @@ -363,3 +349,14 @@ void Instance::Shutdown() { LOG("Triggered world shutdown for zone/clone/instance %i/%i/%i", GetMapID(), GetCloneID(), GetInstanceID()); } + + +bool Instance::IsFull(bool isFriendTransfer) const { + if (!isFriendTransfer && GetSoftCap() > GetCurrentClientCount()) + return false; + else if (isFriendTransfer && GetHardCap() > GetCurrentClientCount()) + return false; + + return true; +} + diff --git a/dMasterServer/InstanceManager.h b/dMasterServer/InstanceManager.h index 3b816b58..a6ba6d9a 100644 --- a/dMasterServer/InstanceManager.h +++ b/dMasterServer/InstanceManager.h @@ -75,6 +75,8 @@ public: void Shutdown(); + bool IsFull(bool isFriendTransfer) const; + private: std::string m_IP{}; uint32_t m_Port{}; @@ -99,42 +101,42 @@ private: //Private functions: }; +using InstancePtr = std::unique_ptr; + class InstanceManager { public: - InstanceManager(Logger* logger, const std::string& externalIP); - ~InstanceManager(); + InstanceManager(const std::string& externalIP); - Instance* GetInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneID); //Creates an instance if none found + const InstancePtr& GetInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneID); //Creates an instance if none found bool IsPortInUse(uint32_t port); uint32_t GetFreePort(); void AddPlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINSTANCEID instanceID); void RemovePlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINSTANCEID instanceID); - std::vector GetInstances() const; - void AddInstance(Instance* instance); - void RemoveInstance(Instance* instance); + const std::vector& GetInstances() const; + void AddInstance(InstancePtr& instance); + void RemoveInstance(const InstancePtr& instance); - void ReadyInstance(Instance* instance); - void RequestAffirmation(Instance* instance, const PendingInstanceRequest& request); - void AffirmTransfer(Instance* instance, uint64_t transferID); + void ReadyInstance(const InstancePtr& instance); + void RequestAffirmation(const InstancePtr& instance, const PendingInstanceRequest& request); + void AffirmTransfer(const InstancePtr& instance, uint64_t transferID); - void RedirectPendingRequests(Instance* instance); + void RedirectPendingRequests(const InstancePtr& instance); - Instance* GetInstanceBySysAddr(SystemAddress& sysAddr); + const InstancePtr& GetInstanceBySysAddr(SystemAddress& sysAddr); - Instance* FindInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneId = 0); - Instance* FindInstance(LWOMAPID mapID, LWOINSTANCEID instanceID); - Instance* FindInstanceWithPrivate(LWOMAPID mapID, LWOINSTANCEID instanceID); + const InstancePtr& FindInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneId = 0); + const InstancePtr& FindInstance(LWOMAPID mapID, LWOINSTANCEID instanceID); + const InstancePtr& FindInstanceWithPrivate(LWOMAPID mapID, LWOINSTANCEID instanceID); - Instance* CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password); - Instance* FindPrivateInstance(const std::string& password); + const InstancePtr& CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password); + const InstancePtr& FindPrivateInstance(const std::string& password); void SetIsShuttingDown(bool value) { this->m_IsShuttingDown = value; }; private: - Logger* mLogger; std::string mExternalIP; - std::vector m_Instances; + std::vector> m_Instances; uint16_t m_LastPort = 3000; LWOINSTANCEID m_LastInstanceID; @@ -144,7 +146,6 @@ private: bool m_IsShuttingDown = false; //Private functions: - bool IsInstanceFull(Instance* instance, bool isFriendTransfer); int GetSoftCap(LWOMAPID mapID); int GetHardCap(LWOMAPID mapID); }; diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index d2fa443d..52bc0eac 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -359,7 +359,7 @@ int main(int argc, char** argv) { //Create additional objects here: PersistentIDManager::Initialize(); - Game::im = new InstanceManager(Game::logger, Game::server->GetIP()); + Game::im = new InstanceManager(Game::server->GetIP()); //Get CDClient initial information try { @@ -434,9 +434,9 @@ int main(int argc, char** argv) { framesSinceKillUniverseCommand++; } - const auto instances = Game::im->GetInstances(); + const auto& instances = Game::im->GetInstances(); - for (auto* instance : instances) { + for (const auto& instance : instances) { if (instance == nullptr) { break; } @@ -460,7 +460,7 @@ int main(int argc, char** argv) { } //Remove dead instances - for (auto* instance : instances) { + for (const auto& instance : instances) { if (instance == nullptr) { break; } @@ -489,7 +489,7 @@ void HandlePacket(Packet* packet) { //Since this disconnection is intentional, we'll just delete it as //we'll start a new one anyway if needed: - Instance* instance = + const auto& instance = Game::im->GetInstanceBySysAddr(packet->systemAddress); if (instance) { LOG("Actually disconnected from zone %i clone %i instance %i port %i", instance->GetMapID(), instance->GetCloneID(), instance->GetInstanceID(), instance->GetPort()); @@ -510,7 +510,7 @@ void HandlePacket(Packet* packet) { if (packet->data[0] == ID_CONNECTION_LOST) { LOG("A server has lost the connection"); - Instance* instance = + const auto& instance = Game::im->GetInstanceBySysAddr(packet->systemAddress); if (instance) { LWOZONEID zoneID = instance->GetZoneID(); //Get the zoneID so we can recreate a server @@ -561,9 +561,9 @@ void HandlePacket(Packet* packet) { LOG("Shutdown sequence has been started. Not creating a new zone."); break; } - Instance* in = Game::im->GetInstance(zoneID, false, zoneClone); + const auto& in = Game::im->GetInstance(zoneID, false, zoneClone); - for (auto* instance : Game::im->GetInstances()) { + for (const auto& instance : Game::im->GetInstances()) { LOG("Instance: %i/%i/%i -> %i %s", instance->GetMapID(), instance->GetCloneID(), instance->GetInstanceID(), instance == in, instance->GetSysAddr().ToString()); } @@ -603,12 +603,12 @@ void HandlePacket(Packet* packet) { if (theirServerType == ServerType::World) { if (!Game::im->IsPortInUse(theirPort)) { - Instance* in = new Instance(theirIP.string, theirPort, theirZoneID, theirInstanceID, 0, 12, 12); + auto in = std::make_unique(theirIP.string, theirPort, theirZoneID, theirInstanceID, 0, 12, 12); in->SetSysAddr(packet->systemAddress); Game::im->AddInstance(in); } else { - auto* instance = Game::im->FindInstanceWithPrivate(theirZoneID, static_cast(theirInstanceID)); + const auto& instance = Game::im->FindInstanceWithPrivate(theirZoneID, static_cast(theirInstanceID)); if (instance) { instance->SetSysAddr(packet->systemAddress); } @@ -682,7 +682,7 @@ void HandlePacket(Packet* packet) { inStream.Read(theirZoneID); inStream.Read(theirInstanceID); - auto instance = + const auto& instance = Game::im->FindInstance(theirZoneID, theirInstanceID); if (instance) { instance->AddPlayer(Player()); @@ -702,7 +702,7 @@ void HandlePacket(Packet* packet) { inStream.Read(theirZoneID); inStream.Read(theirInstanceID); - auto instance = + const auto& instance = Game::im->FindInstance(theirZoneID, theirInstanceID); if (instance) { instance->RemovePlayer(Player()); @@ -728,7 +728,7 @@ void HandlePacket(Packet* packet) { inStream.Read(character); password += character; } - auto* newInst = Game::im->CreatePrivateInstance(mapId, cloneId, password.c_str()); + const auto& newInst = Game::im->CreatePrivateInstance(mapId, cloneId, password.c_str()); LOG("Creating private zone %i/%i/%i with password %s", newInst->GetMapID(), newInst->GetCloneID(), newInst->GetInstanceID(), password.c_str()); break; @@ -754,9 +754,9 @@ void HandlePacket(Packet* packet) { password += character; } - auto* instance = Game::im->FindPrivateInstance(password.c_str()); + const auto& instance = Game::im->FindPrivateInstance(password.c_str()); - LOG("Join private zone: %llu %d %s %p", requestID, mythranShift, password.c_str(), instance); + LOG("Join private zone: %llu %d %s %p", requestID, mythranShift, password.c_str(), instance.get()); if (instance == nullptr) { return; @@ -781,7 +781,7 @@ void HandlePacket(Packet* packet) { LOG("Got world ready %i %i", zoneID, instanceID); - auto* instance = Game::im->FindInstance(zoneID, instanceID); + const auto& instance = Game::im->FindInstance(zoneID, instanceID); if (instance == nullptr) { LOG("Failed to find zone to ready"); @@ -819,7 +819,7 @@ void HandlePacket(Packet* packet) { LOG("Got affirmation of transfer %llu", requestID); - auto* instance = Game::im->GetInstanceBySysAddr(packet->systemAddress); + const auto& instance = Game::im->GetInstanceBySysAddr(packet->systemAddress); if (instance == nullptr) return; @@ -832,7 +832,7 @@ void HandlePacket(Packet* packet) { case MessageType::Master::SHUTDOWN_RESPONSE: { CINSTREAM_SKIP_HEADER; - auto* instance = Game::im->GetInstanceBySysAddr(packet->systemAddress); + const auto& instance = Game::im->GetInstanceBySysAddr(packet->systemAddress); LOG("Got shutdown response from %s", packet->systemAddress.ToString()); if (instance == nullptr) { return; @@ -882,13 +882,13 @@ int ShutdownSequence(int32_t signal) { LOG("Saved ObjectIDTracker to DB"); // A server might not be finished spinning up yet, remove all of those here. - for (auto* instance : Game::im->GetInstances()) { + for (const auto& instance : Game::im->GetInstances()) { + if (!instance) continue; + if (!instance->GetIsReady()) { Game::im->RemoveInstance(instance); } - } - - for (auto* instance : Game::im->GetInstances()) { + instance->SetIsShuttingDown(true); } @@ -909,7 +909,7 @@ int ShutdownSequence(int32_t signal) { allInstancesShutdown = true; - for (auto* instance : Game::im->GetInstances()) { + for (const auto& instance : Game::im->GetInstances()) { if (instance == nullptr) { continue; }