core/smn_usermsgs.cpp
author David Anderson <dvander@alliedmods.net>
Wed Feb 27 13:49:57 2008 +0000 (2008-02-27)
changeset 1900 457329ae65bd
parent 1871 a152bfe8634b
child 1947 e73a1e51833b
permissions -rw-r--r--
fixed amb1483 - GetEntPropString() rejected FIELD_MODELNAME/FIELD_SOUNDNAME
faluco@505
     1
/**
dvander@600
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
dvander@1231
     5
 * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@600
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1231
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1231
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@600
    28
 *
dvander@600
    29
 * Version: $Id$
dvander@600
    30
 */
faluco@505
    31
faluco@505
    32
#include "HandleSys.h"
faluco@552
    33
#include "PluginSys.h"
dvander@592
    34
#include "UserMessages.h"
dvander@590
    35
#include "smn_usermsgs.h"
faluco@505
    36
faluco@505
    37
HandleType_t g_WrBitBufType;
faluco@598
    38
HandleType_t g_RdBitBufType;
faluco@505
    39
Handle_t g_CurMsgHandle;
faluco@598
    40
Handle_t g_ReadBufHandle;
faluco@598
    41
bf_read g_ReadBitBuf;
faluco@598
    42
faluco@552
    43
int g_MsgPlayers[256];
faluco@505
    44
bool g_IsMsgInExec = false;
faluco@505
    45
faluco@593
    46
typedef List<MsgListenerWrapper *> MsgWrapperList;
faluco@593
    47
typedef List<MsgListenerWrapper *>::iterator MsgWrapperIter;
faluco@593
    48
faluco@505
    49
class UsrMessageNatives :
faluco@505
    50
	public SMGlobalClass,
faluco@552
    51
	public IHandleTypeDispatch,
faluco@552
    52
	public IPluginsListener
faluco@505
    53
{
faluco@641
    54
public:
faluco@641
    55
	~UsrMessageNatives();
faluco@552
    56
public: //SMGlobalClass, IHandleTypeDispatch, IPluginListener
faluco@552
    57
	void OnSourceModAllInitialized();
faluco@552
    58
	void OnSourceModShutdown();
faluco@552
    59
	void OnHandleDestroy(HandleType_t type, void *object);
dvander@1766
    60
	bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
faluco@552
    61
	void OnPluginUnloaded(IPlugin *plugin);
faluco@505
    62
public:
faluco@593
    63
	MsgListenerWrapper *CreateListener(IPluginContext *pCtx);
faluco@1541
    64
	bool FindListener(int msgid, IPluginContext *pCtx, IPluginFunction *pHook, bool intercept, MsgWrapperIter *iter);
faluco@593
    65
	bool DeleteListener(IPluginContext *pCtx, MsgWrapperIter iter);
faluco@552
    66
private:
faluco@552
    67
	CStack<MsgListenerWrapper *> m_FreeListeners;
faluco@552
    68
};
faluco@552
    69
faluco@641
    70
UsrMessageNatives::~UsrMessageNatives()
faluco@641
    71
{
faluco@641
    72
	CStack<MsgListenerWrapper *>::iterator iter;
faluco@641
    73
	for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
faluco@641
    74
	{
faluco@641
    75
		delete (*iter);
faluco@641
    76
	}
faluco@641
    77
	m_FreeListeners.popall();
faluco@641
    78
}
faluco@641
    79
faluco@552
    80
void UsrMessageNatives::OnSourceModAllInitialized()
faluco@552
    81
{
faluco@598
    82
	HandleAccess sec;
faluco@1397
    83
faluco@1397
    84
	g_HandleSys.InitAccessDefaults(NULL, &sec);
faluco@1397
    85
	sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY;
faluco@598
    86
faluco@552
    87
	g_WrBitBufType = g_HandleSys.CreateType("BitBufWriter", this, 0, NULL, NULL, g_pCoreIdent, NULL);
faluco@598
    88
	g_RdBitBufType = g_HandleSys.CreateType("BitBufReader", this, 0, NULL, &sec, g_pCoreIdent, NULL);
faluco@598
    89
faluco@598
    90
	g_ReadBufHandle = g_HandleSys.CreateHandle(g_RdBitBufType, &g_ReadBitBuf, NULL, g_pCoreIdent, NULL);
faluco@598
    91
faluco@552
    92
	g_PluginSys.AddPluginsListener(this);
faluco@552
    93
}
faluco@552
    94
