游戏架构其二:游戏通信

10 篇文章 0 订阅

游戏通信主要是对各种事件进行整合,统一处理。

I. 事件的定义:

// EventManager.h
#pragma once

#include <strstream>
#include <memory>
#include "templates.h"
#include "CriticalSection.h"
#include "FastDelegate.h"
#include "MemoryWatcher.h"
using namespace std::shared_ptr;

//---------------------------------------------------------------------------------------------
// Forward declaration & typedefs
//---------------------------------------------------------------------------------------------
class IEventData;

typedef unsigned long EventType;
typedef shared_ptr<IEventData> IEventDataPtr;
typedef fastdelegate::FastDelegate1<IEventDataPtr> EventListenerDelegate;
typedef concurrent_queue<IEventDataPtr> ThreadSafeEventQueue;


//---------------------------------------------------------------------------------------------
// Macro for event registration
//---------------------------------------------------------------------------------------------
extern GenericObjectFactory<IEventData, EventType> g_eventFactory;
#define REGISTER_EVENT(eventClass) g_eventFactory.Register<eventClass>(eventClass::sk_EventType)
#define CREATE_EVENT(eventType) g_eventFactory.Create(eventType)


//---------------------------------------------------------------------------------------------
// IEventData
// Base type for event object hierarchy, may be used itself for simplest event notifications such as those that do not carry additional payload data. If any event needs to propagate with payload data it must be defined separately.
//---------------------------------------------------------------------------------------------
class IEventData
{
public:
	virtual ~IEventData(void) {}
	virtual const EventType& VGetEventType(void) const = 0;
	virtual float GetTimeStamp(void) const = 0;
	virtual void VSerialize(std::ostrstream& out) const = 0;
    virtual void VDeserialize(std::istrstream& in) = 0;
	virtual IEventDataPtr VCopy(void) const = 0;
    virtual const char* GetName(void) const = 0;
};


//---------------------------------------------------------------------------------------------
// class BaseEventData  序列化和反序列化网络的输出输入
//---------------------------------------------------------------------------------------------
class BaseEventData : public IEventData
{
    const float m_timeStamp;

public:
	explicit BaseEventData(const float timeStamp = 0.0f) : m_timeStamp(timeStamp) { }

	// Returns the type of the event
	virtual const EventType& VGetEventType(void) const = 0;

	float GetTimeStamp(void) const { return m_timeStamp; }

	// Serializing for network input / output
	virtual void VSerialize(std::ostrstream &out) const	{ }
    virtual void VDeserialize(std::istrstream& in) { }
};


//---------------------------------------------------------------------------------------------
// IEventManager Description    事件管理者:事件的注册和相应
//
// This is the object which maintains the list of registered events and their listeners.
//
// This is a many-to-many relationship, as both one listener can be configured to process multiple event types and 
// of course multiple listeners can be registered to each event type.
//
// The interface to this construct uses smart pointer wrapped objects, the purpose being to ensure that no object 
// that the registry is referring to is destroyed before it is removed from the registry AND to allow for the registry 
// to be the only place where this list is kept ... the application code does not need to maintain a second list.
//
// Simply tearing down the registry (e.g.: destroying it) will automatically clean up all pointed-to objects (so long 
// as there are no other outstanding references, of course).
//---------------------------------------------------------------------------------------------
class IEventManager
{
public:

	enum eConstants { kINFINITE = 0xffffffff };

	explicit IEventManager(const char* pName, bool setAsGlobal);
	virtual ~IEventManager(void);
    //当这个class无子类继承时 不建议使用virtual 否则会减慢析构速度
    // 当有子类时必须使用virtual否则会导致父类析构不完整

    // Registers a delegate function that will get called when the event type is triggered.  Returns true if successful, false if not.
    virtual bool VAddListener(const EventListenerDelegate& eventDelegate, const EventType& type) = 0;

	// Removes a delegate / event type pairing from the internal tables.  Returns false if the pairing was not found.
	virtual bool VRemoveListener(const EventListenerDelegate& eventDelegate, const EventType& type) = 0;

	// Fire off event NOW.  This bypasses the queue entirely and immediately calls all delegate functions registered for the event.
	virtual bool VTriggerEvent(const IEventDataPtr& pEvent) const = 0;

	// Fire off event.  This uses the queue and will call the delegate function on the next call to VTick(), assuming there's enough time.
	virtual bool VQueueEvent(const IEventDataPtr& pEvent) = 0;
	virtual bool VThreadSafeQueueEvent(const IEventDataPtr& pEvent) = 0;

	// Find the next-available instance of the named event type and remove it from the processing queue.  This may be done up to the point that it is actively being processed ...  e.g.: is safe to happen during event processing itself.
	// if allOfType is true, then all events of that type are cleared from the input queue. returns true if the event was found and removed, false otherwise
	virtual bool VAbortEvent(const EventType& type, bool allOfType = false) = 0;

	// Allow for processing of any queued messages, optionally specify a processing time limit so that the event  processing does not take too long. Note the danger of using this artificial limiter is that all messages may not in fact get processed.
	// returns true if all messages ready for processing were completed, false otherwise (e.g. timeout )
	virtual bool VUpdate(unsigned long maxMillis = kINFINITE) = 0;

    // Getter for the main global event manager.  This is the event manager that is used by the majority of the  engine, though you are free to define your own as long as you instantiate it with setAsGlobal set to false.
    // It is not valid to have more than one global event manager.
	static IEventManager* Get(void);
};
 以上是对事件的定义,下面是实现:

#include "GameCodeStd.h"
#include "EventManager.h"
#include <assert.h>


