⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netconnection.h

📁 五行MMORPG引擎系统V1.0
💻 H
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#ifndef _NETCONNECTION_H_
#define _NETCONNECTION_H_


#ifndef _USE_TGE_NETCONNTION_
	
///////////////////////////////////////////////////////////////////////////////
//调用 RPG的ConnectionLayer

	#ifndef _CONNECTIONLAYER_H_
		#include "server/conn/connectionLayer.h"
	#endif

///////////////////////////////////////////////////////////////////////////////
//调用 TGE的 NetConnection
#else//_USE_TGE_NETCONNTION_


#ifndef _MPOINT_H_
#include "math/mPoint.h"
#endif
#ifndef _NETOBJECT_H_
#include "sim/netObject.h"
#endif
#ifndef _NETSTRINGTABLE_H_
#include "sim/netStringTable.h"
#endif
//#ifndef _EVENT_H_
//#include "platform/event.h"
//#endif
#ifndef _NETEVENT_H_
#include "sim/netEvent.h"
#endif

#ifndef _DNET_H_
#include "core/dnet.h"
#endif

#ifndef _H_CONNECTIONSTRINGTABLE
#include "sim/connectionStringTable.h"
#endif

class NetConnection;
class NetObject;
class BitStream;
class ResizeBitStream;
class Stream;
class Point3F;

struct GhostInfo;
struct SubPacketRef; // defined in NetConnection subclass

//#define TORQUE_DEBUG_NET

//########################################################3333
//以下netevent封装独立到 sim/netEvent.h,配合RPGServer::connectionLayer封装

//#ifdef TORQUE_DEBUG_NET
//#define DEBUG_LOG(x) if(mLogging){Con::printf x;}
//#else
//#define DEBUG_LOG(x)
//#endif
//
////----------------------------------------------------------------------------
//
//class NetEvent;
//
//struct NetEventNote
//{
//   NetEvent *mEvent;
//   S32 mSeqCount;
//   NetEventNote *mNextEvent;
//};

