1.1 --- a/core/smn_usermsgs.cpp Fri Mar 28 06:21:34 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,497 +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 "HandleSys.h"
1.36 -#include "PluginSys.h"
1.37 -#include "UserMessages.h"
1.38 -#include "smn_usermsgs.h"
1.39 -
1.40 -HandleType_t g_WrBitBufType;
1.41 -HandleType_t g_RdBitBufType;
1.42 -Handle_t g_CurMsgHandle;
1.43 -Handle_t g_ReadBufHandle;
1.44 -bf_read g_ReadBitBuf;
1.45 -
1.46 -int g_MsgPlayers[256];
1.47 -bool g_IsMsgInExec = false;
1.48 -
1.49 -typedef List<MsgListenerWrapper *> MsgWrapperList;
1.50 -typedef List<MsgListenerWrapper *>::iterator MsgWrapperIter;
1.51 -
1.52 -class UsrMessageNatives :
1.53 - public SMGlobalClass,
1.54 - public IHandleTypeDispatch,
1.55 - public IPluginsListener
1.56 -{
1.57 -public:
1.58 - ~UsrMessageNatives();
1.59 -public: //SMGlobalClass, IHandleTypeDispatch, IPluginListener
1.60 - void OnSourceModAllInitialized();
1.61 - void OnSourceModShutdown();
1.62 - void OnHandleDestroy(HandleType_t type, void *object);
1.63 - void OnPluginUnloaded(IPlugin *plugin);
1.64 -public:
1.65 - MsgListenerWrapper *CreateListener(IPluginContext *pCtx);
1.66 - bool FindListener(int msgid, IPluginContext *pCtx, IPluginFunction *pHook, bool intercept, MsgWrapperIter *iter);
1.67 - bool DeleteListener(IPluginContext *pCtx, MsgWrapperIter iter);
1.68 -private:
1.69 - CStack<MsgListenerWrapper *> m_FreeListeners;
1.70 -};
1.71 -
1.72 -UsrMessageNatives::~UsrMessageNatives()
1.73 -{
1.74 - CStack<MsgListenerWrapper *>::iterator iter;
1.75 - for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
1.76 - {
1.77 - delete (*iter);
1.78 - }
1.79 - m_FreeListeners.popall();
1.80 -}
1.81 -
1.82 -void UsrMessageNatives::OnSourceModAllInitialized()
1.83 -{
1.84 - HandleAccess sec;
1.85 -
1.86 - g_HandleSys.InitAccessDefaults(NULL, &sec);
1.87 - sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY;
1.88 -
1.89 - g_WrBitBufType = g_HandleSys.CreateType("BitBufWriter", this, 0, NULL, NULL, g_pCoreIdent, NULL);
1.90 - g_RdBitBufType = g_HandleSys.CreateType("BitBufReader", this, 0, NULL, &sec, g_pCoreIdent, NULL);
1.91 -
1.92 - g_ReadBufHandle = g_HandleSys.CreateHandle(g_RdBitBufType, &g_ReadBitBuf, NULL, g_pCoreIdent, NULL);
1.93 -
1.94 - g_PluginSys.AddPluginsListener(this);
1.95 -}
1.96 -
1.97 -void UsrMessageNatives::OnSourceModShutdown()
1.98 -{
1.99 - HandleSecurity sec;
1.100 - sec.pIdentity = g_pCoreIdent;
1.101 -
1.102 - g_HandleSys.FreeHandle(g_ReadBufHandle, &sec);
1.103 -
1.104 - g_HandleSys.RemoveType(g_WrBitBufType, g_pCoreIdent);
1.105 - g_HandleSys.RemoveType(g_RdBitBufType, g_pCoreIdent);
1.106 -
1.107 - g_WrBitBufType = 0;
1.108 - g_RdBitBufType = 0;
1.109 -}
1.110 -
1.111 -void UsrMessageNatives::OnHandleDestroy(HandleType_t type, void *object)
1.112 -{
1.113 -}
1.114 -
1.115 -void UsrMessageNatives::OnPluginUnloaded(IPlugin *plugin)
1.116 -{
1.117 - MsgWrapperList *pList;
1.118 -
1.119 - if (plugin->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList), true))
1.120 - {
1.121 - MsgWrapperIter iter;
1.122 - MsgListenerWrapper *pListener;
1.123 -
1.124 - for (iter=pList->begin(); iter!=pList->end(); iter++)
1.125 - {
1.126 - pListener = (*iter);
1.127 - if (g_UserMsgs.UnhookUserMessage(pListener->GetMessageId(), pListener, pListener->IsInterceptHook()))
1.128 - {
1.129 - m_FreeListeners.push(pListener);
1.130 - }
1.131 - }
1.132 -
1.133 - delete pList;
1.134 - }
1.135 -}
1.136 -
1.137 -MsgListenerWrapper *UsrMessageNatives::CreateListener(IPluginContext *pCtx)
1.138 -{
1.139 - MsgWrapperList *pList;
1.140 - MsgListenerWrapper *pListener;
1.141 - IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext());
1.142 -
1.143 - if (m_FreeListeners.empty())
1.144 - {
1.145 - pListener = new MsgListenerWrapper;
1.146 - } else {
1.147 - pListener = m_FreeListeners.front();
1.148 - m_FreeListeners.pop();
1.149 - }
1.150 -
1.151 - if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList)))
1.152 - {
1.153 - pList = new List<MsgListenerWrapper *>;
1.154 - pl->SetProperty("MsgListeners", pList);
1.155 - }
1.156 -
1.157 - pList->push_back(pListener);
1.158 -
1.159 - return pListener;
1.160 -}
1.161 -
1.162 -bool UsrMessageNatives::FindListener(int msgid, IPluginContext *pCtx, IPluginFunction *pHook, bool intercept, MsgWrapperIter *iter)
1.163 -{
1.164 - MsgWrapperList *pList;
1.165 - MsgWrapperIter _iter;
1.166 - MsgListenerWrapper *pListener;
1.167 - IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext());
1.168 -
1.169 - if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList)))
1.170 - {
1.171 - return false;
1.172 - }
1.173 -
1.174 - for (_iter=pList->begin(); _iter!=pList->end(); _iter++)
1.175 - {
1.176 - pListener = (*_iter);
1.177 - if ((msgid == pListener->GetMessageId())
1.178 - && (intercept == pListener->IsInterceptHook())
1.179 - && (pHook == pListener->GetHookedFunction()))
1.180 - {
1.181 - *iter = _iter;
1.182 - return true;
1.183 - }
1.184 - }
1.185 -
1.186 - return false;
1.187 -}
1.188 -
1.189 -bool UsrMessageNatives::DeleteListener(IPluginContext *pCtx, MsgWrapperIter iter)
1.190 -{
1.191 - MsgWrapperList *pList;
1.192 - MsgListenerWrapper *pListener;
1.193 - IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext());
1.194 -
1.195 - if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&pList)))
1.196 - {
1.197 - return false;
1.198 - }
1.199 -
1.200 - pListener = (*iter);
1.201 - pList->erase(iter);
1.202 - m_FreeListeners.push(pListener);
1.203 -
1.204 - return true;
1.205 -}
1.206 -
1.207 -/***************************************
1.208 - * *
1.209 - * USER MESSAGE WRAPPER IMPLEMENTATION *
1.210 - * *
1.211 - ***************************************/
1.212 -
1.213 -void MsgListenerWrapper::Initialize(int msgid, IPluginFunction *hook, IPluginFunction *notify, bool intercept)
1.214 -{
1.215 - if (intercept)
1.216 - {
1.217 - m_Intercept = hook;
1.218 - m_Hook = NULL;
1.219 - } else {
1.220 - m_Hook = hook;
1.221 - m_Intercept = NULL;
1.222 - }
1.223 -
1.224 - if (notify)
1.225 - {
1.226 - m_Notify = notify;
1.227 - } else {
1.228 - m_Notify = NULL;
1.229 - }
1.230 -
1.231 - m_MsgId = msgid;
1.232 - m_IsInterceptHook = intercept;
1.233 -}
1.234 -
1.235 -size_t MsgListenerWrapper::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter)
1.236 -{
1.237 - size_t size = static_cast<size_t>(pFilter->GetRecipientCount());
1.238 -
1.239 - for (size_t i=0; i<size; i++)
1.240 - {
1.241 - pl_array[i] = pFilter->GetRecipientIndex(i);
1.242 - }
1.243 -
1.244 - return size;
1.245 -}
1.246 -
1.247 -bool MsgListenerWrapper::IsInterceptHook() const
1.248 -{
1.249 - return m_IsInterceptHook;
1.250 -}
1.251 -
1.252 -int MsgListenerWrapper::GetMessageId() const
1.253 -{
1.254 - return m_MsgId;
1.255 -}
1.256 -
1.257 -IPluginFunction *MsgListenerWrapper::GetHookedFunction() const
1.258 -{
1.259 - if (m_Hook)
1.260 - {
1.261 - return m_Hook;
1.262 - } else {
1.263 - return m_Intercept;
1.264 - }
1.265 -}
1.266 -
1.267 -IPluginFunction *MsgListenerWrapper::GetNotifyFunction() const
1.268 -{
1.269 - return m_Notify;
1.270 -}
1.271 -
1.272 -void MsgListenerWrapper::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
1.273 -{
1.274 - cell_t res;
1.275 - size_t size = _FillInPlayers(g_MsgPlayers, pFilter);
1.276 -
1.277 - g_ReadBitBuf.StartReading(bf->GetBasePointer(), bf->GetNumBytesWritten());
1.278 -
1.279 - m_Hook->PushCell(msg_id);
1.280 - m_Hook->PushCell(g_ReadBufHandle);
1.281 - m_Hook->PushArray(g_MsgPlayers, size);
1.282 - m_Hook->PushCell(size);
1.283 - m_Hook->PushCell(pFilter->IsReliable());
1.284 - m_Hook->PushCell(pFilter->IsInitMessage());
1.285 - m_Hook->Execute(&res);
1.286 -}
1.287 -
1.288 -ResultType MsgListenerWrapper::InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
1.289 -{
1.290 - cell_t res = static_cast<cell_t>(Pl_Continue);
1.291 - size_t size = _FillInPlayers(g_MsgPlayers, pFilter);
1.292 -
1.293 - g_ReadBitBuf.StartReading(bf->GetBasePointer(), bf->GetNumBytesWritten());
1.294 -
1.295 - m_Intercept->PushCell(msg_id);
1.296 - m_Intercept->PushCell(g_ReadBufHandle);
1.297 - m_Intercept->PushArray(g_MsgPlayers, size);
1.298 - m_Intercept->PushCell(size);
1.299 - m_Intercept->PushCell(pFilter->IsReliable());
1.300 - m_Intercept->PushCell(pFilter->IsInitMessage());
1.301 - m_Intercept->Execute(&res);
1.302 -
1.303 - return static_cast<ResultType>(res);
1.304 -}
1.305 -
1.306 -void MsgListenerWrapper::OnUserMessageSent(int msg_id)
1.307 -{
1.308 - if (!m_Notify)
1.309 - {
1.310 - return;
1.311 - }
1.312 -
1.313 - cell_t res;
1.314 - m_Notify->PushCell(msg_id);
1.315 - m_Notify->Execute(&res);
1.316 -}
1.317 -
1.318 -/***************************************
1.319 - * *
1.320 - * USER MESSAGE NATIVE IMPLEMENTATIONS *
1.321 - * *
1.322 - ***************************************/
1.323 -
1.324 -static UsrMessageNatives s_UsrMessageNatives;
1.325 -
1.326 -static cell_t smn_GetUserMessageId(IPluginContext *pCtx, const cell_t *params)
1.327 -{
1.328 - char *msgname;
1.329 - pCtx->LocalToString(params[1], &msgname);
1.330 -
1.331 - return g_UserMsgs.GetMessageIndex(msgname);
1.332 -}
1.333 -
1.334 -static cell_t smn_GetUserMessageName(IPluginContext *pCtx, const cell_t *params)
1.335 -{
1.336 - char *msgname;
1.337 -
1.338 - pCtx->LocalToPhysAddr(params[2], (cell_t **)&msgname);
1.339 -
1.340 - return g_UserMsgs.GetMessageName(params[1], msgname, params[3]);
1.341 -}
1.342 -
1.343 -static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params)
1.344 -{
1.345 - char *msgname;
1.346 - cell_t *cl_array;
1.347 - int msgid;
1.348 - bf_write *pBitBuf;
1.349 -
1.350 - if (g_IsMsgInExec)
1.351 - {
1.352 - return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
1.353 - }
1.354 -
1.355 - pCtx->LocalToString(params[1], &msgname);
1.356 -
1.357 - if ((msgid=g_UserMsgs.GetMessageIndex(msgname)) == INVALID_MESSAGE_ID)
1.358 - {
1.359 - return pCtx->ThrowNativeError("Invalid message name: \"%s\"", msgname);
1.360 - }
1.361 -
1.362 - pCtx->LocalToPhysAddr(params[2], &cl_array);
1.363 -
1.364 - pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, params[3], params[4]);
1.365 - if (!pBitBuf)
1.366 - {
1.367 - return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
1.368 - }
1.369 -
1.370 - g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
1.371 - g_IsMsgInExec = true;
1.372 -
1.373 - return g_CurMsgHandle;
1.374 -}
1.375 -
1.376 -static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params)
1.377 -{
1.378 - cell_t *cl_array;
1.379 - bf_write *pBitBuf;
1.380 - int msgid = params[1];
1.381 -
1.382 - if (g_IsMsgInExec)
1.383 - {
1.384 - return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
1.385 - }
1.386 -
1.387 - if (msgid < 0 || msgid >= 255)
1.388 - {
1.389 - return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
1.390 - }
1.391 -
1.392 - pCtx->LocalToPhysAddr(params[2], &cl_array);
1.393 -
1.394 - pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, params[3], params[4]);
1.395 - if (!pBitBuf)
1.396 - {
1.397 - return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
1.398 - }
1.399 -
1.400 - g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
1.401 - g_IsMsgInExec = true;
1.402 -
1.403 - return g_CurMsgHandle;
1.404 -}
1.405 -
1.406 -static cell_t smn_EndMessage(IPluginContext *pCtx, const cell_t *params)
1.407 -{
1.408 - HandleSecurity sec;
1.409 -
1.410 - if (!g_IsMsgInExec)
1.411 - {
1.412 - return pCtx->ThrowNativeError("Unable to end message, no message is in progress");
1.413 - }
1.414 -
1.415 - g_UserMsgs.EndMessage();
1.416 -
1.417 - sec.pOwner = pCtx->GetIdentity();
1.418 - sec.pIdentity = g_pCoreIdent;
1.419 - g_HandleSys.FreeHandle(g_CurMsgHandle, &sec);
1.420 -
1.421 - g_IsMsgInExec = false;
1.422 -
1.423 - return 1;
1.424 -}
1.425 -
1.426 -static cell_t smn_HookUserMessage(IPluginContext *pCtx, const cell_t *params)
1.427 -{
1.428 - IPluginFunction *pHook, *pNotify;
1.429 - MsgListenerWrapper *pListener;
1.430 - bool intercept;
1.431 - int msgid = params[1];
1.432 -
1.433 - if (msgid < 0 || msgid >= 255)
1.434 - {
1.435 - return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
1.436 - }
1.437 -
1.438 - pHook = pCtx->GetFunctionById(params[2]);
1.439 - if (!pHook)
1.440 - {
1.441 - return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]);
1.442 - }
1.443 - pNotify = pCtx->GetFunctionById(params[4]);
1.444 - intercept = (params[3]) ? true : false;
1.445 -
1.446 - pListener = s_UsrMessageNatives.CreateListener(pCtx);
1.447 - pListener->Initialize(msgid, pHook, pNotify, intercept);
1.448 -
1.449 - g_UserMsgs.HookUserMessage(msgid, pListener, intercept);
1.450 -
1.451 - return 1;
1.452 -}
1.453 -
1.454 -static cell_t smn_UnhookUserMessage(IPluginContext *pCtx, const cell_t *params)
1.455 -{
1.456 - IPluginFunction *pFunc;
1.457 - MsgListenerWrapper *pListener;
1.458 - MsgWrapperIter iter;
1.459 - bool intercept;
1.460 - int msgid = params[1];
1.461 -
1.462 - if (msgid < 0 || msgid >= 255)
1.463 - {
1.464 - return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
1.465 - }
1.466 -
1.467 - pFunc = pCtx->GetFunctionById(params[2]);
1.468 - if (!pFunc)
1.469 - {
1.470 - return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]);
1.471 - }
1.472 - intercept = (params[3]) ? true : false;
1.473 -
1.474 - if (!s_UsrMessageNatives.FindListener(msgid, pCtx, pFunc, intercept, &iter))
1.475 - {
1.476 - return pCtx->ThrowNativeError("Unable to unhook the current user message");
1.477 - }
1.478 -
1.479 - pListener = (*iter);
1.480 - if (!g_UserMsgs.UnhookUserMessage(msgid, pListener, intercept))
1.481 - {
1.482 - return pCtx->ThrowNativeError("Unable to unhook the current user message");
1.483 - }
1.484 -
1.485 - s_UsrMessageNatives.DeleteListener(pCtx, iter);
1.486 -
1.487 - return 1;
1.488 -}
1.489 -
1.490 -REGISTER_NATIVES(usrmsgnatives)
1.491 -{
1.492 - {"GetUserMessageId", smn_GetUserMessageId},
1.493 - {"GetUserMessageName", smn_GetUserMessageName},
1.494 - {"StartMessage", smn_StartMessage},
1.495 - {"StartMessageEx", smn_StartMessageEx},
1.496 - {"EndMessage", smn_EndMessage},
1.497 - {"HookUserMessage", smn_HookUserMessage},
1.498 - {"UnhookUserMessage", smn_UnhookUserMessage},
1.499 - {NULL, NULL}
1.500 -};