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

📄 ghostconnection.h

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

#ifndef _CONNECTIONGHOST_H_
#define _CONNECTIONGHOST_H_


#ifndef _CONNECTIONEVENT_H_
#include "EventConnection.h"
#endif


class NetObject;


//namespace CS
//{

class NetConnection;

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



class GhostConnection : public EventConnection
{
	friend class NetConnection;
   typedef EventConnection Parent;

public:
   /// Structure to track ghost references in packets.
   ///
   /// Every packet we send out with an update from a ghost causes one of these to be
   /// allocated. mask is used to track what states were sent; that way if a packet is
   /// dropped, we can easily manipulate the stored states and figure out what if any data
   /// we need to resend.
   ///
   //struct GhostRef
   //{
   //   U32 mask;                  ///< States we transmitted.
   //   U32 ghostInfoFlags;        ///< Flags from GhostInfo::Flags
   //   GhostInfo *ghost;          ///< Reference to the GhostInfo we're from.
   //   GhostRef *nextRef;         ///< Next GhostRef in this packet.
   //   GhostRef *nextUpdateChain; ///< Next update we sent for this ghost.
   //};



public:
   static void consoleInit();
   void onRemove();


   GhostConnection();
   ~GhostConnection();

	virtual void setRemoteConnectionObject(GhostConnection *connection) { mRemoteConnection = connection; Parent::setRemoteConnectionObject(connection);};
protected:
   SimObjectPtr<GhostConnection> mRemoteConnection;

protected:
   virtual void readPacket(BitStream *bstream);
   virtual void writePacket(BitStream *bstream, PacketNotify *note);
   virtual void packetReceived(PacketNotify *note);
   virtual void packetDropped(PacketNotify *note);
   //virtual void connectionError(const char *errorString);

   virtual void writeDemoStartBlock(ResizeBitStream *stream);
   virtual bool readDemoStartBlock(BitStream *stream);
   //virtual void demoPlaybackComplete();

public:


   void setGhostFrom(bool ghostFrom);     ///< Sets whether ghosts transmit from this side of the connection.
   void setGhostTo(bool ghostTo);         ///< Sets whether ghosts are allowed from the other side of the connection.

//----------------------------------------------------------------
/// @name Ghost manager
/// @{

protected:
   enum GhostStates
   {
		GhostAlwaysDone = Parent::NumConnectionMessages,
      ReadyForNormalGhosts,
      EndGhosting,
      GhostAlwaysStarting,
      NumConnectionMessages,
   };
   GhostInfo **mGhostArray;    ///< Linked list of ghostInfos ghosted by this side of the connection

   U32 mGhostZeroUpdateIndex;  ///< Index in mGhostArray of first ghost with 0 update mask.
   U32 mGhostFreeIndex;        ///< Index in mGhostArray of first free ghost.

   U32 mGhostsActive;			///- Track actve ghosts on client side

   bool mGhosting;             ///< Am I currently ghosting objects?
   bool mScoping;              ///< am I currently scoping objects?
   U32  mGhostingSequence;     ///< Sequence number describing this ghosting session.

   NetObject **mLocalGhosts;  ///< Local ghost for remote object.
                              ///
                              /// mLocalGhosts pointer is NULL if mGhostTo is false

   GhostInfo *mGhostRefs;           ///< Allocated array of ghostInfos. Null if ghostFrom is false.
   GhostInfo **mGhostLookupTable;   ///< Table indexed by object id to GhostInfo. Null if ghostFrom is false.

   /// The object around which we are scoping this connection.
   ///
   /// This is usually the player object, or a related object, like a vehicle
   /// that the player is driving.
   SimObjectPtr<NetObject> mScopeObject;

   void clearGhostInfo();
   bool validateGhostArray();

   void ghostPacketDropped(PacketNotify *notify);
   void ghostPacketReceived(PacketNotify *notify);

   void ghostWritePacket(BitStream *bstream, PacketNotify *notify);
   void ghostReadPacket(BitStream *bstream);
   void freeGhostInfo(GhostInfo *);

   void ghostWriteStartBlock(ResizeBitStream *stream);
   void ghostReadStartBlock(BitStream *stream);


   /// Called when we finish downloading file data.
   virtual void fileDownloadSegmentComplete();
   void loadNextGhostAlwaysObject(bool hadNewFiles);


public:
   /// Some configuration values.
   enum GhostConstants
   {
      GhostIdBitSize = 12,
      MaxGhostCount = 1 << GhostIdBitSize, //4096,
      GhostLookupTableSize = 1 << GhostIdBitSize, //4096
      GhostIndexBitSize = 4 // number of bits GhostIdBitSize-3 fits into
   };

