core/UserMessages.cpp
author David Anderson <dvander@alliedmods.net>
Sun Aug 25 12:16:07 2013 -0700 (2013-08-25)
changeset 4073 56283c919b7b
parent 3872 4c93f74cae51
permissions -rw-r--r--
Switch UserMessages off KTrie (bug 5884 part 11, r=ds).
dvander@592
     1
/**
dvander@4073
     2
 * vim: set ts=4 sw=4 tw=99 noet :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
ds@3099
     5
 * Copyright (C) 2004-2010 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
ds@653
     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>.
ds@653
    28
 *
ds@653
    29
 * Version: $Id$
ds@653
    30
 */
dvander@592
    31
dvander@592
    32
#include "UserMessages.h"
ds@765
    33
#include "sm_stringutil.h"
dvander@3872
    34
#include "logic_bridge.h"
dvander@592
    35
skamonkey@3855
    36
#if SOURCE_ENGINE == SE_DOTA
skamonkey@3855
    37
#include <dota_usermessage_helpers.h>
skamonkey@3855
    38
#elif SOURCE_ENGINE == SE_CSGO
skamonkey@3743
    39
#include <cstrike15_usermessage_helpers.h>
skamonkey@3743
    40
#endif
skamonkey@3743
    41
dvander@616
    42
UserMessages g_UserMsgs;
dvander@592
    43
skamonkey@3855
    44
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
skamonkey@3743
    45
SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
skamonkey@3743
    46
#else
ds@3099
    47
#if SOURCE_ENGINE >= SE_LEFT4DEAD
ds@2400
    48
SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *);
ds@2400
    49
#else
dvander@592
    50
SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
ds@2400
    51
#endif
dvander@592
    52
SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
skamonkey@3743
    53
#endif // ==SE_CSGO
dvander@592
    54
skamonkey@3743
    55
UserMessages::UserMessages()
skamonkey@3743
    56
#ifndef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
    57
	: m_InterceptBuffer(m_pBase, 2500)
dvander@592
    58
{
skamonkey@3743
    59
#else
skamonkey@3743
    60
	: m_InterceptBuffer(NULL)
skamonkey@3743
    61
{
skamonkey@3743
    62
#endif
dvander@592
    63
	m_HookCount = 0;
dvander@592
    64
	m_InExec = false;
dvander@592
    65
	m_InHook = false;
dvander@592
    66
	m_CurFlags = 0;
dvander@592
    67
	m_CurId = INVALID_MESSAGE_ID;
dvander@592
    68
}
dvander@592
    69
dvander@616
    70
UserMessages::~UserMessages()
dvander@592
    71
{
faluco@641
    72
	CStack<ListenerInfo *>::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();
dvander@592
    78
}
dvander@592
    79
ds@765
    80
void UserMessages::OnSourceModStartup(bool late)
ds@765
    81
{
skamonkey@3743
    82
#ifndef USE_PROTOBUF_USERMESSAGES
ds@765
    83
	/* -1 means SourceMM was unable to get the user message list */
ds@765
    84
	m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
skamonkey@3743
    85
#endif
ds@765
    86
}
ds@765
    87
dvander@616
    88
void UserMessages::OnSourceModAllInitialized()
dvander@592
    89
{
dvander@3872
    90
	sharesys->AddInterface(NULL, this);
dvander@592
    91
}
dvander@592
    92
dvander@616
    93
void UserMessages::OnSourceModAllShutdown()
dvander@592
    94
{
dvander@592
    95
	if (m_HookCount)
dvander@592
    96
	{
skamonkey@3855
    97
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
kyle@3819
    98
		SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
kyle@3819
    99
		SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
skamonkey@3743
   100
#else
kyle@3819
   101
		SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false);
kyle@3819
   102
		SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true);
kyle@3819
   103
		SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false);
kyle@3819
   104
		SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true);
skamonkey@3743
   105
#endif
dvander@592
   106
	}
dvander@592
   107
	m_HookCount = 0;
dvander@592
   108
}
dvander@592
   109
dvander@616
   110