/// An event to be sent over the network.
///
/// @note Torque implements two methods of network data passing; this is one of them.
/// See NetConnection for details of the other, which is referred to as ghosting.
///
/// Torque's network layer lets you pass events to/from the server. There are three
/// types of events:
///      - <b>Unguaranteed events</b> are events which are sent once. If they don't
///        make it through the link, they are not resent. This is good for quick,
///        frequent status updates which are of transient interest, like position
///        updates or voice communication.
///      - <b>Guaranteed events</b> are events which are guaranteed to be
///        delivered. If they don't make it through the link, they are sent as
///        needed. This is good for important, one-time information,
///        like which team a user wants to play on, or the current weather.
///      - <b>GuaranteedOrdered events</b> are events which are guaranteed not
///        only to be delivered, but to be delivered in order. This is good for
///        information which is not only important, but also order-critical, like
///        chat messages.
///
/// There are 6 methods that you need to implement if you want to make a
/// basic NetEvent subclass, and 2 macros you need to call.
///
/// @code
/// // A simple NetEvent to transmit a string over the network.
/// // This is based on the code in netTest.cc
/// class SimpleMessageEvent : public NetEvent
/// {
///    typedef NetEvent Parent;
///    char *msg;
/// public:
///    SimpleMessageEvent(const char *message = NULL);
///    ~SimpleMessageEvent();
///
///    virtual void pack   (NetConnection *conn, BitStream *bstream);
///    virtual void write  (NetConnection *conn, BitStream *bstream);
///    virtual void unpack (NetConnection *conn, BitStream *bstream);
///    virtual void process(NetConnection *conn);
///
///    DECLARE_CONOBJECT(SimpleMessageEvent);
/// };
///
/// IMPLEMENT_CO_NETEVENT_V1(SimpleMessageEvent);
/// @endcode
///
/// Notice the two macros which we call. The first, DECLARE_CONOBJECT() is there
/// because we're a ConsoleObject. The second, IMPLEMENT_CO_NETEVENT_V1(), is there
/// to register this event type with Torque's networking layer, so that it can be
/// properly transmitted over the wire. There are three macros which you might use:
///      - <b>IMPLEMENT_CO_NETEVENT_V1</b>, which indicates an event which may be sent
///        in either direction, from the client to the server, or from the server to the
///        client.
///      - <b>IMPLEMENT_CO_CLIENTEVENT_V1</b>, which indicates an event which may only
///        be sent to the client.
///      - <b>IMPLEMENT_CO_SERVEREVENT_V1</b>, which indicates an event which may only
///        be sent to the server.
///
/// Choosing the right macro is a good way to make your game more resistant to hacking; for instance,
/// PathManager events are marked as CLIENTEVENTs, because they would cause the server to crash if
/// a client sent them.
///
/// @note Torque allows you to call NetConnection::setLastError() on the NetConnection passed to
///       your NetEvent. You can cause the connection to abort if invalid data is received, specifying
///       a reason to the user.
///
/// Now, the 6 methods which we have above; the constructor and destructor need only do
/// whatever book-keeping is needed for your specific implementation. In our case, we
/// just need to allocate/deallocate the space for our string:
///
/// @code
///    SimpleMessageEvent::SimpleMessageEvent(const char *message = NULL)
///    {
///       // If we wanted to make this not be a GuaranteedOrdered event, we'd
///       // put a line like this in the constructor:
///       // mGuaranteeType = Guaranteed;
///       // (or whatever type you wanted.)
///       if(message)
///          msg = dStrdup(message);
///       else
///          msg = NULL;
///    }
///
///    SimpleMessageEvent::~SimpleMessageEvent()
///    {
///      dFree(msg);
///    }
/// @endcode
///
/// Simple as that! Now, onto pack(), write(), unpack(), process().
///
/// <b>pack()</b> is responsible for packing the event over the wire:
///
/// @code
/// void SimpleMessageEvent::pack(NetConnection* conn, BitStream *bstream)
/// {
///   bstream->writeString(msg);
/// }
/// @endcode
///
/// <b>unpack()</b> is responsible for unpacking the event on the other end:
///
/// @code
/// // The networking layer takes care of instantiating a new
/// // SimpleMessageEvent, which saves us a bit of effort.
/// void SimpleMessageEvent::unpack(NetConnection *conn, BitStream *bstream)
/// {
///   char buf[256];
///   bstream->readString(buf);
///   msg = dStrdup(buf);
/// }
/// @endcode
///
/// <b>process()</b> is called when the network layer is finished with things.
/// A typical case is that a GuaranteedOrdered event is unpacked and stored, but
/// not processed until the events preceding it in the sequence have also been
/// dealt with.
///
/// @code
/// // This just prints the event in the console. You might
/// // want to do something more clever here -- BJG
/// void SimpleMessageEvent::process(NetConnection *conn)
/// {
///   Con::printf("RMSG %d  %s", mSourceId, msg);
/// }
/// @endcode
///
/// <b>write()</b> is called if a demo recording is started, and the event has not yet been
/// processed, but it has been unpacked. It should be identical in its output to the bitstream
/// compared to pack(), but since it is called after unpack() some lookups may not need to be
/// performed. In normal demo recording, whole network packets are recorded, meaning that most
/// of the time write() will not be called.
///
/// In our case, it's entirely identical to pack():
///
/// @code
/// virtual void write(NetConnection*, BitStream *bstream)
/// {
///   bstream->writeString(msg);
/// }
/// @endcode
///
/// The NetEvent is sent over the wire in a straightforward way (assuming you have a
/// handle to a NetConnection):
///
/// @code
/// NetConnection *conn; // We assume you have filled this in.
///
/// con->postNetEvent(new SimpleMessageEvent("This is a test!"));
/// @endcode
///
/// @see GhostAlwaysObjectEvent for an example of dissimilar write()/pack() methods.
///
/// Finally, for more advanced applications, notifySent() is called whenever the event is
/// sent over the wire, in NetConnection::eventWritePacket(). notifyDelivered() is called
/// when the packet is finally received or (in the case of Unguaranteed packets) dropped.
///
/// @note IMPLEMENT_CO_NETEVENT_V1 and co. have sibling macros which allow you to specify a
///       groupMask; see ConsoleObject for a further discussion of this.
//class NetEvent : public ConsoleObject
//{
//public:
//   /// @name Implementation Details
//   ///
//   /// These are internal fields which you won't need to manipulate, except for mGuaranteeType.
//   /// @{
//
//   ///
//   S32 mRefCount;
//   typedef ConsoleObject Parent;
//   enum {
//      GuaranteedOrdered = 0,
//      Guaranteed = 1,
//      Unguaranteed = 2
//   } mGuaranteeType;
//   NetConnectionId mSourceId;
//
//   void incRef()
//   {
//      mRefCount++;
//   }
//   void decRef()
//   {
//      mRefCount--;
//      if(!mRefCount)
//         delete this;
//   }
//
//#ifdef TORQUE_DEBUG_NET
//   virtual const char *getDebugName();
//#endif
//   /// @}
//
//   /// @name Things To Subclass
//   /// @{
//
//   ///
//   NetEvent() { mGuaranteeType = GuaranteedOrdered; mRefCount = 0; }
//   virtual ~NetEvent();
//
//   virtual void write(NetConnection *ps, BitStream *bstream) = 0;
//   virtual void pack(NetConnection *ps, BitStream *bstream) = 0;
//   virtual void unpack(NetConnection *ps, BitStream *bstream) = 0;
//   virtual void process(NetConnection *ps) = 0;
//   virtual void notifySent(NetConnection *ps);
//   virtual void notifyDelivered(NetConnection *ps, bool madeit);
//   /// @}
//};
//
//#define IMPLEMENT_CO_NETEVENT_V1(className)                    \
//   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
//   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
//   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
//   ConcreteClassRep<className> className::dynClassRep(#className,NetClassGroupGameMask, NetClassTypeEvent, NetEventDirAny, className::getParentStaticClassRep())
//
//#define IMPLEMENT_CO_CLIENTEVENT_V1(className)                    \
//   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
//   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
//   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
//   ConcreteClassRep<className> className::dynClassRep(#className,NetClassGroupGameMask, NetClassTypeEvent, NetEventDirServerToClient, className::getParentStaticClassRep())
//
//#define IMPLEMENT_CO_SERVEREVENT_V1(className)                    \
//   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
//   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
//   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
//   ConcreteClassRep<className> className::dynClassRep(#className,NetClassGroupGameMask, NetClassTypeEvent, NetEventDirClientToServer, className::getParentStaticClassRep())
//
//#define IMPLEMENT_CO_NETEVENT(className,groupMask)                    \
//   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
//   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
//   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
//   ConcreteClassRep<className> className::dynClassRep(#className,groupMask, NetClassTypeEvent, NetEventDirAny, className::getParentStaticClassRep())
//
//#define IMPLEMENT_CO_CLIENTEVENT(className,groupMask)                    \
//   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
//   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
//   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
//   ConcreteClassRep<className> className::dynClassRep(#className,groupMask, NetClassTypeEvent, NetEventDirServerToClient, className::getParentStaticClassRep())
//
//#define IMPLEMENT_CO_SERVEREVENT(className,groupMask)                    \
//   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
//   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
//   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
//   ConcreteClassRep<className> className::dynClassRep(#className,groupMask, NetClassTypeEvent, NetEventDirClientToServer, className::getParentStaticClassRep())


