core/smn_usermsgs.cpp
author David Anderson <dvander@alliedmods.net>
Mon Oct 26 23:51:39 2009 -0700 (2009-10-26)
changeset 2832 bf5d37088b6d
parent 2736 3bab645fb4c7
child 3743 a98686a77974
permissions -rw-r--r--
Don't pass unconnected clients into OnClientCommand (bug 3732, r=fyren).
faluco@505
     1
/**
dvander@600
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 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"
ds@2112
    35
#include "PlayerManager.h"
dvander@590
    36
#include "smn_usermsgs.h"
faluco@505
    37
faluco@505
    38
HandleType_t g_WrBitBufType;
faluco@598
    39
HandleType_t g_RdBitBufType;
faluco@505
    40
Handle_t g_CurMsgHandle;
faluco@598
    41
Handle_t g_ReadBufHandle;
faluco@598
    42
bf_read g_ReadBitBuf;
faluco@598
    43
faluco@552
    44
int g_MsgPlayers[256];
faluco@505
    45
bool g_IsMsgInExec = false;
faluco@505
    46
faluco@593
    47
typedef List<MsgListenerWrapper *> MsgWrapperList;
faluco@593
    48
typedef List<MsgListenerWrapper *>::iterator MsgWrapperIter;
faluco@593
    49
faluco@505
    50
class UsrMessageNatives :
faluco@505
    51
	public SMGlobalClass,
faluco@552
    52
	public IHandleTypeDispatch,
faluco@552
    53
	public IPluginsListener
faluco@505
    54
{
faluco@641
    55
public:
faluco@641
    56
	~UsrMessageNatives();
faluco@552
    57
public: //SMGlobalClass, IHandleTypeDispatch, IPluginListener
faluco@552
    58
	void OnSourceModAllInitialized();
faluco@552
    59
	void OnSourceModShutdown();
faluco@552
    60
	void OnHandleDestroy(HandleType_t type, void *object);
dvander@1766
    61
	bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
faluco@552
    62
	void OnPluginUnloaded(IPlugin *plugin);
faluco@505
    63
public:
faluco@593
    64
	MsgListenerWrapper *CreateListener(IPluginContext *pCtx);
faluco@1541
    65
	bool FindListener(int msgid, IPluginContext *pCtx, IPluginFunction *pHook, bool intercept, MsgWrapperIter *iter);
faluco@593
    66
	bool DeleteListener(IPluginContext *pCtx, MsgWrapperIter iter);
faluco@552
    67
private:
faluco@552
    68
	CStack<MsgListenerWrapper *> m_FreeListeners;
faluco@552
    69
};
faluco@552
    70
faluco@641
    71
UsrMessageNatives::~UsrMessageNatives()
faluco@641
    72
{
faluco@641
    73
	CStack<MsgListenerWrapper *>::iterator iter;
faluco@641
    74
	for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
faluco@641
    75
	{
faluco@641
    76
		delete (*iter);
faluco@641
    77
	}
faluco@641
    78
	m_FreeListeners.popall();
faluco@641
    79
}
faluco@641
    80
faluco@552
    81
void UsrMessageNatives::OnSourceModAllInitialized()
faluco@552
    82
{
faluco@598
    83
	HandleAccess sec;
faluco@1397
    84
faluco@1397
    85
	g_HandleSys.InitAccessDefaults(NULL, &sec);
faluco@1397
    86
	sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY;
faluco@598
    87
faluco@552
    88
	g_WrBitBufType = g_HandleSys.CreateType("BitBufWriter", this, 0, NULL, NULL, g_pCoreIdent, NULL);
faluco@598
    89
	g_RdBitBufType = g_HandleSys.CreateType("BitBufReader", this, 0, NULL, &sec, g_pCoreIdent, NULL);
faluco@598
    90
faluco@598
    91
	g_ReadBufHandle = g_HandleSys.CreateHandle(g_RdBitBufType, &g_ReadBitBuf, NULL, g_pCoreIdent, NULL);
faluco@598
    92
faluco@552
    93
	g_PluginSys.AddPluginsListener(this);
faluco@552
    94
}
faluco@552
    95
faluco@552
    96
void UsrMessageNatives::OnSourceModShutdown()
faluco@552
    97
{
faluco@598
    98
	HandleSecurity sec;
faluco@598
    99
	sec.pIdentity = g_pCoreIdent;
faluco@598
   100
faluco@598
   101
	g_HandleSys.FreeHandle(g_ReadBufHandle, &sec);
faluco@598
   102
faluco@552
   103
	g_HandleSys.RemoveType(g_WrBitBufType, g_pCoreIdent);
faluco@598
   104
	g_HandleSys.RemoveType(g_RdBitBufType, g_pCoreIdent);
faluco@598
   105
faluco@552
   106
	g_WrBitBufType = 0;
faluco@598
   107
	g_RdBitBufType = 0;
faluco@552
   108
}
faluco@553
   109
faluco@552
   110
void UsrMessageNatives::OnHandleDestroy(HandleType_t type, void *object)
faluco@552
   111
{
faluco@552
   112
}
faluco@552
   113
dvander@1766
   114
bool UsrMessageNatives::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
dvander@1766
   115
{
pred@1871
   116
	*pSize = sizeof(bf_read);
dvander@1766
   117
dvander@1766
   118
	return true;
dvander@1766
   119
}
dvander@1766
   120
faluco@552
   121
void UsrMessageNatives::OnPluginUnloaded(IPlugin *plugin)
faluco@552
   122
{
faluco@593
   123
	MsgWrapperList *pList;
faluco@552
   124
faluco@593
   125
	if (plugin->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList), true))
faluco@505
   126
	{
faluco@593
   127
		MsgWrapperIter iter;
faluco@593
   128
		MsgListenerWrapper *pListener;
faluco@552
   129
faluco@593
   130
		for (iter=pList->begin(); iter!=pList->end(); iter++)
faluco@552
   131
		{
faluco@593
   132
			pListener = (*iter);
fyrenmoo@2736
   133
			if (g_UserMsgs.UnhookUserMessage2(pListener->GetMessageId(), pListener, pListener->IsInterceptHook()))
faluco@552
   134
			{
faluco@593
   135
				m_FreeListeners.push(pListener);
faluco@552
   136
			}
faluco@552
   137
		}
faluco@552
   138
faluco@593
   139
		delete pList;
faluco@552
   140
	}
faluco@552
   141
}
faluco@552
   142
faluco@593
   143
MsgListenerWrapper *UsrMessageNatives::CreateListener(IPluginContext *pCtx)
faluco@552
   144
{
faluco@593
   145
	MsgWrapperList *pList;
faluco@593
   146
	MsgListenerWrapper *pListener;
faluco@593
   147
	IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext());
faluco@552
   148
faluco@552
   149
	if (m_FreeListeners.empty())
faluco@552
   150
	{
faluco@593
   151
		pListener = new MsgListenerWrapper;
faluco@552
   152
	} else {
faluco@593
   153
		pListener = m_FreeListeners.front();
faluco@552
   154
		m_FreeListeners.pop();
faluco@505
   155
	}
faluco@552
   156
faluco@593
   157
	if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList)))
faluco@505
   158
	{
faluco@593
   159
		pList = new List<MsgListenerWrapper *>;
faluco@593
   160
		pl->SetProperty("MsgListeners", pList);
faluco@552
   161
	}
faluco@552
   162
faluco@593
   163
	pList->push_back(pListener);
faluco@552
   164
faluco@593
   165
	return pListener;
faluco@552
   166
}
faluco@552
   167
faluco@1541
   168
bool UsrMessageNatives::FindListener(int msgid, IPluginContext *pCtx, IPluginFunction *pHook, bool intercept, MsgWrapperIter *iter)
faluco@552
   169
{
faluco@593
   170
	MsgWrapperList *pList;
faluco@1541
   171
	MsgWrapperIter _iter;
faluco@593
   172
	MsgListenerWrapper *pListener;
faluco@552
   173
	IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext());
faluco@552
   174
faluco@593
   175
	if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList)))
faluco@552
   176
	{
faluco@1541
   177
		return false;
faluco@505
   178
	}
faluco@552
   179
faluco@1541
   180
	for (_iter=pList->begin(); _iter!=pList->end(); _iter++)
faluco@505
   181
	{
faluco@1541
   182
		pListener = (*_iter);
faluco@593
   183
		if ((msgid == pListener->GetMessageId()) 
faluco@593
   184
			&& (intercept == pListener->IsInterceptHook()) 
faluco@593
   185
			&& (pHook == pListener->GetHookedFunction()))
faluco@552
   186
		{
faluco@1541
   187
			*iter = _iter;
faluco@1541
   188
			return true;
faluco@552
   189
		}
faluco@505
   190
	}
faluco@552
   191
faluco@1541
   192
	return false;
faluco@552
   193
}
faluco@553
   194
faluco@593
   195
bool UsrMessageNatives::DeleteListener(IPluginContext *pCtx, MsgWrapperIter iter)
faluco@552
   196
{
faluco@593
   197
	MsgWrapperList *pList;
faluco@593
   198
	MsgListenerWrapper *pListener;
faluco@552
   199
	IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext());
faluco@552
   200
faluco@593
   201
	if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList)))
faluco@552
   202
	{
faluco@552
   203
		return false;
faluco@552
   204
	}
faluco@552
   205
faluco@593
   206
	pListener = (*iter);
faluco@593
   207
	pList->erase(iter);
faluco@593
   208
	m_FreeListeners.push(pListener);
faluco@552
   209
faluco@552
   210
	return true;
faluco@552
   211
}
faluco@552
   212
dvander@590
   213
/***************************************
dvander@590
   214
 *                                     *
dvander@590
   215
 * USER MESSAGE WRAPPER IMPLEMENTATION *
dvander@590
   216
 *                                     *
dvander@590
   217
 ***************************************/