int UserMessages::GetMessageIndex(const char *msg)
dvander@592
   111
{
skamonkey@3855
   112
#if SOURCE_ENGINE == SE_DOTA
skamonkey@3855
   113
	// Can split this per engine and/or game later
skamonkey@3855
   114
	return g_DotaUsermessageHelpers.GetIndex(msg);
skamonkey@3855
   115
#elif SOURCE_ENGINE == SE_CSGO
skamonkey@3743
   116
	// Can split this per engine and/or game later
skamonkey@3743
   117
	return g_Cstrike15UsermessageHelpers.GetIndex(msg);
skamonkey@3743
   118
#else
dvander@4073
   119
dvander@592
   120
	int msgid;
dvander@4073
   121
	if (!m_Names.retrieve(msg, &msgid))
dvander@592
   122
	{
ds@765
   123
		if (m_FallbackSearch)
ds@765
   124
		{
ds@765
   125
			char msgbuf[64];
ds@765
   126
			int size;
ds@765
   127
			msgid = 0;
ds@765
   128
ds@765
   129
			while (gamedll->GetUserMessageInfo(msgid, msgbuf, sizeof(msgbuf), size))
ds@765
   130
			{
ds@765
   131
				if (strcmp(msgbuf, msg) == 0)
ds@765
   132
				{
dvander@4073
   133
					m_Names.insert(msg, msgid);
ds@765
   134
					return msgid;
ds@765
   135
				}
ds@765
   136
				msgid++;
ds@765
   137
			}
ds@765
   138
		}
ds@765
   139
ds@698
   140
		msgid = g_SMAPI->FindUserMessage(msg);
dvander@592
   141
ds@698
   142
		if (msgid != INVALID_MESSAGE_ID)
dvander@4073
   143
			m_Names.insert(msg, msgid);
dvander@592
   144
	}
dvander@592
   145
dvander@592
   146
	return msgid;
skamonkey@3743
   147
#endif
dvander@592
   148
}
dvander@592
   149
ds@765
   150
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
ds@765
   151
{
skamonkey@3855
   152
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3855
   153
#if SOURCE_ENGINE == SE_DOTA
skamonkey@3855
   154
	const char *pszName = g_DotaUsermessageHelpers.GetName(msgid);
skamonkey@3855
   155
#elif SOURCE_ENGINE == SE_CSGO
skamonkey@3743
   156
	const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
skamonkey@3855
   157
#endif
skamonkey@3743
   158
	if (!pszName)
skamonkey@3743
   159
		return false;
skamonkey@3743
   160
skamonkey@3743
   161
	strncopy(buffer, pszName, maxlength);
skamonkey@3743
   162
	return true;
skamonkey@3743
   163
#else
ds@765
   164
	if (m_FallbackSearch)
ds@765
   165
	{
ds@765
   166
		int size;
ds@765
   167
		return gamedll->GetUserMessageInfo(msgid, buffer, maxlength, size);
ds@765
   168
	}
ds@766
   169
ds@765
   170
	const char *msg = g_SMAPI->GetUserMessage(msgid);
ds@765
   171
ds@765
   172
	if (msg)
ds@765
   173
	{
ds@765
   174
		strncopy(buffer, msg, maxlength);
ds@765
   175
		return true;
ds@765
   176
	}
ds@765
   177
ds@765
   178
	return false;
skamonkey@3743
   179
#endif
ds@765
   180
}
ds@765
   181
skamonkey@3743
   182
bf_write *UserMessages::StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
dvander@592
   183
{
skamonkey@3743
   184
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   185
	return NULL;
skamonkey@3743
   186
#else
dvander@592
   187
	bf_write *buffer;
faluco@593
   188
faluco@593
   189
	if (m_InExec || m_InHook)
dvander@592
   190
	{
dvander@592
   191
		return NULL;
dvander@592
   192
	}
dvander@592
   193
	if (msg_id < 0 || msg_id >= 255)
dvander@592
   194
	{
dvander@592
   195
		return NULL;
dvander@592
   196
	}
dvander@592
   197
faluco@593
   198
	m_CellRecFilter.Initialize(players, playersNum);
dvander@592
   199
dvander@592
   200
	m_CurFlags = flags;
dvander@592
   201
	if (m_CurFlags & USERMSG_INITMSG)
dvander@592
   202
	{
faluco@593
   203
		m_CellRecFilter.SetToInit(true);
dvander@592
   204
	}
dvander@592
   205
	if (m_CurFlags & USERMSG_RELIABLE)
dvander@592
   206
	{
faluco@593
   207
		m_CellRecFilter.SetToReliable(true);
dvander@592
   208
	}
dvander@592
   209
dvander@592
   210
	m_InExec = true;
dvander@592
   211
faluco@1250
   212
	if (m_CurFlags & USERMSG_BLOCKHOOKS)
dvander@592
   213
	{
ds@3099
   214
#if SOURCE_ENGINE >= SE_LEFT4DEAD
ds@2400
   215
		buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
ds@2400
   216
#else
faluco@1250
   217
		buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
ds@2400
   218
#endif
faluco@1250
   219
	} else {
ds@3099
   220
#if SOURCE_ENGINE >= SE_LEFT4DEAD
ds@2400
   221
		buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
ds@2400
   222
#else
dvander@592
   223
		buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
ds@2400
   224
#endif
dvander@592
   225
	}
dvander@592
   226
dvander@592
   227
	return buffer;
skamonkey@3743
   228
#endif // USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   229
}
skamonkey@3743
   230
