Added part of amb1604: unregister_message - OH GOD I HOPE I DIDNT BREAK IT

This commit is contained in:
Steve Dudenhoeffer 2008-04-29 02:18:39 +00:00
parent 9100ec753c
commit f410ea743d
3 changed files with 175 additions and 8 deletions

View File

@ -2,7 +2,8 @@
#include "messages.h"
Message Msg;
CVector<int> msgHooks[256];
//CVector<int> msgHooks[256];
RegisteredMessage msgHooks[256];
int msgBlocks[256] = {BLOCK_NOT};
int msgDest;
int msgType;
@ -16,7 +17,7 @@ void ClearMessages()
{
for (size_t i=0; i<MAX_MESSAGES; i++)
{
msgHooks[i].clear();
msgHooks[i].Clear();
msgBlocks[i] = BLOCK_NOT;
}
}
@ -200,7 +201,7 @@ void C_MessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *e
inblock = true;
msgType = msg_type;
RETURN_META(MRES_SUPERCEDE);
} else if (msgHooks[msg_type].size()) {
} else if (msgHooks[msg_type].Hooked()) {
inhook = true;
msgDest = msg_dest;
msgType = msg_type;
@ -318,8 +319,8 @@ void C_WriteEntity(int iValue)
void C_MessageEnd(void)
{
int mres = 0, mresB = 0;
unsigned int i = 0;
int mres = 0;
if (inblock)
{
inblock = false;
@ -329,12 +330,17 @@ void C_MessageEnd(void)
}
RETURN_META(MRES_SUPERCEDE);
} else if (inhook) {
mres = msgHooks[msgType].Execute((cell)msgType, (cell)msgDest, (cell)ENTINDEX(msgpEntity));
/*
for (i=0; i<msgHooks[msgType].size(); i++)
{
mresB = executeForwards(msgHooks[msgType].at(i), (cell)msgType, (cell)msgDest, (cell)ENTINDEX(msgpEntity));
if (mresB > mres)
mres = mresB;
}
*/
inhook = false;
if (mres & 1)
{
@ -477,7 +483,7 @@ static cell AMX_NATIVE_CALL register_message(AMX *amx, cell *params)
int id = registerSPForwardByName(amx, name, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
if (id != -1)
{
msgHooks[params[1]].push_back(id);
msgHooks[params[1]].AddHook(id);
return id;
} else {
LogError(amx, AMX_ERR_NOTFOUND, "Could not find function \"%s\"", name);
@ -488,6 +494,29 @@ static cell AMX_NATIVE_CALL register_message(AMX *amx, cell *params)
return 0;
}
// unregister_message(msgid, msghandle)
static cell AMX_NATIVE_CALL unregister_message(AMX *amx, cell *params)
{
if (!Msg.Ready())
Msg.Init();
if (params[1]>0 && params[1] < 256)
{
int id = params[2];
if (id != -1)
{
msgHooks[params[1]].RemoveHook(id);
return id;
} else {
LogError(amx, AMX_ERR_NOTFOUND, "Invalid registered message handle");
return -1;
}
}
return 0;
}
static cell AMX_NATIVE_CALL set_msg_block(AMX *amx, cell *params)
{
int msgid = params[1];
@ -775,6 +804,7 @@ AMX_NATIVE_INFO msg_Natives[] =
{"write_string", write_string},
{"register_message", register_message},
{"unregister_message", unregister_message},
{"set_msg_block", set_msg_block},
{"get_msg_block", get_msg_block},

View File

@ -6,6 +6,7 @@
#include "amx.h"
#include "CVector.h"
#include "CString.h"
#include "sh_stack.h"
#define MAX_MESSAGES 255
@ -15,6 +16,136 @@
#define BLOCK_ONCE 1
#define BLOCK_SET 2
class RegisteredMessage
{
private:
CVector<int> m_Forwards;
CStack<int> m_InExecution;
bool m_Cleanup;
public:
RegisteredMessage() : m_Cleanup(false) { }
~RegisteredMessage() { this->Clear(); }
void AddHook(int fwd)
{
m_Forwards.push_back(fwd);
}
bool RemoveHook(int fwd)
{
// Don't erase a forward if we're in the middle of execution; this
// could throw off the iterator that is going through the forwards
// and executing them. Instead, unregister the forward and set it
// to -1 from within the vector.
if (m_InExecution.size())
{
this->m_Cleanup = true;
CVector<int>::iterator iter = m_Forwards.begin();
CVector<int>::iterator end = m_Forwards.end();
while (iter != end)
{
if (*iter == fwd)
{
if (*iter != -1)
{
unregisterSPForward(*iter);
}
*iter = -1;
return true;
}
else
{
iter++;
}
}
}
else
{
CVector<int>::iterator iter = m_Forwards.begin();
CVector<int>::iterator end = m_Forwards.end();
while (iter != end)
{
if (*iter == fwd)
{
if (fwd != -1)
{
unregisterSPForward(fwd);
m_Forwards.erase(iter);
return true;
}
else
{
// -1 could be in here more than once
m_Forwards.erase(iter);
}
}
else
{
iter++;
}
}
}
return false;
}
void Clear()
{
while (m_InExecution.size())
{
m_InExecution.pop();
}
for (size_t i = 0; i < m_Forwards.size(); i++)
{
int fwd = m_Forwards[i];
if (fwd != -1)
{
unregisterSPForward(m_Forwards[i]);
}
}
m_Forwards.clear();
}
cell Execute(cell type, cell dest, cell entity)
{
m_InExecution.push(1);
cell res = 0;
cell thisres = 0;
for (size_t i = 0; i < m_Forwards.size(); i++)
{
int fwd = m_Forwards[i];
if (fwd != -1)
{
thisres = executeForwards(fwd, type, dest, entity);
if (thisres > res)
{
res = thisres;
}
}
}
m_InExecution.pop();
if (m_InExecution.size() == 0 && m_Cleanup)
{
this->RemoveHook(-1);
}
return res;
}
bool Hooked() const
{
return m_Forwards.size() != 0;
}
};
enum msgtype
{
arg_byte = 1,
@ -76,7 +207,7 @@ void C_WriteString(const char *sz);
void C_WriteEntity(int iValue);
void C_MessageEnd(void);
extern CVector<int> msgHooks[256];
extern RegisteredMessage msgHooks[256];
extern int msgBlocks[256];
void ClearMessages();

View File

@ -55,9 +55,15 @@ native get_msg_block(iMessage);
* or fully block it. Here is how it works:
* If you hook a message, the message is stored but not sent. You have the opportunity to
* not only execute code, but to get/set the contents of the message, before you choose to
* either block it or let it go on its way. The hooked function will be passed a msg_id, msg_dest, and entity index. */
* either block it or let it go on its way. The hooked function will be passed a msg_id, msg_dest, and entity index.
* The return value can be passed to unregister_message() to stop the message from being hooked */
native register_message(iMsgId, const szFunction[]);
/* Unregisters a message hook previously created with register_message
* You must pass the proper message id, and return value from the message to unregister the message successfully. */
native unregister_message(iMsgId, registeredmsg);
/* The get/set _msg commands will fail if used outside a hooked message scope.
* They should never be used unless inside a registered message function.
* There are eight different ways of sending a message, five are ints, two are floats, and one is string.