Ifdefing out usermessaging on CS:GO to fix builds.
3 * =============================================================================
5 * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "UserMessages.h"
33 #include "sm_stringutil.h"
35 UserMessages g_UserMsgs;
37 #ifndef CSGO_USERMESSAGES_ENABLE
38 #if SOURCE_ENGINE >= SE_LEFT4DEAD
39 SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *);
41 SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
43 SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
46 UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
48 m_Names = sm_trie_create();
53 m_CurId = INVALID_MESSAGE_ID;
56 UserMessages::~UserMessages()
58 sm_trie_destroy(m_Names);
60 CStack<ListenerInfo *>::iterator iter;
61 for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
65 m_FreeListeners.popall();
68 void UserMessages::OnSourceModStartup(bool late)
70 /* -1 means SourceMM was unable to get the user message list */
71 m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
74 void UserMessages::OnSourceModAllInitialized()
76 g_ShareSys.AddInterface(NULL, this);
79 void UserMessages::OnSourceModAllShutdown()
83 #ifndef CSGO_USERMESSAGES_ENABLE
84 SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
85 SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
86 SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
87 SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
93 int UserMessages::GetMessageIndex(const char *msg)
97 if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid)))
105 #ifndef CSGO_USERMESSAGES_ENABLE
106 while (gamedll->GetUserMessageInfo(msgid, msgbuf, sizeof(msgbuf), size))
108 if (strcmp(msgbuf, msg) == 0)
110 sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
118 msgid = g_SMAPI->FindUserMessage(msg);
120 if (msgid != INVALID_MESSAGE_ID)
122 sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
129 bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
131 #ifndef CSGO_USERMESSAGES_ENABLE
132 if (m_FallbackSearch)
135 return gamedll->GetUserMessageInfo(msgid, buffer, maxlength, size);
139 const char *msg = g_SMAPI->GetUserMessage(msgid);
143 strncopy(buffer, msg, maxlength);
150 bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
154 if (m_InExec || m_InHook)
158 if (msg_id < 0 || msg_id >= 255)
163 m_CellRecFilter.Initialize(players, playersNum);
166 if (m_CurFlags & USERMSG_INITMSG)
168 m_CellRecFilter.SetToInit(true);
170 if (m_CurFlags & USERMSG_RELIABLE)
172 m_CellRecFilter.SetToReliable(true);
177 if (m_CurFlags & USERMSG_BLOCKHOOKS)
179 #ifndef CSGO_USERMESSAGES_ENABLE
180 #if SOURCE_ENGINE >= SE_LEFT4DEAD
181 buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
183 buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
186 #if SOURCE_ENGINE >= SE_LEFT4DEAD
187 buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
189 buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
197 bool UserMessages::EndMessage()
204 if (m_CurFlags & USERMSG_BLOCKHOOKS)
206 ENGINE_CALL(MessageEnd)();
208 engine->MessageEnd();
213 m_CellRecFilter.Reset();
218 bool UserMessages::HookUserMessage2(int msg_id,
219 IUserMessageListener *pListener,
222 return InternalHook(msg_id, pListener, intercept, true);
225 bool UserMessages::UnhookUserMessage2(int msg_id,
226 IUserMessageListener *pListener,
229 return InternalUnhook(msg_id, pListener, intercept, true);
232 bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
234 return InternalHook(msg_id, pListener, intercept, false);
237 bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
239 return InternalUnhook(msg_id, pListener, intercept, false);
242 bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
244 if (msg_id < 0 || msg_id >= 255)
250 if (m_FreeListeners.empty())
252 pInfo = new ListenerInfo;
254 pInfo = m_FreeListeners.front();
255 m_FreeListeners.pop();
258 pInfo->Callback = pListener;
259 pInfo->IsHooked = false;
260 pInfo->KillMe = false;
261 pInfo->IsNew = isNew;
265 #ifndef CSGO_USERMESSAGES_ENABLE
266 SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
267 SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
268 SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
269 SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
275 m_msgIntercepts[msg_id].push_back(pInfo);
277 m_msgHooks[msg_id].push_back(pInfo);
283 bool UserMessages::InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
288 bool deleted = false;
290 if (msg_id < 0 || msg_id >= 255)
295 pList = (intercept) ? &m_msgIntercepts[msg_id] : &m_msgHooks[msg_id];
296 for (iter=pList->begin(); iter!=pList->end(); iter++)
299 if (pInfo->Callback == pListener && pInfo->IsNew == isNew)
303 pInfo->KillMe = true;
320 void UserMessages::_DecRefCounter()
322 if (--m_HookCount == 0)
324 #ifndef CSGO_USERMESSAGES_ENABLE
325 SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
326 SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
327 SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
328 SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
333 #if SOURCE_ENGINE >= SE_LEFT4DEAD
334 bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
336 bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type)
339 bool is_intercept_empty = m_msgIntercepts[msg_type].empty();
340 bool is_hook_empty = m_msgHooks[msg_type].empty();
342 if ((is_intercept_empty && is_hook_empty)
343 || (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
346 RETURN_META_VALUE(MRES_IGNORED, NULL);
350 m_CurRecFilter = filter;
352 m_BlockEndPost = false;
354 if (!is_intercept_empty)
356 m_InterceptBuffer.Reset();
357 RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
360 RETURN_META_VALUE(MRES_IGNORED, NULL);
363 #if SOURCE_ENGINE >= SE_LEFT4DEAD
364 bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
366 bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type)
371 RETURN_META_VALUE(MRES_IGNORED, NULL);
374 m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *);
376 RETURN_META_VALUE(MRES_IGNORED, NULL);
379 void UserMessages::OnMessageEnd_Post()
383 RETURN_META(MRES_IGNORED);
392 pList = &m_msgIntercepts[m_CurId];
393 for (iter=pList->begin(); iter!=pList->end(); )
396 if (m_BlockEndPost && !pInfo->IsNew)
400 pInfo->IsHooked = true;
401 pInfo->Callback->OnUserMessageSent(m_CurId);
404 pInfo->Callback->OnPostUserMessage(m_CurId, !m_BlockEndPost);
409 iter = pList->erase(iter);
410 m_FreeListeners.push(pInfo);
415 pInfo->IsHooked = false;
419 pList = &m_msgHooks[m_CurId];
420 for (iter=pList->begin(); iter!=pList->end(); )
423 if (m_BlockEndPost && !pInfo->IsNew)
427 pInfo->IsHooked = true;
428 pInfo->Callback->OnUserMessageSent(m_CurId);
431 pInfo->Callback->OnPostUserMessage(m_CurId, !m_BlockEndPost);
436 iter = pList->erase(iter);
437 m_FreeListeners.push(pInfo);
442 pInfo->IsHooked = false;
447 void UserMessages::OnMessageEnd_Pre()
451 RETURN_META(MRES_IGNORED);
459 bool intercepted = false;
460 bool handled = false;
462 pList = &m_msgIntercepts[m_CurId];
463 for (iter=pList->begin(); iter!=pList->end(); )
466 pInfo->IsHooked = true;
467 res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
478 m_FreeListeners.push(pInfo);
482 pInfo->IsHooked = false;
490 iter = pList->erase(iter);
491 m_FreeListeners.push(pInfo);
501 iter = pList->erase(iter);
502 m_FreeListeners.push(pInfo);
509 pInfo->IsHooked = false;
513 if (!handled && intercepted)
515 bf_write *engine_bfw;
517 #ifndef CSGO_USERMESSAGES_ENABLE
518 #if SOURCE_ENGINE >= SE_LEFT4DEAD
519 engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId));
521 engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId);
523 m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
524 engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
525 ENGINE_CALL(MessageEnd)();
529 pList = &m_msgHooks[m_CurId];
530 for (iter=pList->begin(); iter!=pList->end(); )
533 pInfo->IsHooked = true;
534 pInfo->Callback->OnUserMessage(m_CurId, m_OrigBuffer, m_CurRecFilter);
538 iter = pList->erase(iter);
539 m_FreeListeners.push(pInfo);
544 pInfo->IsHooked = false;
548 RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
550 m_BlockEndPost = true;
551 RETURN_META(MRES_SUPERCEDE);