static IEventManager* g_pEventMgr = NULL;
GenericObjectFactory<IEventData, EventType> g_eventFactory;

IEventManager* IEventManager::Get(void)
{
    assert(g_pEventMgr);
	return g_pEventMgr;
}

IEventManager::IEventManager(const char* pName, bool setAsGlobal)
{
	if (setAsGlobal)
    {
        if (g_pEventMgr)
        {
            assert("Attempting to create two global event managers! The old one will be destroyed and overwritten with this one.");
            delete g_pEventMgr;
        }

		g_pEventMgr = this;
    }
}

IEventManager::~IEventManager(void)
{
	if (g_pEventMgr == this)
		g_pEventMgr = NULL;
}

以上是对事件管理实现的基本实现,下面是对整个事件进行统筹规划与全局管理:

II. 事件管理的核心类:

// EventManagerImpl 事件管理实现
#pragma once

#include "EventManager.h"
#include <list>
#include <map>
namespace std {
    using std::map;
    using std::list;
};

const unsigned int EVENTMANAGER_NUM_QUEUES = 2;

class EventManager : public IEventManager
{
private:
    typedef std::list<EventListenerDelegate> EventListenerList;
    typedef std::map<EventType, EventListenerList> EventListenerMap;
    typedef std::list<IEventDataPtr> EventQueue;

    EventListenerMap m_eventListeners;
    EventQueue m_queues[EVENTMANAGER_NUM_QUEUES];
    int m_activeQueue;  // index of actively processing queue; events enque to the opposing queue

    ThreadSafeEventQueue m_realtimeEventQueue;

public:
	explicit EventManager(const char* pName, bool setAsGlobal);
	virtual ~EventManager(void);

    virtual bool VAddListener(const EventListenerDelegate& eventDelegate, const EventType& type);
    virtual bool VRemoveListener(const EventListenerDelegate& eventDelegate, const EventType& type);

    virtual bool VTriggerEvent(const IEventDataPtr& pEvent) const;
    virtual bool VQueueEvent(const IEventDataPtr& pEvent);
    virtual bool VThreadSafeQueueEvent(const IEventDataPtr& pEvent);
    virtual bool VAbortEvent(const EventType& type, bool allOfType = false);

    virtual bool VUpdate(unsigned long maxMillis = kINFINITE);
};
#include "GameCodeStd.h"
#include "EventManagerImpl.h"
#include "String.h"
#include "EventManager.h"

//----------------------------------------------------------------------------------------------
// EventManager::EventManager
//----------------------------------------------------------------------------------------------
EventManager::EventManager(const char* pName, bool setAsGlobal)
	: IEventManager(pName, setAsGlobal)
{
    m_activeQueue = 0;
}

//-----------------------------------------------------------------------------------------------
// EventManager::~EventManager
//-----------------------------------------------------------------------------------------------
EventManager::~EventManager(void)
{
}

//----------------------------------------------------------------------------------------------
// EventManager::VAddListener 为EventType类型添加代理 当EventType类型事件被触发时delegate function会执行
//----------------------------------------------------------------------------------------------
bool EventManager::VAddListener(const EventListenerDelegate& eventDelegate, const EventType& type)
{
    GCC_LOG("Events", "Attempting to add delegate function for event type: " + ToStr(type, 16));

    EventListenerList& eventListenerList = m_eventListeners[type];  // this will find or create the entry
    for (auto it = eventListenerList.begin(); it != eventListenerList.end(); ++it)
    {
        if (eventDelegate == (*it))
        {
            GCC_WARNING("Attempting to double-register a delegate");
            return false;
        }
    }

    eventListenerList.push_back(eventDelegate);
    GCC_LOG("Events", "Successfully added delegate for event type: " + ToStr(type, 16));

	return true;
}

//----------------------------------------------------------------------------------------------
// EventManager::VRemoveListener 删除一对 delegate/eventtype
//----------------------------------------------------------------------------------------------
bool EventManager::VRemoveListener(const EventListenerDelegate& eventDelegate, const EventType& type)
{
    GCC_LOG("Events", "Attempting to remove delegate function from event type: " + ToStr(type, 16));
	bool success = false;

    auto findIt = m_eventListeners.find(type);
    if (findIt != m_eventListeners.end())
    {
        EventListenerList& listeners = findIt->second;
        for (auto it = listeners.begin(); it != listeners.end(); ++it)
        {
            if (eventDelegate == (*it))
            {
                listeners.erase(it);
                GCC_LOG("Events", "Successfully removed delegate function from event type: " + ToStr(type, 16));
                success = true;
                break;  // we don't need to continue because it should be impossible for the same delegate function to be registered for the same event more than once
            }
        }
    }

    return success;
}

//----------------------------------------------------------------------------------------------
// EventManager::VTrigger 从现在起一个接一个的执行实行注册时的代理
//----------------------------------------------------------------------------------------------
bool EventManager::VTriggerEvent(const IEventDataPtr& pEvent) const
{
    GCC_LOG("Events", "Attempting to trigger event " + std::string(pEvent->GetName()));
    bool processed = false;

    auto findIt = m_eventListeners.find(pEvent->VGetEventType());
	if (findIt != m_eventListeners.end())
    {
	    const EventListenerList& eventListenerList = findIt->second;
	    for (EventListenerList::const_iterator it = eventListenerList.begin(); it != eventListenerList.end(); ++it)
	    {
		    EventListenerDelegate listener = (*it);
            GCC_LOG("Events", "Sending Event " + std::string(pEvent->GetName()) + " to delegate.");
		    listener(pEvent);  // call the delegate
            processed = true;
	    }
    }
	
	return processed;
}