faluco@552
    95
void UsrMessageNatives::OnSourceModShutdown()
faluco@552
    96
{
faluco@598
    97
	HandleSecurity sec;
faluco@598
    98
	sec.pIdentity = g_pCoreIdent;
faluco@598
    99
faluco@598
   100
	g_HandleSys.FreeHandle(g_ReadBufHandle, &sec);
faluco@598
   101
faluco@552
   102
	g_HandleSys.RemoveType(g_WrBitBufType, g_pCoreIdent);
faluco@598
   103
	g_HandleSys.RemoveType(g_RdBitBufType, g_pCoreIdent);
faluco@598
   104
faluco@552
   105
	g_WrBitBufType = 0;
faluco@598
   106
	g_RdBitBufType = 0;
faluco@552
   107
}
faluco@553
   108
faluco@552
   109
void UsrMessageNatives::OnHandleDestroy(HandleType_t type, void *object)
faluco@552
   110
{
faluco@552
   111
}
faluco@552
   112
dvander@1766
   113
bool UsrMessageNatives::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
dvander@1766
   114
{
pred@1871
   115
	*pSize = sizeof(bf_read);
dvander@1766
   116
dvander@1766
   117
	return true;
dvander@1766
   118
}
dvander@1766
   119
faluco@552
   120
void UsrMessageNatives::OnPluginUnloaded(IPlugin *plugin)
faluco@552
   121
{
faluco@593
   122
	MsgWrapperList *pList;
faluco@552
   123
faluco@593
   124
	if (plugin->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList), true))
faluco@505
   125
	{
faluco@593
   126
		MsgWrapperIter iter;
faluco@593
   127
		MsgListenerWrapper *pListener;
faluco@552
   128
faluco@593
   129
		for (iter=pList->begin(); iter!=pList->end(); iter++)
faluco@552
   130
		{
faluco@593
   131
			pListener = (*iter);
faluco@593
   132
			if (g_UserMsgs.UnhookUserMessage(pListener->GetMessageId(), pListener, pListener->IsInterceptHook()))
faluco@552
   133
			{
faluco@593
   134
				m_FreeListeners.push(pListener);
faluco@552
   135
			}
faluco@552
   136
		}
faluco@552
   137
faluco@593
   138
		delete pList;
faluco@552
   139
	}
faluco@552
   140
}
faluco@552
   141
faluco@593
   142
MsgListenerWrapper *UsrMessageNatives::CreateListener(IPluginContext *pCtx)
faluco@552
   143
{
faluco@593
   144
	MsgWrapperList *pList;
faluco@593
   145
	MsgListenerWrapper *pListener;
faluco@593
   146
	IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext());
faluco@552
   147
faluco@552
   148
	if (m_FreeListeners.empty())
faluco@552
   149
	{
faluco@593
   150
		pListener = new MsgListenerWrapper;
faluco@552
   151
	} else {
faluco@593
   152
		pListener = m_FreeListeners.front();
faluco@552
   153
		m_FreeListeners.pop();
faluco@505
   154
	}
faluco@552
   155
faluco@593
   156
	if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList)))
faluco@505
   157
	{
faluco@593
   158
		pList = new List<MsgListenerWrapper *>;
faluco@593
   159
		pl->SetProperty("MsgListeners", pList);
faluco@552
   160
	}
faluco@552
   161
faluco@593
   162
	pList->push_back(pListener);
faluco@552
   163
faluco@593
   164
	return pListener;
faluco@552
   165
}
faluco@552
   166
faluco@1541
   167