dvander@590
   218
faluco@593
   219
void MsgListenerWrapper::Initialize(int msgid, IPluginFunction *hook, IPluginFunction *notify, bool intercept)
faluco@593
   220
{
faluco@593
   221
	if (intercept)
faluco@593
   222
	{
faluco@593
   223
		m_Intercept = hook;
faluco@593
   224
		m_Hook = NULL;
faluco@593
   225
	} else {
faluco@593
   226
		m_Hook = hook;
faluco@593
   227
		m_Intercept = NULL;
faluco@593
   228
	}
faluco@593
   229
faluco@593
   230
	if (notify)
faluco@593
   231
	{
faluco@593
   232
		m_Notify = notify;
faluco@593
   233
	} else {
faluco@593
   234
		m_Notify = NULL;
faluco@593
   235
	}
faluco@593
   236
faluco@593
   237
	m_MsgId = msgid;
faluco@593
   238
	m_IsInterceptHook = intercept;
faluco@593
   239
}
faluco@593
   240
faluco@593
   241
size_t MsgListenerWrapper::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter)
dvander@590
   242
{
dvander@590
   243
	size_t size = static_cast<size_t>(pFilter->GetRecipientCount());
dvander@590
   244
dvander@590
   245
	for (size_t i=0; i<size; i++)
dvander@590
   246
	{
dvander@590
   247
		pl_array[i] = pFilter->GetRecipientIndex(i);
dvander@590
   248
	}
dvander@590
   249
dvander@590
   250
	return size;
dvander@590
   251
}
dvander@590
   252
