The NetGameObjectManager is used for storing and generating network game objects on the client side of Chrono-Drive. I utilize this within the CNetGameObject for adding to the managed network object unordered map upon the particular objects initialization. Also, for dynamic network objects created within LUA we can use the NetGameObjectManager::CreateNetGameObject function for allowing those dynamic network objects to be created.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
/* Author : Chase Hutchens Date : 11/11/15 - 1/17/16 */ // Copyright: All content © 2016 DigiPen (USA) Corporation, all rights reserved. #pragma once // Local Modules #include "Export.h" #include "CNetGameObject.h" // Other Engine Modules #include "../Engine/Messages.h" // 3rd Party Modules #include <unordered_map> #define DYNAMIC_NET_OBJECT 0xD00A00C // I'm wanting this struct to contain the common data that is sent/received for each NetObject // then the customData contains the specific NetObject data for the particular NetObject struct NetObjectInfo { NetObjModule objType; std::string archeType, netObjId, objName; std::vector<std::shared_ptr<void> > customData; NetObjectInfo() : objType(NetObjModule::NONE), archeType(""), netObjId(""), objName("") { } NetObjectInfo(const NetObjModule type, const std::string& arch, const std::string& netId) : objType(type), archeType(arch), netObjId(netId) { } ~NetObjectInfo() { customData.clear(); } }; class NetGameObjectManager : public EventBase { private: std::unordered_map<std::string, GameObject*> netGameObjects; std::vector<std::shared_ptr<NetObjectInfo> > netObjsToAdd; std::vector<std::string> netObjToRemove; private: void DynamicallyCreatedNetObject(EnumEvent* enumEvent); public: GAM_EXPORT static NetGameObjectManager& GetInstance(); virtual void OnInit(); std::unordered_map<std::string, GameObject*>& GetNetGameObjects(); std::vector<std::shared_ptr<NetObjectInfo> >& GetNetObjectsToAdd(); std::vector<std::string>& GetNetObjectsToRemove(); GAM_EXPORT GameObject* CreateNetGameObject(const std::string& archName, const Vec3& pos, const std::string& objName); GAM_EXPORT void AddNetGameObject(const std::string& netId, GameObject* netGameObj, bool generateId = true, bool dynamicNetObj = false); GAM_EXPORT void RemoveNetGameObject(const std::string& netId); GAM_EXPORT void SafeRemoveNetGameObject(const std::string& netId); GAM_EXPORT GameObject* GetGameObjectFromNetID(const std::string& netId); }; |
Implementation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
/* Author : Chase Hutchens Date : 11/11/15 - 1/17/16 */ // All content © 2014-2015 DigiPen (USA) Corporation, all rights reserved. // Local Modules #include "Precompiled.h" #include "NetGameObjectManager.h" #include "NetworkGameService.h" #include "CNetGameObject.h" #include "CPressureSwitch.h" // Other Engine Modules #include "../Engine/GSM.h" #include "../Engine/Archetype.h" #include "../Engine/Space.h" #include "../Network/NetworkManager.h" // 3rd Party Modules #include <iostream> #include <sstream> // PRIVATE void NetGameObjectManager::DynamicallyCreatedNetObject(EnumEvent* enumEvent) { *enumEvent->enumVal = DYNAMIC_NET_OBJECT; } // ----- // PUBLIC NetGameObjectManager& NetGameObjectManager::GetInstance() { static NetGameObjectManager netGameObjManager; return netGameObjManager; } void NetGameObjectManager::OnInit() { } std::unordered_map<std::string, GameObject*>& NetGameObjectManager::GetNetGameObjects() { return netGameObjects; } std::vector<std::shared_ptr<NetObjectInfo> >& NetGameObjectManager::GetNetObjectsToAdd() { return netObjsToAdd; } std::vector<std::string>& NetGameObjectManager::GetNetObjectsToRemove() { return netObjToRemove; } // just specific to the main host right now GameObject* NetGameObjectManager::CreateNetGameObject(const std::string& archName, const Vec3& pos, const std::string& objName) { GameObject* netGameObj = nullptr; if (!(Archetype::GetArchetypeList().at(archName))->FindComponent<CNetGameObject>("CNetGameObject")) { // just create the regular object (failing gracefully) std::cerr << "[warning]NetGameObjectManager::CreateNetGameObject being called for: " << archName << " that contains no CNetGameObject\n"; netGameObj = GSM::FindCurrentSpace("GameSpace")->CreateArchetypeAtPosWithName(archName, pos, objName); } else { if (NetworkManager::GetInstance().IsActiveConnection()) { if (ActiveNetworkGameManager::GetInstance().IsMainClient()) { //std::cout << "Dynamic Net Object Created\n"; CONNECT(&ActiveNetworkGameManager::GetInstance(), EventList::NetObjectCreated, &NetGameObjectManager::DynamicallyCreatedNetObject); netGameObj = GSM::FindCurrentSpace("GameSpace")->CreateArchetypeAtPosWithName(archName, pos, objName); Disconnect(EventList::NetObjectCreated); } } else { // just create the regular object (failing gracefully) netGameObj = GSM::FindCurrentSpace("GameSpace")->CreateArchetypeAtPosWithName(archName, pos, objName); } } return netGameObj; } // Adds a NetGameObject to the netGameObjs<netId, netGameObj> map for keeping track of when it needs to send or receive a network message // generateId (true) => creates a message that is sent to the server about this net game object's existence, in it's expected format // generateId (false) => only needs to associate the netId with this netGameObj on this client void NetGameObjectManager::AddNetGameObject(const std::string& netId, GameObject* netGameObj, bool generateId, bool dynamicNetObj) { //std::cout << "Adding NetGameObj: " << netId << NLDS << netGameObj->GetArchName() << std::endl; ActiveNetworkGameManager& netGameManager = ActiveNetworkGameManager::GetInstance(); netGameManager.LockNetGameObjMutex(); netGameObjects[netId] = netGameObj; netGameManager.UnlockNetGameObjMutex(); CNetGameObject* netObj = netGameObj->FindComponent<CNetGameObject>("CNetGameObject"); if (generateId) { std::stringstream msg; // expected format : // :GAME!NETGAMEOBJECT <netId>:<objType>:<objName>:<dynamic>[:<specificNetObjInfo>]\r\n // TODO: Will need to send other custom data eventually switch (netObj->GetObjModule()) { case (int)NetObjModule::ITEM: { msg << NetworkManager::GetInstance().GetServerCmdFromMessageType(MESSAGE_TYPE::Game) << netObj->GenerateMessageID(NetworkMessages::NETGAMEOBJECT) << NetObjModuleNames[(int)NetObjModule::ITEM] << NMS << netGameObj->GetName() << NMS << dynamicNetObj << NMS << netGameObj->GetArchName() << NMS << netGameObj->m_Pos.GetX() << NMDS << netGameObj->m_Pos.GetY() << NMDS << netGameObj->m_Pos.GetZ() << NMDS << netGameObj->m_Rot.GetX() << NMDS << netGameObj->m_Rot.GetY() << NMDS << netGameObj->m_Rot.GetZ() << NMDS << netGameObj->m_Scale << NMDS << NME; break; } case (int)NetObjModule::SWITCH: { CPressureSwitch* pSwitch = netGameObj->FindComponent<CPressureSwitch>("CPressureSwitch"); msg << NetworkManager::GetInstance().GetServerCmdFromMessageType(MESSAGE_TYPE::Game) << netObj->GenerateMessageID(NetworkMessages::NETGAMEOBJECT) << NetObjModuleNames[(int)NetObjModule::SWITCH] << NMS << netGameObj->GetName() << NMS << dynamicNetObj << NMS << pSwitch->IsActivated() << NME; break; } case (int)NetObjModule::LEVELTRANSITION: { msg << NetworkManager::GetInstance().GetServerCmdFromMessageType(MESSAGE_TYPE::Game) << netObj->GenerateMessageID(NetworkMessages::NETGAMEOBJECT) << NetObjModuleNames[(int)NetObjModule::LEVELTRANSITION] << NMS << netGameObj->GetName() << NMS << dynamicNetObj << NMS << netGameObj->m_Pos.GetX() << NMDS << netGameObj->m_Pos.GetY() << NMDS << netGameObj->m_Pos.GetZ() << NMDS << netGameObj->m_Rot.GetX() << NMDS << netGameObj->m_Rot.GetY() << NMDS << netGameObj->m_Rot.GetZ() << NMDS << netGameObj->m_Scale << NMDS << (dynamicNetObj ? netObj->GetNetObjectBehaviorModule()->DynamicInfo() : "") << NME; break; } case (int)NetObjModule::ENEMY: { msg << NetworkManager::GetInstance().GetServerCmdFromMessageType(MESSAGE_TYPE::Game) << netObj->GenerateMessageID(NetworkMessages::NETGAMEOBJECT) << NetObjModuleNames[(int)NetObjModule::ENEMY] << NMS << netGameObj->GetName() << NMS << dynamicNetObj << NMS << netGameObj->m_Pos.GetX() << NMDS << netGameObj->m_Pos.GetY() << NMDS << netGameObj->m_Pos.GetZ() << NMDS << netGameObj->m_Rot.GetX() << NMDS << netGameObj->m_Rot.GetY() << NMDS << netGameObj->m_Rot.GetZ() << NMDS << netGameObj->m_Scale << NMDS << NME; break; } } netGameManager.AppendDelayedClientGeneratedNetObjMsg(msg.str()); } else // we aren't needing to tell the server about this object { // need to set the associated netId for this object netObj->SetNetObjID(netId); } } // mutex is already locked prior to this function being called void NetGameObjectManager::RemoveNetGameObject(const std::string& netId) { netGameObjects.erase(netId); } void NetGameObjectManager::SafeRemoveNetGameObject(const std::string& netId) { // we don't need to safe remove if we are transition to a new level, we don't want to delete persistent objects if (!ActiveNetworkGameManager::GetInstance().IsTransitioningLevel()) { netObjToRemove.push_back(netId); } } GameObject* NetGameObjectManager::GetGameObjectFromNetID(const std::string& netId) { return netGameObjects[netId]; } // ----- |