bool UsrMessageNatives::FindListener(int msgid, IPluginContext *pCtx, IPluginFunction *pHook, bool intercept, MsgWrapperIter *iter)
faluco@552
   168
{
faluco@593
   169
	MsgWrapperList *pList;
faluco@1541
   170
	MsgWrapperIter _iter;
faluco@593
   171
	MsgListenerWrapper *pListener;
faluco@552
   172
	IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext());
faluco@552
   173
faluco@593
   174
	if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList)))
faluco@552
   175
	{
faluco@1541
   176
		return false;
faluco@505
   177
	}
faluco@552
   178
faluco@1541
   179
	for (_iter=pList->begin(); _iter!=pList->end(); _iter++)
faluco@505
   180
	{
faluco@1541
   181
		pListener = (*_iter);
faluco@593
   182
		if ((msgid == pListener->GetMessageId()) 
faluco@593
   183
			&& (intercept == pListener->IsInterceptHook()) 
faluco@593
   184
			&& (pHook == pListener->GetHookedFunction()))
faluco@552
   185
		{
faluco@1541
   186
			*iter = _iter;
faluco@1541
   187
			return true;
faluco@552
   188
		}
faluco@505
   189
	}
faluco@552
   190
faluco@1541
   191
	return false;
faluco@552
   192
}
faluco@553
   193
faluco@593
   194
bool UsrMessageNatives::DeleteListener(IPluginContext *pCtx, MsgWrapperIter iter)
faluco@552
   195
{
faluco@593
   196
	MsgWrapperList *pList;
faluco@593
   197
	MsgListenerWrapper *pListener;
faluco@552
   198
	IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext());
faluco@552
   199
faluco@593
   200
	if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList)))
faluco@552
   201
	{
faluco@552
   202
		return false;
faluco@552
   203
	}
faluco@552
   204
faluco@593
   205
	pListener = (*iter);
faluco@593
   206
	pList->erase(iter);
faluco@593
   207
	m_FreeListeners.push(pListener);
faluco@552
   208
faluco@552
   209
	return true;
faluco@552
   210
}
faluco@552
   211
dvander@590
   212
/***************************************
dvander@590
   213
 *                                     *
dvander@590
   214
 * USER MESSAGE WRAPPER IMPLEMENTATION *
dvander@590
   215
 *                                     *
dvander@590
   216
 ***************************************/
dvander@590
   217
faluco@593
   218
void MsgListenerWrapper::Initialize(int msgid, IPluginFunction *hook, IPluginFunction *notify, bool intercept)
faluco@593
   219
{
faluco@593
   220
	if (intercept)
faluco@593
   221
	{
faluco@593
   222
		m_Intercept = hook;
faluco@593
   223
		m_Hook = NULL;
faluco@593
   224
	} else {
faluco@593
   225
		m_Hook = hook;
faluco@593
   226
		m_Intercept = NULL;
faluco@593
   227
	}
faluco@593
   228
faluco@593
   229
	if (notify)
faluco@593
   230
	{
faluco@593
   231
		m_Notify = notify;
faluco@593
   232
	} else {
faluco@593
   233
		m_Notify = NULL;
faluco@593
   234
	}
faluco@593
   235
faluco@593
   236
	m_MsgId = msgid;
faluco@593
   237
	m_IsInterceptHook = intercept;
faluco@593
   238
}
faluco@593
   239
faluco@593
   240
size_t MsgListenerWrapper::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter)
dvander@590
   241
{
dvander@590
   242
	size_t size = static_cast<size_t>(pFilter->GetRecipientCount());
dvander@590
   243
dvander@590
   244
	for (size_t i=0; i<size; i++)
dvander@590
   245
	{
dvander@590
   246
		pl_array[i] = pFilter->GetRecipientIndex(i);
dvander@590
   247
	}
dvander@590
   248
dvander@590
   249
	return size;
dvander@590
   250
}
dvander@590
   251
dvander@590
   252
bool MsgListenerWrapper::IsInterceptHook() const
dvander@590
   253
{
dvander@590
   254
	return m_IsInterceptHook;
dvander@590
   255
}
dvander@590
   256
dvander@590
   257
int MsgListenerWrapper::GetMessageId() const
dvander@590
   258
{
dvander@590
   259
	return m_MsgId;
dvander@590
   260
}
dvander@590
   261