skamonkey@3743
   231
google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
skamonkey@3743
   232
{
skamonkey@3743
   233
#ifndef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   234
	return NULL;
skamonkey@3743
   235
#else
skamonkey@3743
   236
	protobuf::Message *buffer;
skamonkey@3743
   237
skamonkey@3743
   238
	if (m_InExec || m_InHook)
skamonkey@3743
   239
	{
skamonkey@3743
   240
		return NULL;
skamonkey@3743
   241
	}
skamonkey@3743
   242
	if (msg_id < 0 || msg_id >= 255)
skamonkey@3743
   243
	{
skamonkey@3743
   244
		return NULL;
skamonkey@3743
   245
	}
skamonkey@3743
   246
skamonkey@3743
   247
	m_CurId = msg_id;
skamonkey@3743
   248
	m_CellRecFilter.Initialize(players, playersNum);
skamonkey@3743
   249
skamonkey@3743
   250
	m_CurFlags = flags;
skamonkey@3743
   251
	if (m_CurFlags & USERMSG_INITMSG)
skamonkey@3743
   252
	{
skamonkey@3743
   253
		m_CellRecFilter.SetToInit(true);
skamonkey@3743
   254
	}
skamonkey@3743
   255
	if (m_CurFlags & USERMSG_RELIABLE)
skamonkey@3743
   256
	{
skamonkey@3743
   257
		m_CellRecFilter.SetToReliable(true);
skamonkey@3743
   258
	}
skamonkey@3743
   259
skamonkey@3743
   260
	m_InExec = true;
skamonkey@3743
   261
skamonkey@3743
   262
	if (m_CurFlags & USERMSG_BLOCKHOOKS)
skamonkey@3743
   263
	{
skamonkey@3743
   264
		// direct message creation, return buffer "from engine". keep track
skamonkey@3855
   265
		m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
skamonkey@3743
   266
		buffer = m_FakeEngineBuffer;
skamonkey@3743
   267
	} else {
skamonkey@3757
   268
		char messageName[32];
skamonkey@3757
   269
		if (!GetMessageName(msg_id, messageName, sizeof(messageName)))
skamonkey@3757
   270
		{
skamonkey@3757
   271
			m_InExec = false;
skamonkey@3757
   272
			return NULL;
skamonkey@3757
   273
		}
skamonkey@3757
   274
skamonkey@3757
   275
		protobuf::Message *msg = OnStartMessage_Pre(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
skamonkey@3743
   276
		switch (m_FakeMetaRes)
skamonkey@3743
   277
		{
skamonkey@3743
   278
		case MRES_IGNORED:
skamonkey@3743
   279
		case MRES_HANDLED:
skamonkey@3855
   280
			m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
skamonkey@3743
   281
			buffer = m_FakeEngineBuffer;
skamonkey@3743
   282
			break;		
skamonkey@3743
   283
skamonkey@3743
   284
		case MRES_OVERRIDE:
skamonkey@3855
   285
			m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
skamonkey@3743
   286
		// fallthrough
skamonkey@3743
   287
		case MRES_SUPERCEDE:
skamonkey@3743
   288
			buffer = msg;
skamonkey@3743
   289
			break;
skamonkey@3743
   290
		}
skamonkey@3743
   291
		
skamonkey@3757
   292
		OnStartMessage_Post(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
skamonkey@3743
   293
	}
skamonkey@3743
   294
skamonkey@3743
   295
	return buffer;
skamonkey@3743
   296
#endif // USE_PROTOBUF_USERMESSAGES
dvander@592
   297
}
dvander@592
   298
dvander@616
   299
bool UserMessages::EndMessage()
dvander@592
   300
{
dvander@592
   301
	if (!m_InExec)
dvander@592
   302
	{
dvander@592
   303
		return false;
dvander@592
   304
	}
dvander@592
   305
skamonkey@3855
   306
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
skamonkey@3743
   307
	if (m_CurFlags & USERMSG_BLOCKHOOKS)
skamonkey@3743
   308
	{
skamonkey@3743
   309
		ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
skamonkey@3743
   310
		delete m_FakeEngineBuffer;
skamonkey@3743
   311
		m_FakeEngineBuffer = NULL;
skamonkey@3743
   312
	} else {
skamonkey@3743
   313
		OnMessageEnd_Pre();
skamonkey@3743
   314
skamonkey@3743
   315
		switch (m_FakeMetaRes)
skamonkey@3743
   316
		{
skamonkey@3743
   317
		case MRES_IGNORED:
skamonkey@3743
   318
		case MRES_HANDLED:
skamonkey@3743
   319
		case MRES_OVERRIDE:
skamonkey@3743
   320
			engine->SendUserMessage(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
skamonkey@3743
   321
			delete m_FakeEngineBuffer;
skamonkey@3743
   322
			m_FakeEngineBuffer = NULL;
skamonkey@3743
   323
			break;
skamonkey@3743
   324
		//case MRES_SUPERCEDE:
skamonkey@3743
   325
		}
skamonkey@3743
   326
skamonkey@3743
   327
		OnMessageEnd_Post();
skamonkey@3743
   328
	}
skamonkey@3743
   329
#else
faluco@1250
   330
	if (m_CurFlags & USERMSG_BLOCKHOOKS)
dvander@592
   331
	{
faluco@1250
   332
		ENGINE_CALL(MessageEnd)();
faluco@1250
   333
	} else {
dvander@592
   334
		engine->MessageEnd();
dvander@592
   335
	}
skamonkey@3855
   336
#endif // SE_CSGO || SE_DOTA
dvander@592
   337
dvander@592
   338
	m_InExec = false;
dvander@592
   339
	m_CurFlags = 0;
faluco@593
   340
	m_CellRecFilter.Reset();
dvander@592
   341
dvander@592
   342
	return true;
dvander@592
   343
}
dvander@592
   344
skamonkey@3743
   345
UserMessageType UserMessages::GetUserMessageType() const
skamonkey@3743
   346
{
skamonkey@3743
   347
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   348
	return UM_Protobuf;
skamonkey@3743
   349
#else
skamonkey@3743
   350
	return UM_BitBuf;
skamonkey@3743
   351
#endif
skamonkey@3743
   352
}
skamonkey@3743
   353
dvander@2636
   354
bool UserMessages::HookUserMessage2(int msg_id,
dvander@2636
   355
									IUserMessageListener *pListener,
dvander@2636
   356
									bool intercept)
dvander@2636
   357
{
skamonkey@3743
   358
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   359
	return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
skamonkey@3743
   360
#else
skamonkey@3743
   361
	return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
skamonkey@3743
   362
#endif
dvander@2636
   363
}
dvander@2636
   364
dvander@2636
   365
bool UserMessages::UnhookUserMessage2(int msg_id,
dvander@2636
   366
									  IUserMessageListener *pListener,
dvander@2636
   367
									  bool intercept)
dvander@2636
   368
{
skamonkey@3743
   369
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   370
	return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
skamonkey@3743
   371
#else
skamonkey@3743
   372
	return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
skamonkey@3743
   373
#endif
dvander@2636
   374
}
dvander@2636
   375
dvander@616
   376
bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
dvander@592
   377
{
skamonkey@3743
   378
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   379
	return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
skamonkey@3743
   380
#else
skamonkey@3743
   381
	return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
skamonkey@3743
   382
#endif
dvander@2636
   383
}
dvander@2636
   384
dvander@2636
   385
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
dvander@2636
   386
{	
skamonkey@3743
   387
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   388
	return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
skamonkey@3743
   389
#else
skamonkey@3743
   390
	return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
skamonkey@3743
   391
#endif
dvander@2636
   392
}
dvander@2636
   393
skamonkey@3743
   394
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   395
bool UserMessages::InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
skamonkey@3743
   396
#else
skamonkey@3743
   397
bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
skamonkey@3743
   398
#endif
dvander@2636
   399
{
dvander@592
   400
	if (msg_id < 0 || msg_id >= 255)
dvander@592
   401
	{
dvander@592
   402
		return false;
dvander@592
   403
	}
dvander@592
   404
faluco@593
   405
	ListenerInfo *pInfo;
faluco@593
   406
	if (m_FreeListeners.empty())
faluco@593
   407
	{
faluco@593
   408
		pInfo = new ListenerInfo;
faluco@593
   409
	} else {
faluco@593
   410
		pInfo = m_FreeListeners.front();
faluco@593
   411
		m_FreeListeners.pop();
faluco@593
   412
	}
faluco@593
   413
faluco@593
   414
	pInfo->Callback = pListener;
faluco@593
   415
	pInfo->IsHooked = false;
faluco@593
   416
	pInfo->KillMe = false;
dvander@2636
   417
	pInfo->IsNew = isNew;
faluco@593
   418
dvander@592
   419
	if (!m_HookCount++)
dvander@592
   420
	{
skamonkey@3855
   421
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
kyle@3819
   422
		SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
kyle@3819
   423
		SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
skamonkey@3743
   424
#else
kyle@3819
   425
		SH_ADD_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false);
kyle@3819
   426
		SH_ADD_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true);
kyle@3819
   427
		SH_ADD_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false);
kyle@3819
   428
		SH_ADD_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true);
skamonkey@3743
   429
#endif
dvander@592
   430
	}
