netConnection.cpp
Engine/source/sim/netConnection.cpp
Classes:
class
Used when simulating lag.
Public Enumerations
enum
NetConnectionConstants { PingTimeout = 4500 DefaultPingRetryCount = 15 }
enum
NetStringConstants { NullString = 0 CString TagString Integer }
Public Variables
Public Functions
ConsoleDocClass(ConnectionMessageEvent , "@brief This event is used inside by the connection and subclasses <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> message itself when sequencing events <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )
ConsoleDocClass(NetConnection , "@brief Provides the basis <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> implementing a 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:<address >:<port &rt;" "although the< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >IP:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > portion is optional. The< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >address</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > portion may be in the form " "of w.x.y.z or as a 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_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:<address >:<port &rt;" "although the< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >IP:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > portion is optional. The< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >address</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > portion may be in the form " "of w.x.y.z or as a 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:<port></b> for broadcast type addresses\n" 574 "- <b>IP:<address>:<port></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:<address>:<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