//----------------------------------------------------------------------------------------------
// EventManager::VQueueEvent
//----------------------------------------------------------------------------------------------
bool EventManager::VQueueEvent(const IEventDataPtr& pEvent)
{
	GCC_ASSERT(m_activeQueue >= 0);
	GCC_ASSERT(m_activeQueue < EVENTMANAGER_NUM_QUEUES);

    // make sure the event is valid
    if (!pEvent)
    {
        GCC_ERROR("Invalid event in VQueueEvent()");
        return false;
    }

    GCC_LOG("Events", "Attempting to queue event: " + std::string(pEvent->GetName()));

	auto findIt = m_eventListeners.find(pEvent->VGetEventType());
    if (findIt != m_eventListeners.end())
    {
        m_queues[m_activeQueue].push_back(pEvent);
        GCC_LOG("Events", "Successfully queued event: " + std::string(pEvent->GetName()));
        return true;
    }
    else
    {
        GCC_LOG("Events", "Skipping event since there are no delegates registered to receive it: " + std::string(pEvent->GetName()));
        return false;
    }
}

//----------------------------------------------------------------------------------------------
// EventManager::VThreadSafeQueueEvent 供每次update使用
//----------------------------------------------------------------------------------------------
bool EventManager::VThreadSafeQueueEvent(const IEventDataPtr& pEvent)
{
	m_realtimeEventQueue.push(pEvent);
	return true;
}

//----------------------------------------------------------------------------------------------
// EventManager::VAbortEvent 放弃这类事情 是否成功返回
//----------------------------------------------------------------------------------------------
bool EventManager::VAbortEvent(const EventType& inType, bool allOfType)
{
	GCC_ASSERT(m_activeQueue >= 0);
	GCC_ASSERT(m_activeQueue < EVENTMANAGER_NUM_QUEUES);

    bool success = false;
	EventListenerMap::iterator findIt = m_eventListeners.find(inType);

	if (findIt != m_eventListeners.end())
    {
        EventQueue& eventQueue = m_queues[m_activeQueue];
        auto it = eventQueue.begin();
        while (it != eventQueue.end())
        {
            // Removing an item from the queue will invalidate the iterator, so have it point to the next member.  All
            // work inside this loop will be done using thisIt.
            auto thisIt = it;
            ++it;

	        if ((*thisIt)->VGetEventType() == inType)
	        {
		        eventQueue.erase(thisIt);
		        success = true;
		        if (!allOfType)
			        break;
	        }
        }
    }

	return success;
}

//----------------------------------------------------------------------------------------------
// EventManager::VTick 每帧执行一次
//----------------------------------------------------------------------------------------------
bool EventManager::VUpdate(unsigned long maxMillis)
{
	unsigned long currMs = GetTickCount();
	unsigned long maxMs = ((maxMillis == IEventManager::kINFINITE) ? (IEventManager::kINFINITE) : (currMs + maxMillis));

	// This section added to handle events from other threads.  Check out Chapter 20.
	IEventDataPtr pRealtimeEvent;
	while (m_realtimeEventQueue.try_pop(pRealtimeEvent))
	{
		VQueueEvent(pRealtimeEvent);

		currMs = GetTickCount();
		if (maxMillis != IEventManager::kINFINITE)
		{
			if (currMs >= maxMs)
			{
				GCC_ERROR("A realtime process is spamming the event manager!");
			}
		}
	}

	// swap active queues and clear the new queue after the swap
    int queueToProcess = m_activeQueue;
	m_activeQueue = (m_activeQueue + 1) % EVENTMANAGER_NUM_QUEUES;
	m_queues[m_activeQueue].clear();

    GCC_LOG("EventLoop", "Processing Event Queue " + ToStr(queueToProcess) + "; " + ToStr((unsigned long)m_queues[queueToProcess].size()) + " events to process");

	// Process the queue
	while (!m_queues[queueToProcess].empty())
	{
        // pop the front of the queue
		IEventDataPtr pEvent = m_queues[queueToProcess].front();
        m_queues[queueToProcess].pop_front();
        GCC_LOG("EventLoop", "\t\tProcessing Event " + std::string(pEvent->GetName()));

		const EventType& eventType = pEvent->VGetEventType();

        // find all the delegate functions registered for this event
		auto findIt = m_eventListeners.find(eventType);
		if (findIt != m_eventListeners.end())
		{
			const EventListenerList& eventListeners = findIt->second;
            GCC_LOG("EventLoop", "\t\tFound " + ToStr((unsigned long)eventListeners.size()) + " delegates");

            // call each listener
			for (auto it = eventListeners.begin(); it != eventListeners.end(); ++it)
			{
                EventListenerDelegate listener = (*it);
                GCC_LOG("EventLoop", "\t\tSending event " + std::string(pEvent->GetName()) + " to delegate");
				listener(pEvent);
			}
		}

        // check to see if time ran out
		currMs = GetTickCount();
		if (maxMillis != IEventManager::kINFINITE && currMs >= maxMs)
        {
            GCC_LOG("EventLoop", "Aborting event processing; time ran out");
			break;
        }
	}
	
	// If we couldn't process all of the events, push the remaining events to the new active queue.
	// Note: To preserve sequencing, go back-to-front, inserting them at the head of the active queue
	bool queueFlushed = (m_queues[queueToProcess].empty());
	if (!queueFlushed)
	{
		while (!m_queues[queueToProcess].empty())
		{
			IEventDataPtr pEvent = m_queues[queueToProcess].back();
			m_queues[queueToProcess].pop_back();
			m_queues[m_activeQueue].push_front(pEvent);
		}
	}
	
	return queueFlushed;
}

