Torque3D Documentation / _generateds / gameConnection.cpp

gameConnection.cpp

Engine/source/T3D/gameBase/gameConnection.cpp

More...

Public Defines

Public Functions

ConsoleDocClass(GameConnection , "@brief The game-specific subclass of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">NetConnection.\n\n</a>" "The <a href="/coding/class/classgameconnection/">GameConnection</a> introduces the concept of the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object. The <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object " "is simply the object that the client is associated with that network connection controls. By " "default the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object is an instance of the <a href="/coding/class/classplayer/">Player</a> class, but can also be an instance " "of  Camera, or any other <a href="/coding/class/classshapebase/">ShapeBase</a> derived class as " "appropriate <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">game.\n\n</a>" "Torque uses <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> model in which the server is the authoritative master of the simulation. To " "prevent clients from cheating, the server simulates all player moves and then tells the " "client where his player is in the world. This model, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a0e48c1f64b558d03d870367324920354">while</a> secure, can have problems. If " "the network latency is high, this round-trip time can give the player <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> very noticeable sense " "of movement lag. To correct this problem, the game uses <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> form of prediction - it simulates " "the movement of the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object on the client and on the server both. This way the client " "doesn '<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a> need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> wait <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> round-trip verification of his moves. Only in the case of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> force " "acting on the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object on the server that doesn '<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a> exist on the client does the client 's " "position need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be forcefully <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">changed.\n\n</a>" "To support this, all <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> objects(derivative of <a href="/coding/class/classshapebase/">ShapeBase</a>) must supply <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> writePacketData() " "and readPacketData() function that send enough data <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> accurately simulate the object on the " "client. These functions are only called <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the current <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object, and only when the " "server can determine that the client 's simulation is somehow out of sync with the server. This " "occurs usually <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the client is affected by <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> force not present on the server(like an " "interpolating object) or <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the server object is affected by <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> server only force(such as the " "impulse from an explosion).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "The <a href="/coding/class/structmove/">Move</a> structure is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 32 millisecond snapshot of player input, containing x, y , and z " "positional and rotational changes as well as trigger state changes. When time passes in the " "simulation moves are  collected, and applied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the current " "<a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object on the client. The same moves are then packed over <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server in " " GameConnection::writePacket, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> processing on the server 's version of the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" " @see @ref Networking, <a href="/coding/class/classnetconnection/">NetConnection</a> , <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ShapeBase\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Networking\n</a>" )
DefineEngineMethod(GameConnection , activateGhosting , void , () , "@brief Called by the server during phase 2 of the mission download <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> start sending ghosts <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n\n</a>" "Ghosts represent objects on the server that are in scope <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the client. These need " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be synchronized with the client in order <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the client <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> see and interact with them. " "This is typically done during the standard mission start phase 2 when following Torque's " "example mission startup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">sequence.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function serverCmdMissionStartPhase2Ack(%client, %seq, %playerDB)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Make sure <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> ignore calls from <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> previous mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">load\n</a>" "   <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> (%seq != $missionSequence || !$MissionRunning)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      return;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> (%client.currentPhase != 1.5)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      return;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   %client.currentPhase = 2;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Set the player datablock <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">choice\n</a>" "   %client.playerDB = %playerDB;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Update mod paths, this needs <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get there before the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">objects.\n</a>" "   %client.transmitPaths();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Start ghosting objects <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client\n</a>" "   %client.activateGhosting();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see @ref ghosting_scoping <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> description of the ghosting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">system.\n\n</a>" )
DefineEngineMethod(GameConnection , chaseCam , bool , (S32 size) , "@brief Sets the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of the chase camera's matrix <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue.\n\n</a>" "@note This sets the queue <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> across all <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GameConnections.\n\n</a>" "@note This is not currently hooked <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">up.\n\n</a>" )
DefineEngineMethod(GameConnection , clearCameraObject , void , () , "@brief Clear the connection's camera object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">reference.\n\n</a>" "@see <a href="/coding/class/classgameconnection/#classgameconnection_1a34ab83c3521274d2ebc44755892cedf5">GameConnection::setCameraObject</a>() and <a href="/coding/class/classgameconnection/#classgameconnection_1a30d6982550f88f92023231129d150ffe">GameConnection::getCameraObject</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )
DefineEngineMethod(GameConnection , clearDisplayDevice , void , () , "@brief Clear any display <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">device.\n\n</a>" "A display device may define <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> number of properties that are used during <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rendering.\n\n</a>" )
DefineEngineMethod(GameConnection , delete , void , (const char *reason) , ("") , "@brief On the server, disconnect <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> client and pass along an optional reason <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">why.\n\n</a>" "This method performs two operations:it disconnects <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> client connection from the server, " "and it deletes the connection object. The optional reason is sent in the disconnect packet " "and is often displayed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the user so they know why they 've been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disconnected.\n\n</a>" " @param reason The reason why the user has been disconnected from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function kick(%client)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " messageAll( 'MsgAdminForce', '\\c2The Admin has kicked %1.', %client.playerName);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a>(!%client.isAIControlled())\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " BanList::add(%client.guid, %client.getAddress(), $Pref::Server::KickBanTime);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %client.delete(\"You have been kicked from this server\");\n" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" )
DefineEngineMethod(GameConnection , getCameraObject , SimObject * , () , "@brief Returns the connection's camera object used when not viewing through the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@see <a href="/coding/class/classgameconnection/#classgameconnection_1a34ab83c3521274d2ebc44755892cedf5">GameConnection::setCameraObject</a>() and GameConnection::clearCameraObject()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )
DefineEngineMethod(GameConnection , getControlCameraDefaultFov , F32 , () , "@brief Returns the default field of view as used by the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">camera.\n\n</a>" )
DefineEngineMethod(GameConnection , getControlCameraFov , F32 , () , "@brief Returns the field of view as used by the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">camera.\n\n</a>" )
DefineEngineMethod(GameConnection , getControlObject , GameBase * , () , "@brief On the server, returns the object that the client is controlling." "By default the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object is an instance of the <a href="/coding/class/classplayer/">Player</a> class, but can also be an instance " "of  Camera, or any other <a href="/coding/class/classshapebase/">ShapeBase</a> derived class as " "appropriate <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">game.\n\n</a>" " @see <a href="/coding/class/classgameconnection/#classgameconnection_1aad985dd7714086beede38fd1a0ffa348">GameConnection::setControlObject</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )
DefineEngineMethod(GameConnection , getControlSchemeAbsoluteRotation , bool , () , "@brief Get the connection's <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> scheme absolute rotation <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">property.\n\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the connection's <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object should use an absolute rotation <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">scheme.\n\n</a>" "@see <a href="/coding/class/classgameconnection/#classgameconnection_1a2917e148fe52eb0d0eb8859d711664e6">GameConnection::setControlSchemeParameters</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )
DefineEngineMethod(GameConnection , getDamageFlash , F32 , () , "@brief On the client, get the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object 's damage flash <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">level.\n\n</a>" " @return flash <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">level\n</a>" )
DefineEngineMethod(GameConnection , getVisibleGhostDistance , F32 , () , "@brief Gets the distance that objects around the connection will be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ghosted.\n\n</a>" "@return <a href="/coding/file/types_8h/#types_8h_1a57a2244776e01ad620c556de58eb7880">S32</a> of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">distance.\n\n</a>" )
DefineEngineMethod(GameConnection , getWhiteOut , F32 , () , "@brief On the client, get the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object 's white-out <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">level.\n\n</a>" " @return white-out <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">level\n</a>" )
DefineEngineMethod(GameConnection , isAIControlled , bool , () , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> this connection is AI <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">controlled.\n\n</a>" "@see <a href="/coding/class/classaiconnection/">AIConnection</a>" )
DefineEngineMethod(GameConnection , isControlObjectRotDampedCamera , bool , () , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object being controlled by the client is making use " "of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> rotation damped <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">camera.\n\n</a>" "@see <a href="/coding/class/classcamera/">Camera</a>" )
DefineEngineMethod(GameConnection , isDemoPlaying , bool , () , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> previously recorded demo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> is now <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">playing.\n\n</a>" "@see GameConnection::playDemo()" )
DefineEngineMethod(GameConnection , isDemoRecording , bool , () , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> demo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> is now being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">recorded.\n\n</a>" "@see  GameConnection::startRecording, <a href="/coding/class/classnetconnection/#classnetconnection_1ac63a781c4ae8a788ffca957695eaa831">GameConnection::stopRecording</a>()" )
DefineEngineMethod(GameConnection , isFirstPerson , bool , () , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> this connection is in first person <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mode.\n\n</a>" "@note Transition <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> first person occurs over time via mCameraPos, so this " "won '<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a> immediately return true after <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n\n</a>" )
DefineEngineMethod(GameConnection , listClassIDs , void , () , "@brief List all of the classes that this connection knows about, and what their IDs are. Useful <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> debugging network <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">problems.\n\n</a>" " @note The list is sent <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">console.\n\n</a>" )
DefineEngineMethod(GameConnection , play2D , bool , (SFXProfile *profile) , "@brief Used on the server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> play <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 2D sound that is not attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> any <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param profile The <a href="/coding/class/classsfxprofile/">SFXProfile</a> that defines the sound <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">play.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function ServerPlay2D(%profile)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Play the given sound profile on every <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n</a>" "   // The sounds will be transmitted as an event, not attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> any <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "   <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a>(%<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a> = 0; %<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a> < ClientGroup.getCount(); %<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a>++)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      ClientGroup.getObject(%<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a>).play2D(%profile);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" )
DefineEngineMethod(GameConnection , play3D , bool , (SFXProfile *profile, TransformF location) , "@brief Used on the server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> play <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 3D sound that is not attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> any <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param profile The <a href="/coding/class/classsfxprofile/">SFXProfile</a> that defines the sound <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">play.\n</a>" "@param location The position and orientation of the 3D sound given in the form of \"x y z ax ay az aa\".\n\n" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function ServerPlay3D(%profile,%transform)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Play the given sound profile at the given position on every <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client\n</a>" "   // The sound will be transmitted as an event, not attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> any <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "   <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a>(%<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a> = 0; %<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a> < ClientGroup.getCount(); %<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a>++)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      ClientGroup.getObject(%<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a>).play3D(%profile,%transform);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" )
DefineEngineMethod(GameConnection , playDemo , bool , (const char *demoFileName) , "@brief On the client, play back <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> previously recorded game <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">session.\n\n</a>" "It is often useful <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> play back <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> game session. This could be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> producing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> " "demo of the game that will be shown at <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> later time, or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> debugging <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> game. " "By recording the entire network stream it is possible <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> later play game the game " "exactly as it unfolded during the actual play session. This is because all user " "<a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> and server results pass through the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connection.\n\n</a>" " @returns True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the playback was successful. False <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> there was an issue, such as " "not being able <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> open the demo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">playback.\n\n</a>" " @see  GameConnection::startRecording, <a href="/coding/class/classnetconnection/#classnetconnection_1ac63a781c4ae8a788ffca957695eaa831">GameConnection::stopRecording</a>()" )
DefineEngineMethod(GameConnection , resetGhosting , void , () , "@brief On the server, resets the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> indicate that ghosting has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disabled.\n\n</a>" "Typically when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> mission has ended on the server, all connected clients are informed of this change " "and their connections are reset back <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> starting state. This method resets <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection on the " "server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> indicate that ghosts are no longer being transmitted. On the client end, all ghost " "information will be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deleted.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//Inform the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">clients\n</a>" " <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a>(%clientIndex=0;%clientIndex< ClientGroup.getCount();%clientIndex++)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//clear ghosts and paths from all <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">clients\n</a>" " %cl=ClientGroup.getObject(%clientIndex);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %cl.endMission();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %cl.resetGhosting();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %cl.clearPaths();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " }\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see @ref ghosting_scoping <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> description of the ghosting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">system.\n\n</a>" )
DefineEngineMethod(GameConnection , setBlackOut , void , (bool doFade, S32 timeMS) , "@brief On the server, sets the client 's 3D display <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fade <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">black.\n\n</a>" " @param doFade Set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fade <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> black, and false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fade from <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">black.\n</a>" " @param timeMS Time it takes <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> perform the fade as measured in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ms.\n\n</a>" " @note Not currently hooked up, and is not synchronized over the network." )
DefineEngineMethod(GameConnection , setCameraObject , bool , (GameBase *camera) , "@brief On the server, set the connection 's camera object used when not viewing " "through the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" " @see <a href="/coding/class/classgameconnection/#classgameconnection_1a30d6982550f88f92023231129d150ffe">GameConnection::getCameraObject</a>() and GameConnection::clearCameraObject()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )
DefineEngineMethod(GameConnection , setControlCameraFov , void , (F32 newFOV) , "@brief On the server, sets the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object 's camera 's field of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">view.\n\n</a>" " @param newFOV New field of view(in degrees) <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> force the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object 's camera <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use. This <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> " "is clamped <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be within the range of 1 <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 179 <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">degrees.\n\n</a>" " @note When transmitted over the network <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client, the resolution is limited <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "one degree. Any fraction is dropped." )
DefineEngineMethod(GameConnection , setControlObject , bool , (GameBase *ctrlObj) , "@brief On the server, sets the object that the client will <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "By default the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object is an instance of the <a href="/coding/class/classplayer/">Player</a> class, but can also be an instance " "of  Camera, or any other <a href="/coding/class/classshapebase/">ShapeBase</a> derived class as " "appropriate <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">game.\n\n</a>" " @param ctrlObj The <a href="/coding/class/classgamebase/">GameBase</a> object on the server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> control." )
DefineEngineMethod(GameConnection , setControlSchemeParameters , void , (bool absoluteRotation, bool addYawToAbsRot, bool addPitchToAbsRot) , "@brief Set the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> scheme that may be used by <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection's <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param absoluteRotation Use absolute rotation values from client, likely through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ExtendedMove.\n</a>" " @param addYawToAbsRot Add relative yaw <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the absolute rotation calculation. Only useful when absoluteRotation is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">true.\n\n</a>" )
DefineEngineMethod(GameConnection , setFirstPerson , void , (bool firstPerson) , "@brief On the server, sets this connection into or out of first person <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mode.\n\n</a>" " @param firstPerson Set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> put the connection into first person <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mode.\n\n</a>" )
DefineEngineMethod(GameConnection , setJoinPassword , void , (const char *password) , "@brief On the client, set the password that will be passed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n\n</a>" "On the server, this password is compared with what is stored in $pref::Server::Password. " "If $pref::Server::Password is empty then the client 's sent password is ignored. Otherwise, " "<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the passed in client password and the server password do not match, the CHR_PASSWORD " "error string is sent back <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client and the connection is immediately <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">terminated.\n\n</a>" "This password checking is performed quite early on in the connection request process so as " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> minimize the impact of multiple failed attempts -- also known as hacking." )
DefineEngineMethod(GameConnection , setMissionCRC , void , (S32 CRC) , "@brief On the server, transmits the mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> 's CRC <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n\n</a>" " Typically, during the standard mission start phase 1, the mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> 's CRC <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> " "on the server is send <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client. This allows the client <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> determine <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the mission " "has changed since the last time it downloaded this mission and act appropriately, such as " "rebuilt cached <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">lightmaps.\n\n</a>" " @param CRC The mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> 's CRC <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function serverCmdMissionStartPhase1Ack(%client, %seq)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Make sure <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> ignore calls from <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> previous mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">load\n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a>(%seq !=$missionSequence||! $MissionRunning)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " return;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a>(%client.currentPhase !=0)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " return;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %client.currentPhase=1;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Start with the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">CRC\n</a>" " %client.setMissionCRC( $missionCRC);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Send over the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablocks...\n</a>" "//OnDataBlocksDone will get called when have <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">confirmation\n</a>" "//that they 've all been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">received.\n</a>" " %client.transmitDataBlocks($missionSequence);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" )
DefineEngineMethod(GameConnection , setVisibleGhostDistance , void , (F32 dist) , "@brief Sets the distance that objects around it will be ghosted. If set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 0, " "it may be defined by the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">LevelInfo.\n\n</a>" " @dist - is the max <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">distance\n\n</a>" )
DefineEngineMethod(GameConnection , startRecording , void , (const char *fileName) , "@brief On the client, starts recording the network connection 's traffic <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> demo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">file.\n\n</a>" "It is often useful <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> play back <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> game session. This could be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> producing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> " "demo of the game that will be shown at <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> later time, or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> debugging <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> game. " "By recording the entire network stream it is possible <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> later play game the game " "exactly as it unfolded during the actual play session. This is because all user " "<a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> and server results pass through the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connection.\n\n</a>" " @param fileName The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> name <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the demo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">recording.\n\n</a>" " @see  GameConnection::stopRecording, GameConnection::playDemo()" )
DefineEngineMethod(GameConnection , stopRecording , void , () , "@brief On the client, stops the recording of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection 's network traffic <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">file.\n\n</a>" " @see  GameConnection::startRecording, GameConnection::playDemo()" )
DefineEngineMethod(GameConnection , transmitDataBlocks , void , (S32 sequence) , "@brief Sent by the server during phase 1 of the mission download <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> send the datablocks <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n\n</a>" " SimDataBlocks, also known as just datablocks, need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be transmitted <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client " "prior <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client entering the game world. These represent the static data that " "most objects in the world reference. This is typically done during the standard " "mission start phase 1 when following Torque 's example mission startup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">sequence.\n\n</a>" "When the datablocks have all been transmitted, onDataBlocksDone() is called <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> move " "the mission start process <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the next phase." " @param sequence The sequence is common between the server and client and ensures " "that the client is acting on the most recent mission start process. If an errant " "network packet(one that was lost but has now been found) is received by the client " "with an incorrect sequence, it is just ignored. This sequence number is updated on " "the server every time <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> mission is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function serverCmdMissionStartPhase1Ack(%client, %seq)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Make sure <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> ignore calls from <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> previous mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">load\n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a>(%seq !=$missionSequence||! $MissionRunning)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " return;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a>(%client.currentPhase !=0)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " return;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %client.currentPhase=1;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Start with the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">CRC\n</a>" " %client.setMissionCRC( $missionCRC);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Send over the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablocks...\n</a>" "//OnDataBlocksDone will get called when have <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">confirmation\n</a>" "//that they 've all been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">received.\n</a>" " %client.transmitDataBlocks($missionSequence);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see GameConnection::onDataBlocksDone()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )
DefineEngineStaticMethod(GameConnection , getServerConnection , S32 , () , "@brief On the client, this static mehtod will return the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server, <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">any.\n\n</a>" " @returns The <a href="/coding/class/classsimobject/">SimObject</a> ID of the server connection, or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> none is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">found.\n\n</a>" )
DefineEngineStringlyVariadicMethod(GameConnection , setConnectArgs , void , 3 , 17 , "(const char* args) @brief On the client, pass along <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> variable set of parameters <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n\n</a>" "Once the connection is established with the server, the server calls its onConnect() method " "with the client 's passed in parameters as <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">aruments.\n\n</a>" " @see GameConnection::onConnect()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )
IMPLEMENT_CALLBACK(GameConnection , initialControlSet , void , () , () , "@brief Called on the client when the first <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object has been set by the " "server and we are now ready <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">go.\n\n</a>" "A common action <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> perform when this callback is called is <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> switch the GUI " "canvas from the loading screen and over <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the 3D game GUI." )
IMPLEMENT_CALLBACK(GameConnection , onConnectionAccepted , void , () , () , "@brief Called on the client when the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">established.\n\n</a>" )
IMPLEMENT_CALLBACK(GameConnection , onConnectionDropped , void , (const char *reason) , (reason) , "@brief Called on the client when the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dropped.\n\n</a>" "@param reason The reason why the connection was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dropped.\n\n</a>" )
IMPLEMENT_CALLBACK(GameConnection , onConnectionError , void , (const char *errorString) , (errorString) , "@brief Called on the client when there is an error with the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n\n</a>" "@param errorString The connection error <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">text.\n\n</a>" )
IMPLEMENT_CALLBACK(GameConnection , onConnectionTimedOut , void , () , () , "@brief Called on the client when the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server times <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">out.\n\n</a>" )
IMPLEMENT_CALLBACK(GameConnection , onConnectRequestRejected , void , (const char *reason) , (reason) , "@brief Called on the client when the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rejected.\n\n</a>" "@param reason The reason why the connection request was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rejected.\n\n</a>" )
IMPLEMENT_CALLBACK(GameConnection , onConnectRequestTimedOut , void , () , () , "@brief Called when connection attempts have timed <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">out.\n\n</a>" )
IMPLEMENT_CALLBACK(GameConnection , onControlObjectChange , void , () , () , "@brief Called on the client when the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object has been changed by the " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n\n</a>" )
IMPLEMENT_CALLBACK(GameConnection , onDataBlocksDone , void , (U32 sequence) , (sequence) , "@brief Called on the server when all datablocks has been sent <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n\n</a>" "During phase 1 of the mission download, all datablocks are sent from the server " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client. Once all datablocks have been sent, this callback is called and " "the mission download procedure may move on <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the next <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">phase.\n\n</a>" " @param sequence The sequence is common between the server and client and ensures " "that the client is acting on the most recent mission start process. If an errant " "network packet(one that was lost but has now been found) is received by the client " "with an incorrect sequence, it is just ignored. This sequence number is updated on " "the server every time <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> mission is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n\n</a>" " @see GameConnection::transmitDataBlocks()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )
IMPLEMENT_CALLBACK(GameConnection , onDrop , void , (const char *disconnectReason) , (disconnectReason) , "@brief Called on the server when the client's connection has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dropped.\n\n</a>" "@param disconnectReason The reason why the connection was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dropped.\n\n</a>" )
IMPLEMENT_CALLBACK(GameConnection , onFlash , void , (bool state) , (state) , "@brief Called on the client when the damage flash or white out states <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">change.\n\n</a>" "When the server changes the damage flash or white out values, this callback is called " "either is on or both are off. Typically this is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> enable the flash <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">postFx.\n\n</a>" " @param state Set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> either the damage flash or white out conditions are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">active.\n\n</a>" )
IMPLEMENT_CALLBACK(GameConnection , setLagIcon , void , (bool state) , (state) , "@brief Called on the client <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display the lag <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">icon.\n\n</a>" "When the connection with the server is lagging, this callback is called <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "allow the game GUI <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display some indicator <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">player.\n\n</a>" " @param state Set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the lag icon should be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">displayed.\n\n</a>" )
IMPLEMENT_GLOBAL_CALLBACK(onDataBlockObjectReceived , void , (U32 index, U32 total) , (index, total) , "@brief Called on the client each time <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> datablock has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">received.\n\n</a>" "This callback is typically used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/gamefunctions_8cpp/#gamefunctions_8cpp_1aa17ef8ef4f36199ef68ab2859f9fbda4">notify</a> the player of how far along " "in the datablock download process they <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">are.\n\n</a>" "@param index The index of the datablock just <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">received.\n</a>" "@param total The total number of datablocks <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">received.\n\n</a>" "@see GameConnection, GameConnection::transmitDataBlocks() , GameConnection::onDataBlocksDone()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Networking\n</a>" )

Detailed Description

Public Defines

ControlRequestTime() 5000
MAX_MOVE_PACKET_SENDS() 4

Public Variables

MatrixF * sChaseQueue 
S32 sChaseQueueHead 
S32 sChaseQueueSize 
S32 sChaseQueueTail 

Public Functions

ConsoleDocClass(GameConnection , "@brief The game-specific subclass of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">NetConnection.\n\n</a>" "The <a href="/coding/class/classgameconnection/">GameConnection</a> introduces the concept of the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object. The <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object " "is simply the object that the client is associated with that network connection controls. By " "default the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object is an instance of the <a href="/coding/class/classplayer/">Player</a> class, but can also be an instance " "of  Camera, or any other <a href="/coding/class/classshapebase/">ShapeBase</a> derived class as " "appropriate <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">game.\n\n</a>" "Torque uses <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> model in which the server is the authoritative master of the simulation. To " "prevent clients from cheating, the server simulates all player moves and then tells the " "client where his player is in the world. This model, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a0e48c1f64b558d03d870367324920354">while</a> secure, can have problems. If " "the network latency is high, this round-trip time can give the player <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> very noticeable sense " "of movement lag. To correct this problem, the game uses <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> form of prediction - it simulates " "the movement of the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object on the client and on the server both. This way the client " "doesn '<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a> need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> wait <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> round-trip verification of his moves. Only in the case of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> force " "acting on the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object on the server that doesn '<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a> exist on the client does the client 's " "position need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be forcefully <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">changed.\n\n</a>" "To support this, all <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> objects(derivative of <a href="/coding/class/classshapebase/">ShapeBase</a>) must supply <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> writePacketData() " "and readPacketData() function that send enough data <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> accurately simulate the object on the " "client. These functions are only called <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the current <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object, and only when the " "server can determine that the client 's simulation is somehow out of sync with the server. This " "occurs usually <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the client is affected by <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> force not present on the server(like an " "interpolating object) or <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the server object is affected by <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> server only force(such as the " "impulse from an explosion).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "The <a href="/coding/class/structmove/">Move</a> structure is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 32 millisecond snapshot of player input, containing x, y , and z " "positional and rotational changes as well as trigger state changes. When time passes in the " "simulation moves are  collected, and applied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the current " "<a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object on the client. The same moves are then packed over <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server in " " GameConnection::writePacket, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> processing on the server 's version of the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" " @see @ref Networking, <a href="/coding/class/classnetconnection/">NetConnection</a> , <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ShapeBase\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Networking\n</a>" )

DefineEngineMethod(GameConnection , activateGhosting , void , () , "@brief Called by the server during phase 2 of the mission download <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> start sending ghosts <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n\n</a>" "Ghosts represent objects on the server that are in scope <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the client. These need " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be synchronized with the client in order <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the client <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> see and interact with them. " "This is typically done during the standard mission start phase 2 when following Torque's " "example mission startup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">sequence.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function serverCmdMissionStartPhase2Ack(%client, %seq, %playerDB)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Make sure <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> ignore calls from <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> previous mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">load\n</a>" "   <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> (%seq != $missionSequence || !$MissionRunning)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      return;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> (%client.currentPhase != 1.5)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      return;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   %client.currentPhase = 2;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Set the player datablock <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">choice\n</a>" "   %client.playerDB = %playerDB;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Update mod paths, this needs <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get there before the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">objects.\n</a>" "   %client.transmitPaths();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Start ghosting objects <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client\n</a>" "   %client.activateGhosting();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see @ref ghosting_scoping <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> description of the ghosting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">system.\n\n</a>" )

DefineEngineMethod(GameConnection , chaseCam , bool , (S32 size) , "@brief Sets the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of the chase camera's matrix <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">queue.\n\n</a>" "@note This sets the queue <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> across all <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GameConnections.\n\n</a>" "@note This is not currently hooked <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">up.\n\n</a>" )

DefineEngineMethod(GameConnection , clearCameraObject , void , () , "@brief Clear the connection's camera object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">reference.\n\n</a>" "@see <a href="/coding/class/classgameconnection/#classgameconnection_1a34ab83c3521274d2ebc44755892cedf5">GameConnection::setCameraObject</a>() and <a href="/coding/class/classgameconnection/#classgameconnection_1a30d6982550f88f92023231129d150ffe">GameConnection::getCameraObject</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )

DefineEngineMethod(GameConnection , clearDisplayDevice , void , () , "@brief Clear any display <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">device.\n\n</a>" "A display device may define <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> number of properties that are used during <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rendering.\n\n</a>" )

DefineEngineMethod(GameConnection , delete , void , (const char *reason) , ("") , "@brief On the server, disconnect <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> client and pass along an optional reason <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">why.\n\n</a>" "This method performs two operations:it disconnects <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> client connection from the server, " "and it deletes the connection object. The optional reason is sent in the disconnect packet " "and is often displayed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the user so they know why they 've been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disconnected.\n\n</a>" " @param reason The reason why the user has been disconnected from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function kick(%client)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " messageAll( 'MsgAdminForce', '\\c2The Admin has kicked %1.', %client.playerName);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a>(!%client.isAIControlled())\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " BanList::add(%client.guid, %client.getAddress(), $Pref::Server::KickBanTime);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %client.delete(\"You have been kicked from this server\");\n" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" )

DefineEngineMethod(GameConnection , getCameraObject , SimObject * , () , "@brief Returns the connection's camera object used when not viewing through the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@see <a href="/coding/class/classgameconnection/#classgameconnection_1a34ab83c3521274d2ebc44755892cedf5">GameConnection::setCameraObject</a>() and GameConnection::clearCameraObject()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )

DefineEngineMethod(GameConnection , getControlCameraDefaultFov , F32 , () , "@brief Returns the default field of view as used by the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">camera.\n\n</a>" )

DefineEngineMethod(GameConnection , getControlCameraFov , F32 , () , "@brief Returns the field of view as used by the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">camera.\n\n</a>" )

DefineEngineMethod(GameConnection , getControlObject , GameBase * , () , "@brief On the server, returns the object that the client is controlling." "By default the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object is an instance of the <a href="/coding/class/classplayer/">Player</a> class, but can also be an instance " "of  Camera, or any other <a href="/coding/class/classshapebase/">ShapeBase</a> derived class as " "appropriate <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">game.\n\n</a>" " @see <a href="/coding/class/classgameconnection/#classgameconnection_1aad985dd7714086beede38fd1a0ffa348">GameConnection::setControlObject</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )

DefineEngineMethod(GameConnection , getControlSchemeAbsoluteRotation , bool , () , "@brief Get the connection's <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> scheme absolute rotation <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">property.\n\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the connection's <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object should use an absolute rotation <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">scheme.\n\n</a>" "@see <a href="/coding/class/classgameconnection/#classgameconnection_1a2917e148fe52eb0d0eb8859d711664e6">GameConnection::setControlSchemeParameters</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )

DefineEngineMethod(GameConnection , getDamageFlash , F32 , () , "@brief On the client, get the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object 's damage flash <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">level.\n\n</a>" " @return flash <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">level\n</a>" )

DefineEngineMethod(GameConnection , getVisibleGhostDistance , F32 , () , "@brief Gets the distance that objects around the connection will be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ghosted.\n\n</a>" "@return <a href="/coding/file/types_8h/#types_8h_1a57a2244776e01ad620c556de58eb7880">S32</a> of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">distance.\n\n</a>" )

DefineEngineMethod(GameConnection , getWhiteOut , F32 , () , "@brief On the client, get the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object 's white-out <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">level.\n\n</a>" " @return white-out <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">level\n</a>" )

DefineEngineMethod(GameConnection , isAIControlled , bool , () , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> this connection is AI <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">controlled.\n\n</a>" "@see <a href="/coding/class/classaiconnection/">AIConnection</a>" )

DefineEngineMethod(GameConnection , isControlObjectRotDampedCamera , bool , () , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object being controlled by the client is making use " "of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> rotation damped <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">camera.\n\n</a>" "@see <a href="/coding/class/classcamera/">Camera</a>" )

DefineEngineMethod(GameConnection , isDemoPlaying , bool , () , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> previously recorded demo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> is now <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">playing.\n\n</a>" "@see GameConnection::playDemo()" )

DefineEngineMethod(GameConnection , isDemoRecording , bool , () , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> demo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> is now being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">recorded.\n\n</a>" "@see  GameConnection::startRecording, <a href="/coding/class/classnetconnection/#classnetconnection_1ac63a781c4ae8a788ffca957695eaa831">GameConnection::stopRecording</a>()" )

DefineEngineMethod(GameConnection , isFirstPerson , bool , () , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> this connection is in first person <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mode.\n\n</a>" "@note Transition <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> first person occurs over time via mCameraPos, so this " "won '<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a> immediately return true after <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n\n</a>" )

DefineEngineMethod(GameConnection , listClassIDs , void , () , "@brief List all of the classes that this connection knows about, and what their IDs are. Useful <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> debugging network <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">problems.\n\n</a>" " @note The list is sent <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">console.\n\n</a>" )

DefineEngineMethod(GameConnection , play2D , bool , (SFXProfile *profile) , "@brief Used on the server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> play <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 2D sound that is not attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> any <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param profile The <a href="/coding/class/classsfxprofile/">SFXProfile</a> that defines the sound <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">play.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function ServerPlay2D(%profile)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Play the given sound profile on every <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n</a>" "   // The sounds will be transmitted as an event, not attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> any <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "   <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a>(%<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a> = 0; %<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a> < ClientGroup.getCount(); %<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a>++)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      ClientGroup.getObject(%<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a>).play2D(%profile);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" )

DefineEngineMethod(GameConnection , play3D , bool , (SFXProfile *profile, TransformF location) , "@brief Used on the server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> play <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 3D sound that is not attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> any <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param profile The <a href="/coding/class/classsfxprofile/">SFXProfile</a> that defines the sound <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">play.\n</a>" "@param location The position and orientation of the 3D sound given in the form of \"x y z ax ay az aa\".\n\n" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function ServerPlay3D(%profile,%transform)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Play the given sound profile at the given position on every <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client\n</a>" "   // The sound will be transmitted as an event, not attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> any <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "   <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a>(%<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a> = 0; %<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a> < ClientGroup.getCount(); %<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a>++)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      ClientGroup.getObject(%<a href="/coding/file/mquat_8cpp/#mquat_8cpp_1ad66b7690eb5b70f95cb7cb584e91c9ea">idx</a>).play3D(%profile,%transform);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" )

DefineEngineMethod(GameConnection , playDemo , bool , (const char *demoFileName) , "@brief On the client, play back <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> previously recorded game <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">session.\n\n</a>" "It is often useful <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> play back <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> game session. This could be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> producing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> " "demo of the game that will be shown at <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> later time, or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> debugging <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> game. " "By recording the entire network stream it is possible <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> later play game the game " "exactly as it unfolded during the actual play session. This is because all user " "<a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> and server results pass through the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connection.\n\n</a>" " @returns True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the playback was successful. False <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> there was an issue, such as " "not being able <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> open the demo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">playback.\n\n</a>" " @see  GameConnection::startRecording, <a href="/coding/class/classnetconnection/#classnetconnection_1ac63a781c4ae8a788ffca957695eaa831">GameConnection::stopRecording</a>()" )

DefineEngineMethod(GameConnection , resetGhosting , void , () , "@brief On the server, resets the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> indicate that ghosting has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disabled.\n\n</a>" "Typically when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> mission has ended on the server, all connected clients are informed of this change " "and their connections are reset back <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> starting state. This method resets <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection on the " "server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> indicate that ghosts are no longer being transmitted. On the client end, all ghost " "information will be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deleted.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//Inform the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">clients\n</a>" " <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a>(%clientIndex=0;%clientIndex< ClientGroup.getCount();%clientIndex++)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//clear ghosts and paths from all <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">clients\n</a>" " %cl=ClientGroup.getObject(%clientIndex);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %cl.endMission();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %cl.resetGhosting();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %cl.clearPaths();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " }\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see @ref ghosting_scoping <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> description of the ghosting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">system.\n\n</a>" )

DefineEngineMethod(GameConnection , setBlackOut , void , (bool doFade, S32 timeMS) , "@brief On the server, sets the client 's 3D display <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fade <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">black.\n\n</a>" " @param doFade Set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fade <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> black, and false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fade from <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">black.\n</a>" " @param timeMS Time it takes <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> perform the fade as measured in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ms.\n\n</a>" " @note Not currently hooked up, and is not synchronized over the network." )

DefineEngineMethod(GameConnection , setCameraObject , bool , (GameBase *camera) , "@brief On the server, set the connection 's camera object used when not viewing " "through the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" " @see <a href="/coding/class/classgameconnection/#classgameconnection_1a30d6982550f88f92023231129d150ffe">GameConnection::getCameraObject</a>() and GameConnection::clearCameraObject()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )

DefineEngineMethod(GameConnection , setControlCameraFov , void , (F32 newFOV) , "@brief On the server, sets the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object 's camera 's field of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">view.\n\n</a>" " @param newFOV New field of view(in degrees) <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> force the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object 's camera <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use. This <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> " "is clamped <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be within the range of 1 <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 179 <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">degrees.\n\n</a>" " @note When transmitted over the network <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client, the resolution is limited <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "one degree. Any fraction is dropped." )

DefineEngineMethod(GameConnection , setControlObject , bool , (GameBase *ctrlObj) , "@brief On the server, sets the object that the client will <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "By default the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object is an instance of the <a href="/coding/class/classplayer/">Player</a> class, but can also be an instance " "of  Camera, or any other <a href="/coding/class/classshapebase/">ShapeBase</a> derived class as " "appropriate <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">game.\n\n</a>" " @param ctrlObj The <a href="/coding/class/classgamebase/">GameBase</a> object on the server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> control." )

DefineEngineMethod(GameConnection , setControlSchemeParameters , void , (bool absoluteRotation, bool addYawToAbsRot, bool addPitchToAbsRot) , "@brief Set the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> scheme that may be used by <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection's <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param absoluteRotation Use absolute rotation values from client, likely through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ExtendedMove.\n</a>" " @param addYawToAbsRot Add relative yaw <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the absolute rotation calculation. Only useful when absoluteRotation is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">true.\n\n</a>" )

DefineEngineMethod(GameConnection , setFirstPerson , void , (bool firstPerson) , "@brief On the server, sets this connection into or out of first person <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mode.\n\n</a>" " @param firstPerson Set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> put the connection into first person <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mode.\n\n</a>" )

DefineEngineMethod(GameConnection , setJoinPassword , void , (const char *password) , "@brief On the client, set the password that will be passed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n\n</a>" "On the server, this password is compared with what is stored in $pref::Server::Password. " "If $pref::Server::Password is empty then the client 's sent password is ignored. Otherwise, " "<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the passed in client password and the server password do not match, the CHR_PASSWORD " "error string is sent back <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client and the connection is immediately <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">terminated.\n\n</a>" "This password checking is performed quite early on in the connection request process so as " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> minimize the impact of multiple failed attempts -- also known as hacking." )

DefineEngineMethod(GameConnection , setMissionCRC , void , (S32 CRC) , "@brief On the server, transmits the mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> 's CRC <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n\n</a>" " Typically, during the standard mission start phase 1, the mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> 's CRC <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> " "on the server is send <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client. This allows the client <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> determine <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the mission " "has changed since the last time it downloaded this mission and act appropriately, such as " "rebuilt cached <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">lightmaps.\n\n</a>" " @param CRC The mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> 's CRC <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function serverCmdMissionStartPhase1Ack(%client, %seq)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Make sure <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> ignore calls from <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> previous mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">load\n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a>(%seq !=$missionSequence||! $MissionRunning)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " return;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a>(%client.currentPhase !=0)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " return;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %client.currentPhase=1;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Start with the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">CRC\n</a>" " %client.setMissionCRC( $missionCRC);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Send over the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablocks...\n</a>" "//OnDataBlocksDone will get called when have <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">confirmation\n</a>" "//that they 've all been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">received.\n</a>" " %client.transmitDataBlocks($missionSequence);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" )

DefineEngineMethod(GameConnection , setVisibleGhostDistance , void , (F32 dist) , "@brief Sets the distance that objects around it will be ghosted. If set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 0, " "it may be defined by the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">LevelInfo.\n\n</a>" " @dist - is the max <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">distance\n\n</a>" )

DefineEngineMethod(GameConnection , startRecording , void , (const char *fileName) , "@brief On the client, starts recording the network connection 's traffic <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> demo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">file.\n\n</a>" "It is often useful <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> play back <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> game session. This could be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> producing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> " "demo of the game that will be shown at <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> later time, or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> debugging <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> game. " "By recording the entire network stream it is possible <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> later play game the game " "exactly as it unfolded during the actual play session. This is because all user " "<a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> and server results pass through the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connection.\n\n</a>" " @param fileName The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> name <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the demo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">recording.\n\n</a>" " @see  GameConnection::stopRecording, GameConnection::playDemo()" )

DefineEngineMethod(GameConnection , stopRecording , void , () , "@brief On the client, stops the recording of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection 's network traffic <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">file.\n\n</a>" " @see  GameConnection::startRecording, GameConnection::playDemo()" )

DefineEngineMethod(GameConnection , transmitDataBlocks , void , (S32 sequence) , "@brief Sent by the server during phase 1 of the mission download <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> send the datablocks <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n\n</a>" " SimDataBlocks, also known as just datablocks, need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be transmitted <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client " "prior <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client entering the game world. These represent the static data that " "most objects in the world reference. This is typically done during the standard " "mission start phase 1 when following Torque 's example mission startup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">sequence.\n\n</a>" "When the datablocks have all been transmitted, onDataBlocksDone() is called <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> move " "the mission start process <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the next phase." " @param sequence The sequence is common between the server and client and ensures " "that the client is acting on the most recent mission start process. If an errant " "network packet(one that was lost but has now been found) is received by the client " "with an incorrect sequence, it is just ignored. This sequence number is updated on " "the server every time <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> mission is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function serverCmdMissionStartPhase1Ack(%client, %seq)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Make sure <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> ignore calls from <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> previous mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">load\n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a>(%seq !=$missionSequence||! $MissionRunning)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " return;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a>(%client.currentPhase !=0)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " return;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %client.currentPhase=1;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Start with the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">CRC\n</a>" " %client.setMissionCRC( $missionCRC);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Send over the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablocks...\n</a>" "//OnDataBlocksDone will get called when have <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">confirmation\n</a>" "//that they 've all been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">received.\n</a>" " %client.transmitDataBlocks($missionSequence);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see GameConnection::onDataBlocksDone()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )

DefineEngineStaticMethod(GameConnection , getServerConnection , S32 , () , "@brief On the client, this static mehtod will return the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server, <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">any.\n\n</a>" " @returns The <a href="/coding/class/classsimobject/">SimObject</a> ID of the server connection, or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> none is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">found.\n\n</a>" )

DefineEngineStringlyVariadicMethod(GameConnection , setConnectArgs , void , 3 , 17 , "(const char* args) @brief On the client, pass along <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> variable set of parameters <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n\n</a>" "Once the connection is established with the server, the server calls its onConnect() method " "with the client 's passed in parameters as <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">aruments.\n\n</a>" " @see GameConnection::onConnect()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )

IMPLEMENT_CALLBACK(GameConnection , initialControlSet , void , () , () , "@brief Called on the client when the first <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object has been set by the " "server and we are now ready <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">go.\n\n</a>" "A common action <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> perform when this callback is called is <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> switch the GUI " "canvas from the loading screen and over <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the 3D game GUI." )

IMPLEMENT_CALLBACK(GameConnection , onConnectionAccepted , void , () , () , "@brief Called on the client when the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">established.\n\n</a>" )

IMPLEMENT_CALLBACK(GameConnection , onConnectionDropped , void , (const char *reason) , (reason) , "@brief Called on the client when the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dropped.\n\n</a>" "@param reason The reason why the connection was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dropped.\n\n</a>" )

IMPLEMENT_CALLBACK(GameConnection , onConnectionError , void , (const char *errorString) , (errorString) , "@brief Called on the client when there is an error with the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n\n</a>" "@param errorString The connection error <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">text.\n\n</a>" )

IMPLEMENT_CALLBACK(GameConnection , onConnectionTimedOut , void , () , () , "@brief Called on the client when the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server times <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">out.\n\n</a>" )

IMPLEMENT_CALLBACK(GameConnection , onConnectRequestRejected , void , (const char *reason) , (reason) , "@brief Called on the client when the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rejected.\n\n</a>" "@param reason The reason why the connection request was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rejected.\n\n</a>" )

IMPLEMENT_CALLBACK(GameConnection , onConnectRequestTimedOut , void , () , () , "@brief Called when connection attempts have timed <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">out.\n\n</a>" )

IMPLEMENT_CALLBACK(GameConnection , onControlObjectChange , void , () , () , "@brief Called on the client when the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object has been changed by the " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n\n</a>" )

IMPLEMENT_CALLBACK(GameConnection , onDataBlocksDone , void , (U32 sequence) , (sequence) , "@brief Called on the server when all datablocks has been sent <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n\n</a>" "During phase 1 of the mission download, all datablocks are sent from the server " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client. Once all datablocks have been sent, this callback is called and " "the mission download procedure may move on <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the next <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">phase.\n\n</a>" " @param sequence The sequence is common between the server and client and ensures " "that the client is acting on the most recent mission start process. If an errant " "network packet(one that was lost but has now been found) is received by the client " "with an incorrect sequence, it is just ignored. This sequence number is updated on " "the server every time <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> mission is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n\n</a>" " @see GameConnection::transmitDataBlocks()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" )

IMPLEMENT_CALLBACK(GameConnection , onDrop , void , (const char *disconnectReason) , (disconnectReason) , "@brief Called on the server when the client's connection has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dropped.\n\n</a>" "@param disconnectReason The reason why the connection was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">dropped.\n\n</a>" )

IMPLEMENT_CALLBACK(GameConnection , onFlash , void , (bool state) , (state) , "@brief Called on the client when the damage flash or white out states <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">change.\n\n</a>" "When the server changes the damage flash or white out values, this callback is called " "either is on or both are off. Typically this is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> enable the flash <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">postFx.\n\n</a>" " @param state Set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> either the damage flash or white out conditions are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">active.\n\n</a>" )

IMPLEMENT_CALLBACK(GameConnection , setLagIcon , void , (bool state) , (state) , "@brief Called on the client <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display the lag <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">icon.\n\n</a>" "When the connection with the server is lagging, this callback is called <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "allow the game GUI <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display some indicator <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">player.\n\n</a>" " @param state Set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the lag icon should be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">displayed.\n\n</a>" )

IMPLEMENT_CONOBJECT(GameConnection )

IMPLEMENT_GLOBAL_CALLBACK(onDataBlockObjectReceived , void , (U32 index, U32 total) , (index, total) , "@brief Called on the client each time <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> datablock has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">received.\n\n</a>" "This callback is typically used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/gamefunctions_8cpp/#gamefunctions_8cpp_1aa17ef8ef4f36199ef68ab2859f9fbda4">notify</a> the player of how far along " "in the datablock download process they <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">are.\n\n</a>" "@param index The index of the datablock just <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">received.\n</a>" "@param total The total number of datablocks <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">received.\n\n</a>" "@see GameConnection, GameConnection::transmitDataBlocks() , GameConnection::onDataBlocksDone()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Networking\n</a>" )

   1
   2//-----------------------------------------------------------------------------
   3// Copyright (c) 2012 GarageGames, LLC
   4//
   5// Permission is hereby granted, free of charge, to any person obtaining a copy
   6// of this software and associated documentation files (the "Software"), to
   7// deal in the Software without restriction, including without limitation the
   8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   9// sell copies of the Software, and to permit persons to whom the Software is
  10// furnished to do so, subject to the following conditions:
  11//
  12// The above copyright notice and this permission notice shall be included in
  13// all copies or substantial portions of the Software.
  14//
  15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21// IN THE SOFTWARE.
  22//-----------------------------------------------------------------------------
  23
  24//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  25// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  26// Copyright (C) 2015 Faust Logic, Inc.
  27//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  28
  29#include "platform/platform.h"
  30#include "T3D/gameBase/gameConnection.h"
  31
  32#include "platform/profiler.h"
  33#include "core/dnet.h"
  34#include "core/util/safeDelete.h"
  35#include "core/stream/bitStream.h"
  36#include "console/consoleTypes.h"
  37#include "console/simBase.h"
  38#include "sfx/sfxProfile.h"
  39#include "sfx/sfxDescription.h"
  40#include "app/game.h"
  41#include "app/auth.h"
  42#include "T3D/camera.h"
  43#include "T3D/gameBase/gameProcess.h"
  44#include "T3D/gameBase/gameConnectionEvents.h"
  45#include "console/engineAPI.h"
  46#include "math/mTransform.h"
  47
  48#ifdef TORQUE_HIFI_NET
  49   #include "T3D/gameBase/hifi/hifiMoveList.h"
  50#elif defined TORQUE_EXTENDED_MOVE
  51   #include "T3D/gameBase/extended/extendedMoveList.h"
  52#else
  53   #include "T3D/gameBase/std/stdMoveList.h"
  54#endif
  55
  56#ifdef AFX_CAP_DATABLOCK_CACHE 
  57#include "core/stream/fileStream.h"
  58#endif 
  59
  60#ifdef TORQUE_AFX_ENABLED
  61#include "afx/arcaneFX.h"
  62#endif
  63//----------------------------------------------------------------------------
  64#define MAX_MOVE_PACKET_SENDS 4
  65
  66#define ControlRequestTime 5000
  67
  68const U32 GameConnection::CurrentProtocolVersion = 12;
  69const U32 GameConnection::MinRequiredProtocolVersion = 12;
  70
  71//----------------------------------------------------------------------------
  72
  73IMPLEMENT_CONOBJECT(GameConnection);
  74S32 GameConnection::mLagThresholdMS = 0;
  75Signal<void(F32)> GameConnection::smFovUpdate;
  76Signal<void()>    GameConnection::smPlayingDemo;
  77
  78ConsoleDocClass( GameConnection,
  79   "@brief The game-specific subclass of NetConnection.\n\n"
  80   
  81   "The GameConnection introduces the concept of the control object.  The control object "
  82   "is simply the object that the client is associated with that network connection controls.  By "
  83   "default the control object is an instance of the Player class, but can also be an instance "
  84   "of Camera (when editing the mission, for example), or any other ShapeBase derived class as "
  85   "appropriate for the game.\n\n"
  86
  87   "Torque uses a model in which the server is the authoritative master of the simulation.  To "
  88   "prevent clients from cheating, the server simulates all player moves and then tells the "
  89   "client where his player is in the world.  This model, while secure, can have problems.  If "
  90   "the network latency is high, this round-trip time can give the player a very noticeable sense "
  91   "of movement lag.  To correct this problem, the game uses a form of prediction - it simulates "
  92   "the movement of the control object on the client and on the server both.  This way the client "
  93   "doesn't need to wait for round-trip verification of his moves.  Only in the case of a force "
  94   "acting on the control object on the server that doesn't exist on the client does the client's "
  95   "position need to be forcefully changed.\n\n"
  96
  97   "To support this, all control objects (derivative of ShapeBase) must supply a writePacketData() "
  98   "and readPacketData() function that send enough data to accurately simulate the object on the "
  99   "client.  These functions are only called for the current control object, and only when the "
 100   "server can determine that the client's simulation is somehow out of sync with the server.  This "
 101   "occurs usually if the client is affected by a force not present on the server (like an "
 102   "interpolating object) or if the server object is affected by a server only force (such as the "
 103   "impulse from an explosion).\n\n"
 104
 105   "The Move structure is a 32 millisecond snapshot of player input, containing x, y, and z "
 106   "positional and rotational changes as well as trigger state changes. When time passes in the "
 107   "simulation moves are collected (depending on how much time passes), and applied to the current "
 108   "control object on the client. The same moves are then packed over to the server in "
 109   "GameConnection::writePacket(), for processing on the server's version of the control object.\n\n"
 110
 111   "@see @ref Networking, NetConnection, ShapeBase\n\n"
 112
 113   "@ingroup Networking\n");
 114
 115//----------------------------------------------------------------------------
 116IMPLEMENT_CALLBACK( GameConnection, onConnectionTimedOut, void, (), (),
 117   "@brief Called on the client when the connection to the server times out.\n\n");
 118
 119IMPLEMENT_CALLBACK( GameConnection, onConnectionAccepted, void, (), (),
 120   "@brief Called on the client when the connection to the server has been established.\n\n");
 121
 122IMPLEMENT_CALLBACK( GameConnection, onConnectRequestTimedOut, void, (), (),
 123   "@brief Called when connection attempts have timed out.\n\n");
 124
 125IMPLEMENT_CALLBACK( GameConnection, onConnectionDropped, void, (const char* reason), (reason),
 126   "@brief Called on the client when the connection to the server has been dropped.\n\n"
 127   "@param reason The reason why the connection was dropped.\n\n");
 128
 129IMPLEMENT_CALLBACK( GameConnection, onConnectRequestRejected, void, (const char* reason), (reason),
 130   "@brief Called on the client when the connection to the server has been rejected.\n\n"
 131   "@param reason The reason why the connection request was rejected.\n\n");
 132
 133IMPLEMENT_CALLBACK( GameConnection, onConnectionError, void, (const char* errorString), (errorString),
 134   "@brief Called on the client when there is an error with the connection to the server.\n\n"
 135   "@param errorString The connection error text.\n\n");
 136
 137IMPLEMENT_CALLBACK( GameConnection, onDrop, void, (const char* disconnectReason), (disconnectReason),
 138   "@brief Called on the server when the client's connection has been dropped.\n\n"
 139   "@param disconnectReason The reason why the connection was dropped.\n\n");
 140
 141IMPLEMENT_CALLBACK( GameConnection, initialControlSet, void, (), (),
 142   "@brief Called on the client when the first control object has been set by the "
 143   "server and we are now ready to go.\n\n"
 144   "A common action to perform when this callback is called is to switch the GUI "
 145   "canvas from the loading screen and over to the 3D game GUI.");
 146
 147IMPLEMENT_CALLBACK( GameConnection, onControlObjectChange, void, (), (),
 148   "@brief Called on the client when the control object has been changed by the "
 149   "server.\n\n");
 150
 151IMPLEMENT_CALLBACK( GameConnection, setLagIcon, void, (bool state), (state),
 152   "@brief Called on the client to display the lag icon.\n\n"
 153   "When the connection with the server is lagging, this callback is called to "
 154   "allow the game GUI to display some indicator to the player.\n\n"
 155   "@param state Set to true if the lag icon should be displayed.\n\n");
 156
 157IMPLEMENT_CALLBACK( GameConnection, onDataBlocksDone, void, (U32 sequence), (sequence),
 158   "@brief Called on the server when all datablocks has been sent to the client.\n\n"
 159   "During phase 1 of the mission download, all datablocks are sent from the server "
 160   "to the client.  Once all datablocks have been sent, this callback is called and "
 161   "the mission download procedure may move on to the next phase.\n\n"
 162   "@param sequence The sequence is common between the server and client and ensures "
 163   "that the client is acting on the most recent mission start process.  If an errant "
 164   "network packet (one that was lost but has now been found) is received by the client "
 165   "with an incorrect sequence, it is just ignored.  This sequence number is updated on "
 166   "the server every time a mission is loaded.\n\n"
 167   "@see GameConnection::transmitDataBlocks()\n\n");
 168
 169IMPLEMENT_GLOBAL_CALLBACK( onDataBlockObjectReceived, void, (U32 index, U32 total), (index, total),
 170   "@brief Called on the client each time a datablock has been received.\n\n"
 171   "This callback is typically used to notify the player of how far along "
 172   "in the datablock download process they are.\n\n"
 173   "@param index The index of the datablock just received.\n"
 174   "@param total The total number of datablocks to be received.\n\n"
 175   "@see GameConnection, GameConnection::transmitDataBlocks(), GameConnection::onDataBlocksDone()\n\n"
 176   "@ingroup Networking\n");
 177
 178IMPLEMENT_CALLBACK( GameConnection, onFlash, void, (bool state), (state),
 179   "@brief Called on the client when the damage flash or white out states change.\n\n"
 180   "When the server changes the damage flash or white out values, this callback is called "
 181   "either is on or both are off.  Typically this is used to enable the flash postFx.\n\n"
 182   "@param state Set to true if either the damage flash or white out conditions are active.\n\n");
 183
 184#ifdef AFX_CAP_DATABLOCK_CACHE 
 185StringTableEntry GameConnection::server_cache_filename = "";
 186StringTableEntry GameConnection::client_cache_filename = "";
 187bool GameConnection::server_cache_on = false;
 188bool GameConnection::client_cache_on = false;
 189#endif 
 190//----------------------------------------------------------------------------
 191GameConnection::GameConnection()
 192{
 193#ifdef TORQUE_AFX_ENABLED
 194   mRolloverObj = NULL;
 195   mPreSelectedObj = NULL;
 196   mSelectedObj = NULL;
 197   mChangedSelectedObj = false;
 198   mPreSelectTimestamp = 0;
 199   zoned_in = false;
 200#endif
 201   
 202#ifdef AFX_CAP_DATABLOCK_CACHE 
 203   client_db_stream = new InfiniteBitStream;
 204   server_cache_CRC = 0xffffffff;
 205#endif 
 206   mLagging = false;
 207   mControlObject = NULL;
 208   mCameraObject = NULL;
 209
 210#ifdef TORQUE_HIFI_NET
 211   mMoveList = new HifiMoveList();
 212#elif defined TORQUE_EXTENDED_MOVE
 213   mMoveList = new ExtendedMoveList();
 214#else
 215   mMoveList = new StdMoveList();
 216#endif
 217
 218   mMoveList->setConnection( this );
 219
 220   mDataBlockModifiedKey = 0;
 221   mMaxDataBlockModifiedKey = 0;
 222   mAuthInfo = NULL;
 223   mControlForceMismatch = false;
 224   mConnectArgc = 0;
 225
 226   for(U32 i = 0; i < MaxConnectArgs; i++)
 227      mConnectArgv[i] = 0;
 228
 229   mJoinPassword = NULL;
 230
 231   mMissionCRC = 0xffffffff;
 232
 233   mDamageFlash = mWhiteOut = 0;
 234
 235   mCameraPos = 0;
 236   mCameraSpeed = 10;
 237
 238   mCameraFov = 90.f;
 239   mUpdateCameraFov = false;
 240
 241   mAIControlled = false;
 242
 243   mLastPacketTime = 0;
 244
 245   mDisconnectReason[0] = 0;
 246
 247   //blackout vars
 248   mBlackOut = 0.0f;
 249   mBlackOutTimeMS = 0;
 250   mBlackOutStartTimeMS = 0;
 251   mFadeToBlack = false;
 252
 253   // first person
 254   mFirstPerson = true;
 255   mUpdateFirstPerson = false;
 256
 257   // Control scheme
 258   mUpdateControlScheme = false;
 259   mAbsoluteRotation = false;
 260   mAddYawToAbsRot = false;
 261   mAddPitchToAbsRot = false;
 262
 263   mVisibleGhostDistance = 0.0f;
 264
 265   clearDisplayDevice();
 266}
 267
 268GameConnection::~GameConnection()
 269{
 270   setDisplayDevice(NULL);
 271   delete mAuthInfo;
 272   for(U32 i = 0; i < mConnectArgc; i++)
 273      dFree(mConnectArgv[i]);
 274   dFree(mJoinPassword);
 275   delete mMoveList;
 276
 277#ifdef AFX_CAP_DATABLOCK_CACHE
 278   delete client_db_stream;
 279#endif 
 280}
 281
 282//----------------------------------------------------------------------------
 283
 284void GameConnection::setVisibleGhostDistance(F32 dist)
 285{
 286   mVisibleGhostDistance = dist;
 287}
 288
 289F32 GameConnection::getVisibleGhostDistance()
 290{
 291   return mVisibleGhostDistance;
 292}
 293
 294bool GameConnection::canRemoteCreate()
 295{
 296   return true;
 297}
 298
 299void GameConnection::setConnectArgs(U32 argc, const char **argv)
 300{
 301   if(argc > MaxConnectArgs)
 302      argc = MaxConnectArgs;
 303   mConnectArgc = argc;
 304   for(U32 i = 0; i < mConnectArgc; i++)
 305      mConnectArgv[i] = dStrdup(argv[i]);
 306}
 307
 308void GameConnection::setJoinPassword(const char *password)
 309{
 310   mJoinPassword = dStrdup(password);
 311}
 312
 313DefineEngineMethod( GameConnection, setJoinPassword, void, (const char* password),,
 314              "@brief On the client, set the password that will be passed to the server.\n\n"
 315              
 316              "On the server, this password is compared with what is stored in $pref::Server::Password.  "
 317              "If $pref::Server::Password is empty then the client's sent password is ignored.  Otherwise, "
 318              "if the passed in client password and the server password do not match, the CHR_PASSWORD "
 319              "error string is sent back to the client and the connection is immediately terminated.\n\n"
 320              
 321              "This password checking is performed quite early on in the connection request process so as "
 322              "to minimize the impact of multiple failed attempts -- also known as hacking.")
 323{
 324   object->setJoinPassword(password);
 325}
 326
 327DefineEngineStringlyVariadicMethod(GameConnection, setConnectArgs, void, 3, 17,
 328   "(const char* args) @brief On the client, pass along a variable set of parameters to the server.\n\n"
 329   
 330   "Once the connection is established with the server, the server calls its onConnect() method "
 331   "with the client's passed in parameters as aruments.\n\n"
 332   
 333   "@see GameConnection::onConnect()\n\n")
 334{
 335   StringStackWrapper args(argc - 2, argv + 2);
 336   object->setConnectArgs(args.count(), args);
 337}
 338
 339void GameConnection::onTimedOut()
 340{
 341   if(isConnectionToServer())
 342   {
 343      Con::printf("Connection to server timed out");
 344      onConnectionTimedOut_callback();
 345   }
 346   else
 347   {
 348      Con::printf("Client %d timed out.", getId());
 349      setDisconnectReason("TimedOut");
 350   }
 351
 352}
 353
 354void GameConnection::onConnectionEstablished(bool isInitiator)
 355{
 356   if(isInitiator)
 357   {
 358      setGhostFrom(false);
 359      setGhostTo(true);
 360      setSendingEvents(true);
 361      setTranslatesStrings(true);
 362      setIsConnectionToServer();
 363      mServerConnection = this;
 364      Con::printf("Connection established %d", getId());
 365      onConnectionAccepted_callback();
 366   }
 367   else
 368   {
 369      setGhostFrom(true);
 370      setGhostTo(false);
 371      setSendingEvents(true);
 372      setTranslatesStrings(true);
 373      Sim::getClientGroup()->addObject(this);
 374      mMoveList->init();
 375
 376      const char *argv[MaxConnectArgs + 2];
 377      argv[0] = "onConnect";
 378      argv[1] = NULL; // Filled in later
 379      for(U32 i = 0; i < mConnectArgc; i++)
 380         argv[i + 2] = mConnectArgv[i];
 381      // NOTE: Need to fallback to Con::execute() as IMPLEMENT_CALLBACK does not 
 382      // support variadic functions.
 383      Con::execute(this, mConnectArgc + 2, argv);
 384   }
 385}
 386
 387void GameConnection::onConnectTimedOut()
 388{
 389   onConnectRequestTimedOut_callback();
 390}
 391
 392void GameConnection::onDisconnect(const char *reason)
 393{
 394   if(isConnectionToServer())
 395   {
 396      Con::printf("Connection with server lost.");
 397      onConnectionDropped_callback(reason);
 398      mMoveList->init();
 399   }
 400   else
 401   {
 402      Con::printf("Client %d disconnected.", getId());
 403      setDisconnectReason(reason);
 404   }
 405}
 406
 407void GameConnection::onConnectionRejected(const char *reason)
 408{
 409   onConnectRequestRejected_callback(reason);
 410}
 411
 412void GameConnection::handleStartupError(const char *errorString)
 413{
 414   onConnectRequestRejected_callback(errorString);
 415}
 416
 417void GameConnection::writeConnectAccept(BitStream *stream)
 418{
 419   Parent::writeConnectAccept(stream);
 420   stream->write(getProtocolVersion());
 421}
 422
 423bool GameConnection::readConnectAccept(BitStream *stream, const char **errorString)
 424{
 425   if(!Parent::readConnectAccept(stream, errorString))
 426      return false;
 427
 428   U32 protocolVersion;
 429   stream->read(&protocolVersion);
 430   if(protocolVersion < MinRequiredProtocolVersion || protocolVersion > CurrentProtocolVersion)
 431   {
 432      *errorString = "CHR_PROTOCOL"; // this should never happen unless someone is faking us out.
 433      return false;
 434   }
 435   return true;
 436}
 437
 438void GameConnection::writeConnectRequest(BitStream *stream)
 439{
 440   Parent::writeConnectRequest(stream);
 441   stream->writeString(TORQUE_APP_NAME);
 442   stream->write(CurrentProtocolVersion);
 443   stream->write(MinRequiredProtocolVersion);
 444   stream->writeString(mJoinPassword);
 445
 446   stream->write(mConnectArgc);
 447   for(U32 i = 0; i < mConnectArgc; i++)
 448      stream->writeString(mConnectArgv[i]);
 449}
 450
 451bool GameConnection::readConnectRequest(BitStream *stream, const char **errorString)
 452{
 453   if(!Parent::readConnectRequest(stream, errorString))
 454      return false;
 455   U32 currentProtocol, minProtocol;
 456   char gameString[256];
 457   stream->readString(gameString);
 458   if(String::compare(gameString, TORQUE_APP_NAME))
 459   {
 460      *errorString = "CHR_GAME";
 461      return false;
 462   }
 463
 464   stream->read(&currentProtocol);
 465   stream->read(&minProtocol);
 466
 467   char joinPassword[256];
 468   stream->readString(joinPassword);
 469
 470   if(currentProtocol < MinRequiredProtocolVersion)
 471   {
 472      *errorString = "CHR_PROTOCOL_LESS";
 473      return false;
 474   }
 475   if(minProtocol > CurrentProtocolVersion)
 476   {
 477      *errorString = "CHR_PROTOCOL_GREATER";
 478      return false;
 479   }
 480   setProtocolVersion(currentProtocol < CurrentProtocolVersion ? currentProtocol : CurrentProtocolVersion);
 481
 482   const char *serverPassword = Con::getVariable("pref::Server::Password");
 483   if(serverPassword[0])
 484   {
 485      if(String::compare(joinPassword, serverPassword))
 486      {
 487         *errorString = "CHR_PASSWORD";
 488         return false;
 489      }
 490   }
 491
 492   stream->read(&mConnectArgc);
 493   if(mConnectArgc > MaxConnectArgs)
 494   {
 495      *errorString = "CR_INVALID_ARGS";
 496      return false;
 497   }
 498   ConsoleValueRef connectArgv[MaxConnectArgs + 3];
 499   ConsoleValue connectArgvValue[MaxConnectArgs + 3];
 500
 501   for(U32 i = 0; i < mConnectArgc+3; i++)
 502   {
 503      connectArgv[i].value = &connectArgvValue[i];
 504      connectArgvValue[i].init();
 505   }
 506
 507   for(U32 i = 0; i < mConnectArgc; i++)
 508   {
 509      char argString[256];
 510      stream->readString(argString);
 511      mConnectArgv[i] = dStrdup(argString);
 512      connectArgv[i + 3] = mConnectArgv[i];
 513   }
 514   connectArgvValue[0].setStackStringValue("onConnectRequest");
 515   connectArgvValue[1].setIntValue(0);
 516   char buffer[256];
 517   Net::addressToString(getNetAddress(), buffer);
 518   connectArgvValue[2].setStackStringValue(buffer);
 519
 520   // NOTE: Cannot convert over to IMPLEMENT_CALLBACK as it has variable args.
 521   const char *ret = Con::execute(this, mConnectArgc + 3, connectArgv);
 522   if(ret[0])
 523   {
 524      *errorString = ret;
 525      return false;
 526   }
 527   return true;
 528}
 529//----------------------------------------------------------------------------
 530//----------------------------------------------------------------------------
 531void GameConnection::connectionError(const char *errorString)
 532{
 533   if(isConnectionToServer())
 534   {
 535      Con::printf("Connection error: %s.", errorString);
 536      onConnectionError_callback(errorString);
 537   }
 538   else
 539   {
 540      Con::printf("Client %d packet error: %s.", getId(), errorString);
 541      setDisconnectReason("Packet Error.");
 542   }
 543   deleteObject();
 544}
 545
 546
 547void GameConnection::setAuthInfo(const AuthInfo *info)
 548{
 549   mAuthInfo = new AuthInfo;
 550   *mAuthInfo = *info;
 551}
 552
 553const AuthInfo *GameConnection::getAuthInfo()
 554{
 555   return mAuthInfo;
 556}
 557
 558
 559//----------------------------------------------------------------------------
 560
 561void GameConnection::setControlObject(GameBase *obj)
 562{
 563   if(mControlObject == obj)
 564      return;
 565
 566   if(mControlObject && mControlObject != mCameraObject)
 567      mControlObject->setControllingClient(0);
 568
 569   if(obj)
 570   {
 571      // Nothing else is permitted to control this object.
 572      if (GameBase* coo = obj->getControllingObject())
 573         coo->setControlObject(0);
 574      if (GameConnection *con = obj->getControllingClient())
 575      {
 576         if(this != con)
 577         {
 578            // was it controlled via camera or control
 579            if(con->getControlObject() == obj)
 580               con->setControlObject(0);
 581            else
 582               con->setCameraObject(0);
 583         }
 584      }
 585
 586      // We are now the controlling client of this object.
 587      obj->setControllingClient(this);
 588
 589      // Update the camera's FOV to match the new control object
 590      //but only if we don't have a specific camera object
 591      if (!mCameraObject)
 592         setControlCameraFov(obj->getCameraFov());
 593   }
 594
 595   // Okay, set our control object.
 596   mControlObject = obj;
 597   mControlForceMismatch = true;
 598
 599   if(mCameraObject.isNull())
 600      setScopeObject(mControlObject);
 601}
 602
 603void GameConnection::setCameraObject(GameBase *obj)
 604{
 605   if(mCameraObject == obj)
 606      return;
 607
 608   if(mCameraObject && mCameraObject != mControlObject)
 609      mCameraObject->setControllingClient(0);
 610
 611   if(obj)
 612   {
 613      // nothing else is permitted to control this object
 614      if(GameBase *coo = obj->getControllingObject())
 615         coo->setControlObject(0);
 616
 617      if(GameConnection *con = obj->getControllingClient())
 618      {
 619         if(this != con)
 620         {
 621            // was it controlled via camera or control
 622            if(con->getControlObject() == obj)
 623               con->setControlObject(0);
 624            else
 625               con->setCameraObject(0);
 626         }
 627      }
 628
 629      // we are now the controlling client of this object
 630      obj->setControllingClient(this);
 631   }
 632
 633   // Okay, set our camera object.
 634   mCameraObject = obj;
 635
 636   if(mCameraObject.isNull())
 637      setScopeObject(mControlObject);
 638   else
 639   {
 640      setScopeObject(mCameraObject);
 641
 642      // if this is a client then set the fov and active image
 643      if(isConnectionToServer())
 644      {
 645         F32 fov = mCameraObject->getDefaultCameraFov();
 646         //GameSetCameraFov(fov);
 647         smFovUpdate.trigger(fov);
 648      }
 649   }
 650}
 651
 652GameBase* GameConnection::getCameraObject()
 653{
 654   // If there is no camera object, or if we're first person, return
 655   // the control object.
 656   if( !mControlObject.isNull() && (mCameraObject.isNull() || mFirstPerson))
 657      return mControlObject;
 658   return mCameraObject;
 659}
 660
 661static S32 sChaseQueueSize = 0;
 662static MatrixF* sChaseQueue = 0;
 663static S32 sChaseQueueHead = 0;
 664static S32 sChaseQueueTail = 0;
 665
 666bool GameConnection::getControlCameraTransform(F32 dt, MatrixF* mat)
 667{
 668   GameBase* obj = getCameraObject();
 669   if(!obj)
 670      return false;
 671
 672   GameBase* cObj = obj;
 673   while((cObj = cObj->getControlObject()) != 0)
 674   {
 675      if(cObj->useObjsEyePoint())
 676         obj = cObj;
 677   }
 678
 679   if (dt) 
 680   {
 681      if (mFirstPerson || obj->onlyFirstPerson()) 
 682      {
 683         if (mCameraPos > 0)
 684            if ((mCameraPos -= mCameraSpeed * dt) <= 0)
 685               mCameraPos = 0;
 686      }
 687      else 
 688      {
 689         if (mCameraPos < 1)
 690            if ((mCameraPos += mCameraSpeed * dt) > 1)
 691               mCameraPos = 1;
 692      }
 693   }
 694
 695   if (!sChaseQueueSize || mFirstPerson || obj->onlyFirstPerson())
 696      obj->getCameraTransform(&mCameraPos,mat);
 697   else 
 698   {
 699      MatrixF& hm = sChaseQueue[sChaseQueueHead];
 700      MatrixF& tm = sChaseQueue[sChaseQueueTail];
 701      obj->getCameraTransform(&mCameraPos,&hm);
 702      *mat = tm;
 703      if (dt) 
 704      {
 705         if ((sChaseQueueHead += 1) >= sChaseQueueSize)
 706            sChaseQueueHead = 0;
 707         if (sChaseQueueHead == sChaseQueueTail)
 708            if ((sChaseQueueTail += 1) >= sChaseQueueSize)
 709               sChaseQueueTail = 0;
 710      }
 711   }
 712   return true;
 713}
 714
 715bool GameConnection::getControlCameraHeadTransform(IDisplayDevice *display, MatrixF *transform)
 716{
 717   GameBase* obj = getCameraObject();
 718   if (!obj)
 719      return false;
 720
 721   GameBase* cObj = obj;
 722   while ((cObj = cObj->getControlObject()) != 0)
 723   {
 724      if (cObj->useObjsEyePoint())
 725         obj = cObj;
 726   }
 727
 728   obj->getEyeCameraTransform(display, -1, transform);
 729
 730   return true;
 731}
 732
 733bool GameConnection::getControlCameraEyeTransforms(IDisplayDevice *display, MatrixF *transforms)
 734{
 735   GameBase* obj = getCameraObject();
 736   if(!obj)
 737      return false;
 738
 739   GameBase* cObj = obj;
 740   while((cObj = cObj->getControlObject()) != 0)
 741   {
 742      if(cObj->useObjsEyePoint())
 743         obj = cObj;
 744   }
 745
 746   // Perform operation on left & right eyes. For each we need to calculate the world space 
 747   // of the rotated eye offset and add that onto the camera world space.
 748   for (U32 i=0; i<2; i++)
 749   {
 750      obj->getEyeCameraTransform(display, i, &transforms[i]);
 751   }
 752
 753   return true;
 754}
 755
 756
 757bool GameConnection::getControlCameraDefaultFov(F32 * fov)
 758{
 759   //find the last control object in the chain (client->player->turret->whatever...)
 760   GameBase *obj = getCameraObject();
 761   GameBase *cObj = NULL;
 762   while (obj)
 763   {
 764      cObj = obj;
 765      obj = obj->getControlObject();
 766   }
 767   if (cObj)
 768   {
 769      *fov = cObj->getDefaultCameraFov();
 770      return(true);
 771   }
 772
 773   return(false);
 774}
 775
 776bool GameConnection::getControlCameraFov(F32 * fov)
 777{
 778   //find the last control object in the chain (client->player->turret->whatever...)
 779   GameBase *obj = getCameraObject();
 780   GameBase *cObj = NULL;
 781   while (obj)
 782   {
 783      cObj = obj;
 784      obj = obj->getControlObject();
 785   }
 786   if (cObj)
 787   {
 788      *fov = cObj->getCameraFov();
 789
 790      return(true);
 791   }
 792
 793   return(false);
 794}
 795
 796bool GameConnection::isValidControlCameraFov(F32 fov)
 797{
 798   //find the last control object in the chain (client->player->turret->whatever...)
 799   GameBase *obj = getCameraObject();
 800   GameBase *cObj = NULL;
 801   while (obj)
 802   {
 803      cObj = obj;
 804      obj = obj->getControlObject();
 805   }
 806
 807   if (cObj)
 808   {
 809      return cObj->isValidCameraFov(fov);
 810   }
 811
 812   return NULL;
 813}
 814
 815bool GameConnection::setControlCameraFov(F32 fov)
 816{
 817   //find the last control object in the chain (client->player->turret->whatever...)
 818   GameBase *obj = getCameraObject();
 819   GameBase *cObj = NULL;
 820   while (obj)
 821   {
 822      cObj = obj;
 823      obj = obj->getControlObject();
 824   }
 825   if (cObj)
 826   {
 827      F32 newFov = 90.f;
 828
 829      // allow shapebase to clamp fov to its datablock values
 830      cObj->setCameraFov(mClampF(fov, MinCameraFov, MaxCameraFov));
 831      newFov = cObj->getCameraFov();
 832
 833      // server fov of client has 1degree resolution
 834      if( S32(newFov) != S32(mCameraFov) || newFov != fov )
 835         mUpdateCameraFov = true;
 836
 837      mCameraFov = newFov;
 838      return(true);
 839   }
 840   return(false);
 841}
 842
 843bool GameConnection::getControlCameraVelocity(Point3F *vel)
 844{
 845   if (GameBase* obj = getCameraObject()) {
 846      *vel = obj->getVelocity();
 847      return true;
 848   }
 849   return false;
 850}
 851
 852bool GameConnection::isControlObjectRotDampedCamera()
 853{
 854   if (Camera* cam = dynamic_cast<Camera*>(getCameraObject())) {
 855      if(cam->isRotationDamped())
 856         return true;
 857   }
 858   return false;
 859}
 860
 861void GameConnection::setFirstPerson(bool firstPerson)
 862{
 863   mFirstPerson = firstPerson;
 864   mUpdateFirstPerson = true;
 865}
 866
 867//----------------------------------------------------------------------------
 868
 869void GameConnection::setControlSchemeParameters(bool absoluteRotation, bool addYawToAbsRot, bool addPitchToAbsRot)
 870{
 871   mAbsoluteRotation = absoluteRotation;
 872   mAddYawToAbsRot = addYawToAbsRot;
 873   mAddPitchToAbsRot = addPitchToAbsRot;
 874   mUpdateControlScheme = true;
 875}
 876
 877//----------------------------------------------------------------------------
 878
 879bool GameConnection::onAdd()
 880{
 881   if (!Parent::onAdd())
 882      return false;
 883
 884   return true;
 885}
 886
 887void GameConnection::onRemove()
 888{
 889   if(isNetworkConnection())
 890   {
 891      sendDisconnectPacket(mDisconnectReason);
 892   }
 893   else if (isLocalConnection() && isConnectionToServer())
 894   {
 895      // We're a client-side but local connection
 896      // delete the server side of the connection on our local server so that it updates 
 897      // clientgroup and what not (this is so that we can disconnect from a local server
 898      // without needing to destroy and recreate the server before we can connect to it 
 899      // again).
 900      // Safe-delete as we don't know whether the server connection is currently being
 901      // worked on.
 902      getRemoteConnection()->safeDeleteObject();
 903      setRemoteConnectionObject(NULL);
 904   }
 905   if(!isConnectionToServer())
 906   {
 907      onDrop_callback(mDisconnectReason);
 908   }
 909
 910   if (mControlObject)
 911      mControlObject->setControllingClient(0);
 912   Parent::onRemove();
 913}
 914
 915void GameConnection::setDisconnectReason(const char *str)
 916{
 917   dStrncpy(mDisconnectReason, str, sizeof(mDisconnectReason) - 1);
 918   mDisconnectReason[sizeof(mDisconnectReason) - 1] = 0;
 919}
 920
 921//----------------------------------------------------------------------------
 922
 923void GameConnection::handleRecordedBlock(U32 type, U32 size, void *data)
 924{
 925   switch(type)
 926   {
 927      case BlockTypeMove:
 928         mMoveList->pushMove(*((Move *) data));
 929         if(isRecording()) // put it back into the stream
 930            recordBlock(type, size, data);
 931         break;
 932      default:
 933         Parent::handleRecordedBlock(type, size, data);
 934         break;
 935   }
 936}
 937
 938void GameConnection::writeDemoStartBlock(ResizeBitStream *stream)
 939{
 940   // write all the data blocks to the stream:
 941
 942   for(SimObjectId i = DataBlockObjectIdFirst; i <= DataBlockObjectIdLast; i++)
 943   {
 944      SimDataBlock *data;
 945      if(Sim::findObject(i, data))
 946      {
 947         stream->writeFlag(true);
 948         SimDataBlockEvent evt(data);
 949         evt.pack(this, stream);
 950         stream->validate();
 951      }
 952   }
 953   stream->writeFlag(false);
 954   stream->write(mFirstPerson);
 955   stream->write(mCameraPos);
 956   stream->write(mCameraSpeed);
 957
 958   // Control scheme
 959   stream->write(mAbsoluteRotation);
 960   stream->write(mAddYawToAbsRot);
 961   stream->write(mAddPitchToAbsRot);
 962
 963   stream->writeString(Con::getVariable("$Client::MissionFile"));
 964
 965   mMoveList->writeDemoStartBlock(stream);
 966
 967   // dump all the "demo" vars associated with this connection:
 968   SimFieldDictionaryIterator itr(getFieldDictionary());
 969
 970   SimFieldDictionary::Entry *entry;
 971   while((entry = *itr) != NULL)
 972   {
 973      if(!dStrnicmp(entry->slotName, "demo", 4))
 974      {
 975         stream->writeFlag(true);
 976         stream->writeString(entry->slotName + 4);
 977         stream->writeString(entry->value);
 978         stream->validate();
 979      }
 980      ++itr;
 981   }
 982   stream->writeFlag(false);
 983   Parent::writeDemoStartBlock(stream);
 984
 985   stream->validate();
 986
 987   // dump out the control object ghost id
 988   S32 idx = mControlObject ? getGhostIndex(mControlObject) : -1;
 989   stream->write(idx);
 990   if(mControlObject)
 991   {
 992#ifdef TORQUE_NET_STATS
 993      U32 beginPos = stream->getBitPosition();
 994#endif
 995      mControlObject->writePacketData(this, stream);
 996#ifdef TORQUE_NET_STATS
 997//      TYPEOF( mControlObject )->getNetInfo().updateNetStatWriteData( stream->getBitPosition() - beginPos );
 998      
 999      mControlObject->getClassRep()->updateNetStatWriteData( stream->getBitPosition() - beginPos);
1000#endif
1001   }
1002   idx = mCameraObject ? getGhostIndex(mCameraObject) : -1;
1003   stream->write(idx);
1004   if(mCameraObject && mCameraObject != mControlObject)
1005   {
1006#ifdef TORQUE_NET_STATS
1007      U32 beginPos = stream->getBitPosition();
1008#endif
1009
1010      mCameraObject->writePacketData(this, stream);
1011
1012#ifdef TORQUE_NET_STATS
1013      mCameraObject->getClassRep()->updateNetStatWriteData( stream->getBitPosition() - beginPos);
1014#endif
1015   }
1016   mLastControlRequestTime = Platform::getVirtualMilliseconds();
1017}
1018
1019bool GameConnection::readDemoStartBlock(BitStream *stream)
1020{
1021   while(stream->readFlag())
1022   {
1023      SimDataBlockEvent evt;
1024      evt.unpack(this, stream);
1025      evt.process(this);
1026   }
1027
1028   while(mDataBlockLoadList.size())
1029   {
1030      preloadNextDataBlock(false);
1031      if(mErrorBuffer.isNotEmpty())
1032         return false;
1033   }
1034
1035   stream->read(&mFirstPerson);
1036   stream->read(&mCameraPos);
1037   stream->read(&mCameraSpeed);
1038
1039   // Control scheme
1040   stream->read(&mAbsoluteRotation);
1041   stream->read(&mAddYawToAbsRot);
1042   stream->read(&mAddPitchToAbsRot);
1043
1044   char buf[256];
1045   stream->readString(buf);
1046   Con::setVariable("$Client::MissionFile",buf);
1047
1048   mMoveList->readDemoStartBlock(stream);
1049
1050   // read in all the demo vars associated with this recording
1051   // they are all tagged on to the object and start with the
1052   // string "demo"
1053
1054   while(stream->readFlag())
1055   {
1056      StringTableEntry slotName = StringTable->insert("demo");
1057      char array[256];
1058      char value[256];
1059      stream->readString(array);
1060      stream->readString(value);
1061      setDataField(slotName, array, value);
1062   }
1063   bool ret = Parent::readDemoStartBlock(stream);
1064   // grab the control object
1065   S32 idx;
1066   stream->read(&idx);
1067
1068   GameBase * obj = 0;
1069   if(idx != -1)
1070   {
1071      obj = dynamic_cast<GameBase*>(resolveGhost(idx));
1072      setControlObject(obj);
1073      obj->readPacketData(this, stream);
1074   }
1075
1076   // Get the camera object, and read it in if it's different
1077   S32 idx2;
1078   stream->read(&idx2);
1079   obj = 0;
1080   if(idx2 != -1 && idx2 != idx)
1081   {
1082      obj = dynamic_cast<GameBase*>(resolveGhost(idx2));
1083      setCameraObject(obj);
1084      obj->readPacketData(this, stream);
1085   }
1086   return ret;
1087}
1088
1089void GameConnection::demoPlaybackComplete()
1090{
1091   static const char* demoPlaybackArgv[1] = { "demoPlaybackComplete" };
1092   static StringStackConsoleWrapper demoPlaybackCmd(1, demoPlaybackArgv);
1093
1094   Sim::postCurrentEvent(Sim::getRootGroup(), new SimConsoleEvent(demoPlaybackCmd.argc, demoPlaybackCmd.argv, false));
1095   Parent::demoPlaybackComplete();
1096}
1097
1098void GameConnection::ghostPreRead(NetObject * nobj, bool newGhost)
1099{
1100   Parent::ghostPreRead( nobj, newGhost );
1101
1102   mMoveList->ghostPreRead(nobj,newGhost);
1103}
1104
1105void GameConnection::ghostReadExtra(NetObject * nobj, BitStream * bstream, bool newGhost)
1106{
1107   Parent::ghostReadExtra( nobj, bstream, newGhost );
1108
1109   mMoveList->ghostReadExtra(nobj, bstream, newGhost);
1110   }
1111
1112void GameConnection::ghostWriteExtra(NetObject * nobj, BitStream * bstream)
1113{
1114   Parent::ghostWriteExtra( nobj, bstream);
1115
1116   mMoveList->ghostWriteExtra(nobj, bstream);
1117}
1118
1119//----------------------------------------------------------------------------
1120
1121void GameConnection::readPacket(BitStream *bstream)
1122{
1123   bstream->clearStringBuffer();
1124   bstream->clearCompressionPoint();
1125
1126   if (isConnectionToServer())
1127   {
1128      mMoveList->clientReadMovePacket(bstream);
1129
1130#ifdef TORQUE_AFX_ENABLED
1131      // selected object - do we have a change in status?
1132      if (bstream->readFlag()) 
1133      { 
1134         if (bstream->readFlag()) 
1135         { 
1136            S32 gIndex = bstream->readInt(NetConnection::GhostIdBitSize);
1137            setSelectedObj(static_cast<SceneObject*>(resolveGhost(gIndex)));
1138         }
1139         else
1140            setSelectedObj(NULL);
1141      }
1142#endif
1143
1144      bool hadFlash = mDamageFlash > 0 || mWhiteOut > 0;
1145      mDamageFlash = 0;
1146      mWhiteOut = 0;
1147      if(bstream->readFlag())
1148      {
1149         if(bstream->readFlag())
1150            mDamageFlash = bstream->readFloat(7);
1151         if(bstream->readFlag())
1152            mWhiteOut = bstream->readFloat(7) * 1.5;
1153
1154         if(!hadFlash)
1155         {
1156            // Started a damage flash or white out
1157            onFlash_callback(true);
1158         }
1159         else
1160         {
1161            if(!(mDamageFlash > 0 || mWhiteOut > 0))
1162            {
1163               // Received a zero damage flash and white out.
1164               onFlash_callback(false);
1165            }
1166         }
1167      }
1168      else if(hadFlash)
1169      {
1170         // Catch those cases where both the damage flash and white out are at zero
1171         // on the server but we did not receive an exact zero packet due to
1172         // precision over the network issues.  No problem as the flag we just
1173         // read (which is false if we're here) has also told us about the change.
1174         onFlash_callback(false);
1175      }
1176
1177      if ( bstream->readFlag() ) // gIndex != -1
1178      {         
1179         if ( bstream->readFlag() ) // mMoveList->isMismatch() || mControlForceMismatch
1180         {
1181            // the control object is dirty...so we get an update:
1182            bool callScript = false;
1183            bool controlObjChange = false;
1184            if(mControlObject.isNull())
1185               callScript = true;
1186
1187            S32 gIndex = bstream->readInt(NetConnection::GhostIdBitSize);
1188            GameBase* obj = dynamic_cast<GameBase*>(resolveGhost(gIndex));
1189            if (mControlObject != obj)
1190            {
1191               setControlObject(obj);
1192               controlObjChange = true;
1193            }
1194#ifdef TORQUE_NET_STATS
1195            U32 beginSize = bstream->getBitPosition();
1196#endif
1197            obj->readPacketData(this, bstream);
1198#ifdef TORQUE_NET_STATS
1199            obj->getClassRep()->updateNetStatReadData(bstream->getBitPosition() - beginSize);
1200#endif
1201
1202            // let move list know that control object is dirty
1203            mMoveList->markControlDirty();
1204
1205            if(callScript)
1206            {
1207               initialControlSet_callback();
1208            }
1209
1210            if(controlObjChange)
1211            {
1212               onControlObjectChange_callback();
1213            }
1214         }
1215         else
1216         {
1217            // read out the compression point
1218            Point3F pos;
1219            bstream->read(&pos.x);
1220            bstream->read(&pos.y);
1221            bstream->read(&pos.z);
1222            bstream->setCompressionPoint(pos);
1223         }
1224      }
1225
1226      if (bstream->readFlag())
1227      {
1228         bool callScript = false;
1229         if (mCameraObject.isNull())
1230            callScript = true;
1231
1232         S32 gIndex = bstream->readInt(NetConnection::GhostIdBitSize);
1233         GameBase* obj = dynamic_cast<GameBase*>(resolveGhost(gIndex));
1234         setCameraObject(obj);
1235         obj->readPacketData(this, bstream);
1236
1237         if (callScript)
1238            initialControlSet_callback();
1239      }
1240      else
1241         setCameraObject(0);
1242
1243      // server changed control scheme
1244      if(bstream->readFlag())
1245      {
1246         bool absoluteRotation = bstream->readFlag();
1247         bool addYawToAbsRot = bstream->readFlag();
1248         bool addPitchToAbsRot = bstream->readFlag();
1249         setControlSchemeParameters(absoluteRotation, addYawToAbsRot, addPitchToAbsRot);
1250         mUpdateControlScheme = false;
1251      }
1252
1253      // server changed first person
1254      if(bstream->readFlag())
1255      {
1256         setFirstPerson(bstream->readFlag());
1257         mUpdateFirstPerson = false;
1258      }
1259
1260      // server forcing a fov change?
1261      if(bstream->readFlag())
1262      {
1263         S32 fov = bstream->readInt(8);
1264         setControlCameraFov((F32)fov);
1265
1266         // don't bother telling the server if we were able to set the fov
1267         F32 setFov;
1268         if(getControlCameraFov(&setFov) && (S32(setFov) == fov))
1269            mUpdateCameraFov = false;
1270
1271         // update the games fov info
1272         smFovUpdate.trigger((F32)fov);
1273      }
1274   }
1275   else
1276   {
1277      mMoveList->serverReadMovePacket(bstream);
1278
1279      mCameraPos = bstream->readFlag() ? 1.0f : 0.0f;
1280      if (bstream->readFlag())
1281         mControlForceMismatch = true;
1282
1283      // client changed control scheme
1284      if(bstream->readFlag())
1285      {
1286         bool absoluteRotation = bstream->readFlag();
1287         bool addYawToAbsRot = bstream->readFlag();
1288         bool addPitchToAbsRot = bstream->readFlag();
1289         setControlSchemeParameters(absoluteRotation, addYawToAbsRot, addPitchToAbsRot);
1290         mUpdateControlScheme = false;
1291      }
1292
1293      // client changed first person
1294      if(bstream->readFlag())
1295      {
1296         setFirstPerson(bstream->readFlag());
1297         mUpdateFirstPerson = false;
1298      }
1299
1300      // check fov change.. 1degree granularity on server
1301      if(bstream->readFlag())
1302      {
1303         S32 fov = mClamp(bstream->readInt(8), S32(MinCameraFov), S32(MaxCameraFov));
1304         setControlCameraFov((F32)fov);
1305
1306         // may need to force client back to a valid fov
1307         F32 setFov;
1308         if(getControlCameraFov(&setFov) && (S32(setFov) == fov))
1309            mUpdateCameraFov = false;
1310      }
1311   }
1312
1313   Parent::readPacket(bstream);
1314   bstream->clearCompressionPoint();
1315   bstream->clearStringBuffer();
1316
1317   if (isConnectionToServer())
1318   {
1319      PROFILE_START(ClientCatchup);
1320      ClientProcessList::get()->clientCatchup(this);
1321      PROFILE_END();
1322   }
1323}
1324
1325void GameConnection::writePacket(BitStream *bstream, PacketNotify *note)
1326{
1327   bstream->clearCompressionPoint();
1328   bstream->clearStringBuffer();
1329
1330   GamePacketNotify *gnote = (GamePacketNotify *) note;
1331
1332   U32 startPos = bstream->getBitPosition();
1333   if (isConnectionToServer())
1334   {
1335      mMoveList->clientWriteMovePacket(bstream);
1336
1337      bstream->writeFlag(mCameraPos == 1);
1338
1339      // if we're recording, we want to make sure that we get periodic updates of the
1340      // control object "just in case" - ie if the math copro is different between the
1341      // recording machine (SIMD vs FPU), we get periodic corrections
1342
1343      bool forceUpdate = false;
1344      if(isRecording())
1345      {
1346         U32 currentTime = Platform::getVirtualMilliseconds();
1347         if(currentTime - mLastControlRequestTime > ControlRequestTime)
1348         {
1349            mLastControlRequestTime = currentTime;
1350            forceUpdate=true;;
1351         }
1352      }
1353      bstream->writeFlag(forceUpdate);
1354
1355      // Control scheme changed?
1356      if(bstream->writeFlag(mUpdateControlScheme))
1357      {
1358         bstream->writeFlag(mAbsoluteRotation);
1359         bstream->writeFlag(mAddYawToAbsRot);
1360         bstream->writeFlag(mAddPitchToAbsRot);
1361         mUpdateControlScheme = false;
1362      }
1363
1364      // first person changed?
1365      if(bstream->writeFlag(mUpdateFirstPerson)) 
1366      {
1367         bstream->writeFlag(mFirstPerson);
1368         mUpdateFirstPerson = false;
1369      }
1370
1371      // camera fov changed? (server fov resolution is 1 degree)
1372      if(bstream->writeFlag(mUpdateCameraFov))
1373      {
1374         bstream->writeInt(mClamp(S32(mCameraFov), S32(MinCameraFov), S32(MaxCameraFov)), 8);
1375         mUpdateCameraFov = false;
1376      }
1377      DEBUG_LOG(("PKLOG %d CLIENTMOVES: %d", getId(), bstream->getCurPos() - startPos));
1378   }
1379   else
1380   {
1381      mMoveList->serverWriteMovePacket(bstream);
1382
1383      // get the ghost index of the control object, and write out
1384      // all the damage flash & white out
1385
1386      S32 gIndex = -1;
1387#ifdef TORQUE_AFX_ENABLED
1388      if (mChangedSelectedObj)
1389      {
1390         S32 gidx;
1391         // send NULL player
1392         if ((mSelectedObj == NULL) || mSelectedObj.isNull())
1393         {
1394            bstream->writeFlag(true);
1395            bstream->writeFlag(false);
1396            mChangedSelectedObj = false;
1397         }
1398         // send ghost-idx
1399         else if ((gidx = getGhostIndex(mSelectedObj)) != -1)
1400         {
1401            Con::printf("SEND OBJECT SELECTION");
1402            bstream->writeFlag(true);
1403            bstream->writeFlag(true);
1404            bstream->writeInt(gidx, NetConnection::GhostIdBitSize);
1405            mChangedSelectedObj = false;
1406         }
1407         // not fully changed yet
1408         else
1409         {
1410            bstream->writeFlag(false);
1411            mChangedSelectedObj = true;
1412         }
1413      }
1414      else
1415         bstream->writeFlag(false);
1416#endif
1417       
1418      if (!mControlObject.isNull())
1419      {
1420         gIndex = getGhostIndex(mControlObject);
1421
1422         F32 flash = mControlObject->getDamageFlash();
1423         F32 whiteOut = mControlObject->getWhiteOut();
1424         if(bstream->writeFlag(flash != 0 || whiteOut != 0))
1425         {
1426            if(bstream->writeFlag(flash != 0))
1427               bstream->writeFloat(flash, 7);
1428            if(bstream->writeFlag(whiteOut != 0))
1429               bstream->writeFloat(whiteOut/1.5, 7);
1430         }
1431      }
1432      else
1433         bstream->writeFlag(false);
1434
1435      if (bstream->writeFlag(gIndex != -1))
1436      {
1437         // assume that the control object will write in a compression point
1438         if(bstream->writeFlag(mMoveList->isMismatch() || mControlForceMismatch))
1439         {
1440#ifdef TORQUE_DEBUG_NET
1441            if (mMoveList->isMismatch())
1442               Con::printf("packetDataChecksum disagree!");
1443            else
1444               Con::printf("packetDataChecksum disagree! (force)");
1445#endif
1446
1447            bstream->writeInt(gIndex, NetConnection::GhostIdBitSize);
1448#ifdef TORQUE_NET_STATS
1449            U32 beginSize = bstream->getBitPosition();
1450#endif
1451            mControlObject->writePacketData(this, bstream);
1452#ifdef TORQUE_NET_STATS
1453            mControlObject->getClassRep()->updateNetStatWriteData(bstream->getBitPosition() - beginSize);
1454#endif
1455            mControlForceMismatch = false;
1456         }
1457         else
1458         {
1459            // we'll have to use the control object's position as the compression point
1460            // should make this lower res for better space usage:
1461            Point3F coPos = mControlObject->getPosition();
1462            bstream->write(coPos.x);
1463            bstream->write(coPos.y);
1464            bstream->write(coPos.z);
1465            bstream->setCompressionPoint(coPos);
1466         }
1467      }
1468      DEBUG_LOG(("PKLOG %d CONTROLOBJECTSTATE: %d", getId(), bstream->getCurPos() - startPos));
1469      startPos = bstream->getBitPosition();
1470
1471      if (!mCameraObject.isNull() && mCameraObject != mControlObject)
1472      {
1473         gIndex = getGhostIndex(mCameraObject);
1474         if (bstream->writeFlag(gIndex != -1))
1475         {
1476            bstream->writeInt(gIndex, NetConnection::GhostIdBitSize);
1477            mCameraObject->writePacketData(this, bstream);
1478         }
1479      }
1480      else
1481         bstream->writeFlag( false );
1482
1483      // Control scheme changed?
1484      if(bstream->writeFlag(mUpdateControlScheme))
1485      {
1486         bstream->writeFlag(mAbsoluteRotation);
1487         bstream->writeFlag(mAddYawToAbsRot);
1488         bstream->writeFlag(mAddPitchToAbsRot);
1489         mUpdateControlScheme = false;
1490      }
1491
1492      // first person changed?
1493      if(bstream->writeFlag(mUpdateFirstPerson)) 
1494      {
1495         bstream->writeFlag(mFirstPerson);
1496         mUpdateFirstPerson = false;
1497      }
1498
1499      // server forcing client fov?
1500      gnote->cameraFov = -1;
1501      if(bstream->writeFlag(mUpdateCameraFov))
1502      {
1503         gnote->cameraFov = mClamp(S32(mCameraFov), S32(MinCameraFov), S32(MaxCameraFov));
1504         bstream->writeInt(gnote->cameraFov, 8);
1505         mUpdateCameraFov = false;
1506      }
1507      DEBUG_LOG(("PKLOG %d PINGCAMSTATE: %d", getId(), bstream->getCurPos() - startPos));
1508   }
1509
1510   Parent::writePacket(bstream, note);
1511   bstream->clearCompressionPoint();
1512   bstream->clearStringBuffer();
1513}
1514
1515
1516void GameConnection::detectLag()
1517{
1518   //see if we're lagging...
1519   S32 curTime = Sim::getCurrentTime();
1520   if (curTime - mLastPacketTime > mLagThresholdMS)
1521   {
1522      if (!mLagging)
1523      {
1524         mLagging = true;
1525         setLagIcon_callback(true);
1526      }
1527   }
1528   else if (mLagging)
1529   {
1530      mLagging = false;
1531      setLagIcon_callback(false);
1532   }
1533}
1534
1535GameConnection::GamePacketNotify::GamePacketNotify()
1536{
1537   // need to fill in empty notifes for demo start block
1538   cameraFov = 0;
1539}
1540
1541NetConnection::PacketNotify *GameConnection::allocNotify()
1542{
1543   return new GamePacketNotify;
1544}
1545
1546void GameConnection::packetReceived(PacketNotify *note)
1547{
1548   //record the time so we can tell if we're lagging...
1549   mLastPacketTime = Sim::getCurrentTime();
1550
1551   // If we wanted to do something special, we grab our note like this:
1552   //GamePacketNotify *gnote = (GamePacketNotify *) note;
1553
1554   Parent::packetReceived(note);
1555}
1556
1557void GameConnection::packetDropped(PacketNotify *note)
1558{
1559   Parent::packetDropped(note);
1560   GamePacketNotify *gnote = (GamePacketNotify *) note;
1561   if(gnote->cameraFov != -1)
1562      mUpdateCameraFov = true;
1563}
1564
1565//----------------------------------------------------------------------------
1566
1567void GameConnection::play2D(SFXProfile* profile)
1568{
1569   postNetEvent(new Sim2DAudioEvent(profile));
1570}
1571
1572void GameConnection::play3D(SFXProfile* profile, const MatrixF *transform)
1573{
1574   if ( !transform )
1575      play2D(profile);
1576
1577   else if ( !mControlObject )
1578      postNetEvent(new Sim3DAudioEvent(profile,transform));
1579
1580   else
1581   {
1582      // TODO: Maybe improve this to account for the duration
1583      // of the sound effect and if the control object can get
1584      // into hearing range within time?
1585
1586      // Only post the event if it's within audible range
1587      // of the control object.
1588      Point3F ear,pos;
1589      transform->getColumn(3,&pos);
1590      mControlObject->getTransform().getColumn(3,&ear);
1591      if ((ear - pos).len() < profile->getDescription()->mMaxDistance)
1592         postNetEvent(new Sim3DAudioEvent(profile,transform));
1593   } 
1594}
1595
1596void GameConnection::doneScopingScene()
1597{
1598   // Could add special post-scene scoping here, such as scoping
1599   // objects not visible to the camera, but visible to sensors.
1600}
1601
1602void GameConnection::preloadDataBlock(SimDataBlock *db)
1603{
1604   mDataBlockLoadList.push_back(db);
1605   if(mDataBlockLoadList.size() == 1)
1606      preloadNextDataBlock(false);
1607}
1608
1609void GameConnection::fileDownloadSegmentComplete()
1610{
1611   // this is called when a the file list has finished processing...
1612   // at this point we can try again to add the object
1613   // subclasses can override this to do, for example, datablock redos.
1614   if(mDataBlockLoadList.size())
1615      preloadNextDataBlock(mNumDownloadedFiles != 0);
1616   Parent::fileDownloadSegmentComplete();
1617}
1618
1619void GameConnection::preloadNextDataBlock(bool hadNewFiles)
1620{
1621   if(!mDataBlockLoadList.size())
1622      return;
1623   while(mDataBlockLoadList.size())
1624   {
1625      // only check for new files if this is the first load, or if new
1626      // files were downloaded from the server.
1627//       if(hadNewFiles)
1628//          gResourceManager->setMissingFileLogging(true);
1629//       gResourceManager->clearMissingFileList();
1630      SimDataBlock *object = mDataBlockLoadList[0];
1631      if(!object)
1632      {
1633         // a null object is used to signify that the last ghost in the list is down
1634         mDataBlockLoadList.pop_front();
1635         AssertFatal(mDataBlockLoadList.size() == 0, "Error! Datablock save list should be empty!");
1636         sendConnectionMessage(DataBlocksDownloadDone, mDataBlockSequence);
1637
1638//          gResourceManager->setMissingFileLogging(false);
1639
1640#ifdef AFX_CAP_DATABLOCK_CACHE 
1641         // This should be the last of the datablocks. An argument of false
1642         // indicates that this is a client save.
1643         if (clientCacheEnabled())
1644            saveDatablockCache(false);
1645#endif 
1646
1647         return;
1648      }
1649      mFilesWereDownloaded = hadNewFiles;
1650      if(!object->preload(false, mErrorBuffer))
1651      {
1652         mFilesWereDownloaded = false;
1653         // make sure there's an error message if necessary
1654         if(mErrorBuffer.isEmpty())
1655            setLastError("Invalid packet. (object preload)");
1656
1657         // if there were new files, make sure the error message
1658         // is the one from the last time we tried to add this object
1659         if(hadNewFiles)
1660         {
1661            mErrorBuffer = mLastFileErrorBuffer;
1662//             gResourceManager->setMissingFileLogging(false);
1663            return;
1664         }
1665
1666         // object failed to load, let's see if it had any missing files
1667         if(isLocalConnection() /*|| !gResourceManager->getMissingFileList(mMissingFileList)*/)
1668         {
1669            // no missing files, must be an error
1670            // connection will automagically delete the ghost always list
1671            // when this error is reported.
1672//             gResourceManager->setMissingFileLogging(false);
1673            return;
1674         }
1675
1676         // ok, copy the error buffer out to a scratch pad for now
1677         mLastFileErrorBuffer = mErrorBuffer;
1678         //mErrorBuffer = String();
1679
1680         // request the missing files...
1681         mNumDownloadedFiles = 0;
1682         sendNextFileDownloadRequest();
1683         break;
1684      }
1685      mFilesWereDownloaded = false;
1686//       gResourceManager->setMissingFileLogging(false);
1687      mDataBlockLoadList.pop_front();
1688      hadNewFiles = true;
1689   }
1690}
1691
1692void GameConnection::onEndGhosting()
1693{
1694   Parent::onEndGhosting();
1695   
1696   // Reset move list.  All the moves are obsolete now and furthermore,
1697   // if we don't clear out the list now we might run in danger of
1698   // getting backlogged later on what is a list full of obsolete moves.
1699   
1700   mMoveList->reset();
1701}
1702
1703//----------------------------------------------------------------------------
1704//localconnection only blackout functions
1705void GameConnection::setBlackOut(bool fadeToBlack, S32 timeMS)
1706{
1707   mFadeToBlack = fadeToBlack;
1708   mBlackOutStartTimeMS = Sim::getCurrentTime();
1709   mBlackOutTimeMS = timeMS;
1710
1711   //if timeMS <= 0 set the value instantly
1712   if (mBlackOutTimeMS <= 0)
1713      mBlackOut = (mFadeToBlack ? 1.0f : 0.0f);
1714}
1715
1716F32 GameConnection::getBlackOut()
1717{
1718   S32 curTime = Sim::getCurrentTime();
1719
1720   //see if we're in the middle of a black out
1721   if (curTime < mBlackOutStartTimeMS + mBlackOutTimeMS)
1722   {
1723      S32 elapsedTime = curTime - mBlackOutStartTimeMS;
1724      F32 timePercent = F32(elapsedTime) / F32(mBlackOutTimeMS);
1725      mBlackOut = (mFadeToBlack ? timePercent : 1.0f - timePercent);
1726   }
1727   else
1728      mBlackOut = (mFadeToBlack ? 1.0f : 0.0f);
1729
1730   //return the blackout time
1731   return mBlackOut;
1732}
1733
1734void GameConnection::handleConnectionMessage(U32 message, U32 sequence, U32 ghostCount)
1735{
1736   if(isConnectionToServer())
1737   {
1738      if(message == DataBlocksDone)
1739      {
1740         mDataBlockLoadList.push_back(NULL);
1741         mDataBlockSequence = sequence;
1742         if(mDataBlockLoadList.size() == 1)
1743            preloadNextDataBlock(true);
1744      }
1745   }
1746   else
1747   {
1748      if(message == DataBlocksDownloadDone)
1749      {
1750         if(getDataBlockSequence() == sequence)
1751         {
1752            onDataBlocksDone_callback( getDataBlockSequence() );
1753         }
1754      }
1755   }
1756   Parent::handleConnectionMessage(message, sequence, ghostCount);
1757}
1758
1759//----------------------------------------------------------------------------
1760
1761DefineEngineMethod( GameConnection, transmitDataBlocks, void, (S32 sequence),,
1762   "@brief Sent by the server during phase 1 of the mission download to send the datablocks to the client.\n\n"
1763   
1764   "SimDataBlocks, also known as just datablocks, need to be transmitted to the client "
1765   "prior to the client entering the game world.  These represent the static data that "
1766   "most objects in the world reference.  This is typically done during the standard "
1767   "mission start phase 1 when following Torque's example mission startup sequence.\n\n"
1768
1769   "When the datablocks have all been transmitted, onDataBlocksDone() is called to move "
1770   "the mission start process to the next phase."
1771
1772   "@param sequence The sequence is common between the server and client and ensures "
1773   "that the client is acting on the most recent mission start process.  If an errant "
1774   "network packet (one that was lost but has now been found) is received by the client "
1775   "with an incorrect sequence, it is just ignored.  This sequence number is updated on "
1776   "the server every time a mission is loaded.\n\n"
1777
1778   "@tsexample\n"
1779   "function serverCmdMissionStartPhase1Ack(%client, %seq)\n"
1780   "{\n"
1781   "   // Make sure to ignore calls from a previous mission load\n"
1782   "   if (%seq != $missionSequence || !$MissionRunning)\n"
1783   "      return;\n"
1784   "   if (%client.currentPhase != 0)\n"
1785   "      return;\n"
1786   "   %client.currentPhase = 1;\n"
1787   "\n"
1788   "   // Start with the CRC\n"
1789   "   %client.setMissionCRC( $missionCRC );\n"
1790   "\n"
1791   "   // Send over the datablocks...\n"
1792   "   // OnDataBlocksDone will get called when have confirmation\n"
1793   "   // that they've all been received.\n"
1794   "   %client.transmitDataBlocks($missionSequence);\n"
1795   "}\n"
1796   "@endtsexample\n\n"
1797   
1798   "@see GameConnection::onDataBlocksDone()\n\n")
1799{
1800    // Set the datablock sequence.
1801    object->setDataBlockSequence(sequence);
1802
1803    // Store a pointer to the datablock group.
1804    SimDataBlockGroup* pGroup = Sim::getDataBlockGroup();
1805
1806    // Determine the size of the datablock group.
1807    const U32 iCount = pGroup->size();
1808
1809    // If this is the local client...
1810#ifdef AFX_CAP_DATABLOCK_CACHE 
1811    if (GameConnection::getLocalClientConnection() == object && !GameConnection::serverCacheEnabled())
1812#else
1813    if (GameConnection::getLocalClientConnection() == object)
1814#endif 
1815    {
1816        // Set up a pointer to the datablock.
1817        SimDataBlock* pDataBlock = 0;
1818
1819        // Set up a buffer for the datablock send.
1820        U8 iBuffer[16384];
1821        BitStream mStream(iBuffer, 16384);
1822
1823        // Iterate through all the datablocks...
1824        for (U32 i = 0; i < iCount; i++)
1825        {
1826            // Get a pointer to the datablock in question...
1827            pDataBlock = (SimDataBlock*)(*pGroup)[i];
1828
1829            // Set the client's new modified key.
1830            object->setMaxDataBlockModifiedKey(pDataBlock->getModifiedKey());
1831
1832            // Pack the datablock stream.
1833            mStream.setPosition(0);
1834            mStream.clearCompressionPoint();
1835            pDataBlock->packData(&mStream);
1836
1837            // Unpack the datablock stream.
1838            mStream.setPosition(0);
1839            mStream.clearCompressionPoint();
1840            pDataBlock->unpackData(&mStream);
1841
1842            // Call the console function to set the number of blocks to be sent.
1843            onDataBlockObjectReceived_callback(i, iCount);
1844
1845            // Preload the datablock on the dummy client.
1846            pDataBlock->preload(false, NetConnection::getErrorBuffer());
1847        }
1848
1849        // Get the last datablock (if any)...
1850        if (pDataBlock)
1851        {
1852            // Ensure the datablock modified key is set.
1853            object->setDataBlockModifiedKey(object->getMaxDataBlockModifiedKey());
1854
1855            // Ensure that the client knows that the datablock send is done...
1856            object->sendConnectionMessage(GameConnection::DataBlocksDone, object->getDataBlockSequence());
1857        }
1858
1859        if (iCount == 0)
1860        {
1861           //if we have no datablocks to send, we still need to be able to complete the level load process
1862           //so fire off our callback anyways
1863           object->sendConnectionMessage(GameConnection::DataBlocksDone, object->getDataBlockSequence());
1864        }
1865    } 
1866    else
1867    {
1868        // Otherwise, store the current datablock modified key.
1869        const S32 iKey = object->getDataBlockModifiedKey();
1870
1871        // Iterate through the datablock group...
1872        U32 i = 0;
1873        for (; i < iCount; i++)
1874        {
1875            // If the datablock's modified key has already been set, break out of the loop...
1876            if (((SimDataBlock*)(*pGroup)[i])->getModifiedKey() > iKey)
1877            {
1878                break;
1879            }
1880        }
1881
1882        // If this is the last datablock in the group...
1883        if (i == iCount)
1884        {
1885            // Ensure that the client knows that the datablock send is done...
1886            object->sendConnectionMessage(GameConnection::DataBlocksDone, object->getDataBlockSequence());
1887
1888            // Then exit out since nothing else needs to be done.
1889            return;
1890        }
1891
1892        // Set the maximum datablock modified key value.
1893        object->setMaxDataBlockModifiedKey(iKey);
1894
1895        // Get the minimum number of datablocks...
1896        const U32 iMax = getMin(i + DataBlockQueueCount, iCount);
1897
1898        // Iterate through the remaining datablocks...
1899        for (;i < iMax; i++)
1900        {
1901            // Get a pointer to the datablock in question...
1902            SimDataBlock* pDataBlock = (SimDataBlock*)(*pGroup)[i];
1903
1904            // Post the datablock event to the client.
1905            object->postNetEvent(new SimDataBlockEvent(pDataBlock, i, iCount, object->getDataBlockSequence()));
1906        }
1907    }
1908}
1909
1910DefineEngineMethod( GameConnection, activateGhosting, void, (),,
1911   "@brief Called by the server during phase 2 of the mission download to start sending ghosts to the client.\n\n"
1912   
1913   "Ghosts represent objects on the server that are in scope for the client.  These need "
1914   "to be synchronized with the client in order for the client to see and interact with them.  "
1915   "This is typically done during the standard mission start phase 2 when following Torque's "
1916   "example mission startup sequence.\n\n"
1917
1918   "@tsexample\n"
1919   "function serverCmdMissionStartPhase2Ack(%client, %seq, %playerDB)\n"
1920   "{\n"
1921   "   // Make sure to ignore calls from a previous mission load\n"
1922   "   if (%seq != $missionSequence || !$MissionRunning)\n"
1923   "      return;\n"
1924   "   if (%client.currentPhase != 1.5)\n"
1925   "      return;\n"
1926   "   %client.currentPhase = 2;\n"
1927   "\n"
1928   "   // Set the player datablock choice\n"
1929   "   %client.playerDB = %playerDB;\n"
1930   "\n"
1931   "   // Update mod paths, this needs to get there before the objects.\n"
1932   "   %client.transmitPaths();\n"
1933   "\n"
1934   "   // Start ghosting objects to the client\n"
1935   "   %client.activateGhosting();\n"
1936   "}\n"
1937   "@endtsexample\n\n"
1938
1939   "@see @ref ghosting_scoping for a description of the ghosting system.\n\n")
1940{
1941   object->activateGhosting();
1942}
1943
1944DefineEngineMethod( GameConnection, resetGhosting, void, (),,
1945   "@brief On the server, resets the connection to indicate that ghosting has been disabled.\n\n"
1946
1947   "Typically when a mission has ended on the server, all connected clients are informed of this change "
1948   "and their connections are reset back to a starting state.  This method resets a connection on the "
1949   "server to indicate that ghosts are no longer being transmitted.  On the client end, all ghost "
1950   "information will be deleted.\n\n"
1951
1952   "@tsexample\n"
1953   "   // Inform the clients\n"
1954   "   for (%clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++)\n"
1955   "   {\n"
1956   "      // clear ghosts and paths from all clients\n"
1957   "      %cl = ClientGroup.getObject(%clientIndex);\n"
1958   "      %cl.endMission();\n"
1959   "      %cl.resetGhosting();\n"
1960   "      %cl.clearPaths();\n"
1961   "   }\n"
1962   "@endtsexample\n\n"
1963
1964   "@see @ref ghosting_scoping for a description of the ghosting system.\n\n")
1965{
1966   object->resetGhosting();
1967}
1968
1969DefineEngineMethod( GameConnection, setControlObject, bool, (GameBase* ctrlObj),,
1970   "@brief On the server, sets the object that the client will control.\n\n"
1971   "By default the control object is an instance of the Player class, but can also be an instance "
1972   "of Camera (when editing the mission, for example), or any other ShapeBase derived class as "
1973   "appropriate for the game.\n\n"
1974   "@param ctrlObj The GameBase object on the server to control.")
1975{
1976   if(!ctrlObj)
1977      return false;
1978
1979   object->setControlObject(ctrlObj);
1980   return true;
1981}
1982
1983DefineEngineMethod( GameConnection, clearDisplayDevice, void, (),,
1984   "@brief Clear any display device.\n\n"
1985   "A display device may define a number of properties that are used during rendering.\n\n")
1986{
1987   object->clearDisplayDevice();
1988}
1989
1990DefineEngineMethod( GameConnection, getControlObject, GameBase*, (),,
1991   "@brief On the server, returns the object that the client is controlling."
1992   "By default the control object is an instance of the Player class, but can also be an instance "
1993   "of Camera (when editing the mission, for example), or any other ShapeBase derived class as "
1994   "appropriate for the game.\n\n"
1995   "@see GameConnection::setControlObject()\n\n")
1996{
1997   return object->getControlObject();
1998}
1999
2000DefineEngineMethod( GameConnection, isAIControlled, bool, (),,
2001   "@brief Returns true if this connection is AI controlled.\n\n"
2002   "@see AIConnection")
2003{
2004   return object->isAIControlled();
2005}
2006
2007DefineEngineMethod( GameConnection, isControlObjectRotDampedCamera, bool, (),,
2008   "@brief Returns true if the object being controlled by the client is making use "
2009   "of a rotation damped camera.\n\n"
2010   "@see Camera")
2011{
2012   return object->isControlObjectRotDampedCamera();
2013}
2014
2015DefineEngineMethod( GameConnection, play2D, bool, (SFXProfile* profile),,
2016   "@brief Used on the server to play a 2D sound that is not attached to any object.\n\n"
2017
2018   "@param profile The SFXProfile that defines the sound to play.\n\n"
2019
2020   "@tsexample\n"
2021   "function ServerPlay2D(%profile)\n"
2022   "{\n"
2023   "   // Play the given sound profile on every client.\n"
2024   "   // The sounds will be transmitted as an event, not attached to any object.\n"
2025   "   for(%idx = 0; %idx < ClientGroup.getCount(); %idx++)\n"
2026   "      ClientGroup.getObject(%idx).play2D(%profile);\n"
2027   "}\n"
2028   "@endtsexample\n\n")
2029{
2030   if(!profile)
2031      return false;
2032
2033   object->play2D(profile);
2034   return true;
2035}
2036
2037DefineEngineMethod( GameConnection, play3D, bool, (SFXProfile* profile, TransformF location),,
2038   "@brief Used on the server to play a 3D sound that is not attached to any object.\n\n"
2039   
2040   "@param profile The SFXProfile that defines the sound to play.\n"
2041   "@param location The position and orientation of the 3D sound given in the form of \"x y z ax ay az aa\".\n\n"
2042
2043   "@tsexample\n"
2044   "function ServerPlay3D(%profile,%transform)\n"
2045   "{\n"
2046   "   // Play the given sound profile at the given position on every client\n"
2047   "   // The sound will be transmitted as an event, not attached to any object.\n"
2048   "   for(%idx = 0; %idx < ClientGroup.getCount(); %idx++)\n"
2049   "      ClientGroup.getObject(%idx).play3D(%profile,%transform);\n"
2050   "}\n"
2051   "@endtsexample\n\n")
2052{
2053   if(!profile)
2054      return false;
2055
2056   MatrixF mat = location.getMatrix();
2057   object->play3D(profile,&mat);
2058   return true;
2059}
2060
2061DefineEngineMethod( GameConnection, chaseCam, bool, (S32 size),,
2062   "@brief Sets the size of the chase camera's matrix queue.\n\n"
2063   "@note This sets the queue size across all GameConnections.\n\n"
2064   "@note This is not currently hooked up.\n\n")
2065{
2066   if (size != sChaseQueueSize) 
2067   {
2068      SAFE_DELETE_ARRAY(sChaseQueue);
2069
2070      sChaseQueueSize = size;
2071      sChaseQueueHead = sChaseQueueTail = 0;
2072
2073      if (size) 
2074      {
2075         sChaseQueue = new MatrixF[size];
2076         return true;
2077      }
2078   }
2079   return false;
2080}
2081
2082DefineEngineMethod( GameConnection, getControlCameraDefaultFov, F32, (),,
2083   "@brief Returns the default field of view as used by the control object's camera.\n\n")
2084{
2085   F32 fov = 0.0f;
2086   if(!object->getControlCameraDefaultFov(&fov))
2087      return(0.0f);
2088   return(fov);
2089}
2090
2091DefineEngineMethod( GameConnection, setControlCameraFov, void, (F32 newFOV),,
2092   "@brief On the server, sets the control object's camera's field of view.\n\n"
2093   "@param newFOV New field of view (in degrees) to force the control object's camera to use.  This value "
2094   "is clamped to be within the range of 1 to 179 degrees.\n\n"
2095   "@note When transmitted over the network to the client, the resolution is limited to "
2096   "one degree.  Any fraction is dropped.")
2097{
2098   object->setControlCameraFov(newFOV);
2099}
2100
2101DefineEngineMethod( GameConnection, getControlCameraFov, F32, (),,
2102   "@brief Returns the field of view as used by the control object's camera.\n\n")
2103{
2104   F32 fov = 0.0f;
2105   if(!object->getControlCameraFov(&fov))
2106      return(0.0f);
2107   return(fov);
2108}
2109
2110DefineEngineMethod( GameConnection, getDamageFlash, F32, (),,
2111   "@brief On the client, get the control object's damage flash level.\n\n"
2112   "@return flash level\n")
2113{
2114   return object->getDamageFlash();
2115}
2116
2117DefineEngineMethod( GameConnection, getWhiteOut, F32, (),,
2118   "@brief On the client, get the control object's white-out level.\n\n"
2119   "@return white-out level\n")
2120{
2121   return object->getWhiteOut();
2122}
2123
2124DefineEngineMethod( GameConnection, setBlackOut, void, (bool doFade, S32 timeMS),,
2125   "@brief On the server, sets the client's 3D display to fade to black.\n\n"
2126   "@param doFade Set to true to fade to black, and false to fade from black.\n"
2127   "@param timeMS Time it takes to perform the fade as measured in ms.\n\n"
2128   "@note Not currently hooked up, and is not synchronized over the network.")
2129{
2130   object->setBlackOut(doFade, timeMS);
2131}
2132
2133DefineEngineMethod( GameConnection, setMissionCRC, void, (S32 CRC),,
2134   "@brief On the server, transmits the mission file's CRC value to the client.\n\n"
2135
2136   "Typically, during the standard mission start phase 1, the mission file's CRC value "
2137   "on the server is send to the client.  This allows the client to determine if the mission "
2138   "has changed since the last time it downloaded this mission and act appropriately, such as "
2139   "rebuilt cached lightmaps.\n\n"
2140
2141   "@param CRC The mission file's CRC value on the server.\n\n"
2142
2143   "@tsexample\n"
2144   "function serverCmdMissionStartPhase1Ack(%client, %seq)\n"
2145   "{\n"
2146   "   // Make sure to ignore calls from a previous mission load\n"
2147   "   if (%seq != $missionSequence || !$MissionRunning)\n"
2148   "      return;\n"
2149   "   if (%client.currentPhase != 0)\n"
2150   "      return;\n"
2151   "   %client.currentPhase = 1;\n"
2152   "\n"
2153   "   // Start with the CRC\n"
2154   "   %client.setMissionCRC( $missionCRC );\n"
2155   "\n"
2156   "   // Send over the datablocks...\n"
2157   "   // OnDataBlocksDone will get called when have confirmation\n"
2158   "   // that they've all been received.\n"
2159   "   %client.transmitDataBlocks($missionSequence);\n"
2160   "}\n"
2161   "@endtsexample\n\n")
2162{
2163   if(object->isConnectionToServer())
2164      return;
2165
2166   object->postNetEvent(new SetMissionCRCEvent(CRC));
2167}
2168
2169DefineEngineMethod( GameConnection, delete, void, (const char* reason), (""),
2170   "@brief On the server, disconnect a client and pass along an optional reason why.\n\n"
2171
2172   "This method performs two operations: it disconnects a client connection from the server, "
2173   "and it deletes the connection object.  The optional reason is sent in the disconnect packet "
2174   "and is often displayed to the user so they know why they've been disconnected.\n\n"
2175   
2176   "@param reason [optional] The reason why the user has been disconnected from the server.\n\n"
2177   
2178   "@tsexample\n"
2179   "function kick(%client)\n"
2180   "{\n"
2181   "   messageAll( 'MsgAdminForce', '\\c2The Admin has kicked %1.', %client.playerName);\n"
2182   "\n"
2183   "   if (!%client.isAIControlled())\n"
2184   "      BanList::add(%client.guid, %client.getAddress(), $Pref::Server::KickBanTime);\n"
2185   "   %client.delete(\"You have been kicked from this server\");\n"
2186   "}\n"
2187   "@endtsexample\n\n")
2188{
2189   object->setDisconnectReason(reason);
2190   object->deleteObject();
2191}
2192
2193
2194//--------------------------------------------------------------------------
2195void GameConnection::consoleInit()
2196{
2197   Con::addVariable("$pref::Net::LagThreshold", TypeS32, &mLagThresholdMS,
2198      "@brief How long between received packets before the client is considered as lagging (in ms).\n\n"
2199
2200      "This is used by GameConnection to determine if the client is lagging.  "
2201      "If the client is indeed lagging, setLagIcon() is called to inform the user in some way.  i.e. "
2202      "display an icon on screen.\n\n"
2203
2204      "@see GameConnection, GameConnection::setLagIcon()\n\n"
2205
2206      "@ingroup Networking\n");
2207
2208   // Con::addVariable("specialFog", TypeBool, &SceneGraph::useSpecial);
2209
2210#ifdef AFX_CAP_DATABLOCK_CACHE 
2211   Con::addVariable("$Pref::Server::DatablockCacheFilename",  TypeString,   &server_cache_filename);
2212   Con::addVariable("$pref::Client::DatablockCacheFilename",  TypeString,   &client_cache_filename);
2213   Con::addVariable("$Pref::Server::EnableDatablockCache",    TypeBool,     &server_cache_on);
2214   Con::addVariable("$pref::Client::EnableDatablockCache",    TypeBool,     &client_cache_on);
2215#endif 
2216}
2217
2218DefineEngineMethod( GameConnection, startRecording, void, (const char* fileName),,
2219   "@brief On the client, starts recording the network connection's traffic to a demo file.\n\n"
2220   
2221   "It is often useful to play back a game session.  This could be for producing a "
2222   "demo of the game that will be shown at a later time, or for debugging a game.  "
2223   "By recording the entire network stream it is possible to later play game the game "
2224   "exactly as it unfolded during the actual play session.  This is because all user "
2225   "control and server results pass through the connection.\n\n"
2226   
2227   "@param fileName The file name to use for the demo recording.\n\n"
2228   
2229   "@see GameConnection::stopRecording(), GameConnection::playDemo()")
2230{
2231   char expFileName[1024];
2232   Con::expandScriptFilename(expFileName, sizeof(expFileName), fileName);
2233   object->startDemoRecord(expFileName);
2234}
2235
2236DefineEngineMethod( GameConnection, stopRecording, void, (),,
2237   "@brief On the client, stops the recording of a connection's network traffic to a file.\n\n"
2238   
2239   "@see GameConnection::startRecording(), GameConnection::playDemo()")
2240{
2241   object->stopRecording();
2242}
2243
2244DefineEngineMethod( GameConnection, playDemo, bool, (const char* demoFileName),,
2245   "@brief On the client, play back a previously recorded game session.\n\n"
2246   
2247   "It is often useful to play back a game session.  This could be for producing a "
2248   "demo of the game that will be shown at a later time, or for debugging a game.  "
2249   "By recording the entire network stream it is possible to later play game the game "
2250   "exactly as it unfolded during the actual play session.  This is because all user "
2251   "control and server results pass through the connection.\n\n"
2252
2253   "@returns True if the playback was successful.  False if there was an issue, such as "
2254   "not being able to open the demo file for playback.\n\n"
2255   
2256   "@see GameConnection::startRecording(), GameConnection::stopRecording()")
2257{
2258   char filename[1024];
2259   Con::expandScriptFilename(filename, sizeof(filename), demoFileName);
2260
2261   // Note that calling onConnectionEstablished will change the values in argv!
2262   object->onConnectionEstablished(true);
2263   object->setEstablished();
2264
2265   if(!object->replayDemoRecord(filename))
2266   {
2267      Con::printf("Unable to open demo file %s.", filename);
2268      object->deleteObject();
2269      return false;
2270   }
2271
2272   // After demo has loaded, execute the scene re-light the scene
2273   //SceneLighting::lightScene(0, 0);
2274   GameConnection::smPlayingDemo.trigger();
2275
2276   return true;
2277}
2278
2279DefineEngineMethod( GameConnection, isDemoPlaying, bool, (),,
2280   "@brief Returns true if a previously recorded demo file is now playing.\n\n"
2281   
2282   "@see GameConnection::playDemo()")
2283{
2284   return object->isPlayingBack();
2285}
2286
2287DefineEngineMethod( GameConnection, isDemoRecording, bool, (),,
2288   "@brief Returns true if a demo file is now being recorded.\n\n"
2289   
2290   "@see GameConnection::startRecording(), GameConnection::stopRecording()")
2291{
2292   return object->isRecording();
2293}
2294
2295DefineEngineMethod( GameConnection, listClassIDs, void, (),,
2296   "@brief List all of the classes that this connection knows about, and what their IDs are. Useful for debugging network problems.\n\n"
2297   "@note The list is sent to the console.\n\n")
2298{
2299   Con::printf("--------------- Class ID Listing ----------------");
2300   Con::printf(" id    |   name");
2301
2302   for(AbstractClassRep *rep = AbstractClassRep::getClassList();
2303      rep;
2304      rep = rep->getNextClass())
2305   {
2306      ConsoleObject *obj = rep->create();
2307      if(obj && rep->getClassId(object->getNetClassGroup()) >= 0)
2308         Con::printf("%7.7d| %s", rep->getClassId(object->getNetClassGroup()), rep->getClassName());
2309      delete obj;
2310   }
2311}
2312
2313DefineEngineStaticMethod( GameConnection, getServerConnection, S32, (),,
2314   "@brief On the client, this static mehtod will return the connection to the server, if any.\n\n"
2315
2316   "@returns The SimObject ID of the server connection, or -1 if none is found.\n\n")
2317{
2318   if(GameConnection::getConnectionToServer())
2319      return GameConnection::getConnectionToServer()->getId();
2320   else
2321   {
2322      Con::errorf("GameConnection::getServerConnection - no connection available.");
2323      return -1;
2324   }
2325}
2326
2327DefineEngineMethod( GameConnection, setCameraObject, bool, (GameBase* camera),,
2328   "@brief On the server, set the connection's camera object used when not viewing "
2329   "through the control object.\n\n"
2330   
2331   "@see GameConnection::getCameraObject() and GameConnection::clearCameraObject()\n\n")
2332{
2333   if(!camera)
2334      return false;
2335
2336   object->setCameraObject(camera);
2337   return true;
2338}
2339
2340DefineEngineMethod( GameConnection, getCameraObject, SimObject*, (),,
2341   "@brief Returns the connection's camera object used when not viewing through the control object.\n\n"
2342   
2343   "@see GameConnection::setCameraObject() and GameConnection::clearCameraObject()\n\n")
2344{
2345   SimObject *obj = dynamic_cast<SimObject*>(object->getCameraObject());
2346   return obj;
2347}
2348
2349DefineEngineMethod( GameConnection, clearCameraObject, void, (),,
2350   "@brief Clear the connection's camera object reference.\n\n"
2351   
2352   "@see GameConnection::setCameraObject() and GameConnection::getCameraObject()\n\n")
2353{
2354   object->setCameraObject(NULL);
2355}
2356
2357DefineEngineMethod( GameConnection, isFirstPerson, bool, (),,
2358   "@brief Returns true if this connection is in first person mode.\n\n"
2359
2360   "@note Transition to first person occurs over time via mCameraPos, so this "
2361   "won't immediately return true after a set.\n\n")
2362{
2363   // Note: Transition to first person occurs over time via mCameraPos, so this
2364   // won't immediately return true after a set.
2365   return object->isFirstPerson();
2366}
2367
2368DefineEngineMethod( GameConnection, setFirstPerson, void, (bool firstPerson),,
2369   "@brief On the server, sets this connection into or out of first person mode.\n\n"
2370   
2371   "@param firstPerson Set to true to put the connection into first person mode.\n\n")
2372{
2373   object->setFirstPerson(firstPerson);
2374}
2375
2376DefineEngineMethod( GameConnection, setControlSchemeParameters, void, (bool absoluteRotation, bool addYawToAbsRot, bool addPitchToAbsRot),,
2377   "@brief Set the control scheme that may be used by a connection's control object.\n\n"
2378   
2379   "@param absoluteRotation Use absolute rotation values from client, likely through ExtendedMove.\n"
2380   "@param addYawToAbsRot Add relative yaw control to the absolute rotation calculation.  Only useful when absoluteRotation is true.\n\n" )
2381{
2382   object->setControlSchemeParameters(absoluteRotation, addYawToAbsRot, addPitchToAbsRot);
2383}
2384
2385DefineEngineMethod( GameConnection, getControlSchemeAbsoluteRotation, bool, (),,
2386   "@brief Get the connection's control scheme absolute rotation property.\n\n"
2387   
2388   "@return True if the connection's control object should use an absolute rotation control scheme.\n\n"
2389   "@see GameConnection::setControlSchemeParameters()\n\n")
2390{
2391   return object->getControlSchemeAbsoluteRotation();
2392}
2393
2394DefineEngineMethod( GameConnection, setVisibleGhostDistance, void, (F32 dist),,
2395   "@brief Sets the distance that objects around it will be ghosted. If set to 0, "
2396   "it may be defined by the LevelInfo.\n\n"
2397   "@dist - is the max distance\n\n"
2398   )
2399{
2400   object->setVisibleGhostDistance(dist);
2401}
2402
2403DefineEngineMethod( GameConnection, getVisibleGhostDistance, F32, (),,
2404   "@brief Gets the distance that objects around the connection will be ghosted.\n\n"
2405   
2406   "@return S32 of distance.\n\n"
2407   )
2408{
2409   return object->getVisibleGhostDistance();
2410}
2411
2412#ifdef TORQUE_AFX_ENABLED 
2413// The object selection code here is, in part, based, on functionality described
2414// in the following resource:
2415// Object Selection in Torque by Dave Myers 
2416//   http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7335
2417
2418DefineEngineMethod(GameConnection, setSelectedObj, bool, (SceneObject* obj, bool propagate_to_client), (false), "")
2419{
2420   if (!obj)
2421      return false;
2422
2423   object->setSelectedObj(obj, propagate_to_client);
2424
2425   return true;
2426}
2427
2428DefineEngineMethod(GameConnection, getSelectedObj, SimObject*, (),, "")
2429{
2430   return object->getSelectedObj();
2431}
2432
2433DefineEngineMethod(GameConnection, clearSelectedObj, void, (bool propagate_to_client), (false), "")
2434{
2435   object->setSelectedObj(NULL, propagate_to_client);
2436}
2437
2438DefineEngineMethod(GameConnection, setPreSelectedObjFromRollover, void, (),, "")
2439{
2440   object->setPreSelectedObjFromRollover();
2441}
2442
2443DefineEngineMethod(GameConnection, clearPreSelectedObj, void, (),, "")
2444{
2445   object->clearPreSelectedObj();
2446}
2447
2448DefineEngineMethod(GameConnection, setSelectedObjFromPreSelected, void, (),, "")
2449{
2450   object->setSelectedObjFromPreSelected();
2451}
2452
2453void GameConnection::setSelectedObj(SceneObject* so, bool propagate_to_client) 
2454{ 
2455   if (!isConnectionToServer())
2456   {
2457      // clear previously selected object
2458      if (mSelectedObj)
2459         clearNotify(mSelectedObj);
2460
2461      // save new selection
2462      mSelectedObj = so; 
2463
2464      // mark selected object
2465      if (mSelectedObj)
2466         deleteNotify(mSelectedObj);
2467
2468      // mark selection dirty
2469      if (propagate_to_client)
2470         mChangedSelectedObj = true; 
2471
2472      return;
2473   }
2474
2475   // clear previously selected object
2476   if (mSelectedObj)
2477   {
2478      mSelectedObj->setSelectionFlags(mSelectedObj->getSelectionFlags() & ~<a href="/coding/class/classsceneobject/#classsceneobject_1ac79530217cc9af2577689342aba68be1a30a33ce7ad6bd1abd28b5ce070d05354">SceneObject::SELECTED</a>);
2479      clearNotify(mSelectedObj);
2480      Con::executef(this, "onObjectDeselected", mSelectedObj->getIdString());
2481   }
2482
2483   // save new selection
2484   mSelectedObj = so; 
2485
2486   // mark selected object
2487   if (mSelectedObj)
2488   {
2489      mSelectedObj->setSelectionFlags(mSelectedObj->getSelectionFlags() | SceneObject::SELECTED);
2490      deleteNotify(mSelectedObj);
2491   }
2492
2493   // mark selection dirty
2494   //mChangedSelectedObj = true; 
2495
2496   // notify appropriate script of the change
2497   if (mSelectedObj)
2498      Con::executef(this, "onObjectSelected", mSelectedObj->getIdString());
2499}
2500
2501void GameConnection::setRolloverObj(SceneObject* so) 
2502{ 
2503   // save new selection
2504   mRolloverObj = so;  
2505
2506   // notify appropriate script of the change
2507   Con::executef(this, "onObjectRollover", (mRolloverObj) ? mRolloverObj->getIdString() : "");
2508}
2509
2510void GameConnection::setPreSelectedObjFromRollover()
2511{
2512   mPreSelectedObj = mRolloverObj;
2513   mPreSelectTimestamp = Platform::getRealMilliseconds();
2514}
2515
2516void GameConnection::clearPreSelectedObj()
2517{
2518   mPreSelectedObj = 0;
2519   mPreSelectTimestamp = 0;
2520}
2521
2522void GameConnection::setSelectedObjFromPreSelected()
2523{
2524   U32 now = Platform::getRealMilliseconds();
2525   if (now - mPreSelectTimestamp < arcaneFX::sTargetSelectionTimeoutMS)
2526      setSelectedObj(mPreSelectedObj);
2527   mPreSelectedObj = 0;
2528}
2529
2530void GameConnection::onDeleteNotify(SimObject* obj)
2531{
2532   if (obj == mSelectedObj)
2533      setSelectedObj(NULL);
2534
2535   Parent::onDeleteNotify(obj);
2536}
2537#endif
2538
2539#ifdef AFX_CAP_DATABLOCK_CACHE 
2540
2541void GameConnection::tempDisableStringBuffering(BitStream* bs) const 
2542{ 
2543   bs->setStringBuffer(0); 
2544}
2545
2546void GameConnection::restoreStringBuffering(BitStream* bs) const 
2547{ 
2548   bs->clearStringBuffer();
2549}              
2550
2551// rewind to stream postion and then move raw bytes into client_db_stream
2552// for caching purposes.
2553void GameConnection::repackClientDatablock(BitStream* bstream, S32 start_pos)
2554{
2555   static U8 bit_buffer[Net::MaxPacketDataSize];
2556
2557   if (!clientCacheEnabled() || !client_db_stream)
2558      return;
2559
2560   S32 cur_pos = bstream->getCurPos();
2561   S32 n_bits = cur_pos - start_pos;
2562   if (n_bits <= 0)
2563      return;
2564
2565   bstream->setCurPos(start_pos);
2566   bstream->readBits(n_bits, bit_buffer);
2567   bstream->setCurPos(cur_pos);
2568
2569   //S32 start_pos2 = client_db_stream->getCurPos();
2570   client_db_stream->writeBits(n_bits, bit_buffer);
2571}
2572
2573#define CLIENT_CACHE_VERSION_CODE 47241113
2574
2575void GameConnection::saveDatablockCache(bool on_server)
2576{
2577   InfiniteBitStream bit_stream;
2578   BitStream* bstream = 0;
2579
2580   if (on_server)
2581   {
2582      SimDataBlockGroup *g = Sim::getDataBlockGroup();
2583
2584      // find the first one we haven't sent:
2585      U32 i, groupCount = g->size();
2586      S32 key = this->getDataBlockModifiedKey();
2587      for (i = 0; i < groupCount; i++)
2588         if (((SimDataBlock*)(*g)[i])->getModifiedKey() > key)
2589            break;
2590
2591      // nothing to save
2592      if (i == groupCount) 
2593         return;
2594
2595      bstream = &bit_stream;
2596
2597      for (;i < groupCount; i++) 
2598      {
2599         SimDataBlock* obj = (SimDataBlock*)(*g)[i];
2600         GameConnection* gc = this;
2601         NetConnection* conn = this;
2602         SimObjectId id = obj->getId();
2603
2604         if (bstream->writeFlag(gc->getDataBlockModifiedKey() < obj->getModifiedKey()))        // A - flag
2605         {
2606            if (obj->getModifiedKey() > gc->getMaxDataBlockModifiedKey())
2607               gc->setMaxDataBlockModifiedKey(obj->getModifiedKey());
2608
2609            bstream->writeInt(id - DataBlockObjectIdFirst,DataBlockObjectIdBitSize);            // B - int
2610
2611            S32 classId = obj->getClassId(conn->getNetClassGroup());
2612            bstream->writeClassId(classId, NetClassTypeDataBlock, conn->getNetClassGroup());    // C - id
2613            bstream->writeInt(i, DataBlockObjectIdBitSize);                                     // D - int
2614            bstream->writeInt(groupCount, DataBlockObjectIdBitSize + 1);                        // E - int
2615            obj->packData(bstream);
2616         }
2617      }
2618   }
2619   else
2620   {
2621      bstream = client_db_stream;
2622   }
2623
2624   if (bstream->getPosition() <= 0)
2625      return;
2626
2627   // zero out any leftover bits short of an even byte count
2628   U32 n_leftover_bits = (bstream->getPosition()*8) - bstream->getCurPos();
2629   if (n_leftover_bits >= 0 && n_leftover_bits <= 8)
2630   {
2631      // note - an unusual problem regarding setCurPos() results when there 
2632      // are no leftover bytes. Adding a buffer byte in this case avoids the problem.
2633      if (n_leftover_bits == 0)
2634         n_leftover_bits = 8;
2635      U8 bzero = 0;
2636      bstream->writeBits(n_leftover_bits, &bzero);
2637   }
2638
2639   // this is where we actually save the file
2640   const char* filename = (on_server) ? server_cache_filename : client_cache_filename;
2641   if (filename && filename[0] != '\0')
2642   {
2643      FileStream* f_stream;
2644      if((f_stream = FileStream::createAndOpen(filename, Torque::FS::File::Write )) == NULL)
2645      {
2646         Con::printf("Failed to open file '%s'.", filename);
2647         return;
2648      }
2649
2650      U32 save_sz = bstream->getPosition();
2651
2652      if (!on_server)
2653      {
2654         f_stream->write((U32)CLIENT_CACHE_VERSION_CODE);
2655         f_stream->write(save_sz);
2656         f_stream->write(server_cache_CRC);
2657         f_stream->write((U32)CLIENT_CACHE_VERSION_CODE);
2658      }
2659
2660      f_stream->write(save_sz, bstream->getBuffer());
2661
2662      // zero out any leftover bytes short of a 4-byte multiple
2663      while ((save_sz % 4) != 0)
2664      {
2665         f_stream->write((U8)0);
2666         save_sz++;
2667      }
2668
2669      delete f_stream;
2670   }
2671
2672   if (!on_server)
2673      client_db_stream->clear();
2674}
2675
2676static bool afx_saved_db_cache = false;
2677static U32 afx_saved_db_cache_CRC = 0xffffffff;
2678
2679void GameConnection::resetDatablockCache()
2680{
2681   afx_saved_db_cache = false;
2682   afx_saved_db_cache_CRC = 0xffffffff;
2683}
2684
2685DefineEngineFunction(resetDatablockCache, void, (),,"")
2686{
2687   GameConnection::resetDatablockCache();
2688}
2689
2690DefineEngineFunction(isDatablockCacheSaved, bool, (),,"")
2691{
2692   return afx_saved_db_cache;
2693}
2694
2695DefineEngineFunction(getDatablockCacheCRC, S32, (),,"")
2696{
2697   return (S32)afx_saved_db_cache_CRC;
2698}
2699
2700DefineEngineFunction(extractDatablockCacheCRC, S32, (const char* fileName),,"")
2701{
2702   FileStream f_stream;
2703   if (!f_stream.open(fileName, Torque::FS::File::Read))
2704   {
2705      Con::errorf("Failed to open file '%s'.", fileName);
2706      return -1;
2707   }
2708
2709   U32 stream_sz = f_stream.getStreamSize();
2710   if (stream_sz < 4 * 32)
2711   {
2712      Con::errorf("File '%s' is not a valid datablock cache.", fileName);
2713      f_stream.close();
2714      return -1;
2715   }
2716
2717   U32 pre_code; f_stream.read(&pre_code);
2718   U32 save_sz; f_stream.read(&save_sz);
2719   U32 crc_code; f_stream.read(&crc_code);
2720   U32 post_code; f_stream.read(&post_code);
2721
2722   f_stream.close();
2723
2724   if (pre_code != post_code)
2725   {
2726      Con::errorf("File '%s' is not a valid datablock cache.", fileName);
2727      return -1;
2728   }
2729
2730   if (pre_code != (U32)CLIENT_CACHE_VERSION_CODE)
2731   {
2732      Con::errorf("Version of datablock cache file '%s' does not match version of running software.", fileName);
2733      return -1;
2734   }
2735
2736   return (S32)crc_code;
2737}
2738
2739DefineEngineFunction(setDatablockCacheCRC, void, (U32 crc), , "")
2740{
2741   GameConnection *conn = GameConnection::getConnectionToServer();
2742   if (!conn)
2743      return;
2744
2745   conn->setServerCacheCRC(crc);
2746}
2747
2748DefineEngineMethod(GameConnection, saveDatablockCache, void, (),, "")
2749{
2750   if (GameConnection::serverCacheEnabled() && !afx_saved_db_cache)
2751   {
2752      // Save the datablocks to a cache file. An argument
2753      // of true indicates that this is a server save.
2754      object->saveDatablockCache(true);
2755      afx_saved_db_cache = true;
2756      afx_saved_db_cache_CRC = 0xffffffff;
2757
2758      static char filename_buffer[1024];
2759      String filename(Torque::Path::CleanSeparators(object->serverCacheFilename()));
2760      Con::expandScriptFilename(filename_buffer, sizeof(filename_buffer), filename.c_str());
2761      Torque::Path givenPath(Torque::Path::CompressPath(filename_buffer));
2762      Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(givenPath);
2763      if (fileRef == NULL)
2764         Con::errorf("saveDatablockCache() failed to get CRC for file '%s'.", filename.c_str());
2765      else
2766         afx_saved_db_cache_CRC = (S32)fileRef->getChecksum();
2767   }
2768}
2769
2770DefineEngineMethod(GameConnection, loadDatablockCache, void, (),, "")
2771{
2772   if (GameConnection::clientCacheEnabled())
2773   {
2774      object->loadDatablockCache();
2775   }
2776}
2777
2778DefineEngineMethod(GameConnection, loadDatablockCache_Begin, bool, (),, "")
2779{
2780   if (GameConnection::clientCacheEnabled())
2781   {
2782      return object->loadDatablockCache_Begin();
2783   }
2784
2785   return false;
2786}
2787
2788DefineEngineMethod(GameConnection, loadDatablockCache_Continue, bool, (),, "")
2789{
2790   if (GameConnection::clientCacheEnabled())
2791   {
2792      return object->loadDatablockCache_Continue();
2793   }
2794
2795   return false;
2796}
2797
2798static char*        afx_db_load_buf = 0;
2799static U32          afx_db_load_buf_sz = 0;
2800static BitStream*   afx_db_load_bstream = 0;
2801
2802void GameConnection::loadDatablockCache()
2803{
2804   if (!loadDatablockCache_Begin())
2805      return;
2806
2807   while (loadDatablockCache_Continue())
2808      ;
2809}
2810
2811bool GameConnection::loadDatablockCache_Begin()
2812{
2813   if (!client_cache_filename || client_cache_filename[0] == '\0')
2814   {
2815      Con::errorf("No filename was specified for the client datablock cache.");
2816      return false;
2817   }
2818
2819   // open cache file
2820   FileStream f_stream;
2821   if(!f_stream.open(client_cache_filename, Torque::FS::File::Read))
2822   {
2823      Con::errorf("Failed to open file '%s'.", client_cache_filename);
2824      return false;
2825   }
2826
2827   // get file size
2828   U32 stream_sz = f_stream.getStreamSize();
2829   if (stream_sz <= 4*4)
2830   {
2831      Con::errorf("File '%s' is too small to be a valid datablock cache.", client_cache_filename);
2832      f_stream.close();
2833      return false;
2834   }
2835
2836   // load header data
2837   U32 pre_code; f_stream.read(&pre_code);
2838   U32 save_sz; f_stream.read(&save_sz);
2839   U32 crc_code; f_stream.read(&crc_code);
2840   U32 post_code; f_stream.read(&post_code);
2841
2842   // validate header info 
2843   if (pre_code != post_code)
2844   {
2845      Con::errorf("File '%s' is not a valid datablock cache.", client_cache_filename);
2846      f_stream.close();
2847      return false;
2848   }
2849   if (pre_code != (U32)CLIENT_CACHE_VERSION_CODE)
2850   {
2851      Con::errorf("Version of datablock cache file '%s' does not match version of running software.", client_cache_filename);
2852      f_stream.close();
2853      return false;
2854   }
2855
2856   // allocated the in-memory buffer
2857   afx_db_load_buf_sz = stream_sz - (4*4);
2858   afx_db_load_buf = new char[afx_db_load_buf_sz];
2859
2860   // load data from file into memory
2861   if (!f_stream.read(stream_sz, afx_db_load_buf))
2862   {
2863      Con::errorf("Failed to read data from file '%s'.", client_cache_filename);
2864      f_stream.close();
2865      delete [] afx_db_load_buf;
2866      afx_db_load_buf = 0;
2867      afx_db_load_buf_sz = 0;
2868      return false;
2869   }
2870
2871   // close file
2872   f_stream.close();
2873
2874   // At this point we have the whole cache in memory
2875
2876   // create a bitstream from the in-memory buffer
2877   afx_db_load_bstream = new BitStream(afx_db_load_buf, afx_db_load_buf_sz);
2878
2879   return true;
2880}
2881
2882bool GameConnection::loadDatablockCache_Continue()
2883{
2884   if (!afx_db_load_bstream)
2885      return false;
2886
2887   // prevent repacking of datablocks during load
2888   BitStream* save_client_db_stream = client_db_stream;
2889   client_db_stream = 0;
2890
2891   bool all_finished = false;
2892
2893   // loop through at most 16 datablocks
2894   BitStream *bstream = afx_db_load_bstream;
2895   for (S32 i = 0; i < 16; i++)
2896   {
2897      S32 save_pos = bstream->getCurPos();
2898      if (!bstream->readFlag())
2899      {
2900         all_finished = true;
2901         break;
2902      }
2903      bstream->setCurPos(save_pos);
2904      SimDataBlockEvent evt;
2905      evt.unpack(this, bstream);
2906      evt.process(this);
2907   }
2908
2909   client_db_stream = save_client_db_stream;
2910
2911   if (all_finished)
2912   {
2913      delete afx_db_load_bstream;
2914      afx_db_load_bstream = 0;
2915      delete [] afx_db_load_buf;
2916      afx_db_load_buf = 0;
2917      afx_db_load_buf_sz = 0;
2918      return false;
2919   }
2920
2921   return true;
2922}
2923
2924#endif 
2925