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 multiplayer game <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">protocol.\n\n</a>" "<a href="/coding/class/classnetconnection/">NetConnection</a> combines 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 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 <a href="/coding/class/structmove/">Move</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server 32 " "times 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 server which is running 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 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 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 log of the network traffic between client " "and server;when a <a href="/coding/class/classnetconnection/">NetConnection</a> records a demo, it simply logs this data <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> a file. When " "it plays 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 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 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 <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_1a2594a51175f310ed96ad6cd7d6514878">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 <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 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 starting state. This method resets 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 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 host name, in which case 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 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 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 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 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_1a2594a51175f310ed96ad6cd7d6514878">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 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 <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 ghost ID from this connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</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 " "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 ghost ID from this connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</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 " "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 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 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 <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 mission on the server, and each " "one is transmitted using 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 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 previous mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">load\n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">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_1a2594a51175f310ed96ad6cd7d6514878">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 multiplayer game <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">protocol.\n\n</a>" "<a href="/coding/class/classnetconnection/">NetConnection</a> combines 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 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 <a href="/coding/class/structmove/">Move</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server 32 " "times 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 server which is running 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 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 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 log of the network traffic between client " "and server;when a <a href="/coding/class/classnetconnection/">NetConnection</a> records a demo, it simply logs this data <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> a file. When " "it plays 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 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 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 <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_1a2594a51175f310ed96ad6cd7d6514878">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 <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 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 starting state. This method resets 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 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 host name, in which case 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 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 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 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 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_1a2594a51175f310ed96ad6cd7d6514878">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 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 <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 ghost ID from this connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</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 " "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 ghost ID from this connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</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 " "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 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 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 <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 mission on the server, and each " "one is transmitted using 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 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 previous mission <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">load\n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">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_1a2594a51175f310ed96ad6cd7d6514878">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      packetSize = 1024;
 321   }
 322
 323   gPacketUpdateDelayToServer = 1024 / packetRateToServer;
 324   U32 toClientUpdateDelay = 1024 / packetRateToClient;
 325
 326   if(mMaxRate.updateDelay != toClientUpdateDelay || mMaxRate.packetSize != packetSize)
 327   {
 328      mMaxRate.updateDelay = toClientUpdateDelay;
 329      mMaxRate.packetSize = packetSize;
 330      mMaxRate.changed = true;
 331   }
 332}
 333
 334void NetConnection::setSendingEvents(bool sending)
 335{
 336   AssertFatal(!mEstablished, "Error, cannot change event behavior after a connection has been established.");
 337   mSendingEvents = sending;
 338}
 339
 340void NetConnection::setTranslatesStrings(bool xl)
 341{
 342   AssertFatal(!mEstablished, "Error, cannot change event behavior after a connection has been established.");
 343   mTranslateStrings = xl;
 344   if(mTranslateStrings)
 345      mStringTable = new ConnectionStringTable(this);
 346}
 347
 348void NetConnection::setNetClassGroup(U32 grp)
 349{
 350   AssertFatal(!mEstablished, "Error, cannot change net class group after a connection has been established.");
 351   mNetClassGroup = grp;
 352}
 353
 354NetConnection::NetConnection()
 355 : mNetAddress()
 356{
 357   mTranslateStrings = false;
 358   mConnectSequence = 0;
 359
 360   mStringTable = NULL;
 361   mSendingEvents = true;
 362   mNetClassGroup = NetClassGroupGame;
 363   AssertFatal(mNetClassGroup >= NetClassGroupGame && mNetClassGroup < NetClassGroupsCount,
 364            "Invalid net event class type.");
 365
 366   mSimulatedPing = 0;
 367   mSimulatedPacketLoss = 0;
 368#ifdef TORQUE_DEBUG_NET
 369   mLogging = false;
 370#endif
 371   mEstablished = false;
 372   mLastUpdateTime = 0;
 373   mRoundTripTime = 0;
 374   mPacketLoss = 0;
 375   mNextTableHash = NULL;
 376   mSendDelayCredit = 0;
 377   mConnectionState = NotConnected;
 378
 379   mCurrentDownloadingFile = NULL;
 380   mCurrentFileBuffer = NULL;
 381
 382   mNextConnection = NULL;
 383   mPrevConnection = NULL;
 384
 385   mNotifyQueueHead = NULL;
 386   mNotifyQueueTail = NULL;
 387
 388   mCurRate.updateDelay = 102;
 389   mCurRate.packetSize = 200;
 390   mCurRate.changed = false;
 391   mMaxRate.updateDelay = 102;
 392   mMaxRate.packetSize = 200;
 393   mMaxRate.changed = false;
 394   checkMaxRate();
 395
 396   // event management data:
 397
 398   mNotifyEventList = NULL;
 399   mSendEventQueueHead = NULL;
 400   mSendEventQueueTail = NULL;
 401   mUnorderedSendEventQueueHead = NULL;
 402   mUnorderedSendEventQueueTail = NULL;
 403   mWaitSeqEvents = NULL;
 404
 405   mNextSendEventSeq = FirstValidSendEventSeq;
 406   mNextRecvEventSeq = FirstValidSendEventSeq;
 407   mLastAckedEventSeq = -1;
 408
 409   // ghost management data:
 410
 411   mScopeObject = NULL;
 412   mGhostingSequence = 0;
 413   mGhosting = false;
 414   mScoping = false;
 415   mGhostArray = NULL;
 416   mGhostRefs = NULL;
 417   mGhostLookupTable = NULL;
 418   mLocalGhosts = NULL;
 419
 420   mGhostsActive = 0;
 421
 422   mMissionPathsSent = false;
 423   mDemoWriteStream = NULL;
 424   mDemoReadStream = NULL;
 425
 426   mPingSendCount = 0;
 427   mPingRetryCount = DefaultPingRetryCount;
 428   mLastPingSendTime = Platform::getVirtualMilliseconds();
 429
 430   mCurrentDownloadingFile = NULL;
 431   mCurrentFileBuffer = NULL;
 432   mCurrentFileBufferSize = 0;
 433   mCurrentFileBufferOffset = 0;
 434   mNumDownloadedFiles = 0;
 435
 436   // Disable starting a new journal recording or playback from here on
 437   Journal::Disable();
 438
 439   // Ensure NetAddress is cleared
 440   dMemset(&mNetAddress, '\0', sizeof(NetAddress));
 441}
 442
 443NetConnection::~NetConnection()
 444{
 445   AssertFatal(mNotifyQueueHead == NULL, "Uncleared notifies remain.");
 446   netAddressTableRemove();
 447
 448   dFree(mCurrentFileBuffer);
 449   if(mCurrentDownloadingFile)
 450      delete mCurrentDownloadingFile;
 451
 452   delete[] mLocalGhosts;
 453   delete[] mGhostLookupTable;
 454   delete[] mGhostRefs;
 455   delete[] mGhostArray;
 456   delete mStringTable;
 457   if(mDemoWriteStream)
 458      delete mDemoWriteStream;
 459   if(mDemoReadStream)
 460      delete mDemoReadStream;
 461}
 462
 463NetConnection::PacketNotify::PacketNotify()
 464{
 465   rateChanged = false;
 466   maxRateChanged = false;
 467   sendTime = 0;
 468   eventList = 0;
 469   ghostList = 0;
 470}
 471
 472bool NetConnection::checkTimeout(U32 time)
 473{
 474   if(!isNetworkConnection())
 475      return false;
 476
 477   if(time > mLastPingSendTime + PingTimeout)
 478   {
 479      if(mPingSendCount >= mPingRetryCount)
 480         return true;
 481      mLastPingSendTime = time;
 482      mPingSendCount++;
 483      sendPingPacket();
 484   }
 485   return false;
 486}
 487
 488void NetConnection::keepAlive()
 489{
 490   mLastPingSendTime = Platform::getVirtualMilliseconds();
 491   mPingSendCount = 0;
 492}
 493
 494void NetConnection::handleConnectionEstablished()
 495{
 496}
 497
 498//--------------------------------------------------------------------------
 499#ifndef TORQUE_TGB_ONLY
 500DefineEngineMethod( NetConnection, transmitPaths, void, (),,
 501   "@brief Sent by the server during phase 2 of the mission download to update motion spline paths.\n\n"
 502
 503   "The server transmits all spline motion paths that are within the mission (Path) separate from "
 504   "other objects.  This is due to the potentially large number of nodes within each path, which may "
 505   "saturate a packet sent to the client.  By managing this step separately, Torque has finer control "
 506   "over how packets are organised vs. doing it during the ghosting stage.\n\n"
 507
 508   "Internally a PathManager is used to track all paths defined within a mission on the server, and each "
 509   "one is transmitted using a PathManagerEvent.  The client side collects these events and builds the "
 510   "given paths within its own PathManager.  This is typically done during the standard mission start "
 511   "phase 2 when following Torque's example mission startup sequence.\n\n"
 512
 513   "When a mission is ended, all paths need to be cleared from their respective path managers."
 514
 515   "@tsexample\n"
 516   "function serverCmdMissionStartPhase2Ack(%client, %seq, %playerDB)\n"
 517   "{\n"
 518   "   // Make sure to ignore calls from a previous mission load\n"
 519   "   if (%seq != $missionSequence || !$MissionRunning)\n"
 520   "      return;\n"
 521   "   if (%client.currentPhase != 1.5)\n"
 522   "      return;\n"
 523   "   %client.currentPhase = 2;\n"
 524   "\n"
 525   "   // Set the player datablock choice\n"
 526   "   %client.playerDB = %playerDB;\n"
 527   "\n"
 528   "   // Update mission paths (SimPath), this needs to get there before the objects.\n"
 529   "   %client.transmitPaths();\n"
 530   "\n"
 531   "   // Start ghosting objects to the client\n"
 532   "   %client.activateGhosting();\n"
 533   "}\n"
 534   "@endtsexample\n"
 535   
 536   "@see clearPaths()\n"
 537   "@see Path\n")
 538{
 539   gServerPathManager->transmitPaths(object);
 540   object->setMissionPathsSent(true);
 541}
 542
 543DefineEngineMethod( NetConnection, clearPaths, void, (),,
 544   "@brief On the server, resets the connection to indicate that motion spline paths have not been transmitted.\n\n"
 545
 546   "Typically when a mission has ended on the server, all connected clients are informed of this change "
 547   "and their connections are reset back to a starting state.  This method resets a connection on the "
 548   "server to indicate that motion spline paths have not been transmitted.\n\n"
 549
 550   "@tsexample\n"
 551   "   // Inform the clients\n"
 552   "   for (%clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++)\n"
 553   "   {\n"
 554   "      // clear ghosts and paths from all clients\n"
 555   "      %cl = ClientGroup.getObject(%clientIndex);\n"
 556   "      %cl.endMission();\n"
 557   "      %cl.resetGhosting();\n"
 558   "      %cl.clearPaths();\n"
 559   "   }\n"
 560   "@endtsexample\n"
 561   
 562   "@see transmitPaths()\n"
 563   "@see Path\n")
 564{
 565   object->setMissionPathsSent(false);
 566}
 567#endif
 568
 569DefineEngineMethod( NetConnection, getAddress, const char *, (),,
 570   "@brief Returns the far end network address for the connection.\n\n"
 571
 572   "The address will be in one of the following forms:\n"
 573   "- <b>IP:Broadcast:&lt;port&gt;</b> for broadcast type addresses\n"
 574   "- <b>IP:&lt;address&gt;:&lt;port&gt;</b> for IP addresses\n"
 575   "- <b>local</b> when connected locally (server and client running in same process\n")
 576{
 577   if(object->isLocalConnection())
 578      return "local";
 579   char *buffer = Con::getReturnBuffer(256);
 580   Net::addressToString(object->getNetAddress(), buffer);
 581   return buffer;
 582}
 583
 584DefineEngineMethod( NetConnection, setSimulatedNetParams, void, (F32 packetLoss, S32 delay),,
 585   "@brief Simulate network issues on the connection for testing.\n\n"
 586
 587   "@param packetLoss The fraction of packets that will be lost.  Ranges from 0.0 (no loss) to 1.0 (complete loss)\n"
 588   "@param delay Delays packets being transmitted by simulating a particular ping.  This is an absolute "
 589   "integer, measured in ms.\n")
 590{
 591   object->setSimulatedNetParams(packetLoss, delay);
 592}
 593
 594DefineEngineMethod( NetConnection, getPing, S32, (),,
 595   "@brief Returns the average round trip time (in ms) for the connection.\n\n"
 596
 597   "The round trip time is recalculated every time a notify packet is received.  Notify "
 598   "packets are used to information the connection that the far end successfully received "
 599   "the sent packet.\n")
 600{
 601   return( S32( object->getRoundTripTime() ) );
 602}
 603
 604DefineEngineMethod( NetConnection, getPacketLoss, S32, (),,
 605   "@brief Returns the percentage of packets lost per tick.\n\n"
 606
 607   "@note This method is not yet hooked up.\n")
 608{
 609   return( S32( 100 * object->getPacketLoss() ) );
 610}
 611
 612DefineEngineMethod( NetConnection, checkMaxRate, void, (),,
 613   "@brief Ensures that all configured packet rates and sizes meet minimum requirements.\n\n"
 614
 615   "This method is normally only called when a NetConnection class is first constructed.  It need "
 616   "only be manually called if the global variables that set the packet rate or size have changed.\n\n"
 617
 618   "@note If @$pref::Net::PacketRateToServer, @$pref::Net::PacketRateToClient or @$pref::Net::PacketSize "
 619   "have been changed since a NetConnection has been created, this method must be called on "
 620   "all connections for them to follow the new rates or size.\n")
 621{
 622   object->checkMaxRate();
 623}
 624
 625#ifdef TORQUE_DEBUG_NET
 626
 627DefineEngineMethod( NetConnection, setLogging, void, (bool state),,
 628   "@brief Sets if debug statements should be written to the console log.\n\n"
 629   "@note Only valid if the executable has been compiled with TORQUE_DEBUG_NET.\n")
 630{
 631   object->setLogging(state);
 632}
 633
 634#endif
 635
 636//--------------------------------------------------------------------
 637
 638void NetConnection::setEstablished()
 639{
 640   AssertFatal(!mEstablished, "NetConnection::setEstablished - Error, this NetConnection has already been established.");
 641
 642   mEstablished = true;
 643   mNextConnection = mConnectionList;
 644   if(mConnectionList)
 645      mConnectionList->mPrevConnection = this;
 646   mConnectionList = this;
 647
 648   if(isNetworkConnection())
 649      netAddressTableInsert();
 650
 651}
 652
 653void NetConnection::onRemove()
 654{
 655   // delete any ghosts that may exist for this connection, but aren't added
 656   while(mGhostAlwaysSaveList.size())
 657   {
 658      delete mGhostAlwaysSaveList[0].ghost;
 659      mGhostAlwaysSaveList.pop_front();
 660   }
 661   if(mNextConnection)
 662      mNextConnection->mPrevConnection = mPrevConnection;
 663   if(mPrevConnection)
 664      mPrevConnection->mNextConnection = mNextConnection;
 665   if(mConnectionList == this)
 666      mConnectionList = mNextConnection;
 667   while(mNotifyQueueHead)
 668      handleNotify(false);
 669
 670   ghostOnRemove();
 671   eventOnRemove();
 672
 673   Parent::onRemove();
 674}
 675
 676String NetConnection::mErrorBuffer;
 677
 678void NetConnection::setLastError(const char *fmt, ...)
 679{
 680   va_list argptr;
 681   va_start(argptr, fmt);
 682   mErrorBuffer = String::ToString(fmt, argptr);
 683   va_end(argptr);
 684
 685#ifdef TORQUE_DEBUG_NET
 686   // setLastErrors assert in net_debug builds
 687   AssertFatal(false, mErrorBuffer.c_str());
 688#endif
 689
 690}
 691
 692//--------------------------------------------------------------------
 693
 694void NetConnection::handleNotify(bool recvd)
 695{
 696//   Con::printf("NET  %d: NOTIFY - %d %s", getId(), gPacketId, recvd ? "RECVD" : "DROPPED");
 697
 698   PacketNotify *note = mNotifyQueueHead;
 699   AssertFatal(note != NULL, "Error: got a notify with a null notify head.");
 700   mNotifyQueueHead = mNotifyQueueHead->nextPacket;
 701
 702   if(note->rateChanged && !recvd)
 703      mCurRate.changed = true;
 704   if(note->maxRateChanged && !recvd)
 705      mMaxRate.changed = true;
 706
 707   if(recvd) 
 708   {
 709      // Running average of roundTrip time
 710      U32 curTime = Platform::getVirtualMilliseconds();
 711      mRoundTripTime = (mRoundTripTime + (curTime - note->sendTime)) * 0.5;
 712      packetReceived(note);
 713   }
 714   else
 715      packetDropped(note);
 716
 717   delete note;
 718}
 719
 720void NetConnection::processRawPacket(BitStream *bstream)
 721{
 722   if(mDemoWriteStream)
 723      recordBlock(BlockTypePacket, bstream->getReadByteSize(), bstream->getBuffer());
 724
 725   ConnectionProtocol::processRawPacket(bstream);
 726}
 727
 728void NetConnection::handlePacket(BitStream *bstream)
 729{
 730//   Con::printf("NET  %d: RECV - %d", getId(), mLastSeqRecvd);
 731   // clear out any errors
 732
 733   mErrorBuffer = String();
 734
 735   if(bstream->readFlag())
 736   {
 737      mCurRate.updateDelay = bstream->readInt(12);
 738      mCurRate.packetSize = bstream->readInt(12);
 739   }
 740
 741   if(bstream->readFlag())
 742   {
 743      U32 omaxDelay = bstream->readInt(12);
 744      S32 omaxSize = bstream->readInt(12);
 745      if(omaxDelay < mMaxRate.updateDelay)
 746         omaxDelay = mMaxRate.updateDelay;
 747      if(omaxSize > mMaxRate.packetSize)
 748         omaxSize = mMaxRate.packetSize;
 749      if(omaxDelay != mCurRate.updateDelay || omaxSize != mCurRate.packetSize)
 750      {
 751         mCurRate.updateDelay = omaxDelay;
 752         mCurRate.packetSize = omaxSize;
 753         mCurRate.changed = true;
 754      }
 755   }
 756   readPacket(bstream);
 757
 758   if(mErrorBuffer.isNotEmpty())
 759      connectionError(mErrorBuffer);
 760}
 761
 762void NetConnection::connectionError(const char *errorString)
 763{
 764   TORQUE_UNUSED(errorString);
 765}
 766
 767//--------------------------------------------------------------------
 768
 769NetConnection::PacketNotify *NetConnection::allocNotify()
 770{
 771   return new PacketNotify;
 772}
 773
 774/// Used when simulating lag.
 775///
 776/// We post this SimEvent when we want to send a packet; it delays for a bit, then
 777/// sends the actual packet.
 778class NetDelayEvent : public SimEvent
 779{
 780   U8 buffer[Net::MaxPacketDataSize];
 781   BitStream stream;
 782public:
 783   NetDelayEvent(BitStream *inStream) : stream(NULL, 0)
 784   {
 785      dMemcpy(buffer, inStream->getBuffer(), inStream->getPosition());
 786      stream.setBuffer(buffer, inStream->getPosition());
 787      stream.setPosition(inStream->getPosition());
 788   }
 789   void process(SimObject *object)
 790   {
 791      ((NetConnection *) object)->sendPacket(&stream);
 792   }
 793};
 794
 795void NetConnection::checkPacketSend(bool force)
 796{
 797   U32 curTime = Platform::getVirtualMilliseconds();
 798   U32 delay = isConnectionToServer() ? gPacketUpdateDelayToServer : mCurRate.updateDelay;
 799
 800   if(!force)
 801   {
 802      if(curTime < mLastUpdateTime + delay - mSendDelayCredit)
 803         return;
 804
 805      mSendDelayCredit = curTime - (mLastUpdateTime + delay - mSendDelayCredit);
 806      if(mSendDelayCredit > 1000)
 807         mSendDelayCredit = 1000;
 808
 809      if(mDemoWriteStream)
 810         recordBlock(BlockTypeSendPacket, 0, 0);
 811   }
 812   if(windowFull())
 813      return;
 814
 815   BitStream *stream = BitStream::getPacketStream(mCurRate.packetSize);
 816   buildSendPacketHeader(stream);
 817
 818   mLastUpdateTime = curTime;
 819
 820   PacketNotify *note = allocNotify();
 821   if(!mNotifyQueueHead)
 822      mNotifyQueueHead = note;
 823   else
 824      mNotifyQueueTail->nextPacket = note;
 825   mNotifyQueueTail = note;
 826   note->nextPacket = NULL;
 827   note->sendTime = curTime;
 828
 829   note->rateChanged = mCurRate.changed;
 830   note->maxRateChanged = mMaxRate.changed;
 831
 832   if(stream->writeFlag(mCurRate.changed))
 833   {
 834      stream->writeInt(mCurRate.updateDelay, 12);
 835      stream->writeInt(mCurRate.packetSize, 12);
 836      mCurRate.changed = false;
 837   }
 838   if(stream->writeFlag(mMaxRate.changed))
 839   {
 840      stream->writeInt(mMaxRate.updateDelay, 12);
 841      stream->writeInt(mMaxRate.packetSize, 12);
 842      mMaxRate.changed = false;
 843   }
 844#ifdef TORQUE_DEBUG_NET
 845   U32 start = stream->getCurPos();
 846#endif
 847
 848   DEBUG_LOG(("PKLOG %d START", getId()) );
 849   writePacket(stream, note);
 850   DEBUG_LOG(("PKLOG %d END - %d", getId(), stream->getCurPos() - start) );
 851   if(mSimulatedPacketLoss && Platform::getRandom() < mSimulatedPacketLoss)
 852   {
 853      //Con::printf("NET  %d: SENDDROP - %d", getId(), mLastSendSeq);
 854      return;
 855   }
 856   if(mSimulatedPing)
 857   {
 858      Sim::postEvent(getId(), new NetDelayEvent(stream), Sim::getCurrentTime() + mSimulatedPing);
 859      return;
 860   }
 861   sendPacket(stream);
 862}
 863
 864Net::Error NetConnection::sendPacket(BitStream *stream)
 865{
 866   //Con::printf("NET  %d: SEND - %d", getId(), mLastSendSeq);
 867   // do nothing on send if this is a demo replay.
 868   if(mDemoReadStream)
 869      return Net::NoError;
 870
 871   gNetBitsSent = stream->getPosition();
 872
 873   if(isLocalConnection())
 874   {
 875      // short circuit connection to the other side.
 876      // handle the packet, then force a notify.
 877      stream->setBuffer(stream->getBuffer(), stream->getPosition(), stream->getPosition());
 878      mRemoteConnection->processRawPacket(stream);
 879
 880      return Net::NoError;
 881   }
 882   else
 883   {
 884      return Net::sendto(getNetAddress(), stream->getBuffer(), stream->getPosition());
 885   }
 886}
 887
 888//--------------------------------------------------------------------
 889//--------------------------------------------------------------------
 890
 891// these are the virtual function defs for Connection -
 892// if your subclass has additional data to read / write / notify, add it in these functions.
 893
 894void NetConnection::readPacket(BitStream *bstream)
 895{
 896   eventReadPacket(bstream);
 897   ghostReadPacket(bstream);
 898}
 899
 900void NetConnection::writePacket(BitStream *bstream, PacketNotify *note)
 901{
 902   eventWritePacket(bstream, note);
 903   ghostWritePacket(bstream, note);
 904}
 905
 906void NetConnection::packetReceived(PacketNotify *note)
 907{
 908   eventPacketReceived(note);
 909   ghostPacketReceived(note);
 910}
 911
 912void NetConnection::packetDropped(PacketNotify *note)
 913{
 914   eventPacketDropped(note);
 915   ghostPacketDropped(note);
 916}
 917
 918//--------------------------------------------------------------------
 919//--------------------------------------------------------------------
 920
 921void NetConnection::writeDemoStartBlock(ResizeBitStream* stream)
 922{
 923   ConnectionProtocol::writeDemoStartBlock(stream);
 924
 925   stream->write(mRoundTripTime);
 926   stream->write(mPacketLoss);
 927#ifndef TORQUE_TGB_ONLY
 928   // Write all the current paths to the stream...
 929   gClientPathManager->dumpState(stream);
 930#endif
 931   stream->validate();
 932   mStringTable->writeDemoStartBlock(stream);
 933
 934   U32 start = 0;
 935   PacketNotify *note = mNotifyQueueHead;
 936   while(note)
 937   {
 938      start++;
 939      note = note->nextPacket;
 940   }
 941   stream->write(start);
 942
 943   eventWriteStartBlock(stream);
 944   ghostWriteStartBlock(stream);
 945}
 946
 947bool NetConnection::readDemoStartBlock(BitStream* stream)
 948{
 949   ConnectionProtocol::readDemoStartBlock(stream);
 950
 951   stream->read(&mRoundTripTime);
 952   stream->read(&mPacketLoss);
 953
 954#ifndef TORQUE_TGB_ONLY
 955   // Read
 956   gClientPathManager->readState(stream);
 957#endif
 958
 959   mStringTable->readDemoStartBlock(stream);
 960   U32 pos;
 961   stream->read(&pos); // notify count
 962   for(U32 i = 0; i < pos; i++)
 963   {
 964      PacketNotify *note = allocNotify();
 965      note->nextPacket = NULL;
 966      if(!mNotifyQueueHead)
 967         mNotifyQueueHead = note;
 968      else
 969         mNotifyQueueTail->nextPacket = note;
 970      mNotifyQueueTail = note;
 971   }
 972   eventReadStartBlock(stream);
 973   ghostReadStartBlock(stream);
 974   return true;
 975}
 976
 977bool NetConnection::startDemoRecord(const char *fileName)
 978{
 979   FileStream *fs = new FileStream;
 980
 981   if((fs = FileStream::createAndOpen( fileName, Torque::FS::File::Write )) == NULL)
 982      return false;
 983
 984   mDemoWriteStream = fs;
 985   mDemoWriteStream->write(mProtocolVersion);
 986   ResizeBitStream bs;
 987
 988   // then write out the start block
 989   writeDemoStartBlock(&bs);
 990   U32 size = bs.getPosition() + 1;
 991   mDemoWriteStream->write(size);
 992   mDemoWriteStream->write(size, bs.getBuffer());
 993   return true;
 994}
 995
 996bool NetConnection::replayDemoRecord(const char *fileName)
 997{
 998   Stream *fs;
 999   if((fs = FileStream::createAndOpen( fileName, Torque::FS::File::Read )) == NULL)
1000      return false;
1001
1002   mDemoReadStream = fs;
1003   mDemoReadStream->read(&mProtocolVersion);
1004   U32 size;
1005   mDemoReadStream->read(&size);
1006   U8 *block = new U8[size];
1007   mDemoReadStream->read(size, block);
1008   BitStream bs(block, size);
1009
1010   bool res = readDemoStartBlock(&bs);
1011   delete[] block;
1012   if(!res)
1013      return false;
1014
1015   // prep for first block read
1016   // type/size stored in U16: [type:4][size:12]
1017   U16 typeSize;
1018   mDemoReadStream->read(&typeSize);
1019
1020   mDemoNextBlockType = typeSize >> 12;
1021   mDemoNextBlockSize = typeSize & 0xFFF;
1022
1023   if(mDemoReadStream->getStatus() != Stream::Ok)
1024      return false;
1025   return true;
1026}
1027
1028void NetConnection::stopRecording()
1029{
1030   if(mDemoWriteStream)
1031   {
1032      delete mDemoWriteStream;
1033      mDemoWriteStream = NULL;
1034   }
1035}
1036
1037void NetConnection::recordBlock(U32 type, U32 size, void *data)
1038{
1039   AssertFatal(type < MaxNumBlockTypes, "NetConnection::recordBlock: invalid type");
1040   AssertFatal(size < MaxBlockSize, "NetConnection::recordBlock: invalid size");
1041   if((type >= MaxNumBlockTypes) || (size >= MaxBlockSize))
1042      return;
1043
1044   if(mDemoWriteStream)
1045   {
1046      // store type/size in U16: [type:4][size:12]
1047      U16 typeSize = (type << 12) | size;
1048      mDemoWriteStream->write(typeSize);
1049      if(size)
1050         mDemoWriteStream->write(size, data);
1051   }
1052}
1053
1054void NetConnection::handleRecordedBlock(U32 type, U32 size, void *data)
1055{
1056   switch(type)
1057   {
1058      case BlockTypePacket: {
1059         BitStream bs(data, size);
1060         processRawPacket(&bs);
1061         break;
1062      }
1063      case BlockTypeSendPacket:
1064         checkPacketSend(true);
1065         break;
1066   }
1067}
1068
1069void NetConnection::demoPlaybackComplete()
1070{
1071}
1072
1073void NetConnection::stopDemoPlayback()
1074{
1075   demoPlaybackComplete();
1076   deleteObject();
1077}
1078
1079bool NetConnection::processNextBlock()
1080{
1081   U8 buffer[Net::MaxPacketDataSize];
1082
1083   // read in and handle
1084   if(mDemoReadStream->read(mDemoNextBlockSize, buffer))
1085      handleRecordedBlock(mDemoNextBlockType, mDemoNextBlockSize, buffer);
1086
1087   U16 typeSize;
1088   mDemoReadStream->read(&typeSize);
1089
1090   mDemoNextBlockType = typeSize >> 12;
1091   mDemoNextBlockSize = typeSize & 0xFFF;
1092
1093   if(mDemoReadStream->getStatus() != Stream::Ok)
1094   {
1095      stopDemoPlayback();
1096      return false;
1097   }
1098   return true;
1099}
1100
1101//--------------------------------------------------------------------
1102//--------------------------------------------------------------------
1103
1104// some handy string functions for compressing strings over a connection:
1105enum NetStringConstants
1106{
1107   NullString = 0,
1108   CString,
1109   TagString,
1110   Integer
1111};
1112
1113void NetConnection::validateSendString(const char *str)
1114{
1115   if(U8(*str) == StringTagPrefixByte)
1116   {
1117      NetStringHandle strHandle(dAtoi(str + 1));
1118      checkString(strHandle);
1119   }
1120}
1121
1122void NetConnection::packString(BitStream *stream, const char *str)
1123{
1124   if(!*str)
1125   {
1126      stream->writeInt(NullString, 2);
1127      return;
1128   }
1129   if(U8(str[0]) == StringTagPrefixByte)
1130   {
1131      stream->writeInt(TagString, 2);
1132      stream->writeInt(dAtoi(str + 1), ConnectionStringTable::EntryBitSize);
1133      return;
1134   }
1135   if(str[0] == '-' || (str[0] >= '0' && str[0] <= '9'))
1136   {
1137      char buf[16];
1138      S32 num = dAtoi(str);
1139      dSprintf(buf, sizeof(buf), "%d", num);
1140      if(!dStrcmp(buf, str))
1141      {
1142         stream->writeInt(Integer, 2);
1143         if(stream->writeFlag(num < 0))
1144            num = -num;
1145         if(stream->writeFlag(num < 128))
1146         {
1147            stream->writeInt(num, 7);
1148            return;
1149         }
1150         if(stream->writeFlag(num < 32768))
1151         {
1152            stream->writeInt(num, 15);
1153            return;
1154         }
1155         else
1156         {
1157            stream->writeInt(num, 31);
1158            return;
1159         }
1160      }
1161   }
1162   stream->writeInt(CString, 2);
1163   stream->writeString(str);
1164}
1165
1166void NetConnection::unpackString(BitStream *stream, char readBuffer[1024])
1167{
1168   U32 code = stream->readInt(2);
1169   switch(code)
1170   {
1171      case NullString:
1172         readBuffer[0] = 0;
1173         return;
1174      case CString:
1175         {
1176            stream->readString(readBuffer);
1177            return;
1178         }
1179      case TagString:
1180         U32 tag;
1181         tag = stream->readInt(ConnectionStringTable::EntryBitSize);
1182         readBuffer[0] = StringTagPrefixByte;
1183         dSprintf(readBuffer+1, 1023, "%d", tag);
1184         return;
1185      case Integer:
1186         bool neg;
1187         neg = stream->readFlag();
1188         S32 num;
1189         if(stream->readFlag())
1190            num = stream->readInt(7);
1191         else if(stream->readFlag())
1192            num = stream->readInt(15);
1193         else
1194            num = stream->readInt(31);
1195         if(neg)
1196            num = -num;
1197         dSprintf(readBuffer, 1024, "%d", num);
1198   }
1199}
1200
1201void NetConnection::packNetStringHandleU(BitStream *stream, NetStringHandle &h)
1202{
1203   if(stream->writeFlag(h.isValidString() ))
1204   {
1205      bool isReceived;
1206      U32 netIndex = checkString(h, &isReceived);
1207      if(stream->writeFlag(isReceived))
1208         stream->writeInt(netIndex, ConnectionStringTable::EntryBitSize);
1209      else
1210         stream->writeString(h.getString());
1211   }
1212}
1213
1214NetStringHandle NetConnection::unpackNetStringHandleU(BitStream *stream)
1215{
1216   NetStringHandle ret;
1217   if(stream->readFlag())
1218   {
1219      if(stream->readFlag())
1220         ret = mStringTable->lookupString(stream->readInt(ConnectionStringTable::EntryBitSize));
1221      else
1222      {
1223         char buf[256];
1224         stream->readString(buf);
1225         ret = NetStringHandle(buf);
1226      }
1227   }
1228   return ret;
1229}
1230
1231//----------------------------------------------------------------------------
1232
1233//----------------------------------------------------------------------------
1234//----------------------------------------------------------------------------
1235
1236void NetConnection::setAddressDigest(U32 digest[4])
1237{
1238   mAddressDigest[0] = digest[0];
1239   mAddressDigest[1] = digest[1];
1240   mAddressDigest[2] = digest[2];
1241   mAddressDigest[3] = digest[3];
1242}
1243
1244void NetConnection::getAddressDigest(U32 digest[4])
1245{
1246   digest[0] = mAddressDigest[0];
1247   digest[1] = mAddressDigest[1];
1248   digest[2] = mAddressDigest[2];
1249   digest[3] = mAddressDigest[3];
1250}
1251
1252bool NetConnection::canRemoteCreate()
1253{
1254   return false;
1255}
1256
1257void NetConnection::onTimedOut()
1258{
1259
1260}
1261
1262void NetConnection::connect(const NetAddress *address)
1263{
1264   mNetAddress = *address;
1265   GNet->startConnection(this);
1266}
1267
1268void NetConnection::onConnectTimedOut()
1269{
1270
1271}
1272
1273void NetConnection::sendDisconnectPacket(const char *reason)
1274{
1275   GNet->sendDisconnectPacket(this, reason);
1276}
1277
1278void NetConnection::onDisconnect(const char *reason)
1279{
1280   TORQUE_UNUSED(reason);
1281}
1282
1283void NetConnection::onConnectionRejected(const char *reason)
1284{
1285}
1286
1287void NetConnection::onConnectionEstablished(bool isInitiator)
1288{
1289
1290}
1291
1292void NetConnection::handleStartupError(const char *errorString)
1293{
1294
1295}
1296
1297void NetConnection::writeConnectRequest(BitStream *stream)
1298{
1299   stream->write(mNetClassGroup);
1300   stream->write(U32(AbstractClassRep::getClassCRC(mNetClassGroup)));
1301}
1302
1303bool NetConnection::readConnectRequest(BitStream *stream, const char **errorString)
1304{
1305   U32 classGroup, classCRC;
1306   stream->read(&classGroup);
1307   stream->read(&classCRC);
1308
1309   if(classGroup == mNetClassGroup && classCRC == AbstractClassRep::getClassCRC(mNetClassGroup))
1310      return true;
1311
1312   *errorString = "CHR_INVALID";
1313   return false;
1314}
1315
1316void NetConnection::writeConnectAccept(BitStream *stream)
1317{
1318   TORQUE_UNUSED(stream);
1319}
1320
1321bool NetConnection::readConnectAccept(BitStream *stream, const char **errorString)
1322{
1323   TORQUE_UNUSED(stream);
1324   TORQUE_UNUSED(errorString);
1325   return true;
1326}
1327
1328DefineEngineMethod( NetConnection, resolveGhostID, S32, (S32 ghostID),,
1329   "@brief On the client, convert a ghost ID from this connection to a real SimObject ID.\n\n"
1330
1331   "Torque's network ghosting system only exchanges ghost ID's between the server and client.  Use "
1332   "this method on the client to discover an object's local SimObject ID when you only have a "
1333   "ghost ID.\n"
1334
1335   "@param ghostID The ghost ID of the object as sent by the server.\n"
1336   "@returns The SimObject ID of the object, or 0 if it could not be resolved.\n\n"
1337
1338   "@tsexample\n"
1339      "%object = ServerConnection.resolveGhostID( %ghostId );\n"
1340   "@endtsexample\n\n"
1341
1342   "@see @ref ghosting_scoping for a description of the ghosting system.\n\n")
1343{
1344   // Safety check
1345   if(ghostID < 0 || ghostID > NetConnection::MaxGhostCount) return 0;
1346
1347   NetObject *foo = object->resolveGhost(ghostID);
1348
1349   if(foo)
1350      return foo->getId();
1351   else
1352      return 0;
1353}
1354
1355DefineEngineMethod( NetConnection, resolveObjectFromGhostIndex, S32, (S32 ghostID),,
1356   "@brief On the server, convert a ghost ID from this connection to a real SimObject ID.\n\n"
1357
1358   "Torque's network ghosting system only exchanges ghost ID's between the server and client.  Use "
1359   "this method on the server to discover an object's local SimObject ID when you only have a "
1360   "ghost ID.\n"
1361
1362   "@param ghostID The ghost ID of the object as sent by the server.\n"
1363   "@returns The SimObject ID of the object, or 0 if it could not be resolved.\n\n"
1364
1365   "@tsexample\n"
1366      "%object = %client.resolveObjectFromGhostIndex( %ghostId );\n"
1367   "@endtsexample\n\n"
1368
1369   "@see @ref ghosting_scoping for a description of the ghosting system.\n\n")
1370{
1371   // Safety check
1372   if(ghostID < 0 || ghostID > NetConnection::MaxGhostCount) return 0;
1373
1374   NetObject *foo = object->resolveObjectFromGhostIndex(ghostID);
1375
1376   if(foo)
1377      return foo->getId();
1378   else
1379      return 0;
1380}
1381
1382DefineEngineMethod( NetConnection, getGhostID, S32, (S32 realID),,
1383   "@brief On server or client, convert a real id to the ghost id for this connection.\n\n"
1384
1385   "Torque's network ghosting system only exchanges ghost ID's between the server and client.  Use "
1386   "this method on the server or client to discover an object's ghost ID based on its real SimObject ID.\n"
1387
1388   "@param realID The real SimObject ID of the object.\n"
1389   "@returns The ghost ID of the object for this connection, or -1 if it could not be resolved.\n\n"
1390
1391   "@see @ref ghosting_scoping for a description of the ghosting system.\n\n")
1392{
1393   NetObject * foo;
1394
1395   if(Sim::findObject(realID, foo))
1396   {
1397      return object->getGhostIndex(foo);
1398   }
1399   else
1400   {
1401      Con::errorf("NetConnection::serverToGhostID - could not find specified object");
1402      return -1;
1403   }
1404}
1405
1406DefineEngineMethod( NetConnection, connect, void, (const char* remoteAddress),,
1407   "@brief Connects to the remote address.\n\n"
1408
1409   "Attempts to connect with another NetConnection on the given address.  Typically once "
1410   "connected, a game's information is passed along from the server to the client, followed "
1411   "by the player entering the game world.  The actual procedure is dependent on "
1412   "the NetConnection subclass that is used.  i.e. GameConnection.\n"
1413
1414   "@param remoteAddress The address to connect to in the form of IP:&lt;address&gt;:&lt;port&rt; "
1415   "although the <i>IP:</i> portion is optional.  The <i>address</i> portion may be in the form "
1416   "of w.x.y.z or as a host name, in which case a DNS lookup will be performed.  You may also "
1417   "substitue the word <i>broadcast</i> for the address to broadcast the connect request over "
1418   "the local subnet.\n\n"
1419
1420   "@see NetConnection::connectLocal() to connect to a server running within the same process "
1421   "as the client.\n"
1422   )
1423{
1424   NetAddress addr;
1425   if (Net::stringToAddress(remoteAddress, &addr) != Net::NoError)
1426   {
1427      Con::errorf("NetConnection::connect: invalid address - %s", remoteAddress);
1428      return;
1429   }
1430   object->connect(&addr);
1431}
1432
1433DefineEngineMethod( NetConnection, connectLocal, const char*, (),,
1434   "@brief Connects with the server that is running within the same process as the client.\n\n"
1435
1436   "@returns An error text message upon failure, or an empty string when successful.\n\n"
1437
1438   "@see See @ref local_connections for a description of local connections and their use.  See "
1439   "NetConnection::connect() to connect to a server running in another process (on the same machine or not).\n")
1440{
1441   ConsoleObject *co = ConsoleObject::create(object->getClassName());
1442   NetConnection *client = object;
1443   NetConnection *server = dynamic_cast<NetConnection *>(co);
1444   BitStream *stream = BitStream::getPacketStream();
1445
1446   if(!server || !server->canRemoteCreate())
1447   {
1448      delete co;
1449      return "error";
1450   }
1451      
1452   server->registerObject();
1453   server->setIsLocalClientConnection();
1454
1455   server->setSequence(0);
1456   client->setSequence(0);
1457   client->setRemoteConnectionObject(server);
1458   server->setRemoteConnectionObject(client);
1459
1460   //We need to reset the maxrate's here, because we
1461   // can't test if it is a local connection until RemoteConnectionObject
1462   // has been set
1463   server->checkMaxRate();  
1464   client->checkMaxRate();
1465
1466   stream->setPosition(0);
1467   client->writeConnectRequest(stream);
1468   stream->setPosition(0);
1469   
1470   const char* error;
1471   if( !server->readConnectRequest( stream, &error ) )
1472   {
1473      client->onConnectionRejected( error );
1474      server->deleteObject();
1475      return "error";
1476   }
1477
1478   stream->setPosition(0);
1479   server->writeConnectAccept(stream);
1480   stream->setPosition(0);
1481
1482   if( !client->readConnectAccept( stream, &error ) )
1483   {
1484      client->handleStartupError( error );
1485      server->deleteObject();
1486      return "error";
1487   }
1488
1489   client->onConnectionEstablished(true);
1490   server->onConnectionEstablished(false);
1491   client->setEstablished();
1492   server->setEstablished();
1493   client->setConnectSequence(0);
1494   server->setConnectSequence(0);
1495   NetConnection::setLocalClientConnection(server);
1496   server->assignName("LocalClientConnection");
1497   
1498   return "";
1499}
1500