Planeshift

msgmanager.h

Go to the documentation of this file.
00001 /*
00002  * msgmanager.h
00003  *
00004  * Copyright (C) 2005 Atomic Blue ([email protected], http://www.atomicblue.org)
00005  *
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation (version 2 of the License)
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017  *
00018  */
00019 #ifndef __MSGMANAGER_H__
00020 #define __MSGMANAGER_H__
00021 //=============================================================================
00022 // Crystal Space Includes
00023 //=============================================================================
00024 #include <csutil/ref.h>
00025 
00026 //=============================================================================
00027 // Project Includes
00028 //=============================================================================
00029 #include "net/subscriber.h"         // Subscriber class
00030 #include "net/message.h"            // For msgtype typedef
00031 #include "util/eventmanager.h"
00032 #include "globals.h"
00033 
00034 //=============================================================================
00035 // Local Includes
00036 //=============================================================================
00037 
00038 class Client;
00039 class gemObject;
00040 class gemActor;
00041 class MsgEntry;
00042 class GEMSupervisor;
00043 
00048 
00049 
00050 #define NO_VALIDATION                0x00
00051 #define REQUIRE_ANY_CLIENT           0x01
00052 #define REQUIRE_READY_CLIENT         0x02
00053 #define REQUIRE_ALREADY_READY_CLIENT 0x04
00054 #define REQUIRE_ACTOR                0x08
00055 #define REQUIRE_ALIVE                0x10
00056 #define REQUIRE_TARGET               0x20
00057 #define REQUIRE_TARGETACTOR          0x40
00058 #define REQUIRE_TARGETNPC            0x80
00059 
00060 
00067 class MessageManagerBase : public iNetSubscriber
00068 {
00069 public:
00070 
00071     virtual bool Verify(MsgEntry* pMsg, unsigned int flags, Client* &client);
00072 
00074     Client* FindPlayerClient(const char* name);
00075 
00082     csArray<csString> DecodeCommandArea(Client* client, csString target);
00083 
00093     gemObject* FindObjectByString(const csString &str, gemActor* me) const;
00094 };
00095 
00103 template <class SubClass>
00104 class MessageManager : public MessageManagerBase
00105 {
00106 public:
00107     typedef void(SubClass::*FunctionPointer)(MsgEntry*, Client*);
00108 
00110     virtual ~MessageManager()
00111     {
00112         UnsubscribeAll();
00113     }
00114 
00124     inline void Subscribe(FunctionPointer fpt, msgtype type, uint32_t flags = 0x01)
00125     {
00126         CS::Threading::RecursiveMutexScopedLock lock(mutex);
00127         if(!handlers.Contains(type))
00128         {
00129             GetEventManager()->Subscribe(this, type, flags);
00130         }
00131         handlers.Put(type, fpt);
00132     }
00133 
00140     inline bool Unsubscribe(msgtype type)
00141     {
00142         CS::Threading::RecursiveMutexScopedLock lock(mutex);
00143         if(handlers.Contains(type))
00144         {
00145             handlers.DeleteAll(type);
00146             return GetEventManager()->Unsubscribe(this, type);
00147         }
00148         return false;
00149     }
00150 
00158     inline bool Unsubscribe(FunctionPointer handler, msgtype type)
00159     {
00160         CS::Threading::RecursiveMutexScopedLock lock(mutex);
00161         if(handlers.Contains(type))
00162         {
00163             handlers.Delete(type, handler);
00164             if(!handlers.Contains(type))
00165             {
00166                 return GetEventManager()->Unsubscribe(this, type);
00167             }
00168             else
00169             {
00170                 return true;
00171             }
00172         }
00173         else
00174         {
00175             return false;
00176         }
00177     }
00178 
00184     inline bool UnsubscribeAll()
00185     {
00186         CS::Threading::RecursiveMutexScopedLock lock(mutex);
00187         handlers.Empty();
00188         if(psserver->GetEventManager())
00189             return GetEventManager()->UnsubscribeAll(this);
00190         return false;
00191     }
00192 
00200     void HandleMessage(MsgEntry* msg, Client* client)
00201     {
00202         csArray<FunctionPointer> msgHandlers;
00203         {
00204             CS::Threading::RecursiveMutexScopedLock lock(mutex);
00205             msgHandlers = handlers.GetAll(msg->GetType());
00206         }
00207         SubClass* self = dynamic_cast<SubClass*>(this);
00208         if(!self)
00209         {
00210             // fatal error, we aren't a base of our subclass!
00211             return;
00212         }
00213 
00214         for(size_t i = 0; i < msgHandlers.GetSize(); ++i)
00215         {
00216             (self->*msgHandlers[i])(msg, client);
00217         }
00218     }
00219 
00220 private:
00221     CS::Threading::RecursiveMutex mutex;
00222     csHash<FunctionPointer, msgtype> handlers;
00223 
00231     inline EventManager* GetEventManager() const
00232     {
00233         EventManager* eventManager = psserver->GetEventManager();
00234         CS_ASSERT(eventManager);
00235         return eventManager;
00236     }
00237 };
00238 
00241 #endif