上面的类名以I开头表示与Interface相关的类.

III. 以下是游戏中经常使用到的各种事件,它们出现在游戏的各个角落

#pragma once

#include "EventManager.h"

typedef unsigned int ActorId;
typedef unsigned int GameViewId;

void RegisterEngineScriptEvents(void);


//----------------------------------------------------------------------------------------------
// EvtData_New_Actor - This event is sent out when an actor is *actually* created.
// 当一个新的actor被创建时 这个事件将被触发
//----------------------------------------------------------------------------------------------
class EvtData_New_Actor : public BaseEventData
{
	ActorId m_actorId;
    GameViewId m_viewId;

public:
	static const EventType sk_EventType;

	EvtData_New_Actor(void) 
	{
		m_actorId = INVALID_ACTOR_ID;
		m_viewId = gc_InvalidGameViewId;
	}

    explicit EvtData_New_Actor(ActorId actorId, GameViewId viewId = gc_InvalidGameViewId) 
        : m_actorId(actorId),
          m_viewId(viewId)
	{
	}

    virtual void VDeserialize(std::istrstream& in)
    {
        in >> m_actorId;
		in >> m_viewId;
    }

	virtual const EventType& VGetEventType(void) const
	{
		return sk_EventType;
	}

	virtual IEventDataPtr VCopy(void) const
	{
		return IEventDataPtr(GCC_NEW EvtData_New_Actor(m_actorId, m_viewId));
	}

	virtual void VSerialize(std::ostrstream& out) const
	{
		out << m_actorId << " ";
		out << m_viewId << " ";
	}


    virtual const char* GetName(void) const
    {
        return "EvtData_New_Actor";
    }

	const ActorId GetActorId(void) const
	{
		return m_actorId;
	}

    GameViewId GetViewId(void) const
    {
        return m_viewId;
    }
};


//----------------------------------------------------------------------------------------------
// EvtData_Destroy_Actor - sent when actors are destroyed
// 当一个动作被销毁时 触发这个动作
//----------------------------------------------------------------------------------------------
class EvtData_Destroy_Actor : public BaseEventData
{
    ActorId m_id;

public:
	static const EventType sk_EventType;

    explicit EvtData_Destroy_Actor(ActorId id = INVALID_ACTOR_ID)
        : m_id(id)
    {
        //
    }

	virtual const EventType& VGetEventType(void) const
	{
		return sk_EventType;
	}

	virtual IEventDataPtr VCopy(void) const
	{
		return IEventDataPtr ( GCC_NEW EvtData_Destroy_Actor ( m_id ) );
	}

	virtual void VSerialize(std::ostrstream &out) const
	{
		out << m_id;
	}

    virtual void VDeserialize(std::istrstream& in)
    {
        in >> m_id;
    }

    virtual const char* GetName(void) const
    {
        return "EvtData_Destroy_Actor";
    }

    ActorId GetId(void) const { return m_id; }
};


//----------------------------------------------------------------------------------------------
// EvtData_Move_Actor - sent when actors are moved
//----------------------------------------------------------------------------------------------
class EvtData_Move_Actor : public BaseEventData
{
    ActorId m_id;
    Mat4x4 m_matrix;

public:
	static const EventType sk_EventType;

	virtual const EventType& VGetEventType(void) const
	{
		return sk_EventType;
	}

    EvtData_Move_Actor(void)
    {
        m_id = INVALID_ACTOR_ID;
    }

	EvtData_Move_Actor(ActorId id, const Mat4x4& matrix)
        : m_id(id), m_matrix(matrix)
	{
        //
	}

	virtual void VSerialize(std::ostrstream &out) const
	{
		out << m_id << " ";
		for (int i=0; i<4; ++i)
		{
			for (int j=0; j<4; ++j)
			{
				out << m_matrix.m[i][j] << " ";
			}
		}
	}

    virtual void VDeserialize(std::istrstream& in)
    {
        in >> m_id;
        for (int i=0; i<4; ++i)
        {
            for (int j=0; j<4; ++j)
            {
                in >> m_matrix.m[i][j];
            }
        }
    }

	virtual IEventDataPtr VCopy() const
	{
		return IEventDataPtr(new EvtData_Move_Actor(m_id, m_matrix));
	}

    virtual const char* GetName(void) const
    {
        return "EvtData_Move_Actor";
    }

    ActorId GetId(void) const
    {
        return m_id;
    }

    const Mat4x4& GetMatrix(void) const
    {
        return m_matrix;
    }
};


//----------------------------------------------------------------------------------------------
// EvtData_New_Render_Component - This event is sent out when an actor is *actually* created.
//----------------------------------------------------------------------------------------------
class EvtData_New_Render_Component : public BaseEventData
{
    ActorId m_actorId;
    shared_ptr<SceneNode> m_pSceneNode;

public:
    static const EventType sk_EventType;

    EvtData_New_Render_Component(void) 
    {
        m_actorId = INVALID_ACTOR_ID;
    }

    explicit EvtData_New_Render_Component(ActorId actorId, shared_ptr<SceneNode> pSceneNode) 
        : m_actorId(actorId),
          m_pSceneNode(pSceneNode)
    {
    }

    virtual void VSerialize(std::ostrstream& out) const
    {
        GCC_ERROR(GetName() + std::string(" should not be serialzied!"));
    }

