netConnection.cpp
Engine/source/sim/netConnection.cpp
Classes:
class
Used when simulating lag.
Public Enumerations
enum
NetConnectionConstants { PingTimeout = 4500 DefaultPingRetryCount = 15 }
enum
NetStringConstants { NullString = 0 CString TagString Integer }
Public Variables
Public Functions
ConsoleDocClass(ConnectionMessageEvent , "@brief This event is used inside by the connection and subclasses <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> message itself when sequencing events <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )
ConsoleDocClass(NetConnection , "@brief Provides the basis <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> implementing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> multiplayer game <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">protocol.\n\n</a>" "<a href="/coding/class/classnetconnection/">NetConnection</a> combines <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> low-level <a href="/coding/file/gamefunctions_8cpp/#gamefunctions_8cpp_1aa17ef8ef4f36199ef68ab2859f9fbda4">notify</a> protocol implemented in <a href="/coding/class/classconnectionprotocol/">ConnectionProtocol</a> with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> SimGroup, " "and implements several distinct <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">subsystems:\n\n</a>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Event Manager</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > This is responsible <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> transmitting NetEvents over the wire. " "It deals with ensuring that the various types of NetEvents are delivered appropriately, " "and with notifying the event of its delivery <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">status.\n\n</a>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> ><a href="/coding/class/structmove/">Move</a> Manager</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > This is responsible <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> transferring <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/structmove/">Move</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server 32 " "times <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> second(on the client) and applying it <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object(on the server).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Ghost Manager</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > This is responsible <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> doing scoping calculations(on the server " "side) and transmitting most-recent ghost information <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>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> ><a href="/coding/class/classfile/">File</a> Transfer</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > It is often the case that clients will lack important files when " "connecting <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> server which is running <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> mod or <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> map. This subsystem allows the " "server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> transfer such files <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>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Networked <a href="/coding/class/classstring/">String</a> Table</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > <a href="/coding/class/classstring/">String</a> data can easily soak up network bandwidth, so <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> " " efficiency, we implement <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> networked string table. We can then <a href="/coding/file/gamefunctions_8cpp/#gamefunctions_8cpp_1aa17ef8ef4f36199ef68ab2859f9fbda4">notify</a> the connection " "of strings we will reference often, such as player names, and transmit only <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> tag, " "instead of the whole <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">string.\n\n</a>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Demo Recording</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > A demo in Torque is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> log of the network traffic between client " "and server;when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classnetconnection/">NetConnection</a> records <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> demo, it simply logs this data <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> file. When " "it plays <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> demo back, it replays the logged <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">data.\n\n</a>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Connection Database</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > This is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> keep track of all the NetConnections;it can " "be iterated over, or queried " "by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">address.\n\n</a>" "The <a href="/coding/class/classnetconnection/">NetConnection</a> is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> SimGroup. On the client side, it contains all the objects which have been " "ghosted <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> that client. On the server side, it is empty;it can be used(typically in script) <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "hold objects related <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the connection. For instance, you might place an observation camera in the " "NetConnnection. In both cases, when the connection is destroyed, so are the contained <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">objects.\n\n</a>" "The <a href="/coding/class/classnetconnection/">NetConnection</a> also has the concept of local connections. These are used when the client and " "server reside in the same process. A local connection is typically <a href="/coding/file/tsshapeconstruct_8cpp/#tsshapeconstruct_8cpp_1a21625ca11566389388a748ad1acc0990">required</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use the standard " "Torque world building tools. A local connection is also <a href="/coding/file/tsshapeconstruct_8cpp/#tsshapeconstruct_8cpp_1a21625ca11566389388a748ad1acc0990">required</a> when building <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single player " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">game.\n\n</a>" " @see @ref Networking, @ref ghosting_scoping, @ref netconnection_simgroup, @ref local_connections, <a href="/coding/class/classgameconnection/">GameConnection</a> , <a href="/coding/class/classaiconnection/">AIConnection</a> , and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AIClient.\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Networking\n</a>" )
DefineEngineMethod(NetConnection , checkMaxRate , void , () , "@brief Ensures that all configured packet rates and sizes meet minimum <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">requirements.\n\n</a>" "This method is normally only called when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classnetconnection/">NetConnection</a> class is first constructed. It need " "only be manually called <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the global variables that set the packet rate or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> have <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">changed.\n\n</a>" "@note If @$pref::Net::PacketRateToServer , @ $pref::Net::PacketRateToClient or @ $pref::Net::PacketSize " "have been changed since <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classnetconnection/">NetConnection</a> has been created, this method must be called on " "all connections <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> them <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> follow the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> rates or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">size.\n</a>" )
DefineEngineMethod(NetConnection , clearPaths , void , () , "@brief On the server, resets the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> indicate that motion spline paths have not been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">transmitted.\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 motion spline paths have not been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">transmitted.\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</a>" " @see transmitPaths()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Path\n</a>" )
DefineEngineMethod(NetConnection , connect , void , (const char *remoteAddress) , "@brief Connects <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the remote <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">address.\n\n</a>" "Attempts <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> connect with another <a href="/coding/class/classnetconnection/">NetConnection</a> on the given address. Typically once " " connected, <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> game 's information is passed along from the server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client, followed " "by the player entering the game world. The actual procedure is dependent on " "the <a href="/coding/class/classnetconnection/">NetConnection</a> subclass that is used. i.e. <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GameConnection.\n</a>" " @param remoteAddress The address <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> connect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> in the form of IP:<address >:<port &rt;" "although the< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >IP:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > portion is optional. The< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >address</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > portion may be in the form " "of w.x.y.z or as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> host name, in which case <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> DNS lookup will be performed. You may also " "substitue the word< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >broadcast</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the address <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> broadcast the connect request over " "the local <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">subnet.\n\n</a>" " @see NetConnection::connectLocal() <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> connect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> server running within the same process " "as the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n</a>" )
DefineEngineMethod(NetConnection , connectLocal , const char * , () , "@brief Connects with the server that is running within the same process as the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n\n</a>" "@returns An error text message upon failure, or an empty string when <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">successful.\n\n</a>" " @see See @ref local_connections <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> description of local connections and their use. See " "<a href="/coding/class/classnetconnection/#classnetconnection_1a55cdb9fec45a9f2bce34d85200850e39">NetConnection::connect</a>() <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> connect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> server running in another process(on the same machine or not).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" )
DefineEngineMethod(NetConnection , getAddress , const char * , () )
DefineEngineMethod(NetConnection , getGhostID , S32 , (S32 realID) , "@brief On server or client, <a href="/coding/file/colladautils_8h/#colladautils_8h_1a24cd315eae41894b5bbf77c8c0b097d4">convert</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> real <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the ghost <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connection.\n\n</a>" "Torque 's network ghosting system only exchanges ghost ID 's between the server and client. Use " "this method on the server or client <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> discover an object 's ghost ID based on its real <a href="/coding/class/classsimobject/">SimObject</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n</a>" " @param realID The real <a href="/coding/class/classsimobject/">SimObject</a> ID of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" " @returns The ghost ID of the object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this connection, or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it could not be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">resolved.\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(NetConnection , getPacketLoss , S32 , () , "@brief Returns the percentage of packets lost per <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tick.\n\n</a>" "@note This method is not yet hooked <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">up.\n</a>" )
DefineEngineMethod(NetConnection , getPing , S32 , () , "@brief Returns the average round trip time (in ms) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connection.\n\n</a>" "The round trip time is recalculated every time <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/gamefunctions_8cpp/#gamefunctions_8cpp_1aa17ef8ef4f36199ef68ab2859f9fbda4">notify</a> packet is received. Notify " "packets are used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> information the connection that the far end successfully received " "the sent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">packet.\n</a>" )
DefineEngineMethod(NetConnection , resolveGhostID , S32 , (S32 ghostID) , "@brief On the client, <a href="/coding/file/colladautils_8h/#colladautils_8h_1a24cd315eae41894b5bbf77c8c0b097d4">convert</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> ghost ID from this connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> real <a href="/coding/class/classsimobject/">SimObject</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n\n</a>" "Torque 's network ghosting system only exchanges ghost ID 's between the server and client. Use " "this method on the client <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> discover an object 's local <a href="/coding/class/classsimobject/">SimObject</a> ID when you only have <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> " "ghost <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n</a>" " @param ghostID The ghost ID of the object as sent by the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" " @returns The <a href="/coding/class/classsimobject/">SimObject</a> ID of the object)
DefineEngineMethod(NetConnection , resolveObjectFromGhostIndex , S32 , (S32 ghostID) , "@brief On the server, <a href="/coding/file/colladautils_8h/#colladautils_8h_1a24cd315eae41894b5bbf77c8c0b097d4">convert</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> ghost ID from this connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> real <a href="/coding/class/classsimobject/">SimObject</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n\n</a>" "Torque 's network ghosting system only exchanges ghost ID 's between the server and client. Use " "this method on the server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> discover an object 's local <a href="/coding/class/classsimobject/">SimObject</a> ID when you only have <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> " "ghost <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n</a>" " @param ghostID The ghost ID of the object as sent by the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" " @returns The <a href="/coding/class/classsimobject/">SimObject</a> ID of the object)
DefineEngineMethod(NetConnection , setSimulatedNetParams , void , (F32 packetLoss, S32 delay) , "@brief Simulate network issues on the connection <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">testing.\n\n</a>" "@param packetLoss The fraction of packets that will be lost. Ranges from 0.0 (no loss) <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 1.0 (complete loss)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param delay Delays packets being transmitted by simulating <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> particular ping. This is an absolute " " integer, measured in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ms.\n</a>" )
DefineEngineMethod(NetConnection , transmitPaths , void , () , "@brief Sent by the server during phase 2 of the mission download <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> update motion spline <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">paths.\n\n</a>" "The server transmits all spline motion paths that are within the mission (Path) separate from " "other objects. This is due <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the potentially large number of nodes within each path, which may " "saturate <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> packet sent <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client. By managing this step separately, Torque has finer <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> " "over how packets are organised vs. doing it during the ghosting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">stage.\n\n</a>" "Internally <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classpathmanager/">PathManager</a> is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> track all paths defined within <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> mission on the server, and each " "one is transmitted using <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> PathManagerEvent. The client side collects these events and builds the " "given paths within its own PathManager. 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>" "When <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> mission is ended, all paths need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be cleared from their respective path managers." " @<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 mission paths(SimPath), 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</a>" " @see clearPaths()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Path\n</a>" )
HashNetAddress(const NetAddress * addr)
IMPLEMENT_NONINSTANTIABLE_CLASS(NetEvent , "An event <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be sent over the network." )
IMPLEMENT_SCOPE(NetAPI , Net , "Networking functionality." )
Detailed Description
Public Enumerations
NetConnectionConstants
Enumerator
- PingTimeout = 4500
milliseconds
- DefaultPingRetryCount = 15
NetStringConstants
Enumerator
- NullString = 0
- CString
- TagString
- Integer
Public Variables
U32 gGhostUpdates
S32 gNetBitsReceived
S32 gNetBitsSent
U32 gPacketRateToClient
U32 gPacketRateToServer
U32 gPacketSize
U32 gPacketUpdateDelayToServer
Public Functions
ConsoleDocClass(ConnectionMessageEvent , "@brief This event is used inside by the connection and subclasses <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> message itself when sequencing events <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )
ConsoleDocClass(NetConnection , "@brief Provides the basis <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> implementing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> multiplayer game <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">protocol.\n\n</a>" "<a href="/coding/class/classnetconnection/">NetConnection</a> combines <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> low-level <a href="/coding/file/gamefunctions_8cpp/#gamefunctions_8cpp_1aa17ef8ef4f36199ef68ab2859f9fbda4">notify</a> protocol implemented in <a href="/coding/class/classconnectionprotocol/">ConnectionProtocol</a> with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> SimGroup, " "and implements several distinct <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">subsystems:\n\n</a>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Event Manager</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > This is responsible <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> transmitting NetEvents over the wire. " "It deals with ensuring that the various types of NetEvents are delivered appropriately, " "and with notifying the event of its delivery <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">status.\n\n</a>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> ><a href="/coding/class/structmove/">Move</a> Manager</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > This is responsible <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> transferring <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/structmove/">Move</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server 32 " "times <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> second(on the client) and applying it <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> object(on the server).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Ghost Manager</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > This is responsible <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> doing scoping calculations(on the server " "side) and transmitting most-recent ghost information <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>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> ><a href="/coding/class/classfile/">File</a> Transfer</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > It is often the case that clients will lack important files when " "connecting <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> server which is running <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> mod or <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> map. This subsystem allows the " "server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> transfer such files <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>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Networked <a href="/coding/class/classstring/">String</a> Table</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > <a href="/coding/class/classstring/">String</a> data can easily soak up network bandwidth, so <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> " " efficiency, we implement <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> networked string table. We can then <a href="/coding/file/gamefunctions_8cpp/#gamefunctions_8cpp_1aa17ef8ef4f36199ef68ab2859f9fbda4">notify</a> the connection " "of strings we will reference often, such as player names, and transmit only <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> tag, " "instead of the whole <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">string.\n\n</a>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Demo Recording</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > A demo in Torque is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> log of the network traffic between client " "and server;when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classnetconnection/">NetConnection</a> records <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> demo, it simply logs this data <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> file. When " "it plays <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> demo back, it replays the logged <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">data.\n\n</a>" "-< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Connection Database</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > This is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> keep track of all the NetConnections;it can " "be iterated over, or queried " "by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">address.\n\n</a>" "The <a href="/coding/class/classnetconnection/">NetConnection</a> is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> SimGroup. On the client side, it contains all the objects which have been " "ghosted <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> that client. On the server side, it is empty;it can be used(typically in script) <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "hold objects related <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the connection. For instance, you might place an observation camera in the " "NetConnnection. In both cases, when the connection is destroyed, so are the contained <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">objects.\n\n</a>" "The <a href="/coding/class/classnetconnection/">NetConnection</a> also has the concept of local connections. These are used when the client and " "server reside in the same process. A local connection is typically <a href="/coding/file/tsshapeconstruct_8cpp/#tsshapeconstruct_8cpp_1a21625ca11566389388a748ad1acc0990">required</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use the standard " "Torque world building tools. A local connection is also <a href="/coding/file/tsshapeconstruct_8cpp/#tsshapeconstruct_8cpp_1a21625ca11566389388a748ad1acc0990">required</a> when building <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single player " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">game.\n\n</a>" " @see @ref Networking, @ref ghosting_scoping, @ref netconnection_simgroup, @ref local_connections, <a href="/coding/class/classgameconnection/">GameConnection</a> , <a href="/coding/class/classaiconnection/">AIConnection</a> , and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AIClient.\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Networking\n</a>" )
DefineEngineMethod(NetConnection , checkMaxRate , void , () , "@brief Ensures that all configured packet rates and sizes meet minimum <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">requirements.\n\n</a>" "This method is normally only called when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classnetconnection/">NetConnection</a> class is first constructed. It need " "only be manually called <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the global variables that set the packet rate or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> have <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">changed.\n\n</a>" "@note If @$pref::Net::PacketRateToServer , @ $pref::Net::PacketRateToClient or @ $pref::Net::PacketSize " "have been changed since <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classnetconnection/">NetConnection</a> has been created, this method must be called on " "all connections <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> them <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> follow the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> rates or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">size.\n</a>" )
DefineEngineMethod(NetConnection , clearPaths , void , () , "@brief On the server, resets the connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> indicate that motion spline paths have not been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">transmitted.\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 motion spline paths have not been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">transmitted.\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</a>" " @see transmitPaths()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Path\n</a>" )
DefineEngineMethod(NetConnection , connect , void , (const char *remoteAddress) , "@brief Connects <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the remote <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">address.\n\n</a>" "Attempts <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> connect with another <a href="/coding/class/classnetconnection/">NetConnection</a> on the given address. Typically once " " connected, <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> game 's information is passed along from the server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client, followed " "by the player entering the game world. The actual procedure is dependent on " "the <a href="/coding/class/classnetconnection/">NetConnection</a> subclass that is used. i.e. <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GameConnection.\n</a>" " @param remoteAddress The address <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> connect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> in the form of IP:<address >:<port &rt;" "although the< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >IP:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > portion is optional. The< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >address</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > portion may be in the form " "of w.x.y.z or as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> host name, in which case <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> DNS lookup will be performed. You may also " "substitue the word< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >broadcast</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the address <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> broadcast the connect request over " "the local <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">subnet.\n\n</a>" " @see NetConnection::connectLocal() <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> connect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> server running within the same process " "as the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n</a>" )
DefineEngineMethod(NetConnection , connectLocal , const char * , () , "@brief Connects with the server that is running within the same process as the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n\n</a>" "@returns An error text message upon failure, or an empty string when <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">successful.\n\n</a>" " @see See @ref local_connections <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> description of local connections and their use. See " "<a href="/coding/class/classnetconnection/#classnetconnection_1a55cdb9fec45a9f2bce34d85200850e39">NetConnection::connect</a>() <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> connect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> server running in another process(on the same machine or not).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" )
DefineEngineMethod(NetConnection , getAddress , const char * , () )
DefineEngineMethod(NetConnection , getGhostID , S32 , (S32 realID) , "@brief On server or client, <a href="/coding/file/colladautils_8h/#colladautils_8h_1a24cd315eae41894b5bbf77c8c0b097d4">convert</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> real <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the ghost <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connection.\n\n</a>" "Torque 's network ghosting system only exchanges ghost ID 's between the server and client. Use " "this method on the server or client <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> discover an object 's ghost ID based on its real <a href="/coding/class/classsimobject/">SimObject</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n</a>" " @param realID The real <a href="/coding/class/classsimobject/">SimObject</a> ID of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" " @returns The ghost ID of the object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this connection, or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it could not be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">resolved.\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(NetConnection , getPacketLoss , S32 , () , "@brief Returns the percentage of packets lost per <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tick.\n\n</a>" "@note This method is not yet hooked <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">up.\n</a>" )
DefineEngineMethod(NetConnection , getPing , S32 , () , "@brief Returns the average round trip time (in ms) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connection.\n\n</a>" "The round trip time is recalculated every time <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/gamefunctions_8cpp/#gamefunctions_8cpp_1aa17ef8ef4f36199ef68ab2859f9fbda4">notify</a> packet is received. Notify " "packets are used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> information the connection that the far end successfully received " "the sent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">packet.\n</a>" )
DefineEngineMethod(NetConnection , resolveGhostID , S32 , (S32 ghostID) , "@brief On the client, <a href="/coding/file/colladautils_8h/#colladautils_8h_1a24cd315eae41894b5bbf77c8c0b097d4">convert</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> ghost ID from this connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> real <a href="/coding/class/classsimobject/">SimObject</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n\n</a>" "Torque 's network ghosting system only exchanges ghost ID 's between the server and client. Use " "this method on the client <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> discover an object 's local <a href="/coding/class/classsimobject/">SimObject</a> ID when you only have <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> " "ghost <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n</a>" " @param ghostID The ghost ID of the object as sent by the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" " @returns The <a href="/coding/class/classsimobject/">SimObject</a> ID of the object)
DefineEngineMethod(NetConnection , resolveObjectFromGhostIndex , S32 , (S32 ghostID) , "@brief On the server, <a href="/coding/file/colladautils_8h/#colladautils_8h_1a24cd315eae41894b5bbf77c8c0b097d4">convert</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> ghost ID from this connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> real <a href="/coding/class/classsimobject/">SimObject</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n\n</a>" "Torque 's network ghosting system only exchanges ghost ID 's between the server and client. Use " "this method on the server <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> discover an object 's local <a href="/coding/class/classsimobject/">SimObject</a> ID when you only have <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> " "ghost <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID.\n</a>" " @param ghostID The ghost ID of the object as sent by the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" " @returns The <a href="/coding/class/classsimobject/">SimObject</a> ID of the object)
DefineEngineMethod(NetConnection , setSimulatedNetParams , void , (F32 packetLoss, S32 delay) , "@brief Simulate network issues on the connection <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">testing.\n\n</a>" "@param packetLoss The fraction of packets that will be lost. Ranges from 0.0 (no loss) <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 1.0 (complete loss)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param delay Delays packets being transmitted by simulating <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> particular ping. This is an absolute " " integer, measured in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ms.\n</a>" )
DefineEngineMethod(NetConnection , transmitPaths , void , () , "@brief Sent by the server during phase 2 of the mission download <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> update motion spline <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">paths.\n\n</a>" "The server transmits all spline motion paths that are within the mission (Path) separate from " "other objects. This is due <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the potentially large number of nodes within each path, which may " "saturate <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> packet sent <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the client. By managing this step separately, Torque has finer <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> " "over how packets are organised vs. doing it during the ghosting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">stage.\n\n</a>" "Internally <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classpathmanager/">PathManager</a> is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> track all paths defined within <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> mission on the server, and each " "one is transmitted using <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> PathManagerEvent. The client side collects these events and builds the " "given paths within its own PathManager. 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>" "When <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> mission is ended, all paths need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be cleared from their respective path managers." " @<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 mission paths(SimPath), 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</a>" " @see clearPaths()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Path\n</a>" )
HashNetAddress(const NetAddress * addr)
IMPLEMENT_CO_NETEVENT_V1(ConnectionMessageEvent )
IMPLEMENT_CONOBJECT(NetConnection )
IMPLEMENT_NONINSTANTIABLE_CLASS(NetEvent , "An event <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be sent over the network." )
IMPLEMENT_SCOPE(NetAPI , Net , "Networking functionality." )
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#include "platform/platform.h" 25#include "core/dnet.h" 26#include "console/simBase.h" 27#include "sim/netConnection.h" 28#include "core/stream/bitStream.h" 29#include "core/stream/fileStream.h" 30#ifndef TORQUE_TGB_ONLY 31#include "scene/pathManager.h" 32#endif 33#include "console/consoleTypes.h" 34#include "sim/netInterface.h" 35#include "console/engineAPI.h" 36#include <stdarg.h> 37 38 39IMPLEMENT_SCOPE( NetAPI, Net,, "Networking functionality." ); 40 41IMPLEMENT_NONINSTANTIABLE_CLASS( NetEvent, 42 "An event to be sent over the network." ) 43END_IMPLEMENT_CLASS; 44 45 46S32 gNetBitsSent = 0; 47extern S32 gNetBitsReceived; 48U32 gGhostUpdates = 0; 49 50enum NetConnectionConstants { 51 PingTimeout = 4500, ///< milliseconds 52 DefaultPingRetryCount = 15, 53}; 54 55SimObjectPtr<NetConnection> NetConnection::mServerConnection; 56SimObjectPtr<NetConnection> NetConnection::mLocalClientConnection; 57 58//---------------------------------------------------------------------- 59/// ConnectionMessageEvent 60/// 61/// This event is used inside by the connection and subclasses to message 62/// itself when sequencing events occur. Right now, the message event 63/// only uses 6 bits to transmit the message, so 64class ConnectionMessageEvent : public NetEvent 65{ 66 U32 sequence; 67 U32 message; 68 U32 ghostCount; 69public: 70 typedef NetEvent Parent; 71 ConnectionMessageEvent(U32 msg=0, U32 seq=0, U32 gc=0) 72 { message = msg; sequence = seq; ghostCount = gc;} 73 void pack(NetConnection *, BitStream *bstream) 74 { 75 bstream->write(sequence); 76 bstream->writeInt(message, 3); 77 bstream->writeInt(ghostCount, NetConnection::GhostIdBitSize + 1); 78 } 79 void write(NetConnection *, BitStream *bstream) 80 { 81 bstream->write(sequence); 82 bstream->writeInt(message, 3); 83 bstream->writeInt(ghostCount, NetConnection::GhostIdBitSize + 1); 84 } 85 void unpack(NetConnection *, BitStream *bstream) 86 { 87 bstream->read(&sequence); 88 message = bstream->readInt(3); 89 ghostCount = bstream->readInt(NetConnection::GhostIdBitSize + 1); 90 } 91 void process(NetConnection *ps) 92 { 93 ps->handleConnectionMessage(message, sequence, ghostCount); 94 } 95 DECLARE_CONOBJECT(ConnectionMessageEvent); 96}; 97 98IMPLEMENT_CO_NETEVENT_V1(ConnectionMessageEvent); 99 100ConsoleDocClass( ConnectionMessageEvent, 101 "@brief This event is used inside by the connection and subclasses to message itself when sequencing events occur.\n\n" 102 "Not intended for game development, for editors or internal use only.\n\n " 103 "@internal"); 104 105void NetConnection::sendConnectionMessage(U32 message, U32 sequence, U32 ghostCount) 106{ 107 postNetEvent(new ConnectionMessageEvent(message, sequence, ghostCount)); 108} 109 110//-------------------------------------------------------------------- 111IMPLEMENT_CONOBJECT(NetConnection); 112 113ConsoleDocClass( NetConnection, 114 "@brief Provides the basis for implementing a multiplayer game protocol.\n\n" 115 116 "NetConnection combines a low-level notify protocol implemented in ConnectionProtocol with a SimGroup, " 117 "and implements several distinct subsystems:\n\n" 118 119 "- <b>Event Manager</b> This is responsible for transmitting NetEvents over the wire. " 120 "It deals with ensuring that the various types of NetEvents are delivered appropriately, " 121 "and with notifying the event of its delivery status.\n\n" 122 "- <b>Move Manager</b> This is responsible for transferring a Move to the server 32 " 123 "times a second (on the client) and applying it to the control object (on the server).\n\n" 124 "- <b>Ghost Manager</b> This is responsible for doing scoping calculations (on the server " 125 "side) and transmitting most-recent ghost information to the client.\n\n" 126 "- <b>File Transfer</b> It is often the case that clients will lack important files when " 127 "connecting to a server which is running a mod or new map. This subsystem allows the " 128 "server to transfer such files to the client.\n\n" 129 "- <b>Networked String Table</b> String data can easily soak up network bandwidth, so for " 130 "efficiency, we implement a networked string table. We can then notify the connection " 131 "of strings we will reference often, such as player names, and transmit only a tag, " 132 "instead of the whole string.\n\n" 133 "- <b>Demo Recording</b> A demo in Torque is a log of the network traffic between client " 134 "and server; when a NetConnection records a demo, it simply logs this data to a file. When " 135 "it plays a demo back, it replays the logged data.\n\n" 136 "- <b>Connection Database</b> This is used to keep track of all the NetConnections; it can " 137 "be iterated over (for instance, to send an event to all active connections), or queried " 138 "by address.\n\n" 139 140 "The NetConnection is a SimGroup. On the client side, it contains all the objects which have been " 141 "ghosted to that client. On the server side, it is empty; it can be used (typically in script) to " 142 "hold objects related to the connection. For instance, you might place an observation camera in the " 143 "NetConnnection. In both cases, when the connection is destroyed, so are the contained objects.\n\n" 144 145 "The NetConnection also has the concept of local connections. These are used when the client and " 146 "server reside in the same process. A local connection is typically required to use the standard " 147 "Torque world building tools. A local connection is also required when building a single player " 148 "game.\n\n" 149 150 "@see @ref Networking, @ref ghosting_scoping, @ref netconnection_simgroup, @ref local_connections, GameConnection, AIConnection, and AIClient.\n\n" 151 152 "@ingroup Networking\n"); 153 154NetConnection* NetConnection::mConnectionList = NULL; 155NetConnection* NetConnection::mHashTable[NetConnection::HashTableSize] = { NULL, }; 156 157bool NetConnection::mFilesWereDownloaded = false; 158 159static inline U32 HashNetAddress(const NetAddress *addr) 160{ 161 return addr->getHash() % NetConnection::HashTableSize; 162} 163 164NetConnection *NetConnection::lookup(const NetAddress *addr) 165{ 166 U32 hashIndex = HashNetAddress(addr); 167 for(NetConnection *walk = mHashTable[hashIndex]; walk; walk = walk->mNextTableHash) 168 if(Net::compareAddresses(addr, walk->getNetAddress())) 169 return walk; 170 return NULL; 171} 172 173void NetConnection::netAddressTableInsert() 174{ 175 U32 hashIndex = HashNetAddress(&mNetAddress); 176 mNextTableHash = mHashTable[hashIndex]; 177 mHashTable[hashIndex] = this; 178} 179 180void NetConnection::netAddressTableRemove() 181{ 182 U32 hashIndex = HashNetAddress(&mNetAddress); 183 NetConnection **walk = &mHashTable[hashIndex]; 184 while(*walk) 185 { 186 if(*walk == this) 187 { 188 *walk = mNextTableHash; 189 mNextTableHash = NULL; 190 return; 191 } 192 walk = &((*walk)->mNextTableHash); 193 } 194} 195 196void NetConnection::setNetAddress(const NetAddress *addr) 197{ 198 mNetAddress = *addr; 199} 200 201const NetAddress *NetConnection::getNetAddress() 202{ 203 return &mNetAddress; 204} 205 206void NetConnection::setSequence(U32 sequence) 207{ 208 mConnectSequence = sequence; 209} 210 211U32 NetConnection::getSequence() 212{ 213 return mConnectSequence; 214} 215 216static U32 gPacketRateToServer = 32; 217static U32 gPacketUpdateDelayToServer = 32; 218static U32 gPacketRateToClient = 10; 219static U32 gPacketSize = 508; 220 221void NetConnection::consoleInit() 222{ 223 Con::addVariable("$pref::Net::PacketRateToServer", TypeS32, &gPacketRateToServer, 224 "@brief Sets how often packets are sent from the client to the server.\n\n" 225 226 "It is possible to control how often packets may be sent to the server. This may be " 227 "used to throttle the amount of bandwidth being used, but should be adjusted with " 228 "caution.\n\n" 229 230 "The actual formula used to calculate the delay between sending packets to the server is:\n" 231 232 "@code\n" 233 "Packet Update Delay To Server = 1024 / $pref::Net::PacketRateToServer" 234 "@endcode\n" 235 236 "with the result in ms. A minimum rate of 8 is enforced in the source code. The default " 237 "value is 32.\n\n" 238 239 "@note When using a local connection (@ref local_connections) be aware that this variable " 240 "is always forced to 128.\n\n" 241 242 "@ingroup Networking"); 243 244 Con::addVariable("$pref::Net::PacketRateToClient", TypeS32, &gPacketRateToClient, 245 "@brief Sets how often packets are sent from the server to a client.\n\n" 246 247 "It is possible to control how often packets may be sent to the clients. This may be " 248 "used to throttle the amount of bandwidth being used, but should be adjusted with " 249 "caution.\n\n" 250 251 "The actual formula used to calculate the delay between sending packets to a client is:\n" 252 253 "@code\n" 254 "Packet Update Delay To Client = 1024 / $pref::Net::PacketRateToClient" 255 "@endcode\n" 256 257 "with the result in ms. A minimum rate of 1 is enforced in the source code. The default " 258 "value is 10.\n\n" 259 260 "@note When using a local connection (@ref local_connections) be aware that this variable " 261 "is always forced to 128.\n\n" 262 263 "@ingroup Networking"); 264 265 Con::addVariable("$pref::Net::PacketSize", TypeS32, &gPacketSize, 266 "@brief Sets the maximum size in bytes an individual network packet may be.\n\n" 267 268 "It is possible to control how large each individual network packet may be. Increasing " 269 "its size from the default allows for more data to be sent on each network send. " 270 "However, this value should be changed with caution as too large a value will cause " 271 "packets to be split up by the networking platform or hardware, which is something " 272 "Torque cannot handle.\n\n" 273 274 "A minimum packet size of 100 bytes is enforced in the source code. There is no " 275 "enforced maximum. The default value is 200 bytes.\n\n" 276 277 "@note When using a local connection (@ref local_connections) be aware that this variable " 278 "is always forced to 1024 bytes.\n\n" 279 280 "@ingroup Networking"); 281 282 Con::addVariable("$Stats::netBitsSent", TypeS32, &gNetBitsSent, 283 "@brief The number of bytes sent during the last packet send operation.\n\n" 284 285 "@note Even though this variable has 'Bits' in it, the value is indeed reported in bytes. This name " 286 "is a legacy holdover and remains for compatibility reasons.\n" 287 288 "@ingroup Networking"); 289 290 Con::addVariable("$Stats::netBitsReceived", TypeS32, &gNetBitsReceived, 291 "@brief The number of bytes received during the last packet process operation.\n\n" 292 293 "@note Even though this variable has 'Bits' in it, the value is indeed reported in bytes. This name " 294 "is a legacy holdover and remains for compatibility reasons.\n" 295 296 "@ingroup Networking"); 297 298 Con::addVariable("$Stats::netGhostUpdates", TypeS32, &gGhostUpdates, 299 "@brief The total number of ghosts added, removed, and/or updated on the client " 300 "during the last packet process operation.\n\n" 301 302 "@ingroup Networking"); 303} 304 305void NetConnection::checkMaxRate() 306{ 307 // Enforce some minimum limits to the network settings. 308 gPacketRateToServer = getMax( gPacketRateToServer, (U32)8 ); 309 gPacketRateToClient = getMax( gPacketRateToClient, (U32)1 ); 310 gPacketSize = getMax( gPacketSize, (U32)100 ); 311 312 U32 packetRateToServer = gPacketRateToServer; 313 U32 packetRateToClient = gPacketRateToClient; 314 U32 packetSize = gPacketSize; 315 316 if (isLocalConnection()) 317 { 318 packetRateToServer = 128; 319 packetRateToClient = 128; 320 // These changes introduced in T3D 1.1 Preview reduce the packet headroom which leads 321 // to some spells and effects running out of room when dynamic variables are used 322 // to send launch-time parameters to clients. 323 packetSize = 512; 324 } 325 326 gPacketUpdateDelayToServer = 1024 / packetRateToServer; 327 U32 toClientUpdateDelay = 1024 / packetRateToClient; 328 329 if(mMaxRate.updateDelay != toClientUpdateDelay || mMaxRate.packetSize != packetSize) 330 { 331 mMaxRate.updateDelay = toClientUpdateDelay; 332 mMaxRate.packetSize = packetSize; 333 mMaxRate.changed = true; 334 } 335} 336 337void NetConnection::setSendingEvents(bool sending) 338{ 339 AssertFatal(!mEstablished, "Error, cannot change event behavior after a connection has been established."); 340 mSendingEvents = sending; 341} 342 343void NetConnection::setTranslatesStrings(bool xl) 344{ 345 AssertFatal(!mEstablished, "Error, cannot change event behavior after a connection has been established."); 346 mTranslateStrings = xl; 347 if(mTranslateStrings) 348 mStringTable = new ConnectionStringTable(this); 349} 350 351void NetConnection::setNetClassGroup(U32 grp) 352{ 353 AssertFatal(!mEstablished, "Error, cannot change net class group after a connection has been established."); 354 mNetClassGroup = grp; 355} 356 357NetConnection::NetConnection() 358 : mNetAddress() 359{ 360 mTranslateStrings = false; 361 mConnectSequence = 0; 362 363 mStringTable = NULL; 364 mSendingEvents = true; 365 mNetClassGroup = NetClassGroupGame; 366 AssertFatal(mNetClassGroup >= NetClassGroupGame && mNetClassGroup < NetClassGroupsCount, 367 "Invalid net event class type."); 368 369 mSimulatedPing = 0; 370 mSimulatedPacketLoss = 0; 371#ifdef TORQUE_DEBUG_NET 372 mLogging = false; 373#endif 374 mEstablished = false; 375 mLastUpdateTime = 0; 376 mRoundTripTime = 0; 377 mPacketLoss = 0; 378 mNextTableHash = NULL; 379 mSendDelayCredit = 0; 380 mConnectionState = NotConnected; 381 382 mCurrentDownloadingFile = NULL; 383 mCurrentFileBuffer = NULL; 384 385 mNextConnection = NULL; 386 mPrevConnection = NULL; 387 388 mNotifyQueueHead = NULL; 389 mNotifyQueueTail = NULL; 390 391 mCurRate.updateDelay = 102; 392 mCurRate.packetSize = 200; 393 mCurRate.changed = false; 394 mMaxRate.updateDelay = 102; 395 mMaxRate.packetSize = 200; 396 mMaxRate.changed = false; 397 checkMaxRate(); 398 399 // event management data: 400 401 mNotifyEventList = NULL; 402 mSendEventQueueHead = NULL; 403 mSendEventQueueTail = NULL; 404 mUnorderedSendEventQueueHead = NULL; 405 mUnorderedSendEventQueueTail = NULL; 406 mWaitSeqEvents = NULL; 407 408 mNextSendEventSeq = FirstValidSendEventSeq; 409 mNextRecvEventSeq = FirstValidSendEventSeq; 410 mLastAckedEventSeq = -1; 411 412 // ghost management data: 413 414 mScopeObject = NULL; 415 mGhostingSequence = 0; 416 mGhosting = false; 417 mScoping = false; 418 mGhostArray = NULL; 419 mGhostRefs = NULL; 420 mGhostLookupTable = NULL; 421 mLocalGhosts = NULL; 422 423 mGhostsActive = 0; 424 425 mMissionPathsSent = false; 426 mDemoWriteStream = NULL; 427 mDemoReadStream = NULL; 428 429 mPingSendCount = 0; 430 mPingRetryCount = DefaultPingRetryCount; 431 mLastPingSendTime = Platform::getVirtualMilliseconds(); 432 433 mCurrentDownloadingFile = NULL; 434 mCurrentFileBuffer = NULL; 435 mCurrentFileBufferSize = 0; 436 mCurrentFileBufferOffset = 0; 437 mNumDownloadedFiles = 0; 438 439 // Disable starting a new journal recording or playback from here on 440 Journal::Disable(); 441 442 // Ensure NetAddress is cleared 443 dMemset(&mNetAddress, '\0', sizeof(NetAddress)); 444} 445 446NetConnection::~NetConnection() 447{ 448 AssertFatal(mNotifyQueueHead == NULL, "Uncleared notifies remain."); 449 netAddressTableRemove(); 450 451 dFree(mCurrentFileBuffer); 452 if(mCurrentDownloadingFile) 453 delete mCurrentDownloadingFile; 454 455 delete[] mLocalGhosts; 456 delete[] mGhostLookupTable; 457 delete[] mGhostRefs; 458 delete[] mGhostArray; 459 delete mStringTable; 460 if(mDemoWriteStream) 461 delete mDemoWriteStream; 462 if(mDemoReadStream) 463 delete mDemoReadStream; 464} 465 466NetConnection::PacketNotify::PacketNotify() 467{ 468 rateChanged = false; 469 maxRateChanged = false; 470 sendTime = 0; 471 eventList = 0; 472 ghostList = 0; 473 subList = NULL; 474 nextPacket = NULL; 475} 476 477bool NetConnection::checkTimeout(U32 time) 478{ 479 if(!isNetworkConnection()) 480 return false; 481 482 if(time > mLastPingSendTime + PingTimeout) 483 { 484 if(mPingSendCount >= mPingRetryCount) 485 return true; 486 mLastPingSendTime = time; 487 mPingSendCount++; 488 sendPingPacket(); 489 } 490 return false; 491} 492 493void NetConnection::keepAlive() 494{ 495 mLastPingSendTime = Platform::getVirtualMilliseconds(); 496 mPingSendCount = 0; 497} 498 499void NetConnection::handleConnectionEstablished() 500{ 501} 502 503//-------------------------------------------------------------------------- 504#ifndef TORQUE_TGB_ONLY 505DefineEngineMethod( NetConnection, transmitPaths, void, (),, 506 "@brief Sent by the server during phase 2 of the mission download to update motion spline paths.\n\n" 507 508 "The server transmits all spline motion paths that are within the mission (Path) separate from " 509 "other objects. This is due to the potentially large number of nodes within each path, which may " 510 "saturate a packet sent to the client. By managing this step separately, Torque has finer control " 511 "over how packets are organised vs. doing it during the ghosting stage.\n\n" 512 513 "Internally a PathManager is used to track all paths defined within a mission on the server, and each " 514 "one is transmitted using a PathManagerEvent. The client side collects these events and builds the " 515 "given paths within its own PathManager. This is typically done during the standard mission start " 516 "phase 2 when following Torque's example mission startup sequence.\n\n" 517 518 "When a mission is ended, all paths need to be cleared from their respective path managers." 519 520 "@tsexample\n" 521 "function serverCmdMissionStartPhase2Ack(%client, %seq, %playerDB)\n" 522 "{\n" 523 " // Make sure to ignore calls from a previous mission load\n" 524 " if (%seq != $missionSequence || !$MissionRunning)\n" 525 " return;\n" 526 " if (%client.currentPhase != 1.5)\n" 527 " return;\n" 528 " %client.currentPhase = 2;\n" 529 "\n" 530 " // Set the player datablock choice\n" 531 " %client.playerDB = %playerDB;\n" 532 "\n" 533 " // Update mission paths (SimPath), this needs to get there before the objects.\n" 534 " %client.transmitPaths();\n" 535 "\n" 536 " // Start ghosting objects to the client\n" 537 " %client.activateGhosting();\n" 538 "}\n" 539 "@endtsexample\n" 540 541 "@see clearPaths()\n" 542 "@see Path\n") 543{ 544 gServerPathManager->transmitPaths(object); 545 object->setMissionPathsSent(true); 546} 547 548DefineEngineMethod( NetConnection, clearPaths, void, (),, 549 "@brief On the server, resets the connection to indicate that motion spline paths have not been transmitted.\n\n" 550 551 "Typically when a mission has ended on the server, all connected clients are informed of this change " 552 "and their connections are reset back to a starting state. This method resets a connection on the " 553 "server to indicate that motion spline paths have not been transmitted.\n\n" 554 555 "@tsexample\n" 556 " // Inform the clients\n" 557 " for (%clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++)\n" 558 " {\n" 559 " // clear ghosts and paths from all clients\n" 560 " %cl = ClientGroup.getObject(%clientIndex);\n" 561 " %cl.endMission();\n" 562 " %cl.resetGhosting();\n" 563 " %cl.clearPaths();\n" 564 " }\n" 565 "@endtsexample\n" 566 567 "@see transmitPaths()\n" 568 "@see Path\n") 569{ 570 object->setMissionPathsSent(false); 571} 572#endif 573 574DefineEngineMethod( NetConnection, getAddress, const char *, (),, 575 "@brief Returns the far end network address for the connection.\n\n" 576 577 "The address will be in one of the following forms:\n" 578 "- <b>IP:Broadcast:<port></b> for broadcast type addresses\n" 579 "- <b>IP:<address>:<port></b> for IP addresses\n" 580 "- <b>local</b> when connected locally (server and client running in same process\n") 581{ 582 if(object->isLocalConnection()) 583 return "local"; 584 char *buffer = Con::getReturnBuffer(256); 585 Net::addressToString(object->getNetAddress(), buffer); 586 return buffer; 587} 588 589DefineEngineMethod( NetConnection, setSimulatedNetParams, void, (F32 packetLoss, S32 delay),, 590 "@brief Simulate network issues on the connection for testing.\n\n" 591 592 "@param packetLoss The fraction of packets that will be lost. Ranges from 0.0 (no loss) to 1.0 (complete loss)\n" 593 "@param delay Delays packets being transmitted by simulating a particular ping. This is an absolute " 594 "integer, measured in ms.\n") 595{ 596 object->setSimulatedNetParams(packetLoss, delay); 597} 598 599DefineEngineMethod( NetConnection, getPing, S32, (),, 600 "@brief Returns the average round trip time (in ms) for the connection.\n\n" 601 602 "The round trip time is recalculated every time a notify packet is received. Notify " 603 "packets are used to information the connection that the far end successfully received " 604 "the sent packet.\n") 605{ 606 return( S32( object->getRoundTripTime() ) ); 607} 608 609DefineEngineMethod( NetConnection, getPacketLoss, S32, (),, 610 "@brief Returns the percentage of packets lost per tick.\n\n" 611 612 "@note This method is not yet hooked up.\n") 613{ 614 return( S32( 100 * object->getPacketLoss() ) ); 615} 616 617DefineEngineMethod( NetConnection, checkMaxRate, void, (),, 618 "@brief Ensures that all configured packet rates and sizes meet minimum requirements.\n\n" 619 620 "This method is normally only called when a NetConnection class is first constructed. It need " 621 "only be manually called if the global variables that set the packet rate or size have changed.\n\n" 622 623 "@note If @$pref::Net::PacketRateToServer, @$pref::Net::PacketRateToClient or @$pref::Net::PacketSize " 624 "have been changed since a NetConnection has been created, this method must be called on " 625 "all connections for them to follow the new rates or size.\n") 626{ 627 object->checkMaxRate(); 628} 629 630#ifdef TORQUE_DEBUG_NET 631 632DefineEngineMethod( NetConnection, setLogging, void, (bool state),, 633 "@brief Sets if debug statements should be written to the console log.\n\n" 634 "@note Only valid if the executable has been compiled with TORQUE_DEBUG_NET.\n") 635{ 636 object->setLogging(state); 637} 638 639#endif 640 641//-------------------------------------------------------------------- 642 643void NetConnection::setEstablished() 644{ 645 AssertFatal(!mEstablished, "NetConnection::setEstablished - Error, this NetConnection has already been established."); 646 647 mEstablished = true; 648 mNextConnection = mConnectionList; 649 if(mConnectionList) 650 mConnectionList->mPrevConnection = this; 651 mConnectionList = this; 652 653 if(isNetworkConnection()) 654 netAddressTableInsert(); 655 656} 657 658void NetConnection::onRemove() 659{ 660 // delete any ghosts that may exist for this connection, but aren't added 661 while(mGhostAlwaysSaveList.size()) 662 { 663 delete mGhostAlwaysSaveList[0].ghost; 664 mGhostAlwaysSaveList.pop_front(); 665 } 666 if(mNextConnection) 667 mNextConnection->mPrevConnection = mPrevConnection; 668 if(mPrevConnection) 669 mPrevConnection->mNextConnection = mNextConnection; 670 if(mConnectionList == this) 671 mConnectionList = mNextConnection; 672 while(mNotifyQueueHead) 673 handleNotify(false); 674 675 ghostOnRemove(); 676 eventOnRemove(); 677 678 Parent::onRemove(); 679} 680 681String NetConnection::mErrorBuffer; 682 683void NetConnection::setLastError(const char *fmt, ...) 684{ 685 va_list argptr; 686 va_start(argptr, fmt); 687 mErrorBuffer = String::ToString(fmt, argptr); 688 va_end(argptr); 689 690#ifdef TORQUE_DEBUG_NET 691 // setLastErrors assert in net_debug builds 692 AssertFatal(false, mErrorBuffer.c_str()); 693#endif 694 695} 696 697//-------------------------------------------------------------------- 698 699void NetConnection::handleNotify(bool recvd) 700{ 701// Con::printf("NET %d: NOTIFY - %d %s", getId(), gPacketId, recvd ? "RECVD" : "DROPPED"); 702 703 PacketNotify *note = mNotifyQueueHead; 704 AssertFatal(note != NULL, "Error: got a notify with a null notify head."); 705 mNotifyQueueHead = mNotifyQueueHead->nextPacket; 706 707 if(note->rateChanged && !recvd) 708 mCurRate.changed = true; 709 if(note->maxRateChanged && !recvd) 710 mMaxRate.changed = true; 711 712 if(recvd) 713 { 714 // Running average of roundTrip time 715 U32 curTime = Platform::getVirtualMilliseconds(); 716 mRoundTripTime = (mRoundTripTime + (curTime - note->sendTime)) * 0.5; 717 packetReceived(note); 718 } 719 else 720 packetDropped(note); 721 722 delete note; 723} 724 725void NetConnection::processRawPacket(BitStream *bstream) 726{ 727 if(mDemoWriteStream) 728 recordBlock(BlockTypePacket, bstream->getReadByteSize(), bstream->getBuffer()); 729 730 ConnectionProtocol::processRawPacket(bstream); 731} 732 733void NetConnection::handlePacket(BitStream *bstream) 734{ 735// Con::printf("NET %d: RECV - %d", getId(), mLastSeqRecvd); 736 // clear out any errors 737 738 mErrorBuffer = String(); 739 740 if(bstream->readFlag()) 741 { 742 mCurRate.updateDelay = bstream->readInt(12); 743 mCurRate.packetSize = bstream->readInt(12); 744 } 745 746 if(bstream->readFlag()) 747 { 748 U32 omaxDelay = bstream->readInt(12); 749 S32 omaxSize = bstream->readInt(12); 750 if(omaxDelay < mMaxRate.updateDelay) 751 omaxDelay = mMaxRate.updateDelay; 752 if(omaxSize > mMaxRate.packetSize) 753 omaxSize = mMaxRate.packetSize; 754 if(omaxDelay != mCurRate.updateDelay || omaxSize != mCurRate.packetSize) 755 { 756 mCurRate.updateDelay = omaxDelay; 757 mCurRate.packetSize = omaxSize; 758 mCurRate.changed = true; 759 } 760 } 761 readPacket(bstream); 762 763 if(mErrorBuffer.isNotEmpty()) 764 connectionError(mErrorBuffer); 765} 766 767void NetConnection::connectionError(const char *errorString) 768{ 769 TORQUE_UNUSED(errorString); 770} 771 772//-------------------------------------------------------------------- 773 774NetConnection::PacketNotify *NetConnection::allocNotify() 775{ 776 return new PacketNotify; 777} 778 779/// Used when simulating lag. 780/// 781/// We post this SimEvent when we want to send a packet; it delays for a bit, then 782/// sends the actual packet. 783class NetDelayEvent : public SimEvent 784{ 785 U8 buffer[Net::MaxPacketDataSize]; 786 BitStream stream; 787public: 788 NetDelayEvent(BitStream *inStream) : stream(NULL, 0) 789 { 790 dMemcpy(buffer, inStream->getBuffer(), inStream->getPosition()); 791 stream.setBuffer(buffer, inStream->getPosition()); 792 stream.setPosition(inStream->getPosition()); 793 } 794 void process(SimObject *object) 795 { 796 ((NetConnection *) object)->sendPacket(&stream); 797 } 798}; 799 800void NetConnection::checkPacketSend(bool force) 801{ 802 U32 curTime = Platform::getVirtualMilliseconds(); 803 U32 delay = isConnectionToServer() ? gPacketUpdateDelayToServer : mCurRate.updateDelay; 804 805 if(!force) 806 { 807 if(curTime < mLastUpdateTime + delay - mSendDelayCredit) 808 return; 809 810 mSendDelayCredit = curTime - (mLastUpdateTime + delay - mSendDelayCredit); 811 if(mSendDelayCredit > 1000) 812 mSendDelayCredit = 1000; 813 814 if(mDemoWriteStream) 815 recordBlock(BlockTypeSendPacket, 0, 0); 816 } 817 if(windowFull()) 818 return; 819 820 BitStream *stream = BitStream::getPacketStream(mCurRate.packetSize); 821 buildSendPacketHeader(stream); 822 823 mLastUpdateTime = curTime; 824 825 PacketNotify *note = allocNotify(); 826 if(!mNotifyQueueHead) 827 mNotifyQueueHead = note; 828 else 829 mNotifyQueueTail->nextPacket = note; 830 mNotifyQueueTail = note; 831 note->nextPacket = NULL; 832 note->sendTime = curTime; 833 834 note->rateChanged = mCurRate.changed; 835 note->maxRateChanged = mMaxRate.changed; 836 837 if(stream->writeFlag(mCurRate.changed)) 838 { 839 stream->writeInt(mCurRate.updateDelay, 12); 840 stream->writeInt(mCurRate.packetSize, 12); 841 mCurRate.changed = false; 842 } 843 if(stream->writeFlag(mMaxRate.changed)) 844 { 845 stream->writeInt(mMaxRate.updateDelay, 12); 846 stream->writeInt(mMaxRate.packetSize, 12); 847 mMaxRate.changed = false; 848 } 849#ifdef TORQUE_DEBUG_NET 850 U32 start = stream->getCurPos(); 851#endif 852 853 DEBUG_LOG(("PKLOG %d START", getId()) ); 854 writePacket(stream, note); 855 DEBUG_LOG(("PKLOG %d END - %d", getId(), stream->getCurPos() - start) ); 856 if(mSimulatedPacketLoss && Platform::getRandom() < mSimulatedPacketLoss) 857 { 858 //Con::printf("NET %d: SENDDROP - %d", getId(), mLastSendSeq); 859 return; 860 } 861 if(mSimulatedPing) 862 { 863 Sim::postEvent(getId(), new NetDelayEvent(stream), Sim::getCurrentTime() + mSimulatedPing); 864 return; 865 } 866 sendPacket(stream); 867} 868 869Net::Error NetConnection::sendPacket(BitStream *stream) 870{ 871 //Con::printf("NET %d: SEND - %d", getId(), mLastSendSeq); 872 // do nothing on send if this is a demo replay. 873 if(mDemoReadStream) 874 return Net::NoError; 875 876 gNetBitsSent = stream->getPosition(); 877 878 if(isLocalConnection()) 879 { 880 // short circuit connection to the other side. 881 // handle the packet, then force a notify. 882 stream->setBuffer(stream->getBuffer(), stream->getPosition(), stream->getPosition()); 883 mRemoteConnection->processRawPacket(stream); 884 885 return Net::NoError; 886 } 887 else 888 { 889 return Net::sendto(getNetAddress(), stream->getBuffer(), stream->getPosition()); 890 } 891} 892 893//-------------------------------------------------------------------- 894//-------------------------------------------------------------------- 895 896// these are the virtual function defs for Connection - 897// if your subclass has additional data to read / write / notify, add it in these functions. 898 899void NetConnection::readPacket(BitStream *bstream) 900{ 901 eventReadPacket(bstream); 902 ghostReadPacket(bstream); 903} 904 905void NetConnection::writePacket(BitStream *bstream, PacketNotify *note) 906{ 907 eventWritePacket(bstream, note); 908 ghostWritePacket(bstream, note); 909} 910 911void NetConnection::packetReceived(PacketNotify *note) 912{ 913 eventPacketReceived(note); 914 ghostPacketReceived(note); 915} 916 917void NetConnection::packetDropped(PacketNotify *note) 918{ 919 eventPacketDropped(note); 920 ghostPacketDropped(note); 921} 922 923//-------------------------------------------------------------------- 924//-------------------------------------------------------------------- 925 926void NetConnection::writeDemoStartBlock(ResizeBitStream* stream) 927{ 928 ConnectionProtocol::writeDemoStartBlock(stream); 929 930 stream->write(mRoundTripTime); 931 stream->write(mPacketLoss); 932#ifndef TORQUE_TGB_ONLY 933 // Write all the current paths to the stream... 934 gClientPathManager->dumpState(stream); 935#endif 936 stream->validate(); 937 mStringTable->writeDemoStartBlock(stream); 938 939 U32 start = 0; 940 PacketNotify *note = mNotifyQueueHead; 941 while(note) 942 { 943 start++; 944 note = note->nextPacket; 945 } 946 stream->write(start); 947 948 eventWriteStartBlock(stream); 949 ghostWriteStartBlock(stream); 950} 951 952bool NetConnection::readDemoStartBlock(BitStream* stream) 953{ 954 ConnectionProtocol::readDemoStartBlock(stream); 955 956 stream->read(&mRoundTripTime); 957 stream->read(&mPacketLoss); 958 959#ifndef TORQUE_TGB_ONLY 960 // Read 961 gClientPathManager->readState(stream); 962#endif 963 964 mStringTable->readDemoStartBlock(stream); 965 U32 pos; 966 stream->read(&pos); // notify count 967 for(U32 i = 0; i < pos; i++) 968 { 969 PacketNotify *note = allocNotify(); 970 note->nextPacket = NULL; 971 if(!mNotifyQueueHead) 972 mNotifyQueueHead = note; 973 else 974 mNotifyQueueTail->nextPacket = note; 975 mNotifyQueueTail = note; 976 } 977 eventReadStartBlock(stream); 978 ghostReadStartBlock(stream); 979 return true; 980} 981 982bool NetConnection::startDemoRecord(const char *fileName) 983{ 984 FileStream *fs = new FileStream; 985 986 if((fs = FileStream::createAndOpen( fileName, Torque::FS::File::Write )) == NULL) 987 return false; 988 989 mDemoWriteStream = fs; 990 mDemoWriteStream->write(mProtocolVersion); 991 ResizeBitStream bs; 992 993 // then write out the start block 994 writeDemoStartBlock(&bs); 995 U32 size = bs.getPosition() + 1; 996 mDemoWriteStream->write(size); 997 mDemoWriteStream->write(size, bs.getBuffer()); 998 return true; 999} 1000 1001bool NetConnection::replayDemoRecord(const char *fileName) 1002{ 1003 Stream *fs; 1004 if((fs = FileStream::createAndOpen( fileName, Torque::FS::File::Read )) == NULL) 1005 return false; 1006 1007 mDemoReadStream = fs; 1008 mDemoReadStream->read(&mProtocolVersion); 1009 U32 size; 1010 mDemoReadStream->read(&size); 1011 U8 *block = new U8[size]; 1012 mDemoReadStream->read(size, block); 1013 BitStream bs(block, size); 1014 1015 bool res = readDemoStartBlock(&bs); 1016 delete[] block; 1017 if(!res) 1018 return false; 1019 1020 // prep for first block read 1021 // type/size stored in U16: [type:4][size:12] 1022 U16 typeSize; 1023 mDemoReadStream->read(&typeSize); 1024 1025 mDemoNextBlockType = typeSize >> 12; 1026 mDemoNextBlockSize = typeSize & 0xFFF; 1027 1028 if(mDemoReadStream->getStatus() != Stream::Ok) 1029 return false; 1030 return true; 1031} 1032 1033void NetConnection::stopRecording() 1034{ 1035 if(mDemoWriteStream) 1036 { 1037 delete mDemoWriteStream; 1038 mDemoWriteStream = NULL; 1039 } 1040} 1041 1042void NetConnection::recordBlock(U32 type, U32 size, void *data) 1043{ 1044 AssertFatal(type < MaxNumBlockTypes, "NetConnection::recordBlock: invalid type"); 1045 AssertFatal(size < MaxBlockSize, "NetConnection::recordBlock: invalid size"); 1046 if((type >= MaxNumBlockTypes) || (size >= MaxBlockSize)) 1047 return; 1048 1049 if(mDemoWriteStream) 1050 { 1051 // store type/size in U16: [type:4][size:12] 1052 U16 typeSize = (type << 12) | size; 1053 mDemoWriteStream->write(typeSize); 1054 if(size) 1055 mDemoWriteStream->write(size, data); 1056 } 1057} 1058 1059void NetConnection::handleRecordedBlock(U32 type, U32 size, void *data) 1060{ 1061 switch(type) 1062 { 1063 case BlockTypePacket: { 1064 BitStream bs(data, size); 1065 processRawPacket(&bs); 1066 break; 1067 } 1068 case BlockTypeSendPacket: 1069 checkPacketSend(true); 1070 break; 1071 } 1072} 1073 1074void NetConnection::demoPlaybackComplete() 1075{ 1076} 1077 1078void NetConnection::stopDemoPlayback() 1079{ 1080 demoPlaybackComplete(); 1081 deleteObject(); 1082} 1083 1084bool NetConnection::processNextBlock() 1085{ 1086 U8 buffer[Net::MaxPacketDataSize]; 1087 1088 // read in and handle 1089 if(mDemoReadStream->read(mDemoNextBlockSize, buffer)) 1090 handleRecordedBlock(mDemoNextBlockType, mDemoNextBlockSize, buffer); 1091 1092 U16 typeSize; 1093 mDemoReadStream->read(&typeSize); 1094 1095 mDemoNextBlockType = typeSize >> 12; 1096 mDemoNextBlockSize = typeSize & 0xFFF; 1097 1098 if(mDemoReadStream->getStatus() != Stream::Ok) 1099 { 1100 stopDemoPlayback(); 1101 return false; 1102 } 1103 return true; 1104} 1105 1106//-------------------------------------------------------------------- 1107//-------------------------------------------------------------------- 1108 1109// some handy string functions for compressing strings over a connection: 1110enum NetStringConstants 1111{ 1112 NullString = 0, 1113 CString, 1114 TagString, 1115 Integer 1116}; 1117 1118void NetConnection::validateSendString(const char *str) 1119{ 1120 if(U8(*str) == StringTagPrefixByte) 1121 { 1122 NetStringHandle strHandle(dAtoi(str + 1)); 1123 checkString(strHandle); 1124 } 1125} 1126 1127void NetConnection::packString(BitStream *stream, const char *str) 1128{ 1129 if(!*str) 1130 { 1131 stream->writeInt(NullString, 2); 1132 return; 1133 } 1134 if(U8(str[0]) == StringTagPrefixByte) 1135 { 1136 stream->writeInt(TagString, 2); 1137 stream->writeInt(dAtoi(str + 1), ConnectionStringTable::EntryBitSize); 1138 return; 1139 } 1140 if(str[0] == '-' || (str[0] >= '0' && str[0] <= '9')) 1141 { 1142 char buf[16]; 1143 S32 num = dAtoi(str); 1144 dSprintf(buf, sizeof(buf), "%d", num); 1145 if(!String::compare(buf, str)) 1146 { 1147 stream->writeInt(Integer, 2); 1148 if(stream->writeFlag(num < 0)) 1149 num = -num; 1150 if(stream->writeFlag(num < 128)) 1151 { 1152 stream->writeInt(num, 7); 1153 return; 1154 } 1155 if(stream->writeFlag(num < 32768)) 1156 { 1157 stream->writeInt(num, 15); 1158 return; 1159 } 1160 else 1161 { 1162 stream->writeInt(num, 31); 1163 return; 1164 } 1165 } 1166 } 1167 stream->writeInt(CString, 2); 1168 stream->writeString(str); 1169} 1170 1171void NetConnection::unpackString(BitStream *stream, char readBuffer[1024]) 1172{ 1173 U32 code = stream->readInt(2); 1174 switch(code) 1175 { 1176 case NullString: 1177 readBuffer[0] = 0; 1178 return; 1179 case CString: 1180 { 1181 stream->readString(readBuffer); 1182 return; 1183 } 1184 case TagString: 1185 U32 tag; 1186 tag = stream->readInt(ConnectionStringTable::EntryBitSize); 1187 readBuffer[0] = StringTagPrefixByte; 1188 dSprintf(readBuffer+1, 1023, "%d", tag); 1189 return; 1190 case Integer: 1191 bool neg; 1192 neg = stream->readFlag(); 1193 S32 num; 1194 if(stream->readFlag()) 1195 num = stream->readInt(7); 1196 else if(stream->readFlag()) 1197 num = stream->readInt(15); 1198 else 1199 num = stream->readInt(31); 1200 if(neg) 1201 num = -num; 1202 dSprintf(readBuffer, 1024, "%d", num); 1203 } 1204} 1205 1206void NetConnection::packNetStringHandleU(BitStream *stream, NetStringHandle &h) 1207{ 1208 if(stream->writeFlag(h.isValidString() )) 1209 { 1210 bool isReceived; 1211 U32 netIndex = checkString(h, &isReceived); 1212 if(stream->writeFlag(isReceived)) 1213 stream->writeInt(netIndex, ConnectionStringTable::EntryBitSize); 1214 else 1215 stream->writeString(h.getString()); 1216 } 1217} 1218 1219NetStringHandle NetConnection::unpackNetStringHandleU(BitStream *stream) 1220{ 1221 NetStringHandle ret; 1222 if(stream->readFlag()) 1223 { 1224 if(stream->readFlag()) 1225 ret = mStringTable->lookupString(stream->readInt(ConnectionStringTable::EntryBitSize)); 1226 else 1227 { 1228 char buf[256]; 1229 stream->readString(buf); 1230 ret = NetStringHandle(buf); 1231 } 1232 } 1233 return ret; 1234} 1235 1236//---------------------------------------------------------------------------- 1237 1238//---------------------------------------------------------------------------- 1239//---------------------------------------------------------------------------- 1240 1241void NetConnection::setAddressDigest(U32 digest[4]) 1242{ 1243 mAddressDigest[0] = digest[0]; 1244 mAddressDigest[1] = digest[1]; 1245 mAddressDigest[2] = digest[2]; 1246 mAddressDigest[3] = digest[3]; 1247} 1248 1249void NetConnection::getAddressDigest(U32 digest[4]) 1250{ 1251 digest[0] = mAddressDigest[0]; 1252 digest[1] = mAddressDigest[1]; 1253 digest[2] = mAddressDigest[2]; 1254 digest[3] = mAddressDigest[3]; 1255} 1256 1257bool NetConnection::canRemoteCreate() 1258{ 1259 return false; 1260} 1261 1262void NetConnection::onTimedOut() 1263{ 1264 1265} 1266 1267void NetConnection::connect(const NetAddress *address) 1268{ 1269 mNetAddress = *address; 1270 GNet->startConnection(this); 1271} 1272 1273void NetConnection::onConnectTimedOut() 1274{ 1275 1276} 1277 1278void NetConnection::sendDisconnectPacket(const char *reason) 1279{ 1280 GNet->sendDisconnectPacket(this, reason); 1281} 1282 1283void NetConnection::onDisconnect(const char *reason) 1284{ 1285 TORQUE_UNUSED(reason); 1286} 1287 1288void NetConnection::onConnectionRejected(const char *reason) 1289{ 1290} 1291 1292void NetConnection::onConnectionEstablished(bool isInitiator) 1293{ 1294 1295} 1296 1297void NetConnection::handleStartupError(const char *errorString) 1298{ 1299 1300} 1301 1302void NetConnection::writeConnectRequest(BitStream *stream) 1303{ 1304 stream->write(mNetClassGroup); 1305 stream->write(U32(AbstractClassRep::getClassCRC(mNetClassGroup))); 1306} 1307 1308bool NetConnection::readConnectRequest(BitStream *stream, const char **errorString) 1309{ 1310 U32 classGroup, classCRC; 1311 stream->read(&classGroup); 1312 stream->read(&classCRC); 1313 1314 if(classGroup == mNetClassGroup && classCRC == AbstractClassRep::getClassCRC(mNetClassGroup)) 1315 return true; 1316 1317 *errorString = "CHR_INVALID"; 1318 return false; 1319} 1320 1321void NetConnection::writeConnectAccept(BitStream *stream) 1322{ 1323 TORQUE_UNUSED(stream); 1324} 1325 1326bool NetConnection::readConnectAccept(BitStream *stream, const char **errorString) 1327{ 1328 TORQUE_UNUSED(stream); 1329 TORQUE_UNUSED(errorString); 1330 return true; 1331} 1332 1333DefineEngineMethod( NetConnection, resolveGhostID, S32, (S32 ghostID),, 1334 "@brief On the client, convert a ghost ID from this connection to a real SimObject ID.\n\n" 1335 1336 "Torque's network ghosting system only exchanges ghost ID's between the server and client. Use " 1337 "this method on the client to discover an object's local SimObject ID when you only have a " 1338 "ghost ID.\n" 1339 1340 "@param ghostID The ghost ID of the object as sent by the server.\n" 1341 "@returns The SimObject ID of the object, or 0 if it could not be resolved.\n\n" 1342 1343 "@tsexample\n" 1344 "%object = ServerConnection.resolveGhostID( %ghostId );\n" 1345 "@endtsexample\n\n" 1346 1347 "@see @ref ghosting_scoping for a description of the ghosting system.\n\n") 1348{ 1349 // Safety check 1350 if(ghostID < 0 || ghostID > NetConnection::MaxGhostCount) return 0; 1351 1352 NetObject *foo = object->resolveGhost(ghostID); 1353 1354 if(foo) 1355 return foo->getId(); 1356 else 1357 return 0; 1358} 1359 1360DefineEngineMethod( NetConnection, resolveObjectFromGhostIndex, S32, (S32 ghostID),, 1361 "@brief On the server, convert a ghost ID from this connection to a real SimObject ID.\n\n" 1362 1363 "Torque's network ghosting system only exchanges ghost ID's between the server and client. Use " 1364 "this method on the server to discover an object's local SimObject ID when you only have a " 1365 "ghost ID.\n" 1366 1367 "@param ghostID The ghost ID of the object as sent by the server.\n" 1368 "@returns The SimObject ID of the object, or 0 if it could not be resolved.\n\n" 1369 1370 "@tsexample\n" 1371 "%object = %client.resolveObjectFromGhostIndex( %ghostId );\n" 1372 "@endtsexample\n\n" 1373 1374 "@see @ref ghosting_scoping for a description of the ghosting system.\n\n") 1375{ 1376 // Safety check 1377 if(ghostID < 0 || ghostID > NetConnection::MaxGhostCount) return 0; 1378 1379 NetObject *foo = object->resolveObjectFromGhostIndex(ghostID); 1380 1381 if(foo) 1382 return foo->getId(); 1383 else 1384 return 0; 1385} 1386 1387DefineEngineMethod( NetConnection, getGhostID, S32, (S32 realID),, 1388 "@brief On server or client, convert a real id to the ghost id for this connection.\n\n" 1389 1390 "Torque's network ghosting system only exchanges ghost ID's between the server and client. Use " 1391 "this method on the server or client to discover an object's ghost ID based on its real SimObject ID.\n" 1392 1393 "@param realID The real SimObject ID of the object.\n" 1394 "@returns The ghost ID of the object for this connection, or -1 if it could not be resolved.\n\n" 1395 1396 "@see @ref ghosting_scoping for a description of the ghosting system.\n\n") 1397{ 1398 NetObject * foo; 1399 1400 if(Sim::findObject(realID, foo)) 1401 { 1402 return object->getGhostIndex(foo); 1403 } 1404 else 1405 { 1406 Con::errorf("NetConnection::serverToGhostID - could not find specified object"); 1407 return -1; 1408 } 1409} 1410 1411DefineEngineMethod( NetConnection, connect, void, (const char* remoteAddress),, 1412 "@brief Connects to the remote address.\n\n" 1413 1414 "Attempts to connect with another NetConnection on the given address. Typically once " 1415 "connected, a game's information is passed along from the server to the client, followed " 1416 "by the player entering the game world. The actual procedure is dependent on " 1417 "the NetConnection subclass that is used. i.e. GameConnection.\n" 1418 1419 "@param remoteAddress The address to connect to in the form of IP:<address>:<port&rt; " 1420 "although the <i>IP:</i> portion is optional. The <i>address</i> portion may be in the form " 1421 "of w.x.y.z or as a host name, in which case a DNS lookup will be performed. You may also " 1422 "substitue the word <i>broadcast</i> for the address to broadcast the connect request over " 1423 "the local subnet.\n\n" 1424 1425 "@see NetConnection::connectLocal() to connect to a server running within the same process " 1426 "as the client.\n" 1427 ) 1428{ 1429 NetAddress addr; 1430 if (Net::stringToAddress(remoteAddress, &addr) != Net::NoError) 1431 { 1432 Con::errorf("NetConnection::connect: invalid address - %s", remoteAddress); 1433 return; 1434 } 1435 object->connect(&addr); 1436} 1437 1438DefineEngineMethod( NetConnection, connectLocal, const char*, (),, 1439 "@brief Connects with the server that is running within the same process as the client.\n\n" 1440 1441 "@returns An error text message upon failure, or an empty string when successful.\n\n" 1442 1443 "@see See @ref local_connections for a description of local connections and their use. See " 1444 "NetConnection::connect() to connect to a server running in another process (on the same machine or not).\n") 1445{ 1446 ConsoleObject *co = ConsoleObject::create(object->getClassName()); 1447 NetConnection *client = object; 1448 NetConnection *server = dynamic_cast<NetConnection *>(co); 1449 BitStream *stream = BitStream::getPacketStream(); 1450 1451 if(!server || !server->canRemoteCreate()) 1452 { 1453 delete co; 1454 return "error"; 1455 } 1456 1457 server->registerObject(); 1458 server->setIsLocalClientConnection(); 1459 1460 server->setSequence(0); 1461 client->setSequence(0); 1462 client->setRemoteConnectionObject(server); 1463 server->setRemoteConnectionObject(client); 1464 1465 //We need to reset the maxrate's here, because we 1466 // can't test if it is a local connection until RemoteConnectionObject 1467 // has been set 1468 server->checkMaxRate(); 1469 client->checkMaxRate(); 1470 1471 stream->setPosition(0); 1472 client->writeConnectRequest(stream); 1473 stream->setPosition(0); 1474 1475 const char* error; 1476 if( !server->readConnectRequest( stream, &error ) ) 1477 { 1478 client->onConnectionRejected( error ); 1479 server->deleteObject(); 1480 return "error"; 1481 } 1482 1483 stream->setPosition(0); 1484 server->writeConnectAccept(stream); 1485 stream->setPosition(0); 1486 1487 if( !client->readConnectAccept( stream, &error ) ) 1488 { 1489 client->handleStartupError( error ); 1490 server->deleteObject(); 1491 return "error"; 1492 } 1493 1494 client->onConnectionEstablished(true); 1495 server->onConnectionEstablished(false); 1496 client->setEstablished(); 1497 server->setEstablished(); 1498 client->setConnectSequence(0); 1499 server->setConnectSequence(0); 1500 NetConnection::setLocalClientConnection(server); 1501 server->assignName("LocalClientConnection"); 1502 1503 return ""; 1504} 1505