dvander@592: /**
ds@653: * vim: set ts=4 :
ds@1330: * =============================================================================
dvander@1231: * SourceMod
ds@3099: * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
ds@1330: * =============================================================================
ds@653: *
ds@1330: * This program is free software; you can redistribute it and/or modify it under
ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330: * Free Software Foundation.
dvander@1231: *
ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
ds@1330: * details.
dvander@1231: *
ds@1330: * You should have received a copy of the GNU General Public License along with
ds@1330: * this program. If not, see .
dvander@1231: *
ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in
ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants
ds@1330: * this exception to all derivative works. AlliedModders LLC defines further
ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330: * or .
ds@653: *
ds@653: * Version: $Id$
ds@653: */
dvander@592:
dvander@592: #ifndef _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
dvander@592: #define _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
dvander@592:
dvander@592: #include
dvander@592: #include "sourcemm_api.h"
dvander@592: #include "sm_trie.h"
skamonkey@3743: #include "sm_stringutil.h"
dvander@592: #include "CellRecipientFilter.h"
dvander@3872: #include "sm_globals.h"
dvander@3872: #include
dvander@3872: #include
dvander@592:
dvander@592: using namespace SourceHook;
dvander@592: using namespace SourceMod;
dvander@592:
skamonkey@3855: #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
skamonkey@3743: #define USE_PROTOBUF_USERMESSAGES
skamonkey@3743: #endif
skamonkey@3743:
skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743: #include
skamonkey@3743: #include
skamonkey@3743: #include
skamonkey@3743:
skamonkey@3743: using namespace google;
skamonkey@3743: #else
skamonkey@3743: #include
skamonkey@3743: #endif
skamonkey@3743:
dvander@592: #define INVALID_MESSAGE_ID -1
dvander@592:
faluco@593: struct ListenerInfo
faluco@593: {
skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743: IProtobufUserMessageListener *Callback;
skamonkey@3743: #else
skamonkey@3743: IBitBufUserMessageListener *Callback;
skamonkey@3743: #endif
faluco@593: bool IsHooked;
faluco@593: bool KillMe;
dvander@2636: bool IsNew;
faluco@593: };
faluco@593:
faluco@593: typedef List MsgList;
faluco@593: typedef List::iterator MsgIter;
dvander@592:
dvander@616: class UserMessages :
dvander@592: public IUserMessages,
dvander@592: public SMGlobalClass
dvander@592: {
dvander@592: public:
dvander@616: UserMessages();
dvander@616: ~UserMessages();
dvander@592: public: //SMGlobalClass
ds@765: void OnSourceModStartup(bool late);
dvander@592: void OnSourceModAllInitialized();
dvander@592: void OnSourceModAllShutdown();
dvander@592: public: //IUserMessages
dvander@592: int GetMessageIndex(const char *msg);
ds@765: bool GetMessageName(int msgid, char *buffer, size_t maxlength) const;
dvander@592: bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
dvander@592: bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
skamonkey@3743: bf_write *StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
skamonkey@3743: google::protobuf::Message *StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
dvander@592: bool EndMessage();
dvander@2636: bool HookUserMessage2(int msg_id,
dvander@2636: IUserMessageListener *pListener,
dvander@2636: bool intercept=false);
dvander@2636: bool UnhookUserMessage2(int msg_id,
dvander@2636: IUserMessageListener *pListener,
dvander@2636: bool intercept=false);
skamonkey@3743: UserMessageType GetUserMessageType() const;
dvander@592: public:
skamonkey@3855: #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
skamonkey@3743: void OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
skamonkey@3743: void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
skamonkey@3743: #endif
skamonkey@3743:
skamonkey@3855: #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
skamonkey@3743: protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
skamonkey@3743: protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
skamonkey@3743: #elif SOURCE_ENGINE >= SE_LEFT4DEAD
ds@2400: bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
ds@2400: bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
ds@2400: #else
dvander@592: bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type);
dvander@592: bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type);
ds@2400: #endif
dvander@592: void OnMessageEnd_Pre();
dvander@592: void OnMessageEnd_Post();
dvander@592: private:
skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3855: const protobuf::Message *GetMessagePrototype(int msg_type);
skamonkey@3743: bool InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
skamonkey@3743: bool InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
skamonkey@3743: #else
skamonkey@3743: bool InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
skamonkey@3743: bool InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
skamonkey@3743: #endif
faluco@593: void _DecRefCounter();
faluco@593: private:
faluco@593: List m_msgHooks[255];
faluco@593: List m_msgIntercepts[255];
faluco@593: CStack m_FreeListeners;
dvander@592: IRecipientFilter *m_CurRecFilter;
skamonkey@3743: #ifndef USE_PROTOBUF_USERMESSAGES
skamonkey@3815: unsigned char m_pBase[2500];
dvander@592: bf_write m_InterceptBuffer;
dvander@592: bf_write *m_OrigBuffer;
dvander@592: bf_read m_ReadBuffer;
skamonkey@3743: #else
skamonkey@3743: // The engine used to provide this. Now we track it.
skamonkey@3743: protobuf::Message *m_OrigBuffer;
skamonkey@3743: protobuf::Message *m_FakeEngineBuffer;
skamonkey@3743: META_RES m_FakeMetaRes;
skamonkey@3743:
skamonkey@3743: protobuf::Message *m_InterceptBuffer;
skamonkey@3743: #endif
dvander@592: size_t m_HookCount;
dvander@592: bool m_InHook;
faluco@597: bool m_BlockEndPost;
skamonkey@3743: #ifndef USE_PROTOBUF_USERMESSAGES
ds@765: bool m_FallbackSearch;
dvander@592:
dvander@592: Trie *m_Names;
skamonkey@3743: #endif
dvander@592: CellRecipientFilter m_CellRecFilter;
dvander@592: bool m_InExec;
dvander@592: int m_CurFlags;
dvander@592: int m_CurId;
dvander@592: };
dvander@592:
dvander@616: extern UserMessages g_UserMsgs;
dvander@592:
dvander@592: #endif //_INCLUDE_SOURCEMOD_CUSERMESSAGES_H_