dvander@592
   431
dvander@592
   432
	if (intercept)
dvander@592
   433
	{
faluco@593
   434
		m_msgIntercepts[msg_id].push_back(pInfo);
dvander@592
   435
	} else {
faluco@593
   436
		m_msgHooks[msg_id].push_back(pInfo);
dvander@592
   437
	}
dvander@592
   438
dvander@592
   439
	return true;
dvander@592
   440
}
dvander@592
   441
skamonkey@3743
   442
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3861
   443
const protobuf::Message *UserMessages::GetMessagePrototype(int msg_type)
skamonkey@3855
   444
{
skamonkey@3855
   445
#if SOURCE_ENGINE == SE_DOTA
skamonkey@3855
   446
	return g_DotaUsermessageHelpers.GetPrototype(msg_type);
skamonkey@3855
   447
#elif SOURCE_ENGINE == SE_CSGO
skamonkey@3855
   448
	return g_Cstrike15UsermessageHelpers.GetPrototype(msg_type);
skamonkey@3855
   449
#endif
skamonkey@3855
   450
}
skamonkey@3855
   451
#endif
skamonkey@3855
   452
skamonkey@3855
   453
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   454
bool UserMessages::InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
skamonkey@3743
   455
#else
skamonkey@3743
   456
bool UserMessages::InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
skamonkey@3743
   457
