1.1 --- a/core/smn_usermsgs.cpp Thu Mar 01 16:35:06 2007 +0000
1.2 +++ b/core/smn_usermsgs.cpp Thu Mar 01 22:49:08 2007 +0000
1.3 @@ -13,39 +13,147 @@
1.4 */
1.5
1.6 #include "HandleSys.h"
1.7 -#include "CellRecipientFilter.h"
1.8 -#include "CMsgIdPool.h"
1.9 +#include "PluginSys.h"
1.10 +#include "CUserMessages.h"
1.11 +#include "CMsgListenerWrapper.h"
1.12
1.13 -#define USERMSG_PASSTHRU (1<<0)
1.14 -#define USERMSG_PASSTHRU_ALL (1<<1)
1.15 -#define USERMSG_RELIABLE (1<<2)
1.16 -#define USERMSG_INITMSG (1<<3)
1.17 -
1.18 -CMessageIdPool g_MessageIds;
1.19 -CellRecipientFilter g_MsgRecFilter;
1.20 HandleType_t g_WrBitBufType;
1.21 Handle_t g_CurMsgHandle;
1.22 +int g_MsgPlayers[256];
1.23 bool g_IsMsgInExec = false;
1.24 -int g_CurMsgFlags = 0;
1.25
1.26 class UsrMessageNatives :
1.27 public SMGlobalClass,
1.28 - public IHandleTypeDispatch
1.29 + public IHandleTypeDispatch,
1.30 + public IPluginsListener
1.31 {
1.32 +public: //SMGlobalClass, IHandleTypeDispatch, IPluginListener
1.33 + void OnSourceModAllInitialized();
1.34 + void OnSourceModShutdown();
1.35 + void OnHandleDestroy(HandleType_t type, void *object);
1.36 + void OnPluginUnloaded(IPlugin *plugin);
1.37 public:
1.38 - void OnSourceModAllInitialized()
1.39 + MsgListenerWrapper *GetNewListener(IPluginContext *pCtx);
1.40 + MsgListenerWrapper *FindListener(int msgid, IPluginContext *pCtx, IPluginFunction *pHook, bool intercept);
1.41 + bool RemoveListener(IPluginContext *pCtx, MsgListenerWrapper *listener, bool intercept);
1.42 +private:
1.43 + CStack<MsgListenerWrapper *> m_FreeListeners;
1.44 +};
1.45 +
1.46 +void UsrMessageNatives::OnSourceModAllInitialized()
1.47 +{
1.48 + g_WrBitBufType = g_HandleSys.CreateType("BitBufWriter", this, 0, NULL, NULL, g_pCoreIdent, NULL);
1.49 + g_PluginSys.AddPluginsListener(this);
1.50 +}
1.51 +
1.52 +void UsrMessageNatives::OnSourceModShutdown()
1.53 +{
1.54 + g_HandleSys.RemoveType(g_WrBitBufType, g_pCoreIdent);
1.55 + g_PluginSys.RemovePluginsListener(this);
1.56 + g_WrBitBufType = 0;
1.57 +}
1.58 +void UsrMessageNatives::OnHandleDestroy(HandleType_t type, void *object)
1.59 +{
1.60 +}
1.61 +
1.62 +void UsrMessageNatives::OnPluginUnloaded(IPlugin *plugin)
1.63 +{
1.64 + List<MsgListenerWrapper *> *wrapper_list;
1.65 +
1.66 + if (plugin->GetProperty("MsgListeners", reinterpret_cast<void **>(&wrapper_list), true))
1.67 {
1.68 - g_WrBitBufType = g_HandleSys.CreateType("BitBufWriter", this, 0, NULL, NULL, g_pCoreIdent, NULL);
1.69 + List<MsgListenerWrapper *>::iterator iter;
1.70 + MsgListenerWrapper *listener;
1.71 +
1.72 + for (iter=wrapper_list->begin(); iter!=wrapper_list->end(); iter++)
1.73 + {
1.74 + listener = (*iter);
1.75 + if (g_UserMsgs.UnhookUserMessage(listener->GetMessageId(), listener, listener->IsInterceptHook()))
1.76 + {
1.77 + m_FreeListeners.push(listener);
1.78 + }
1.79 + }
1.80 +
1.81 + delete wrapper_list;
1.82 + }
1.83 +}
1.84 +
1.85 +MsgListenerWrapper *UsrMessageNatives::GetNewListener(IPluginContext *pCtx)
1.86 +{
1.87 + MsgListenerWrapper *listener_wrapper;
1.88 +
1.89 + if (m_FreeListeners.empty())
1.90 + {
1.91 + listener_wrapper = new MsgListenerWrapper;
1.92 + } else {
1.93 + listener_wrapper = m_FreeListeners.front();
1.94 + m_FreeListeners.pop();
1.95 }
1.96 - void OnSourceModShutdown()
1.97 +
1.98 + List<MsgListenerWrapper *> *wrapper_list;
1.99 + IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext());
1.100 +
1.101 + if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&wrapper_list)))
1.102 {
1.103 - g_HandleSys.RemoveType(g_WrBitBufType, g_pCoreIdent);
1.104 - g_WrBitBufType = 0;
1.105 + wrapper_list = new List<MsgListenerWrapper *>;
1.106 + pl->SetProperty("MsgListeners", wrapper_list);
1.107 + }
1.108 +
1.109 + wrapper_list->push_back(listener_wrapper);
1.110 +
1.111 + return listener_wrapper;
1.112 +}
1.113 +
1.114 +MsgListenerWrapper *UsrMessageNatives::FindListener(int msgid, IPluginContext *pCtx, IPluginFunction *pHook, bool intercept)
1.115 +{
1.116 + MsgListenerWrapper *listener;
1.117 + List<MsgListenerWrapper *> *wrapper_list;
1.118 + List<MsgListenerWrapper *>::iterator iter;
1.119 + IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext());
1.120 + bool found = false;
1.121 +
1.122 + if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&wrapper_list)))
1.123 + {
1.124 + return NULL;
1.125 }
1.126 - void OnHandleDestroy(HandleType_t type, void *object)
1.127 +
1.128 + for (iter=wrapper_list->begin(); iter!=wrapper_list->end(); iter++)
1.129 {
1.130 + listener = (*iter);
1.131 + if ((msgid == listener->GetMessageId())
1.132 + && (intercept == listener->IsInterceptHook())
1.133 + && (pHook == listener->GetHookedFunction()))
1.134 + {
1.135 + found = true;
1.136 + break;
1.137 + }
1.138 }
1.139 -};
1.140 +
1.141 + return (found) ? listener : NULL;
1.142 +}
1.143 +bool UsrMessageNatives::RemoveListener(IPluginContext *pCtx, MsgListenerWrapper *listener, bool intercept)
1.144 +{
1.145 + List<MsgListenerWrapper *> *wrapper_list;
1.146 + IPlugin *pl = g_PluginSys.FindPluginByContext(pCtx->GetContext());
1.147 +
1.148 + if (!pl->GetProperty("MsgListeners", reinterpret_cast<void **>(&wrapper_list)))
1.149 + {
1.150 + return false;
1.151 + }
1.152 +
1.153 + wrapper_list->remove(listener);
1.154 + m_FreeListeners.push(listener);
1.155 +
1.156 + return true;
1.157 +}
1.158 +
1.159 +/**************************************
1.160 +* *
1.161 +* USER MESSAGE NATIVE IMPLEMENTATIONS *
1.162 +* *
1.163 +***************************************/
1.164 +
1.165 +static UsrMessageNatives s_UsrMessageNatives;
1.166
1.167 static cell_t smn_GetUserMessageId(IPluginContext *pCtx, const cell_t *params)
1.168 {
1.169 @@ -57,7 +165,7 @@
1.170 return 0;
1.171 }
1.172
1.173 - return g_MessageIds.GetMessageId(msgname);
1.174 + return g_UserMsgs.GetMessageIndex(msgname);
1.175 }
1.176
1.177 static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params)
1.178 @@ -78,30 +186,14 @@
1.179 return 0;
1.180 }
1.181
1.182 - if ((msgid=g_MessageIds.GetMessageId(msgname)) == INVALID_MESSAGE_ID)
1.183 + if ((msgid=g_UserMsgs.GetMessageIndex(msgname)) == INVALID_MESSAGE_ID)
1.184 {
1.185 return pCtx->ThrowNativeError("Invalid message name: \"%s\"", msgname);
1.186 }
1.187
1.188 pCtx->LocalToPhysAddr(params[2], &cl_array);
1.189 - g_CurMsgFlags = params[4];
1.190
1.191 - g_MsgRecFilter.SetRecipientPtr(cl_array, params[3]);
1.192 - if (g_CurMsgFlags & USERMSG_INITMSG)
1.193 - {
1.194 - g_MsgRecFilter.SetInitMessage(true);
1.195 - }
1.196 - if (g_CurMsgFlags & USERMSG_RELIABLE)
1.197 - {
1.198 - g_MsgRecFilter.SetReliable(true);
1.199 - }
1.200 -
1.201 - if (g_CurMsgFlags & (USERMSG_PASSTHRU_ALL|USERMSG_PASSTHRU)) //:TODO: change this when we can hook messages
1.202 - {
1.203 - pBitBuf = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
1.204 - } else {
1.205 - pBitBuf = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
1.206 - }
1.207 + pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, params[3], params[4]);
1.208
1.209 g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
1.210 g_IsMsgInExec = true;
1.211 @@ -120,30 +212,14 @@
1.212 return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
1.213 }
1.214
1.215 - if (msgid < 0 || msgid > 255)
1.216 + if (msgid < 0 || msgid >= 255)
1.217 {
1.218 return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
1.219 }
1.220
1.221 pCtx->LocalToPhysAddr(params[2], &cl_array);
1.222 - g_CurMsgFlags = params[4];
1.223
1.224 - g_MsgRecFilter.SetRecipientPtr(cl_array, params[3]);
1.225 - if (g_CurMsgFlags & USERMSG_INITMSG)
1.226 - {
1.227 - g_MsgRecFilter.SetInitMessage(true);
1.228 - }
1.229 - if (g_CurMsgFlags & USERMSG_RELIABLE)
1.230 - {
1.231 - g_MsgRecFilter.SetReliable(true);
1.232 - }
1.233 -
1.234 - if (g_CurMsgFlags & (USERMSG_PASSTHRU_ALL|USERMSG_PASSTHRU)) //:TODO: change this when we can hook messages
1.235 - {
1.236 - pBitBuf = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
1.237 - } else {
1.238 - pBitBuf = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
1.239 - }
1.240 + pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, params[3], params[4]);
1.241
1.242 g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
1.243 g_IsMsgInExec = true;
1.244 @@ -160,25 +236,78 @@
1.245 return pCtx->ThrowNativeError("Unable to end message, no message is in progress");
1.246 }
1.247
1.248 - if (g_CurMsgFlags & (USERMSG_PASSTHRU_ALL|USERMSG_PASSTHRU))
1.249 - {
1.250 - engine->MessageEnd();
1.251 - } else {
1.252 - ENGINE_CALL(MessageEnd)();
1.253 - }
1.254 + g_UserMsgs.EndMessage();
1.255
1.256 sec.pOwner = pCtx->GetIdentity();
1.257 sec.pIdentity = g_pCoreIdent;
1.258 g_HandleSys.FreeHandle(g_CurMsgHandle, &sec);
1.259
1.260 g_IsMsgInExec = false;
1.261 - g_CurMsgFlags = 0;
1.262 - g_MsgRecFilter.ResetFilter();
1.263 +
1.264 + return 1;
1.265 +}
1.266 +
1.267 +static cell_t smn_HookUserMessage(IPluginContext *pCtx, const cell_t *params)
1.268 +{
1.269 + IPluginFunction *pHook, *pNotify;
1.270 + MsgListenerWrapper *listener;
1.271 + bool intercept;
1.272 + int msgid = params[1];
1.273 +
1.274 + if (msgid < 0 || msgid >= 255)
1.275 + {
1.276 + return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
1.277 + }
1.278 +
1.279 + pHook = pCtx->GetFunctionById(params[2]);
1.280 + if (!pHook)
1.281 + {
1.282 + return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]);
1.283 + }
1.284 + pNotify = pCtx->GetFunctionById(params[4]);
1.285 +
1.286 + intercept = (params[3]) ? true : false;
1.287 + listener = s_UsrMessageNatives.GetNewListener(pCtx);
1.288 + listener->InitListener(msgid, pHook, pNotify, intercept);
1.289 + g_UserMsgs.HookUserMessage(msgid, listener, intercept);
1.290
1.291 return 1;
1.292 }
1.293
1.294 -static UsrMessageNatives s_UsrMessageNatives;
1.295 +static cell_t smn_UnHookUserMessage(IPluginContext *pCtx, const cell_t *params)
1.296 +{
1.297 + IPluginFunction *pFunc;
1.298 + MsgListenerWrapper *listener;
1.299 + bool intercept;
1.300 + int msgid = params[1];
1.301 +
1.302 + if (msgid < 0 || msgid >= 255)
1.303 + {
1.304 + return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
1.305 + }
1.306 +
1.307 + pFunc = pCtx->GetFunctionById(params[2]);
1.308 + if (!pFunc)
1.309 + {
1.310 + return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]);
1.311 + }
1.312 +
1.313 + intercept = (params[3]) ? true : false;
1.314 + listener = s_UsrMessageNatives.FindListener(msgid, pCtx, pFunc, intercept);
1.315 + if (!listener)
1.316 + {
1.317 + return pCtx->ThrowNativeError("Unable to unhook the current user message");
1.318 + }
1.319 +
1.320 + if (!g_UserMsgs.UnhookUserMessage(msgid, listener, intercept))
1.321 + {
1.322 + return pCtx->ThrowNativeError("Unable to unhook the current user message");
1.323 + }
1.324 +
1.325 + s_UsrMessageNatives.RemoveListener(pCtx, listener, intercept);
1.326 +
1.327 + return 1;
1.328 +}
1.329
1.330 REGISTER_NATIVES(usrmsgnatives)
1.331 {
1.332 @@ -186,5 +315,7 @@
1.333 {"StartMessage", smn_StartMessage},
1.334 {"StartMessageEx", smn_StartMessageEx},
1.335 {"EndMessage", smn_EndMessage},
1.336 + {"HookUserMessage", smn_HookUserMessage},
1.337 + {"UnHookUserMessage", smn_UnHookUserMessage},
1.338 {NULL, NULL}
1.339 };