1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/smn_usermsgs.cpp Fri Feb 16 18:47:16 2007 +0000
1.3 @@ -0,0 +1,190 @@
1.4 +/**
1.5 +* vim: set ts=4 :
1.6 +* ===============================================================
1.7 +* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
1.8 +* ===============================================================
1.9 +*
1.10 +* This file is not open source and may not be copied without explicit
1.11 +* written permission of AlliedModders LLC. This file may not be redistributed
1.12 +* in whole or significant part.
1.13 +* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
1.14 +*
1.15 +* Version: $Id$
1.16 +*/
1.17 +
1.18 +#include "HandleSys.h"
1.19 +#include "CellRecipientFilter.h"
1.20 +#include "CMsgIdPool.h"
1.21 +
1.22 +#define USERMSG_PASSTHRU (1<<0)
1.23 +#define USERMSG_PASSTHRU_ALL (1<<1)
1.24 +#define USERMSG_RELIABLE (1<<2)
1.25 +#define USERMSG_INITMSG (1<<3)
1.26 +
1.27 +CMessageIdPool g_MessageIds;
1.28 +CellRecipientFilter g_MsgRecFilter;
1.29 +HandleType_t g_WrBitBufType;
1.30 +Handle_t g_CurMsgHandle;
1.31 +bool g_IsMsgInExec = false;
1.32 +int g_CurMsgFlags = 0;
1.33 +
1.34 +class UsrMessageNatives :
1.35 + public SMGlobalClass,
1.36 + public IHandleTypeDispatch
1.37 +{
1.38 +public:
1.39 + void OnSourceModAllInitialized()
1.40 + {
1.41 + g_WrBitBufType = g_HandleSys.CreateType("BitBufWriter", this, 0, NULL, NULL, g_pCoreIdent, NULL);
1.42 + }
1.43 + void OnSourceModShutdown()
1.44 + {
1.45 + g_HandleSys.RemoveType(g_WrBitBufType, g_pCoreIdent);
1.46 + g_WrBitBufType = 0;
1.47 + }
1.48 + void OnHandleDestroy(HandleType_t type, void *object)
1.49 + {
1.50 + }
1.51 +};
1.52 +
1.53 +static cell_t smn_GetUserMessageId(IPluginContext *pCtx, const cell_t *params)
1.54 +{
1.55 + char *msgname;
1.56 + int err;
1.57 + if ((err=pCtx->LocalToString(params[1], &msgname)) != SP_ERROR_NONE)
1.58 + {
1.59 + pCtx->ThrowNativeErrorEx(err, NULL);
1.60 + return 0;
1.61 + }
1.62 +
1.63 + return g_MessageIds.GetMessageId(msgname);
1.64 +}
1.65 +
1.66 +static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params)
1.67 +{
1.68 + char *msgname;
1.69 + cell_t *cl_array;
1.70 + int msgid, err;
1.71 + bf_write *pBitBuf;
1.72 +
1.73 + if (g_IsMsgInExec)
1.74 + {
1.75 + return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
1.76 + }
1.77 +
1.78 + if ((err=pCtx->LocalToString(params[1], &msgname)) != SP_ERROR_NONE)
1.79 + {
1.80 + pCtx->ThrowNativeErrorEx(err, NULL);
1.81 + return 0;
1.82 + }
1.83 +
1.84 + if ((msgid=g_MessageIds.GetMessageId(msgname)) == INVALID_MESSAGE_ID)
1.85 + {
1.86 + return pCtx->ThrowNativeError("Invalid message name: \"%s\"", msgname);
1.87 + }
1.88 +
1.89 + pCtx->LocalToPhysAddr(params[2], &cl_array);
1.90 + g_CurMsgFlags = params[4];
1.91 +
1.92 + g_MsgRecFilter.SetRecipientPtr(cl_array, params[3]);
1.93 + if (g_CurMsgFlags & USERMSG_INITMSG)
1.94 + {
1.95 + g_MsgRecFilter.SetInitMessage(true);
1.96 + }
1.97 + if (g_CurMsgFlags & USERMSG_RELIABLE)
1.98 + {
1.99 + g_MsgRecFilter.SetReliable(true);
1.100 + }
1.101 +
1.102 + if (g_CurMsgFlags & (USERMSG_PASSTHRU_ALL|USERMSG_PASSTHRU)) //:TODO: change this when we can hook messages
1.103 + {
1.104 + pBitBuf = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
1.105 + } else {
1.106 + pBitBuf = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
1.107 + }
1.108 +
1.109 + g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
1.110 + g_IsMsgInExec = true;
1.111 +
1.112 + return g_CurMsgHandle;
1.113 +}
1.114 +
1.115 +static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params)
1.116 +{
1.117 + cell_t *cl_array;
1.118 + bf_write *pBitBuf;
1.119 + int msgid = params[1];
1.120 +
1.121 + if (g_IsMsgInExec)
1.122 + {
1.123 + return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
1.124 + }
1.125 +
1.126 + if (msgid < 0 || msgid > 255)
1.127 + {
1.128 + return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
1.129 + }
1.130 +
1.131 + pCtx->LocalToPhysAddr(params[2], &cl_array);
1.132 + g_CurMsgFlags = params[4];
1.133 +
1.134 + g_MsgRecFilter.SetRecipientPtr(cl_array, params[3]);
1.135 + if (g_CurMsgFlags & USERMSG_INITMSG)
1.136 + {
1.137 + g_MsgRecFilter.SetInitMessage(true);
1.138 + }
1.139 + if (g_CurMsgFlags & USERMSG_RELIABLE)
1.140 + {
1.141 + g_MsgRecFilter.SetReliable(true);
1.142 + }
1.143 +
1.144 + if (g_CurMsgFlags & (USERMSG_PASSTHRU_ALL|USERMSG_PASSTHRU)) //:TODO: change this when we can hook messages
1.145 + {
1.146 + pBitBuf = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
1.147 + } else {
1.148 + pBitBuf = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
1.149 + }
1.150 +
1.151 + g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
1.152 + g_IsMsgInExec = true;
1.153 +
1.154 + return g_CurMsgHandle;
1.155 +}
1.156 +
1.157 +static cell_t smn_EndMessage(IPluginContext *pCtx, const cell_t *params)
1.158 +{
1.159 + HandleSecurity sec;
1.160 +
1.161 + if (!g_IsMsgInExec)
1.162 + {
1.163 + return pCtx->ThrowNativeError("Unable to end message, no message is in progress");
1.164 + }
1.165 +
1.166 + if (g_CurMsgFlags & (USERMSG_PASSTHRU_ALL|USERMSG_PASSTHRU))
1.167 + {
1.168 + engine->MessageEnd();
1.169 + } else {
1.170 + ENGINE_CALL(MessageEnd)();
1.171 + }
1.172 +
1.173 + sec.pOwner = pCtx->GetIdentity();
1.174 + sec.pIdentity = g_pCoreIdent;
1.175 + g_HandleSys.FreeHandle(g_CurMsgHandle, &sec);
1.176 +
1.177 + g_IsMsgInExec = false;
1.178 + g_CurMsgFlags = 0;
1.179 + g_MsgRecFilter.ResetFilter();
1.180 +
1.181 + return 1;
1.182 +}
1.183 +
1.184 +static UsrMessageNatives s_UsrMessageNatives;
1.185 +
1.186 +REGISTER_NATIVES(usrmsgnatives)
1.187 +{
1.188 + {"GetUserMessageId", smn_GetUserMessageId},
1.189 + {"StartMessage", smn_StartMessage},
1.190 + {"StartMessageEx", smn_StartMessageEx},
1.191 + {"EndMessage", smn_EndMessage},
1.192 + {NULL, NULL}
1.193 +};