   U32 getGhostsActive() { return mGhostsActive;};

   /// Are we ghosting to someone?
   bool isGhostingTo() { return mLocalGhosts != NULL; };

   /// Are we ghosting from someone?
   bool isGhostingFrom() { return mGhostArray != NULL; };

   /// Called by onRemove, to shut down the ghost subsystem.
   void ghostOnRemove();

   /// Called when we're done with normal scoping.
   ///
   /// This gives subclasses a chance to shove things into scope, such as
   /// the results of a sensor network calculation, that would otherwise
   /// be awkward to add.
   virtual void doneScopingScene() { /* null */ }

   /// Set the object around which we are currently scoping network traffic.
   void setScopeObject(NetObject *object);

   /// Get the object aorund which we are currently scoping network traffic.
   NetObject *getScopeObject();

   /// Add an object to scope.
   void objectInScope(NetObject *object);

   /// Add an object to scope, marking that it should always be scoped to this connection.
   void objectLocalScopeAlways(NetObject *object);

   /// Mark an object that is being ghosted as not always needing to be scoped.
   ///
   /// This undoes objectLocalScopeAlways(), but doesn't immediately flush it from scope.
   ///
   /// Instead, the standard scoping mechanisms will clear it from scope when it is appropos
   /// to do so.
   void objectLocalClearAlways(NetObject *object);

   /// Get a NetObject* from a ghost ID (on client side).
   NetObject *resolveGhost(S32 id);

   /// Get a NetObject* from a ghost index (on the server side).
   NetObject *resolveObjectFromGhostIndex(S32 id);

   /// Get the ghost index corresponding to a given NetObject. This is only
   /// meaningful on the server side.
   S32 getGhostIndex(NetObject *object);

   /// Move a GhostInfo into the nonzero portion of the list (so that we know to update it).
   void ghostPushNonZero(GhostInfo *gi);

   /// Move a GhostInfo into the zero portion of the list (so that we know not to update it).
   void ghostPushToZero(GhostInfo *gi);

   /// Move a GhostInfo from the zero portion of the list to the free portion.
   void ghostPushZeroToFree(GhostInfo *gi);

   /// Move a GhostInfo from the free portion of the list to the zero portion.
   inline void ghostPushFreeToZero(GhostInfo *info);

   /// Stop all ghosting activity and inform the other side about this.
   ///
   /// Turns off ghosting.
   void resetGhosting();

   /// Activate ghosting, once it's enabled.
   void activateGhosting();

   /// Are we ghosting?
   bool isGhosting() { return mGhosting; }

   /// Begin to stop ghosting an object.
   void detachObject(GhostInfo *info);

   /// Mark an object to be always ghosted. Index is the ghost index of the object.
   void setGhostAlwaysObject(NetObject *object, U32 index);


   /// Send ghost connection handshake message.
   ///
   /// As part of the ghoost connection process, extensive hand-shaking must be performed.
   ///
   /// This is done by passing ConnectionMessageEvents; this is a helper function
   /// to more effectively perform this task. Messages are dealt with by
   /// handleConnectionMessage().
   ///
   /// @param  message     One of GhostStates
   /// @param  sequence    A sequence number, if any.
   /// @param  ghostCount  A count of ghosts relating to this message.
   //void sendConnectionMessage(U32 message, U32 sequence = 0, U32 ghostCount = 0);

   /// Handle message from sendConnectionMessage().
   ///
   /// This is called to handle messages sent via sendConnectionMessage.
   ///
   /// @param  message     One of GhostStates
   /// @param  sequence    A sequence number, if any.
   /// @param  ghostCount  A count of ghosts relating to this message.
   virtual void handleConnectionMessage(U32 message, U32 sequence, U32 ghostCount);

   /// @}

};



//----------------------------------------------------------------------------
/// Information about a ghosted object.
///
/// @note If the size of this structure changes, the
///       GhostConnection::getGhostIndex function MUST be changed
///       to reflect the new size.
struct GhostInfo
{
public:  // required for MSVC
   NetObject *obj;                        ///< The object being ghosted.
   U32 updateMask;                        ///< Flags indicating what state data needs to be transferred.

   U32 updateSkipCount;                   ///< How many updates have we skipped this guy?
   U32 flags;                             ///< Flags from GhostInfo::Flags
   F32 priority;                          ///< A float value indicating the priority of this object for
                                          ///  updates.