    virtual void VDeserialize(std::istrstream& in)
    {
        GCC_ERROR(GetName() + std::string(" should not be serialzied!"));
    }

    virtual const EventType& VGetEventType(void) const
    {
        return sk_EventType;
    }

    virtual IEventDataPtr VCopy(void) const
    {
        return IEventDataPtr(GCC_NEW EvtData_New_Render_Component(m_actorId, m_pSceneNode));
    }

    virtual const char* GetName(void) const
    {
        return "EvtData_New_Render_Component";
    }

    const ActorId GetActorId(void) const
    {
        return m_actorId;
    }

    shared_ptr<SceneNode> GetSceneNode(void) const
    {
        return m_pSceneNode;
    }
};


//---------------------------------------------------------------------------------------------------------------------
// EvtData_Modified_Render_Component - This event is sent out when a render component is changed
//   NOTE: This class is not described in the book!
//---------------------------------------------------------------------------------------------------------------------
class EvtData_Modified_Render_Component : public BaseEventData
{
    ActorId m_id;

public:
	static const EventType sk_EventType;

	virtual const EventType& VGetEventType(void) const
	{
		return sk_EventType;
	}

    EvtData_Modified_Render_Component(void)
    {
        m_id = INVALID_ACTOR_ID;
    }

	EvtData_Modified_Render_Component(ActorId id)
        : m_id(id)
	{
	}

	virtual void VSerialize(std::ostrstream &out) const
	{
		out << m_id;
	}

    virtual void VDeserialize(std::istrstream& in)
    {
        in >> m_id;
    }

	virtual IEventDataPtr VCopy() const
	{
		return IEventDataPtr(GCC_NEW EvtData_Modified_Render_Component(m_id));
	}

    virtual const char* GetName(void) const
    {
        return "EvtData_Modified_Render_Component";
    }

    ActorId GetActorId(void) const
    {
        return m_id;
    }
};



//---------------------------------------------------------------------------------------------------------------------
// EvtData_Environment_Loaded - this event is sent when a new game is started
//---------------------------------------------------------------------------------------------------------------------
class EvtData_Environment_Loaded : public BaseEventData
{
public:
	static const EventType sk_EventType;

    EvtData_Environment_Loaded(void) { }
	virtual const EventType& VGetEventType(void) const	{ return sk_EventType; }
	virtual IEventDataPtr VCopy(void) const
		{ return IEventDataPtr( GCC_NEW EvtData_Environment_Loaded( ) ); }
    virtual const char* GetName(void) const  { return "EvtData_Environment_Loaded";  }
};


//---------------------------------------------------------------------------------------------------------------------
// EvtData_Environment_Loaded - this event is sent when a client has loaded its environment
//   This is special because we only want this event to go from client to server, and stop there. The
//   EvtData_Environment_Loaded is received by server and proxy logics alike. Thy to do this with just the above 
//   event and you'll get into an endless loop of the EvtData_Environment_Loaded event making infinite round trips
//   from client to server.
//
// FUTURE_WORK: It would be an interesting idea to add a "Private" type of event that is addressed only to a specific 
//              listener. Of course, that might be a really dumb idea too - someone will have to try it!
//---------------------------------------------------------------------------------------------------------------------
class EvtData_Remote_Environment_Loaded : public BaseEventData
{
public:
	static const EventType sk_EventType;

    EvtData_Remote_Environment_Loaded(void) { }
	virtual const EventType& VGetEventType(void) const	{ return sk_EventType; }
	virtual IEventDataPtr VCopy(void) const
		{ return IEventDataPtr( GCC_NEW EvtData_Remote_Environment_Loaded( ) ); }
    virtual const char* GetName(void) const  { return "EvtData_Remote_Environment_Loaded";  }
};


//----------------------------------------------------------------------------------------------
// EvtData_Request_Start_Game - this is sent by the authoritative game logic to all views so they will load a game level.
//----------------------------------------------------------------------------------------------
class EvtData_Request_Start_Game : public BaseEventData
{

public:
	static const EventType sk_EventType;

    EvtData_Request_Start_Game(void) { }

	virtual const EventType& VGetEventType(void) const
	{
		return sk_EventType;
	}

	virtual IEventDataPtr VCopy() const
	{
		return IEventDataPtr( GCC_NEW EvtData_Request_Start_Game( ) );
	}

    virtual const char* GetName(void) const
    {
        return "EvtData_Request_Start_Game";
    }
};


/**** HOLY CRAP THIS ISN"T USED ANYMORE????
//---------------------------------------------------------------------------------------------------------------------
// EvtData_Game_State - sent whenever the game state is changed (look for "BGS_" to see the different states)
//---------------------------------------------------------------------------------------------------------------------
class EvtData_Game_State : public BaseEventData
{
    BaseGameState m_gameState;
	std::string m_parameter;

public:
	static const EventType sk_EventType;

	EvtData_Game_State(void)
    {
        m_gameState = BGS_Invalid;
    }
    
    explicit EvtData_Game_State(const BaseGameState gameState, const std::string ¶meter)
		: m_gameState(gameState), m_parameter(parameter)
	{
	}

    virtual const EventType & VGetEventType( void ) const
    {
        return sk_EventType;
    }

	virtual IEventDataPtr VCopy() const
	{
		return IEventDataPtr( GCC_NEW EvtData_Game_State( m_gameState, m_parameter ) );
	}

	virtual void VSerialize(std::ostrstream &out) const
	{
		const int tempVal = static_cast< int >( m_gameState );
		out << tempVal << " ";
		out << m_parameter;
	}

    virtual void VDeserialize(std::istrstream &in)
    {
        int tempVal;
        in >> tempVal;
        m_gameState = static_cast<BaseGameState>( tempVal );
		in >> m_parameter;
    }

    virtual const char* GetName(void) const
    {
        return "EvtData_Game_State";
    }

    BaseGameState GetGameState(void) const
    {
        return m_gameState;
    }

	const std::string GetParameter(void) const 
	{
		return m_parameter;
	}
};
**********************/


