faluco@505: /** dvander@600: * vim: set ts=4 : ds@1330: * ============================================================================= dvander@1231: * SourceMod ds@1947: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. ds@1330: * ============================================================================= dvander@600: * 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 . dvander@600: * dvander@600: * Version: $Id$ dvander@600: */ faluco@505: ds@2112: #include "PlayerManager.h" dvander@590: #include "smn_usermsgs.h" dvander@3872: #include "logic_bridge.h" skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES skamonkey@3743: #include "UserMessagePBHelpers.h" skamonkey@3743: #endif faluco@505: skamonkey@3743: HandleType_t g_ProtobufType = NO_HANDLE_TYPE; skamonkey@3743: HandleType_t g_WrBitBufType = NO_HANDLE_TYPE; skamonkey@3743: HandleType_t g_RdBitBufType = NO_HANDLE_TYPE; skamonkey@3743: faluco@505: Handle_t g_CurMsgHandle; skamonkey@3743: skamonkey@3743: #ifndef USE_PROTOBUF_USERMESSAGES faluco@598: Handle_t g_ReadBufHandle; faluco@598: bf_read g_ReadBitBuf; skamonkey@3743: #endif faluco@598: faluco@552: int g_MsgPlayers[256]; faluco@505: bool g_IsMsgInExec = false; faluco@505: faluco@593: typedef List MsgWrapperList; faluco@593: typedef List::iterator MsgWrapperIter; faluco@593: faluco@505: class UsrMessageNatives : faluco@505: public SMGlobalClass, faluco@552: public IHandleTypeDispatch, faluco@552: public IPluginsListener faluco@505: { faluco@641: public: faluco@641: ~UsrMessageNatives(); faluco@552: public: //SMGlobalClass, IHandleTypeDispatch, IPluginListener faluco@552: void OnSourceModAllInitialized(); faluco@552: void OnSourceModShutdown(); faluco@552: void OnHandleDestroy(HandleType_t type, void *object); dvander@1766: bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize); faluco@552: void OnPluginUnloaded(IPlugin *plugin); faluco@505: public: faluco@593: MsgListenerWrapper *CreateListener(IPluginContext *pCtx); faluco@1541: bool FindListener(int msgid, IPluginContext *pCtx, IPluginFunction *pHook, bool intercept, MsgWrapperIter *iter); faluco@593: bool DeleteListener(IPluginContext *pCtx, MsgWrapperIter iter); faluco@552: private: faluco@552: CStack m_FreeListeners; faluco@552: }; faluco@552: faluco@641: UsrMessageNatives::~UsrMessageNatives() faluco@641: { faluco@641: CStack::iterator iter; faluco@641: for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++) faluco@641: { faluco@641: delete (*iter); faluco@641: } faluco@641: m_FreeListeners.popall(); faluco@641: } faluco@641: faluco@552: void UsrMessageNatives::OnSourceModAllInitialized() faluco@552: { faluco@598: HandleAccess sec; faluco@1397: dvander@3872: handlesys->InitAccessDefaults(NULL, &sec); faluco@1397: sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY; faluco@598: skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES dvander@3872: g_ProtobufType = handlesys->CreateType("ProtobufUM", this, 0, NULL, NULL, g_pCoreIdent, NULL); skamonkey@3743: #else dvander@3872: g_WrBitBufType = handlesys->CreateType("BitBufWriter", this, 0, NULL, NULL, g_pCoreIdent, NULL); dvander@3872: g_RdBitBufType = handlesys->CreateType("BitBufReader", this, 0, NULL, &sec, g_pCoreIdent, NULL); faluco@598: dvander@3872: g_ReadBufHandle = handlesys->CreateHandle(g_RdBitBufType, &g_ReadBitBuf, NULL, g_pCoreIdent, NULL); skamonkey@3743: #endif faluco@598: dvander@3872: scripts->AddPluginsListener(this); faluco@552: } faluco@552: faluco@552: void UsrMessageNatives::OnSourceModShutdown() faluco@552: { faluco@598: HandleSecurity sec; faluco@598: sec.pIdentity = g_pCoreIdent; faluco@598: skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES dvander@3872: handlesys->RemoveType(g_ProtobufType, g_pCoreIdent); skamonkey@3743: skamonkey@3743: g_ProtobufType = 0; skamonkey@3743: #else dvander@3872: handlesys->FreeHandle(g_ReadBufHandle, &sec); faluco@598: dvander@3872: handlesys->RemoveType(g_WrBitBufType, g_pCoreIdent); dvander@3872: handlesys->RemoveType(g_RdBitBufType, g_pCoreIdent); faluco@598: faluco@552: g_WrBitBufType = 0; faluco@598: g_RdBitBufType = 0; skamonkey@3743: #endif faluco@552: } faluco@553: faluco@552: void UsrMessageNatives::OnHandleDestroy(HandleType_t type, void *object) faluco@552: { skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES skamonkey@3743: delete (SMProtobufMessage *)object; skamonkey@3743: #endif faluco@552: } faluco@552: dvander@1766: bool UsrMessageNatives::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize) dvander@1766: { skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES skamonkey@3743: // Different messages have different sizes, but this works as an approximate skamonkey@3743: *pSize = sizeof(protobuf::Message) + sizeof(SMProtobufMessage); skamonkey@3743: #else pred@1871: *pSize = sizeof(bf_read); skamonkey@3743: #endif dvander@1766: dvander@1766: return true; dvander@1766: } dvander@1766: faluco@552: void UsrMessageNatives::OnPluginUnloaded(IPlugin *plugin) faluco@552: { faluco@593: MsgWrapperList *pList; faluco@552: faluco@593: if (plugin->GetProperty("MsgListeners", reinterpret_cast(&pList), true)) faluco@505: { faluco@593: MsgWrapperIter iter; faluco@593: MsgListenerWrapper *pListener; faluco@552: faluco@593: for (iter=pList->begin(); iter!=pList->end(); iter++) faluco@552: { faluco@593: pListener = (*iter); fyrenmoo@2736: if (g_UserMsgs.UnhookUserMessage2(pListener->GetMessageId(), pListener, pListener->IsInterceptHook())) faluco@552: { faluco@593: m_FreeListeners.push(pListener); faluco@552: } faluco@552: } faluco@552: faluco@593: delete pList; faluco@552: } faluco@552: } faluco@552: faluco@593: MsgListenerWrapper *UsrMessageNatives::CreateListener(IPluginContext *pCtx) faluco@552: { faluco@593: MsgWrapperList *pList; faluco@593: MsgListenerWrapper *pListener; dvander@3872: IPlugin *pl = scripts->FindPluginByContext(pCtx->GetContext()); faluco@552: faluco@552: if (m_FreeListeners.empty()) faluco@552: { faluco@593: pListener = new MsgListenerWrapper; faluco@552: } else { faluco@593: pListener = m_FreeListeners.front(); faluco@552: m_FreeListeners.pop(); faluco@505: } faluco@552: faluco@593: if (!pl->GetProperty("MsgListeners", reinterpret_cast(&pList))) faluco@505: { faluco@593: pList = new List; faluco@593: pl->SetProperty("MsgListeners", pList); faluco@552: } faluco@552: faluco@593: pList->push_back(pListener); faluco@552: faluco@593: return pListener; faluco@552: } faluco@552: faluco@1541: bool UsrMessageNatives::FindListener(int msgid, IPluginContext *pCtx, IPluginFunction *pHook, bool intercept, MsgWrapperIter *iter) faluco@552: { faluco@593: MsgWrapperList *pList; faluco@1541: MsgWrapperIter _iter; faluco@593: MsgListenerWrapper *pListener; dvander@3872: IPlugin *pl = scripts->FindPluginByContext(pCtx->GetContext()); faluco@552: faluco@593: if (!pl->GetProperty("MsgListeners", reinterpret_cast(&pList))) faluco@552: { faluco@1541: return false; faluco@505: } faluco@552: faluco@1541: for (_iter=pList->begin(); _iter!=pList->end(); _iter++) faluco@505: { faluco@1541: pListener = (*_iter); faluco@593: if ((msgid == pListener->GetMessageId()) faluco@593: && (intercept == pListener->IsInterceptHook()) faluco@593: && (pHook == pListener->GetHookedFunction())) faluco@552: { faluco@1541: *iter = _iter; faluco@1541: return true; faluco@552: } faluco@505: } faluco@552: faluco@1541: return false; faluco@552: } faluco@553: faluco@593: bool UsrMessageNatives::DeleteListener(IPluginContext *pCtx, MsgWrapperIter iter) faluco@552: { faluco@593: MsgWrapperList *pList; faluco@593: MsgListenerWrapper *pListener; dvander@3872: IPlugin *pl = scripts->FindPluginByContext(pCtx->GetContext()); faluco@552: faluco@593: if (!pl->GetProperty("MsgListeners", reinterpret_cast(&pList))) faluco@552: { faluco@552: return false; faluco@552: } faluco@552: faluco@593: pListener = (*iter); faluco@593: pList->erase(iter); faluco@593: m_FreeListeners.push(pListener); faluco@552: faluco@552: return true; faluco@552: } faluco@552: dvander@590: /*************************************** dvander@590: * * dvander@590: * USER MESSAGE WRAPPER IMPLEMENTATION * dvander@590: * * dvander@590: ***************************************/ dvander@590: faluco@593: void MsgListenerWrapper::Initialize(int msgid, IPluginFunction *hook, IPluginFunction *notify, bool intercept) faluco@593: { faluco@593: if (intercept) faluco@593: { faluco@593: m_Intercept = hook; faluco@593: m_Hook = NULL; faluco@593: } else { faluco@593: m_Hook = hook; faluco@593: m_Intercept = NULL; faluco@593: } faluco@593: faluco@593: if (notify) faluco@593: { faluco@593: m_Notify = notify; faluco@593: } else { faluco@593: m_Notify = NULL; faluco@593: } faluco@593: faluco@593: m_MsgId = msgid; faluco@593: m_IsInterceptHook = intercept; faluco@593: } faluco@593: faluco@593: size_t MsgListenerWrapper::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter) dvander@590: { dvander@590: size_t size = static_cast(pFilter->GetRecipientCount()); dvander@590: dvander@590: for (size_t i=0; iGetRecipientIndex(i).Get(); skamonkey@3916: #else skamonkey@3916: index = pFilter->GetRecipientIndex(i); skamonkey@3916: #endif skamonkey@3916: pl_array[i] = index; dvander@590: } dvander@590: dvander@590: return size; dvander@590: } dvander@590: dvander@590: bool MsgListenerWrapper::IsInterceptHook() const dvander@590: { dvander@590: return m_IsInterceptHook; dvander@590: } dvander@590: dvander@590: int MsgListenerWrapper::GetMessageId() const dvander@590: { dvander@590: return m_MsgId; dvander@590: } dvander@590: dvander@590: IPluginFunction *MsgListenerWrapper::GetHookedFunction() const dvander@590: { dvander@590: if (m_Hook) dvander@590: { dvander@590: return m_Hook; dvander@590: } else { dvander@590: return m_Intercept; dvander@590: } dvander@590: } dvander@590: dvander@590: IPluginFunction *MsgListenerWrapper::GetNotifyFunction() const dvander@590: { dvander@590: return m_Notify; dvander@590: } dvander@590: skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES skamonkey@3743: void MsgListenerWrapper::OnUserMessage(int msg_id, protobuf::Message *msg, IRecipientFilter *pFilter) skamonkey@3743: #else dvander@590: void MsgListenerWrapper::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter) skamonkey@3743: #endif dvander@590: { dvander@590: cell_t res; skamonkey@3743: Handle_t hndl; faluco@593: size_t size = _FillInPlayers(g_MsgPlayers, pFilter); dvander@590: skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES dvander@3872: hndl = handlesys->CreateHandle(g_ProtobufType, new SMProtobufMessage(msg), NULL, g_pCoreIdent, NULL); skamonkey@3743: #else faluco@598: g_ReadBitBuf.StartReading(bf->GetBasePointer(), bf->GetNumBytesWritten()); skamonkey@3743: hndl = g_ReadBufHandle; skamonkey@3743: #endif faluco@598: dvander@590: m_Hook->PushCell(msg_id); skamonkey@3743: m_Hook->PushCell(hndl); dvander@590: m_Hook->PushArray(g_MsgPlayers, size); dvander@590: m_Hook->PushCell(size); dvander@590: m_Hook->PushCell(pFilter->IsReliable()); dvander@590: m_Hook->PushCell(pFilter->IsInitMessage()); dvander@590: m_Hook->Execute(&res); skamonkey@3743: skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES skamonkey@3743: HandleSecurity sec; skamonkey@3743: sec.pIdentity = g_pCoreIdent; dvander@3872: handlesys->FreeHandle(hndl, &sec); skamonkey@3743: #endif dvander@590: } dvander@590: skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES skamonkey@3743: ResultType MsgListenerWrapper::InterceptUserMessage(int msg_id, protobuf::Message *msg, IRecipientFilter *pFilter) skamonkey@3743: #else dvander@590: ResultType MsgListenerWrapper::InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter) skamonkey@3743: #endif dvander@590: { skamonkey@3743: Handle_t hndl; dvander@590: cell_t res = static_cast(Pl_Continue); faluco@593: size_t size = _FillInPlayers(g_MsgPlayers, pFilter); dvander@590: skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES dvander@3872: hndl = handlesys->CreateHandle(g_ProtobufType, new SMProtobufMessage(msg), NULL, g_pCoreIdent, NULL); skamonkey@3743: #else faluco@598: g_ReadBitBuf.StartReading(bf->GetBasePointer(), bf->GetNumBytesWritten()); skamonkey@3743: hndl = g_ReadBufHandle; skamonkey@3743: #endif faluco@598: dvander@590: m_Intercept->PushCell(msg_id); skamonkey@3743: m_Intercept->PushCell(hndl); dvander@590: m_Intercept->PushArray(g_MsgPlayers, size); dvander@590: m_Intercept->PushCell(size); dvander@590: m_Intercept->PushCell(pFilter->IsReliable()); dvander@590: m_Intercept->PushCell(pFilter->IsInitMessage()); dvander@590: m_Intercept->Execute(&res); dvander@590: skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES skamonkey@3743: HandleSecurity sec; skamonkey@3743: sec.pIdentity = g_pCoreIdent; dvander@3872: handlesys->FreeHandle(hndl, &sec); skamonkey@3743: #endif skamonkey@3743: dvander@590: return static_cast(res); dvander@590: } dvander@590: dvander@2636: void MsgListenerWrapper::OnPostUserMessage(int msg_id, bool sent) dvander@590: { dvander@590: if (!m_Notify) dvander@590: { dvander@590: return; dvander@590: } dvander@590: faluco@593: cell_t res; dvander@590: m_Notify->PushCell(msg_id); dvander@2636: m_Notify->PushCell(sent ? 1 : 0); dvander@590: m_Notify->Execute(&res); dvander@590: } dvander@590: dvander@590: /*************************************** dvander@590: * * dvander@590: * USER MESSAGE NATIVE IMPLEMENTATIONS * dvander@590: * * dvander@590: ***************************************/ faluco@552: faluco@552: static UsrMessageNatives s_UsrMessageNatives; faluco@505: skamonkey@3743: static cell_t smn_GetUserMessageType(IPluginContext *pCtx, const cell_t *params) skamonkey@3743: { skamonkey@3743: return g_UserMsgs.GetUserMessageType(); skamonkey@3743: } skamonkey@3743: faluco@505: static cell_t smn_GetUserMessageId(IPluginContext *pCtx, const cell_t *params) faluco@505: { faluco@505: char *msgname; ds@698: pCtx->LocalToString(params[1], &msgname); faluco@505: faluco@552: return g_UserMsgs.GetMessageIndex(msgname); faluco@505: } faluco@505: faluco@553: static cell_t smn_GetUserMessageName(IPluginContext *pCtx, const cell_t *params) faluco@553: { ds@765: char *msgname; faluco@553: ds@765: pCtx->LocalToPhysAddr(params[2], (cell_t **)&msgname); faluco@553: ds@765: return g_UserMsgs.GetMessageName(params[1], msgname, params[3]); faluco@553: } faluco@553: faluco@505: static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params) faluco@505: { faluco@505: char *msgname; faluco@505: cell_t *cl_array; ds@2112: unsigned int numClients; ds@698: int msgid; ds@2112: int client; ds@2112: CPlayer *pPlayer = NULL; faluco@505: faluco@505: if (g_IsMsgInExec) faluco@505: { faluco@505: return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress"); faluco@505: } faluco@505: ds@698: pCtx->LocalToString(params[1], &msgname); faluco@505: faluco@552: if ((msgid=g_UserMsgs.GetMessageIndex(msgname)) == INVALID_MESSAGE_ID) faluco@505: { faluco@505: return pCtx->ThrowNativeError("Invalid message name: \"%s\"", msgname); faluco@505: } faluco@505: faluco@505: pCtx->LocalToPhysAddr(params[2], &cl_array); faluco@505: ds@2112: numClients = params[3]; ds@2112: ds@2112: /* Client validation */ ds@2112: for (unsigned int i = 0; i < numClients; i++) ds@2112: { ds@2112: client = cl_array[i]; ds@2112: pPlayer = g_Players.GetPlayerByIndex(client); ds@2112: ds@2112: if (!pPlayer) ds@2112: { ds@2112: return pCtx->ThrowNativeError("Client index %d is invalid", client); ds@2112: } else if (!pPlayer->IsConnected()) { ds@2112: return pCtx->ThrowNativeError("Client %d is not connected", client); ds@2112: } ds@2112: } ds@2112: skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES skamonkey@3743: protobuf::Message *msg = g_UserMsgs.StartProtobufMessage(msgid, cl_array, numClients, params[4]); skamonkey@3743: if (!msg) skamonkey@3743: { skamonkey@3743: return pCtx->ThrowNativeError("Unable to execute a new message while in hook"); skamonkey@3743: } skamonkey@3743: dvander@3872: g_CurMsgHandle = handlesys->CreateHandle(g_ProtobufType, new SMProtobufMessage(msg), pCtx->GetIdentity(), g_pCoreIdent, NULL); skamonkey@3743: #else skamonkey@3743: bf_write *pBitBuf = g_UserMsgs.StartBitBufMessage(msgid, cl_array, numClients, params[4]); faluco@593: if (!pBitBuf) faluco@593: { faluco@593: return pCtx->ThrowNativeError("Unable to execute a new message while in hook"); faluco@593: } faluco@505: dvander@3872: g_CurMsgHandle = handlesys->CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL); skamonkey@3743: #endif skamonkey@3743: faluco@505: g_IsMsgInExec = true; faluco@505: faluco@505: return g_CurMsgHandle; faluco@505: } faluco@505: faluco@505: static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params) faluco@505: { faluco@505: cell_t *cl_array; ds@2112: unsigned int numClients; ds@2112: int client; ds@2112: CPlayer *pPlayer = NULL; faluco@505: int msgid = params[1]; faluco@505: faluco@505: if (g_IsMsgInExec) faluco@505: { faluco@505: return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress"); faluco@505: } faluco@505: faluco@552: if (msgid < 0 || msgid >= 255) faluco@505: { faluco@505: return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid); faluco@505: } faluco@505: faluco@505: pCtx->LocalToPhysAddr(params[2], &cl_array); faluco@505: ds@2112: numClients = params[3]; ds@2112: ds@2112: /* Client validation */ ds@2112: for (unsigned int i = 0; i < numClients; i++) ds@2112: { ds@2112: client = cl_array[i]; ds@2112: pPlayer = g_Players.GetPlayerByIndex(client); ds@2112: ds@2112: if (!pPlayer) ds@2112: { ds@2112: return pCtx->ThrowNativeError("Client index %d is invalid", client); ds@2112: } else if (!pPlayer->IsConnected()) { ds@2112: return pCtx->ThrowNativeError("Client %d is not connected", client); ds@2112: } ds@2112: } ds@2112: skamonkey@3743: #ifdef USE_PROTOBUF_USERMESSAGES skamonkey@3743: protobuf::Message *msg = g_UserMsgs.StartProtobufMessage(msgid, cl_array, numClients, params[4]); skamonkey@3743: if (!msg) skamonkey@3743: { skamonkey@3743: return pCtx->ThrowNativeError("Unable to execute a new message while in hook"); skamonkey@3743: } skamonkey@3743: dvander@3872: g_CurMsgHandle = handlesys->CreateHandle(g_ProtobufType, new SMProtobufMessage(msg), pCtx->GetIdentity(), g_pCoreIdent, NULL); skamonkey@3743: #else skamonkey@3743: bf_write *pBitBuf = g_UserMsgs.StartBitBufMessage(msgid, cl_array, numClients, params[4]); faluco@593: if (!pBitBuf) faluco@593: { faluco@593: return pCtx->ThrowNativeError("Unable to execute a new message while in hook"); faluco@593: } faluco@505: dvander@3872: g_CurMsgHandle = handlesys->CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL); skamonkey@3743: #endif faluco@505: g_IsMsgInExec = true; faluco@505: faluco@505: return g_CurMsgHandle; faluco@505: } faluco@505: faluco@505: static cell_t smn_EndMessage(IPluginContext *pCtx, const cell_t *params) faluco@505: { faluco@505: HandleSecurity sec; faluco@505: faluco@505: if (!g_IsMsgInExec) faluco@505: { faluco@505: return pCtx->ThrowNativeError("Unable to end message, no message is in progress"); faluco@505: } faluco@505: faluco@552: g_UserMsgs.EndMessage(); faluco@505: faluco@505: sec.pOwner = pCtx->GetIdentity(); faluco@505: sec.pIdentity = g_pCoreIdent; dvander@3872: handlesys->FreeHandle(g_CurMsgHandle, &sec); faluco@505: faluco@505: g_IsMsgInExec = false; faluco@552: faluco@552: return 1; faluco@552: } faluco@552: faluco@552: static cell_t smn_HookUserMessage(IPluginContext *pCtx, const cell_t *params) faluco@552: { faluco@552: IPluginFunction *pHook, *pNotify; faluco@593: MsgListenerWrapper *pListener; faluco@552: bool intercept; faluco@552: int msgid = params[1]; faluco@552: faluco@552: if (msgid < 0 || msgid >= 255) faluco@552: { faluco@552: return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid); faluco@552: } faluco@552: faluco@552: pHook = pCtx->GetFunctionById(params[2]); faluco@552: if (!pHook) faluco@552: { faluco@552: return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]); faluco@552: } faluco@552: pNotify = pCtx->GetFunctionById(params[4]); faluco@593: intercept = (params[3]) ? true : false; faluco@552: faluco@593: pListener = s_UsrMessageNatives.CreateListener(pCtx); faluco@593: pListener->Initialize(msgid, pHook, pNotify, intercept); faluco@553: dvander@2636: g_UserMsgs.HookUserMessage2(msgid, pListener, intercept); faluco@505: faluco@505: return 1; faluco@505: } faluco@505: ds@626: static cell_t smn_UnhookUserMessage(IPluginContext *pCtx, const cell_t *params) faluco@552: { faluco@552: IPluginFunction *pFunc; faluco@593: MsgListenerWrapper *pListener; faluco@593: MsgWrapperIter iter; faluco@552: bool intercept; faluco@552: int msgid = params[1]; faluco@552: faluco@552: if (msgid < 0 || msgid >= 255) faluco@552: { faluco@552: return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid); faluco@552: } faluco@552: faluco@552: pFunc = pCtx->GetFunctionById(params[2]); faluco@552: if (!pFunc) faluco@552: { faluco@552: return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]); faluco@552: } faluco@593: intercept = (params[3]) ? true : false; faluco@552: faluco@1541: if (!s_UsrMessageNatives.FindListener(msgid, pCtx, pFunc, intercept, &iter)) faluco@552: { faluco@552: return pCtx->ThrowNativeError("Unable to unhook the current user message"); faluco@552: } faluco@552: faluco@593: pListener = (*iter); dvander@2636: if (!g_UserMsgs.UnhookUserMessage2(msgid, pListener, intercept)) faluco@552: { faluco@552: return pCtx->ThrowNativeError("Unable to unhook the current user message"); faluco@552: } faluco@552: faluco@593: s_UsrMessageNatives.DeleteListener(pCtx, iter); faluco@552: faluco@552: return 1; faluco@552: } faluco@505: faluco@505: REGISTER_NATIVES(usrmsgnatives) faluco@505: { skamonkey@3743: {"GetUserMessageType", smn_GetUserMessageType}, faluco@505: {"GetUserMessageId", smn_GetUserMessageId}, faluco@553: {"GetUserMessageName", smn_GetUserMessageName}, faluco@505: {"StartMessage", smn_StartMessage}, faluco@505: {"StartMessageEx", smn_StartMessageEx}, faluco@505: {"EndMessage", smn_EndMessage}, faluco@552: {"HookUserMessage", smn_HookUserMessage}, ds@626: {"UnhookUserMessage", smn_UnhookUserMessage}, faluco@505: {NULL, NULL} faluco@505: };