gameConnection.cpp
Engine/source/T3D/gameBase/gameConnection.cpp
Public Defines
define
ControlRequestTime() 5000
define
Public Variables
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(¤tProtocol); 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