//----------------------------------------------------------------------------------------------
// EvtData_Remote_Client
// 
// Sent whenever a new client attaches to a game logic acting as a server
//----------------------------------------------------------------------------------------------
class EvtData_Remote_Client : public BaseEventData
{
    int m_socketId;
    int m_ipAddress;

public:
	static const EventType sk_EventType;

    EvtData_Remote_Client(void)
    {
        m_socketId = 0;
        m_ipAddress = 0;
    }

	EvtData_Remote_Client( const int socketid, const int ipaddress )
		: m_socketId( socketid ), m_ipAddress(ipaddress)
	{
	}

    virtual const EventType & VGetEventType( void ) const
    {
        return sk_EventType;
    }

	virtual IEventDataPtr VCopy() const
	{
		return IEventDataPtr( GCC_NEW EvtData_Remote_Client( m_socketId, m_ipAddress ) );
	}

    virtual const char* GetName(void) const
    {
        return "EvtData_Remote_Client";
    }

	virtual void VSerialize(std::ostrstream &out) const
	{
		out << m_socketId << " ";
		out << m_ipAddress;
	}

    virtual void VDeserialize( std::istrstream &in )
    {
        in >> m_socketId;
        in >> m_ipAddress;
    }

    int GetSocketId(void) const
    {
        return m_socketId;
    }

    int GetIpAddress(void) const
    {
        return m_ipAddress;
    }
};


//----------------------------------------------------------------------------------------------
// EvtData_Update_Tick - sent by the game logic each game tick
//----------------------------------------------------------------------------------------------
class EvtData_Update_Tick : public BaseEventData
{
    int m_DeltaMilliseconds;

public:
	static const EventType sk_EventType;

    explicit EvtData_Update_Tick( const int deltaMilliseconds )
        : m_DeltaMilliseconds( deltaMilliseconds )
    {
    }

	virtual const EventType& VGetEventType( void ) const
	{
		return sk_EventType;
	}

	virtual IEventDataPtr VCopy() const
	{
		return IEventDataPtr (GCC_NEW EvtData_Update_Tick ( m_DeltaMilliseconds ) );
	}

	virtual void VSerialize( std::ostrstream & out )
	{
		GCC_ERROR("You should not be serializing update ticks!");
	}

    virtual const char* GetName(void) const
    {
        return "EvtData_Update_Tick";
    }
};


//----------------------------------------------------------------------------------------------
// EvtData_Network_Player_Actor_Assignment - sent by the server to the clients when a network view is assigned a player number
//----------------------------------------------------------------------------------------------
class EvtData_Network_Player_Actor_Assignment : public BaseEventData
{
    ActorId m_ActorId;
    int m_SocketId;

public:
	static const EventType sk_EventType;

	EvtData_Network_Player_Actor_Assignment()
	{
		m_ActorId = INVALID_ACTOR_ID;
		m_SocketId = -1;
	}

    explicit EvtData_Network_Player_Actor_Assignment( const ActorId actorId, const int socketId )
        : m_ActorId( actorId ), m_SocketId(socketId)

    {
    }

	virtual const EventType & VGetEventType( void ) const
	{
		return sk_EventType;
	}

	virtual IEventDataPtr VCopy() const
	{
		 return IEventDataPtr( GCC_NEW EvtData_Network_Player_Actor_Assignment( m_ActorId, m_SocketId ) ) ;
	}

    virtual const char* GetName(void) const
    {
        return "EvtData_Network_Player_Actor_Assignment";
    }


	virtual void VSerialize(std::ostrstream &out) const
	{
		out << m_ActorId << " ";
		out << m_SocketId;
	}

    virtual void VDeserialize( std::istrstream &in )
    {
        in >> m_ActorId;
        in >> m_SocketId;
    }

    ActorId GetActorId(void) const
    {
        return m_ActorId;
    }

    ActorId GetSocketId(void) const
    {
        return m_SocketId;
    }
};


//----------------------------------------------------------------------------------------------
// EvtData_Decompress_Request - sent to a multithreaded game event listener to decompress something in the resource file
//----------------------------------------------------------------------------------------------
class EvtData_Decompress_Request : public BaseEventData
{
    std::wstring m_zipFileName;
    std::string m_fileName;

public:
	static const EventType sk_EventType;

    explicit EvtData_Decompress_Request( std::wstring zipFileName, std::string filename  )
        : m_zipFileName( zipFileName ),
        m_fileName ( filename )
    {
    }

	virtual const EventType& VGetEventType( void ) const
	{
		return sk_EventType;
	}

	virtual IEventDataPtr VCopy() const
	{
		return IEventDataPtr (GCC_NEW EvtData_Decompress_Request ( m_zipFileName, m_fileName ) );
	}

	virtual void VSerialize( std::ostrstream & out )
	{
		GCC_ERROR( "You should not be serializing decompression requests!" );
	}

    const std::wstring& GetZipFilename(void) const
    {
        return m_zipFileName;
    }

    const std::string& GetFilename(void) const
    {
        return m_fileName;
    }
    virtual const char* GetName(void) const
    {
        return "EvtData_Decompress_Request";
    }
};