dvander@590
   262
IPluginFunction *MsgListenerWrapper::GetHookedFunction() const
dvander@590
   263
{
dvander@590
   264
	if (m_Hook)
dvander@590
   265
	{
dvander@590
   266
		return m_Hook;
dvander@590
   267
	} else {
dvander@590
   268
		return m_Intercept;
dvander@590
   269
	}
dvander@590
   270
}
dvander@590
   271
dvander@590
   272
IPluginFunction *MsgListenerWrapper::GetNotifyFunction() const
dvander@590
   273
{
dvander@590
   274
	return m_Notify;
dvander@590
   275
}
dvander@590
   276
dvander@590
   277
void MsgListenerWrapper::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
dvander@590
   278
{
dvander@590
   279
	cell_t res;
faluco@593
   280
	size_t size = _FillInPlayers(g_MsgPlayers, pFilter);
dvander@590
   281
faluco@598
   282
	g_ReadBitBuf.StartReading(bf->GetBasePointer(), bf->GetNumBytesWritten());
faluco@598
   283
dvander@590
   284
	m_Hook->PushCell(msg_id);
faluco@598
   285
	m_Hook->PushCell(g_ReadBufHandle);
dvander@590
   286
	m_Hook->PushArray(g_MsgPlayers, size);
dvander@590
   287
	m_Hook->PushCell(size);
dvander@590
   288
	m_Hook->PushCell(pFilter->IsReliable());
dvander@590
   289
	m_Hook->PushCell(pFilter->IsInitMessage());
dvander@590
   290
	m_Hook->Execute(&res);
dvander@590
   291
}
dvander@590
   292
dvander@590
   293
ResultType MsgListenerWrapper::InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
dvander@590
   294
{
dvander@590
   295
	cell_t res = static_cast<cell_t>(Pl_Continue);
faluco@593
   296
	size_t size = _FillInPlayers(g_MsgPlayers, pFilter);
dvander@590
   297
faluco@598
   298
	g_ReadBitBuf.StartReading(bf->GetBasePointer(), bf->GetNumBytesWritten());
faluco@598
   299
dvander@590
   300
	m_Intercept->PushCell(msg_id);
faluco@598
   301
	m_Intercept->PushCell(g_ReadBufHandle);
dvander@590
   302
	m_Intercept->PushArray(g_MsgPlayers, size);
dvander@590
   303
	m_Intercept->PushCell(size);
dvander@590
   304
	m_Intercept->PushCell(pFilter->IsReliable());
dvander@590
   305
	m_Intercept->PushCell(pFilter->IsInitMessage());
dvander@590
   306
	m_Intercept->Execute(&res);
dvander@590
   307
dvander@590
   308
	return static_cast<ResultType>(res);
dvander@590
   309
}
dvander@590
   310
dvander@590
   311
void MsgListenerWrapper::OnUserMessageSent(int msg_id)
dvander@590
   312
{
dvander@590
   313
	if (!m_Notify)
dvander@590
   314
	{
dvander@590
   315
		return;
dvander@590
   316
	}
dvander@590
   317
faluco@593
   318
	cell_t res;
dvander@590
   319
	m_Notify->PushCell(msg_id);
dvander@590
   320
	m_Notify->Execute(&res);
dvander@590
   321
}
dvander@590
   322
dvander@590
   323
/***************************************
dvander@590
   324
 *                                     *
dvander@590
   325
 * USER MESSAGE NATIVE IMPLEMENTATIONS *
dvander@590
   326
 *                                     *
dvander@590
   327
 ***************************************/
faluco@552
   328
faluco@552
   329
static UsrMessageNatives s_UsrMessageNatives;
faluco@505
   330
faluco@505
   331
static cell_t smn_GetUserMessageId(IPluginContext *pCtx, const cell_t *params)
faluco@505
   332
{
faluco@505
   333
	char *msgname;
ds@698
   334
	pCtx->LocalToString(params[1], &msgname);
faluco@505
   335
faluco@552
   336
	return g_UserMsgs.GetMessageIndex(msgname);
faluco@505
   337
}
faluco@505
   338