dvander@590
   253
bool MsgListenerWrapper::IsInterceptHook() const
dvander@590
   254
{
dvander@590
   255
	return m_IsInterceptHook;
dvander@590
   256
}
dvander@590
   257
dvander@590
   258
int MsgListenerWrapper::GetMessageId() const
dvander@590
   259
{
dvander@590
   260
	return m_MsgId;
dvander@590
   261
}
dvander@590
   262
dvander@590
   263
IPluginFunction *MsgListenerWrapper::GetHookedFunction() const
dvander@590
   264
{
dvander@590
   265
	if (m_Hook)
dvander@590
   266
	{
dvander@590
   267
		return m_Hook;
dvander@590
   268
	} else {
dvander@590
   269
		return m_Intercept;
dvander@590
   270
	}
dvander@590
   271
}
dvander@590
   272
dvander@590
   273
IPluginFunction *MsgListenerWrapper::GetNotifyFunction() const
dvander@590
   274
{
dvander@590
   275
	return m_Notify;
dvander@590
   276
}
dvander@590
   277
dvander@590
   278
void MsgListenerWrapper::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
dvander@590
   279
{
dvander@590
   280
	cell_t res;
faluco@593
   281
	size_t size = _FillInPlayers(g_MsgPlayers, pFilter);
dvander@590
   282
faluco@598
   283
	g_ReadBitBuf.StartReading(bf->GetBasePointer(), bf->GetNumBytesWritten());
faluco@598
   284
dvander@590
   285
	m_Hook->PushCell(msg_id);
faluco@598
   286
	m_Hook->PushCell(g_ReadBufHandle);
dvander@590
   287
	m_Hook->PushArray(g_MsgPlayers, size);
dvander@590
   288
	m_Hook->PushCell(size);
dvander@590
   289
	m_Hook->PushCell(pFilter->IsReliable());
dvander@590
   290
	m_Hook->PushCell(pFilter->IsInitMessage());
dvander@590
   291
	m_Hook->Execute(&res);
dvander@590
   292
}
dvander@590
   293
