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