faluco@553
   339
static cell_t smn_GetUserMessageName(IPluginContext *pCtx, const cell_t *params)
faluco@553
   340
{
ds@765
   341
	char *msgname;
faluco@553
   342
ds@765
   343
	pCtx->LocalToPhysAddr(params[2], (cell_t **)&msgname);
faluco@553
   344
ds@765
   345
	return g_UserMsgs.GetMessageName(params[1], msgname, params[3]);
faluco@553
   346
}
faluco@553
   347
faluco@505
   348
static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params)
faluco@505
   349
{
faluco@505
   350
	char *msgname;
faluco@505
   351
	cell_t *cl_array;
ds@698
   352
	int msgid;
faluco@505
   353
	bf_write *pBitBuf;
faluco@505
   354
faluco@505
   355
	if (g_IsMsgInExec)
faluco@505
   356
	{
faluco@505
   357
		return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
faluco@505
   358
	}
faluco@505
   359
ds@698
   360
	pCtx->LocalToString(params[1], &msgname);
faluco@505
   361
faluco@552
   362
	if ((msgid=g_UserMsgs.GetMessageIndex(msgname)) == INVALID_MESSAGE_ID)
faluco@505
   363
	{
faluco@505
   364
		return pCtx->ThrowNativeError("Invalid message name: \"%s\"", msgname);
faluco@505
   365
	}
faluco@505
   366
faluco@505
   367
	pCtx->LocalToPhysAddr(params[2], &cl_array);
faluco@505
   368
faluco@552
   369
	pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, params[3], params[4]);
faluco@593
   370
	if (!pBitBuf)
faluco@593
   371
	{
faluco@593
   372
		return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
faluco@593
   373
	}
faluco@505
   374
faluco@505
   375
	g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
faluco@505
   376
	g_IsMsgInExec = true;
faluco@505
   377
faluco@505
   378
	return g_CurMsgHandle;
faluco@505
   379
}
faluco@505
   380
faluco@505
   381
static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params)
faluco@505
   382
{
faluco@505
   383
	cell_t *cl_array;
faluco@505
   384
	bf_write *pBitBuf;
faluco@505
   385
	int msgid = params[1];
faluco@505
   386
faluco@505
   387
	if (g_IsMsgInExec)
faluco@505
   388
	{
faluco@505
   389
		return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
faluco@505
   390
	}
faluco@505
   391
faluco@552
   392
	if (msgid < 0 || msgid >= 255)
faluco@505
   393
	{
faluco@505
   394
		return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
faluco@505
   395
	}
faluco@505
   396
faluco@505
   397
	pCtx->LocalToPhysAddr(params[2], &cl_array);
faluco@505
   398
faluco@552
   399
	pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, params[3], params[4]);
faluco@593
   400
	if (!pBitBuf)
faluco@593
   401
	{
faluco@593
   402
		return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
faluco@593
   403
	}
faluco@505
   404
faluco@505
   405
	g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
faluco@505
   406
	g_IsMsgInExec = true;
faluco@505
   407
faluco@505
   408
	return g_CurMsgHandle;
faluco@505
   409
}
faluco@505
   410
faluco@505
   411
static cell_t smn_EndMessage(IPluginContext *pCtx, const cell_t *params)
faluco@505
   412
{
faluco@505
   413
	HandleSecurity sec;
faluco@505
   414
faluco@505
   415
	if (!g_IsMsgInExec)
faluco@505
   416
	{
faluco@505
   417
		return pCtx->ThrowNativeError("Unable to end message, no message is in progress");
faluco@505
   418
	}
faluco@505
   419
faluco@552
   420
	g_UserMsgs.EndMessage();
faluco@505
   421
faluco@505
   422
	sec.pOwner = pCtx->GetIdentity();
faluco@505
   423
	sec.pIdentity = g_pCoreIdent;
faluco@505
   424
	g_HandleSys.FreeHandle(g_CurMsgHandle, &sec);
faluco@505
   425
faluco@505
   426
	g_IsMsgInExec = false;
faluco@552
   427
faluco@552
   428
	return 1;
faluco@552
   429
}
faluco@552
   430