#endif
dvander@2636
   458
{
faluco@593
   459
	MsgList *pList;
dvander@592
   460
	MsgIter iter;
faluco@593
   461
	ListenerInfo *pInfo;
dvander@592
   462
	bool deleted = false;
dvander@592
   463
dvander@592
   464
	if (msg_id < 0 || msg_id >= 255)
dvander@592
   465
	{
dvander@592
   466
		return false;
dvander@592
   467
	}
dvander@592
   468
faluco@593
   469
	pList = (intercept) ? &m_msgIntercepts[msg_id] : &m_msgHooks[msg_id];
faluco@593
   470
	for (iter=pList->begin(); iter!=pList->end(); iter++)
dvander@592
   471
	{
faluco@593
   472
		pInfo = (*iter);
dvander@2636
   473
		if (pInfo->Callback == pListener && pInfo->IsNew == isNew)
dvander@592
   474
		{
faluco@593
   475
			if (pInfo->IsHooked)
faluco@593
   476
			{
faluco@593
   477
				pInfo->KillMe = true;
faluco@593
   478
				return true;
faluco@593
   479
			}
faluco@593
   480
			pList->erase(iter);
dvander@592
   481
			deleted = true;
dvander@592
   482
			break;
dvander@592
   483
		}
dvander@592
   484
	}
dvander@592
   485
faluco@593
   486
	if (deleted)
faluco@593
   487
	{
faluco@593
   488
		_DecRefCounter();
faluco@593
   489
	}
faluco@593
   490
faluco@593
   491
	return deleted;
faluco@593
   492
}
faluco@593
   493
dvander@616
   494
void UserMessages::_DecRefCounter()
faluco@593
   495
{
faluco@593
   496
	if (--m_HookCount == 0)
dvander@592
   497
	{
skamonkey@3855
   498
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
kyle@3819
   499
		SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
kyle@3819
   500
		SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
skamonkey@3743
   501
#else
kyle@3819
   502
		SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false);
kyle@3819
   503
		SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true);
kyle@3819
   504
		SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false);
kyle@3819
   505
		SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true);
skamonkey@3743
   506
#endif
dvander@592
   507
	}
dvander@592
   508
}
dvander@592
   509
skamonkey@3855
   510
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
skamonkey@3743
   511
void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
skamonkey@3743
   512
{
skamonkey@3855
   513
#if SOURCE_ENGINE == SE_DOTA
skamonkey@3855
   514
	OnStartMessage_Pre(&filter, msg_type, g_DotaUsermessageHelpers.GetName(msg_type));
skamonkey@3855
   515
#elif SOURCE_ENGINE == SE_CSGO
skamonkey@3743
   516
	OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
skamonkey@3855
   517
#endif
skamonkey@3743
   518
	if (m_FakeMetaRes == MRES_SUPERCEDE)
skamonkey@3743
   519
	{
skamonkey@3778
   520
		int size = msg.ByteSize();
skamonkey@3778
   521
		uint8 *data = (uint8 *)stackalloc(size);
skamonkey@3778
   522
		msg.SerializePartialToArray(data, size);
skamonkey@3786
   523
		m_InterceptBuffer->ParsePartialFromArray(data, size);
skamonkey@3743
   524
	}
skamonkey@3743
   525
	else
skamonkey@3743
   526
	{
skamonkey@3759
   527
		m_FakeEngineBuffer = &const_cast<protobuf::Message &>(msg);
skamonkey@3743
   528
	}
skamonkey@3743
   529
skamonkey@3855
   530
#if SOURCE_ENGINE == SE_DOTA
skamonkey@3855
   531
	OnStartMessage_Post(&filter, msg_type, g_DotaUsermessageHelpers.GetName(msg_type));
skamonkey@3855
   532
#elif SOURCE_ENGINE == SE_CSGO
skamonkey@3786
   533
	OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
skamonkey@3855
   534
#endif
skamonkey@3786
   535
skamonkey@3743
   536
	OnMessageEnd_Pre();
skamonkey@3743
   537
	if (m_FakeMetaRes == MRES_SUPERCEDE)
skamonkey@3743
   538
		RETURN_META(MRES_SUPERCEDE);
skamonkey@3743
   539
skamonkey@3743
   540
	RETURN_META(MRES_IGNORED);
skamonkey@3743
   541
}
skamonkey@3743
   542
