BVB Source Codes

CRYENGINE Show NetMsgDispatcher.cpp Source code

Return Download CRYENGINE: download NetMsgDispatcher.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name:   NetMsgDispatcher.h
  5. //  Description: Central Hub for bidirectional communication of simple messages
  6. //  Uses: Can be used to send messages from client to server and vice versa.
  7. //  - Thread Safety:
  8. //              * Listeners
  9. //                      - Are all local.
  10. //                      - Registration / de-registration / OnMessage callback must happen on the same thread
  11. //              * Received messages through the network (m_receivedNetMsgQueue)
  12. //                      - Thread safe via m_criticalSectionReceivedQueue
  13. //              * Messages sent through the network
  14. //                      - Only the stats are not thread safe (but they are debug only)
  15. //                      - If needed they could be guarded but currently all messages are sent from main thread (Flow Graph)
  16. // -------------------------------------------------------------------------
  17. //  History: Dario Sancho. 15.10.2014. Created
  18. //
  19. ////////////////////////////////////////////////////////////////////////////
  20.  
  21. #include "StdAfx.h"
  22. #include "NetMsgDispatcher.h"
  23. #include <CryRenderer/IRenderer.h> // for debug render
  24. #include "GameClientChannel.h"
  25. #include "GameClientNub.h"
  26. #include "GameServerChannel.h"
  27. #include "GameServerNub.h"
  28.  
  29. // ------------------------------------------------------------------------
  30. // Local CVARS
  31. // ------------------------------------------------------------------------
  32. int CNetMessageDistpatcher::CVars::net_netMsgDispatcherDebug = 0;
  33. int CNetMessageDistpatcher::CVars::net_netMsgDispatcherLogging = 0;
  34. int CNetMessageDistpatcher::CVars::net_netMsgDispatcherWarnThreshold = 10;
  35.  
  36. void CNetMessageDistpatcher::CVars::Register()
  37. {
  38.         REGISTER_CVAR_DEV_ONLY(net_netMsgDispatcherDebug, net_netMsgDispatcherDebug, VF_DEV_ONLY, "Enables (1) / Disables (0) the debug render for CNetMessageDistpatcher");
  39.         REGISTER_CVAR_DEV_ONLY(net_netMsgDispatcherLogging, net_netMsgDispatcherLogging, VF_DEV_ONLY, "Enables (1) / Disables (0) console logging for CNetMessageDistpatcher");
  40.         REGISTER_CVAR_DEV_ONLY(net_netMsgDispatcherWarnThreshold, net_netMsgDispatcherWarnThreshold, VF_DEV_ONLY, "If net_netMsgDispatcherDebug is enabled, the debug render will warn if in a frame the number messages dispatched by CNetMessageDistpatcher is bigger than net_netMsgDispatcherWarnThreshold");
  41.         REGISTER_COMMAND_DEV_ONLY("net_netMsgDispatcherClearStats", &ClearStatsCommand, VF_DEV_ONLY, "Clears the stats gathered for CNetMessageDistpatcher");
  42. }
  43.  
  44. void CNetMessageDistpatcher::CVars::UnRegister()
  45. {
  46. #if !defined(_RELEASE)
  47.         if (IConsole* pConsole = gEnv->pConsole)
  48.         {
  49.                 pConsole->RemoveCommand("net_netMsgDispatcherClearStats");
  50.                 pConsole->UnregisterVariable("net_netMsgDispatcherDebug", true);
  51.                 pConsole->UnregisterVariable("net_netMsgDispatcherLogging", true);
  52.                 pConsole->UnregisterVariable("net_netMsgDispatcherWarnThreshold", true);
  53.         }
  54. #endif
  55. }
  56.  
  57. void CNetMessageDistpatcher::CVars::ClearStatsCommand(IConsoleCmdArgs* pArgs)
  58. {
  59.         if (CNetMessageDistpatcher* pNetMsgDispatcher = CCryAction::GetCryAction()->GetNetMessageDispatcher())
  60.         {
  61.                 pNetMsgDispatcher->ClearStatsCommand();
  62.         }
  63. }
  64.  
  65. // ------------------------------------------------------------------------
  66. // NetMsgDispatcher
  67. // ------------------------------------------------------------------------
  68.  
  69. CNetMessageDistpatcher::CNetMessageDistpatcher() :
  70.         m_listeners(8) // reserve some space for listeners
  71. {
  72.         CVars::Register();
  73. }
  74.  
  75. // ------------------------------------------------------------------------
  76. CNetMessageDistpatcher::~CNetMessageDistpatcher()
  77. {
  78.         CVars::UnRegister();
  79. }
  80.  
  81. // ------------------------------------------------------------------------
  82. void CNetMessageDistpatcher::DefineProtocol(IProtocolBuilder* pBuilder)
  83. {
  84.         pBuilder->AddMessageSink(this, CNetMessageDistpatcher::GetProtocolDef(), CNetMessageDistpatcher::GetProtocolDef());
  85. }
  86.  
  87. // ------------------------------------------------------------------------
  88. void CNetMessageDistpatcher::AddReceivedNetMsgToQueue(const SNetMsgData& msg, ENetMsgSrc src)
  89. {
  90.         {
  91.                 CryAutoLock<CryCriticalSectionNonRecursive> lock(m_criticalSectionReceivedQueue);
  92.                 m_receivedNetMsgQueue.push_back(msg);
  93.         }
  94.  
  95.         if (src == eNMS_Network)
  96.         {
  97.                 m_stats.Add(CNetStats::eT_Received, 1);
  98.         }
  99.  
  100.         NET_MSG_DISPATCHER_LOG("[AddReceivedNetMsgToQueue]: %s received new message [%s->%s]-[%s/%s]",
  101.                                DbgTranslateLocationToString(), msg.DbgTranslateSourceToString(), msg.DbgTranslateTargetToString(), msg.key.c_str(), msg.value.c_str());
  102. }
  103.  
  104. // ------------------------------------------------------------------------
  105. // Functions exposed through the network
  106. // ------------------------------------------------------------------------
  107. NET_IMPLEMENT_SIMPLE_ATSYNC_MESSAGE(CNetMessageDistpatcher, OnIncomingMessage, eNRT_ReliableOrdered, eMPF_NoSendDelay)
  108. {
  109.         // Get the messages sent over the network and add them to the queue
  110.         AddReceivedNetMsgToQueue(param, eNMS_Network);
  111.         return true;
  112. }
  113.  
  114. // ------------------------------------------------------------------------
  115. void CNetMessageDistpatcher::SendMessage(const SNetMsgData& msg)
  116. {
  117.         uint32 cntDispatchedMsgs = 0;
  118.  
  119.         CRY_ASSERT_MESSAGE(msg.tgt != SNetMsgData::eT_Invalid, "Invalid message target");
  120.  
  121.         // Create network message
  122.         INetSendablePtr netMsg = new CSimpleNetMessage<SNetMsgData>(msg, CNetMessageDistpatcher::OnIncomingMessage);
  123.         const SNetMsgData::ELocation whereAmI = GetLocation();
  124.         switch (whereAmI)
  125.         {
  126.         case SNetMsgData::eL_Client:
  127.                 {
  128.                         CGameClientNub* pClientNub = CCryAction::GetCryAction()->GetGameClientNub();
  129.                         // Dispatch message to the server
  130.                         if (pClientNub)
  131.                         {
  132.                                 if (CGameClientChannel* pGCC = pClientNub->GetGameClientChannel())
  133.                                 {
  134.                                         ++cntDispatchedMsgs;
  135.  
  136.                                         pGCC->GetNetChannel()->AddSendable(netMsg, 0, NULL, NULL);
  137.                                         NET_MSG_DISPATCHER_LOG("[DispatchNetMessages]: %s dispatched [%s->%s]-[%s/%s] to Server",
  138.                                                                DbgTranslateLocationToString(), msg.DbgTranslateSourceToString(), msg.DbgTranslateTargetToString(), msg.key.c_str(), msg.value.c_str());
  139.                                 }
  140.  
  141.                                 if (msg.tgt == SNetMsgData::eT_All)
  142.                                 {
  143.                                         // loop back and make local listeners aware of this message
  144.                                         NET_MSG_DISPATCHER_LOG("[DispatchNetMessages]: %s loop back [%s->%s]-[%s/%s]",
  145.                                                                DbgTranslateLocationToString(), msg.DbgTranslateSourceToString(), msg.DbgTranslateTargetToString(), msg.key.c_str(), msg.value.c_str());
  146.  
  147.                                         AddReceivedNetMsgToQueue(msg, eNMS_Local);
  148.                                 }
  149.                         }
  150.                         else
  151.                         {
  152.                                 CryWarning(VALIDATOR_MODULE_NETWORK, VALIDATOR_WARNING, "[CNetMessageDistpatcher::DispatchNetMessages] ClientNub == NULL");
  153.                         }
  154.                 }
  155.                 break;
  156.         case SNetMsgData::eL_Server: // intentional fall through
  157.         case SNetMsgData::eL_DedicatedServer:
  158.                 {
  159.                         // send message to all clients
  160.                         if (CGameServerNub* pServerNub = CCryAction::GetCryAction()->GetGameServerNub())
  161.                         {
  162.                                 if (TServerChannelMap* m = pServerNub->GetServerChannelMap())
  163.                                 {
  164.                                         for (TServerChannelMap::iterator iter = m->begin(); iter != m->end(); ++iter)
  165.                                         {
  166.                                                 if (INetChannel* pNetChannel = iter->second->GetNetChannel()) //channel can be on hold thus not having net channel currently
  167.                                                 {
  168.                                                         ++cntDispatchedMsgs;
  169.  
  170.                                                         pNetChannel->AddSendable(netMsg, 0, NULL, NULL);
  171.  
  172.                                                         NET_MSG_DISPATCHER_LOG("[DispatchNetMessages]: %s dispatched [%s->%s]-[%s/%s] to Client",
  173.                                                                                DbgTranslateLocationToString(), msg.DbgTranslateSourceToString(), msg.DbgTranslateTargetToString(), msg.key.c_str(), msg.value.c_str());
  174.                                                 }
  175.                                         }
  176.                                 }
  177.                         }
  178.                         else
  179.                         {
  180.                                 CryWarning(VALIDATOR_MODULE_NETWORK, VALIDATOR_WARNING, "[CNetMessageDistpatcher::DispatchNetMessages] pServerNub == NULL");
  181.                         }
  182.                 }
  183.                 break;
  184.         default:
  185.                 CRY_ASSERT(0);
  186.         }
  187.  
  188.         m_stats.Add(CNetStats::eT_Sent, cntDispatchedMsgs);
  189.  
  190.         NET_MSG_DISPATCHER_LOG("[SendMessage]: %s queued message [%s->%s]-[%s/%s]",
  191.                                DbgTranslateLocationToString(), msg.DbgTranslateSourceToString(), msg.DbgTranslateTargetToString(), msg.key.c_str(), msg.value.c_str());
  192. }
  193.  
  194. // ------------------------------------------------------------------------
  195. void CNetMessageDistpatcher::DispatchQueuedMessagesToLocalListeners()
  196. {
  197.         if (m_receivedNetMsgQueue.empty() == true)
  198.                 return;
  199.  
  200.         m_criticalSectionReceivedQueue.Lock();
  201.         m_copyOfReceivedNetMsgQueue.clear();
  202.         m_copyOfReceivedNetMsgQueue.swap(m_receivedNetMsgQueue);
  203.         m_criticalSectionReceivedQueue.Unlock();
  204.  
  205.         // We have received messages over the network. It is time to dispatch them to our local listeners
  206.         for (size_t i = 0, iSize = m_copyOfReceivedNetMsgQueue.size(); i < iSize; ++i)
  207.         {
  208.                 const SNetMsgData& msg = m_copyOfReceivedNetMsgQueue[i];
  209.                 for (TNetMsgListener::Notifier notifier(m_listeners); notifier.IsValid(); notifier.Next())
  210.                 {
  211.                         notifier->OnMessage(msg);
  212.                         NET_MSG_DISPATCHER_LOG("[DispatchQueuedMessagesToLocalListeners]: %s call [%s->%s] OnMessage(%s/%s) on Listener",
  213.                                                DbgTranslateLocationToString(), msg.DbgTranslateSourceToString(), msg.DbgTranslateTargetToString(), msg.key.c_str(), msg.value.c_str());
  214.                 }
  215.         }
  216.  
  217. }
  218.  
  219. // ------------------------------------------------------------------------
  220. void CNetMessageDistpatcher::RegisterListener(INetMsgListener* pListener, const char* name)
  221. {
  222.         const bool ok = m_listeners.Add(pListener, name);
  223.         NET_MSG_DISPATCHER_LOG("[RegisterListener]: %s Registering listener %s [total:%" PRISIZE_T "] - %s", DbgTranslateLocationToString(), name ? name : "[unnamed]", m_listeners.ValidListenerCount(), ok ? "OK" : "ALREADY REGISTERED");
  224. }
  225.  
  226. // ------------------------------------------------------------------------
  227. void CNetMessageDistpatcher::UnRegisterListener(INetMsgListener* pListener)
  228. {
  229.         m_listeners.Remove(pListener);
  230.         NET_MSG_DISPATCHER_LOG("[UnRegisterListener]: %s removing listener [total:%" PRISIZE_T "]", DbgTranslateLocationToString(), m_listeners.ValidListenerCount());
  231. }
  232.  
  233. // ------------------------------------------------------------------------
  234. void CNetMessageDistpatcher::ClearListeners()
  235. {
  236.         m_listeners.Clear();
  237.         NET_MSG_DISPATCHER_LOG("[CNetMessageDistpatcher]: %s ClearListeners", DbgTranslateLocationToString());
  238. }
  239.  
  240. // ------------------------------------------------------------------------
  241. void CNetMessageDistpatcher::Update()
  242. {
  243.         // Send messages received through the network to listeners
  244.         DispatchQueuedMessagesToLocalListeners();
  245.  
  246.         // Stats
  247.         if (CVars::net_netMsgDispatcherDebug)
  248.         {
  249.                 DebugDraw();
  250.                 m_stats.ClearFrameStats();
  251.         }
  252. }
  253.  
  254. // ------------------------------------------------------------------------
  255. /* static */ SNetMsgData::ELocation CNetMessageDistpatcher::GetLocation()
  256. {
  257.         return gEnv->bServer ? SNetMsgData::eL_Server :
  258.                gEnv->IsDedicated() ? SNetMsgData::eL_DedicatedServer :
  259.                gEnv->IsClient() ? SNetMsgData::eL_Client :
  260.                SNetMsgData::eL_Unknown;
  261. }
  262.  
  263. // ------------------------------------------------------------------------
  264. /* static */ const char* CNetMessageDistpatcher::DbgTranslateLocationToString()
  265. {
  266.         SNetMsgData msg(GetLocation(), SNetMsgData::eT_Default, "", "");
  267.         return msg.DbgTranslateSourceToString();
  268. }
  269.  
  270. // ------------------------------------------------------------------------
  271. /* static */ void CNetMessageDistpatcher::Log(const char* szMessage)
  272. {
  273.         if (CVars::net_netMsgDispatcherLogging == 0)
  274.         {
  275.                 return;
  276.         }
  277.  
  278.         CryLog("%s", szMessage);
  279. }
  280.  
  281. // ------------------------------------------------------------------------
  282. void CNetMessageDistpatcher::DebugDraw()
  283. {
  284.         const float xPosLabel = 10.f, xPosData = 10.f, yPos = 80.f, yDelta = 20.f;
  285.         float y = yPos;
  286.         const ColorF fColorLabel(1.0f, 1.0f, 1.0f, 1.0f);
  287.         const ColorF fColorData(1.0f, 1.0f, 0.0f, 1.0f);
  288.         const ColorF fColorWarning(1.0f, 0.0f, 0.0f, 1.0f);
  289.  
  290.         const float kFontSize = m_stats.GetSentStats().m_max <= CVars::net_netMsgDispatcherWarnThreshold ? 1.3f : 1.7f;
  291.         const ColorF& fColor = m_stats.GetSentStats().m_max <= CVars::net_netMsgDispatcherWarnThreshold ? fColorData : fColorWarning;
  292.         IRenderAuxText::Draw2dLabel(xPosLabel, y, 1.3f, fColorLabel, false, "NetMsg Stats (Total: %" PRIu64 " / Local List.: %" PRISIZE_T ")", m_stats.GetSentStats().m_total, m_listeners.ValidListenerCount());
  293.         y += yDelta;
  294.         IRenderAuxText::Draw2dLabel(xPosData, y, kFontSize, fColor, false, "Max frame cnt: %u/%d", m_stats.GetSentStats().m_max, CVars::net_netMsgDispatcherWarnThreshold);
  295. }
  296.  
  297. // ------------------------------------------------------------------------
  298. void CNetMessageDistpatcher::CNetStats::Add(ETypes type, uint32 value)
  299. {
  300.         if (CVars::net_netMsgDispatcherDebug)
  301.         {
  302.                 switch (type)
  303.                 {
  304.                 case eT_Sent:
  305.                         {
  306.                                 m_sent.Add(value);
  307.                         } break;
  308.                 case eT_Received:
  309.                         {
  310.                                 /* not needed for the moment */ } break;
  311.                 default:
  312.                         CRY_ASSERT(0);
  313.                 }
  314.         }
  315. }
  316.  
downloadNetMsgDispatcher.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top