//----------------------------------------------------------------------------------------------
// EvtData_Decompression_Progress - sent by the decompression thread to report progress
//----------------------------------------------------------------------------------------------
class EvtData_Decompression_Progress : public BaseEventData
{
    int m_progress;
    std::wstring m_zipFileName;
    std::string m_fileName;
    void *m_buffer;

public:
	static const EventType sk_EventType;

    EvtData_Decompression_Progress( int progress, std::wstring zipFileName, std::string filename, void *buffer )
        : m_progress(progress),
        m_zipFileName( zipFileName ),
        m_fileName ( filename ),
        m_buffer (buffer)
    {
    }

	virtual const EventType & VGetEventType( void ) const
	{
		return sk_EventType;
	}

	virtual IEventDataPtr VCopy() const
	{
		return IEventDataPtr (GCC_NEW EvtData_Decompression_Progress ( m_progress, m_zipFileName, m_fileName, m_buffer ) );
	}

	virtual void VSerialize( std::ostrstream & out )
	{
		GCC_ERROR( "You should not be serializing decompression progress events!" );
	}

    virtual const char* GetName(void) const
    {
        return "EvtData_Decompression_Progress";
    }

};


//----------------------------------------------------------------------------------------------
// class EvtData_Request_New_Actor
// This event is sent by a server asking Client proxy logics to create new actors from their local resources.
// It can be sent from script or via code.
// This event is also sent from the server game logic to client logics AFTER it has created a new actor. The logics will allow follow suit to stay in sync.
//----------------------------------------------------------------------------------------------
class EvtData_Request_New_Actor : public BaseEventData
{
    std::string m_actorResource;
	bool m_hasInitialTransform;
	Mat4x4 m_initialTransform;
	ActorId m_serverActorId;
    GameViewId m_viewId;

public:
	static const EventType sk_EventType;

	EvtData_Request_New_Actor()
	{
		m_actorResource = "";
		m_hasInitialTransform = false;
		m_initialTransform = Mat4x4::g_Identity;
		m_serverActorId = -1;
		m_viewId = gc_InvalidGameViewId;
	}

    explicit EvtData_Request_New_Actor(const std::string &actorResource, const Mat4x4 *initialTransform=NULL, const ActorId serverActorId = INVALID_ACTOR_ID, const GameViewId viewId = gc_InvalidGameViewId)
    {
        m_actorResource = actorResource;
		if (initialTransform)
		{
			m_hasInitialTransform = true;
			m_initialTransform = *initialTransform;
		}
		else
			m_hasInitialTransform = false;

		m_serverActorId = serverActorId;
        m_viewId = viewId;
    }

	virtual const EventType& VGetEventType(void) const
	{
		return sk_EventType;
	}

	virtual void VDeserialize( std::istrstream & in )
	{
		in >> m_actorResource;
		in >> m_hasInitialTransform;
		if (m_hasInitialTransform)
		{
			for (int i=0; i<4; ++i)
			{
				for (int j=0; j<4; ++j)
				{
					in >> m_initialTransform.m[i][j];
				}
			}
		}
		in >> m_serverActorId;
		in >> m_viewId;
	}

	virtual IEventDataPtr VCopy() const
	{	 
		return IEventDataPtr (GCC_NEW EvtData_Request_New_Actor(m_actorResource, (m_hasInitialTransform) ? &m_initialTransform : NULL, m_serverActorId, m_viewId));
	}

	virtual void VSerialize( std::ostrstream & out ) const
	{
		out << m_actorResource << " ";
		out << m_hasInitialTransform << " ";
		if (m_hasInitialTransform)
		{
			for (int i=0; i<4; ++i)
			{
				for (int j=0; j<4; ++j)
				{
					out << m_initialTransform.m[i][j] << " ";
				}
			}		
		}
		out << m_serverActorId << " ";
		out << m_viewId << " ";
	}

    virtual const char* GetName(void) const { return "EvtData_Request_New_Actor";  }

    const std::string &GetActorResource(void) const { return m_actorResource;  }
	const Mat4x4 *GetInitialTransform(void) const { return (m_hasInitialTransform) ? &m_initialTransform : NULL; }
	const ActorId GetServerActorId(void) const 	{ return m_serverActorId; }
    GameViewId GetViewId(void) const { return m_viewId; }
};


//----------------------------------------------------------------------------------------------
// EvtData_Request_Destroy_Actor - sent by any system requesting that the game logic destroy an actor
//    FUTURE WORK - This event shouldn't really exist - subsystems should never ask the game logic to destroy something through an event, should they?
//----------------------------------------------------------------------------------------------
class EvtData_Request_Destroy_Actor : public ScriptEvent
{
    ActorId m_actorId;

public:
    static const EventType sk_EventType;

    EvtData_Request_Destroy_Actor()
    {
        m_actorId = INVALID_ACTOR_ID;
    }

    EvtData_Request_Destroy_Actor(ActorId actorId)
    {
        m_actorId = actorId;
    }

    virtual const EventType& VGetEventType(void) const
    {
        return sk_EventType;
    }

    virtual void VDeserialize( std::istrstream & in )
    {
        in >> m_actorId;
    }

    virtual IEventDataPtr VCopy() const
    {
        return IEventDataPtr (GCC_NEW EvtData_Request_Destroy_Actor(m_actorId));
    }

    virtual void VSerialize( std::ostrstream & out ) const
    {
        out << m_actorId;
    }

    virtual const char* GetName(void) const
    {
        return "EvtData_Request_Destroy_Actor";
    }

    ActorId GetActorId(void) const
    {
        return m_actorId;
    }