skamonkey@3743
   543
void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
skamonkey@3743
   544
{
skamonkey@3743
   545
	OnMessageEnd_Post();
skamonkey@3743
   546
	RETURN_META(MRES_IGNORED);
skamonkey@3743
   547
}
skamonkey@3743
   548
#endif
skamonkey@3743
   549
skamonkey@3743
   550
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   551
#define UM_RETURN_META_VALUE(res, val) \
skamonkey@3743
   552
	m_FakeMetaRes = res;               \
skamonkey@3743
   553
	return val;
skamonkey@3743
   554
skamonkey@3743
   555
#define UM_RETURN_META(res)            \
skamonkey@3743
   556
	m_FakeMetaRes = res;               \
skamonkey@3743
   557
	return;
skamonkey@3743
   558
#else
skamonkey@3743
   559
#define UM_RETURN_META_VALUE(res, val) \
skamonkey@3743
   560
	RETURN_META_VALUE(res, val)
skamonkey@3743
   561
skamonkey@3743
   562
#define UM_RETURN_META(res)            \
skamonkey@3743
   563
	RETURN_META(res)
skamonkey@3743
   564
#endif
skamonkey@3743
   565
skamonkey@3855
   566
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
skamonkey@3743
   567
protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
skamonkey@3743
   568
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
ds@2400
   569
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
ds@2400
   570
#else
dvander@616
   571
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type)
ds@2400
   572
#endif
dvander@592
   573
{
dvander@592
   574
	bool is_intercept_empty = m_msgIntercepts[msg_type].empty();
dvander@592
   575
	bool is_hook_empty = m_msgHooks[msg_type].empty();
dvander@592
   576
faluco@593
   577
	if ((is_intercept_empty && is_hook_empty)
faluco@1250
   578
		|| (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
dvander@592
   579
	{
dvander@592
   580
		m_InHook = false;
skamonkey@3743
   581
		UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
dvander@592
   582
	}
dvander@592
   583
dvander@592
   584
	m_CurId = msg_type;
dvander@592
   585
	m_CurRecFilter = filter;
dvander@592
   586
	m_InHook = true;
faluco@597
   587
	m_BlockEndPost = false;
dvander@592
   588
dvander@592
   589
	if (!is_intercept_empty)
dvander@592
   590
	{
skamonkey@3743
   591
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   592
		if (m_InterceptBuffer)
skamonkey@3743
   593
			delete m_InterceptBuffer;
skamonkey@3855
   594
		m_InterceptBuffer = GetMessagePrototype(msg_type)->New();
skamonkey@3855
   595
skamonkey@3743
   596
		UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer);
skamonkey@3743
   597
#else
faluco@593
   598
		m_InterceptBuffer.Reset();
skamonkey@3743
   599
		UM_RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
skamonkey@3743
   600
#endif
dvander@592
   601
	}
dvander@592
   602
skamonkey@3743
   603
	UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
dvander@592
   604
}
dvander@592
   605
skamonkey@3855
   606
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
skamonkey@3743
   607
protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
skamonkey@3743
   608
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
ds@2400
   609
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
ds@2400
   610
#else
dvander@616
   611
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type)
ds@2400
   612
#endif
dvander@592
   613
{
dvander@592
   614
	if (!m_InHook)
dvander@592
   615
	{
skamonkey@3743
   616
		UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
dvander@592
   617
	}
dvander@592
   618
skamonkey@3743
   619
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3786
   620
	if (m_FakeMetaRes == MRES_SUPERCEDE)
skamonkey@3786
   621
		m_OrigBuffer = m_InterceptBuffer;
skamonkey@3786
   622
	else
skamonkey@3786
   623
		m_OrigBuffer = m_FakeEngineBuffer;
skamonkey@3743
   624
#else
dvander@592
   625
	m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *);
skamonkey@3743
   626
#endif
dvander@592
   627
skamonkey@3743
   628
	UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