dvander@590
   294
ResultType MsgListenerWrapper::InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
dvander@590
   295
{
dvander@590
   296
	cell_t res = static_cast<cell_t>(Pl_Continue);
faluco@593
   297
	size_t size = _FillInPlayers(g_MsgPlayers, pFilter);
dvander@590
   298
faluco@598
   299
	g_ReadBitBuf.StartReading(bf->GetBasePointer(), bf->GetNumBytesWritten());
faluco@598
   300
dvander@590
   301
	m_Intercept->PushCell(msg_id);
faluco@598
   302
	m_Intercept->PushCell(g_ReadBufHandle);
dvander@590
   303
	m_Intercept->PushArray(g_MsgPlayers, size);
dvander@590
   304
	m_Intercept->PushCell(size);
dvander@590
   305
	m_Intercept->PushCell(pFilter->IsReliable());
dvander@590
   306
	m_Intercept->PushCell(pFilter->IsInitMessage());
dvander@590
   307
	m_Intercept->Execute(&res);
dvander@590
   308
dvander@590
   309
	return static_cast<ResultType>(res);
dvander@590
   310
}
dvander@590
   311
dvander@2636
   312
void MsgListenerWrapper::OnPostUserMessage(int msg_id, bool sent)
dvander@590
   313
{
dvander@590
   314
	if (!m_Notify)
dvander@590
   315
	{
dvander@590
   316
		return;
dvander@590
   317
	}
dvander@590
   318
faluco@593
   319
	cell_t res;
dvander@590
   320
	m_Notify->PushCell(msg_id);
dvander@2636
   321
	m_Notify->PushCell(sent ? 1 : 0);
dvander@590
   322
	m_Notify->Execute(&res);
dvander@590
   323
}
dvander@590
   324
dvander@590
   325
/***************************************
dvander@590
   326
 *                                     *
dvander@590
   327
 * USER MESSAGE NATIVE IMPLEMENTATIONS *
dvander@590
   328
 *                                     *
dvander@590
   329
 ***************************************/
faluco@552
   330
faluco@552
   331
static UsrMessageNatives s_UsrMessageNatives;
faluco@505
   332
faluco@505
   333
static cell_t smn_GetUserMessageId(IPluginContext *pCtx, const cell_t *params)
faluco@505
   334
{
faluco@505
   335
	char *msgname;
ds@698
   336
	pCtx->LocalToString(params[1], &msgname);
faluco@505
   337
faluco@552
   338
	return g_UserMsgs.GetMessageIndex(msgname);
faluco@505
   339
}
faluco@505
   340
faluco@553
   341
static cell_t smn_GetUserMessageName(IPluginContext *pCtx, const cell_t *params)
faluco@553
   342
{
ds@765
   343
	char *msgname;
faluco@553
   344
ds@765
   345
	pCtx->LocalToPhysAddr(params[2], (cell_t **)&msgname);
faluco@553
   346
ds@765
   347
	return g_UserMsgs.GetMessageName(params[1], msgname, params[3]);
faluco@553
   348
}
faluco@553
   349
faluco@505
   350