    virtual bool VBuildEventFromScript(void)
    {
        if (m_eventData.IsInteger())
        {
            m_actorId = m_eventData.GetInteger();
            return true;
        }
        return false;
    }

    EXPORT_FOR_SCRIPT_EVENT(EvtData_Request_Destroy_Actor);
};


//----------------------------------------------------------------------------------------------
// EvtData_PlaySound - sent by any system wishing for a HumanView to play a sound
//----------------------------------------------------------------------------------------------
class EvtData_PlaySound : public ScriptEvent
{
    std::string m_soundResource;

public:
    static const EventType sk_EventType;

    EvtData_PlaySound(void) { }
    EvtData_PlaySound(const std::string& soundResource)
        : m_soundResource(soundResource)
    {
    }

    virtual const EventType& VGetEventType(void) const
    {
        return sk_EventType;
    }

    virtual IEventDataPtr VCopy() const
    {
        return IEventDataPtr(GCC_NEW EvtData_PlaySound(m_soundResource));
    }

    virtual void VSerialize(std::ostrstream& out) const
    {
        out << m_soundResource;
    }

    virtual void VDeserialize(std::istrstream& in)
    {
        in >> m_soundResource;
    }

    const std::string& GetResource(void) const
    {
        return m_soundResource;
    }

    virtual const char* GetName(void) const
    {
        return "EvtData_PlaySound";
    }

    virtual bool VBuildEventFromScript(void);

    EXPORT_FOR_SCRIPT_EVENT(EvtData_PlaySound);
};
//========================================================================
// Events.cpp : defines common game events
//
// Part of the GameCode4 Application
//
// GameCode4 is the sample application that encapsulates much of the source code
// discussed in "Game Coding Complete - 4th Edition" by Mike McShaffry and David
// "Rez" Graham, published by Charles River Media. 
// ISBN-10: 1133776574 | ISBN-13: 978-1133776574
//
// If this source code has found it's way to you, and you think it has helped you
// in any way, do the authors a favor and buy a new copy of the book - there are 
// detailed explanations in it that compliment this code well. Buy a copy at Amazon.com
// by clicking here: 
//    http://www.amazon.com/gp/product/1133776574/ref=olp_product_details?ie=UTF8&me=&seller=
//
// There's a companion web site at http://www.mcshaffry.com/GameCode/
// 
// The source code is managed and maintained through Google Code: 
//    http://code.google.com/p/gamecode4/6
//
// (c) Copyright 2012 Michael L. McShaffry and David Graham
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser GPL v3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 
// http://www.gnu.org/licenses/lgpl-3.0.txt for more details.
//
// You should have received a copy of the GNU Lesser GPL v3
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//
//========================================================================

#include "GameCodeStd.h"
#include "Events.h"
#include "PhysicsEventListener.h"
#include "ScriptEvent.h"

#define REGISTER_SCRIPT_EVENT(eventClass, eventType) \
ScriptEvent::RegisterEventTypeWithScript(#eventClass, eventType); \
ScriptEvent::AddCreationFunction(eventType, &eventClass::CreateEventForScript)

#define EXPORT_FOR_SCRIPT_EVENT(eventClass) \
public: \
static ScriptEvent* CreateEventForScript(void) \
{ \
    return new eventClass; \
}

// To define a new event - you need a 32-bit GUID.
// 将声名中的各个事件分别定义一种类型
const EventType EvtData_Environment_Loaded::sk_EventType(0xa3814acd);
const EventType EvtData_Remote_Environment_Loaded::sk_EventType(0x8E2AD6E6);
const EventType EvtData_New_Actor::sk_EventType(0xe86c7c31);
const EventType EvtData_Move_Actor::sk_EventType(0xeeaa0a40);
const EventType EvtData_Destroy_Actor::sk_EventType(0x77dd2b3a);
const EventType EvtData_New_Render_Component::sk_EventType(0xaf4aff75);
const EventType EvtData_Modified_Render_Component::sk_EventType(0x80fe9766);
const EventType EvtData_Request_Start_Game::sk_EventType(0x11f2b19d);
const EventType EvtData_Remote_Client::sk_EventType(0x301693d5);
const EventType EvtData_Network_Player_Actor_Assignment::sk_EventType(0xa7c92f11);
const EventType EvtData_Update_Tick::sk_EventType(0xf0f5d183);
const EventType EvtData_Decompress_Request::sk_EventType(0xc128a129);
const EventType EvtData_Decompression_Progress::sk_EventType(0x68de1f28);
const EventType EvtData_Request_New_Actor::sk_EventType(0x40378c64);
const EventType EvtData_Request_Destroy_Actor::sk_EventType(0xf5395770);
const EventType EvtData_PlaySound::sk_EventType(0x3d8118ee);

bool EvtData_PlaySound::VBuildEventFromScript(void)
{
    if (m_eventData.IsString())
    {
        m_soundResource = m_eventData.GetString();
        return true;
    }

    return false;
}

void RegisterEngineScriptEvents(void)
{
    REGISTER_SCRIPT_EVENT(EvtData_Request_Destroy_Actor, EvtData_Request_Destroy_Actor::sk_EventType);
    REGISTER_SCRIPT_EVENT(EvtData_PhysCollision, EvtData_PhysCollision::sk_EventType);
	REGISTER_SCRIPT_EVENT(EvtData_PlaySound, EvtData_PlaySound::sk_EventType);
}

以上就是游戏通信中的事件管理相关的代码了,其中多种事件定义以及处理只得我们借鉴。下篇我介绍资源缓存相关的~~







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值