dvander@592
   629
}
dvander@592
   630
dvander@616
   631
void UserMessages::OnMessageEnd_Post()
dvander@592
   632
{
dvander@2636
   633
	if (!m_InHook)
dvander@592
   634
	{
skamonkey@3743
   635
		UM_RETURN_META(MRES_IGNORED);
dvander@592
   636
	}
dvander@592
   637
faluco@593
   638
	MsgList *pList;
dvander@592
   639
	MsgIter iter;
faluco@593
   640
	ListenerInfo *pInfo;
faluco@593
   641
pred@2577
   642
	m_InHook = false;
pred@2577
   643
faluco@593
   644
	pList = &m_msgIntercepts[m_CurId];
faluco@593
   645
	for (iter=pList->begin(); iter!=pList->end(); )
faluco@593
   646
	{
faluco@593
   647
		pInfo = (*iter);
dvander@2636
   648
		if (m_BlockEndPost && !pInfo->IsNew)
dvander@2636
   649
		{
dvander@2636
   650
			continue;
dvander@2636
   651
		}
faluco@593
   652
		pInfo->IsHooked = true;
faluco@593
   653
		pInfo->Callback->OnUserMessageSent(m_CurId);
dvander@2636
   654
		if (pInfo->IsNew)
dvander@2636
   655
		{
dvander@2636
   656
			pInfo->Callback->OnPostUserMessage(m_CurId, !m_BlockEndPost);
dvander@2636
   657
		}
dvander@592
   658
faluco@593
   659
		if (pInfo->KillMe)
faluco@593
   660
		{
faluco@593
   661
			iter = pList->erase(iter);
faluco@593
   662
			m_FreeListeners.push(pInfo);
faluco@593
   663
			_DecRefCounter();
faluco@593
   664
			continue;
faluco@593
   665
		}
faluco@593
   666
faluco@593
   667
		pInfo->IsHooked = false;
faluco@593
   668
		iter++;
dvander@592
   669
	}
dvander@592
   670
faluco@593
   671
	pList = &m_msgHooks[m_CurId];
faluco@594
   672
	for (iter=pList->begin(); iter!=pList->end(); )
dvander@592
   673
	{
faluco@593
   674
		pInfo = (*iter);
dvander@2636
   675
		if (m_BlockEndPost && !pInfo->IsNew)
dvander@2636
   676
		{
dvander@2636
   677
			continue;
dvander@2636
   678
		}
faluco@594
   679
		pInfo->IsHooked = true;
faluco@593
   680
		pInfo->Callback->OnUserMessageSent(m_CurId);
dvander@2636
   681
		if (pInfo->IsNew)
dvander@2636
   682
		{
dvander@2636
   683
			pInfo->Callback->OnPostUserMessage(m_CurId, !m_BlockEndPost);
dvander@2636
   684
		}
faluco@593
   685
faluco@593
   686
		if (pInfo->KillMe)
faluco@593
   687
		{
faluco@593
   688
			iter = pList->erase(iter);
faluco@593
   689
			m_FreeListeners.push(pInfo);
faluco@593
   690
			_DecRefCounter();
faluco@593
   691
			continue;
faluco@593
   692
		}
faluco@593
   693
faluco@593
   694
		pInfo->IsHooked = false;
faluco@593
   695
		iter++;
dvander@592
   696
	}
dvander@592
   697
}
dvander@592
   698
dvander@616
   699
