BVB Source Codes

CRYENGINE Show GameContext.cpp Source code

Return Download CRYENGINE: download GameContext.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /*************************************************************************
  4.    -------------------------------------------------------------------------
  5.    $Id$
  6.    $DateTime$
  7.  
  8.    -------------------------------------------------------------------------
  9.    History:
  10.    - 3:9:2004   11:25 : Created by M谩rcio Martins
  11.  
  12. *************************************************************************/
  13. #include "StdAfx.h"
  14. #include "GameContext.h"
  15. #include "GameServerChannel.h"
  16. #include "GameClientChannel.h"
  17. #include "IActorSystem.h"
  18. #include "IGameSessionHandler.h"
  19. #include "CryAction.h"
  20. #include "GameRulesSystem.h"
  21. #include <CryScriptSystem/ScriptHelpers.h>
  22. #include "GameObjects/GameObject.h"
  23. #include "ScriptRMI.h"
  24. #include <CryPhysics/IPhysics.h>
  25. #include "PhysicsSync.h"
  26. #include "GameClientNub.h"
  27. #include "GameServerNub.h"
  28. #include "ActionGame.h"
  29. #include "ILevelSystem.h"
  30. #include "IPlayerProfiles.h"
  31. #include "VoiceController.h"
  32. #include "BreakReplicator.h"
  33. #include "CVarListProcessor.h"
  34. #include "NetworkCVars.h"
  35. #include "CryActionCVars.h"
  36. #include <CryNetwork/INetwork.h>
  37. #include <CryCore/Platform/IPlatformOS.h>
  38.  
  39. // context establishment tasks
  40. #include <CryNetwork/NetHelpers.h>
  41. #include "CET_ClassRegistry.h"
  42. #include "CET_CVars.h"
  43. #include "CET_EntitySystem.h"
  44. #include "CET_GameRules.h"
  45. #include "CET_LevelLoading.h"
  46. #include "CET_NetConfig.h"
  47.  
  48. #include "NetDebug.h"
  49.  
  50. #include "NetMsgDispatcher.h"
  51. #include "ManualFrameStep.h"
  52.  
  53. #define VERBOSE_TRACE_CONTEXT_SPAWNS 0
  54.  
  55. CGameContext* CGameContext::s_pGameContext = NULL;
  56.  
  57. #ifdef USE_NETWORK_STALL_TICKER_THREAD
  58. CryLockT<CRYLOCK_RECURSIVE> SScopedTickerLock::s_tickerMutex;
  59. #endif // #ifdef USE_NETWORK_STALL_TICKER_THREAD
  60.  
  61. static const char* hexchars = "0123456789abcdef";
  62.  
  63. static ILINE string ToHexStr(const char* x, int len)
  64. {
  65.         string out;
  66.         for (int i = 0; i < len; i++)
  67.         {
  68.                 uint8 c = x[i];
  69.                 out += hexchars[c >> 4];
  70.                 out += hexchars[c & 0xf];
  71.         }
  72.         return out;
  73. }
  74.  
  75. static ILINE bool FromHexStr(string& x)
  76. {
  77.         string out;
  78.         uint8 cur = 0;
  79.         for (int i = 0; i < x.length(); i++)
  80.         {
  81.                 int j;
  82.                 for (j = 0; hexchars[j]; j++)
  83.                         if (hexchars[j] == x[i])
  84.                                 break;
  85.                 if (!hexchars[j])
  86.                         return false;
  87.                 cur = (cur << 4) | j;
  88.                 if (i & 1)
  89.                         out += cur;
  90.         }
  91.         x.swap(out);
  92.         return true;
  93. }
  94.  
  95. CGameContext::CGameContext(CCryAction* pFramework, CScriptRMI* pScriptRMI, CActionGame* pGame) :
  96.         m_pFramework(pFramework),
  97.         m_pPhysicsSync(0),
  98.         m_pNetContext(0),
  99.         m_pEntitySystem(0),
  100.         m_pGame(pGame),
  101.         m_controlledObjects(false),
  102.         m_isInLevelLoad(false),
  103.         m_pScriptRMI(pScriptRMI),
  104.         m_bStarted(false),
  105.         m_bIsLoadingSaveGame(false),
  106.         m_bHasSpawnPoint(true),
  107.         m_bAllowSendClientConnect(false),
  108.         m_loadFlags(eEF_LoadNewLevel),
  109.         m_resourceLocks(0),
  110.         m_removeObjectUnlocks(0),
  111.         m_broadcastActionEventInGame(-1)
  112. #if ENABLE_NETDEBUG
  113.         , m_pNetDebug(0)
  114. #endif
  115. {
  116.         CRY_ASSERT(s_pGameContext == NULL);
  117.         s_pGameContext = this;
  118.         gEnv->pConsole->AddConsoleVarSink(this);
  119.  
  120.         m_pScriptRMI->SetContext(this);
  121. #ifndef OLD_VOICE_SYSTEM_DEPRECATED
  122.         m_pVoiceController = NULL;
  123. #endif
  124.  
  125.         // default (permissive) flags until we are initialized correctly
  126.         // ensures cvars can be changed just at the editor start
  127.         m_flags = eGSF_LocalOnly | eGSF_Server | eGSF_Client;
  128.  
  129.         //      Recently the loading has changed on C2 MP to get clients to load in parallel with the server loading. This unfortunately means that
  130.         //      the message that turns on immersive multiplayer arrives _after_ rigid bodies are created. So they don't have the flag set, and
  131.         //      they don't work. We have one day left to fix as much stuff as possible, so this is being done instead of a nice fix involving
  132.         //      changing which network message things are sent in and such.
  133.         m_flags |= eGSF_ImmersiveMultiplayer;
  134.  
  135.         m_pPhysicalWorld = gEnv->pPhysicalWorld;
  136.         m_pGame->AddGlobalPhysicsCallback(eEPE_OnCollisionLogged, OnCollision, 0);
  137.  
  138.         gEnv->pNetwork->AddHostMigrationEventListener(this, "CGameContext", ELPT_PostEngine);
  139.  
  140.         if (!CCryActionCVars::Get().g_syncClassRegistry)
  141.         {
  142.                 IEntityClassRegistry* pClassRegistry = gEnv->pEntitySystem->GetClassRegistry();
  143.                 IEntityClass* pClass;
  144.                 pClassRegistry->IteratorMoveFirst();
  145.                 while (pClass = pClassRegistry->IteratorNext())
  146.                 {
  147.                         m_classRegistry.RegisterClassName(pClass->GetName(), ~uint16(0));
  148.                 }
  149.         }
  150. }
  151.  
  152. CGameContext::~CGameContext()
  153. {
  154.         gEnv->pNetwork->RemoveHostMigrationEventListener(this);
  155.  
  156.         gEnv->pConsole->RemoveConsoleVarSink(this);
  157.  
  158.         IScriptSystem* pSS = gEnv->pScriptSystem;
  159.         for (DelegateCallbacks::iterator iter = m_delegateCallbacks.begin(); iter != m_delegateCallbacks.end(); ++iter)
  160.         {
  161.                 pSS->ReleaseFunc(iter->second);
  162.         }
  163.  
  164.         if (m_pEntitySystem)
  165.                 m_pEntitySystem->RemoveSink(this);
  166.  
  167.         m_pGame->RemoveGlobalPhysicsCallback(eEPE_OnCollisionLogged, OnCollision, 0);
  168.  
  169.         m_pScriptRMI->SetContext(NULL);
  170. #ifndef OLD_VOICE_SYSTEM_DEPRECATED
  171.         delete m_pVoiceController;
  172. #endif
  173.  
  174. #if ENABLE_NETDEBUG
  175.         SAFE_DELETE(m_pNetDebug);
  176. #endif
  177.  
  178.         s_pGameContext = NULL;
  179. }
  180.  
  181. void CGameContext::Init(INetContext* pNetContext)
  182. {
  183.         CRY_ASSERT(!m_pEntitySystem);
  184.         m_pEntitySystem = gEnv->pEntitySystem;
  185.         CRY_ASSERT(m_pEntitySystem);
  186.  
  187.         uint64 onEventSubscriptions = 0;
  188.         onEventSubscriptions |= ENTITY_EVENT_BIT(ENTITY_EVENT_XFORM);
  189.         onEventSubscriptions |= ENTITY_EVENT_BIT(ENTITY_EVENT_ENTER_SCRIPT_STATE);
  190.  
  191.         m_pEntitySystem->AddSink(this, static_cast<uint32>(IEntitySystem::AllSinkEvents), onEventSubscriptions);
  192.         m_pNetContext = pNetContext;
  193.  
  194. #if ENABLE_NETDEBUG
  195.         m_pNetDebug = new CNetDebug();
  196.         assert(m_pNetDebug);
  197. #endif
  198.  
  199.         m_pNetContext->DeclareAspect("GameClientDynamic", eEA_GameClientDynamic, eAF_Delegatable);
  200.         m_pNetContext->DeclareAspect("GameServerDynamic", eEA_GameServerDynamic, 0);
  201.         m_pNetContext->DeclareAspect("GameClientStatic", eEA_GameClientStatic, eAF_Delegatable);
  202.         m_pNetContext->DeclareAspect("GameServerStatic", eEA_GameServerStatic, eAF_ServerManagedProfile);
  203.         m_pNetContext->DeclareAspect("Physics", eEA_Physics, eAF_Delegatable | eAF_ServerManagedProfile | eAF_HashState | eAF_TimestampState);
  204.         m_pNetContext->DeclareAspect("Script", eEA_Script, 0);
  205.  
  206.         m_pNetContext->DeclareAspect("GameClientA", eEA_GameClientA, eAF_Delegatable);
  207.         m_pNetContext->DeclareAspect("PlayerUpdate", eEA_Aspect31, eAF_Delegatable);
  208.         m_pNetContext->DeclareAspect("GameServerA", eEA_GameServerA, 0);
  209.         m_pNetContext->DeclareAspect("GameClientB", eEA_GameClientB, eAF_Delegatable);
  210.         m_pNetContext->DeclareAspect("GameServerB", eEA_GameServerB, 0);
  211.         m_pNetContext->DeclareAspect("GameClientC", eEA_GameClientC, eAF_Delegatable);
  212.         m_pNetContext->DeclareAspect("GameServerC", eEA_GameServerC, 0);
  213.         m_pNetContext->DeclareAspect("GameClientD", eEA_GameClientD, eAF_Delegatable);
  214.         m_pNetContext->DeclareAspect("GameClientE", eEA_GameClientE, eAF_Delegatable);
  215.         m_pNetContext->DeclareAspect("GameClientF", eEA_GameClientF, eAF_Delegatable);
  216.         m_pNetContext->DeclareAspect("GameClientG", eEA_GameClientG, eAF_Delegatable);
  217.         m_pNetContext->DeclareAspect("GameClientH", eEA_GameClientH, eAF_Delegatable);
  218.         m_pNetContext->DeclareAspect("GameClientI", eEA_GameClientI, eAF_Delegatable);
  219.         m_pNetContext->DeclareAspect("GameClientJ", eEA_GameClientJ, eAF_Delegatable);
  220.         m_pNetContext->DeclareAspect("GameServerD", eEA_GameServerD, 0);
  221.         m_pNetContext->DeclareAspect("GameClientK", eEA_GameClientK, eAF_Delegatable);
  222.         m_pNetContext->DeclareAspect("GameClientL", eEA_GameClientL, eAF_Delegatable);
  223.         m_pNetContext->DeclareAspect("GameClientM", eEA_GameClientM, eAF_Delegatable);
  224.         m_pNetContext->DeclareAspect("GameClientN", eEA_GameClientN, eAF_Delegatable | eAF_ServerControllerOnly);
  225.         m_pNetContext->DeclareAspect("GameClientO", eEA_GameClientO, eAF_Delegatable);
  226.         m_pNetContext->DeclareAspect("GameClientP", eEA_GameClientP, eAF_Delegatable);
  227.         m_pNetContext->DeclareAspect("GameServerE", eEA_GameServerE, 0);
  228.  
  229.         //m_pNetContext->RegisterServerControlledFile("Game/motd.txt");
  230.         //m_pNetContext->RegisterServerControlledFile("Game/Libs/ActionGraphs/yawn.xml");
  231. }
  232.  
  233. void CGameContext::SetContextInfo(unsigned flags, uint16 port, const char* connectionString)
  234. {
  235.         m_flags = flags;
  236.         m_port = port;
  237.         m_connectionString = connectionString;
  238.  
  239.         if (!(flags & eGSF_LocalOnly))
  240.                 m_pBreakReplicator.reset(new CBreakReplicator(this));
  241.  
  242. #ifndef OLD_VOICE_SYSTEM_DEPRECATED
  243.         if (!gEnv->IsDedicated())
  244.         {
  245.                 m_pVoiceController = new CVoiceController(this);
  246.                 if (!m_pVoiceController->Init())
  247.                 {
  248.                         delete m_pVoiceController;
  249.                         m_pVoiceController = NULL;
  250.                 }
  251.                 else
  252.                         m_pVoiceController->Enable(m_pFramework->IsVoiceRecordingEnabled());
  253.         }
  254. #endif
  255. }
  256.  
  257. //
  258. // IGameContext
  259. //
  260.  
  261. void CGameContext::AddLoadLevelTasks(IContextEstablisher* pEst, bool isServer, int flags, bool** ppLoadingStarted, int establishedToken, bool bChannelIsMigrating)
  262. {
  263.         bool usingLobbyHints = false;
  264.  
  265.         ICryLobby* pLobby = gEnv->pNetwork->GetLobby();
  266.         if (pLobby && gEnv->bMultiplayer)
  267.         {
  268.                 const char* pLevelName = pLobby->GetCryEngineLevelNameHint();
  269.                 const char* pRulesName = pLobby->GetCryEngineRulesNameHint();
  270.                 if (strlen(pLevelName) != 0 && strlen(pRulesName) != 0)
  271.                 {
  272.                         usingLobbyHints = true;
  273.                 }
  274.         }
  275.  
  276.         if (!bChannelIsMigrating)
  277.         {
  278.                 if (gEnv->IsClient() && (flags & eEF_LoadNewLevel) == 0)
  279.                 {
  280.                         AddActionEvent(pEst, eCVS_Begin, eAE_resetBegin);
  281.                         AddActionEvent(pEst, eCVS_Begin, SActionEvent(eAE_resetProgress, 0));
  282.                 }
  283.  
  284.                 const bool loadingNewLevel = (flags & eEF_LoadNewLevel) != 0;
  285.                 if (flags & eEF_LevelLoaded)
  286.                 {
  287.                         AddRandomSystemReset(pEst, eCVS_Begin, loadingNewLevel);
  288.                 }
  289.                 if (flags & eEF_LoadNewLevel)
  290.                 {
  291.                         AddPrepareLevelLoad(pEst, usingLobbyHints ? eCVS_Initial : eCVS_Begin);
  292.                 }
  293.                 if (flags & eEF_LevelLoaded)
  294.                 {
  295.                         bool resetSkipPlayers = false && ((flags & eEF_LoadNewLevel) == 0) && isServer;
  296.                         bool resetSkipGamerules = ((flags & eEF_LoadNewLevel) == 0);
  297.                         AddEntitySystemReset(pEst, eCVS_Begin, resetSkipPlayers, resetSkipGamerules);
  298.                 }
  299.                 if (flags & eEF_LoadNewLevel)
  300.                         AddClearPlayerIds(pEst, eCVS_Begin);
  301.                 AddSetValue(pEst, usingLobbyHints ? eCVS_Initial : eCVS_EstablishContext, &m_isInLevelLoad, true, "BeginLevelLoad");
  302.                 AddInitImmersiveness(pEst, eCVS_EstablishContext);
  303.                 if (flags & eEF_LoadNewLevel)
  304.                 {
  305.                         //              We used to add a task create the game rules here using AddGameRulesCreation.
  306.                         //              That has moved into the LoadLevel task as of 25/5/10 - peter.
  307.                         AddLoadLevel(pEst, usingLobbyHints ? eCVS_Initial : eCVS_EstablishContext, ppLoadingStarted);
  308.                 }
  309.                 else
  310.                 {
  311.                         AddFakeSpawn(pEst, eCVS_EstablishContext, eFS_GameRules | eFS_Opt_Rebind);
  312.                         AddLoadLevelEntities(pEst, eCVS_EstablishContext);
  313.                         /*
  314.                            if (isServer)
  315.                            {
  316.                             AddSetValue( pEst, eCVS_EstablishContext, &m_isInLevelLoad, false, "PauseLevelLoad" );
  317.                             AddFakeSpawn( pEst, eCVS_EstablishContext, eFS_Players | eFS_Opt_Rebind );
  318.                             AddSetValue( pEst, eCVS_EstablishContext, &m_isInLevelLoad, true, "RestartLevelLoad" );
  319.                            }
  320.                          */
  321.                 }
  322.  
  323.                 // Only reset areas right after the level loading task!
  324.                 if (!gEnv->IsEditor() && gEnv->pSystem->IsSerializingFile() != 2)
  325.                 {
  326.                         AddResetAreas(pEst, usingLobbyHints ? eCVS_Initial : eCVS_EstablishContext);
  327.                 }
  328.  
  329.                 AddSetValue(pEst, eCVS_EstablishContext, &m_isInLevelLoad, false, "EndLevelLoad");
  330.                 AddEstablishedContext(pEst, eCVS_EstablishContext, establishedToken);
  331.                 AddLockResources(pEst, eCVS_Begin, gEnv->IsEditor() ? eCVS_PostSpawnEntities : eCVS_InGame, this);
  332.         }
  333. }
  334.  
  335. void CGameContext::AddLoadingCompleteTasks(IContextEstablisher* pEst, int flags, bool* pLoadingStarted, bool bChannelIsMigrating)
  336. {
  337.         if (HasContextFlag(eGSF_Server) && !bChannelIsMigrating)
  338.         {
  339.                 AddPauseGame(pEst, eCVS_Begin, true, false);
  340.         }
  341.  
  342.         if (!bChannelIsMigrating)
  343.         {
  344.                 if (flags & eEF_LoadNewLevel)
  345.                 {
  346.                         SEntityEvent startLevelEvent(ENTITY_EVENT_START_LEVEL);
  347.                         AddEntitySystemEvent(pEst, eCVS_InGame, startLevelEvent);
  348.                 }
  349.  
  350.                 if (!gEnv->IsEditor() && gEnv->pSystem->IsSerializingFile() != 2) /*  && (flags&eEF_LoadNewLevel)==0) */
  351.                 {
  352.                         AddResetAreas(pEst, eCVS_InGame);
  353.                 }
  354.  
  355.                 if ((flags & eEF_LoadNewLevel) == 0)
  356.                 {
  357.                         AddGameRulesReset(pEst, eCVS_InGame);
  358.                 }
  359.  
  360.                 if (!gEnv->IsEditor() && (flags & eEF_LoadNewLevel))
  361.                 {
  362.                         AddLoadingComplete(pEst, eCVS_InGame, pLoadingStarted);
  363.                 }
  364.  
  365.                 if (HasContextFlag(eGSF_Server))
  366.                 {
  367.                         AddPauseGame(pEst, eCVS_InGame, false, false);
  368.                 }
  369.         }
  370.  
  371.         AddWaitForPrecachingToFinish(pEst, eCVS_InGame, &m_bStarted);
  372.  
  373.         if (!bChannelIsMigrating)
  374.         {
  375.                 if (HasContextFlag(eGSF_Client))
  376.                 {
  377.                         if (CGameClientNub* pGCN = CCryAction::GetCryAction()->GetGameClientNub())
  378.                         {
  379.                                 if (CGameClientChannel* pGCC = pGCN->GetGameClientChannel())
  380.                                 {
  381.                                         pGCC->AddUpdateLevelLoaded(pEst);
  382.                                 }
  383.                         }
  384.                 }
  385.  
  386.                 AddLockResources(pEst, eCVS_Begin, gEnv->IsEditor() ? eCVS_PostSpawnEntities : eCVS_InGame, this);
  387.         }
  388. }
  389.  
  390. class CCET_WaitForPendingConnections : public CCET_Base
  391. {
  392. public:
  393.         const char* GetName() { return ""; }
  394.  
  395.         enum EWaitState
  396.         {
  397.                 EW_INITIAL_TICK,
  398.                 EW_WAIT_FOR_PENDING,
  399.                 EW_WAIT_UNTIL_CONNECTED
  400.         };
  401.  
  402. #define DEFAULT_WAIT_LENGTH    (10.f)
  403. #define NEW_CLIENT_WAIT_LENGTH (5.f)
  404.  
  405.         CCET_WaitForPendingConnections(CActionGame* cag, CCryAction* cca) : m_state(EW_INITIAL_TICK), m_cag(cag), m_cca(cca), m_start(0.f), m_prevNumConnections(0), m_waitLen(DEFAULT_WAIT_LENGTH) {}
  406.  
  407.         EContextEstablishTaskResult OnStep(SContextEstablishState& state)
  408.         {
  409.                 if (m_cag->GetServerNetNub())
  410.                 {
  411.                         bool havePendingConnections = m_cag->GetServerNetNub()->HasPendingConnections();
  412.  
  413.                         if (m_state == EW_INITIAL_TICK)
  414.                         {
  415.                                 m_start = gEnv->pTimer->GetAsyncTime();
  416.                                 m_state = EW_WAIT_FOR_PENDING;
  417.                         }
  418.  
  419.                         float diff = (gEnv->pTimer->GetAsyncTime() - m_start).GetSeconds();
  420.  
  421.                         switch (m_state)
  422.                         {
  423.                         case EW_WAIT_FOR_PENDING:
  424.                                 CryLog("CEst -- Waiting until we have pending connections!");
  425.                                 if (havePendingConnections)
  426.                                 {
  427.                                         CryLog("CEst -- We now have pending connections!");
  428.                                         m_state = EW_WAIT_UNTIL_CONNECTED;
  429.                                 }
  430.                                 break;
  431.  
  432.                         case EW_WAIT_UNTIL_CONNECTED:
  433.                                 {
  434.                                         IGameSessionHandler* gsh = m_cca->GetIGameSessionHandler();
  435.                                         int numExpected = 1;
  436.  
  437.                                         if (gsh)
  438.                                         {
  439.                                                 numExpected = gsh->GetNumberOfExpectedClients();
  440.                                         }
  441.  
  442.                                         int numChannels = m_cag->GetServerNetNub()->GetNumChannels();
  443.  
  444.                                         if (numChannels > m_prevNumConnections)
  445.                                         {
  446.                                                 m_prevNumConnections = numChannels;
  447.                                                 // wait for this client to tick through states
  448.                                                 m_waitLen = max(m_waitLen, (diff + NEW_CLIENT_WAIT_LENGTH));
  449.                                         }
  450.  
  451.                                         //CryLog("CEst -- num channels %d, expecting %d!", numChannels, numExpected);
  452.  
  453.                                         if (numChannels >= numExpected && !havePendingConnections)
  454.                                         {
  455.                                                 CryLog("CEst -- We have NO pending connections remaining!");
  456.                                                 //m_start = gEnv->pTimer->GetAsyncTime();
  457.                                                 return eCETR_Ok;
  458.                                         }
  459.                                         break;
  460.                                 }
  461.                         }
  462.  
  463.                         if (diff < m_waitLen)
  464.                                 return eCETR_Wait;
  465.                         else
  466.                                 CryLog("CEst -- Waited more than %f seconds, continuing...", m_waitLen);
  467.                 }
  468.  
  469.                 CryLog("CEst -- No pending connections, we have a go!");
  470.                 return eCETR_Ok;
  471.         }
  472.  
  473. private:
  474.         EWaitState   m_state;
  475.         CActionGame* m_cag;
  476.         CCryAction*  m_cca;
  477.         CTimeValue   m_start;
  478.         int          m_prevNumConnections;
  479.         float        m_waitLen;
  480. };
  481.  
  482. void AddWaitForPendingConnections(IContextEstablisher* pEst, EContextViewState state, CActionGame* cag, CCryAction* cca)
  483. {
  484.         if (gEnv->bMultiplayer)
  485.         {
  486.                 //pEst->AddTask(state, new CCET_WaitForPendingConnections(cag, cca));
  487.         }
  488. }
  489.  
  490. bool CGameContext::InitGlobalEstablishmentTasks(IContextEstablisher* pEst, int establishedToken)
  491. {
  492.         AddLockResources(pEst, eCVS_Begin, gEnv->IsEditor() ? eCVS_PostSpawnEntities : eCVS_InGame, this);
  493.         AddSetValue(pEst, eCVS_Begin, &m_bStarted, false, "GameNotStarted");
  494.         AddWaitForPendingConnections(pEst, eCVS_Begin, m_pGame, m_pFramework);
  495.         if (gEnv->IsEditor())
  496.         {
  497.                 AddEstablishedContext(pEst, eCVS_EstablishContext, establishedToken);
  498.                 AddFakeSpawn(pEst, eCVS_EstablishContext, eFS_All);
  499.         }
  500.         else if (HasContextFlag(eGSF_Server))
  501.         {
  502.                 bool* pLoadingStarted = 0;
  503.                 AddLoadLevelTasks(pEst, true, m_loadFlags, &pLoadingStarted, establishedToken, false);
  504.                 // here is the special handling for playing back a demo session in dedicated mode - both eGSF_Server and eGSF_Client are specified,
  505.                 // but we need to perform LoadingCompleteTasks while skipping all the channel establishment tasks
  506.                 if (gEnv->IsDedicated() || !HasContextFlag(eGSF_Client))
  507.                         AddLoadingCompleteTasks(pEst, m_loadFlags, pLoadingStarted, false);
  508.                 if (HasContextFlag(eGSF_Server))
  509.                 {
  510.                         SEntityEvent startGameEvent(ENTITY_EVENT_START_GAME);
  511.                         AddEntitySystemEvent(pEst, eCVS_InGame, startGameEvent);
  512.                 }
  513.         }
  514.         return true;
  515. }
  516.  
  517. bool CGameContext::InitChannelEstablishmentTasks(IContextEstablisher* pEst, INetChannel* pChannel, int establishedSerial)
  518. {
  519.         // local channels on a dedicated server are dummy connection for dedicated server demo recording
  520.         // skip all the channel establishment tasks (esp. player spawning and setup - OnClientConnect/EnteredGame)
  521.         if (gEnv->IsDedicated() && pChannel->IsLocal())
  522.                 return true;
  523.  
  524.         // for DemoPlayback, we want the local player spawned as a spectator for the demo session, so
  525.         // the normal channel establishment tasks are needed
  526.  
  527.         bool isLocal = pChannel->IsLocal();
  528.         bool isServer = ((CGameChannel*)pChannel->GetGameChannel())->IsServer();
  529.         bool isClient = !isServer;
  530.         bool isLevelLoaded = false;
  531.         bool bIsChannelMigrating = pChannel->IsMigratingChannel();
  532.  
  533.         CGameServerChannel* pServerChannel = 0;
  534.         if (isServer)
  535.         {
  536.                 pServerChannel = (CGameServerChannel*)pChannel->GetGameChannel();
  537.                 isLevelLoaded = pServerChannel->CheckLevelLoaded();
  538.         }
  539.         else
  540.         {
  541.                 if (CGameClientNub* pGCN = CCryAction::GetCryAction()->GetGameClientNub())
  542.                         if (CGameClientChannel* pGCC = pGCN->GetGameClientChannel())
  543.                                 isLevelLoaded = pGCC->CheckLevelLoaded();
  544.         }
  545.  
  546.         bool isReset = stl::member_find_and_erase(m_resetChannels, pChannel);
  547.  
  548.         if (isReset && !isLevelLoaded)
  549.                 isReset = false;
  550.  
  551.         int flags = (isLevelLoaded ? eEF_LevelLoaded : 0) | (isReset ? 0 : eEF_LoadNewLevel);
  552.  
  553.         if (CCryActionCVars::Get().g_syncClassRegistry)
  554.         {
  555.                 if (isServer && !isReset && (0 == (flags & eEF_LevelLoaded)))
  556.                 {
  557.                         AddRegisterAllClasses(pEst, eCVS_Begin, &m_classRegistry);
  558.                 }
  559.         }
  560.  
  561.         // please keep the following bare minimum channel establishment tasks first, since DemoRecorderChannel will make
  562.         // an early out right after these
  563.         if (isServer && !isLocal)
  564.         {
  565.                 if (!isReset)
  566.                 {
  567.                         std::vector<SSendableHandle>* pWaitFor = 0;
  568.                         if (0 == (flags & eEF_LevelLoaded))
  569.                         {
  570.                                 // Don't send all the cvar's again - makes it ages to join a network game
  571.                                 // Might want to do this on a PC build - need to discuss it
  572. #if ENABLE_CVARS_FLUSHING
  573.                                 AddCVarSync(pEst, eCVS_Begin, static_cast<CGameServerChannel*>(pChannel->GetGameChannel()));
  574. #endif
  575.                                 if (CCryActionCVars::Get().g_syncClassRegistry)
  576.                                 {
  577.                                         AddSendClassRegistration(pEst, eCVS_Begin, &m_classRegistry, &pWaitFor);
  578.                                 }
  579.                                 else
  580.                                 {
  581.                                         AddSendClassHashRegistration(pEst, eCVS_Begin, &m_classRegistry, &pWaitFor);
  582.                                 }
  583.                         }
  584.                         if (!bIsChannelMigrating)
  585.                         {
  586.                                 AddSendGameType(pEst, eCVS_Begin, &m_classRegistry, pWaitFor);
  587.                         }
  588.                 }
  589.                 else
  590.                 {
  591.                         //AddSendResetMap( pEst, eCVS_Begin );
  592.                 }
  593.         }
  594.  
  595.         pChannel->AddWaitForFileSyncComplete(pEst, eCVS_Begin);
  596.  
  597.         // do NOT add normal channel establishment tasks here, otherwise it breaks DemoRecorder
  598.  
  599. #if defined(GAME_CHANNEL_SYNC_CLIENT_SERVER_TIME)
  600.         if (isClient)
  601.         {
  602.                 AddClientTimeSync(pEst, eCVS_Begin);
  603.         }
  604. #endif
  605.  
  606.         // should skip all other channel establishment tasks for DemoRecorderChannel (local channel ID is 0)
  607.         if (pChannel->GetLocalChannelID() == 0)
  608.                 return true;
  609.  
  610.         // add normal channel establishment tasks here
  611.  
  612.         AddLockResources(pEst, eCVS_Begin, gEnv->IsEditor() ? eCVS_PostSpawnEntities : eCVS_InGame, this);
  613.  
  614.         if (isServer)
  615.         {
  616.                 if (gEnv->IsEditor())
  617.                         AddWaitValue(pEst, eCVS_PostSpawnEntities, &m_bAllowSendClientConnect, true, "WaitForAllowSendClientConnect", 20.0f);
  618.                 AddOnClientConnect(pEst, eCVS_PostSpawnEntities, isReset);
  619.                 AddOnClientEnteredGame(pEst, eCVS_InGame, isReset);
  620.                 if (pServerChannel->IsOnHold())
  621.                         AddClearOnHold(pEst, eCVS_InGame);
  622.  
  623.                 AddDelegateAuthorityToClientActor(pEst, eCVS_InGame);
  624.         }
  625.  
  626.         bool* pLoadingStarted = 0;
  627.         if (isClient && !HasContextFlag(eGSF_Server))
  628.         {
  629.                 AddLoadLevelTasks(pEst, false, flags, &pLoadingStarted, establishedSerial, bIsChannelMigrating);
  630.         }
  631.  
  632.         if (isClient)
  633.                 AddLoadingCompleteTasks(pEst, flags, pLoadingStarted, bIsChannelMigrating);
  634.  
  635.         if (isClient && !HasContextFlag(eGSF_Server))
  636.         {
  637.                 SEntityEvent startGameEvent(ENTITY_EVENT_START_GAME);
  638.                 AddEntitySystemEvent(pEst, eCVS_InGame, startGameEvent);
  639.         }
  640.  
  641.         if (isClient && !gEnv->IsEditor() && !gEnv->bMultiplayer && !(m_flags & eGSF_DemoPlayback))
  642.                 AddInitialSaveGame(pEst, eCVS_InGame);
  643.  
  644.         if (isClient)
  645.         {
  646.                 if (isReset)
  647.                 {
  648.                         for (int i = eCVS_EstablishContext; i < eCVS_PostSpawnEntities; i++)
  649.                                 AddActionEvent(pEst, eCVS_Begin, SActionEvent(eAE_resetProgress, 100 * (i - eCVS_EstablishContext) / (eCVS_PostSpawnEntities - eCVS_EstablishContext)));
  650.                         AddActionEvent(pEst, eCVS_InGame, eAE_resetEnd);
  651.                 }
  652.                 else
  653.                 {
  654.                         AddSetValue(pEst, eCVS_InGame, &m_broadcastActionEventInGame, 4, "BroadcastInGame");
  655.                 }
  656.         }
  657.  
  658.         // AlexL: Unpause the Game when Editor is started, but no Level isLevelLoaded
  659.         //        this ensures that CTimer's ETIMER_GAME is updated and systems relying
  660.         //        on it work correctly (CharEditor)
  661.         if (gEnv->IsEditor() && HasContextFlag(eGSF_Server))
  662.                 AddPauseGame(pEst, eCVS_Begin, false, false);
  663.  
  664.         if (pServerChannel)
  665.                 pServerChannel->AddUpdateLevelLoaded(pEst);
  666.  
  667.         return true;
  668. }
  669.  
  670. void CGameContext::ResetMap(bool isServer)
  671. {
  672.         if (m_pBreakReplicator.get())
  673.                 m_pBreakReplicator->Reset();
  674.  
  675.         if (!isServer && HasContextFlag(eGSF_Server))
  676.                 return;
  677.  
  678.         m_loadFlags = EstablishmentFlags_ResetMap;
  679.         m_resetChannels.clear();
  680.  
  681.         if (CGameClientNub* pGCN = CCryAction::GetCryAction()->GetGameClientNub())
  682.                 if (CGameClientChannel* pGCC = pGCN->GetGameClientChannel())
  683.                         m_resetChannels.insert(pGCC->GetNetChannel());
  684.  
  685.         if (CGameServerNub* pGSN = CCryAction::GetCryAction()->GetGameServerNub())
  686.                 if (TServerChannelMap* m = pGSN->GetServerChannelMap())
  687.                         for (TServerChannelMap::iterator iter = m->begin(); iter != m->end(); ++iter)
  688.                         {
  689.                                 if (iter->second->GetNetChannel())//channel can be on hold thus not having net channel currently
  690.                                 {
  691.                                         CGameClientChannel::SendResetMapWith(SNoParams(), iter->second->GetNetChannel());
  692.                                         m_resetChannels.insert(iter->second->GetNetChannel());
  693.                                 }
  694.                         }
  695.  
  696.         if (isServer)
  697.                 m_pNetContext->ChangeContext();
  698. }
  699.  
  700. /*
  701.    void CGameContext::EndContext()
  702.    {
  703.    // TODO: temporary
  704.    IActionMap* pActionMap = 0;
  705.    IPlayerProfileManager* pPPMgr = m_pFramework->GetIPlayerProfileManager();
  706.    if (pPPMgr)
  707.    {
  708.     int userCount = pPPMgr->GetUserCount();
  709.     if (userCount > 0)
  710.     {
  711.       IPlayerProfileManager::SUserInfo info;
  712.       pPPMgr->GetUserInfo(0, info);
  713.       IPlayerProfile* pProfile = pPPMgr->GetCurrentProfile(info.userId);
  714.       if (pProfile)
  715.       {
  716.         pActionMap = pProfile->GetActionMap("default");
  717.         if (pActionMap == 0)
  718.           GameWarning("[PlayerProfiles] CGameContext::EndContext: User '%s' has no actionmap 'default'!", info.userId);
  719.       }
  720.       else
  721.         GameWarning("[PlayerProfiles] CGameContext::EndContext: User '%s' has no active profile!", info.userId);
  722.     }
  723.     else
  724.     {
  725.       ;
  726.       // GameWarning("[PlayerProfiles] CGameContext::EndContext: No users logged in");
  727.     }
  728.    }
  729.  
  730.    if (pActionMap == 0)
  731.    {
  732.     // use action map without any profile stuff
  733.     IActionMapManager * pActionMapMan = m_pFramework->GetIActionMapManager();
  734.     if (pActionMapMan)
  735.     {
  736.       pActionMap = pActionMapMan->GetActionMap("default");
  737.     }
  738.    }
  739.  
  740.    if (pActionMap)
  741.     pActionMap->SetActionListener(0);
  742.    // ~TODO: temporary
  743.  
  744.    if (!HasContextFlag(eGSF_NoGameRules))
  745.    {
  746.     m_pEntitySystem->Reset();
  747.     for (int i=0; i<64; i++)
  748.       m_pEntitySystem->ReserveEntityId(LOCAL_PLAYER_ENTITY_ID+i);
  749.     if (CGameClientNub * pClientNub = m_pFramework->GetGameClientNub())
  750.       if (CGameClientChannel * pClientChannel = pClientNub->GetGameClientChannel())
  751.         pClientChannel->ClearPlayer();
  752.    }
  753.  
  754.    m_classRegistry.Reset();
  755.    m_controlledObjects.Reset( m_pFramework->IsServer() );
  756.    }
  757.  */
  758.  
  759. void CGameContext::LockResources()
  760. {
  761.         /*
  762.            if (1 == ++m_resourceLocks)
  763.            {
  764.            gEnv->p3DEngine->LockCGFResources();
  765.            gEnv->pCharacterManager->LockResources();
  766.            gEnv->pSoundSystem->LockResources();
  767.            }
  768.          */
  769. }
  770.  
  771. void CGameContext::UnlockResources()
  772. {
  773.         /*
  774.            if (0 == --m_resourceLocks)
  775.            {
  776.            gEnv->p3DEngine->UnlockCGFResources();
  777.            gEnv->pCharacterManager->UnlockResources();
  778.            gEnv->pSoundSystem->UnlockResources();
  779.            }
  780.          */
  781. }
  782.  
  783. bool CGameContext::HasSpawnPoint()
  784. {
  785.         IEntityItPtr pIt = gEnv->pEntitySystem->GetEntityIterator();
  786.  
  787.         pIt->MoveFirst();
  788.         while (!pIt->IsEnd())
  789.         {
  790.                 if (IEntity* pEntity = pIt->Next())
  791.                         if (0 == strcmp(pEntity->GetClass()->GetName(), "SpawnPoint"))
  792.                                 return true;
  793.         }
  794.         return false;
  795. }
  796.  
  797. void CGameContext::CallOnSpawnComplete(IEntity* pEntity)
  798. {
  799.         IScriptTable* pScriptTable(pEntity->GetScriptTable());
  800.         if (!pScriptTable)
  801.                 return;
  802.  
  803.         if (gEnv->bServer)
  804.         {
  805.                 SmartScriptTable server;
  806.                 if (pScriptTable->GetValue("Server", server))
  807.                 {
  808.                         if ((server->GetValueType("OnSpawnComplete") == svtFunction) && pScriptTable->GetScriptSystem()->BeginCall(server, "OnSpawnComplete"))
  809.                         {
  810.                                 pScriptTable->GetScriptSystem()->PushFuncParam(pScriptTable);
  811.                                 pScriptTable->GetScriptSystem()->EndCall();
  812.                         }
  813.                 }
  814.         }
  815.  
  816.         if (gEnv->IsClient())
  817.         {
  818.                 SmartScriptTable client;
  819.                 if (pScriptTable->GetValue("Client", client))
  820.                 {
  821.                         if ((client->GetValueType("OnSpawnComplete") == svtFunction) && pScriptTable->GetScriptSystem()->BeginCall(client, "OnSpawnComplete"))
  822.                         {
  823.                                 pScriptTable->GetScriptSystem()->PushFuncParam(pScriptTable);
  824.                                 pScriptTable->GetScriptSystem()->EndCall();
  825.                         }
  826.                 }
  827.         }
  828. }
  829.  
  830. uint8 CGameContext::GetDefaultProfileForAspect(EntityId id, NetworkAspectType aspectID)
  831. {
  832.         IEntity* pEntity = m_pEntitySystem->GetEntity(id);
  833.         if (!pEntity)
  834.         {
  835.                 if (!gEnv->IsEditor())
  836.                         GameWarning("Trying to get default profile for aspect %d on unknown entity %d", aspectID, id);
  837.                 return ~uint8(0);
  838.         }
  839.  
  840.         IEntityComponent* pProxy = pEntity->GetProxy(ENTITY_PROXY_USER);
  841.         if (pProxy)
  842.         {
  843.                 CGameObject* pGameObject = (CGameObject*)pProxy;
  844.                 return pGameObject->GetDefaultProfile((EEntityAspects)aspectID);
  845.         }
  846.         return 0;
  847. }
  848.  
  849. static uint32 GetLowResSpacialCoord(float x)
  850. {
  851.         return (uint32)(x / 0.75f);
  852. }
  853.  
  854. static uint32 GetLowResAngle(float x)
  855. {
  856.         return (uint32)(180.0f * x / gf_PI / 10);
  857. }
  858.  
  859. uint32 CGameContext::HashAspect(EntityId entityId, NetworkAspectType nAspect)
  860. {
  861.         IEntity* pEntity = m_pEntitySystem->GetEntity(entityId);
  862.         if (!pEntity)
  863.         {
  864.                 if (!gEnv->IsEditor())
  865.                         GameWarning("Trying to hash non-existant entity %d", entityId);
  866.                 return 0;
  867.         }
  868.  
  869.         switch (nAspect)
  870.         {
  871.         case eEA_Physics:
  872.                 {
  873.                         pe_status_pos p;
  874.                         IPhysicalEntity* pPhys = pEntity->GetPhysics();
  875.                         if (!pPhys)
  876.                                 break;
  877.                         pPhys->GetStatus(&p);
  878.                         static const int MULTIPLIER = 16;
  879.                         static const uint32 MASK = 0xf;
  880.                         uint32 hash = 0;
  881.                         hash = MULTIPLIER * hash + (GetLowResSpacialCoord(p.pos.x) & MASK);
  882.                         hash = MULTIPLIER * hash + (GetLowResSpacialCoord(p.pos.y) & MASK);
  883.                         hash = MULTIPLIER * hash + (GetLowResSpacialCoord(p.pos.z) & MASK);
  884.                         Ang3 angles(p.q);
  885.                         hash = MULTIPLIER * hash + (GetLowResAngle(angles.x) & MASK);
  886.                         hash = MULTIPLIER * hash + (GetLowResAngle(angles.y) & MASK);
  887.                         hash = MULTIPLIER * hash + (GetLowResAngle(angles.z) & MASK);
  888.                         return hash;
  889.                 }
  890.                 break;
  891.         }
  892.  
  893.         return 0;
  894. }
  895.  
  896. ESynchObjectResult CGameContext::SynchObject(EntityId entityId, NetworkAspectType nAspect, uint8 profile, TSerialize serialize, bool verboseLogging)
  897. {
  898.         IEntity* pEntity = m_pEntitySystem->GetEntity(entityId);
  899.         if (!pEntity)
  900.         {
  901.                 if (!gEnv->IsEditor())
  902.                         GameWarning("Trying to synchronize non-existent entity %d", entityId);
  903.                 return eSOR_Failed;
  904.         }
  905.  
  906.         if (gEnv->bServer && serialize.IsReading() && (m_pNetContext->DelegatableAspects() & nAspect) && !(m_pNetContext->ServerControllerOnlyAspects() & nAspect))
  907.         {
  908.                 NET_PROFILE_COUNT_READ_BITS(true);
  909.         }
  910.         NET_PROFILE_SCOPE(pEntity->GetClass()->GetName(), serialize.IsReading());
  911.         NET_PROFILE_SCOPE(pEntity->GetName(), serialize.IsReading());
  912.  
  913.         switch (nAspect)
  914.         {
  915.         case eEA_GameClientStatic:
  916.         case eEA_GameServerStatic:
  917.         case eEA_GameClientDynamic:
  918.         case eEA_GameServerDynamic:
  919.         case eEA_GameClientA:
  920.         case eEA_GameServerA:
  921.         case eEA_GameClientB:
  922.         case eEA_GameServerB:
  923.         case eEA_GameClientC:
  924.         case eEA_GameServerC:
  925.         case eEA_GameClientD:
  926.         case eEA_GameClientE:
  927.         case eEA_GameClientF:
  928.         case eEA_GameClientG:
  929.         case eEA_GameClientH:
  930.         case eEA_GameClientI:
  931.         case eEA_GameClientJ:
  932.         case eEA_GameServerD:
  933.         case eEA_GameClientK:
  934.         case eEA_GameClientL:
  935.         case eEA_GameClientM:
  936.         case eEA_GameClientN:
  937.         case eEA_GameClientO:
  938.         case eEA_GameClientP:
  939.         case eEA_GameServerE:
  940.         case eEA_Aspect31:
  941.                 {
  942.                         IEntityComponent* pProxy = pEntity->GetProxy(ENTITY_PROXY_USER);
  943.                         if (!pProxy)
  944.                         {
  945.                                 if (verboseLogging)
  946.                                         GameWarning("CGameContext::SynchObject: No user proxy with eEA_GameObject");
  947.                                 NET_PROFILE_COUNT_READ_BITS(false);
  948.                                 return eSOR_Failed;
  949.                         }
  950.  
  951.                         NET_PROFILE_SCOPE("NetSerialize", serialize.IsReading());
  952.  
  953.                         CGameObject* pGameObject = (CGameObject*)pProxy;
  954.                         if (!pGameObject->NetSerialize(serialize, (EEntityAspects)nAspect, profile, 0))
  955.                         {
  956.                                 if (verboseLogging)
  957.                                         GameWarning("CGameContext::SynchObject: game fails to serialize aspect %d on profile %d", BitIndex(nAspect), int(profile));
  958.                                 NET_PROFILE_COUNT_READ_BITS(false);
  959.                                 return eSOR_Failed;
  960.                         }
  961.                 }
  962.                 break;
  963.         case eEA_Physics:
  964.                 {
  965.                         int pflags = 0;
  966.                         if (m_pPhysicsSync && serialize.IsReading())
  967.                         {
  968.                                 if (m_pPhysicsSync->IgnoreSnapshot())
  969.                                 {
  970.                                         NET_PROFILE_COUNT_READ_BITS(false);
  971.                                         return eSOR_Skip;
  972.                                 }
  973.                                 else if (m_pPhysicsSync->NeedToCatchup())
  974.                                 {
  975.                                         pflags |= ssf_compensate_time_diff;
  976.                                 }
  977.                         }
  978.                         IEntityComponent* pProxy = pEntity->GetProxy(ENTITY_PROXY_USER);
  979.                         if (pProxy)
  980.                         {
  981.                                 NET_PROFILE_SCOPE("NetSerialize", serialize.IsReading());
  982.  
  983.                                 CGameObject* pGameObject = (CGameObject*)pProxy;
  984.                                 if (!pGameObject->NetSerialize(serialize, eEA_Physics, profile, pflags))
  985.                                 {
  986.                                         if (verboseLogging)
  987.                                                 GameWarning("CGameContext::SynchObject: game fails to serialize physics aspect on profile %d", int(profile));
  988.                                         NET_PROFILE_COUNT_READ_BITS(false);
  989.                                         return eSOR_Failed;
  990.                                 }
  991.                         }
  992.                         else
  993.                         {
  994.                                 pEntity->PhysicsNetSerialize(serialize);
  995.                         }
  996.                         if (m_pPhysicsSync && serialize.IsReading() && serialize.ShouldCommitValues())
  997.                                 m_pPhysicsSync->UpdatedEntity(entityId);
  998.                 }
  999.                 break;
  1000.         case eEA_Script:
  1001.                 {
  1002.                         IEntityScriptComponent* pScriptProxy = static_cast<IEntityScriptComponent*>(pEntity->GetProxy(ENTITY_PROXY_SCRIPT));
  1003.                         if (pScriptProxy)
  1004.                         {
  1005.                                 NET_PROFILE_SCOPE("ScriptProxy", serialize.IsReading());
  1006.                                 pScriptProxy->GameSerialize(serialize);
  1007.                         }
  1008.  
  1009.                         NET_PROFILE_SCOPE("ScriptRMI", serialize.IsReading());
  1010.                         if (!m_pScriptRMI->SerializeScript(serialize, pEntity))
  1011.                         {
  1012.                                 if (verboseLogging)
  1013.                                         GameWarning("CGameContext::SynchObject: failed to serialize script aspect");
  1014.                                 NET_PROFILE_COUNT_READ_BITS(false);
  1015.                                 return eSOR_Failed;
  1016.                         }
  1017.                 }
  1018.                 break;
  1019.         default:
  1020.                 ;
  1021.                 //              GameWarning("Unknown aspect %d", nAspect);
  1022.                 //              NET_PROFILE_COUNT_READ_BITS(false);
  1023.                 //              return false;
  1024.         }
  1025.         NET_PROFILE_COUNT_READ_BITS(false);
  1026.         return eSOR_Ok;
  1027. }
  1028.  
  1029. bool CGameContext::SetAspectProfile(EntityId id, NetworkAspectType aspectBit, uint8 profile)
  1030. {
  1031.         IEntity* pEntity = m_pEntitySystem->GetEntity(id);
  1032.         if (!pEntity)
  1033.         {
  1034.                 GameWarning("Trying to set the profile of a non-existant entity %d", id);
  1035.                 return true;
  1036.         }
  1037.  
  1038.         CRY_ASSERT(0 == (aspectBit & (aspectBit - 1)));
  1039.  
  1040.         IEntityComponent* pProxy = pEntity->GetProxy(ENTITY_PROXY_USER);
  1041.         if (pProxy)
  1042.         {
  1043.                 CGameObject* pGameObject = (CGameObject*)pProxy;
  1044.                 if (pGameObject->SetAspectProfile((EEntityAspects)aspectBit, profile, true))
  1045.                         return true;
  1046.         }
  1047.         return false;
  1048. }
  1049.  
  1050. class CSpawnMsg : public INetSendableHook, private SBasicSpawnParams
  1051. {
  1052. public:
  1053.         CSpawnMsg(const SBasicSpawnParams& params, ISerializableInfoPtr pObj) :
  1054.                 INetSendableHook(),
  1055.                 SBasicSpawnParams(params),
  1056.                 m_pObj(pObj) {}
  1057.  
  1058.         EMessageSendResult Send(INetSender* pSender)
  1059.         {
  1060.                 pSender->BeginMessage(CGameClientChannel::DefaultSpawn);
  1061. #if RESERVE_UNBOUND_ENTITIES
  1062.                 pSender->ser.Value("partialNetID", m_partialNetID, 'eid');
  1063. #endif
  1064.                 SBasicSpawnParams::SerializeWith(pSender->ser);
  1065.                 if (m_pObj)
  1066.                         m_pObj->SerializeWith(pSender->ser);
  1067.                 return eMSR_SentOk;
  1068.         }
  1069.  
  1070.         void UpdateState(uint32 nFromSeq, ENetSendableStateUpdate)
  1071.         {
  1072.         }
  1073.  
  1074.         size_t GetSize()
  1075.         {
  1076.                 return sizeof(*this);
  1077.         }
  1078.  
  1079. private:
  1080.         ISerializableInfoPtr m_pObj;
  1081. };
  1082.  
  1083. INetSendableHookPtr CGameContext::CreateObjectSpawner(EntityId entityId, INetChannel* pChannel)
  1084. {
  1085.         IEntity* pEntity = m_pEntitySystem->GetEntity(entityId);
  1086.         if (!pEntity)
  1087.         {
  1088.                 return NULL;
  1089.         }
  1090.  
  1091.         uint16 channelId = ~uint16(0);
  1092.         if (pChannel)
  1093.         {
  1094.                 IGameChannel* pIGameChannel = pChannel->GetGameChannel();
  1095.                 CGameServerChannel* pGameServerChannel = (CGameServerChannel*) pIGameChannel;
  1096.                 channelId = pGameServerChannel->GetChannelId();
  1097.         }
  1098.  
  1099.         IEntityComponent* pProxy = pEntity->GetProxy(ENTITY_PROXY_USER);
  1100.  
  1101.         CGameObject* pGameObject = reinterpret_cast<CGameObject*>(pProxy);
  1102.         assert(pGameObject);
  1103.         PREFAST_ASSUME(pGameObject);
  1104.  
  1105.         SBasicSpawnParams params;
  1106.         params.name = pEntity->GetName();
  1107.         if (pEntity->GetArchetype())
  1108.         {
  1109.                 ClassIdFromName(params.classId, pEntity->GetArchetype()->GetName());
  1110.         }
  1111.         else
  1112.         {
  1113.                 ClassIdFromName(params.classId, pEntity->GetClass()->GetName());
  1114.         }
  1115.         params.pos = pEntity->GetPos();
  1116.         params.scale = pEntity->GetScale();
  1117.         params.rotation = pEntity->GetRotation();
  1118.         params.nChannelId = pGameObject ? pGameObject->GetChannelId() : 0;
  1119.         params.flags = pEntity->GetFlags();
  1120.  
  1121.         params.bClientActor = pChannel ?
  1122.                               ((CGameChannel*)pChannel->GetGameChannel())->GetPlayerId() == pEntity->GetId() : false;
  1123.  
  1124.         if (params.bClientActor)
  1125.         {
  1126.                 pChannel->DeclareWitness(entityId);
  1127.         }
  1128.  
  1129.         return new CSpawnMsg(params, pGameObject->GetSpawnInfo());
  1130. }
  1131.  
  1132. void CGameContext::ObjectInitClient(EntityId entityId, INetChannel* pChannel)
  1133. {
  1134.         IEntity* pEntity = m_pEntitySystem->GetEntity(entityId);
  1135.         if (!pEntity)
  1136.         {
  1137.                 return;
  1138.         }
  1139.  
  1140.         uint16 channelId = ~uint16(0);
  1141.         if (pChannel)
  1142.         {
  1143.                 IGameChannel* pIGameChannel = pChannel->GetGameChannel();
  1144.                 CGameServerChannel* pGameServerChannel = (CGameServerChannel*) pIGameChannel;
  1145.                 channelId = pGameServerChannel->GetChannelId();
  1146.         }
  1147.  
  1148.         IEntityComponent* pProxy = pEntity->GetProxy(ENTITY_PROXY_USER);
  1149.  
  1150.         CGameObject* pGameObject = reinterpret_cast<CGameObject*>(pProxy);
  1151.         if (pGameObject)
  1152.         {
  1153.                 pGameObject->InitClient(channelId);
  1154.         }
  1155.         m_pScriptRMI->OnInitClient(channelId, pEntity);
  1156. }
  1157.  
  1158. bool CGameContext::SendPostSpawnObject(EntityId id, INetChannel* pINetChannel)
  1159. {
  1160.         IEntity* pEntity = m_pEntitySystem->GetEntity(id);
  1161.         if (!pEntity)
  1162.                 return false;
  1163.  
  1164.         uint16 channelId = ~uint16(0);
  1165.         if (pINetChannel)
  1166.         {
  1167.                 IGameChannel* pIGameChannel = pINetChannel->GetGameChannel();
  1168.                 CGameServerChannel* pGameServerChannel = (CGameServerChannel*) pIGameChannel;
  1169.                 channelId = pGameServerChannel->GetChannelId();
  1170.         }
  1171.  
  1172.         IEntityComponent* pProxy = pEntity->GetProxy(ENTITY_PROXY_USER);
  1173.         CGameObject* pGameObject = reinterpret_cast<CGameObject*>(pProxy);
  1174.         if (pGameObject)
  1175.                 pGameObject->PostInitClient(channelId);
  1176.         m_pScriptRMI->OnPostInitClient(channelId, pEntity);
  1177.  
  1178.         return true;
  1179. }
  1180.  
  1181. void CGameContext::ControlObject(EntityId id, bool bHaveControl)
  1182. {
  1183.         m_controlledObjects.Set(id, bHaveControl);
  1184.  
  1185.         if (IEntity* pEntity = m_pEntitySystem->GetEntity(id))
  1186.         {
  1187.                 if (CGameObject* pGameObject = (CGameObject*) pEntity->GetProxy(ENTITY_PROXY_USER))
  1188.                 {
  1189.                         pGameObject->SetAuthority(bHaveControl);
  1190.                 }
  1191.                 {
  1192.                         IPhysicalEntity* pPhysicalEntity = pEntity->GetPhysicalEntity();
  1193.                         if (pPhysicalEntity)
  1194.                         {
  1195.                                 pPhysicalEntity->SetNetworkAuthority(bHaveControl ? 1 : 0);
  1196.                         }
  1197.                 }
  1198.         }
  1199.  
  1200.         SDelegateCallbackIndex idx = { id, bHaveControl };
  1201.         DelegateCallbacks::iterator iter = m_delegateCallbacks.lower_bound(idx);
  1202.         IScriptSystem* pSS = gEnv->pScriptSystem;
  1203.         while (iter != m_delegateCallbacks.end() && iter->first == idx)
  1204.         {
  1205.                 DelegateCallbacks::iterator next = iter;
  1206.                 ++next;
  1207.  
  1208.                 Script::Call(pSS, iter->second);
  1209.                 pSS->ReleaseFunc(iter->second);
  1210.                 m_delegateCallbacks.erase(iter);
  1211.  
  1212.                 iter = next;
  1213.         }
  1214. }
  1215.  
  1216. void CGameContext::PassDemoPlaybackMappedOriginalServerPlayer(EntityId id)
  1217. {
  1218.         CCryAction::GetCryAction()->GetIActorSystem()->SetDemoPlaybackMappedOriginalServerPlayer(id);
  1219. }
  1220.  
  1221. void CGameContext::AddControlObjectCallback(EntityId id, bool willHaveControl, HSCRIPTFUNCTION func)
  1222. {
  1223.         SDelegateCallbackIndex idx = { id, willHaveControl };
  1224.         m_delegateCallbacks.insert(std::make_pair(idx, func));
  1225. }
  1226.  
  1227. void CGameContext::UnboundObject(EntityId entityId)
  1228. {
  1229.         m_pEntitySystem->RemoveEntity(entityId, false);
  1230. }
  1231.  
  1232. INetAtSyncItem* CGameContext::HandleRMI(bool bClient, EntityId objID, uint8 funcID, TSerialize ser, INetChannel* pChannel)
  1233. {
  1234.         return m_pScriptRMI->HandleRMI(bClient, objID, funcID, ser, pChannel);
  1235. }
  1236.  
  1237. //
  1238. // IEntitySystemSink
  1239. //
  1240.  
  1241. bool CGameContext::OnBeforeSpawn(SEntitySpawnParams& params)
  1242. {
  1243.         if (m_isInLevelLoad && !gEnv->IsEditor() && gEnv->bMultiplayer)
  1244.         {
  1245. #ifndef _RELEASE
  1246.                 static ICVar* pLoadAllLayersForResList = 0;
  1247.                 if (!pLoadAllLayersForResList)
  1248.                 {
  1249.                         pLoadAllLayersForResList = gEnv->pConsole->GetCVar("sv_LoadAllLayersForResList");
  1250.                 }
  1251.  
  1252.                 if (pLoadAllLayersForResList && pLoadAllLayersForResList->GetIVal() != 0)
  1253.                 {
  1254.                         //Bypass the layer filtering. This ensures that an autoresourcelist for generating pak files will contain all the possible assets.
  1255.                         return true;
  1256.                 }
  1257. #endif // #ifndef _RELEASE
  1258.  
  1259.                 static const char prefix[] = "GameType_";
  1260.                 static const size_t prefixLen = sizeof(prefix) - 1;
  1261.  
  1262.                 // if a layer prefixed with GameType_ exists,
  1263.                 // then discard it if it's not the current game type
  1264.                 if (params.sLayerName && !strnicmp(params.sLayerName, prefix, prefixLen))
  1265.                 {
  1266.                         if (IEntity* pGameRules = CCryAction::GetCryAction()->GetIGameRulesSystem()->GetCurrentGameRulesEntity())
  1267.                         {
  1268.                                 const char* currentType = pGameRules->GetClass()->GetName();
  1269.                                 const char* gameType = params.sLayerName + prefixLen;
  1270.                                 if (stricmp(gameType, currentType))
  1271.                                         return false;
  1272.                         }
  1273.                 }
  1274.         }
  1275.  
  1276.         return true;
  1277. }
  1278.  
  1279. void CGameContext::OnSpawn(IEntity* pEntity, SEntitySpawnParams& params)
  1280. {
  1281.         if (HasContextFlag(eGSF_ImmersiveMultiplayer) && m_pBreakReplicator.get())
  1282.                 m_pBreakReplicator->OnSpawn(pEntity, params);
  1283.  
  1284.         if (IGameRules* pGameRules = GetGameRules())
  1285.                 pGameRules->OnEntitySpawn(pEntity);
  1286.  
  1287.         if (params.nFlags & (ENTITY_FLAG_CLIENT_ONLY | ENTITY_FLAG_SERVER_ONLY))
  1288.                 return;
  1289.         if (pEntity->GetFlags() & (ENTITY_FLAG_CLIENT_ONLY | ENTITY_FLAG_SERVER_ONLY))
  1290.                 return;
  1291.  
  1292.         //      if (aspects & eEA_Physics)
  1293.         //      {
  1294.         //              aspects &= ~eEA_Volatile;
  1295.         //      }
  1296.  
  1297. #if VERBOSE_TRACE_CONTEXT_SPAWNS
  1298.         CryLogAlways("CGameContext: Spawn Entity");
  1299.         CryLogAlways("  name       : %s", params.sName);
  1300.         CryLogAlways("  id         : 0x%.4x", params.id);
  1301.         CryLogAlways("  flags      : 0x%.8x", params.nFlags);
  1302.         CryLogAlways("  pos        : %.1f %.1f %.1f", params.vPosition.x, params.vPosition.y, params.vPosition.z);
  1303.         CryLogAlways("  cls name   : %s", params.pClass->GetName());
  1304.         CryLogAlways("  cls flags  : 0x%.8x", params.pClass->GetFlags());
  1305.         CryLogAlways("  channel    : %d", channelId);
  1306.         CryLogAlways("  net aspects: 0x%.8x", aspects);
  1307. #endif
  1308.  
  1309.         if (pEntity->GetProxy(ENTITY_PROXY_SCRIPT))
  1310.         {
  1311.                 m_pScriptRMI->SetupEntity(params.id, pEntity, true, true);
  1312.         }
  1313.  
  1314.         bool calledBindToNetwork = false;
  1315.         if (m_isInLevelLoad && gEnv->bMultiplayer)
  1316.         {
  1317.                 if (!pEntity->GetProxy(ENTITY_PROXY_USER))
  1318.                 {
  1319.                         if (pEntity->GetScriptTable())
  1320.                         {
  1321.                                 IGameObject* pGO = CCryAction::GetCryAction()->GetIGameObjectSystem()->CreateGameObjectForEntity(pEntity->GetId());
  1322.                                 if (pGO)
  1323.                                 {
  1324.                                         //CryLog("Forcibly binding %s to network", params.sName);
  1325.                                         calledBindToNetwork = true;
  1326.                                         pGO->BindToNetwork();
  1327.                                 }
  1328.                         }
  1329.                 }
  1330.         }
  1331.  
  1332.         if (!calledBindToNetwork)
  1333.         {
  1334.                 if (CGameObject* pGO = (CGameObject*)pEntity->GetProxy(ENTITY_PROXY_USER))
  1335.                         pGO->BindToNetwork(eBTNM_NowInitialized);
  1336.         }
  1337.  
  1338.         CallOnSpawnComplete(pEntity);
  1339. }
  1340.  
  1341. void CGameContext::CompleteUnbind(EntityId id)
  1342. {
  1343.         CScopedRemoveObjectUnlock removeObjectUnlock(this);
  1344.         gEnv->pEntitySystem->RemoveEntity(id);
  1345. }
  1346.  
  1347. bool CGameContext::OnRemove(IEntity* pEntity)
  1348. {
  1349.         EntityId id = pEntity->GetId();
  1350.         bool bound = m_pNetContext->IsBound(id);
  1351.  
  1352.         if (IGameRules* pGameRules = GetGameRules())
  1353.                 pGameRules->OnEntityRemoved(pEntity);
  1354.  
  1355.         if (gEnv->IsEditor() || CCryAction::GetCryAction()->IsGameSessionMigrating())
  1356.         {
  1357.                 if (bound)
  1358.                 {
  1359.                         m_pNetContext->UnbindObject(id);
  1360.                 }
  1361.  
  1362.                 return true;
  1363.         }
  1364.  
  1365.         if (0 == m_removeObjectUnlocks)
  1366.         {
  1367.                 if (!HasContextFlag(eGSF_Server) && bound)
  1368.                 {
  1369.                         GameWarning("Attempt to remove entity %s %.8x - disallowing", pEntity->GetName(), id);
  1370.                         return false;
  1371.                 }
  1372.                 else if (gEnv->bMultiplayer)
  1373.                 {
  1374.                         m_pNetContext->SafelyUnbind(id);
  1375.                         return false;
  1376.                 }
  1377.         }
  1378.  
  1379.         if (m_pBreakReplicator.get())
  1380.                 m_pBreakReplicator->OnRemove(pEntity);
  1381.  
  1382.         bool ok = true;
  1383.  
  1384.         if (bound)
  1385.         {
  1386.                 ok = m_pNetContext->UnbindObject(id);
  1387.         }
  1388.  
  1389.         if (pEntity->GetFlags() & (ENTITY_FLAG_CLIENT_ONLY | ENTITY_FLAG_SERVER_ONLY | ENTITY_FLAG_UNREMOVABLE))
  1390.         {
  1391.                 return true;
  1392.         }
  1393.  
  1394.         if (ok)
  1395.         {
  1396.                 m_pScriptRMI->RemoveEntity(id);
  1397.  
  1398.                 if (CGameClientNub* pClientNub = m_pFramework->GetGameClientNub())
  1399.                         if (CGameClientChannel* pClientChannel = pClientNub->GetGameClientChannel())
  1400.                                 if (pClientChannel->GetPlayerId() == id)
  1401.                                         pClientChannel->ClearPlayer();
  1402.         }
  1403.         return ok;
  1404. }
  1405.  
  1406. void CGameContext::OnReused(IEntity* pEntity, SEntitySpawnParams& params)
  1407. {
  1408.         if (IGameRules* pGameRules = GetGameRules())
  1409.                 pGameRules->OnEntityReused(pEntity, params, params.prevId);
  1410.  
  1411.         m_pNetContext->UnbindObject(params.prevId);
  1412.  
  1413.         if (0 == m_removeObjectUnlocks && gEnv->bMultiplayer && !CCryAction::GetCryAction()->IsGameSessionMigrating())
  1414.         {
  1415.                 m_pNetContext->SafelyUnbind(pEntity->GetId());
  1416.         }
  1417.  
  1418.         if (m_pBreakReplicator.get())
  1419.                 m_pBreakReplicator->OnReuse(pEntity, params);
  1420.  
  1421.         m_pScriptRMI->RemoveEntity(params.prevId);
  1422.  
  1423.         if (pEntity->GetProxy(ENTITY_PROXY_SCRIPT))
  1424.         {
  1425.                 m_pScriptRMI->SetupEntity(params.id, pEntity, true, true);
  1426.         }
  1427.  
  1428.         if (CGameClientNub* pClientNub = m_pFramework->GetGameClientNub())
  1429.                 if (CGameClientChannel* pClientChannel = pClientNub->GetGameClientChannel())
  1430.                         if (pClientChannel->GetPlayerId() == params.prevId)
  1431.                                 pClientChannel->ClearPlayer();
  1432.  
  1433.         if (CGameObject* pGO = (CGameObject*)pEntity->GetProxy(ENTITY_PROXY_USER))
  1434.                 pGO->BindToNetwork(eBTNM_NowInitialized);
  1435. }
  1436.  
  1437. void CGameContext::OnEvent(IEntity* pEntity, SEntityEvent& event)
  1438. {
  1439.         struct SGetEntId
  1440.         {
  1441.                 ILINE SGetEntId(IEntity* pEntity) : m_pEntity(pEntity), m_id(0) {}
  1442.  
  1443.                 ILINE operator EntityId()
  1444.                 {
  1445.                         if (!m_id && m_pEntity)
  1446.                                 m_id = m_pEntity->GetId();
  1447.                         return m_id;
  1448.                 }
  1449.  
  1450.                 IEntity* m_pEntity;
  1451.                 EntityId m_id;
  1452.         };
  1453.         SGetEntId entId(pEntity);
  1454.  
  1455.         struct SEntIsMP
  1456.         {
  1457.                 ILINE SEntIsMP(IEntity* pEntity) : m_pEntity(pEntity), m_got(false), m_is(false) {}
  1458.  
  1459.                 ILINE operator bool()
  1460.                 {
  1461.                         if (!m_got)
  1462.                         {
  1463.                                 m_is = !(m_pEntity->GetFlags() & (ENTITY_FLAG_CLIENT_ONLY | ENTITY_FLAG_SERVER_ONLY));
  1464.                                 m_got = true;
  1465.                         }
  1466.                         return m_is;
  1467.                 }
  1468.  
  1469.                 IEntity* m_pEntity;
  1470.                 bool     m_got;
  1471.                 bool     m_is;
  1472.         };
  1473.         SEntIsMP entIsMP(pEntity);
  1474.  
  1475.         switch (event.event)
  1476.         {
  1477.         case ENTITY_EVENT_XFORM:
  1478.                 if (gEnv->bMultiplayer && entIsMP)
  1479.                 {
  1480.                         bool doAspectUpdate = true;
  1481.                         if (event.nParam[0] & (ENTITY_XFORM_FROM_PARENT | ENTITY_XFORM_NO_PROPOGATE))
  1482.                                 doAspectUpdate = false;
  1483.                         // position has changed, best let other people know about it
  1484.                         // disabled volatile... see OnSpawn for reasoning
  1485.                         if (doAspectUpdate)
  1486.                         {
  1487. #if ENABLE_NETDEBUG
  1488.                                 if (GetNetDebug())
  1489.                                         GetNetDebug()->DebugAspectsChange(pEntity, eEA_Physics);
  1490. #endif
  1491.  
  1492.                                 m_pNetContext->ChangedAspects(entId, /*eEA_Volatile |*/ eEA_Physics);
  1493.                         }
  1494. #if FULL_ON_SCHEDULING
  1495.                         float drawDistance = -1;
  1496.                         if (IEntityRender* pRP = pEntity->GetRenderInterface())
  1497.                                 if (IRenderNode* pRN = pRP->GetRenderNode())
  1498.                                         drawDistance = pRN->GetMaxViewDist();
  1499.                         m_pNetContext->ChangedTransform(entId, pEntity->GetWorldPos(), pEntity->GetWorldRotation(), drawDistance);
  1500. #endif
  1501.                 }
  1502.                 break;
  1503.         case ENTITY_EVENT_ENTER_SCRIPT_STATE:
  1504.                 if (entIsMP)
  1505.                 {
  1506.                         m_pNetContext->ChangedAspects(entId, eEA_Script);
  1507.                 }
  1508.                 break;
  1509.         }
  1510. }
  1511.  
  1512. //
  1513. // physics synchronization
  1514. //
  1515.  
  1516. void CGameContext::OnCollision(const EventPhys* pEvent, void*)
  1517. {
  1518.         const EventPhysCollision* pCEvent = static_cast<const EventPhysCollision*>(pEvent);
  1519.         //IGameObject *pSrc = pCollision->iForeignData[0]==PHYS_FOREIGN_ID_ENTITY ? s_this->GetEntityGameObject((IEntity*)pCollision->pForeignData[0]):0;
  1520.         //IGameObject *pTrg = pCollision->iForeignData[1]==PHYS_FOREIGN_ID_ENTITY ? s_this->GetEntityGameObject((IEntity*)pCollision->pForeignData[1]):0;
  1521.         IEntity* pEntitySrc = GetEntity(pCEvent->iForeignData[0], pCEvent->pForeignData[0]);
  1522.         IEntity* pEntityTrg = GetEntity(pCEvent->iForeignData[1], pCEvent->pForeignData[1]);
  1523.  
  1524.         if (!pEntitySrc || !pEntityTrg)
  1525.                 return;
  1526.  
  1527.         s_pGameContext->m_pNetContext->PulseObject(pEntitySrc->GetId(), 'bump');
  1528.         s_pGameContext->m_pNetContext->PulseObject(pEntityTrg->GetId(), 'bump');
  1529. }
  1530.  
  1531. //
  1532. // internal functions
  1533. //
  1534.  
  1535. bool CGameContext::RegisterClassName(const string& name, uint16 id)
  1536. {
  1537.         return m_classRegistry.RegisterClassName(name, id);
  1538. }
  1539.  
  1540. uint32 CGameContext::GetClassesHash()
  1541. {
  1542.         return m_classRegistry.GetHash();
  1543. }
  1544.  
  1545. void CGameContext::DumpClasses()
  1546. {
  1547.         m_classRegistry.DumpClasses();
  1548. }
  1549.  
  1550. bool CGameContext::ClassIdFromName(uint16& id, const string& name) const
  1551. {
  1552.         return m_classRegistry.ClassIdFromName(id, name);
  1553. }
  1554.  
  1555. bool CGameContext::ClassNameFromId(string& name, uint16 id) const
  1556. {
  1557.         return m_classRegistry.ClassNameFromId(name, id);
  1558. }
  1559.  
  1560. void CGameContext::EnablePhysics(EntityId id, bool enable)
  1561. {
  1562.         EEntityAspects aspect;
  1563.         aspect = eEA_Physics;
  1564.         // disabled... see OnSpawn
  1565.         //      m_pNetContext->EnableAspects( id, eEA_Volatile, !enable );
  1566.         EnableAspects(id, aspect, enable);
  1567. }
  1568.  
  1569. void CGameContext::BoundObject(EntityId id, NetworkAspectType nAspects)
  1570. {
  1571.         // called by net system only on the client when a new object has been bound
  1572.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(id);
  1573.         if (!pEntity)
  1574.         {
  1575.                 GameWarning("[net] notification of binding non existant entity %.8x received", id);
  1576.                 return;
  1577.         }
  1578.         CGameObject* pGameObject = (CGameObject*) pEntity->GetProxy(ENTITY_PROXY_USER);
  1579.         if (!pGameObject)
  1580.                 return; // not a game object, things are ok
  1581.         pGameObject->BecomeBound();
  1582. }
  1583.  
  1584. bool CGameContext::ChangeContext(bool isServer, const SGameContextParams* params)
  1585. {
  1586.         if (CCryAction::GetCryAction()->GetILevelSystem()->IsLevelLoaded())
  1587.                 m_loadFlags = EstablishmentFlags_LoadNextLevel;
  1588.         else
  1589.                 m_loadFlags = EstablishmentFlags_InitialLoad;
  1590.  
  1591.         m_resetChannels.clear();
  1592.  
  1593.         if (HasContextFlag(eGSF_DemoRecorder) && HasContextFlag(eGSF_DemoPlayback))
  1594.         {
  1595.                 GameWarning("Cannot both playback a demo file and record a demo at the same time.");
  1596.                 return false;
  1597.         }
  1598.  
  1599.         if (!HasContextFlag(eGSF_NoLevelLoading))
  1600.         {
  1601.                 if (!params->levelName)
  1602.                 {
  1603.                         GameWarning("No level specified: not changing context");
  1604.                         return false;
  1605.                 }
  1606.  
  1607.                 ILevelInfo* pLevelInfo = m_pFramework->GetILevelSystem()->GetLevelInfo(params->levelName);
  1608.                 if (!pLevelInfo)
  1609.                 {
  1610.                         GameWarning("Level %s not found", params->levelName);
  1611.  
  1612.                         m_pFramework->GetILevelSystem()->OnLevelNotFound(params->levelName);
  1613.  
  1614.                         return false;
  1615.                 }
  1616.  
  1617. #ifndef _DEBUG
  1618.                 string gameMode = params->gameRules;
  1619.                 if ((pLevelInfo->GetGameTypeCount() > 0) && (gameMode != "SinglePlayer") && !pLevelInfo->SupportsGameType(gameMode) && !gEnv->IsEditor() && !gEnv->pSystem->IsDevMode())
  1620.                 {
  1621.                         GameWarning("Level %s does not support %s gamerules.", params->levelName, gameMode.c_str());
  1622.  
  1623.                         return false;
  1624.                 }
  1625. #endif
  1626.         }
  1627.  
  1628.         if (!HasContextFlag(eGSF_NoGameRules))
  1629.         {
  1630.                 if (!params->gameRules)
  1631.                 {
  1632.                         GameWarning("No rules specified: not changing context");
  1633.                         return false;
  1634.                 }
  1635.  
  1636.                 if (!m_pFramework->GetIGameRulesSystem()->HaveGameRules(params->gameRules))
  1637.                 {
  1638.                         GameWarning("Game rules %s not found; not changing context", params->gameRules);
  1639.                         return false;
  1640.                 }
  1641.         }
  1642.  
  1643.         if (params->levelName)
  1644.                 m_levelName = params->levelName;
  1645.         else
  1646.                 m_levelName.clear();
  1647.         if (params->gameRules)
  1648.                 m_gameRules = params->gameRules;
  1649.         else
  1650.                 m_gameRules.clear();
  1651.  
  1652.         //if (HasContextFlag(eGSF_Server) && HasContextFlag(eGSF_Client))
  1653.         while (HasContextFlag(eGSF_Server))
  1654.         {
  1655.                 if (HasContextFlag(eGSF_Client) && HasContextFlag(eGSF_DemoPlayback))
  1656.                 {
  1657.                         if (params->demoPlaybackFilename == NULL)
  1658.                                 break;
  1659.                         INetChannel* pClientChannel = m_pFramework->GetGameClientNub()->GetGameClientChannel()->GetNetChannel();
  1660.                         INetChannel* pServerChannel = m_pFramework->GetGameServerNub()->GetChannel(1)->GetNetChannel();
  1661.                         m_pNetContext->ActivateDemoPlayback(params->demoPlaybackFilename, pClientChannel, pServerChannel);
  1662.                         break;
  1663.                 }
  1664.                 if (HasContextFlag(eGSF_DemoRecorder))
  1665.                 {
  1666.                         if (params->demoRecorderFilename == NULL)
  1667.                                 break;
  1668.                         m_pNetContext->ActivateDemoRecorder(params->demoRecorderFilename);
  1669.                         CCryAction::GetCryAction()->OnActionEvent(SActionEvent(eAE_demoRecorderCreated, 0));
  1670.                         break;
  1671.                 }
  1672.  
  1673.                 break;
  1674.         }
  1675.  
  1676.         m_pNetContext->EnableBackgroundPassthrough(HasContextFlag(eGSF_Server) && gEnv->bMultiplayer);
  1677.  
  1678.         // start this thing off
  1679.         if (isServer)
  1680.         {
  1681.                 if (!m_pNetContext->ChangeContext())
  1682.                         return false;
  1683.         }
  1684.  
  1685.         return true;
  1686. }
  1687.  
  1688. bool CGameContext::Update()
  1689. {
  1690.         bool ret = false;
  1691.  
  1692.         float white[] = { 1, 1, 1, 1 };
  1693.         if (!m_bHasSpawnPoint)
  1694.         {
  1695.                 IRenderAuxText::Draw2dLabel(10, 10, 4, white, false, "NO SPAWN POINT");
  1696.         }
  1697.  
  1698.         // TODO: This block should be moved into GameSDK code, since sv_pacifist is a GameSDK-only CVar
  1699.         {
  1700.                 static ICVar* pPacifist = 0;
  1701.                 static bool bTried = false;
  1702.                 if (!pPacifist && !bTried)
  1703.                 {
  1704.                         pPacifist = gEnv->pConsole->GetCVar("sv_pacifist");
  1705.                         bTried = true;
  1706.                 }
  1707.                 if (gEnv->IsClient() && !gEnv->bServer && pPacifist && pPacifist->GetIVal() == 1)
  1708.                 {
  1709.                         IRenderAuxText::Draw2dLabel(10, 10, 4, white, false, "PACIFIST MODE");
  1710.                 }
  1711.         }
  1712.  
  1713.         /*
  1714.            else if (m_bScheduledLevelLoad)
  1715.            {
  1716.             m_bScheduledLevelLoad = false;
  1717.             // if we're not the editor then we need to load a level
  1718.             bool oldLevelLoad = m_isInLevelLoad;
  1719.             m_isInLevelLoad = true;
  1720.             m_pFramework->GetIActionMapManager()->Enable(false); // diable action processing during loading
  1721.             if (!m_pFramework->GetILevelSystem()->LoadLevel(m_levelName.c_str()))
  1722.             {
  1723.               m_pFramework->EndGameContext();
  1724.               return false;
  1725.             }
  1726.             m_bHasSpawnPoint = HasSpawnPoint();
  1727.             m_pFramework->GetIActionMapManager()->Enable(true);
  1728.             m_isInLevelLoad = oldLevelLoad;
  1729.             m_pNetContext->EstablishedContext();
  1730.  
  1731.             if (!HasContextFlag(eGSF_Client))
  1732.             {
  1733.               StartGame();
  1734.               m_bStarted = true;
  1735.             }
  1736.            }
  1737.          */
  1738.  
  1739. #ifndef OLD_VOICE_SYSTEM_DEPRECATED
  1740.         if (m_pVoiceController)
  1741.                 m_pVoiceController->Enable(m_pFramework->IsVoiceRecordingEnabled());
  1742. #endif
  1743.  
  1744.         if (0 == (m_broadcastActionEventInGame -= (m_broadcastActionEventInGame != -1)))
  1745.                 CCryAction::GetCryAction()->OnActionEvent(eAE_inGame);
  1746.  
  1747. #if ENABLE_NETEDEBUG
  1748.         if (m_pNetDebug)
  1749.                 m_pNetDebug->Update();
  1750. #endif
  1751.  
  1752.         return ret;
  1753. }
  1754.  
  1755. bool CGameContext::OnBeforeVarChange(ICVar* pVar, const char* sNewValue)
  1756. {
  1757.         int flags = pVar->GetFlags();
  1758.         bool netSynced = ((flags & VF_NET_SYNCED) != 0);
  1759.         bool isServer = HasContextFlag(eGSF_Server);
  1760.         bool allowChange = (!netSynced) || isServer;
  1761.  
  1762. #if LOG_CVAR_USAGE
  1763.         if (!allowChange)
  1764.         {
  1765.                 CryLog("[CVARS]: [CHANGED] CGameContext::OnBeforeVarChange(): variable [%s] is VF_NET_SYNCED with a value of [%s]; CLIENT changing attempting to set to [%s] - IGNORING",
  1766.                        pVar->GetName(),
  1767.                        pVar->GetString(),
  1768.                        sNewValue);
  1769.         }
  1770. #endif // LOG_CVAR_USAGE
  1771.  
  1772.         return allowChange;
  1773. }
  1774.  
  1775. void CGameContext::OnAfterVarChange(ICVar* pVar)
  1776. {
  1777. }
  1778.  
  1779. // IHostMigrationEventListener
  1780. IHostMigrationEventListener::EHostMigrationReturn CGameContext::OnInitiate(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  1781. {
  1782.         // Register all client actor data in the game at this point
  1783.         // (N.B. Even if we're not going to become the new server, we know
  1784.         // that we can accurately store all local player statistics here
  1785.         // (such as health and ammo counts) that aren't normally transmitted
  1786.         // to other clients). This info could be sent as part of the
  1787.         // migrating player connection string, or a discrete message.
  1788.         IGameRules* pGameRules = gEnv->pGameFramework->GetIGameRulesSystem()->GetCurrentGameRules();
  1789.         if (pGameRules)
  1790.         {
  1791.                 pGameRules->ClearAllMigratingPlayers();
  1792.                 IActorSystem* pActorSystem = gEnv->pGameFramework->GetIActorSystem();
  1793.                 IActorIteratorPtr pActorIterator = pActorSystem->CreateActorIterator();
  1794.                 IActor* pActor = pActorIterator->Next();
  1795.  
  1796.                 while (pActor != NULL)
  1797.                 {
  1798.                         if (pActor->IsPlayer())
  1799.                         {
  1800.                                 pGameRules->StoreMigratingPlayer(pActor);
  1801.                         }
  1802.  
  1803.                         pActor = pActorIterator->Next();
  1804.                 }
  1805.         }
  1806.         else
  1807.         {
  1808.                 CryLogAlways("[Host Migration]: no game rules found - aborting");
  1809.                 gEnv->pNetwork->TerminateHostMigration(hostMigrationInfo.m_session);
  1810.         }
  1811.  
  1812.         return IHostMigrationEventListener::Listener_Done;
  1813. }
  1814.  
  1815. IHostMigrationEventListener::EHostMigrationReturn CGameContext::OnDisconnectClient(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  1816. {
  1817.         return IHostMigrationEventListener::Listener_Done;
  1818. }
  1819.  
  1820. IHostMigrationEventListener::EHostMigrationReturn CGameContext::OnDemoteToClient(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  1821. {
  1822.         if (!hostMigrationInfo.ShouldMigrateNub())
  1823.         {
  1824.                 return IHostMigrationEventListener::Listener_Done;
  1825.         }
  1826.  
  1827.         CryLogAlways("[Host Migration]: CGameContext::OnDemoteToClient() started");
  1828.  
  1829.         if (HasContextFlag(eGSF_Server) == true)
  1830.         {
  1831.                 m_flags &= ~eGSF_Server;
  1832.  
  1833.                 CCryAction::GetCryAction()->GetIGameSessionHandler()->EndSession();
  1834.         }
  1835.  
  1836.         CryLogAlways("[Host Migration]: CGameContext::OnDemoteToClient() finished");
  1837.         return IHostMigrationEventListener::Listener_Done;
  1838. }
  1839.  
  1840. IHostMigrationEventListener::EHostMigrationReturn CGameContext::OnPromoteToServer(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  1841. {
  1842.         if (!hostMigrationInfo.ShouldMigrateNub())
  1843.         {
  1844.                 return IHostMigrationEventListener::Listener_Done;
  1845.         }
  1846.  
  1847.         CryLogAlways("[Host Migration]: CGameContext::OnPromoteToServer() started");
  1848.         m_flags |= eGSF_Server;
  1849.  
  1850.         ICVar* pCVar = gEnv->pConsole->GetCVar("sv_requireinputdevice");
  1851.         if (pCVar)
  1852.         {
  1853.                 const char* requiredInputDevice = pCVar->GetString();
  1854.                 if (0 == strcmpi(requiredInputDevice, "none"))
  1855.                 {
  1856.                         m_flags &= ~(eGSF_RequireKeyboardMouse | eGSF_RequireController);
  1857.                 }
  1858.                 else if (0 == strcmpi(requiredInputDevice, "keyboard"))
  1859.                 {
  1860.                         m_flags |= eGSF_RequireKeyboardMouse;
  1861.                         m_flags &= ~eGSF_RequireController;
  1862.                 }
  1863.                 else if (0 == strcmpi(requiredInputDevice, "gamepad"))
  1864.                 {
  1865.                         m_flags |= eGSF_RequireController;
  1866.                         m_flags &= ~eGSF_RequireKeyboardMouse;
  1867.                 }
  1868.                 else if (0 == strcmpi(requiredInputDevice, "dontcare"))
  1869.                 {
  1870.                 }
  1871.         }
  1872.  
  1873.         CryLogAlways("[Host Migration]: CGameContext::OnPromoteToServer() finished");
  1874.         return IHostMigrationEventListener::Listener_Done;
  1875. }
  1876.  
  1877. IHostMigrationEventListener::EHostMigrationReturn CGameContext::OnReconnectClient(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  1878. {
  1879.         return IHostMigrationEventListener::Listener_Done;
  1880. }
  1881.  
  1882. IHostMigrationEventListener::EHostMigrationReturn CGameContext::OnFinalise(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  1883. {
  1884.         return IHostMigrationEventListener::Listener_Done;
  1885. }
  1886.  
  1887. IHostMigrationEventListener::EHostMigrationReturn CGameContext::OnTerminate(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  1888. {
  1889.         return IHostMigrationEventListener::Listener_Done;
  1890. }
  1891.  
  1892. IHostMigrationEventListener::EHostMigrationReturn CGameContext::OnReset(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  1893. {
  1894.         return IHostMigrationEventListener::Listener_Done;
  1895. }
  1896. // ~IHostMigrationEventListener
  1897.  
  1898. static XmlNodeRef Child(XmlNodeRef& from, const char* name)
  1899. {
  1900.         if (XmlNodeRef found = from->findChild(name))
  1901.                 return found;
  1902.         else
  1903.         {
  1904.                 XmlNodeRef newNode = from->createNode(name);
  1905.                 from->addChild(newNode);
  1906.                 return newNode;
  1907.         }
  1908. }
  1909.  
  1910. XmlNodeRef CGameContext::GetGameState()
  1911. {
  1912.         CGameServerNub* pGameServerNub = m_pFramework->GetGameServerNub();
  1913.  
  1914.         XmlNodeRef root = GetISystem()->CreateXmlNode("root");
  1915.  
  1916.         // add server/network properties
  1917.         XmlNodeRef serverProperties = Child(root, "server");
  1918.  
  1919.         // add game properties
  1920.         XmlNodeRef gameProperties = Child(root, "game");
  1921.         gameProperties->setAttr("levelName", m_levelName.c_str());
  1922.         gameProperties->setAttr("curPlayers", pGameServerNub->GetPlayerCount());
  1923.         gameProperties->setAttr("gameRules", m_gameRules.c_str());
  1924.         char buffer[32];
  1925.         GetISystem()->GetProductVersion().ToShortString(buffer);
  1926.         gameProperties->setAttr("version", string(buffer).c_str());
  1927.         gameProperties->setAttr("maxPlayers", pGameServerNub->GetMaxPlayers());
  1928.  
  1929.         return root;
  1930. }
  1931.  
  1932. void CGameContext::EnableAspects(EntityId id, NetworkAspectType aspects, bool bEnable)
  1933. {
  1934.         if (bEnable)
  1935.         {
  1936.                 IEntity* pEntity = m_pEntitySystem->GetEntity(id);
  1937.                 CRY_ASSERT(pEntity);
  1938.                 CGameObject* pGameObject = (CGameObject*) pEntity->GetProxy(ENTITY_PROXY_USER);
  1939.                 if (pGameObject)
  1940.                 {
  1941.                         aspects &= pGameObject->GetEnabledAspects();
  1942.                 }
  1943.         }
  1944.         m_pNetContext->EnableAspects(id, aspects, bEnable);
  1945. }
  1946.  
  1947. IGameRules* CGameContext::GetGameRules()
  1948. {
  1949.         IEntity* pGameRules = m_pFramework->GetIGameRulesSystem()->GetCurrentGameRulesEntity();
  1950.         if (pGameRules)
  1951.         {
  1952.                 return 0;
  1953.         }
  1954.  
  1955.         return 0;
  1956. }
  1957.  
  1958. void CGameContext::OnStartNetworkFrame()
  1959. {
  1960.         if (m_pBreakReplicator.get())
  1961.                 m_pBreakReplicator->OnStartFrame();
  1962. }
  1963.  
  1964. void CGameContext::OnEndNetworkFrame()
  1965. {
  1966.         if (m_pBreakReplicator.get())
  1967.                 m_pBreakReplicator->OnEndFrame();
  1968. }
  1969.  
  1970. void CGameContext::OnBrokeSomething(const SBreakEvent& be, EventPhysMono* pMono, bool isPlane)
  1971. {
  1972.         if (m_pBreakReplicator.get())
  1973.                 m_pBreakReplicator->OnBrokeSomething(be, pMono, isPlane);
  1974. }
  1975.  
  1976. void CGameContext::ReconfigureGame(INetChannel* pNetChannel)
  1977. {
  1978.         CryLogAlways("Game reconfiguration: %s", pNetChannel->GetName());
  1979. }
  1980.  
  1981. void CGameContext::AllowCallOnClientConnect()
  1982. {
  1983.         m_bAllowSendClientConnect = true;
  1984. }
  1985.  
  1986. CTimeValue CGameContext::GetPhysicsTime()
  1987. {
  1988.         int tick = gEnv->pPhysicalWorld->GetiPhysicsTime();
  1989.         CTimeValue tm = tick * double(gEnv->pPhysicalWorld->GetPhysVars()->timeGranularity);
  1990.         return tm;
  1991. }
  1992.  
  1993. void CGameContext::BeginUpdateObjects(CTimeValue physTime, INetChannel* pChannel)
  1994. {
  1995.         //UpdateTimestampedAspect calls this and pChannel is used there already; will be valid
  1996.         if (CGameChannel* pGameChannel = (CGameChannel*)pChannel->GetGameChannel())
  1997.                 if (m_pPhysicsSync = pGameChannel->CGameChannel::GetPhysicsSync())
  1998.                         m_pPhysicsSync->OnPacketHeader(physTime);
  1999. }
  2000.  
  2001. void CGameContext::EndUpdateObjects()
  2002. {
  2003.         if (m_pPhysicsSync)
  2004.         {
  2005.                 m_pPhysicsSync->OnPacketFooter();
  2006.                 m_pPhysicsSync = nullptr;
  2007.         }
  2008. }
  2009.  
  2010. void CGameContext::GetMemoryUsage(ICrySizer* s) const
  2011. {
  2012.         s->Add(*this);
  2013. #ifndef OLD_VOICE_SYSTEM_DEPRECATED
  2014.         if (m_pVoiceController)
  2015.                 m_pVoiceController->GetMemoryStatistics(s);
  2016. #endif
  2017.         m_classRegistry.GetMemoryStatistics(s);
  2018.         m_controlledObjects.GetMemoryStatistics(s);
  2019.         if (m_pBreakReplicator.get())
  2020.                 m_pBreakReplicator->GetMemoryStatistics(s);
  2021.         s->AddObject(m_levelName);
  2022.         s->AddObject(m_gameRules);
  2023.         s->AddObject(m_connectionString);
  2024.         //s->AddObject(m_delegateCallbacks);
  2025. }
  2026.  
  2027. // encode size ignore last 3 bits of size in bytes. (encode by 8bytes min)
  2028. #define TEA_GETSIZE(len) ((len) & (~7))
  2029.  
  2030. static ILINE bool IsDX11()
  2031. {
  2032.         ERenderType renderType = gEnv->pRenderer->GetRenderType();
  2033.         return true;//renderType == eRT_DX11;   // marcio: in this context, we assume DX11 for Crysis2, so immersiveness can work
  2034. }
  2035.  
  2036. static ILINE bool HasController()
  2037. {
  2038.         if (gEnv->pInput)
  2039.                 return gEnv->pInput->HasInputDeviceOfType(eIDT_Gamepad);
  2040.         else
  2041.                 return false;
  2042. }
  2043.  
  2044. static ILINE bool HasKeyboardMouse()
  2045. {
  2046.         if (gEnv->pInput)
  2047.                 return gEnv->pInput->HasInputDeviceOfType(eIDT_Keyboard) && gEnv->pInput->HasInputDeviceOfType(eIDT_Mouse);
  2048.         else
  2049.                 return true;
  2050. }
  2051.  
  2052. string CGameContext::GetConnectionString(CryFixedStringT<HOST_MIGRATION_MAX_PLAYER_NAME_SIZE>* pNameOverride, bool fake) const
  2053. {
  2054.         bool bForceImmersive = false;
  2055.         ICVar* pImmersive = gEnv->pConsole->GetCVar("g_immersive");
  2056.         if (pImmersive && pImmersive->GetIVal() != 0)
  2057.         {
  2058.                 bForceImmersive = true;
  2059.         }
  2060.  
  2061.         string playerName;
  2062.         if (pNameOverride)
  2063.         {
  2064.                 playerName = pNameOverride->c_str();
  2065.         }
  2066.         else
  2067.         {
  2068.                 bool bDefaultName = false;
  2069.                 if (IPlayerProfileManager* pProfileManager = CCryAction::GetCryAction()->GetIPlayerProfileManager())
  2070.                 {
  2071.                         IPlatformOS::TUserName userName;
  2072.                         IPlatformOS* pOS = GetISystem()->GetPlatformOS();
  2073.                         uint32 userIndex = pProfileManager->GetExclusiveControllerDeviceIndex();
  2074.                         if (!pOS->UserGetOnlineName(userIndex, userName) || userName.empty())
  2075.                         {
  2076.                                 if (!pOS->UserGetName(userIndex, userName) || userName.empty())
  2077.                                 {
  2078.                                         bDefaultName = true;
  2079.                                 }
  2080.                         }
  2081.  
  2082.                         if (!bDefaultName)
  2083.                         {
  2084.                                 playerName = userName.c_str();
  2085.                         }
  2086.                         else if (CCryActionCVars::Get().useCurrentUserNameAsDefault != 0)
  2087.                         {
  2088.                                 playerName = gEnv->pSystem->GetUserName();
  2089.                         }
  2090.                 }
  2091.         }
  2092.  
  2093.         char buf[128];
  2094.         string constr;
  2095.         constr += '!';
  2096.         gEnv->pSystem->GetProductVersion().ToShortString(buf);
  2097.         constr += buf;
  2098.         constr += ':';
  2099.         if (fake || bForceImmersive || IsDX11())
  2100.                 constr += 'X';
  2101.         if (fake || HasController())
  2102.                 constr += 'C';
  2103.         if (fake || HasKeyboardMouse())
  2104.                 constr += 'K';
  2105.         // Indicate this is a migrating player so it can be handled slightly
  2106.         // differently when CGameServerNub::CreateChannel() deals with it.
  2107.         if (CCryAction::GetCryAction()->IsGameSessionMigrating())
  2108.                 constr += 'M';
  2109.         constr += ':';
  2110.         constr += ToHexStr(playerName.data(), playerName.size());
  2111.         constr += ':';
  2112.         constr += fake ? "fake" : m_connectionString;
  2113.         cry_sprintf(buf, "%d", (int)time(NULL));
  2114.         constr = buf + constr;
  2115.         int len = constr.length();
  2116.         int r = cry_random(0, 19) + CLAMP(64 - len, 0, 64);
  2117.         for (int i = 0; i < r || (constr.length() & 7); i++)
  2118.         {
  2119.                 char c = cry_random('a', 'z');
  2120.                 constr = c + constr;
  2121.         }
  2122.         len = constr.length();
  2123.  
  2124.         string out = ToHexStr(&constr[0], len);
  2125.         string temp = out;
  2126.         CRY_ASSERT(FromHexStr(temp));
  2127.         CRY_ASSERT(temp == constr);
  2128.         return out;
  2129. }
  2130.  
  2131. SParsedConnectionInfo CGameContext::ParseConnectionInfo(const string& sconst)
  2132. {
  2133.         SParsedConnectionInfo info;
  2134.         info.allowConnect = false;
  2135.         info.isMigrating = false;
  2136.         info.cause = eDC_GameError;
  2137.  
  2138.         string badFormat = "Illegal connection packet";
  2139.         string temp = sconst;
  2140.         if (!FromHexStr(temp))
  2141.         {
  2142.                 info.errmsg = badFormat;
  2143.                 return info;
  2144.         }
  2145.  
  2146.         int slen = temp.length();
  2147.         if (temp.length() > 511)
  2148.         {
  2149.                 info.errmsg = badFormat;
  2150.                 return info;
  2151.         }
  2152.  
  2153.         char s[512];
  2154.         memset(s, 0, 512);
  2155.         memcpy(s, temp.data(), TEA_GETSIZE(slen));
  2156.  
  2157.         char buf[128];
  2158.         gEnv->pSystem->GetProductVersion().ToShortString(buf);
  2159.  
  2160.         int i = 0;
  2161.         string versionMismatch = "Version mismatch";
  2162.         while (i < slen && s[i] != '!')
  2163.                 ++i;
  2164.         if (!s[i])
  2165.                 return info;
  2166.         ++i;
  2167.         int sbuf = i;
  2168.         for (; buf[i - sbuf]; i++)
  2169.         {
  2170.                 if (slen <= i)
  2171.                 {
  2172.                         info.errmsg = badFormat;
  2173.                         return info;
  2174.                 }
  2175.                 if (s[i] != buf[i - sbuf])
  2176.                 {
  2177.                         info.errmsg = versionMismatch;
  2178.                         info.cause = eDC_VersionMismatch;
  2179.                         return info;
  2180.                 }
  2181.         }
  2182.         if (slen <= i)
  2183.         {
  2184.                 info.errmsg = badFormat;
  2185.                 return info;
  2186.         }
  2187.         if (s[i++] != ':')
  2188.         {
  2189.                 info.errmsg = badFormat;
  2190.                 return info;
  2191.         }
  2192.  
  2193.         bool isDX11 = false;
  2194.         bool hasController = false;
  2195.         bool hasKeyboardMouse = false;
  2196.         bool gotName = false;
  2197.         for (; i < slen; i++)
  2198.         {
  2199.                 switch (s[i])
  2200.                 {
  2201.                 case 'X':
  2202.                         isDX11 = true;
  2203.                         break;
  2204.                 case 'C':
  2205.                         hasController = true;
  2206.                         break;
  2207.                 case 'K':
  2208.                         hasKeyboardMouse = true;
  2209.                         break;
  2210.                 case 'M':
  2211.                         info.isMigrating = true;
  2212.                         break;
  2213.                 case ':':
  2214.                         if (!gotName)
  2215.                         {
  2216.                                 gotName = true;
  2217.                                 int k = i + 1;
  2218.                                 while (k < slen && s[k] != ':')
  2219.                                         ++k;
  2220.                                 info.playerName = string(&s[i + 1], k - i - 1);
  2221.                                 i = k - 1;
  2222.  
  2223.                                 if (!FromHexStr(info.playerName))
  2224.                                 {
  2225.                                         info.errmsg = badFormat;
  2226.                                         return info;
  2227.                                 }
  2228.                                 break;
  2229.                         }
  2230.                         else
  2231.                         {
  2232.                                 if (HasContextFlag(eGSF_RequireController) && !hasController)
  2233.                                 {
  2234.                                         info.errmsg = "Client has no game controller";
  2235.                                         info.cause = eDC_NoController;
  2236.                                         return info;
  2237.                                 }
  2238.                                 if (HasContextFlag(eGSF_RequireKeyboardMouse) && !hasKeyboardMouse)
  2239.                                 {
  2240.                                         info.errmsg = "Client has no keyboard/mouse";
  2241.                                         info.cause = eDC_GameError;
  2242.                                         return info;
  2243.                                 }
  2244.                                 if (HasContextFlag(eGSF_ImmersiveMultiplayer) && !isDX11)
  2245.                                 {
  2246.                                         info.errmsg = "Client is not DX11 capable";
  2247.                                         info.cause = eDC_NotDX11Capable;
  2248.                                         return info;
  2249.                                 }
  2250.                                 info.allowConnect = true;
  2251.                                 info.gameConnectionString = s + i + 1;
  2252.                                 return info;
  2253.                         }
  2254.                 default:
  2255.                         info.errmsg = badFormat;
  2256.                         return info;
  2257.                 }
  2258.         }
  2259.         info.errmsg = badFormat;
  2260.         return info;
  2261. }
  2262.  
  2263. void CGameContext::DefineContextProtocols(IProtocolBuilder* pBuilder, bool server)
  2264. {
  2265.         if (m_pBreakReplicator.get())
  2266.         {
  2267.                 m_pBreakReplicator->m_bDefineProtocolMode_server = server;
  2268.                 m_pBreakReplicator->DefineProtocol(pBuilder);
  2269.         }
  2270.  
  2271.         CCryAction* cca = CCryAction::GetCryAction();
  2272.         if (cca->GetNetMessageDispatcher())
  2273.                 cca->GetNetMessageDispatcher()->DefineProtocol(pBuilder);
  2274.         if (cca->GetManualFrameStepController())
  2275.                 cca->GetManualFrameStepController()->DefineProtocol(pBuilder);
  2276. }
  2277.  
  2278. void CGameContext::PlaybackBreakage(int breakId, INetBreakagePlaybackPtr pBreakage)
  2279. {
  2280.         if (m_pBreakReplicator.get())
  2281.                 m_pBreakReplicator->PlaybackBreakage(breakId, pBreakage);
  2282. }
  2283.  
  2284. void* CGameContext::ReceiveSimpleBreakage(TSerialize ser)
  2285. {
  2286.         if (m_pBreakReplicator.get())
  2287.                 return m_pBreakReplicator->ReceiveSimpleBreakage(ser);
  2288.         return NULL;
  2289. }
  2290.  
  2291. void CGameContext::PlaybackSimpleBreakage(void* userData, INetBreakageSimplePlaybackPtr pBreakage)
  2292. {
  2293.         if (m_pBreakReplicator.get())
  2294.                 m_pBreakReplicator->PlaybackSimpleBreakage(userData, pBreakage);
  2295. }
  2296.  
  2297. bool CGameContext::SetImmersive(bool immersive)
  2298. {
  2299.         bool bForceImmersive = false;
  2300.         ICVar* pImmersive = gEnv->pConsole->GetCVar("g_immersive");
  2301.         if (pImmersive && pImmersive->GetIVal() != 0)
  2302.         {
  2303.                 bForceImmersive = true;
  2304.         }
  2305.  
  2306.         if (!bForceImmersive && (immersive && !IsDX11()))
  2307.                 return false;
  2308.         if (immersive)
  2309.                 m_flags |= eGSF_ImmersiveMultiplayer;
  2310.         else
  2311.                 m_flags &= ~eGSF_ImmersiveMultiplayer;
  2312.         return true;
  2313. }
  2314.  
downloadGameContext.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