Torque3D Documentation / _generateds / netConnection.cpp

netConnection.cpp

Engine/source/sim/netConnection.cpp

More...

Classes:

Public Enumerations

enum
NetConnectionConstants {
  PingTimeout = 4500
  DefaultPingRetryCount = 15
}
enum
NetStringConstants {
  NullString = 0
  CString 
  TagString 
  Integer 
}

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:&lt;address &gt;:&lt;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>" )
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:&lt;address &gt;:&lt;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:&lt;port&gt;</b> for broadcast type addresses\n"
 579   "- <b>IP:&lt;address&gt;:&lt;port&gt;</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:&lt;address&gt;:&lt;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