core/smn_usermsgs.cpp
author Scott Ehlert <ds@alliedmods.net>
Sat Feb 17 05:33:31 2007 +0000 (2007-02-17)
changeset 511 c29f8796bcf4
parent 505 9fb8a1ccd4ec
child 552 e58968c96860
permissions -rw-r--r--
Initial fixes to ensure static strings passed to new convars
Also fixed minor warning in smn_bitbuffer.cpp
     1 /**
     2 * vim: set ts=4 :
     3 * ===============================================================
     4 * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5 * ===============================================================
     6 *
     7 * This file is not open source and may not be copied without explicit
     8 * written permission of AlliedModders LLC.  This file may not be redistributed 
     9 * in whole or significant part.
    10 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    11 *
    12 * Version: $Id$
    13 */
    14 
    15 #include "HandleSys.h"
    16 #include "CellRecipientFilter.h"
    17 #include "CMsgIdPool.h"
    18 
    19 #define USERMSG_PASSTHRU			(1<<0)
    20 #define USERMSG_PASSTHRU_ALL		(1<<1)
    21 #define USERMSG_RELIABLE			(1<<2)
    22 #define USERMSG_INITMSG				(1<<3)
    23 
    24 CMessageIdPool g_MessageIds;
    25 CellRecipientFilter g_MsgRecFilter;
    26 HandleType_t g_WrBitBufType;
    27 Handle_t g_CurMsgHandle;
    28 bool g_IsMsgInExec = false;
    29 int g_CurMsgFlags = 0;
    30 
    31 class UsrMessageNatives :
    32 	public SMGlobalClass,
    33 	public IHandleTypeDispatch
    34 {
    35 public:
    36 	void OnSourceModAllInitialized()
    37 	{
    38 		g_WrBitBufType = g_HandleSys.CreateType("BitBufWriter", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    39 	}
    40 	void OnSourceModShutdown()
    41 	{
    42 		g_HandleSys.RemoveType(g_WrBitBufType, g_pCoreIdent);
    43 		g_WrBitBufType = 0;
    44 	}
    45 	void OnHandleDestroy(HandleType_t type, void *object)
    46 	{
    47 	}
    48 };
    49 
    50 static cell_t smn_GetUserMessageId(IPluginContext *pCtx, const cell_t *params)
    51 {
    52 	char *msgname;
    53 	int err;
    54 	if ((err=pCtx->LocalToString(params[1], &msgname)) != SP_ERROR_NONE)
    55 	{
    56 		pCtx->ThrowNativeErrorEx(err, NULL);
    57 		return 0;
    58 	}
    59 
    60 	return g_MessageIds.GetMessageId(msgname);
    61 }
    62 
    63 static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params)
    64 {
    65 	char *msgname;
    66 	cell_t *cl_array;
    67 	int msgid, err;
    68 	bf_write *pBitBuf;
    69 
    70 	if (g_IsMsgInExec)
    71 	{
    72 		return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
    73 	}
    74 
    75 	if ((err=pCtx->LocalToString(params[1], &msgname)) != SP_ERROR_NONE)
    76 	{
    77 		pCtx->ThrowNativeErrorEx(err, NULL);
    78 		return 0;
    79 	}
    80 
    81 	if ((msgid=g_MessageIds.GetMessageId(msgname)) == INVALID_MESSAGE_ID)
    82 	{
    83 		return pCtx->ThrowNativeError("Invalid message name: \"%s\"", msgname);
    84 	}
    85 
    86 	pCtx->LocalToPhysAddr(params[2], &cl_array);
    87 	g_CurMsgFlags = params[4];
    88 
    89 	g_MsgRecFilter.SetRecipientPtr(cl_array, params[3]);
    90 	if (g_CurMsgFlags & USERMSG_INITMSG)
    91 	{
    92 		g_MsgRecFilter.SetInitMessage(true);
    93 	}
    94 	if (g_CurMsgFlags & USERMSG_RELIABLE)
    95 	{
    96 		g_MsgRecFilter.SetReliable(true);
    97 	}
    98 
    99 	if (g_CurMsgFlags & (USERMSG_PASSTHRU_ALL|USERMSG_PASSTHRU)) //:TODO: change this when we can hook messages
   100 	{
   101 		pBitBuf = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
   102 	} else {
   103 		pBitBuf = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
   104 	}
   105 
   106 	g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
   107 	g_IsMsgInExec = true;
   108 
   109 	return g_CurMsgHandle;
   110 }
   111 
   112 static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params)
   113 {
   114 	cell_t *cl_array;
   115 	bf_write *pBitBuf;
   116 	int msgid = params[1];
   117 
   118 	if (g_IsMsgInExec)
   119 	{
   120 		return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
   121 	}
   122 
   123 	if (msgid < 0 || msgid > 255)
   124 	{
   125 		return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
   126 	}
   127 
   128 	pCtx->LocalToPhysAddr(params[2], &cl_array);
   129 	g_CurMsgFlags = params[4];
   130 
   131 	g_MsgRecFilter.SetRecipientPtr(cl_array, params[3]);
   132 	if (g_CurMsgFlags & USERMSG_INITMSG)
   133 	{
   134 		g_MsgRecFilter.SetInitMessage(true);
   135 	}
   136 	if (g_CurMsgFlags & USERMSG_RELIABLE)
   137 	{
   138 		g_MsgRecFilter.SetReliable(true);
   139 	}
   140 
   141 	if (g_CurMsgFlags & (USERMSG_PASSTHRU_ALL|USERMSG_PASSTHRU)) //:TODO: change this when we can hook messages
   142 	{
   143 		pBitBuf = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
   144 	} else {
   145 		pBitBuf = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
   146 	}
   147 
   148 	g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
   149 	g_IsMsgInExec = true;
   150 
   151 	return g_CurMsgHandle;
   152 }
   153 
   154 static cell_t smn_EndMessage(IPluginContext *pCtx, const cell_t *params)
   155 {
   156 	HandleSecurity sec;
   157 
   158 	if (!g_IsMsgInExec)
   159 	{
   160 		return pCtx->ThrowNativeError("Unable to end message, no message is in progress");
   161 	}
   162 
   163 	if (g_CurMsgFlags & (USERMSG_PASSTHRU_ALL|USERMSG_PASSTHRU))
   164 	{
   165 		engine->MessageEnd();
   166 	} else {
   167 		ENGINE_CALL(MessageEnd)();
   168 	}
   169 
   170 	sec.pOwner = pCtx->GetIdentity();
   171 	sec.pIdentity = g_pCoreIdent;
   172 	g_HandleSys.FreeHandle(g_CurMsgHandle, &sec);
   173 
   174 	g_IsMsgInExec = false;
   175 	g_CurMsgFlags = 0;
   176 	g_MsgRecFilter.ResetFilter();
   177 
   178 	return 1;
   179 }
   180 
   181 static UsrMessageNatives s_UsrMessageNatives;
   182 
   183 REGISTER_NATIVES(usrmsgnatives)
   184 {
   185 	{"GetUserMessageId",			smn_GetUserMessageId},
   186 	{"StartMessage",				smn_StartMessage},
   187 	{"StartMessageEx",				smn_StartMessageEx},
   188 	{"EndMessage",					smn_EndMessage},
   189 	{NULL,							NULL}
   190 };