faluco@552
   431
static cell_t smn_HookUserMessage(IPluginContext *pCtx, const cell_t *params)
faluco@552
   432
{
faluco@552
   433
	IPluginFunction *pHook, *pNotify;
faluco@593
   434
	MsgListenerWrapper *pListener;
faluco@552
   435
	bool intercept;
faluco@552
   436
	int msgid = params[1];
faluco@552
   437
faluco@552
   438
	if (msgid < 0 || msgid >= 255)
faluco@552
   439
	{
faluco@552
   440
		return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
faluco@552
   441
	}
faluco@552
   442
faluco@552
   443
	pHook = pCtx->GetFunctionById(params[2]);
faluco@552
   444
	if (!pHook)
faluco@552
   445
	{
faluco@552
   446
		return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]);
faluco@552
   447
	}
faluco@552
   448
	pNotify = pCtx->GetFunctionById(params[4]);
faluco@593
   449
	intercept = (params[3]) ? true : false;
faluco@552
   450
faluco@593
   451
	pListener = s_UsrMessageNatives.CreateListener(pCtx);
faluco@593
   452
	pListener->Initialize(msgid, pHook, pNotify, intercept);
faluco@553
   453
faluco@593
   454
	g_UserMsgs.HookUserMessage(msgid, pListener, intercept);
faluco@505
   455
faluco@505
   456
	return 1;
faluco@505
   457
}
faluco@505
   458
ds@626
   459
static cell_t smn_UnhookUserMessage(IPluginContext *pCtx, const cell_t *params)
faluco@552
   460
{
faluco@552
   461
	IPluginFunction *pFunc;
faluco@593
   462
	MsgListenerWrapper *pListener;
faluco@593
   463
	MsgWrapperIter iter;
faluco@552
   464
	bool intercept;
faluco@552
   465
	int msgid = params[1];
faluco@552
   466
faluco@552
   467
	if (msgid < 0 || msgid >= 255)
faluco@552
   468
	{
faluco@552
   469
		return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
faluco@552
   470
	}
faluco@552
   471
faluco@552
   472
	pFunc = pCtx->GetFunctionById(params[2]);
faluco@552
   473
	if (!pFunc)
faluco@552
   474
	{
faluco@552
   475
		return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]);
faluco@552
   476
	}
faluco@593
   477
	intercept = (params[3]) ? true : false;
faluco@552
   478
faluco@1541
   479
	if (!s_UsrMessageNatives.FindListener(msgid, pCtx, pFunc, intercept, &iter))
faluco@552
   480
	{
faluco@552
   481
		return pCtx->ThrowNativeError("Unable to unhook the current user message");
faluco@552
   482
	}
faluco@552
   483
faluco@593
   484
	pListener = (*iter);
faluco@593
   485
	if (!g_UserMsgs.UnhookUserMessage(msgid, pListener, intercept))
faluco@552
   486
	{
faluco@552
   487
		return pCtx->ThrowNativeError("Unable to unhook the current user message");
faluco@552
   488
	}
faluco@552
   489
faluco@593
   490
	s_UsrMessageNatives.DeleteListener(pCtx, iter);
faluco@552
   491
faluco@552
   492
	return 1;
faluco@552
   493
}
faluco@505
   494
faluco@505
   495
REGISTER_NATIVES(usrmsgnatives)
faluco@505
   496
{
faluco@505
   497
	{"GetUserMessageId",			smn_GetUserMessageId},
faluco@553
   498
	{"GetUserMessageName",			smn_GetUserMessageName},
faluco@505
   499
	{"StartMessage",				smn_StartMessage},
faluco@505
   500
	{"StartMessageEx",				smn_StartMessageEx},
faluco@505
   501
	{"EndMessage",					smn_EndMessage},
faluco@552
   502
	{"HookUserMessage",				smn_HookUserMessage},
ds@626
   503
	{"UnhookUserMessage",			smn_UnhookUserMessage},
faluco@505
   504
	{NULL,							NULL}
faluco@505
   505
};