void UserMessages::OnMessageEnd_Pre()
dvander@592
   700
{
dvander@592
   701
	if (!m_InHook)
dvander@592
   702
	{
skamonkey@3743
   703
		UM_RETURN_META(MRES_IGNORED);
dvander@592
   704
	}
dvander@592
   705
faluco@593
   706
	MsgList *pList;
dvander@592
   707
	MsgIter iter;
faluco@593
   708
	ListenerInfo *pInfo;
faluco@593
   709
dvander@592
   710
	ResultType res;
dvander@592
   711
	bool intercepted = false;
dvander@592
   712
	bool handled = false;
dvander@592
   713
faluco@593
   714
	pList = &m_msgIntercepts[m_CurId];
faluco@593
   715
	for (iter=pList->begin(); iter!=pList->end(); )
dvander@592
   716
	{
faluco@593
   717
		pInfo = (*iter);
faluco@593
   718
		pInfo->IsHooked = true;
skamonkey@3743
   719
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   720
		res = pInfo->Callback->InterceptUserMessage(m_CurId, m_InterceptBuffer, m_CurRecFilter);
skamonkey@3743
   721
#else
faluco@593
   722
		res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
skamonkey@3743
   723
#endif
faluco@593
   724
faluco@597
   725
		intercepted = true;
faluco@597
   726
faluco@593
   727
		switch (res)
dvander@592
   728
		{
faluco@593
   729
		case Pl_Stop:
faluco@593
   730
			{
faluco@593
   731
				if (pInfo->KillMe)
faluco@593
   732
				{
faluco@593
   733
					pList->erase(iter);
faluco@593
   734
					m_FreeListeners.push(pInfo);
faluco@593
   735
					_DecRefCounter();
faluco@593
   736
					goto supercede;
faluco@593
   737
				}
faluco@593
   738
				pInfo->IsHooked = false;
faluco@593
   739
				goto supercede;
faluco@593
   740
			}
faluco@593
   741
		case Pl_Handled:
faluco@593
   742
			{
faluco@593
   743
				handled = true;
faluco@593
   744
				if (pInfo->KillMe)
faluco@593
   745
				{
faluco@593
   746
					iter = pList->erase(iter);
faluco@593
   747
					m_FreeListeners.push(pInfo);
faluco@593
   748
					_DecRefCounter();
faluco@593
   749
					continue;
faluco@593
   750
				}
faluco@593
   751
				break;
faluco@593
   752
			}
faluco@593
   753
		default:
faluco@593
   754
			{
faluco@593
   755
				if (pInfo->KillMe)
faluco@593
   756
				{
faluco@593
   757
					iter = pList->erase(iter);
faluco@593
   758
					m_FreeListeners.push(pInfo);
faluco@593
   759
					_DecRefCounter();
faluco@593
   760
					continue;
faluco@593
   761
				}
faluco@597
   762
				break;
faluco@593
   763
			}
dvander@592
   764
		}
faluco@593
   765
		pInfo->IsHooked = false;
faluco@593
   766
		iter++;
dvander@592
   767
	}
dvander@592
   768
dvander@2734
   769
	if (!handled && intercepted)
dvander@592
   770
	{
skamonkey@3855
   771
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
skamonkey@3743
   772
		ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
skamonkey@3743
   773
#else
faluco@593
   774
		bf_write *engine_bfw;
ds@3099
   775
#if SOURCE_ENGINE >= SE_LEFT4DEAD
ds@2400
   776
		engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId));
ds@2400
   777
#else
dvander@592
   778
		engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId);
ds@2400
   779
#endif
dvander@592
   780
		m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
dvander@592
   781
		engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
dvander@592
   782
		ENGINE_CALL(MessageEnd)();
skamonkey@3855
   783
#endif // SE_CSGO || SE_DOTA
dvander@592
   784
	}
dvander@592
   785
dvander@592
   786
	{
skamonkey@3855
   787
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
skamonkey@3778
   788
		int size = m_OrigBuffer->ByteSize();
skamonkey@3778
   789
		uint8 *data = (uint8 *)stackalloc(size);
skamonkey@3778
   790
		m_OrigBuffer->SerializePartialToArray(data, size);
skamonkey@3855
   791
skamonkey@3855
   792
		protobuf::Message *pTempMsg = GetMessagePrototype(m_CurId)->New();
skamonkey@3786
   793
		pTempMsg->ParsePartialFromArray(data, size);
skamonkey@3779
   794
#else
skamonkey@3779
   795
		bf_write *pTempMsg = m_OrigBuffer;
skamonkey@3779
   796
#endif
faluco@593
   797
skamonkey@3778
   798
		pList = &m_msgHooks[m_CurId];
skamonkey@3778
   799
		for (iter=pList->begin(); iter!=pList->end(); )
faluco@593
   800
		{
skamonkey@3778
   801
			pInfo = (*iter);
skamonkey@3778
   802
			pInfo->IsHooked = true;
skamonkey@3778
   803
			pInfo->Callback->OnUserMessage(m_CurId, pTempMsg, m_CurRecFilter);
skamonkey@3778
   804
skamonkey@3778
   805
			if (pInfo->KillMe)
skamonkey@3778
   806
			{
skamonkey@3778
   807
				iter = pList->erase(iter);
skamonkey@3778
   808
				m_FreeListeners.push(pInfo);
skamonkey@3778
   809
				_DecRefCounter();
skamonkey@3778
   810
				continue;
skamonkey@3778
   811
			}
skamonkey@3778
   812
skamonkey@3778
   813
			pInfo->IsHooked = false;
skamonkey@3778
   814
			iter++;
faluco@593
   815
		}
faluco@593
   816
skamonkey@3855
   817
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
skamonkey@3778
   818
		delete pTempMsg;
skamonkey@3779
   819
#endif
dvander@592
   820
	}
dvander@592
   821
skamonkey@3743
   822
	UM_RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
dvander@592
   823
supercede:
faluco@597
   824
	m_BlockEndPost = true;
skamonkey@3743
   825
	UM_RETURN_META(MRES_SUPERCEDE);
dvander@592
   826
}