static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params)
faluco@505
   351
{
faluco@505
   352
	char *msgname;
faluco@505
   353
	cell_t *cl_array;
ds@2112
   354
	unsigned int numClients;
ds@698
   355
	int msgid;
faluco@505
   356
	bf_write *pBitBuf;
ds@2112
   357
	int client;
ds@2112
   358
	CPlayer *pPlayer = NULL;
faluco@505
   359
faluco@505
   360
	if (g_IsMsgInExec)
faluco@505
   361
	{
faluco@505
   362
		return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
faluco@505
   363
	}
faluco@505
   364
ds@698
   365
	pCtx->LocalToString(params[1], &msgname);
faluco@505
   366
faluco@552
   367
	if ((msgid=g_UserMsgs.GetMessageIndex(msgname)) == INVALID_MESSAGE_ID)
faluco@505
   368
	{
faluco@505
   369
		return pCtx->ThrowNativeError("Invalid message name: \"%s\"", msgname);
faluco@505
   370
	}
faluco@505
   371
faluco@505
   372
	pCtx->LocalToPhysAddr(params[2], &cl_array);
faluco@505
   373
ds@2112
   374
	numClients = params[3];
ds@2112
   375
ds@2112
   376
	/* Client validation */
ds@2112
   377
	for (unsigned int i = 0; i < numClients; i++)
ds@2112
   378
	{
ds@2112
   379
		client = cl_array[i];
ds@2112
   380
		pPlayer = g_Players.GetPlayerByIndex(client);
ds@2112
   381
ds@2112
   382
		if (!pPlayer)
ds@2112
   383
		{
ds@2112
   384
			return pCtx->ThrowNativeError("Client index %d is invalid", client);
ds@2112
   385
		} else if (!pPlayer->IsConnected()) {
ds@2112
   386
			return pCtx->ThrowNativeError("Client %d is not connected", client);
ds@2112
   387
		}
ds@2112
   388
	}
ds@2112
   389
ds@2112
   390
	pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, numClients, params[4]);
faluco@593
   391
	if (!pBitBuf)
faluco@593
   392
	{
faluco@593
   393
		return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
faluco@593
   394
	}
faluco@505
   395
faluco@505
   396
	g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
faluco@505
   397
	g_IsMsgInExec = true;
faluco@505
   398
faluco@505
   399
	return g_CurMsgHandle;
faluco@505
   400
}
faluco@505
   401
faluco@505
   402
static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params)
faluco@505
   403
{
faluco@505
   404
	cell_t *cl_array;
ds@2112
   405
	unsigned int numClients;
faluco@505
   406
	bf_write *pBitBuf;
ds@2112
   407
	int client;
ds@2112
   408
	CPlayer *pPlayer = NULL;
faluco@505
   409
	int msgid = params[1];
faluco@505
   410
faluco@505
   411
	if (g_IsMsgInExec)
faluco@505
   412
	{
faluco@505
   413
		return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
faluco@505
   414
	}
faluco@505
   415
faluco@552
   416
	if (msgid < 0 || msgid >= 255)
faluco@505
   417
	{
faluco@505
   418
		return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
faluco@505
   419
	}
faluco@505
   420
faluco@505
   421
	pCtx->LocalToPhysAddr(params[2], &cl_array);
faluco@505
   422
ds@2112
   423
	numClients = params[3];
ds@2112
   424
ds@2112
   425
	/* Client validation */
ds@2112
   426
	for (unsigned int i = 0; i < numClients; i++)
ds@2112
   427
	{
ds@2112
   428
		client = cl_array[i];
ds@2112
   429
		pPlayer = g_Players.GetPlayerByIndex(client);
ds@2112
   430
ds@2112
   431
		if (!pPlayer)
ds@2112
   432
		{
ds@2112
   433
			return pCtx->ThrowNativeError("Client index %d is invalid", client);
ds@2112
   434
		} else if (!pPlayer->IsConnected()) {
ds@2112
   435
			return pCtx->ThrowNativeError("Client %d is not connected", client);
ds@2112
   436
		}
ds@2112
   437
	}
ds@2112
   438
ds@2112
   439
	pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, numClients, params[4]);
faluco@593
   440
	if (!pBitBuf)
faluco@593
   441
	{
faluco@593
   442
		return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
faluco@593
   443
	}
faluco@505
   444
faluco@505
   445
	g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
faluco@505
   446
	g_IsMsgInExec = true;
faluco@505
   447
faluco@505
   448
	return g_CurMsgHandle;
faluco@505
   449
}
faluco@505
   450
faluco@505
   451
static cell_t smn_EndMessage(IPluginContext *pCtx, const cell_t *params)
faluco@505
   452
{
faluco@505
   453
	HandleSecurity sec;
faluco@505
   454
faluco@505
   455
	if (!g_IsMsgInExec)
faluco@505
   456
	{
faluco@505
   457
		return pCtx->ThrowNativeError("Unable to end message, no message is in progress");
faluco@505
   458
	}
faluco@505
   459
faluco@552
   460
	g_UserMsgs.EndMessage();
faluco@505
   461
faluco@505
   462
	sec.pOwner = pCtx->GetIdentity();
faluco@505
   463
	sec.pIdentity = g_pCoreIdent;
faluco@505
   464
	g_HandleSys.FreeHandle(g_CurMsgHandle, &sec);
faluco@505
   465
faluco@505
   466
	g_IsMsgInExec = false;
faluco@552
   467
faluco@552
   468
	return 1;
faluco@552
   469
}
faluco@552
   470
