📄 netconnection.h
字号:
//-----------------------------------------------------------------------------
// 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 + -