1.1 --- a/core/UserMessages.cpp Fri Mar 28 06:21:34 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,477 +0,0 @@
1.4 -/**
1.5 - * vim: set ts=4 :
1.6 - * =============================================================================
1.7 - * SourceMod
1.8 - * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
1.9 - * =============================================================================
1.10 - *
1.11 - * This program is free software; you can redistribute it and/or modify it under
1.12 - * the terms of the GNU General Public License, version 3.0, as published by the
1.13 - * Free Software Foundation.
1.14 - *
1.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 - * details.
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License along with
1.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 - *
1.23 - * As a special exception, AlliedModders LLC gives you permission to link the
1.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 - * by the Valve Corporation. You must obey the GNU General Public License in
1.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 - * this exception to all derivative works. AlliedModders LLC defines further
1.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 - * or <http://www.sourcemod.net/license.php>.
1.31 - *
1.32 - * Version: $Id$
1.33 - */
1.34 -
1.35 -#include "UserMessages.h"
1.36 -#include "sm_stringutil.h"
1.37 -
1.38 -UserMessages g_UserMsgs;
1.39 -
1.40 -SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
1.41 -SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
1.42 -
1.43 -UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
1.44 -{
1.45 - m_Names = sm_trie_create();
1.46 - m_HookCount = 0;
1.47 - m_InExec = false;
1.48 - m_InHook = false;
1.49 - m_CurFlags = 0;
1.50 - m_CurId = INVALID_MESSAGE_ID;
1.51 -}
1.52 -
1.53 -UserMessages::~UserMessages()
1.54 -{
1.55 - sm_trie_destroy(m_Names);
1.56 -
1.57 - CStack<ListenerInfo *>::iterator iter;
1.58 - for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
1.59 - {
1.60 - delete (*iter);
1.61 - }
1.62 - m_FreeListeners.popall();
1.63 -}
1.64 -
1.65 -void UserMessages::OnSourceModStartup(bool late)
1.66 -{
1.67 - /* -1 means SourceMM was unable to get the user message list */
1.68 - m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
1.69 -}
1.70 -
1.71 -void UserMessages::OnSourceModAllInitialized()
1.72 -{
1.73 - g_ShareSys.AddInterface(NULL, this);
1.74 -}
1.75 -
1.76 -void UserMessages::OnSourceModAllShutdown()
1.77 -{
1.78 - if (m_HookCount)
1.79 - {
1.80 - SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
1.81 - SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
1.82 - SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
1.83 - SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
1.84 - }
1.85 - m_HookCount = 0;
1.86 -}
1.87 -
1.88 -int UserMessages::GetMessageIndex(const char *msg)
1.89 -{
1.90 - int msgid;
1.91 -
1.92 - if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid)))
1.93 - {
1.94 - if (m_FallbackSearch)
1.95 - {
1.96 - char msgbuf[64];
1.97 - int size;
1.98 - msgid = 0;
1.99 -
1.100 - while (gamedll->GetUserMessageInfo(msgid, msgbuf, sizeof(msgbuf), size))
1.101 - {
1.102 - if (strcmp(msgbuf, msg) == 0)
1.103 - {
1.104 - sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
1.105 - return msgid;
1.106 - }
1.107 - msgid++;
1.108 - }
1.109 - }
1.110 -
1.111 - msgid = g_SMAPI->FindUserMessage(msg);
1.112 -
1.113 - if (msgid != INVALID_MESSAGE_ID)
1.114 - {
1.115 - sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
1.116 - }
1.117 - }
1.118 -
1.119 - return msgid;
1.120 -}
1.121 -
1.122 -bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
1.123 -{
1.124 - if (m_FallbackSearch)
1.125 - {
1.126 - int size;
1.127 - return gamedll->GetUserMessageInfo(msgid, buffer, maxlength, size);
1.128 - }
1.129 -
1.130 - const char *msg = g_SMAPI->GetUserMessage(msgid);
1.131 -
1.132 - if (msg)
1.133 - {
1.134 - strncopy(buffer, msg, maxlength);
1.135 - return true;
1.136 - }
1.137 -
1.138 - return false;
1.139 -}
1.140 -
1.141 -bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
1.142 -{
1.143 - bf_write *buffer;
1.144 -
1.145 - if (m_InExec || m_InHook)
1.146 - {
1.147 - return NULL;
1.148 - }
1.149 - if (msg_id < 0 || msg_id >= 255)
1.150 - {
1.151 - return NULL;
1.152 - }
1.153 -
1.154 - m_CellRecFilter.Initialize(players, playersNum);
1.155 -
1.156 - m_CurFlags = flags;
1.157 - if (m_CurFlags & USERMSG_INITMSG)
1.158 - {
1.159 - m_CellRecFilter.SetToInit(true);
1.160 - }
1.161 - if (m_CurFlags & USERMSG_RELIABLE)
1.162 - {
1.163 - m_CellRecFilter.SetToReliable(true);
1.164 - }
1.165 -
1.166 - m_InExec = true;
1.167 -
1.168 - if (m_CurFlags & USERMSG_BLOCKHOOKS)
1.169 - {
1.170 - buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
1.171 - } else {
1.172 - buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
1.173 - }
1.174 -
1.175 - return buffer;
1.176 -}
1.177 -
1.178 -bool UserMessages::EndMessage()
1.179 -{
1.180 - if (!m_InExec)
1.181 - {
1.182 - return false;
1.183 - }
1.184 -
1.185 - if (m_CurFlags & USERMSG_BLOCKHOOKS)
1.186 - {
1.187 - ENGINE_CALL(MessageEnd)();
1.188 - } else {
1.189 - engine->MessageEnd();
1.190 - }
1.191 -
1.192 - m_InExec = false;
1.193 - m_CurFlags = 0;
1.194 - m_CellRecFilter.Reset();
1.195 -
1.196 - return true;
1.197 -}
1.198 -
1.199 -bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
1.200 -{
1.201 - if (msg_id < 0 || msg_id >= 255)
1.202 - {
1.203 - return false;
1.204 - }
1.205 -
1.206 - ListenerInfo *pInfo;
1.207 - if (m_FreeListeners.empty())
1.208 - {
1.209 - pInfo = new ListenerInfo;
1.210 - } else {
1.211 - pInfo = m_FreeListeners.front();
1.212 - m_FreeListeners.pop();
1.213 - }
1.214 -
1.215 - pInfo->Callback = pListener;
1.216 - pInfo->IsHooked = false;
1.217 - pInfo->KillMe = false;
1.218 -
1.219 - if (!m_HookCount++)
1.220 - {
1.221 - SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
1.222 - SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
1.223 - SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
1.224 - SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
1.225 - }
1.226 -
1.227 - if (intercept)
1.228 - {
1.229 - m_msgIntercepts[msg_id].push_back(pInfo);
1.230 - } else {
1.231 - m_msgHooks[msg_id].push_back(pInfo);
1.232 - }
1.233 -
1.234 - return true;
1.235 -}
1.236 -
1.237 -bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
1.238 -{
1.239 - MsgList *pList;
1.240 - MsgIter iter;
1.241 - ListenerInfo *pInfo;
1.242 - bool deleted = false;
1.243 -
1.244 - if (msg_id < 0 || msg_id >= 255)
1.245 - {
1.246 - return false;
1.247 - }
1.248 -
1.249 - pList = (intercept) ? &m_msgIntercepts[msg_id] : &m_msgHooks[msg_id];
1.250 - for (iter=pList->begin(); iter!=pList->end(); iter++)
1.251 - {
1.252 - pInfo = (*iter);
1.253 - if (pInfo->Callback == pListener)
1.254 - {
1.255 - if (pInfo->IsHooked)
1.256 - {
1.257 - pInfo->KillMe = true;
1.258 - return true;
1.259 - }
1.260 - pList->erase(iter);
1.261 - deleted = true;
1.262 - break;
1.263 - }
1.264 - }
1.265 -
1.266 - if (deleted)
1.267 - {
1.268 - _DecRefCounter();
1.269 - }
1.270 -
1.271 - return deleted;
1.272 -}
1.273 -
1.274 -void UserMessages::_DecRefCounter()
1.275 -{
1.276 - if (--m_HookCount == 0)
1.277 - {
1.278 - SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
1.279 - SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
1.280 - SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
1.281 - SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
1.282 - }
1.283 -}
1.284 -
1.285 -bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type)
1.286 -{
1.287 - bool is_intercept_empty = m_msgIntercepts[msg_type].empty();
1.288 - bool is_hook_empty = m_msgHooks[msg_type].empty();
1.289 -
1.290 - if ((is_intercept_empty && is_hook_empty)
1.291 - || (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
1.292 - {
1.293 - m_InHook = false;
1.294 - RETURN_META_VALUE(MRES_IGNORED, NULL);
1.295 - }
1.296 -
1.297 - m_CurId = msg_type;
1.298 - m_CurRecFilter = filter;
1.299 - m_InHook = true;
1.300 - m_BlockEndPost = false;
1.301 -
1.302 - if (!is_intercept_empty)
1.303 - {
1.304 - m_InterceptBuffer.Reset();
1.305 - RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
1.306 - }
1.307 -
1.308 - RETURN_META_VALUE(MRES_IGNORED, NULL);
1.309 -}
1.310 -
1.311 -bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type)
1.312 -{
1.313 - if (!m_InHook)
1.314 - {
1.315 - RETURN_META_VALUE(MRES_IGNORED, NULL);
1.316 - }
1.317 -
1.318 - m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *);
1.319 -
1.320 - RETURN_META_VALUE(MRES_IGNORED, NULL);
1.321 -}
1.322 -
1.323 -void UserMessages::OnMessageEnd_Post()
1.324 -{
1.325 - if (!m_InHook || m_BlockEndPost)
1.326 - {
1.327 - RETURN_META(MRES_IGNORED);
1.328 - }
1.329 -
1.330 - MsgList *pList;
1.331 - MsgIter iter;
1.332 - ListenerInfo *pInfo;
1.333 -
1.334 - pList = &m_msgIntercepts[m_CurId];
1.335 - for (iter=pList->begin(); iter!=pList->end(); )
1.336 - {
1.337 - pInfo = (*iter);
1.338 - pInfo->IsHooked = true;
1.339 - pInfo->Callback->OnUserMessageSent(m_CurId);
1.340 -
1.341 - if (pInfo->KillMe)
1.342 - {
1.343 - iter = pList->erase(iter);
1.344 - m_FreeListeners.push(pInfo);
1.345 - _DecRefCounter();
1.346 - continue;
1.347 - }
1.348 -
1.349 - pInfo->IsHooked = false;
1.350 - iter++;
1.351 - }
1.352 -
1.353 - m_InHook = false;
1.354 -
1.355 - pList = &m_msgHooks[m_CurId];
1.356 - for (iter=pList->begin(); iter!=pList->end(); )
1.357 - {
1.358 - pInfo = (*iter);
1.359 - pInfo->IsHooked = true;
1.360 - pInfo->Callback->OnUserMessageSent(m_CurId);
1.361 -
1.362 - if (pInfo->KillMe)
1.363 - {
1.364 - iter = pList->erase(iter);
1.365 - m_FreeListeners.push(pInfo);
1.366 - _DecRefCounter();
1.367 - continue;
1.368 - }
1.369 -
1.370 - pInfo->IsHooked = false;
1.371 - iter++;
1.372 - }
1.373 -}
1.374 -
1.375 -void UserMessages::OnMessageEnd_Pre()
1.376 -{
1.377 - if (!m_InHook)
1.378 - {
1.379 - RETURN_META(MRES_IGNORED);
1.380 - }
1.381 -
1.382 - MsgList *pList;
1.383 - MsgIter iter;
1.384 - ListenerInfo *pInfo;
1.385 -
1.386 - ResultType res;
1.387 - bool intercepted = false;
1.388 - bool handled = false;
1.389 -
1.390 - pList = &m_msgIntercepts[m_CurId];
1.391 - for (iter=pList->begin(); iter!=pList->end(); )
1.392 - {
1.393 - pInfo = (*iter);
1.394 - pInfo->IsHooked = true;
1.395 - res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
1.396 -
1.397 - intercepted = true;
1.398 -
1.399 - switch (res)
1.400 - {
1.401 - case Pl_Stop:
1.402 - {
1.403 - if (pInfo->KillMe)
1.404 - {
1.405 - pList->erase(iter);
1.406 - m_FreeListeners.push(pInfo);
1.407 - _DecRefCounter();
1.408 - goto supercede;
1.409 - }
1.410 - pInfo->IsHooked = false;
1.411 - goto supercede;
1.412 - }
1.413 - case Pl_Handled:
1.414 - {
1.415 - handled = true;
1.416 - if (pInfo->KillMe)
1.417 - {
1.418 - iter = pList->erase(iter);
1.419 - m_FreeListeners.push(pInfo);
1.420 - _DecRefCounter();
1.421 - continue;
1.422 - }
1.423 - break;
1.424 - }
1.425 - default:
1.426 - {
1.427 - if (pInfo->KillMe)
1.428 - {
1.429 - iter = pList->erase(iter);
1.430 - m_FreeListeners.push(pInfo);
1.431 - _DecRefCounter();
1.432 - continue;
1.433 - }
1.434 - break;
1.435 - }
1.436 - }
1.437 - pInfo->IsHooked = false;
1.438 - iter++;
1.439 - }
1.440 -
1.441 - if (handled)
1.442 - {
1.443 - goto supercede;
1.444 - }
1.445 -
1.446 - if (intercepted)
1.447 - {
1.448 - bf_write *engine_bfw;
1.449 -
1.450 - engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId);
1.451 - m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
1.452 - engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
1.453 - ENGINE_CALL(MessageEnd)();
1.454 - }
1.455 -
1.456 - pList = &m_msgHooks[m_CurId];
1.457 - for (iter=pList->begin(); iter!=pList->end(); )
1.458 - {
1.459 - pInfo = (*iter);
1.460 - pInfo->IsHooked = true;
1.461 - pInfo->Callback->OnUserMessage(m_CurId, m_OrigBuffer, m_CurRecFilter);
1.462 -
1.463 - if (pInfo->KillMe)
1.464 - {
1.465 - iter = pList->erase(iter);
1.466 - m_FreeListeners.push(pInfo);
1.467 - _DecRefCounter();
1.468 - continue;
1.469 - }
1.470 -
1.471 - pInfo->IsHooked = false;
1.472 - iter++;
1.473 - }
1.474 -
1.475 - RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
1.476 -supercede:
1.477 - m_InHook = false;
1.478 - m_BlockEndPost = true;
1.479 - RETURN_META(MRES_SUPERCEDE);
1.480 -}