   /// @name References
   ///
   /// The GhostInfo structure is used in several linked lists; these members are
   /// the implementation for this.
   /// @{

   GhostConnection::GhostRef *updateChain;  ///< List of references in NetConnections to us.

   GhostInfo *nextObjectRef;              ///< Next ghosted object.
   GhostInfo *prevObjectRef;              ///< Previous ghosted object.
   NetConnection *connection;             ///< Connection that we're ghosting over.
   GhostInfo *nextLookupInfo;             ///< GhostInfo references are stored in a hash; this is the bucket
                                          ///  implementation.

   /// @}

   U32 index;
   U32 arrayIndex;

   /// Flags relating to the state of the object.
   enum Flags
   {
      Valid             = BIT(0),
      InScope           = BIT(1),
      ScopeAlways       = BIT(2),
      NotYetGhosted     = BIT(3),
      Ghosting          = BIT(4),
      KillGhost         = BIT(5),
      KillingGhost      = BIT(6),
      ScopedEvent       = BIT(7),
      ScopeLocalAlways  = BIT(8),
   };
};




///////////////////////////////////////////////////////////////////////////////
//

inline void GhostConnection::ghostPushNonZero(GhostInfo *info)
{
   AssertFatal(info->arrayIndex >= mGhostZeroUpdateIndex && info->arrayIndex < mGhostFreeIndex, "Out of range arrayIndex.");
   AssertFatal(mGhostArray[info->arrayIndex] == info, "Invalid array object.");
   if(info->arrayIndex != mGhostZeroUpdateIndex)
   {
      mGhostArray[mGhostZeroUpdateIndex]->arrayIndex = info->arrayIndex;
      mGhostArray[info->arrayIndex] = mGhostArray[mGhostZeroUpdateIndex];
      mGhostArray[mGhostZeroUpdateIndex] = info;
      info->arrayIndex = mGhostZeroUpdateIndex;
   }
   mGhostZeroUpdateIndex++;
   //AssertFatal(validateGhostArray(), "Invalid ghost array!");
}

inline void GhostConnection::ghostPushToZero(GhostInfo *info)
{
   AssertFatal(info->arrayIndex < mGhostZeroUpdateIndex, "Out of range arrayIndex.");
   AssertFatal(mGhostArray[info->arrayIndex] == info, "Invalid array object.");
   mGhostZeroUpdateIndex--;
   if(info->arrayIndex != mGhostZeroUpdateIndex)
   {
      mGhostArray[mGhostZeroUpdateIndex]->arrayIndex = info->arrayIndex;
      mGhostArray[info->arrayIndex] = mGhostArray[mGhostZeroUpdateIndex];
      mGhostArray[mGhostZeroUpdateIndex] = info;
      info->arrayIndex = mGhostZeroUpdateIndex;
   }
   //AssertFatal(validateGhostArray(), "Invalid ghost array!");
}

inline void GhostConnection::ghostPushZeroToFree(GhostInfo *info)
{
   AssertFatal(info->arrayIndex >= mGhostZeroUpdateIndex && info->arrayIndex < mGhostFreeIndex, "Out of range arrayIndex.");
   AssertFatal(mGhostArray[info->arrayIndex] == info, "Invalid array object.");
   mGhostFreeIndex--;
   if(info->arrayIndex != mGhostFreeIndex)
   {
      mGhostArray[mGhostFreeIndex]->arrayIndex = info->arrayIndex;
      mGhostArray[info->arrayIndex] = mGhostArray[mGhostFreeIndex];
      mGhostArray[mGhostFreeIndex] = info;
      info->arrayIndex = mGhostFreeIndex;
   }
   //AssertFatal(validateGhostArray(), "Invalid ghost array!");
}

inline void GhostConnection::ghostPushFreeToZero(GhostInfo *info)
{
   AssertFatal(info->arrayIndex >= mGhostFreeIndex, "Out of range arrayIndex.");
   AssertFatal(mGhostArray[info->arrayIndex] == info, "Invalid array object.");
   if(info->arrayIndex != mGhostFreeIndex)
   {
      mGhostArray[mGhostFreeIndex]->arrayIndex = info->arrayIndex;
      mGhostArray[info->arrayIndex] = mGhostArray[mGhostFreeIndex];
      mGhostArray[mGhostFreeIndex] = info;
      info->arrayIndex = mGhostFreeIndex;
   }
   mGhostFreeIndex++;
   //AssertFatal(validateGhostArray(), "Invalid ghost array!");
}

//};//namespace CS
#endif


⌨️ 快捷键说明

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