faluco@552
   471
static cell_t smn_HookUserMessage(IPluginContext *pCtx, const cell_t *params)
faluco@552
   472
{
faluco@552
   473
	IPluginFunction *pHook, *pNotify;
faluco@593
   474
	MsgListenerWrapper *pListener;
faluco@552
   475
	bool intercept;
faluco@552
   476
	int msgid = params[1];
faluco@552
   477
faluco@552
   478
	if (msgid < 0 || msgid >= 255)
faluco@552
   479
	{
faluco@552
   480
		return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
faluco@552
   481
	}
faluco@552
   482
faluco@552
   483
	pHook = pCtx->GetFunctionById(params[2]);
faluco@552
   484
	if (!pHook)
faluco@552
   485
	{
faluco@552
   486
		return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]);
faluco@552
   487
	}
faluco@552
   488
	pNotify = pCtx->GetFunctionById(params[4]);
faluco@593
   489
	intercept = (params[3]) ? true : false;
faluco@552
   490
faluco@593
   491
	pListener = s_UsrMessageNatives.CreateListener(pCtx);
faluco@593
   492
	pListener->Initialize(msgid, pHook, pNotify, intercept);
faluco@553
   493
dvander@2636
   494
	g_UserMsgs.HookUserMessage2(msgid, pListener, intercept);
faluco@505
   495
faluco@505
   496
	return 1;
faluco@505
   497
}
faluco@505
   498
ds@626
   499
static cell_t smn_UnhookUserMessage(IPluginContext *pCtx, const cell_t *params)
faluco@552
   500
{
faluco@552
   501
	IPluginFunction *pFunc;
faluco@593
   502
	MsgListenerWrapper *pListener;
faluco@593
   503
	MsgWrapperIter iter;
faluco@552
   504
	bool intercept;
faluco@552
   505
	int msgid = params[1];
faluco@552
   506
faluco@552
   507
	if (msgid < 0 || msgid >= 255)
faluco@552
   508
	{
faluco@552
   509
		return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
faluco@552
   510
	}
faluco@552
   511
faluco@552
   512
	pFunc = pCtx->GetFunctionById(params[2]);
faluco@552
   513
	if (!pFunc)
faluco@552
   514
	{
faluco@552
   515
		return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]);
faluco@552
   516
	}
faluco@593
   517
	intercept = (params[3]) ? true : false;
faluco@552
   518
faluco@1541
   519
	if (!s_UsrMessageNatives.FindListener(msgid, pCtx, pFunc, intercept, &iter))
faluco@552
   520
	{
faluco@552
   521
		return pCtx->ThrowNativeError("Unable to unhook the current user message");
faluco@552
   522
	}
faluco@552
   523
faluco@593
   524
	pListener = (*iter);
dvander@2636
   525
	if (!g_UserMsgs.UnhookUserMessage2(msgid, pListener, intercept))
faluco@552
   526
	{
faluco@552
   527
		return pCtx->ThrowNativeError("Unable to unhook the current user message");
faluco@552
   528
	}
faluco@552
   529
faluco@593
   530
	s_UsrMessageNatives.DeleteListener(pCtx, iter);
faluco@552
   531
faluco@552
   532
	return 1;
faluco@552
   533
}
faluco@505
   534
faluco@505
   535
REGISTER_NATIVES(usrmsgnatives)
faluco@505
   536
{
faluco@505
   537
	{"GetUserMessageId",			smn_GetUserMessageId},
faluco@553
   538
	{"GetUserMessageName",			smn_GetUserMessageName},
faluco@505
   539
	{"StartMessage",				smn_StartMessage},
faluco@505
   540
	{"StartMessageEx",				smn_StartMessageEx},
faluco@505
   541
	{"EndMessage",					smn_EndMessage},
faluco@552
   542
	{"HookUserMessage",				smn_HookUserMessage},
ds@626
   543
	{"UnhookUserMessage",			smn_UnhookUserMessage},
faluco@505
   544
	{NULL,							NULL}
faluco@505
   545
};