Improved user message interception API (bug 3631, r=pred).

This commit is contained in:
David Anderson 2009-03-01 16:39:25 -05:00
parent 0c028ca9d0
commit 96a3671bb6
8 changed files with 128 additions and 20 deletions

View File

@ -273,13 +273,13 @@ bool CPlugin::UpdateInfo()
base->GetPubvarAddrs(idx, &local_addr, (cell_t **)&info);
m_FileVersion = info->version;
if (m_FileVersion >= 3)
if (m_FileVersion >= 4)
{
base->LocalToString(info->date, (char **)&pDate);
base->LocalToString(info->time, (char **)&pTime);
UTIL_Format(m_DateTime, sizeof(m_DateTime), "%s %s", pDate, pTime);
}
if (m_FileVersion > 4)
if (m_FileVersion > 5)
{
base->LocalToString(info->filevers, (char **)&pFileVers);
SetErrorState(Plugin_Failed, "Newer SourceMod required (%s or higher)", pFileVers);

View File

@ -205,7 +205,31 @@ bool UserMessages::EndMessage()
return true;
}
bool UserMessages::HookUserMessage2(int msg_id,
IUserMessageListener *pListener,
bool intercept)
{
return InternalHook(msg_id, pListener, intercept, true);
}
bool UserMessages::UnhookUserMessage2(int msg_id,
IUserMessageListener *pListener,
bool intercept)
{
return InternalUnhook(msg_id, pListener, intercept, true);
}
bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
{
return InternalHook(msg_id, pListener, intercept, false);
}
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
{
return InternalUnhook(msg_id, pListener, intercept, false);
}
bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
{
if (msg_id < 0 || msg_id >= 255)
{
@ -224,6 +248,7 @@ bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener,
pInfo->Callback = pListener;
pInfo->IsHooked = false;
pInfo->KillMe = false;
pInfo->IsNew = isNew;
if (!m_HookCount++)
{
@ -243,8 +268,8 @@ bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener,
return true;
}
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
{
bool UserMessages::InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
{
MsgList *pList;
MsgIter iter;
ListenerInfo *pInfo;
@ -259,7 +284,7 @@ bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener
for (iter=pList->begin(); iter!=pList->end(); iter++)
{
pInfo = (*iter);
if (pInfo->Callback == pListener)
if (pInfo->Callback == pListener && pInfo->IsNew == isNew)
{
if (pInfo->IsHooked)
{
@ -339,7 +364,7 @@ bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_ty
void UserMessages::OnMessageEnd_Post()
{
if (!m_InHook || m_BlockEndPost)
if (!m_InHook)
{
RETURN_META(MRES_IGNORED);
}
@ -354,8 +379,16 @@ void UserMessages::OnMessageEnd_Post()
for (iter=pList->begin(); iter!=pList->end(); )
{
pInfo = (*iter);
if (m_BlockEndPost && !pInfo->IsNew)
{
continue;
}
pInfo->IsHooked = true;
pInfo->Callback->OnUserMessageSent(m_CurId);
if (pInfo->IsNew)
{
pInfo->Callback->OnPostUserMessage(m_CurId, !m_BlockEndPost);
}
if (pInfo->KillMe)
{
@ -373,8 +406,16 @@ void UserMessages::OnMessageEnd_Post()
for (iter=pList->begin(); iter!=pList->end(); )
{
pInfo = (*iter);
if (m_BlockEndPost && !pInfo->IsNew)
{
continue;
}
pInfo->IsHooked = true;
pInfo->Callback->OnUserMessageSent(m_CurId);
if (pInfo->IsNew)
{
pInfo->Callback->OnPostUserMessage(m_CurId, !m_BlockEndPost);
}
if (pInfo->KillMe)
{
@ -495,7 +536,6 @@ void UserMessages::OnMessageEnd_Pre()
RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
supercede:
m_InHook = false;
m_BlockEndPost = true;
RETURN_META(MRES_SUPERCEDE);
}

View File

@ -48,6 +48,7 @@ struct ListenerInfo
IUserMessageListener *Callback;
bool IsHooked;
bool KillMe;
bool IsNew;
};
typedef List<ListenerInfo *> MsgList;
@ -71,6 +72,12 @@ public: //IUserMessages
bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
bf_write *StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
bool EndMessage();
bool HookUserMessage2(int msg_id,
IUserMessageListener *pListener,
bool intercept=false);
bool UnhookUserMessage2(int msg_id,
IUserMessageListener *pListener,
bool intercept=false);
public:
#if SOURCE_ENGINE == SE_LEFT4DEAD
bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
@ -82,6 +89,8 @@ public:
void OnMessageEnd_Pre();
void OnMessageEnd_Post();
private:
bool InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
bool InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
void _DecRefCounter();
private:
List<ListenerInfo *> m_msgHooks[255];

View File

@ -309,7 +309,7 @@ ResultType MsgListenerWrapper::InterceptUserMessage(int msg_id, bf_write *bf, IR
return static_cast<ResultType>(res);
}
void MsgListenerWrapper::OnUserMessageSent(int msg_id)
void MsgListenerWrapper::OnPostUserMessage(int msg_id, bool sent)
{
if (!m_Notify)
{
@ -318,6 +318,7 @@ void MsgListenerWrapper::OnUserMessageSent(int msg_id)
cell_t res;
m_Notify->PushCell(msg_id);
m_Notify->PushCell(sent ? 1 : 0);
m_Notify->Execute(&res);
}
@ -490,7 +491,7 @@ static cell_t smn_HookUserMessage(IPluginContext *pCtx, const cell_t *params)
pListener = s_UsrMessageNatives.CreateListener(pCtx);
pListener->Initialize(msgid, pHook, pNotify, intercept);
g_UserMsgs.HookUserMessage(msgid, pListener, intercept);
g_UserMsgs.HookUserMessage2(msgid, pListener, intercept);
return 1;
}
@ -521,7 +522,7 @@ static cell_t smn_UnhookUserMessage(IPluginContext *pCtx, const cell_t *params)
}
pListener = (*iter);
if (!g_UserMsgs.UnhookUserMessage(msgid, pListener, intercept))
if (!g_UserMsgs.UnhookUserMessage2(msgid, pListener, intercept))
{
return pCtx->ThrowNativeError("Unable to unhook the current user message");
}

View File

@ -45,7 +45,7 @@ public:
public: //IUserMessageListener
void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
ResultType InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
void OnUserMessageSent(int msg_id);
void OnPostUserMessage(int msg_id, bool sent);
private:
size_t _FillInPlayers(int *pl_array, IRecipientFilter *pFilter);
private:

View File

@ -38,7 +38,7 @@
#include <version>
/** If this gets changed, you need to update Core's check. */
#define SOURCEMOD_PLUGINAPI_VERSION 4
#define SOURCEMOD_PLUGINAPI_VERSION 5
struct PlVers
{

View File

@ -127,11 +127,12 @@ native EndMessage();
functag public Action:MsgHook(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init);
/**
* Called when a message is finished sending.
* Called when a message hook has completed.
*
* @param msg_id Message index.
* @param sent True if message was sent, false if blocked.
*/
functag public MsgSentNotify(UserMsg:msg_id);
functag public MsgPostHook(UserMsg:msg_id, bool:sent);
/**
* Hooks a user message.
@ -145,7 +146,7 @@ functag public MsgSentNotify(UserMsg:msg_id);
* @noreturn
* @error Invalid message index.
*/
native HookUserMessage(UserMsg:msg_id, MsgHook:hook, bool:intercept=false, MsgSentNotify:notify=MsgSentNotify:-1);
native HookUserMessage(UserMsg:msg_id, MsgHook:hook, bool:intercept=false, MsgPostHook:post=MsgPostHook:-1);
/**
* Removes one usermessage hook.

View File

@ -44,7 +44,7 @@
*/
#define SMINTERFACE_USERMSGS_NAME "IUserMessages"
#define SMINTERFACE_USERMSGS_VERSION 1
#define SMINTERFACE_USERMSGS_VERSION 2
namespace SourceMod
{
@ -81,11 +81,35 @@ namespace SourceMod
/**
* @brief Called when a hooked user message is sent, regardless of the hook type.
*
* Note: This is called regardless of the API version, though it only happens if the
* message is successfully sent.
*
* @param msg_id Message Id.
*/
virtual void OnUserMessageSent(int msg_id)
{
}
/**
* @brief Returns the user message API version.
*/
virtual unsigned int GetUserMessageAPIVersion()
{
return SMINTERFACE_USERMSGS_VERSION;
}
/**
* @brief Called when a hooked user message hook is finished, regardless of the hook type.
*
* Note: this is only called if hooked using the new API (version 2 or greater).
*
* @param msg_id Message Id.
* @param sent True if message was sent, false if blocked.
*/
virtual void OnPostUserMessage(int msg_id, bool sent)
{
}
};
#define USERMSG_RELIABLE (1<<2) /**< Message will be set to reliable */
@ -123,17 +147,22 @@ namespace SourceMod
* @param intercept If true, message will be intercepted rather than merely hooked.
* @return True on success, false otherwise.
*/
virtual bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false) =0;
virtual bool HookUserMessage(int msg_id,
IUserMessageListener *pListener,
bool intercept=false) =0;
/**
* @brief Unhooks a user message.
*
* @param msg_id Message Id.
* @param pListener Pointer to an IUserMessageListener.
* @param intercept If true, removed message will from interception pool rather than normal hook pool.
* @param intercept If true, message is removed from interception pool rather than the
* normal hook pool.
* @return True on success, false otherwise.
*/
virtual bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false) =0;
virtual bool UnhookUserMessage(int msg_id,
IUserMessageListener *pListener,
bool intercept=false) =0;
/**
* @brief Wrapper around UserMessageBegin for more options.
@ -144,13 +173,41 @@ namespace SourceMod
* @param flags Flags to use for sending the message.
* @return bf_write structure to write message with, or NULL on failure.
*/
virtual bf_write *StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags) =0;
virtual bf_write *StartMessage(int msg_id,
const cell_t players[],
unsigned int playersNum,
int flags) =0;
/**
* @brief Wrapper around UserMessageEnd for use with StartMessage().
* @return True on success, false otherwise.
*/
virtual bool EndMessage() =0;
/**
* @brief Sets a hook on a user message using the newer API (OnPostUserMessage).
*
* @param msg_id Message Id.
* @param pListener Pointer to an IUserMessageListener.
* @param intercept If true, message will be intercepted rather than merely hooked.
* @return True on success, false otherwise.
*/
virtual bool HookUserMessage2(int msg_id,
IUserMessageListener *pListener,
bool intercept=false) =0;
/**
* @brief Unhooks a user message using the newer API (OnPostUserMessage).
*
* @param msg_id Message Id.
* @param pListener Pointer to an IUserMessageListener.
* @param intercept If true, message is removed from interception pool rather than the
* normal hook pool.
* @return True on success, false otherwise.
*/
virtual bool UnhookUserMessage2(int msg_id,
IUserMessageListener *pListener,
bool intercept=false) =0;
};
}