Added part of amb1604: unregister_message - OH GOD I HOPE I DIDNT BREAK IT
This commit is contained in:
		@@ -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},
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user