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: };