//----------------------------------------------------------------------------

/// Torque network connection.
///
/// @section NetConnection_intro Introduction
///
/// NetConnection is the glue that binds a networked Torque game together. It combines
/// the low-level notify protocol implemented in ConnectionProtocol with a SimGroup to
/// provide a powerful basis for implementing a multiplayer game protocol.
///
/// On top of this basis it implements several distinct subsystems:
///   - <b>Event manager</b>, which is responsible for 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 status.
///   - <b>Move manager</b>, which is responsible for transferring a Move to the server 32
///     times a second (on the client) and applying it to the control object (on the server).
///   - <b>Ghost manager</b>, which is responsible for doing scoping calculations (on the server
///     side) and transmitting most-recent ghost information to the client.
///   - <b>File transfer</b>; it is often the case that clients will lack important files when
///     connecting to a server which is running a mod or new map. This subsystem allows the
///     server to transfer such files to the client.
///   - <b>Networked String Table</b>; string data can easily soak up network bandwidth, so for
///     efficiency, we implement a networked string table. We can then notify the connection
///     of strings we will reference often, such as player names, and transmit only a tag,
///     instead of the whole string.
///   - <b>Demo Recording</b> is also implemented in NetConnection. A demo in Torque is a log
///     of the network traffic between client and server; when a NetConnection records a demo,
///     it simply logs this data to a file. When it plays a demo back, it replays the logged
///     data.
///   - The <b>Connection Database</b> is used to keep track of all the NetConnections; it can
///     be iterated over (for instance, to send an event to all active connections), or queried
///     by address.
///
/// @section NetConnection_events   On Events
///
/// The Event Manager is exposed to the outside world via postNetEvent(), which accepts NetEvents.
///
/// @see NetEvent for a more thorough explanation of how to use events.
///
/// @section NetConnection_ghosting On Ghosting and Scoping
///
/// Ghosting is the most complex, and most powerful, part of Torque's networking capabilities. It
/// allows the information sent to clients to be very precisely matched to what they need, so that
/// no excess bandwidth is wasted. The control object's onCameraScopeQuery() is called, to determine
/// scoping information for the client; then objects which are in scope are then transmitted to the
/// client, prioritized by the results of their getPriority() method.
///
/// There is a cap on the maximum number of ghosts; ghost IDs are currently sent via a 10-bit field,
/// ergo, there is a cap of 1024 objects ghosted per client. This can be easily raised; see the
/// GhostConstants enum.
///
/// Each object ghosted is assigned a ghost ID; the client is _only_ aware of the ghost ID. This acts
/// to enhance game security, as it becomes difficult to map objects from one connection to another, or
/// to reliably identify objects from ID alone. IDs are also reassigned based on need, making it hard
/// to track objects that have fallen out of scope (as any object which the player shouldn't see would).
///

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -