Added initial support for protobuf usermessages on CS:GO (bug 5579, r=asherkin).
authorNicholas Hastings <skamonkey@gmail.com>
Tue Jan 22 21:43:12 2013 -0500 (2013-01-22)
changeset 3743a98686a77974
parent 3742 80034eb49c32
child 3744 74ee8a683813
Added initial support for protobuf usermessages on CS:GO (bug 5579, r=asherkin).
AMBuildScript
core/AMBuilder
core/HalfLife2.cpp
core/MenuStyle_Radio.cpp
core/MenuStyle_Radio.h
core/UserMessagePBHelpers.h
core/UserMessages.cpp
core/UserMessages.h
core/smn_bitbuffer.cpp
core/smn_console.cpp
core/smn_hudtext.cpp
core/smn_protobuf.cpp
core/smn_usermsgs.cpp
core/smn_usermsgs.h
core/sourcemod.h
plugins/funcommands/blind.sp
plugins/funcommands/drug.sp
plugins/include/core.inc
plugins/include/protobuf.inc
plugins/include/sourcemod.inc
plugins/include/usermessages.inc
public/IUserMessages.h
     1.1 --- a/AMBuildScript	Mon Jan 07 09:09:14 2013 -0500
     1.2 +++ b/AMBuildScript	Tue Jan 22 21:43:12 2013 -0500
     1.3 @@ -124,7 +124,6 @@
     1.4  				self.compiler.AddToListVar('CFLAGS', '-m32')
     1.5  				self.compiler.AddToListVar('POSTLINKFLAGS', '-m32')
     1.6  				self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
     1.7 -				self.compiler.AddToListVar('CXXFLAGS', '-fno-rtti')
     1.8  				self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
     1.9  				self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
    1.10  				self.compiler.AddToListVar('CXXFLAGS', '-Wno-overloaded-virtual')
     2.1 --- a/core/AMBuilder	Mon Jan 07 09:09:14 2013 -0500
     2.2 +++ b/core/AMBuilder	Tue Jan 22 21:43:12 2013 -0500
     2.3 @@ -1,5 +1,6 @@
     2.4  # vim: set ts=2 sw=2 tw=99 noet ft=python: 
     2.5  import os
     2.6 +from ambuild.command import SymlinkCommand
     2.7  
     2.8  for i in SM.sdkInfo:
     2.9  	sdk = SM.sdkInfo[i]
    2.10 @@ -10,9 +11,35 @@
    2.11  
    2.12  	compiler = SM.DefaultHL2Compiler('core', i)
    2.13  
    2.14 +	if i == 'csgo':
    2.15 +		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.cache[sdk['sdk']], 'common', 'protobuf-2.3.0', 'src'))
    2.16 +		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.cache[sdk['sdk']], 'public', 'engine', 'protobuf'))
    2.17 +		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.cache[sdk['sdk']], 'public', 'game', 'shared', 'csgo', 'protobuf'))
    2.18 +
    2.19  	extension = AMBuild.AddJob(name)
    2.20  	binary = Cpp.LibraryBuilder(name, AMBuild, extension, compiler)
    2.21  	SM.PreSetupHL2Job(extension, binary, i)
    2.22 +
    2.23 +	if i == 'csgo':
    2.24 +		if AMBuild.target['platform'] == 'linux':
    2.25 +			link = os.path.join(os.path.join(AMBuild.outputFolder, extension.workFolder), 'libprotobuf.a')
    2.26 +			target = os.path.join(os.path.join(AMBuild.cache[sdk['sdk']], 'lib', 'linux32', 'release'), 'libprotobuf.a')
    2.27 +			try:
    2.28 +				os.lstat(link)
    2.29 +			except:
    2.30 +				extension.AddCommand(SymlinkCommand(link, target))
    2.31 +		elif AMBuild.target['platform'] == 'darwin':
    2.32 +			link = os.path.join(os.path.join(AMBuild.outputFolder, extension.workFolder), 'libprotobuf.a')
    2.33 +			target = os.path.join(os.path.join(AMBuild.cache[sdk['sdk']], 'lib', 'osx32', 'release'), 'libprotobuf.a')
    2.34 +			try:
    2.35 +				os.lstat(link)
    2.36 +			except:
    2.37 +				extension.AddCommand(SymlinkCommand(link, target))
    2.38 +		elif AMBuild.target['platform'] == 'windows':
    2.39 +			libPath = os.path.join(AMBuild.cache[sdk['sdk']], 'lib', 'win32', 'release', 'vs2010', 'libprotobuf.lib')
    2.40 +			binary.RebuildIfNewer(libPath)
    2.41 +			binary['POSTLINKFLAGS'].append(libPath)
    2.42 +
    2.43  	files = [
    2.44  		'AdminCache.cpp',
    2.45  		'ExtensionSys.cpp',
    2.46 @@ -49,7 +76,6 @@
    2.47  		'CoreConfig.cpp',
    2.48  		'Logger.cpp',
    2.49  		'PluginInfoDatabase.cpp',
    2.50 -		'smn_bitbuffer.cpp',
    2.51  		'smn_halflife.cpp',
    2.52  		'PluginSys.cpp',
    2.53  		'smn_console.cpp',
    2.54 @@ -71,7 +97,22 @@
    2.55  		'sm_srvcmds.cpp',
    2.56  		'ConsoleDetours.cpp'
    2.57  		]
    2.58 +	
    2.59 +	if i == 'csgo':
    2.60 +		files.append('smn_protobuf.cpp')
    2.61 +	else:
    2.62 +		files.append('smn_bitbuffer.cpp')
    2.63 +
    2.64  	binary.AddSourceFiles('core', files)
    2.65 +
    2.66 +	if i == 'csgo':
    2.67 +		files = [
    2.68 +			os.path.join('public', 'engine', 'protobuf', 'netmessages.pb.cc'),
    2.69 +			os.path.join('public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
    2.70 +			os.path.join('public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
    2.71 +			]
    2.72 +		binary.AddSourceFiles(AMBuild.cache[sdk['sdk']], files)
    2.73 +
    2.74  	SM.PostSetupHL2Job(extension, binary, i)
    2.75  	SM.AutoVersion('core', binary)
    2.76  	binary.SendToJob()
     3.1 --- a/core/HalfLife2.cpp	Mon Jan 07 09:09:14 2013 -0500
     3.2 +++ b/core/HalfLife2.cpp	Tue Jan 22 21:43:12 2013 -0500
     3.3 @@ -42,6 +42,10 @@
     3.4  #include "logic_bridge.h"
     3.5  #include <tier0/mem.h>
     3.6  
     3.7 +#if SOURCE_ENGINE == SE_CSGO
     3.8 +#include <cstrike15_usermessages.pb.h>
     3.9 +#endif
    3.10 +
    3.11  
    3.12  typedef ICommandLine *(*FakeGetCommandLine)();
    3.13  
    3.14 @@ -487,7 +491,9 @@
    3.15  
    3.16  bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
    3.17  {
    3.18 +#if SOURCE_ENGINE != SE_CSGO
    3.19  	bf_write *pBitBuf = NULL;
    3.20 +#endif
    3.21  	cell_t players[] = {client};
    3.22  
    3.23  	if (dest == HUD_PRINTTALK)
    3.24 @@ -500,7 +506,18 @@
    3.25  			char buffer[192];
    3.26  			UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg);
    3.27  
    3.28 -			if ((pBitBuf = g_UserMsgs.StartMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
    3.29 +#if SOURCE_ENGINE == SE_CSGO
    3.30 +			CCSUsrMsg_SayText *pMsg;
    3.31 +			if ((pMsg = (CCSUsrMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
    3.32 +			{
    3.33 +				return false;
    3.34 +			}
    3.35 +
    3.36 +			pMsg->set_ent_idx(0);
    3.37 +			pMsg->set_text(buffer);
    3.38 +			pMsg->set_chat(false);
    3.39 +#else
    3.40 +			if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
    3.41  			{
    3.42  				return false;
    3.43  			}
    3.44 @@ -508,6 +525,7 @@
    3.45  			pBitBuf->WriteByte(0);
    3.46  			pBitBuf->WriteString(buffer);
    3.47  			pBitBuf->WriteByte(1);
    3.48 +#endif
    3.49  
    3.50  			g_UserMsgs.EndMessage();
    3.51  
    3.52 @@ -515,13 +533,29 @@
    3.53  		}
    3.54  	}
    3.55  
    3.56 -	if ((pBitBuf = g_UserMsgs.StartMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
    3.57 +#if SOURCE_ENGINE == SE_CSGO
    3.58 +	CCSUsrMsg_TextMsg *pMsg;
    3.59 +	if ((pMsg = (CCSUsrMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
    3.60 +	{
    3.61 +		return false;
    3.62 +	}
    3.63 +
    3.64 +	// Client tries to read all 5 'params' and will crash if less
    3.65 +	pMsg->set_msg_dst(dest);
    3.66 +	pMsg->add_params(msg);
    3.67 +	pMsg->add_params("");
    3.68 +	pMsg->add_params("");
    3.69 +	pMsg->add_params("");
    3.70 +	pMsg->add_params("");
    3.71 +#else
    3.72 +	if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
    3.73  	{
    3.74  		return false;
    3.75  	}
    3.76  
    3.77  	pBitBuf->WriteByte(dest);
    3.78  	pBitBuf->WriteString(msg);
    3.79 +#endif
    3.80  
    3.81  	g_UserMsgs.EndMessage();
    3.82  
    3.83 @@ -530,10 +564,20 @@
    3.84  
    3.85  bool CHalfLife2::HintTextMsg(int client, const char *msg)
    3.86  {
    3.87 -	bf_write *pBitBuf = NULL;
    3.88  	cell_t players[] = {client};
    3.89  
    3.90 -	if ((pBitBuf = g_UserMsgs.StartMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
    3.91 +#if SOURCE_ENGINE == SE_CSGO
    3.92 +	CCSUsrMsg_HintText *pMsg;
    3.93 +	if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
    3.94 +	{
    3.95 +		return false;
    3.96 +	}
    3.97 +
    3.98 +	pMsg->set_text(msg);
    3.99 +#else
   3.100 +	bf_write *pBitBuf = NULL;
   3.101 +
   3.102 +	if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
   3.103  	{
   3.104  		return false;
   3.105  	}
   3.106 @@ -544,6 +588,7 @@
   3.107  		pBitBuf->WriteByte(1);
   3.108  	}
   3.109  	pBitBuf->WriteString(msg);
   3.110 +#endif
   3.111  	g_UserMsgs.EndMessage();
   3.112  
   3.113  	return true;
   3.114 @@ -551,9 +596,18 @@
   3.115  
   3.116  bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
   3.117  {
   3.118 +#if SOURCE_ENGINE == SE_CSGO
   3.119 +	CCSUsrMsg_HintText *pMsg;
   3.120 +	if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
   3.121 +	{
   3.122 +		return false;
   3.123 +	}
   3.124 +
   3.125 +	pMsg->set_text(msg);
   3.126 +#else
   3.127  	bf_write *pBitBuf = NULL;
   3.128  
   3.129 -	if ((pBitBuf = g_UserMsgs.StartMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
   3.130 +	if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
   3.131  	{
   3.132  		return false;
   3.133  	}
   3.134 @@ -564,6 +618,8 @@
   3.135  		pBitBuf->WriteByte(1);
   3.136  	}
   3.137  	pBitBuf->WriteString(msg);
   3.138 +#endif
   3.139 +
   3.140  	g_UserMsgs.EndMessage();
   3.141  
   3.142  	return true;
   3.143 @@ -571,15 +627,23 @@
   3.144  
   3.145  bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show)
   3.146  {
   3.147 -	bf_write *pBitBuf = NULL;
   3.148  	KeyValues *SubKey = NULL;
   3.149  	int count = 0;
   3.150  	cell_t players[] = {client};
   3.151  
   3.152 -	if ((pBitBuf = g_UserMsgs.StartMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
   3.153 +#if SOURCE_ENGINE == SE_CSGO
   3.154 +	CCSUsrMsg_VGUIMenu *pMsg;
   3.155 +	if ((pMsg = (CCSUsrMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
   3.156  	{
   3.157  		return false;
   3.158  	}
   3.159 +#else
   3.160 +	bf_write *pBitBuf = NULL;
   3.161 +	if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
   3.162 +	{
   3.163 +		return false;
   3.164 +	}
   3.165 +#endif
   3.166  
   3.167  	if (data)
   3.168  	{
   3.169 @@ -592,6 +656,18 @@
   3.170  		SubKey = data->GetFirstSubKey();
   3.171  	}
   3.172  
   3.173 +#if SOURCE_ENGINE == SE_CSGO
   3.174 +	pMsg->set_name(name);
   3.175 +	pMsg->set_show(show);
   3.176 +
   3.177 +	while (SubKey)
   3.178 +	{
   3.179 +		CCSUsrMsg_VGUIMenu_Subkey *key = pMsg->add_subkeys();
   3.180 +		key->set_name(SubKey->GetName());
   3.181 +		key->set_str(SubKey->GetString());
   3.182 +		SubKey = SubKey->GetNextKey();
   3.183 +	}
   3.184 +#else
   3.185  	pBitBuf->WriteString(name);
   3.186  	pBitBuf->WriteByte((show) ? 1 : 0);
   3.187  	pBitBuf->WriteByte(count);
   3.188 @@ -601,6 +677,8 @@
   3.189  		pBitBuf->WriteString(SubKey->GetString());
   3.190  		SubKey = SubKey->GetNextKey();
   3.191  	}
   3.192 +#endif
   3.193 +
   3.194  	g_UserMsgs.EndMessage();
   3.195  
   3.196  	return true;
     4.1 --- a/core/MenuStyle_Radio.cpp	Mon Jan 07 09:09:14 2013 -0500
     4.2 +++ b/core/MenuStyle_Radio.cpp	Tue Jan 22 21:43:12 2013 -0500
     4.3 @@ -39,6 +39,14 @@
     4.4  #endif
     4.5  #include "logic_bridge.h"
     4.6  
     4.7 +#ifdef USE_PROTOBUF_USERMESSAGES
     4.8 +#include <google/protobuf/descriptor.h>
     4.9 +#endif
    4.10 +
    4.11 +#if SOURCE_ENGINE == SE_CSGO
    4.12 +#include <game/shared/csgo/protobuf/cstrike15_usermessages.pb.h>
    4.13 +#endif
    4.14 +
    4.15  extern const char *g_RadioNumTable[];
    4.16  CRadioStyle g_RadioMenuStyle;
    4.17  int g_ShowMenuId = -1;
    4.18 @@ -155,13 +163,22 @@
    4.19  static unsigned int g_last_client_count = 0;
    4.20  static int g_last_clients[256];
    4.21  
    4.22 +#ifdef USE_PROTOBUF_USERMESSAGES
    4.23 +void CRadioStyle::OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter)
    4.24 +#else
    4.25  void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
    4.26 +#endif
    4.27  {
    4.28  	int count = pFilter->GetRecipientCount();
    4.29 +
    4.30 +#ifdef USE_PROTOBUF_USERMESSAGES
    4.31 +	int c = ((CCSUsrMsg_ShowMenu &)msg).display_time();
    4.32 +#else
    4.33  	bf_read br(bf->GetBasePointer(), 3);
    4.34  
    4.35  	br.ReadWord();
    4.36  	int c = br.ReadChar();
    4.37 +#endif
    4.38  
    4.39  	g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
    4.40  
    4.41 @@ -472,6 +489,15 @@
    4.42  		time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
    4.43  	}
    4.44  
    4.45 +#ifdef USE_PROTOBUF_USERMESSAGES
    4.46 +	// If or when we need to support multiple games per engine with this, we can switch to reflection
    4.47 +	// TODO: find what happens past 240 on CS:GO
    4.48 +	CCSUsrMsg_ShowMenu *msg = (CCSUsrMsg_ShowMenu *)g_UserMsgs.StartProtobufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
    4.49 +	msg->set_bits_valid_slots(display_keys);
    4.50 +	msg->set_display_time(time);
    4.51 +	msg->set_menu_string(ptr);
    4.52 +	g_UserMsgs.EndMessage();
    4.53 +#else
    4.54  	while (true)
    4.55  	{
    4.56  		if (len > 240)
    4.57 @@ -479,7 +505,8 @@
    4.58  			save = ptr[240];
    4.59  			ptr[240] = '\0';
    4.60  		}
    4.61 -		bf_write *buffer = g_UserMsgs.StartMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
    4.62 +
    4.63 +		bf_write *buffer = g_UserMsgs.StartBitBufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
    4.64  		buffer->WriteWord(display_keys);
    4.65  		buffer->WriteChar(time ? time : -1);
    4.66  		buffer->WriteByte( (len > 240) ? 1 : 0 );
    4.67 @@ -496,6 +523,7 @@
    4.68  			break;
    4.69  		}
    4.70  	}
    4.71 +#endif
    4.72  
    4.73  	display_last_refresh = gpGlobals->curtime;
    4.74  }
     5.1 --- a/core/MenuStyle_Radio.h	Mon Jan 07 09:09:14 2013 -0500
     5.2 +++ b/core/MenuStyle_Radio.h	Tue Jan 22 21:43:12 2013 -0500
     5.3 @@ -37,7 +37,7 @@
     5.4  #include "MenuStyle_Base.h"
     5.5  #include "sourcemm_api.h"
     5.6  #include <IPlayerHelpers.h>
     5.7 -#include <IUserMessages.h>
     5.8 +#include "UserMessages.h"
     5.9  #include "sm_fastlink.h"
    5.10  #include <sh_stack.h>
    5.11  #include <compat_wrappers.h>
    5.12 @@ -65,7 +65,11 @@
    5.13  class CRadioStyle : 
    5.14  	public BaseMenuStyle,
    5.15  	public SMGlobalClass,
    5.16 -	public IUserMessageListener
    5.17 +#ifdef USE_PROTOBUF_USERMESSAGES
    5.18 +	public IProtobufUserMessageListener
    5.19 +#else
    5.20 +	public IBitBufUserMessageListener
    5.21 +#endif
    5.22  {
    5.23  public:
    5.24  	CRadioStyle();
    5.25 @@ -84,7 +88,11 @@
    5.26  	unsigned int GetMaxPageItems();
    5.27  	unsigned int GetApproxMemUsage();
    5.28  public: //IUserMessageListener
    5.29 +#ifdef USE_PROTOBUF_USERMESSAGES
    5.30 +	void OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter);
    5.31 +#else
    5.32  	void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
    5.33 +#endif
    5.34  	void OnUserMessageSent(int msg_id);
    5.35  public:
    5.36  	bool IsSupported();
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/core/UserMessagePBHelpers.h	Tue Jan 22 21:43:12 2013 -0500
     6.3 @@ -0,0 +1,853 @@
     6.4 +/**
     6.5 + * vim: set ts=4 :
     6.6 + * =============================================================================
     6.7 + * SourceMod
     6.8 + * Copyright (C) 2013 AlliedModders LLC.  All rights reserved.
     6.9 + * =============================================================================
    6.10 + *
    6.11 + * This program is free software; you can redistribute it and/or modify it under
    6.12 + * the terms of the GNU General Public License, version 3.0, as published by the
    6.13 + * Free Software Foundation.
    6.14 + * 
    6.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
    6.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    6.17 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    6.18 + * details.
    6.19 + *
    6.20 + * You should have received a copy of the GNU General Public License along with
    6.21 + * this program.  If not, see <http://www.gnu.org/licenses/>.
    6.22 + *
    6.23 + * As a special exception, AlliedModders LLC gives you permission to link the
    6.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
    6.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    6.26 + * by the Valve Corporation.  You must obey the GNU General Public License in
    6.27 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
    6.28 + * this exception to all derivative works.  AlliedModders LLC defines further
    6.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    6.30 + * or <http://www.sourcemod.net/license.php>.
    6.31 + *
    6.32 + * Version: $Id$
    6.33 + */
    6.34 +
    6.35 +#ifndef _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_
    6.36 +#define _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_
    6.37 +
    6.38 +#include <sh_list.h>
    6.39 +#include <google/protobuf/descriptor.h>
    6.40 +
    6.41 +#define GETCHECK_FIELD() \
    6.42 +	const protobuf::FieldDescriptor *field = msg->GetDescriptor()->FindFieldByName(pszFieldName); \
    6.43 +	if (!field)       \
    6.44 +	{                 \
    6.45 +		return false; \
    6.46 +	}
    6.47 +
    6.48 +#define CHECK_FIELD_TYPE(type) \
    6.49 +	if (field->cpp_type() != protobuf::FieldDescriptor::CPPTYPE_##type) \
    6.50 +	{                 \
    6.51 +		return false; \
    6.52 +	}
    6.53 +
    6.54 +#define CHECK_FIELD_TYPE2(type1, type2) \
    6.55 +	protobuf::FieldDescriptor::CppType fieldType = field->cpp_type(); \
    6.56 +	if (fieldType != protobuf::FieldDescriptor::CPPTYPE_##type1       \
    6.57 +		&& fieldType != protobuf::FieldDescriptor::CPPTYPE_##type2) \
    6.58 +	{                 \
    6.59 +		return false; \
    6.60 +	}
    6.61 +
    6.62 +#define CHECK_FIELD_REPEATED() \
    6.63 +	if (field->label() != protobuf::FieldDescriptor::LABEL_REPEATED) \
    6.64 +	{                 \
    6.65 +		return false; \
    6.66 +	}
    6.67 +
    6.68 +#define CHECK_FIELD_NOT_REPEATED() \
    6.69 +	if (field->label() == protobuf::FieldDescriptor::LABEL_REPEATED) \
    6.70 +	{                 \
    6.71 +		return false; \
    6.72 +	}
    6.73 +
    6.74 +#define CHECK_REPEATED_ELEMENT(idx) \
    6.75 +	int elemCount = msg->GetReflection()->FieldSize(*msg, field); \
    6.76 +	if (elemCount == 0 || idx >= elemCount || idx <= 0)       \
    6.77 +	{                                                         \
    6.78 +		return false;                                         \
    6.79 +	}
    6.80 +
    6.81 +typedef List<Handle_t> PBHandleList;
    6.82 +
    6.83 +class SMProtobufMessage
    6.84 +{
    6.85 +public:
    6.86 +	SMProtobufMessage( protobuf::Message *message )
    6.87 +	{
    6.88 +		msg = message;
    6.89 +	}
    6.90 +
    6.91 +	~SMProtobufMessage()
    6.92 +	{
    6.93 +		PBHandleList::iterator iter = childHandles.begin();
    6.94 +		while (iter != childHandles.end())
    6.95 +		{
    6.96 +			Handle_t &hndl = (*iter);
    6.97 +			HandleSecurity sec;
    6.98 +			sec.pIdentity = g_pCoreIdent;
    6.99 +			g_HandleSys.FreeHandle(hndl, &sec);
   6.100 +			iter = childHandles.erase(iter);
   6.101 +		}
   6.102 +	}
   6.103 +
   6.104 +	inline void AddChildHandle(Handle_t hndl)
   6.105 +	{
   6.106 +		childHandles.push_back(hndl);
   6.107 +	}
   6.108 +
   6.109 +	inline protobuf::Message *GetProtobufMessage()
   6.110 +	{
   6.111 +		return msg;
   6.112 +	}
   6.113 +
   6.114 +	inline bool GetInt32(const char *pszFieldName, int32 *out)
   6.115 +	{
   6.116 +		GETCHECK_FIELD();
   6.117 +		CHECK_FIELD_TYPE(INT32);
   6.118 +		CHECK_FIELD_NOT_REPEATED();
   6.119 +
   6.120 +		*out = msg->GetReflection()->GetInt32(*msg, field);
   6.121 +		return true;	
   6.122 +	}
   6.123 +
   6.124 +	inline bool SetInt32(const char *pszFieldName, int32 value)
   6.125 +	{
   6.126 +		GETCHECK_FIELD();
   6.127 +		CHECK_FIELD_TYPE(INT32);
   6.128 +		CHECK_FIELD_NOT_REPEATED();
   6.129 +
   6.130 +		msg->GetReflection()->SetInt32(msg, field, value);
   6.131 +		return true;
   6.132 +	}
   6.133 +
   6.134 +	inline bool GetRepeatedInt32(const char *pszFieldName, int index, int32 *out)
   6.135 +	{
   6.136 +		GETCHECK_FIELD();
   6.137 +		CHECK_FIELD_TYPE(INT32);
   6.138 +		CHECK_FIELD_REPEATED();
   6.139 +		CHECK_REPEATED_ELEMENT(index);
   6.140 +		
   6.141 +		*out = msg->GetReflection()->GetRepeatedInt32(*msg, field, index);
   6.142 +		return true;
   6.143 +	}
   6.144 +
   6.145 +	inline bool AddInt32(const char *pszFieldName, int32 value)
   6.146 +	{
   6.147 +		GETCHECK_FIELD();
   6.148 +		CHECK_FIELD_TYPE(INT32);
   6.149 +		CHECK_FIELD_REPEATED();
   6.150 +
   6.151 +		msg->GetReflection()->AddInt32(msg, field, value);
   6.152 +		return true;
   6.153 +	}
   6.154 +
   6.155 +	inline bool GetInt64(const char *pszFieldName, int64 *out)
   6.156 +	{
   6.157 +		GETCHECK_FIELD();
   6.158 +		CHECK_FIELD_TYPE(INT64);
   6.159 +		CHECK_FIELD_NOT_REPEATED();
   6.160 +
   6.161 +		*out = msg->GetReflection()->GetInt64(*msg, field);
   6.162 +		return true;	
   6.163 +	}
   6.164 +
   6.165 +	inline bool SetInt64(const char *pszFieldName, int64 value)
   6.166 +	{
   6.167 +		GETCHECK_FIELD();
   6.168 +		CHECK_FIELD_TYPE(INT64);
   6.169 +		CHECK_FIELD_NOT_REPEATED();
   6.170 +
   6.171 +		msg->GetReflection()->SetInt64(msg, field, value);
   6.172 +		return true;
   6.173 +	}
   6.174 +
   6.175 +	inline bool GetRepeatedInt64(const char *pszFieldName, int index, int64 *out)
   6.176 +	{
   6.177 +		GETCHECK_FIELD();
   6.178 +		CHECK_FIELD_TYPE(INT64);
   6.179 +		CHECK_FIELD_REPEATED();
   6.180 +		CHECK_REPEATED_ELEMENT(index);
   6.181 +		
   6.182 +		*out = msg->GetReflection()->GetRepeatedInt64(*msg, field, index);
   6.183 +		return true;
   6.184 +	}
   6.185 +
   6.186 +	inline bool AddInt64(const char *pszFieldName, int64 value)
   6.187 +	{
   6.188 +		GETCHECK_FIELD();
   6.189 +		CHECK_FIELD_TYPE(INT64);
   6.190 +		CHECK_FIELD_REPEATED();
   6.191 +
   6.192 +		msg->GetReflection()->AddInt64(msg, field, value);
   6.193 +		return true;
   6.194 +	}
   6.195 +
   6.196 +	inline bool GetUInt32(const char *pszFieldName, uint32 *out)
   6.197 +	{
   6.198 +		GETCHECK_FIELD();
   6.199 +		CHECK_FIELD_TYPE(UINT32);
   6.200 +		CHECK_FIELD_NOT_REPEATED();
   6.201 +
   6.202 +		*out = msg->GetReflection()->GetUInt32(*msg, field);
   6.203 +		return true;	
   6.204 +	}
   6.205 +
   6.206 +	inline bool SetUInt32(const char *pszFieldName, uint32 value)
   6.207 +	{
   6.208 +		GETCHECK_FIELD();
   6.209 +		CHECK_FIELD_TYPE(UINT32);
   6.210 +		CHECK_FIELD_NOT_REPEATED();
   6.211 +
   6.212 +		msg->GetReflection()->SetUInt32(msg, field, value);
   6.213 +		return true;
   6.214 +	}
   6.215 +
   6.216 +	inline bool GetRepeatedUInt32(const char *pszFieldName, int index, uint32 *out)
   6.217 +	{
   6.218 +		GETCHECK_FIELD();
   6.219 +		CHECK_FIELD_TYPE(UINT32);
   6.220 +		CHECK_FIELD_REPEATED();
   6.221 +		CHECK_REPEATED_ELEMENT(index);
   6.222 +		
   6.223 +		*out = msg->GetReflection()->GetRepeatedUInt32(*msg, field, index);
   6.224 +		return true;
   6.225 +	}
   6.226 +
   6.227 +	inline bool AddUInt32(const char *pszFieldName, uint32 value)
   6.228 +	{
   6.229 +		GETCHECK_FIELD();
   6.230 +		CHECK_FIELD_TYPE(UINT32);
   6.231 +		CHECK_FIELD_REPEATED();
   6.232 +
   6.233 +		msg->GetReflection()->AddUInt32(msg, field, value);
   6.234 +		return true;
   6.235 +	}
   6.236 +
   6.237 +	inline bool GetUInt64(const char *pszFieldName, uint64 *out)
   6.238 +	{
   6.239 +		GETCHECK_FIELD();
   6.240 +		CHECK_FIELD_TYPE(UINT64);
   6.241 +		CHECK_FIELD_NOT_REPEATED();
   6.242 +
   6.243 +		*out = msg->GetReflection()->GetUInt64(*msg, field);
   6.244 +		return true;	
   6.245 +	}
   6.246 +
   6.247 +	inline bool SetUInt64(const char *pszFieldName, uint64 value)
   6.248 +	{
   6.249 +		GETCHECK_FIELD();
   6.250 +		CHECK_FIELD_TYPE(UINT64);
   6.251 +		CHECK_FIELD_NOT_REPEATED();
   6.252 +
   6.253 +		msg->GetReflection()->SetUInt64(msg, field, value);
   6.254 +		return true;
   6.255 +	}
   6.256 +
   6.257 +	inline bool GetRepeatedUInt64(const char *pszFieldName, int index, uint64 *out)
   6.258 +	{
   6.259 +		GETCHECK_FIELD();
   6.260 +		CHECK_FIELD_TYPE(UINT64);
   6.261 +		CHECK_FIELD_REPEATED();
   6.262 +		CHECK_REPEATED_ELEMENT(index);
   6.263 +		
   6.264 +		*out = msg->GetReflection()->GetRepeatedUInt64(*msg, field, index);
   6.265 +		return true;
   6.266 +	}
   6.267 +
   6.268 +	inline bool AddUInt64(const char *pszFieldName, uint64 value)
   6.269 +	{
   6.270 +		GETCHECK_FIELD();
   6.271 +		CHECK_FIELD_TYPE(UINT64);
   6.272 +		CHECK_FIELD_REPEATED();
   6.273 +
   6.274 +		msg->GetReflection()->AddUInt32(msg, field, value);
   6.275 +		return true;
   6.276 +	}
   6.277 +
   6.278 +	inline bool GetInt32OrUnsigned(const char *pszFieldName, int32 *out)
   6.279 +	{
   6.280 +		GETCHECK_FIELD();
   6.281 +		CHECK_FIELD_TYPE2(INT32, UINT32);
   6.282 +		CHECK_FIELD_NOT_REPEATED();
   6.283 +
   6.284 +		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
   6.285 +			*out = (int32)msg->GetReflection()->GetUInt32(*msg, field);
   6.286 +		else
   6.287 +			*out = msg->GetReflection()->GetInt32(*msg, field);
   6.288 +
   6.289 +		return true;	
   6.290 +	}
   6.291 +
   6.292 +	inline bool SetInt32OrUnsigned(const char *pszFieldName, int32 value)
   6.293 +	{
   6.294 +		GETCHECK_FIELD();
   6.295 +		CHECK_FIELD_TYPE2(INT32, UINT32);
   6.296 +		CHECK_FIELD_NOT_REPEATED();
   6.297 +
   6.298 +		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
   6.299 +			msg->GetReflection()->SetUInt32(msg, field, (uint32)value);
   6.300 +		else
   6.301 +			msg->GetReflection()->SetInt32(msg, field, value);
   6.302 +
   6.303 +		return true;
   6.304 +	}
   6.305 +
   6.306 +	inline bool GetRepeatedInt32OrUnsigned(const char *pszFieldName, int index, int32 *out)
   6.307 +	{
   6.308 +		GETCHECK_FIELD();
   6.309 +		CHECK_FIELD_TYPE2(INT32, UINT32);
   6.310 +		CHECK_FIELD_REPEATED();
   6.311 +		CHECK_REPEATED_ELEMENT(index);
   6.312 +		
   6.313 +		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
   6.314 +			*out = (int32)msg->GetReflection()->GetRepeatedUInt32(*msg, field, index);
   6.315 +		else
   6.316 +			*out = msg->GetReflection()->GetRepeatedInt32(*msg, field, index);
   6.317 +
   6.318 +		return true;
   6.319 +	}
   6.320 +
   6.321 +	inline bool AddInt32OrUnsigned(const char *pszFieldName, int32 value)
   6.322 +	{
   6.323 +		GETCHECK_FIELD();
   6.324 +		CHECK_FIELD_TYPE2(INT32, UINT32);
   6.325 +		CHECK_FIELD_REPEATED();
   6.326 +
   6.327 +		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
   6.328 +			msg->GetReflection()->AddUInt32(msg, field, (uint32)value);
   6.329 +		else
   6.330 +			msg->GetReflection()->AddInt32(msg, field, value);
   6.331 +
   6.332 +		return true;
   6.333 +	}
   6.334 +
   6.335 +	inline bool GetBool(const char *pszFieldName, bool *out)
   6.336 +	{
   6.337 +		GETCHECK_FIELD();
   6.338 +		CHECK_FIELD_TYPE(BOOL);
   6.339 +		CHECK_FIELD_NOT_REPEATED();
   6.340 +
   6.341 +		*out = msg->GetReflection()->GetBool(*msg, field);
   6.342 +		return true;	
   6.343 +	}
   6.344 +
   6.345 +	inline bool SetBool(const char *pszFieldName, bool value)
   6.346 +	{
   6.347 +		GETCHECK_FIELD();
   6.348 +		CHECK_FIELD_TYPE(BOOL);
   6.349 +		CHECK_FIELD_NOT_REPEATED();
   6.350 +
   6.351 +		msg->GetReflection()->SetBool(msg, field, value);
   6.352 +		return true;
   6.353 +	}
   6.354 +
   6.355 +	inline bool GetRepeatedBool(const char *pszFieldName, int index, bool *out)
   6.356 +	{
   6.357 +		GETCHECK_FIELD();
   6.358 +		CHECK_FIELD_TYPE(BOOL);
   6.359 +		CHECK_FIELD_REPEATED();
   6.360 +		CHECK_REPEATED_ELEMENT(index);
   6.361 +		
   6.362 +		*out = msg->GetReflection()->GetRepeatedBool(*msg, field, index);
   6.363 +		return true;
   6.364 +	}
   6.365 +
   6.366 +	inline bool AddBool(const char *pszFieldName, bool value)
   6.367 +	{
   6.368 +		GETCHECK_FIELD();
   6.369 +		CHECK_FIELD_TYPE(BOOL);
   6.370 +		CHECK_FIELD_REPEATED();
   6.371 +
   6.372 +		msg->GetReflection()->AddBool(msg, field, value);
   6.373 +		return true;
   6.374 +	}
   6.375 +
   6.376 +	inline bool GetFloat(const char *pszFieldName, float *out)
   6.377 +	{
   6.378 +		GETCHECK_FIELD();
   6.379 +		CHECK_FIELD_TYPE(FLOAT);
   6.380 +		CHECK_FIELD_NOT_REPEATED();
   6.381 +
   6.382 +		*out = msg->GetReflection()->GetFloat(*msg, field);
   6.383 +		return true;	
   6.384 +	}
   6.385 +
   6.386 +	inline bool SetFloat(const char *pszFieldName, float value)
   6.387 +	{
   6.388 +		GETCHECK_FIELD();
   6.389 +		CHECK_FIELD_TYPE(FLOAT);
   6.390 +		CHECK_FIELD_NOT_REPEATED();
   6.391 +
   6.392 +		msg->GetReflection()->SetFloat(msg, field, value);
   6.393 +		return true;
   6.394 +	}
   6.395 +
   6.396 +	inline bool GetRepeatedFloat(const char *pszFieldName, int index, float *out)
   6.397 +	{
   6.398 +		GETCHECK_FIELD();
   6.399 +		CHECK_FIELD_TYPE(FLOAT);
   6.400 +		CHECK_FIELD_REPEATED();
   6.401 +		CHECK_REPEATED_ELEMENT(index);
   6.402 +		
   6.403 +		*out = msg->GetReflection()->GetRepeatedFloat(*msg, field, index);
   6.404 +		return true;
   6.405 +	}
   6.406 +
   6.407 +	inline bool AddFloat(const char *pszFieldName, float value)
   6.408 +	{
   6.409 +		GETCHECK_FIELD();
   6.410 +		CHECK_FIELD_TYPE(FLOAT);
   6.411 +		CHECK_FIELD_REPEATED();
   6.412 +
   6.413 +		msg->GetReflection()->AddFloat(msg, field, value);
   6.414 +		return true;
   6.415 +	}
   6.416 +
   6.417 +	inline bool GetDouble(const char *pszFieldName, double *out)
   6.418 +	{
   6.419 +		GETCHECK_FIELD();
   6.420 +		CHECK_FIELD_TYPE(DOUBLE);
   6.421 +		CHECK_FIELD_NOT_REPEATED();
   6.422 +
   6.423 +		*out = msg->GetReflection()->GetDouble(*msg, field);
   6.424 +		return true;	
   6.425 +	}
   6.426 +
   6.427 +	inline bool SetDouble(const char *pszFieldName, double value)
   6.428 +	{
   6.429 +		GETCHECK_FIELD();
   6.430 +		CHECK_FIELD_TYPE(DOUBLE);
   6.431 +		CHECK_FIELD_NOT_REPEATED();
   6.432 +
   6.433 +		msg->GetReflection()->SetDouble(msg, field, value);
   6.434 +		return true;
   6.435 +	}
   6.436 +
   6.437 +	inline bool GetRepeatedDouble(const char *pszFieldName, int index, double *out)
   6.438 +	{
   6.439 +		GETCHECK_FIELD();
   6.440 +		CHECK_FIELD_TYPE(DOUBLE);
   6.441 +		CHECK_FIELD_REPEATED();
   6.442 +		CHECK_REPEATED_ELEMENT(index);
   6.443 +		
   6.444 +		*out = msg->GetReflection()->GetRepeatedDouble(*msg, field, index);
   6.445 +		return true;
   6.446 +	}
   6.447 +
   6.448 +	inline bool AddDouble(const char *pszFieldName, double value)
   6.449 +	{
   6.450 +		GETCHECK_FIELD();
   6.451 +		CHECK_FIELD_TYPE(DOUBLE);
   6.452 +		CHECK_FIELD_REPEATED();
   6.453 +
   6.454 +		msg->GetReflection()->AddDouble(msg, field, value);
   6.455 +		return true;
   6.456 +	}
   6.457 +
   6.458 +	inline bool GetFloatOrDouble(const char *pszFieldName, float *out)
   6.459 +	{
   6.460 +		GETCHECK_FIELD();
   6.461 +		CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
   6.462 +		CHECK_FIELD_NOT_REPEATED();
   6.463 +
   6.464 +		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
   6.465 +			*out = (float)msg->GetReflection()->GetDouble(*msg, field);
   6.466 +		else
   6.467 +			*out = msg->GetReflection()->GetFloat(*msg, field);
   6.468 +
   6.469 +		return true;	
   6.470 +	}
   6.471 +
   6.472 +	inline bool SetFloatOrDouble(const char *pszFieldName, float value)
   6.473 +	{
   6.474 +		GETCHECK_FIELD();
   6.475 +		CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
   6.476 +		CHECK_FIELD_NOT_REPEATED();
   6.477 +
   6.478 +		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
   6.479 +			msg->GetReflection()->SetDouble(msg, field, (double)value);
   6.480 +		else
   6.481 +			msg->GetReflection()->SetFloat(msg, field, value);
   6.482 +
   6.483 +		return true;
   6.484 +	}
   6.485 +
   6.486 +	inline bool GetRepeatedFloatOrDouble(const char *pszFieldName, int index, float *out)
   6.487 +	{
   6.488 +		GETCHECK_FIELD();
   6.489 +		CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
   6.490 +		CHECK_FIELD_REPEATED();
   6.491 +		CHECK_REPEATED_ELEMENT(index);
   6.492 +		
   6.493 +		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
   6.494 +			*out = (float)msg->GetReflection()->GetRepeatedDouble(*msg, field, index);
   6.495 +		else
   6.496 +			*out = msg->GetReflection()->GetRepeatedFloat(*msg, field, index);
   6.497 +
   6.498 +		return true;
   6.499 +	}
   6.500 +
   6.501 +	inline bool AddFloatOrDouble(const char *pszFieldName, float value)
   6.502 +	{
   6.503 +		GETCHECK_FIELD();
   6.504 +		CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
   6.505 +		CHECK_FIELD_REPEATED();
   6.506 +
   6.507 +		if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
   6.508 +			msg->GetReflection()->AddDouble(msg, field, (double)value);
   6.509 +		else
   6.510 +			msg->GetReflection()->AddFloat(msg, field, value);
   6.511 +
   6.512 +		return true;
   6.513 +	}
   6.514 +
   6.515 +	inline bool GetString(const char *pszFieldName, char *out, int size)
   6.516 +	{
   6.517 +		GETCHECK_FIELD();
   6.518 +		CHECK_FIELD_TYPE(STRING);
   6.519 +		CHECK_FIELD_NOT_REPEATED();
   6.520 +
   6.521 +		std::string scratch;
   6.522 +		strncopy(out, msg->GetReflection()->GetStringReference(*msg, field, &buffer).c_str(), size);
   6.523 +
   6.524 +		return true;	
   6.525 +	}
   6.526 +
   6.527 +	inline bool SetString(const char *pszFieldName, const char *value)
   6.528 +	{
   6.529 +		GETCHECK_FIELD();
   6.530 +		CHECK_FIELD_TYPE(STRING);
   6.531 +		CHECK_FIELD_NOT_REPEATED();
   6.532 +
   6.533 +		msg->GetReflection()->SetString(msg, field, value);
   6.534 +		return true;
   6.535 +	}
   6.536 +
   6.537 +	inline bool GetRepeatedString(const char *pszFieldName, int index, char *out, int size)
   6.538 +	{
   6.539 +		GETCHECK_FIELD();
   6.540 +		CHECK_FIELD_TYPE(STRING);
   6.541 +		CHECK_FIELD_REPEATED();
   6.542 +		CHECK_REPEATED_ELEMENT(index);
   6.543 +		
   6.544 +		std::string scratch;
   6.545 +		strncopy(out, msg->GetReflection()->GetRepeatedStringReference(*msg, field, index, &scratch).c_str(), size);
   6.546 +
   6.547 +		return true;
   6.548 +	}
   6.549 +
   6.550 +	inline bool AddString(const char *pszFieldName, const char *value)
   6.551 +	{
   6.552 +		GETCHECK_FIELD();
   6.553 +		CHECK_FIELD_TYPE(STRING);
   6.554 +		CHECK_FIELD_REPEATED();
   6.555 +
   6.556 +		msg->GetReflection()->AddString(msg, field, value);
   6.557 +		return true;
   6.558 +	}
   6.559 +
   6.560 +	inline bool GetColor(const char *pszFieldName, Color *out)
   6.561 +	{
   6.562 +		GETCHECK_FIELD();
   6.563 +		CHECK_FIELD_TYPE(MESSAGE);
   6.564 +		CHECK_FIELD_NOT_REPEATED();
   6.565 +
   6.566 +		const CMsgRGBA &msgRGBA = (const CMsgRGBA &)msg->GetReflection()->GetMessage(*msg, field);
   6.567 +		out->SetColor(
   6.568 +			msgRGBA.r(),
   6.569 +			msgRGBA.g(),
   6.570 +			msgRGBA.b(),
   6.571 +			msgRGBA.a()
   6.572 +			);
   6.573 +
   6.574 +		return true;
   6.575 +	}
   6.576 +
   6.577 +	inline bool SetColor(const char *pszFieldName, const Color &value)
   6.578 +	{
   6.579 +		GETCHECK_FIELD();
   6.580 +		CHECK_FIELD_TYPE(MESSAGE);
   6.581 +		CHECK_FIELD_NOT_REPEATED();
   6.582 +
   6.583 +		CMsgRGBA *msgRGBA = (CMsgRGBA *)msg->GetReflection()->MutableMessage(msg, field);
   6.584 +		msgRGBA->set_r(value.r());
   6.585 +		msgRGBA->set_g(value.g());
   6.586 +		msgRGBA->set_b(value.b());
   6.587 +		msgRGBA->set_a(value.a());
   6.588 +
   6.589 +		return true;
   6.590 +	}
   6.591 +
   6.592 +	inline bool GetRepeatedColor(const char *pszFieldName, int index, Color *out)
   6.593 +	{
   6.594 +		GETCHECK_FIELD();
   6.595 +		CHECK_FIELD_TYPE(MESSAGE);
   6.596 +		CHECK_FIELD_REPEATED();
   6.597 +		CHECK_REPEATED_ELEMENT(index);
   6.598 +
   6.599 +		const CMsgRGBA &msgRGBA = (const CMsgRGBA &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
   6.600 +		out->SetColor(
   6.601 +			msgRGBA.r(),
   6.602 +			msgRGBA.g(),
   6.603 +			msgRGBA.b(),
   6.604 +			msgRGBA.a()
   6.605 +			);
   6.606 +
   6.607 +		return true;
   6.608 +	}
   6.609 +
   6.610 +	inline bool AddColor(const char *pszFieldName, const Color &value)
   6.611 +	{
   6.612 +		GETCHECK_FIELD();
   6.613 +		CHECK_FIELD_TYPE(MESSAGE);
   6.614 +		CHECK_FIELD_REPEATED();
   6.615 +
   6.616 +		CMsgRGBA *msgRGBA = (CMsgRGBA *)msg->GetReflection()->AddMessage(msg, field);
   6.617 +		msgRGBA->set_r(value.r());
   6.618 +		msgRGBA->set_g(value.g());
   6.619 +		msgRGBA->set_b(value.b());
   6.620 +		msgRGBA->set_a(value.a());
   6.621 +
   6.622 +		return true;
   6.623 +	}
   6.624 +
   6.625 +	inline bool GetVector2D(const char *pszFieldName, Vector2D *out)
   6.626 +	{
   6.627 +		GETCHECK_FIELD();
   6.628 +		CHECK_FIELD_TYPE(MESSAGE);
   6.629 +		CHECK_FIELD_NOT_REPEATED();
   6.630 +
   6.631 +		const CMsgVector2D &msgVec2d = (const CMsgVector2D &)msg->GetReflection()->GetMessage(*msg, field);
   6.632 +		out->Init(
   6.633 +			msgVec2d.x(),
   6.634 +			msgVec2d.y()
   6.635 +			);
   6.636 +
   6.637 +		return true;
   6.638 +	}
   6.639 +
   6.640 +	inline bool SetVector2D(const char *pszFieldName, Vector2D &vec)
   6.641 +	{
   6.642 +		GETCHECK_FIELD();
   6.643 +		CHECK_FIELD_TYPE(MESSAGE);
   6.644 +		CHECK_FIELD_NOT_REPEATED();
   6.645 +
   6.646 +		CMsgVector2D *msgVec2d = (CMsgVector2D *)msg->GetReflection()->MutableMessage(msg, field);
   6.647 +		msgVec2d->set_x(vec.x);
   6.648 +		msgVec2d->set_y(vec.y);
   6.649 +
   6.650 +		return true;
   6.651 +	}
   6.652 +
   6.653 +	inline bool GetRepeatedVector2D(const char *pszFieldName, int index, Vector2D *out)
   6.654 +	{
   6.655 +		GETCHECK_FIELD();
   6.656 +		CHECK_FIELD_TYPE(MESSAGE);
   6.657 +		CHECK_FIELD_REPEATED();
   6.658 +		CHECK_REPEATED_ELEMENT(index);
   6.659 +
   6.660 +		const CMsgVector2D &msgVec2d = (const CMsgVector2D &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
   6.661 +		out->Init(
   6.662 +			msgVec2d.x(),
   6.663 +			msgVec2d.y()
   6.664 +			);
   6.665 +
   6.666 +		return true;
   6.667 +	}
   6.668 +
   6.669 +	inline bool AddVector2D(const char *pszFieldName, Vector2D &vec)
   6.670 +	{
   6.671 +		GETCHECK_FIELD();
   6.672 +		CHECK_FIELD_TYPE(MESSAGE);
   6.673 +		CHECK_FIELD_REPEATED();
   6.674 +
   6.675 +		CMsgVector2D *msgVec2d = (CMsgVector2D *)msg->GetReflection()->AddMessage(msg, field);
   6.676 +		msgVec2d->set_x(vec.x);
   6.677 +		msgVec2d->set_y(vec.y);
   6.678 +
   6.679 +		return true;
   6.680 +	}
   6.681 +
   6.682 +	inline bool GetVector(const char *pszFieldName, Vector *out)
   6.683 +	{
   6.684 +		GETCHECK_FIELD();
   6.685 +		CHECK_FIELD_TYPE(MESSAGE);
   6.686 +		CHECK_FIELD_NOT_REPEATED();
   6.687 +
   6.688 +		const CMsgVector &msgVec = (const CMsgVector &)msg->GetReflection()->GetMessage(*msg, field);
   6.689 +		out->Init(
   6.690 +			msgVec.x(),
   6.691 +			msgVec.y(),
   6.692 +			msgVec.z()
   6.693 +			);
   6.694 +
   6.695 +		return true;
   6.696 +	}
   6.697 +
   6.698 +	inline bool SetVector(const char *pszFieldName, Vector &vec)
   6.699 +	{
   6.700 +		GETCHECK_FIELD();
   6.701 +		CHECK_FIELD_TYPE(MESSAGE);
   6.702 +		CHECK_FIELD_NOT_REPEATED();
   6.703 +
   6.704 +		CMsgVector *msgVec = (CMsgVector *)msg->GetReflection()->MutableMessage(msg, field);
   6.705 +		msgVec->set_x(vec.x);
   6.706 +		msgVec->set_y(vec.y);
   6.707 +		msgVec->set_z(vec.z);
   6.708 +
   6.709 +		return true;
   6.710 +	}
   6.711 +
   6.712 +	inline bool GetRepeatedVector(const char *pszFieldName, int index, Vector *out)
   6.713 +	{
   6.714 +		GETCHECK_FIELD();
   6.715 +		CHECK_FIELD_TYPE(MESSAGE);
   6.716 +		CHECK_FIELD_REPEATED();
   6.717 +		CHECK_REPEATED_ELEMENT(index);
   6.718 +
   6.719 +		const CMsgVector &msgVec = (const CMsgVector &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
   6.720 +		out->Init(
   6.721 +			msgVec.x(),
   6.722 +			msgVec.y(),
   6.723 +			msgVec.z()
   6.724 +			);
   6.725 +
   6.726 +		return true;
   6.727 +	}
   6.728 +
   6.729 +	inline bool AddVector(const char *pszFieldName, Vector &vec)
   6.730 +	{
   6.731 +		GETCHECK_FIELD();
   6.732 +		CHECK_FIELD_TYPE(MESSAGE);
   6.733 +		CHECK_FIELD_REPEATED();
   6.734 +
   6.735 +		CMsgVector *msgVec = (CMsgVector *)msg->GetReflection()->AddMessage(msg, field);
   6.736 +		msgVec->set_x(vec.x);
   6.737 +		msgVec->set_y(vec.y);
   6.738 +		msgVec->set_z(vec.z);
   6.739 +
   6.740 +		return true;
   6.741 +	}
   6.742 +
   6.743 +	inline bool GetQAngle(const char *pszFieldName, QAngle *out)
   6.744 +	{
   6.745 +		GETCHECK_FIELD();
   6.746 +		CHECK_FIELD_TYPE(MESSAGE);
   6.747 +		CHECK_FIELD_NOT_REPEATED();
   6.748 +
   6.749 +		const CMsgQAngle &msgAng = (const CMsgQAngle &)msg->GetReflection()->GetMessage(*msg, field);
   6.750 +		out->Init(
   6.751 +			msgAng.x(),
   6.752 +			msgAng.y(),
   6.753 +			msgAng.z()
   6.754 +			);
   6.755 +
   6.756 +		return true;
   6.757 +	}
   6.758 +
   6.759 +	inline bool SetQAngle(const char *pszFieldName, QAngle &vec)
   6.760 +	{
   6.761 +		GETCHECK_FIELD();
   6.762 +		CHECK_FIELD_TYPE(MESSAGE);
   6.763 +		CHECK_FIELD_NOT_REPEATED();
   6.764 +
   6.765 +		CMsgQAngle *msgAng = (CMsgQAngle *)msg->GetReflection()->MutableMessage(msg, field);
   6.766 +		msgAng->set_x(vec.x);
   6.767 +		msgAng->set_y(vec.y);
   6.768 +		msgAng->set_z(vec.z);
   6.769 +
   6.770 +		return true;
   6.771 +	}
   6.772 +
   6.773 +	inline bool GetRepeatedQAngle(const char *pszFieldName, int index, QAngle *out)
   6.774 +	{
   6.775 +		GETCHECK_FIELD();
   6.776 +		CHECK_FIELD_TYPE(MESSAGE);
   6.777 +		CHECK_FIELD_REPEATED();
   6.778 +		CHECK_REPEATED_ELEMENT(index);
   6.779 +
   6.780 +		const CMsgQAngle &msgAng = (const CMsgQAngle &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
   6.781 +		out->Init(
   6.782 +			msgAng.x(),
   6.783 +			msgAng.y(),
   6.784 +			msgAng.z()
   6.785 +			);
   6.786 +
   6.787 +		return true;
   6.788 +	}
   6.789 +
   6.790 +	inline bool AddQAngle(const char *pszFieldName, QAngle &vec)
   6.791 +	{
   6.792 +		GETCHECK_FIELD();
   6.793 +		CHECK_FIELD_TYPE(MESSAGE);
   6.794 +		CHECK_FIELD_REPEATED();
   6.795 +
   6.796 +		CMsgQAngle *msgAng = (CMsgQAngle *)msg->GetReflection()->AddMessage(msg, field);
   6.797 +		msgAng->set_x(vec.x);
   6.798 +		msgAng->set_y(vec.y);
   6.799 +		msgAng->set_z(vec.z);
   6.800 +
   6.801 +		return true;
   6.802 +	}
   6.803 +
   6.804 +	inline bool GetMessage(const char *pszFieldName, protobuf::Message **message)
   6.805 +	{
   6.806 +		GETCHECK_FIELD();
   6.807 +		CHECK_FIELD_TYPE(MESSAGE);
   6.808 +		CHECK_FIELD_NOT_REPEATED();
   6.809 +
   6.810 +		*message = msg->GetReflection()->MutableMessage(msg, field);
   6.811 +
   6.812 +		return true;
   6.813 +	}
   6.814 +
   6.815 +	inline bool GetRepeatedMessage(const char *pszFieldName, int index, const protobuf::Message **message)
   6.816 +	{
   6.817 +		GETCHECK_FIELD();
   6.818 +		CHECK_FIELD_TYPE(MESSAGE);
   6.819 +		CHECK_FIELD_REPEATED();
   6.820 +		CHECK_REPEATED_ELEMENT(index);
   6.821 +
   6.822 +		const protobuf::Message *m = &msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
   6.823 +		*message = m;
   6.824 +
   6.825 +		return true;
   6.826 +	}
   6.827 +
   6.828 +	inline bool AddMessage(const char *pszFieldName, protobuf::Message **message)
   6.829 +	{
   6.830 +		GETCHECK_FIELD();
   6.831 +		CHECK_FIELD_TYPE(MESSAGE);
   6.832 +		CHECK_FIELD_REPEATED();
   6.833 +
   6.834 +		*message = msg->GetReflection()->AddMessage(msg, field);
   6.835 +
   6.836 +		return true;
   6.837 +	}
   6.838 +
   6.839 +	inline int GetRepeatedFieldCount(const char *pszFieldName)
   6.840 +	{
   6.841 +		const protobuf::FieldDescriptor *field = msg->GetDescriptor()->FindFieldByName(pszFieldName); \
   6.842 +		if (!field)
   6.843 +			return -1;
   6.844 +
   6.845 +		if (field->label() != protobuf::FieldDescriptor::LABEL_REPEATED)
   6.846 +			return -1;
   6.847 +
   6.848 +		return msg->GetReflection()->FieldSize(*msg, field);
   6.849 +	}
   6.850 +
   6.851 +private:
   6.852 +	protobuf::Message *msg;
   6.853 +	PBHandleList childHandles;
   6.854 +};
   6.855 +
   6.856 +#endif // _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_
     7.1 --- a/core/UserMessages.cpp	Mon Jan 07 09:09:14 2013 -0500
     7.2 +++ b/core/UserMessages.cpp	Tue Jan 22 21:43:12 2013 -0500
     7.3 @@ -32,18 +32,32 @@
     7.4  #include "UserMessages.h"
     7.5  #include "sm_stringutil.h"
     7.6  
     7.7 +#if SOURCE_ENGINE == SE_CSGO
     7.8 +#include <cstrike15_usermessage_helpers.h>
     7.9 +#endif
    7.10 +
    7.11  UserMessages g_UserMsgs;
    7.12  
    7.13 +#if SOURCE_ENGINE == SE_CSGO
    7.14 +SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
    7.15 +#else
    7.16  #if SOURCE_ENGINE >= SE_LEFT4DEAD
    7.17  SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *);
    7.18  #else
    7.19  SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
    7.20  #endif
    7.21  SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
    7.22 +#endif // ==SE_CSGO
    7.23  
    7.24 -UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
    7.25 +UserMessages::UserMessages()
    7.26 +#ifndef USE_PROTOBUF_USERMESSAGES
    7.27 +	: m_InterceptBuffer(m_pBase, 2500)
    7.28  {
    7.29  	m_Names = sm_trie_create();
    7.30 +#else
    7.31 +	: m_InterceptBuffer(NULL)
    7.32 +{
    7.33 +#endif
    7.34  	m_HookCount = 0;
    7.35  	m_InExec = false;
    7.36  	m_InHook = false;
    7.37 @@ -53,7 +67,9 @@
    7.38  
    7.39  UserMessages::~UserMessages()
    7.40  {
    7.41 +#ifndef USE_PROTOBUF_USERMESSAGES
    7.42  	sm_trie_destroy(m_Names);
    7.43 +#endif
    7.44  
    7.45  	CStack<ListenerInfo *>::iterator iter;
    7.46  	for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
    7.47 @@ -65,8 +81,10 @@
    7.48  
    7.49  void UserMessages::OnSourceModStartup(bool late)
    7.50  {
    7.51 +#ifndef USE_PROTOBUF_USERMESSAGES
    7.52  	/* -1 means SourceMM was unable to get the user message list */
    7.53  	m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
    7.54 +#endif
    7.55  }
    7.56  
    7.57  void UserMessages::OnSourceModAllInitialized()
    7.58 @@ -78,16 +96,25 @@
    7.59  {
    7.60  	if (m_HookCount)
    7.61  	{
    7.62 +#if SOURCE_ENGINE == SE_CSGO
    7.63 +		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
    7.64 +		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
    7.65 +#else
    7.66  		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
    7.67  		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
    7.68  		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
    7.69  		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
    7.70 +#endif
    7.71  	}
    7.72  	m_HookCount = 0;
    7.73  }
    7.74  
    7.75  int UserMessages::GetMessageIndex(const char *msg)
    7.76  {
    7.77 +#if SOURCE_ENGINE == SE_CSGO
    7.78 +	// Can split this per engine and/or game later
    7.79 +	return g_Cstrike15UsermessageHelpers.GetIndex(msg);
    7.80 +#else
    7.81  	int msgid;
    7.82  
    7.83  	if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid)))
    7.84 @@ -118,10 +145,19 @@
    7.85  	}
    7.86  
    7.87  	return msgid;
    7.88 +#endif
    7.89  }
    7.90  
    7.91  bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
    7.92  {
    7.93 +#if SOURCE_ENGINE == SE_CSGO
    7.94 +	const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
    7.95 +	if (!pszName)
    7.96 +		return false;
    7.97 +
    7.98 +	strncopy(buffer, pszName, maxlength);
    7.99 +	return true;
   7.100 +#else
   7.101  	if (m_FallbackSearch)
   7.102  	{
   7.103  		int size;
   7.104 @@ -137,10 +173,14 @@
   7.105  	}
   7.106  
   7.107  	return false;
   7.108 +#endif
   7.109  }
   7.110  
   7.111 -bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
   7.112 +bf_write *UserMessages::StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
   7.113  {
   7.114 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.115 +	return NULL;
   7.116 +#else
   7.117  	bf_write *buffer;
   7.118  
   7.119  	if (m_InExec || m_InHook)
   7.120 @@ -182,6 +222,68 @@
   7.121  	}
   7.122  
   7.123  	return buffer;
   7.124 +#endif // USE_PROTOBUF_USERMESSAGES
   7.125 +}
   7.126 +
   7.127 +google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
   7.128 +{
   7.129 +#ifndef USE_PROTOBUF_USERMESSAGES
   7.130 +	return NULL;
   7.131 +#else
   7.132 +	protobuf::Message *buffer;
   7.133 +
   7.134 +	if (m_InExec || m_InHook)
   7.135 +	{
   7.136 +		return NULL;
   7.137 +	}
   7.138 +	if (msg_id < 0 || msg_id >= 255)
   7.139 +	{
   7.140 +		return NULL;
   7.141 +	}
   7.142 +
   7.143 +	m_CurId = msg_id;
   7.144 +	m_CellRecFilter.Initialize(players, playersNum);
   7.145 +
   7.146 +	m_CurFlags = flags;
   7.147 +	if (m_CurFlags & USERMSG_INITMSG)
   7.148 +	{
   7.149 +		m_CellRecFilter.SetToInit(true);
   7.150 +	}
   7.151 +	if (m_CurFlags & USERMSG_RELIABLE)
   7.152 +	{
   7.153 +		m_CellRecFilter.SetToReliable(true);
   7.154 +	}
   7.155 +
   7.156 +	m_InExec = true;
   7.157 +
   7.158 +	if (m_CurFlags & USERMSG_BLOCKHOOKS)
   7.159 +	{
   7.160 +		// direct message creation, return buffer "from engine". keep track
   7.161 +		m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
   7.162 +		buffer = m_FakeEngineBuffer;
   7.163 +	} else {
   7.164 +		protobuf::Message *msg = OnStartMessage_Pre(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
   7.165 +		switch (m_FakeMetaRes)
   7.166 +		{
   7.167 +		case MRES_IGNORED:
   7.168 +		case MRES_HANDLED:
   7.169 +			m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
   7.170 +			buffer = m_FakeEngineBuffer;
   7.171 +			break;		
   7.172 +
   7.173 +		case MRES_OVERRIDE:
   7.174 +			m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
   7.175 +		// fallthrough
   7.176 +		case MRES_SUPERCEDE:
   7.177 +			buffer = msg;
   7.178 +			break;
   7.179 +		}
   7.180 +		
   7.181 +		OnStartMessage_Post(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
   7.182 +	}
   7.183 +
   7.184 +	return buffer;
   7.185 +#endif // USE_PROTOBUF_USERMESSAGES
   7.186  }
   7.187  
   7.188  bool UserMessages::EndMessage()
   7.189 @@ -191,12 +293,37 @@
   7.190  		return false;
   7.191  	}
   7.192  
   7.193 +#if SOURCE_ENGINE == SE_CSGO
   7.194 +	if (m_CurFlags & USERMSG_BLOCKHOOKS)
   7.195 +	{
   7.196 +		ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
   7.197 +		delete m_FakeEngineBuffer;
   7.198 +		m_FakeEngineBuffer = NULL;
   7.199 +	} else {
   7.200 +		OnMessageEnd_Pre();
   7.201 +
   7.202 +		switch (m_FakeMetaRes)
   7.203 +		{
   7.204 +		case MRES_IGNORED:
   7.205 +		case MRES_HANDLED:
   7.206 +		case MRES_OVERRIDE:
   7.207 +			engine->SendUserMessage(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
   7.208 +			delete m_FakeEngineBuffer;
   7.209 +			m_FakeEngineBuffer = NULL;
   7.210 +			break;
   7.211 +		//case MRES_SUPERCEDE:
   7.212 +		}
   7.213 +
   7.214 +		OnMessageEnd_Post();
   7.215 +	}
   7.216 +#else
   7.217  	if (m_CurFlags & USERMSG_BLOCKHOOKS)
   7.218  	{
   7.219  		ENGINE_CALL(MessageEnd)();
   7.220  	} else {
   7.221  		engine->MessageEnd();
   7.222  	}
   7.223 +#endif // SE_CSGO
   7.224  
   7.225  	m_InExec = false;
   7.226  	m_CurFlags = 0;
   7.227 @@ -205,31 +332,60 @@
   7.228  	return true;
   7.229  }
   7.230  
   7.231 +UserMessageType UserMessages::GetUserMessageType() const
   7.232 +{
   7.233 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.234 +	return UM_Protobuf;
   7.235 +#else
   7.236 +	return UM_BitBuf;
   7.237 +#endif
   7.238 +}
   7.239 +
   7.240  bool UserMessages::HookUserMessage2(int msg_id,
   7.241  									IUserMessageListener *pListener,
   7.242  									bool intercept)
   7.243  {
   7.244 -	return InternalHook(msg_id, pListener, intercept, true);
   7.245 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.246 +	return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
   7.247 +#else
   7.248 +	return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
   7.249 +#endif
   7.250  }
   7.251  
   7.252  bool UserMessages::UnhookUserMessage2(int msg_id,
   7.253  									  IUserMessageListener *pListener,
   7.254  									  bool intercept)
   7.255  {
   7.256 -	return InternalUnhook(msg_id, pListener, intercept, true);
   7.257 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.258 +	return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
   7.259 +#else
   7.260 +	return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
   7.261 +#endif
   7.262  }
   7.263  
   7.264  bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
   7.265  {
   7.266 -	return InternalHook(msg_id, pListener, intercept, false);
   7.267 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.268 +	return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
   7.269 +#else
   7.270 +	return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
   7.271 +#endif
   7.272  }
   7.273  
   7.274  bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
   7.275  {	
   7.276 -	return InternalUnhook(msg_id, pListener, intercept, false);
   7.277 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.278 +	return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
   7.279 +#else
   7.280 +	return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
   7.281 +#endif
   7.282  }
   7.283  
   7.284 -bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
   7.285 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.286 +bool UserMessages::InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
   7.287 +#else
   7.288 +bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
   7.289 +#endif
   7.290  {
   7.291  	if (msg_id < 0 || msg_id >= 255)
   7.292  	{
   7.293 @@ -252,10 +408,15 @@
   7.294  
   7.295  	if (!m_HookCount++)
   7.296  	{
   7.297 +#if SOURCE_ENGINE == SE_CSGO
   7.298 +		SH_ADD_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
   7.299 +		SH_ADD_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
   7.300 +#else
   7.301  		SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
   7.302  		SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
   7.303  		SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
   7.304  		SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
   7.305 +#endif
   7.306  	}
   7.307  
   7.308  	if (intercept)
   7.309 @@ -268,7 +429,11 @@
   7.310  	return true;
   7.311  }
   7.312  
   7.313 -bool UserMessages::InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
   7.314 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.315 +bool UserMessages::InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
   7.316 +#else
   7.317 +bool UserMessages::InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
   7.318 +#endif
   7.319  {
   7.320  	MsgList *pList;
   7.321  	MsgIter iter;
   7.322 @@ -309,14 +474,167 @@
   7.323  {
   7.324  	if (--m_HookCount == 0)
   7.325  	{
   7.326 +#if SOURCE_ENGINE == SE_CSGO
   7.327 +		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
   7.328 +		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
   7.329 +#else
   7.330  		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
   7.331  		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
   7.332  		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
   7.333  		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
   7.334 +#endif
   7.335  	}
   7.336  }
   7.337  
   7.338 -#if SOURCE_ENGINE >= SE_LEFT4DEAD
   7.339 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.340 +// Unlike protobuf's Message::CopyFrom:
   7.341 +// - Does not require to/from message descriptors to be identical.
   7.342 +// - Fields are copied by name, rather than index.
   7.343 +// - String fields are retrieved for copy with GetStringReference, to avoid destucting libprotobuf std::string in sm.
   7.344 +// - Unknown fields in |from| message are not copied to |to| message.
   7.345 +// - Copying Message fields recursively calls this function, rather than Message::MergeFrom.
   7.346 +static void _CopyProtobufMessage(const protobuf::Message &from, protobuf::Message *to)
   7.347 +{
   7.348 +	const protobuf::Descriptor* descriptor = from.GetDescriptor();
   7.349 +
   7.350 +	const protobuf::Reflection* from_reflection = from.GetReflection();
   7.351 +	const protobuf::Reflection* to_reflection = to->GetReflection();
   7.352 +
   7.353 +	protobuf::UnknownFieldSet toUnknownFields;
   7.354 +
   7.355 +	int fromFieldCount = descriptor->field_count();
   7.356 +	for (int i = 0; i < fromFieldCount; i++)
   7.357 +	{
   7.358 +		const protobuf::FieldDescriptor* fromField = descriptor->field(i);
   7.359 +		const protobuf::FieldDescriptor* toField = to->GetDescriptor()->FindFieldByName(fromField->name());
   7.360 +
   7.361 +		// This will stripped new fields off of intercepted usermessages.
   7.362 +		// TODO: fix that.
   7.363 +		if (!toField)
   7.364 +		{
   7.365 +			continue;
   7.366 +		}
   7.367 +
   7.368 +		if (fromField->is_repeated())
   7.369 +		{
   7.370 +			int count = from_reflection->FieldSize(from, fromField);
   7.371 +			for (int j = 0; j < count; j++)
   7.372 +			{
   7.373 +				switch (fromField->cpp_type())
   7.374 +				{
   7.375 +#define HANDLE_TYPE(CPPTYPE, METHOD)                                           \
   7.376 +				case protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE:             \
   7.377 +					to_reflection->Add##METHOD(to, toField,                    \
   7.378 +					from_reflection->GetRepeated##METHOD(from, fromField, j)); \
   7.379 +					break;
   7.380 +				HANDLE_TYPE(INT32 , Int32 );
   7.381 +				HANDLE_TYPE(INT64 , Int64 );
   7.382 +				HANDLE_TYPE(UINT32, UInt32);
   7.383 +				HANDLE_TYPE(UINT64, UInt64);
   7.384 +				HANDLE_TYPE(FLOAT , Float );
   7.385 +				HANDLE_TYPE(DOUBLE, Double);
   7.386 +				HANDLE_TYPE(BOOL  , Bool  );
   7.387 +				HANDLE_TYPE(ENUM  , Enum  );
   7.388 +#undef HANDLE_TYPE
   7.389 +				case protobuf::FieldDescriptor::CPPTYPE_STRING:
   7.390 +					{
   7.391 +						std::string buffer;
   7.392 +						to_reflection->AddString(to, toField,
   7.393 +							from_reflection->GetRepeatedStringReference(from, fromField, j, &buffer));
   7.394 +					}
   7.395 +					break;
   7.396 +				case protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
   7.397 +					_CopyProtobufMessage(
   7.398 +						from_reflection->GetRepeatedMessage(from, fromField, j),
   7.399 +						to_reflection->AddMessage(to, toField)
   7.400 +						);
   7.401 +					break;
   7.402 +				}
   7.403 +			}
   7.404 +		}
   7.405 +		else
   7.406 +		{
   7.407 +			switch (fromField->cpp_type())
   7.408 +			{
   7.409 +#define HANDLE_TYPE(CPPTYPE, METHOD)                            \
   7.410 +			case protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE:  \
   7.411 +				to_reflection->Set##METHOD(to, toField,         \
   7.412 +				from_reflection->Get##METHOD(from, fromField)); \
   7.413 +				break;
   7.414 +			HANDLE_TYPE(INT32 , Int32 );
   7.415 +			HANDLE_TYPE(INT64 , Int64 );
   7.416 +			HANDLE_TYPE(UINT32, UInt32);
   7.417 +			HANDLE_TYPE(UINT64, UInt64);
   7.418 +			HANDLE_TYPE(FLOAT , Float );
   7.419 +			HANDLE_TYPE(DOUBLE, Double);
   7.420 +			HANDLE_TYPE(BOOL  , Bool  );
   7.421 +			HANDLE_TYPE(ENUM  , Enum  );
   7.422 +#undef HANDLE_TYPE
   7.423 +			case protobuf::FieldDescriptor::CPPTYPE_STRING:
   7.424 +				{
   7.425 +					std::string buffer;
   7.426 +					to_reflection->SetString(to, toField,
   7.427 +						from_reflection->GetStringReference(from, fromField, &buffer));
   7.428 +				}
   7.429 +				break;
   7.430 +			case protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
   7.431 +				_CopyProtobufMessage(
   7.432 +					from_reflection->GetMessage(from, fromField),
   7.433 +					to_reflection->MutableMessage(to, toField)
   7.434 +					);
   7.435 +				break;
   7.436 +			}
   7.437 +		}
   7.438 +	}
   7.439 +}
   7.440 +#endif
   7.441 +
   7.442 +#if SOURCE_ENGINE == SE_CSGO
   7.443 +void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
   7.444 +{
   7.445 +	OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
   7.446 +	if (m_FakeMetaRes == MRES_SUPERCEDE)
   7.447 +	{
   7.448 +		_CopyProtobufMessage(msg, m_InterceptBuffer);
   7.449 +	}
   7.450 +	else
   7.451 +	{
   7.452 +		OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
   7.453 +	}
   7.454 +
   7.455 +	OnMessageEnd_Pre();
   7.456 +	if (m_FakeMetaRes == MRES_SUPERCEDE)
   7.457 +		RETURN_META(MRES_SUPERCEDE);
   7.458 +
   7.459 +	RETURN_META(MRES_IGNORED);
   7.460 +}
   7.461 +
   7.462 +void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
   7.463 +{
   7.464 +	OnMessageEnd_Post();
   7.465 +	RETURN_META(MRES_IGNORED);
   7.466 +}
   7.467 +#endif
   7.468 +
   7.469 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.470 +#define UM_RETURN_META_VALUE(res, val) \
   7.471 +	m_FakeMetaRes = res;               \
   7.472 +	return val;
   7.473 +
   7.474 +#define UM_RETURN_META(res)            \
   7.475 +	m_FakeMetaRes = res;               \
   7.476 +	return;
   7.477 +#else
   7.478 +#define UM_RETURN_META_VALUE(res, val) \
   7.479 +	RETURN_META_VALUE(res, val)
   7.480 +
   7.481 +#define UM_RETURN_META(res)            \
   7.482 +	RETURN_META(res)
   7.483 +#endif
   7.484 +
   7.485 +#if SOURCE_ENGINE == SE_CSGO
   7.486 +protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
   7.487 +#elif SOURCE_ENGINE >= SE_LEFT4DEAD
   7.488  bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
   7.489  #else
   7.490  bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type)
   7.491 @@ -329,7 +647,7 @@
   7.492  		|| (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
   7.493  	{
   7.494  		m_InHook = false;
   7.495 -		RETURN_META_VALUE(MRES_IGNORED, NULL);
   7.496 +		UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
   7.497  	}
   7.498  
   7.499  	m_CurId = msg_type;
   7.500 @@ -339,14 +657,23 @@
   7.501  
   7.502  	if (!is_intercept_empty)
   7.503  	{
   7.504 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.505 +		if (m_InterceptBuffer)
   7.506 +			delete m_InterceptBuffer;
   7.507 +		m_InterceptBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_type)->New();
   7.508 +		UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer);
   7.509 +#else
   7.510  		m_InterceptBuffer.Reset();
   7.511 -		RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
   7.512 +		UM_RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
   7.513 +#endif
   7.514  	}
   7.515  
   7.516 -	RETURN_META_VALUE(MRES_IGNORED, NULL);
   7.517 +	UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
   7.518  }
   7.519  
   7.520 -#if SOURCE_ENGINE >= SE_LEFT4DEAD
   7.521 +#if SOURCE_ENGINE == SE_CSGO
   7.522 +protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
   7.523 +#elif SOURCE_ENGINE >= SE_LEFT4DEAD
   7.524  bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
   7.525  #else
   7.526  bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type)
   7.527 @@ -354,19 +681,24 @@
   7.528  {
   7.529  	if (!m_InHook)
   7.530  	{
   7.531 -		RETURN_META_VALUE(MRES_IGNORED, NULL);
   7.532 +		UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
   7.533  	}
   7.534  
   7.535 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.536 +	m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_type)->New();
   7.537 +	m_OrigBuffer = m_FakeEngineBuffer;
   7.538 +#else
   7.539  	m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *);
   7.540 +#endif
   7.541  
   7.542 -	RETURN_META_VALUE(MRES_IGNORED, NULL);
   7.543 +	UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
   7.544  }
   7.545  
   7.546  void UserMessages::OnMessageEnd_Post()
   7.547  {
   7.548  	if (!m_InHook)
   7.549  	{
   7.550 -		RETURN_META(MRES_IGNORED);
   7.551 +		UM_RETURN_META(MRES_IGNORED);
   7.552  	}
   7.553  
   7.554  	MsgList *pList;
   7.555 @@ -434,7 +766,7 @@
   7.556  {
   7.557  	if (!m_InHook)
   7.558  	{
   7.559 -		RETURN_META(MRES_IGNORED);
   7.560 +		UM_RETURN_META(MRES_IGNORED);
   7.561  	}
   7.562  
   7.563  	MsgList *pList;
   7.564 @@ -450,7 +782,11 @@
   7.565  	{
   7.566  		pInfo = (*iter);
   7.567  		pInfo->IsHooked = true;
   7.568 +#ifdef USE_PROTOBUF_USERMESSAGES
   7.569 +		res = pInfo->Callback->InterceptUserMessage(m_CurId, m_InterceptBuffer, m_CurRecFilter);
   7.570 +#else
   7.571  		res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
   7.572 +#endif
   7.573  
   7.574  		intercepted = true;
   7.575  
   7.576 @@ -498,8 +834,12 @@
   7.577  
   7.578  	if (!handled && intercepted)
   7.579  	{
   7.580 +#if SOURCE_ENGINE == SE_CSGO
   7.581 +		ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
   7.582 +		delete m_InterceptBuffer;
   7.583 +		m_InterceptBuffer = NULL;
   7.584 +#else
   7.585  		bf_write *engine_bfw;
   7.586 -
   7.587  #if SOURCE_ENGINE >= SE_LEFT4DEAD
   7.588  		engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId));
   7.589  #else
   7.590 @@ -508,6 +848,7 @@
   7.591  		m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
   7.592  		engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
   7.593  		ENGINE_CALL(MessageEnd)();
   7.594 +#endif // SE_CSGO
   7.595  	}
   7.596  
   7.597  	pList = &m_msgHooks[m_CurId];
   7.598 @@ -529,8 +870,8 @@
   7.599  		iter++;
   7.600  	}
   7.601  
   7.602 -	RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
   7.603 +	UM_RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
   7.604  supercede:
   7.605  	m_BlockEndPost = true;
   7.606 -	RETURN_META(MRES_SUPERCEDE);
   7.607 +	UM_RETURN_META(MRES_SUPERCEDE);
   7.608  }
     8.1 --- a/core/UserMessages.h	Mon Jan 07 09:09:14 2013 -0500
     8.2 +++ b/core/UserMessages.h	Tue Jan 22 21:43:12 2013 -0500
     8.3 @@ -36,16 +36,35 @@
     8.4  #include <IUserMessages.h>
     8.5  #include "sourcemm_api.h"
     8.6  #include "sm_trie.h"
     8.7 +#include "sm_stringutil.h"
     8.8  #include "CellRecipientFilter.h"
     8.9  
    8.10  using namespace SourceHook;
    8.11  using namespace SourceMod;
    8.12  
    8.13 +#if SOURCE_ENGINE == SE_CSGO
    8.14 +#define USE_PROTOBUF_USERMESSAGES
    8.15 +#endif
    8.16 +
    8.17 +#ifdef USE_PROTOBUF_USERMESSAGES
    8.18 +#include <google/protobuf/message.h>
    8.19 +#include <google/protobuf/descriptor.h>
    8.20 +#include <netmessages.pb.h>
    8.21 +
    8.22 +using namespace google;
    8.23 +#else
    8.24 +#include <bitbuf.h>
    8.25 +#endif
    8.26 +
    8.27  #define INVALID_MESSAGE_ID -1
    8.28  
    8.29  struct ListenerInfo
    8.30  {
    8.31 -	IUserMessageListener *Callback;
    8.32 +#ifdef USE_PROTOBUF_USERMESSAGES
    8.33 +	IProtobufUserMessageListener *Callback;
    8.34 +#else
    8.35 +	IBitBufUserMessageListener *Callback;
    8.36 +#endif
    8.37  	bool IsHooked;
    8.38  	bool KillMe;
    8.39  	bool IsNew;
    8.40 @@ -70,7 +89,8 @@
    8.41  	bool GetMessageName(int msgid, char *buffer, size_t maxlength) const;
    8.42  	bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
    8.43  	bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
    8.44 -	bf_write *StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
    8.45 +	bf_write *StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
    8.46 +	google::protobuf::Message *StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
    8.47  	bool EndMessage();
    8.48  	bool HookUserMessage2(int msg_id,
    8.49  		IUserMessageListener *pListener,
    8.50 @@ -78,8 +98,17 @@
    8.51  	bool UnhookUserMessage2(int msg_id,
    8.52  		IUserMessageListener *pListener,
    8.53  		bool intercept=false);
    8.54 +	UserMessageType GetUserMessageType() const;
    8.55  public:
    8.56 -#if SOURCE_ENGINE >= SE_LEFT4DEAD
    8.57 +#if SOURCE_ENGINE == SE_CSGO
    8.58 +	void OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
    8.59 +	void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
    8.60 +#endif
    8.61 +
    8.62 +#if SOURCE_ENGINE == SE_CSGO
    8.63 +	protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
    8.64 +	protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
    8.65 +#elif SOURCE_ENGINE >= SE_LEFT4DEAD
    8.66  	bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
    8.67  	bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
    8.68  #else
    8.69 @@ -89,8 +118,13 @@
    8.70  	void OnMessageEnd_Pre();
    8.71  	void OnMessageEnd_Post();
    8.72  private:
    8.73 -	bool InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
    8.74 -	bool InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
    8.75 +#ifdef USE_PROTOBUF_USERMESSAGES
    8.76 +	bool InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
    8.77 +	bool InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
    8.78 +#else
    8.79 +	bool InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
    8.80 +	bool InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
    8.81 +#endif
    8.82  	void _DecRefCounter();
    8.83  private:
    8.84  	List<ListenerInfo *> m_msgHooks[255];
    8.85 @@ -98,15 +132,26 @@
    8.86  	CStack<ListenerInfo *> m_FreeListeners;
    8.87  	unsigned char m_pBase[2500];
    8.88  	IRecipientFilter *m_CurRecFilter;
    8.89 +#ifndef USE_PROTOBUF_USERMESSAGES
    8.90  	bf_write m_InterceptBuffer;
    8.91  	bf_write *m_OrigBuffer;
    8.92  	bf_read m_ReadBuffer;
    8.93 +#else
    8.94 +	// The engine used to provide this. Now we track it.
    8.95 +	protobuf::Message *m_OrigBuffer;
    8.96 +	protobuf::Message *m_FakeEngineBuffer;
    8.97 +	META_RES m_FakeMetaRes;
    8.98 +
    8.99 +	protobuf::Message *m_InterceptBuffer;
   8.100 +#endif
   8.101  	size_t m_HookCount;
   8.102  	bool m_InHook;
   8.103  	bool m_BlockEndPost;
   8.104 +#ifndef USE_PROTOBUF_USERMESSAGES
   8.105  	bool m_FallbackSearch;
   8.106  
   8.107  	Trie *m_Names;
   8.108 +#endif
   8.109  	CellRecipientFilter m_CellRecFilter;
   8.110  	bool m_InExec;
   8.111  	int m_CurFlags;
     9.1 --- a/core/smn_bitbuffer.cpp	Mon Jan 07 09:09:14 2013 -0500
     9.2 +++ b/core/smn_bitbuffer.cpp	Tue Jan 22 21:43:12 2013 -0500
     9.3 @@ -29,11 +29,16 @@
     9.4   * Version: $Id$
     9.5   */
     9.6  
     9.7 +#include "UserMessages.h"
     9.8 +
     9.9 +#ifndef USE_PROTOBUF_USERMESSAGES
    9.10 +
    9.11  #include "sourcemod.h"
    9.12  #include "HandleSys.h"
    9.13  #include <bitbuf.h>
    9.14  #include <vector.h>
    9.15  #include <HalfLife2.h>
    9.16 +#include "smn_usermsgs.h"
    9.17  
    9.18  static cell_t smn_BfWriteBool(IPluginContext *pCtx, const cell_t *params)
    9.19  {
    9.20 @@ -713,3 +718,5 @@
    9.21  	{"BfGetNumBytesLeft",		smn_BfGetNumBytesLeft},
    9.22  	{NULL,						NULL}
    9.23  };
    9.24 +
    9.25 +#endif
    10.1 --- a/core/smn_console.cpp	Mon Jan 07 09:09:14 2013 -0500
    10.2 +++ b/core/smn_console.cpp	Tue Jan 22 21:43:12 2013 -0500
    10.3 @@ -48,6 +48,10 @@
    10.4  #include "ConsoleDetours.h"
    10.5  #include "ConCommandBaseIterator.h"
    10.6  
    10.7 +#if SOURCE_ENGINE == SE_CSGO
    10.8 +#include <netmessages.pb.h>
    10.9 +#endif
   10.10 +
   10.11  #if SOURCE_ENGINE >= SE_EYE
   10.12  #define NETMSG_BITS 6
   10.13  #else
   10.14 @@ -1427,10 +1431,22 @@
   10.15  	char data[256];
   10.16  	bf_write buffer(data, sizeof(data));
   10.17  
   10.18 +#if SOURCE_ENGINE == SE_CSGO
   10.19 +	CNETMsg_SetConVar msg;
   10.20 +	CMsg_CVars_CVar *cvar = msg.mutable_convars()->add_cvars();
   10.21 +
   10.22 +	cvar->set_name(pConVar->GetName());
   10.23 +	cvar->set_value(value);
   10.24 +   
   10.25 +	buffer.WriteVarInt32(net_SetConVar);
   10.26 +	buffer.WriteVarInt32(msg.ByteSize());
   10.27 +	msg.SerializeWithCachedSizesToArray( (uint8 *)( buffer.GetBasePointer() + buffer.GetNumBytesWritten() ) );
   10.28 +#else
   10.29  	buffer.WriteUBitLong(NET_SETCONVAR, NETMSG_BITS);
   10.30  	buffer.WriteByte(1);
   10.31  	buffer.WriteString(pConVar->GetName());
   10.32  	buffer.WriteString(value);
   10.33 +#endif
   10.34  
   10.35  	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
   10.36  
    11.1 --- a/core/smn_hudtext.cpp	Mon Jan 07 09:09:14 2013 -0500
    11.2 +++ b/core/smn_hudtext.cpp	Tue Jan 22 21:43:12 2013 -0500
    11.3 @@ -37,6 +37,10 @@
    11.4  #include "HandleSys.h"
    11.5  #include "logic_bridge.h"
    11.6  
    11.7 +#if SOURCE_ENGINE == SE_CSGO
    11.8 +#include <game/shared/csgo/protobuf/cstrike15_usermessages.pb.h>
    11.9 +#endif
   11.10 +
   11.11  #define MAX_HUD_CHANNELS		6
   11.12  
   11.13  int g_HudMsgNum = -1;
   11.14 @@ -308,12 +312,39 @@
   11.15  
   11.16  void UTIL_SendHudText(int client, const hud_text_parms &textparms, const char *pMessage)
   11.17  {
   11.18 -	bf_write *bf;
   11.19  	cell_t players[1];
   11.20  
   11.21  	players[0] = client;
   11.22  
   11.23 -	bf = g_UserMsgs.StartMessage(g_HudMsgNum, players, 1, 0);
   11.24 +#if SOURCE_ENGINE == SE_CSGO
   11.25 +	// If or when we need to support multiple games per engine with this, we can switch to reflection
   11.26 +	CCSUsrMsg_HudMsg *msg = (CCSUsrMsg_HudMsg *)g_UserMsgs.StartProtobufMessage(g_HudMsgNum, players, 1, 0);
   11.27 +	msg->set_channel(textparms.channel & 0xFF);
   11.28 +
   11.29 +	CMsgVector2D *pos = msg->mutable_pos();
   11.30 +	pos->set_x(textparms.x);
   11.31 +	pos->set_y(textparms.y);
   11.32 +
   11.33 +	CMsgRGBA *color1 = msg->mutable_clr1();
   11.34 +	color1->set_r(textparms.r1);
   11.35 +	color1->set_g(textparms.g1);
   11.36 +	color1->set_b(textparms.b1);
   11.37 +	color1->set_a(textparms.a1);
   11.38 +
   11.39 +	CMsgRGBA *color2 = msg->mutable_clr2();
   11.40 +	color2->set_r(textparms.r2);
   11.41 +	color2->set_g(textparms.g2);
   11.42 +	color2->set_b(textparms.b2);
   11.43 +	color2->set_a(textparms.a2);
   11.44 +
   11.45 +	msg->set_effect(textparms.effect);
   11.46 +	msg->set_fade_in_time(textparms.fadeinTime);
   11.47 +	msg->set_fade_out_time(textparms.fadeoutTime);
   11.48 +	msg->set_hold_time(textparms.holdTime);
   11.49 +	msg->set_fx_time(textparms.fxTime);
   11.50 +	msg->set_text(pMessage);
   11.51 +#else
   11.52 +	bf_write *bf = g_UserMsgs.StartBitBufMessage(g_HudMsgNum, players, 1, 0);
   11.53  	bf->WriteByte(textparms.channel & 0xFF );
   11.54  	bf->WriteFloat(textparms.x);
   11.55  	bf->WriteFloat(textparms.y);
   11.56 @@ -331,6 +362,7 @@
   11.57  	bf->WriteFloat(textparms.holdTime);
   11.58  	bf->WriteFloat(textparms.fxTime);
   11.59  	bf->WriteString(pMessage);
   11.60 +#endif
   11.61  	g_UserMsgs.EndMessage();
   11.62  }
   11.63  
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/core/smn_protobuf.cpp	Tue Jan 22 21:43:12 2013 -0500
    12.3 @@ -0,0 +1,823 @@
    12.4 +/**
    12.5 + * vim: set ts=4 :
    12.6 + * =============================================================================
    12.7 + * SourceMod
    12.8 + * Copyright (C) 2013 AlliedModders LLC.  All rights reserved.
    12.9 + * =============================================================================
   12.10 + *
   12.11 + * This program is free software; you can redistribute it and/or modify it under
   12.12 + * the terms of the GNU General Public License, version 3.0, as published by the
   12.13 + * Free Software Foundation.
   12.14 + * 
   12.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
   12.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   12.17 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
   12.18 + * details.
   12.19 + *
   12.20 + * You should have received a copy of the GNU General Public License along with
   12.21 + * this program.  If not, see <http://www.gnu.org/licenses/>.
   12.22 + *
   12.23 + * As a special exception, AlliedModders LLC gives you permission to link the
   12.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
   12.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
   12.26 + * by the Valve Corporation.  You must obey the GNU General Public License in
   12.27 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
   12.28 + * this exception to all derivative works.  AlliedModders LLC defines further
   12.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
   12.30 + * or <http://www.sourcemod.net/license.php>.
   12.31 + *
   12.32 + * Version: $Id$
   12.33 + */
   12.34 +
   12.35 +#include "UserMessages.h"
   12.36 +
   12.37 +#ifdef USE_PROTOBUF_USERMESSAGES
   12.38 +
   12.39 +#include "HandleSys.h"
   12.40 +#include "UserMessagePBHelpers.h"
   12.41 +#include "smn_usermsgs.h"
   12.42 +
   12.43 +// Assumes pbuf message handle is param 1, gets message as msg
   12.44 +#define GET_MSG_FROM_HANDLE_OR_ERR()                  \
   12.45 +	Handle_t hndl = static_cast<Handle_t>(params[1]); \
   12.46 +	HandleError herr;                                 \
   12.47 +	HandleSecurity sec;                               \
   12.48 +	SMProtobufMessage *msg;                           \
   12.49 +	                                                  \
   12.50 +	sec.pOwner = NULL;                                \
   12.51 +	sec.pIdentity = g_pCoreIdent;                     \
   12.52 +	                                                  \
   12.53 +	if ((herr=g_HandleSys.ReadHandle(hndl, g_ProtobufType, &sec, (void **)&msg)) \
   12.54 +		!= HandleError_None)                          \
   12.55 +	{                                                 \
   12.56 +		return pCtx->ThrowNativeError("Invalid protobuf message handle %x (error %d)", hndl, herr); \
   12.57 +	}
   12.58 +
   12.59 +// Assumes message field name is param 2, gets as strField
   12.60 +#define GET_FIELD_NAME_OR_ERR()                                           \
   12.61 +	int err;                                                              \
   12.62 +	char *strField;                                                       \
   12.63 +	if ((err=pCtx->LocalToString(params[2], &strField)) != SP_ERROR_NONE) \
   12.64 +	{                                                                     \
   12.65 +		pCtx->ThrowNativeErrorEx(err, NULL);                              \
   12.66 +		return 0;                                                         \
   12.67 +	}
   12.68 +
   12.69 +static cell_t smn_PbReadInt(IPluginContext *pCtx, const cell_t *params)
   12.70 +{
   12.71 +	GET_MSG_FROM_HANDLE_OR_ERR();
   12.72 +	GET_FIELD_NAME_OR_ERR();
   12.73 +
   12.74 +	int ret;
   12.75 +	if (!msg->GetInt32OrUnsigned(strField, &ret))
   12.76 +	{
   12.77 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   12.78 +	}
   12.79 +
   12.80 +	return ret;
   12.81 +}
   12.82 +
   12.83 +static cell_t smn_PbReadFloat(IPluginContext *pCtx, const cell_t *params)
   12.84 +{
   12.85 +	GET_MSG_FROM_HANDLE_OR_ERR();
   12.86 +	GET_FIELD_NAME_OR_ERR();
   12.87 +
   12.88 +	float ret;
   12.89 +	if (!msg->GetFloatOrDouble(strField, &ret))
   12.90 +	{
   12.91 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   12.92 +	}
   12.93 +
   12.94 +	return sp_ftoc(ret);
   12.95 +}
   12.96 +
   12.97 +static cell_t smn_PbReadBool(IPluginContext *pCtx, const cell_t *params)
   12.98 +{
   12.99 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.100 +	GET_FIELD_NAME_OR_ERR();
  12.101 +
  12.102 +	bool ret;
  12.103 +	if (!msg->GetBool(strField, &ret))
  12.104 +	{
  12.105 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.106 +	}
  12.107 +
  12.108 +	return ret ? 1 : 0;
  12.109 +}
  12.110 +
  12.111 +static cell_t smn_PbReadString(IPluginContext *pCtx, const cell_t *params)
  12.112 +{
  12.113 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.114 +	GET_FIELD_NAME_OR_ERR();
  12.115 +
  12.116 +	char *buf;
  12.117 +	pCtx->LocalToPhysAddr(params[3], (cell_t **)&buf);
  12.118 +
  12.119 +	if (!msg->GetString(strField, buf, params[4]))
  12.120 +	{
  12.121 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.122 +	}
  12.123 +
  12.124 +	return 1;
  12.125 +}
  12.126 +
  12.127 +static cell_t smn_PbReadColor(IPluginContext *pCtx, const cell_t *params)
  12.128 +{
  12.129 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.130 +	GET_FIELD_NAME_OR_ERR();
  12.131 +
  12.132 +	cell_t *out;
  12.133 +	pCtx->LocalToPhysAddr(params[3], &out);
  12.134 +
  12.135 +	Color clr;
  12.136 +	if (!msg->GetColor(strField, &clr))
  12.137 +	{
  12.138 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.139 +	}
  12.140 +
  12.141 +	out[0] = clr.r();
  12.142 +	out[1] = clr.g();
  12.143 +	out[2] = clr.b();
  12.144 +	out[3] = clr.a();
  12.145 +
  12.146 +	return 1;
  12.147 +}
  12.148 +
  12.149 +static cell_t smn_PbReadAngle(IPluginContext *pCtx, const cell_t *params)
  12.150 +{
  12.151 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.152 +	GET_FIELD_NAME_OR_ERR();
  12.153 +
  12.154 +	cell_t *out;
  12.155 +	pCtx->LocalToPhysAddr(params[3], &out);
  12.156 +
  12.157 +	QAngle ang;
  12.158 +	if (!msg->GetQAngle(strField, &ang))
  12.159 +	{
  12.160 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.161 +	}
  12.162 +
  12.163 +	out[0] = sp_ftoc(ang.x);
  12.164 +	out[1] = sp_ftoc(ang.y);
  12.165 +	out[2] = sp_ftoc(ang.z);
  12.166 +
  12.167 +	return 1;
  12.168 +}
  12.169 +
  12.170 +static cell_t smn_PbReadVector(IPluginContext *pCtx, const cell_t *params)
  12.171 +{
  12.172 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.173 +	GET_FIELD_NAME_OR_ERR();
  12.174 +
  12.175 +	cell_t *out;
  12.176 +	pCtx->LocalToPhysAddr(params[3], &out);
  12.177 +
  12.178 +	Vector vec;
  12.179 +	if (!msg->GetVector(strField, &vec))
  12.180 +	{
  12.181 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.182 +	}
  12.183 +
  12.184 +	out[0] = sp_ftoc(vec.x);
  12.185 +	out[1] = sp_ftoc(vec.y);
  12.186 +	out[2] = sp_ftoc(vec.z);
  12.187 +
  12.188 +	return 1;
  12.189 +}
  12.190 +
  12.191 +static cell_t smn_PbReadVector2D(IPluginContext *pCtx, const cell_t *params)
  12.192 +{
  12.193 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.194 +	GET_FIELD_NAME_OR_ERR();
  12.195 +
  12.196 +	cell_t *out;
  12.197 +	pCtx->LocalToPhysAddr(params[3], &out);
  12.198 +
  12.199 +	Vector2D vec;
  12.200 +	if (!msg->GetVector2D(strField, &vec))
  12.201 +	{
  12.202 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.203 +	}
  12.204 +
  12.205 +	out[0] = sp_ftoc(vec.x);
  12.206 +	out[1] = sp_ftoc(vec.y);
  12.207 +
  12.208 +	return 1;
  12.209 +}
  12.210 +
  12.211 +static cell_t smn_PbGetRepeatedFieldCount(IPluginContext *pCtx, const cell_t *params)
  12.212 +{
  12.213 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.214 +	GET_FIELD_NAME_OR_ERR();
  12.215 +
  12.216 +	int cnt = msg->GetRepeatedFieldCount(strField);
  12.217 +	if (cnt == -1)
  12.218 +	{
  12.219 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.220 +	}
  12.221 +
  12.222 +	return cnt;
  12.223 +}
  12.224 +
  12.225 +static cell_t smn_PbReadRepeatedInt(IPluginContext *pCtx, const cell_t *params)
  12.226 +{
  12.227 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.228 +	GET_FIELD_NAME_OR_ERR();
  12.229 +
  12.230 +	int ret;
  12.231 +	if (!msg->GetRepeatedInt32OrUnsigned(strField, params[3], &ret))
  12.232 +	{
  12.233 +		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
  12.234 +	}
  12.235 +
  12.236 +	return ret;
  12.237 +}
  12.238 +
  12.239 +static cell_t smn_PbReadRepeatedFloat(IPluginContext *pCtx, const cell_t *params)
  12.240 +{
  12.241 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.242 +	GET_FIELD_NAME_OR_ERR();
  12.243 +
  12.244 +	float ret;
  12.245 +	if (!msg->GetRepeatedFloatOrDouble(strField, params[3], &ret))
  12.246 +	{
  12.247 +		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
  12.248 +	}
  12.249 +
  12.250 +	return sp_ftoc(ret);
  12.251 +}
  12.252 +
  12.253 +static cell_t smn_PbReadRepeatedBool(IPluginContext *pCtx, const cell_t *params)
  12.254 +{
  12.255 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.256 +	GET_FIELD_NAME_OR_ERR();
  12.257 +
  12.258 +	bool ret;
  12.259 +	if (!msg->GetRepeatedBool(strField, params[3], &ret))
  12.260 +	{
  12.261 +		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
  12.262 +	}
  12.263 +
  12.264 +	return ret ? 1 : 0;
  12.265 +}
  12.266 +
  12.267 +static cell_t smn_PbReadRepeatedString(IPluginContext *pCtx, const cell_t *params)
  12.268 +{
  12.269 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.270 +	GET_FIELD_NAME_OR_ERR();
  12.271 +
  12.272 +	char *buf;
  12.273 +	pCtx->LocalToPhysAddr(params[4], (cell_t **)&buf);
  12.274 +
  12.275 +	if (!msg->GetRepeatedString(strField, params[3], buf, params[5]))
  12.276 +	{
  12.277 +		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
  12.278 +	}
  12.279 +
  12.280 +	return 1;
  12.281 +}
  12.282 +
  12.283 +static cell_t smn_PbReadRepeatedColor(IPluginContext *pCtx, const cell_t *params)
  12.284 +{
  12.285 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.286 +	GET_FIELD_NAME_OR_ERR();
  12.287 +
  12.288 +	cell_t *out;
  12.289 +	pCtx->LocalToPhysAddr(params[4], &out);
  12.290 +
  12.291 +	Color clr;
  12.292 +	if (!msg->GetRepeatedColor(strField, params[3], &clr))
  12.293 +	{
  12.294 +		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
  12.295 +	}
  12.296 +
  12.297 +	out[0] = clr.r();
  12.298 +	out[1] = clr.g();
  12.299 +	out[2] = clr.b();
  12.300 +	out[3] = clr.a();
  12.301 +
  12.302 +	return 1;
  12.303 +}
  12.304 +
  12.305 +static cell_t smn_PbReadRepeatedAngle(IPluginContext *pCtx, const cell_t *params)
  12.306 +{
  12.307 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.308 +	GET_FIELD_NAME_OR_ERR();
  12.309 +
  12.310 +	cell_t *out;
  12.311 +	pCtx->LocalToPhysAddr(params[4], &out);
  12.312 +
  12.313 +	QAngle ang;
  12.314 +	if (!msg->GetRepeatedQAngle(strField, params[3], &ang))
  12.315 +	{
  12.316 +		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
  12.317 +	}
  12.318 +
  12.319 +	out[0] = sp_ftoc(ang.x);
  12.320 +	out[1] = sp_ftoc(ang.y);
  12.321 +	out[2] = sp_ftoc(ang.z);
  12.322 +
  12.323 +	return 1;
  12.324 +}
  12.325 +
  12.326 +static cell_t smn_PbReadRepeatedVector(IPluginContext *pCtx, const cell_t *params)
  12.327 +{
  12.328 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.329 +	GET_FIELD_NAME_OR_ERR();
  12.330 +
  12.331 +	cell_t *out;
  12.332 +	pCtx->LocalToPhysAddr(params[4], &out);
  12.333 +
  12.334 +	Vector vec;
  12.335 +	if (!msg->GetRepeatedVector(strField, params[3], &vec))
  12.336 +	{
  12.337 +		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
  12.338 +	}
  12.339 +
  12.340 +	out[0] = sp_ftoc(vec.x);
  12.341 +	out[1] = sp_ftoc(vec.y);
  12.342 +	out[2] = sp_ftoc(vec.z);
  12.343 +
  12.344 +	return 1;
  12.345 +}
  12.346 +
  12.347 +static cell_t smn_PbReadRepeatedVector2D(IPluginContext *pCtx, const cell_t *params)
  12.348 +{
  12.349 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.350 +	GET_FIELD_NAME_OR_ERR();
  12.351 +
  12.352 +	cell_t *out;
  12.353 +	pCtx->LocalToPhysAddr(params[4], &out);
  12.354 +
  12.355 +	Vector2D vec;
  12.356 +	if (!msg->GetRepeatedVector2D(strField, params[3], &vec))
  12.357 +	{
  12.358 +		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
  12.359 +	}
  12.360 +
  12.361 +	out[0] = sp_ftoc(vec.x);
  12.362 +	out[1] = sp_ftoc(vec.y);
  12.363 +
  12.364 +	return 1;
  12.365 +}
  12.366 +
  12.367 +static cell_t smn_PbSetInt(IPluginContext *pCtx, const cell_t *params)
  12.368 +{
  12.369 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.370 +	GET_FIELD_NAME_OR_ERR();
  12.371 +
  12.372 +	if (!msg->SetInt32OrUnsigned(strField, params[3]))
  12.373 +	{
  12.374 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.375 +	}
  12.376 +
  12.377 +	return 1;
  12.378 +}
  12.379 +
  12.380 +static cell_t smn_PbSetFloat(IPluginContext *pCtx, const cell_t *params)
  12.381 +{
  12.382 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.383 +	GET_FIELD_NAME_OR_ERR();
  12.384 +
  12.385 +	if (!msg->SetFloatOrDouble(strField, sp_ctof(params[3])))
  12.386 +	{
  12.387 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.388 +	}
  12.389 +
  12.390 +	return 1;
  12.391 +}
  12.392 +
  12.393 +static cell_t smn_PbSetBool(IPluginContext *pCtx, const cell_t *params)
  12.394 +{
  12.395 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.396 +	GET_FIELD_NAME_OR_ERR();
  12.397 +
  12.398 +	bool value = (params[3] == 0 ? false : true);
  12.399 +	if (!msg->SetBool(strField, value))
  12.400 +	{
  12.401 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.402 +	}
  12.403 +
  12.404 +	return 1;
  12.405 +}
  12.406 +
  12.407 +static cell_t smn_PbSetString(IPluginContext *pCtx, const cell_t *params)
  12.408 +{
  12.409 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.410 +	GET_FIELD_NAME_OR_ERR();
  12.411 +
  12.412 +	char *strValue;
  12.413 +	if ((err=pCtx->LocalToString(params[3], &strValue)) != SP_ERROR_NONE)
  12.414 +	{
  12.415 +		pCtx->ThrowNativeErrorEx(err, NULL);
  12.416 +		return 0;
  12.417 +	}
  12.418 +
  12.419 +	if (!msg->SetString(strField, strValue))
  12.420 +	{
  12.421 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.422 +	}
  12.423 +
  12.424 +	return 1;
  12.425 +}
  12.426 +
  12.427 +static cell_t smn_PbSetColor(IPluginContext *pCtx, const cell_t *params)
  12.428 +{
  12.429 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.430 +	GET_FIELD_NAME_OR_ERR();
  12.431 +
  12.432 +	cell_t *clrParams;
  12.433 +	if ((err=pCtx->LocalToPhysAddr(params[3], &clrParams)) != SP_ERROR_NONE)
  12.434 +	{
  12.435 +		pCtx->ThrowNativeErrorEx(err, NULL);
  12.436 +		return 0;
  12.437 +	}
  12.438 +
  12.439 +	Color clr(
  12.440 +		clrParams[0],
  12.441 +		clrParams[1],
  12.442 +		clrParams[2],
  12.443 +		clrParams[3]);
  12.444 +
  12.445 +	if (!msg->SetColor(strField, clr))
  12.446 +	{
  12.447 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.448 +	}
  12.449 +
  12.450 +	return 1;
  12.451 +}
  12.452 +
  12.453 +static cell_t smn_PbSetAngle(IPluginContext *pCtx, const cell_t *params)
  12.454 +{
  12.455 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.456 +	GET_FIELD_NAME_OR_ERR();
  12.457 +
  12.458 +	cell_t *angParams;
  12.459 +	if ((err=pCtx->LocalToPhysAddr(params[3], &angParams)) != SP_ERROR_NONE)
  12.460 +	{
  12.461 +		pCtx->ThrowNativeErrorEx(err, NULL);
  12.462 +		return 0;
  12.463 +	}
  12.464 +
  12.465 +	QAngle ang(
  12.466 +		sp_ctof(angParams[0]),
  12.467 +		sp_ctof(angParams[1]),
  12.468 +		sp_ctof(angParams[2]));
  12.469 +
  12.470 +	if (!msg->SetQAngle(strField, ang))
  12.471 +	{
  12.472 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.473 +	}
  12.474 +
  12.475 +	return 1;
  12.476 +}
  12.477 +
  12.478 +static cell_t smn_PbSetVector(IPluginContext *pCtx, const cell_t *params)
  12.479 +{
  12.480 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.481 +	GET_FIELD_NAME_OR_ERR();
  12.482 +
  12.483 +	cell_t *vecParams;
  12.484 +	if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
  12.485 +	{
  12.486 +		pCtx->ThrowNativeErrorEx(err, NULL);
  12.487 +		return 0;
  12.488 +	}
  12.489 +
  12.490 +	Vector vec(
  12.491 +		sp_ctof(vecParams[0]),
  12.492 +		sp_ctof(vecParams[1]),
  12.493 +		sp_ctof(vecParams[2]));
  12.494 +
  12.495 +	if (!msg->SetVector(strField, vec))
  12.496 +	{
  12.497 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.498 +	}
  12.499 +
  12.500 +	return 1;
  12.501 +}
  12.502 +
  12.503 +static cell_t smn_PbSetVector2D(IPluginContext *pCtx, const cell_t *params)
  12.504 +{
  12.505 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.506 +	GET_FIELD_NAME_OR_ERR();
  12.507 +
  12.508 +	cell_t *vecParams;
  12.509 +	if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
  12.510 +	{
  12.511 +		pCtx->ThrowNativeErrorEx(err, NULL);
  12.512 +		return 0;
  12.513 +	}
  12.514 +
  12.515 +	Vector2D vec(
  12.516 +		sp_ctof(vecParams[0]),
  12.517 +		sp_ctof(vecParams[1]));
  12.518 +
  12.519 +	if (!msg->SetVector2D(strField, vec))
  12.520 +	{
  12.521 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.522 +	}
  12.523 +
  12.524 +	return 1;
  12.525 +}
  12.526 +
  12.527 +static cell_t smn_PbAddInt(IPluginContext *pCtx, const cell_t *params)
  12.528 +{
  12.529 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.530 +	GET_FIELD_NAME_OR_ERR();
  12.531 +
  12.532 +	if (!msg->AddInt32OrUnsigned(strField, params[3]))
  12.533 +	{
  12.534 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.535 +	}
  12.536 +
  12.537 +	return 1;
  12.538 +}
  12.539 +
  12.540 +static cell_t smn_PbAddFloat(IPluginContext *pCtx, const cell_t *params)
  12.541 +{
  12.542 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.543 +	GET_FIELD_NAME_OR_ERR();
  12.544 +
  12.545 +	if (!msg->AddFloatOrDouble(strField, sp_ctof(params[3])))
  12.546 +	{
  12.547 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.548 +	}
  12.549 +
  12.550 +	return 1;
  12.551 +}
  12.552 +
  12.553 +static cell_t smn_PbAddBool(IPluginContext *pCtx, const cell_t *params)
  12.554 +{
  12.555 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.556 +	GET_FIELD_NAME_OR_ERR();
  12.557 +
  12.558 +	bool value = (params[3] == 0 ? false : true);
  12.559 +	if (!msg->AddBool(strField, value))
  12.560 +	{
  12.561 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.562 +	}
  12.563 +
  12.564 +	return 1;
  12.565 +}
  12.566 +
  12.567 +static cell_t smn_PbAddString(IPluginContext *pCtx, const cell_t *params)
  12.568 +{
  12.569 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.570 +	GET_FIELD_NAME_OR_ERR();
  12.571 +
  12.572 +	char *strValue;
  12.573 +	if ((err=pCtx->LocalToString(params[3], &strValue)) != SP_ERROR_NONE)
  12.574 +	{
  12.575 +		pCtx->ThrowNativeErrorEx(err, NULL);
  12.576 +		return 0;
  12.577 +	}
  12.578 +
  12.579 +	if (!msg->AddString(strField, strValue))
  12.580 +	{
  12.581 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.582 +	}
  12.583 +
  12.584 +	return 1;
  12.585 +}
  12.586 +
  12.587 +static cell_t smn_PbAddColor(IPluginContext *pCtx, const cell_t *params)
  12.588 +{
  12.589 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.590 +	GET_FIELD_NAME_OR_ERR();
  12.591 +
  12.592 +	cell_t *clrParams;
  12.593 +	if ((err=pCtx->LocalToPhysAddr(params[3], &clrParams)) != SP_ERROR_NONE)
  12.594 +	{
  12.595 +		pCtx->ThrowNativeErrorEx(err, NULL);
  12.596 +		return 0;
  12.597 +	}
  12.598 +
  12.599 +	Color clr(
  12.600 +		clrParams[0],
  12.601 +		clrParams[1],
  12.602 +		clrParams[2],
  12.603 +		clrParams[3]);
  12.604 +
  12.605 +	if (!msg->AddColor(strField, clr))
  12.606 +	{
  12.607 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.608 +	}
  12.609 +
  12.610 +	return 1;
  12.611 +}
  12.612 +
  12.613 +static cell_t smn_PbAddAngle(IPluginContext *pCtx, const cell_t *params)
  12.614 +{
  12.615 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.616 +	GET_FIELD_NAME_OR_ERR();
  12.617 +
  12.618 +	cell_t *angParams;
  12.619 +	if ((err=pCtx->LocalToPhysAddr(params[3], &angParams)) != SP_ERROR_NONE)
  12.620 +	{
  12.621 +		pCtx->ThrowNativeErrorEx(err, NULL);
  12.622 +		return 0;
  12.623 +	}
  12.624 +
  12.625 +	QAngle ang(
  12.626 +		sp_ctof(angParams[0]),
  12.627 +		sp_ctof(angParams[1]),
  12.628 +		sp_ctof(angParams[2]));
  12.629 +
  12.630 +	if (!msg->AddQAngle(strField, ang))
  12.631 +	{
  12.632 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.633 +	}
  12.634 +
  12.635 +	return 1;
  12.636 +}
  12.637 +
  12.638 +static cell_t smn_PbAddVector(IPluginContext *pCtx, const cell_t *params)
  12.639 +{
  12.640 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.641 +	GET_FIELD_NAME_OR_ERR();
  12.642 +
  12.643 +	cell_t *vecParams;
  12.644 +	if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
  12.645 +	{
  12.646 +		pCtx->ThrowNativeErrorEx(err, NULL);
  12.647 +		return 0;
  12.648 +	}
  12.649 +
  12.650 +	Vector vec(
  12.651 +		sp_ctof(vecParams[0]),
  12.652 +		sp_ctof(vecParams[1]),
  12.653 +		sp_ctof(vecParams[2]));
  12.654 +
  12.655 +	if (!msg->AddVector(strField, vec))
  12.656 +	{
  12.657 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.658 +	}
  12.659 +
  12.660 +	return 1;
  12.661 +}
  12.662 +
  12.663 +static cell_t smn_PbAddVector2D(IPluginContext *pCtx, const cell_t *params)
  12.664 +{
  12.665 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.666 +	GET_FIELD_NAME_OR_ERR();
  12.667 +
  12.668 +	cell_t *vecParams;
  12.669 +	if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
  12.670 +	{
  12.671 +		pCtx->ThrowNativeErrorEx(err, NULL);
  12.672 +		return 0;
  12.673 +	}
  12.674 +
  12.675 +	Vector2D vec(
  12.676 +		sp_ctof(vecParams[0]),
  12.677 +		sp_ctof(vecParams[1]));
  12.678 +
  12.679 +	if (!msg->AddVector2D(strField, vec))
  12.680 +	{
  12.681 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.682 +	}
  12.683 +
  12.684 +	return 1;
  12.685 +}
  12.686 +
  12.687 +static cell_t smn_PbReadMessage(IPluginContext *pCtx, const cell_t *params)
  12.688 +{
  12.689 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.690 +	GET_FIELD_NAME_OR_ERR();
  12.691 +
  12.692 +	protobuf::Message *innerMsg;
  12.693 +	if (!msg->GetMessage(strField, &innerMsg))
  12.694 +	{
  12.695 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.696 +	}
  12.697 +
  12.698 +	Handle_t outHndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(innerMsg), NULL, g_pCoreIdent, NULL);
  12.699 +	msg->AddChildHandle(outHndl);
  12.700 +
  12.701 +	return outHndl;
  12.702 +}
  12.703 +
  12.704 +static cell_t smn_PbReadRepeatedMessage(IPluginContext *pCtx, const cell_t *params)
  12.705 +{
  12.706 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.707 +	GET_FIELD_NAME_OR_ERR();
  12.708 +
  12.709 +	const protobuf::Message *innerMsg;
  12.710 +	if (!msg->GetRepeatedMessage(strField, params[3], &innerMsg))
  12.711 +	{
  12.712 +		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
  12.713 +	}
  12.714 +
  12.715 +	Handle_t outHndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(const_cast<protobuf::Message *>(innerMsg)), NULL, g_pCoreIdent, NULL);
  12.716 +	msg->AddChildHandle(outHndl);
  12.717 +
  12.718 +	return outHndl;
  12.719 +}
  12.720 +
  12.721 +static cell_t smn_PbAddMessage(IPluginContext *pCtx, const cell_t *params)
  12.722 +{
  12.723 +	GET_MSG_FROM_HANDLE_OR_ERR();
  12.724 +	GET_FIELD_NAME_OR_ERR();
  12.725 +
  12.726 +	protobuf::Message *innerMsg;
  12.727 +	if (!msg->AddMessage(strField, &innerMsg))
  12.728 +	{
  12.729 +		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
  12.730 +	}
  12.731 +
  12.732 +	Handle_t outHndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(innerMsg), NULL, g_pCoreIdent, NULL);
  12.733 +	msg->AddChildHandle(outHndl);
  12.734 +
  12.735 +	return outHndl;
  12.736 +}
  12.737 +
  12.738 +REGISTER_NATIVES(protobufnatives)
  12.739 +{
  12.740 +	{"PbReadInt",					smn_PbReadInt},
  12.741 +	{"PbReadFloat",					smn_PbReadFloat},
  12.742 +	{"PbReadBool",					smn_PbReadBool},
  12.743 +	{"PbReadString",				smn_PbReadString},
  12.744 +	{"PbReadColor",					smn_PbReadColor},
  12.745 +	{"PbReadAngle",					smn_PbReadAngle},
  12.746 +	{"PbReadVector",				smn_PbReadVector},
  12.747 +	{"PbReadVector2D",				smn_PbReadVector2D},
  12.748 +	{"PbGetRepeatedFieldCount",		smn_PbGetRepeatedFieldCount},
  12.749 +	{"PbReadRepeatedInt",			smn_PbReadRepeatedInt},
  12.750 +	{"PbReadRepeatedFloat",			smn_PbReadRepeatedFloat},
  12.751 +	{"PbReadRepeatedBool",			smn_PbReadRepeatedBool},
  12.752 +	{"PbReadRepeatedString",		smn_PbReadRepeatedString},
  12.753 +	{"PbReadRepeatedColor",			smn_PbReadRepeatedColor},
  12.754 +	{"PbReadRepeatedAngle",			smn_PbReadRepeatedAngle},
  12.755 +	{"PbReadRepeatedVector",		smn_PbReadRepeatedVector},
  12.756 +	{"PbReadRepeatedVector2D",		smn_PbReadRepeatedVector2D},
  12.757 +	{"PbSetInt",					smn_PbSetInt},
  12.758 +	{"PbSetFloat",					smn_PbSetFloat},
  12.759 +	{"PbSetBool",					smn_PbSetBool},
  12.760 +	{"PbSetString",					smn_PbSetString},
  12.761 +	{"PbSetColor",					smn_PbSetColor},
  12.762 +	{"PbSetAngle",					smn_PbSetAngle},
  12.763 +	{"PbSetVector",					smn_PbSetVector},
  12.764 +	{"PbSetVector2D",				smn_PbSetVector2D},
  12.765 +	{"PbAddInt",					smn_PbAddInt},
  12.766 +	{"PbAddFloat",					smn_PbAddFloat},
  12.767 +	{"PbAddBool",					smn_PbAddBool},
  12.768 +	{"PbAddString",					smn_PbAddString},
  12.769 +	{"PbAddColor",					smn_PbAddColor},
  12.770 +	{"PbAddAngle",					smn_PbAddAngle},
  12.771 +	{"PbAddVector",					smn_PbAddVector},
  12.772 +	{"PbAddVector2D",				smn_PbAddVector2D},
  12.773 +	{"PbReadMessage",				smn_PbReadMessage},
  12.774 +	{"PbReadRepeatedMessage",		smn_PbReadRepeatedMessage},
  12.775 +	{"PbAddMessage",				smn_PbAddMessage},
  12.776 +	{NULL,							NULL}
  12.777 +};
  12.778 +
  12.779 +/*
  12.780 +                                       @@@@@@@@@@@@@ 
  12.781 +                                     @@@@@@@@@@@@@@@@@@
  12.782 +                                     @@@@@@@@@@@@@@@@@@@@@      
  12.783 +                                    @@@@@@@@@@@@@@@@@@@@@@@@               
  12.784 +                                   @@@@@@@@    @@@@@@@@@@@@@
  12.785 +                                   @@@@@@@@    @@@@@@@@@@@@@          
  12.786 +                                      @@@@@@  @@@@@@@@@@@@@@@             
  12.787 +                                 0000   @@@@@@@@@@@@@@@@@@@@@                
  12.788 +                              000000000   @@@@@@@@@@@@@@@@@@@           
  12.789 +                       0000000000000000000   @@@@@@@@@@@@@@@          
  12.790 +                       00000000000000000000  @@@@@@@@@@@@@@@            
  12.791 +                            000000000       @@@@@@@@@@@@@@@           
  12.792 +                                         @@@@@@@@@@@@@@@@@               
  12.793 +                                        @@@@@@@@@@@@@@@@@@      
  12.794 +                                       @@@@@@@@@@@@@@@@@@       
  12.795 +                                       @@@@@@@@@@@@@@@@@@                                                                @@@@
  12.796 +                                      @@@@@@@@@@@@@@@@@@@                                                             @@@@@@@  
  12.797 +                                     @@@   @@@@    @@@                                                             @@@@@@@@@@     
  12.798 +                                    @@@@@@@@@@@@@@@@@@@@@@@@@@                                                 @@@@@@@@@@  @@@@@    
  12.799 +                                   @@@@@@@@@@@@@@@@@@@@@@@@@@ @@@   @@@@@@@@                                @@  @@@@@@@@@@@@@@@ 
  12.800 +                                  @@@@@@@@@@@@@@@@@@@@@@@@@@ @@   @@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@@@@@@@  @@  @@@@@@@@@        
  12.801 +                                  @@@@@@@@@@@@@@@@@@@@@@@ @@@@   @@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@  @@  @@@@@@@@@@@@@
  12.802 +                                  @@@@@@@@@@@@@@@@@@@@@ @@@@    @@@@@@@@@@@@@@@@@    @@@@@@@@@@@@@@@@@@@@@@  @@@  @@@@@@@@@@@@     
  12.803 +                                 @@@@@@@@@@@@@@@@@@@@ @@@@@@   @@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@@@   @@@@  @@@@@@@@@@@     
  12.804 +                                 @@@@@@@@@@@@@@@@@  @@@@@@    @@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@      @@@@@ @@@@@@      
  12.805 +                                 @@@@@@@@@       @@@@@@@@@   @@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@     @@  @@@@@ @@@@@@@@   
  12.806 +                                           @@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@@   @@@@@@  @@@@  @@@@@@  
  12.807 +                                  @@@@@@@@@@@@@@@@@@@@@@    @@@@@@@@@@@@@@@@@@@@@  @@@@@@         @@@@@@  @@@@@@
  12.808 +                                 @@@@@@@@@@@@@@@@@@@@@@@    @@@@@@@@@@@@@@@@@@@@@              @@@@@@@@   @@@@
  12.809 +                                  @@@@@@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@@       @@@@@@@@@@@@@@  @  @@@@@  
  12.810 +                                   @@@@@@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@    @@@@@  @@@@    ////
  12.811 +                     ////////////   @@@@@@@@@@@ @@@@@@       @@@@@@@@@@@@@@@@@@@@  @@      @@@@@@@@@  @@@@    //// //////////// 
  12.812 +              ///////////////// ///    @@@@@          @@@@    @@@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@     @@@@   ///// ///////  /////////    
  12.813 +        /////////////////////  /////         @@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@   @@@@@@@      @  @@@@    ////// ///////  ///////////////
  12.814 +    ///////////////////////// ///////    @@@@@@@@@@@@@@@@@@@    @@@@@@@@@@@@@@@           @@@@@   @@@@    //////  ////////  //////////////////// 
  12.815 + ////////////////////////////  //////////   @@@@@@@@@@@@@@@@@@    @@@@@@@@@@@@   @@@@@@@@@     @@@      //////  ////////// ////////////////////////
  12.816 +//////////////////// //////////  ///////////   @@@@@@@@@@@@@@@@@     @@@@@@@@   @@@      @@@@@@      ////// ////////////  //////////////////////////
  12.817 +//////////////////// ////////////   ///////////   @@@@@@@@@@@@@@@@               @@@@            /////////////////////  /////////////////////////////
  12.818 +/////////////////////  //////////////       //////              @@@@@@@@@                ///////////////////////////////////////////////////////////
  12.819 +   ////////////////////    /////////////////////////////////////          ///////////////////////////////////////////////////////////////////////
  12.820 +       /////////////////////     ////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  12.821 +            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  12.822 +                   //////////////////////////////////////////////////////////////////////////////////////////////////////////////   
  12.823 +                             ///////////////////////////////////////////////////////////////////////////////////////// 
  12.824 +                                             //////////////////////////////////////////////////////////
  12.825 +*/
  12.826 +#endif // USE_PROTOBUF_USERMESSAGES
    13.1 --- a/core/smn_usermsgs.cpp	Mon Jan 07 09:09:14 2013 -0500
    13.2 +++ b/core/smn_usermsgs.cpp	Tue Jan 22 21:43:12 2013 -0500
    13.3 @@ -31,15 +31,22 @@
    13.4  
    13.5  #include "HandleSys.h"
    13.6  #include "PluginSys.h"
    13.7 -#include "UserMessages.h"
    13.8  #include "PlayerManager.h"
    13.9  #include "smn_usermsgs.h"
   13.10 +#ifdef USE_PROTOBUF_USERMESSAGES
   13.11 +#include "UserMessagePBHelpers.h"
   13.12 +#endif
   13.13  
   13.14 -HandleType_t g_WrBitBufType;
   13.15 -HandleType_t g_RdBitBufType;
   13.16 +HandleType_t g_ProtobufType = NO_HANDLE_TYPE;
   13.17 +HandleType_t g_WrBitBufType = NO_HANDLE_TYPE;
   13.18 +HandleType_t g_RdBitBufType = NO_HANDLE_TYPE;
   13.19 +
   13.20  Handle_t g_CurMsgHandle;
   13.21 +
   13.22 +#ifndef USE_PROTOBUF_USERMESSAGES
   13.23  Handle_t g_ReadBufHandle;
   13.24  bf_read g_ReadBitBuf;
   13.25 +#endif
   13.26  
   13.27  int g_MsgPlayers[256];
   13.28  bool g_IsMsgInExec = false;
   13.29 @@ -85,10 +92,14 @@
   13.30  	g_HandleSys.InitAccessDefaults(NULL, &sec);
   13.31  	sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY;
   13.32  
   13.33 +#ifdef USE_PROTOBUF_USERMESSAGES
   13.34 +	g_ProtobufType = g_HandleSys.CreateType("ProtobufUM", this, 0, NULL, NULL, g_pCoreIdent, NULL);
   13.35 +#else
   13.36  	g_WrBitBufType = g_HandleSys.CreateType("BitBufWriter", this, 0, NULL, NULL, g_pCoreIdent, NULL);
   13.37  	g_RdBitBufType = g_HandleSys.CreateType("BitBufReader", this, 0, NULL, &sec, g_pCoreIdent, NULL);
   13.38  
   13.39  	g_ReadBufHandle = g_HandleSys.CreateHandle(g_RdBitBufType, &g_ReadBitBuf, NULL, g_pCoreIdent, NULL);
   13.40 +#endif
   13.41  
   13.42  	g_PluginSys.AddPluginsListener(this);
   13.43  }
   13.44 @@ -98,6 +109,11 @@
   13.45  	HandleSecurity sec;
   13.46  	sec.pIdentity = g_pCoreIdent;
   13.47  
   13.48 +#ifdef USE_PROTOBUF_USERMESSAGES
   13.49 +	g_HandleSys.RemoveType(g_ProtobufType, g_pCoreIdent);
   13.50 +
   13.51 +	g_ProtobufType = 0;
   13.52 +#else
   13.53  	g_HandleSys.FreeHandle(g_ReadBufHandle, &sec);
   13.54  
   13.55  	g_HandleSys.RemoveType(g_WrBitBufType, g_pCoreIdent);
   13.56 @@ -105,15 +121,24 @@
   13.57  
   13.58  	g_WrBitBufType = 0;
   13.59  	g_RdBitBufType = 0;
   13.60 +#endif
   13.61  }
   13.62  
   13.63  void UsrMessageNatives::OnHandleDestroy(HandleType_t type, void *object)
   13.64  {
   13.65 +#ifdef USE_PROTOBUF_USERMESSAGES
   13.66 +	delete (SMProtobufMessage *)object;
   13.67 +#endif
   13.68  }
   13.69  
   13.70  bool UsrMessageNatives::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
   13.71  {
   13.72 +#ifdef USE_PROTOBUF_USERMESSAGES
   13.73 +	// Different messages have different sizes, but this works as an approximate
   13.74 +	*pSize = sizeof(protobuf::Message) + sizeof(SMProtobufMessage);
   13.75 +#else
   13.76  	*pSize = sizeof(bf_read);
   13.77 +#endif
   13.78  
   13.79  	return true;
   13.80  }
   13.81 @@ -275,37 +300,69 @@
   13.82  	return m_Notify;
   13.83  }
   13.84  
   13.85 +#ifdef USE_PROTOBUF_USERMESSAGES
   13.86 +void MsgListenerWrapper::OnUserMessage(int msg_id, protobuf::Message *msg, IRecipientFilter *pFilter)
   13.87 +#else
   13.88  void MsgListenerWrapper::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
   13.89 +#endif
   13.90  {
   13.91  	cell_t res;
   13.92 +	Handle_t hndl;
   13.93  	size_t size = _FillInPlayers(g_MsgPlayers, pFilter);
   13.94  
   13.95 +#ifdef USE_PROTOBUF_USERMESSAGES
   13.96 +	hndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(msg), NULL, g_pCoreIdent, NULL);
   13.97 +#else
   13.98  	g_ReadBitBuf.StartReading(bf->GetBasePointer(), bf->GetNumBytesWritten());
   13.99 +	hndl = g_ReadBufHandle;
  13.100 +#endif
  13.101  
  13.102  	m_Hook->PushCell(msg_id);
  13.103 -	m_Hook->PushCell(g_ReadBufHandle);
  13.104 +	m_Hook->PushCell(hndl);
  13.105  	m_Hook->PushArray(g_MsgPlayers, size);
  13.106  	m_Hook->PushCell(size);
  13.107  	m_Hook->PushCell(pFilter->IsReliable());
  13.108  	m_Hook->PushCell(pFilter->IsInitMessage());
  13.109  	m_Hook->Execute(&res);
  13.110 +
  13.111 +#ifdef USE_PROTOBUF_USERMESSAGES
  13.112 +	HandleSecurity sec;
  13.113 +	sec.pIdentity = g_pCoreIdent;
  13.114 +	g_HandleSys.FreeHandle(hndl, &sec);
  13.115 +#endif
  13.116  }
  13.117  
  13.118 +#ifdef USE_PROTOBUF_USERMESSAGES
  13.119 +ResultType MsgListenerWrapper::InterceptUserMessage(int msg_id, protobuf::Message *msg, IRecipientFilter *pFilter)
  13.120 +#else
  13.121  ResultType MsgListenerWrapper::InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
  13.122 +#endif
  13.123  {
  13.124 +	Handle_t hndl;
  13.125  	cell_t res = static_cast<cell_t>(Pl_Continue);
  13.126  	size_t size = _FillInPlayers(g_MsgPlayers, pFilter);
  13.127  
  13.128 +#ifdef USE_PROTOBUF_USERMESSAGES
  13.129 +	hndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(msg), NULL, g_pCoreIdent, NULL);
  13.130 +#else
  13.131  	g_ReadBitBuf.StartReading(bf->GetBasePointer(), bf->GetNumBytesWritten());
  13.132 +	hndl = g_ReadBufHandle;
  13.133 +#endif
  13.134  
  13.135  	m_Intercept->PushCell(msg_id);
  13.136 -	m_Intercept->PushCell(g_ReadBufHandle);
  13.137 +	m_Intercept->PushCell(hndl);
  13.138  	m_Intercept->PushArray(g_MsgPlayers, size);
  13.139  	m_Intercept->PushCell(size);
  13.140  	m_Intercept->PushCell(pFilter->IsReliable());
  13.141  	m_Intercept->PushCell(pFilter->IsInitMessage());
  13.142  	m_Intercept->Execute(&res);
  13.143  
  13.144 +#ifdef USE_PROTOBUF_USERMESSAGES
  13.145 +	HandleSecurity sec;
  13.146 +	sec.pIdentity = g_pCoreIdent;
  13.147 +	g_HandleSys.FreeHandle(hndl, &sec);
  13.148 +#endif
  13.149 +
  13.150  	return static_cast<ResultType>(res);
  13.151  }
  13.152  
  13.153 @@ -330,6 +387,11 @@
  13.154  
  13.155  static UsrMessageNatives s_UsrMessageNatives;
  13.156  
  13.157 +static cell_t smn_GetUserMessageType(IPluginContext *pCtx, const cell_t *params)
  13.158 +{
  13.159 +	return g_UserMsgs.GetUserMessageType();
  13.160 +}
  13.161 +
  13.162  static cell_t smn_GetUserMessageId(IPluginContext *pCtx, const cell_t *params)
  13.163  {
  13.164  	char *msgname;
  13.165 @@ -353,7 +415,6 @@
  13.166  	cell_t *cl_array;
  13.167  	unsigned int numClients;
  13.168  	int msgid;
  13.169 -	bf_write *pBitBuf;
  13.170  	int client;
  13.171  	CPlayer *pPlayer = NULL;
  13.172  
  13.173 @@ -387,13 +448,24 @@
  13.174  		}
  13.175  	}
  13.176  
  13.177 -	pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, numClients, params[4]);
  13.178 +#ifdef USE_PROTOBUF_USERMESSAGES
  13.179 +	protobuf::Message *msg = g_UserMsgs.StartProtobufMessage(msgid, cl_array, numClients, params[4]);
  13.180 +	if (!msg)
  13.181 +	{
  13.182 +		return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
  13.183 +	}
  13.184 +
  13.185 +	g_CurMsgHandle = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(msg), pCtx->GetIdentity(), g_pCoreIdent, NULL);
  13.186 +#else
  13.187 +	bf_write *pBitBuf = g_UserMsgs.StartBitBufMessage(msgid, cl_array, numClients, params[4]);
  13.188  	if (!pBitBuf)
  13.189  	{
  13.190  		return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
  13.191  	}
  13.192  
  13.193  	g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
  13.194 +#endif
  13.195 +
  13.196  	g_IsMsgInExec = true;
  13.197  
  13.198  	return g_CurMsgHandle;
  13.199 @@ -403,7 +475,6 @@
  13.200  {
  13.201  	cell_t *cl_array;
  13.202  	unsigned int numClients;
  13.203 -	bf_write *pBitBuf;
  13.204  	int client;
  13.205  	CPlayer *pPlayer = NULL;
  13.206  	int msgid = params[1];
  13.207 @@ -436,13 +507,23 @@
  13.208  		}
  13.209  	}
  13.210  
  13.211 -	pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, numClients, params[4]);
  13.212 +#ifdef USE_PROTOBUF_USERMESSAGES
  13.213 +	protobuf::Message *msg = g_UserMsgs.StartProtobufMessage(msgid, cl_array, numClients, params[4]);
  13.214 +	if (!msg)
  13.215 +	{
  13.216 +		return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
  13.217 +	}
  13.218 +
  13.219 +	g_CurMsgHandle = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(msg), pCtx->GetIdentity(), g_pCoreIdent, NULL);
  13.220 +#else
  13.221 +	bf_write *pBitBuf = g_UserMsgs.StartBitBufMessage(msgid, cl_array, numClients, params[4]);
  13.222  	if (!pBitBuf)
  13.223  	{
  13.224  		return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
  13.225  	}
  13.226  
  13.227  	g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
  13.228 +#endif
  13.229  	g_IsMsgInExec = true;
  13.230  
  13.231  	return g_CurMsgHandle;
  13.232 @@ -534,6 +615,7 @@
  13.233  
  13.234  REGISTER_NATIVES(usrmsgnatives)
  13.235  {
  13.236 +	{"GetUserMessageType",			smn_GetUserMessageType},
  13.237  	{"GetUserMessageId",			smn_GetUserMessageId},
  13.238  	{"GetUserMessageName",			smn_GetUserMessageName},
  13.239  	{"StartMessage",				smn_StartMessage},
    14.1 --- a/core/smn_usermsgs.h	Mon Jan 07 09:09:14 2013 -0500
    14.2 +++ b/core/smn_usermsgs.h	Tue Jan 22 21:43:12 2013 -0500
    14.3 @@ -32,9 +32,14 @@
    14.4  #ifndef _INCLUDE_SOURCEMOD_CMSGLISTENERWRAPPER_H_
    14.5  #define _INCLUDE_SOURCEMOD_CMSGLISTENERWRAPPER_H_
    14.6  
    14.7 -extern int g_MsgPlayers[256];
    14.8 +#include "UserMessages.h"
    14.9  
   14.10 -class MsgListenerWrapper : public IUserMessageListener
   14.11 +class MsgListenerWrapper
   14.12 +#ifdef USE_PROTOBUF_USERMESSAGES
   14.13 +	: public IProtobufUserMessageListener
   14.14 +#else
   14.15 +	: public IBitBufUserMessageListener
   14.16 +#endif
   14.17  {
   14.18  public:
   14.19  	void Initialize(int msgid, IPluginFunction *hook, IPluginFunction *notify, bool intercept);
   14.20 @@ -43,8 +48,13 @@
   14.21  	IPluginFunction *GetHookedFunction() const;
   14.22  	IPluginFunction *GetNotifyFunction() const;
   14.23  public: //IUserMessageListener
   14.24 +#ifdef USE_PROTOBUF_USERMESSAGES
   14.25 +	void OnUserMessage(int msg_id, protobuf::Message *msg, IRecipientFilter *pFilter);
   14.26 +	ResultType InterceptUserMessage(int msg_id, protobuf::Message *msg, IRecipientFilter *pFilter);
   14.27 +#else
   14.28  	void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
   14.29  	ResultType InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
   14.30 +#endif
   14.31  	void OnPostUserMessage(int msg_id, bool sent);
   14.32  private:
   14.33  	size_t _FillInPlayers(int *pl_array, IRecipientFilter *pFilter);
   14.34 @@ -56,4 +66,8 @@
   14.35  	int m_MsgId;
   14.36  };
   14.37  
   14.38 +extern HandleType_t g_WrBitBufType;
   14.39 +extern HandleType_t g_RdBitBufType;
   14.40 +extern HandleType_t g_ProtobufType;
   14.41 +
   14.42  #endif //_INCLUDE_SOURCEMOD_CMSGLISTENERWRAPPER_H_
    15.1 --- a/core/sourcemod.h	Mon Jan 07 09:09:14 2013 -0500
    15.2 +++ b/core/sourcemod.h	Tue Jan 22 21:43:12 2013 -0500
    15.3 @@ -152,7 +152,5 @@
    15.4  extern bool g_Loaded;
    15.5  extern bool sm_show_debug_spew;
    15.6  extern SourceModBase g_SourceMod;
    15.7 -extern HandleType_t g_WrBitBufType;		//:TODO: find a better place for this
    15.8 -extern HandleType_t g_RdBitBufType;		//:TODO: find a better place for this
    15.9  
   15.10  #endif //_INCLUDE_SOURCEMOD_GLOBALHEADER_H_
    16.1 --- a/plugins/funcommands/blind.sp	Mon Jan 07 09:09:14 2013 -0500
    16.2 +++ b/plugins/funcommands/blind.sp	Tue Jan 22 21:43:12 2013 -0500
    16.3 @@ -38,23 +38,39 @@
    16.4  	new targets[2];
    16.5  	targets[0] = target;
    16.6  	
    16.7 -	new Handle:message = StartMessageEx(g_FadeUserMsgId, targets, 1);
    16.8 -	BfWriteShort(message, 1536);
    16.9 -	BfWriteShort(message, 1536);
   16.10 -	
   16.11 +	new duration = 1536;
   16.12 +	new holdtime = 1536;
   16.13 +	new flags;
   16.14  	if (amount == 0)
   16.15  	{
   16.16 -		BfWriteShort(message, (0x0001 | 0x0010));
   16.17 +		flags = (0x0001 | 0x0010);
   16.18  	}
   16.19  	else
   16.20  	{
   16.21 -		BfWriteShort(message, (0x0002 | 0x0008));
   16.22 +		flags = (0x0002 | 0x0008);
   16.23  	}
   16.24  	
   16.25 -	BfWriteByte(message, 0);
   16.26 -	BfWriteByte(message, 0);
   16.27 -	BfWriteByte(message, 0);
   16.28 -	BfWriteByte(message, amount);
   16.29 +	new color[4] = { 0, 0, 0, 0 };
   16.30 +	color[3] = amount;
   16.31 +	
   16.32 +	new Handle:message = StartMessageEx(g_FadeUserMsgId, targets, 1);
   16.33 +	if (GetUserMessageType() == UM_Protobuf)
   16.34 +	{
   16.35 +		PbSetInt(message, "duration", duration);
   16.36 +		PbSetInt(message, "hold_time", holdtime);
   16.37 +		PbSetInt(message, "flags", flags);
   16.38 +		PbSetColor(message, "clr", color);
   16.39 +	}
   16.40 +	else
   16.41 +	{
   16.42 +		BfWriteShort(message, duration);
   16.43 +		BfWriteShort(message, holdtime);
   16.44 +		BfWriteShort(message, flags);		
   16.45 +		BfWriteByte(message, color[0]);
   16.46 +		BfWriteByte(message, color[1]);
   16.47 +		BfWriteByte(message, color[2]);
   16.48 +		BfWriteByte(message, color[3]);
   16.49 +	}
   16.50  	
   16.51  	EndMessage();
   16.52  
    17.1 --- a/plugins/funcommands/drug.sp	Mon Jan 07 09:09:14 2013 -0500
    17.2 +++ b/plugins/funcommands/drug.sp	Tue Jan 22 21:43:12 2013 -0500
    17.3 @@ -51,17 +51,34 @@
    17.4  	TeleportEntity(client, NULL_VECTOR, angs, NULL_VECTOR);	
    17.5  	
    17.6  	new clients[2];
    17.7 -	clients[0] = client;	
    17.8 -	
    17.9 +	clients[0] = client;
   17.10 +
   17.11 +	new duration = 1536;
   17.12 +	new holdtime = 1536;
   17.13 +	new flags = (0x0001 | 0x0010);
   17.14 +	new color[4] = { 0, 0, 0, 0 };
   17.15 +
   17.16  	new Handle:message = StartMessageEx(g_FadeUserMsgId, clients, 1);
   17.17 -	BfWriteShort(message, 1536);
   17.18 -	BfWriteShort(message, 1536);
   17.19 -	BfWriteShort(message, (0x0001 | 0x0010));
   17.20 -	BfWriteByte(message, 0);
   17.21 -	BfWriteByte(message, 0);
   17.22 -	BfWriteByte(message, 0);
   17.23 -	BfWriteByte(message, 0);
   17.24 -	EndMessage();	
   17.25 +
   17.26 +	if (GetUserMessageType() == UM_Protobuf)
   17.27 +	{
   17.28 +		PbSetInt(message, "duration", duration);
   17.29 +		PbSetInt(message, "hold_time", holdtime);
   17.30 +		PbSetInt(message, "flags", flags);
   17.31 +		PbSetColor(message, "clr", color);
   17.32 +	}
   17.33 +	else
   17.34 +	{	
   17.35 +		BfWriteShort(message, duration);
   17.36 +		BfWriteShort(message, holdtime);
   17.37 +		BfWriteShort(message, flags);
   17.38 +		BfWriteByte(message, color[0]);
   17.39 +		BfWriteByte(message, color[1]);
   17.40 +		BfWriteByte(message, color[2]);
   17.41 +		BfWriteByte(message, color[3]);
   17.42 +	}
   17.43 +	
   17.44 +	EndMessage();
   17.45  }
   17.46  
   17.47  KillDrugTimer(client)
   17.48 @@ -152,16 +169,35 @@
   17.49  	new clients[2];
   17.50  	clients[0] = client;	
   17.51  	
   17.52 +	new duration = 255;
   17.53 +	new holdtime = 255;
   17.54 +	new flags = 0x0002;
   17.55 +	new color[4] = { 0, 0, 0, 128 };
   17.56 +	color[0] = GetRandomInt(0,255);
   17.57 +	color[1] = GetRandomInt(0,255);
   17.58 +	color[2] = GetRandomInt(0,255);
   17.59 +
   17.60  	new Handle:message = StartMessageEx(g_FadeUserMsgId, clients, 1);
   17.61 -	BfWriteShort(message, 255);
   17.62 -	BfWriteShort(message, 255);
   17.63 -	BfWriteShort(message, (0x0002));
   17.64 -	BfWriteByte(message, GetRandomInt(0,255));
   17.65 -	BfWriteByte(message, GetRandomInt(0,255));
   17.66 -	BfWriteByte(message, GetRandomInt(0,255));
   17.67 -	BfWriteByte(message, 128);
   17.68  	
   17.69 -	EndMessage();	
   17.70 +	if (GetUserMessageType() == UM_Protobuf)
   17.71 +	{
   17.72 +		PbSetInt(message, "duration", duration);
   17.73 +		PbSetInt(message, "hold_time", holdtime);
   17.74 +		PbSetInt(message, "flags", flags);
   17.75 +		PbSetColor(message, "clr", color);
   17.76 +	}
   17.77 +	else
   17.78 +	{
   17.79 +		BfWriteShort(message, duration);
   17.80 +		BfWriteShort(message, holdtime);
   17.81 +		BfWriteShort(message, flags);
   17.82 +		BfWriteByte(message, color[0]);
   17.83 +		BfWriteByte(message, color[1]);
   17.84 +		BfWriteByte(message, color[2]);
   17.85 +		BfWriteByte(message, color[3]);
   17.86 +	}
   17.87 +	
   17.88 +	EndMessage();
   17.89  		
   17.90  	return Plugin_Handled;
   17.91  }
    18.1 --- a/plugins/include/core.inc	Mon Jan 07 09:09:14 2013 -0500
    18.2 +++ b/plugins/include/core.inc	Tue Jan 22 21:43:12 2013 -0500
    18.3 @@ -167,6 +167,67 @@
    18.4  	MarkNativeAsOptional("RequireFeature");
    18.5  	MarkNativeAsOptional("AddCommandListener");
    18.6  	MarkNativeAsOptional("RemoveCommandListener");
    18.7 +	
    18.8 +	MarkNativeAsOptional("BfWriteBool");
    18.9 +	MarkNativeAsOptional("BfWriteByte");
   18.10 +	MarkNativeAsOptional("BfWriteChar");
   18.11 +	MarkNativeAsOptional("BfWriteShort");
   18.12 +	MarkNativeAsOptional("BfWriteWord");
   18.13 +	MarkNativeAsOptional("BfWriteNum");
   18.14 +	MarkNativeAsOptional("BfWriteFloat");
   18.15 +	MarkNativeAsOptional("BfWriteString");
   18.16 +	MarkNativeAsOptional("BfWriteEntity");
   18.17 +	MarkNativeAsOptional("BfWriteAngle");
   18.18 +	MarkNativeAsOptional("BfWriteCoord");
   18.19 +	MarkNativeAsOptional("BfWriteVecCoord");
   18.20 +	MarkNativeAsOptional("BfWriteVecNormal");
   18.21 +	MarkNativeAsOptional("BfWriteAngles");
   18.22 +	MarkNativeAsOptional("BfReadBool");
   18.23 +	MarkNativeAsOptional("BfReadByte");
   18.24 +	MarkNativeAsOptional("BfReadChar");
   18.25 +	MarkNativeAsOptional("BfReadShort");
   18.26 +	MarkNativeAsOptional("BfReadWord");
   18.27 +	MarkNativeAsOptional("BfReadNum");
   18.28 +	MarkNativeAsOptional("BfReadFloat");
   18.29 +	MarkNativeAsOptional("BfReadString");
   18.30 +	MarkNativeAsOptional("BfReadEntity");
   18.31 +	MarkNativeAsOptional("BfReadAngle");
   18.32 +	MarkNativeAsOptional("BfReadCoord");
   18.33 +	MarkNativeAsOptional("BfReadVecCoord");
   18.34 +	MarkNativeAsOptional("BfReadVecNormal");
   18.35 +	MarkNativeAsOptional("BfReadAngles");
   18.36 +	MarkNativeAsOptional("BfGetNumBytesLeft");
   18.37 +	
   18.38 +	MarkNativeAsOptional("PbReadInt");
   18.39 +	MarkNativeAsOptional("PbReadFloat");
   18.40 +	MarkNativeAsOptional("PbReadString");
   18.41 +	MarkNativeAsOptional("PbReadColor");
   18.42 +	MarkNativeAsOptional("PbReadAngle");
   18.43 +	MarkNativeAsOptional("PbReadVector");
   18.44 +	MarkNativeAsOptional("PbReadVector2D");
   18.45 +	MarkNativeAsOptional("PbGetRepeatedFieldCount");
   18.46 +	MarkNativeAsOptional("PbReadRepeatedInt");
   18.47 +	MarkNativeAsOptional("PbReadRepeatedFloat");
   18.48 +	MarkNativeAsOptional("PbReadRepeatedString");
   18.49 +	MarkNativeAsOptional("PbReadRepeatedColor");
   18.50 +	MarkNativeAsOptional("PbReadRepeatedAngle");
   18.51 +	MarkNativeAsOptional("PbReadRepeatedVector");
   18.52 +	MarkNativeAsOptional("PbReadRepeatedVector2D");
   18.53 +	MarkNativeAsOptional("PbSetInt");
   18.54 +	MarkNativeAsOptional("PbSetFloat");
   18.55 +	MarkNativeAsOptional("PbSetString");
   18.56 +	MarkNativeAsOptional("PbSetColor");
   18.57 +	MarkNativeAsOptional("PbSetAngle");
   18.58 +	MarkNativeAsOptional("PbSetVector");
   18.59 +	MarkNativeAsOptional("PbSetVector2D");
   18.60 +	MarkNativeAsOptional("PbAddInt");
   18.61 +	MarkNativeAsOptional("PbAddFloat");
   18.62 +	MarkNativeAsOptional("PbAddString");
   18.63 +	MarkNativeAsOptional("PbAddColor");
   18.64 +	MarkNativeAsOptional("PbAddAngle");
   18.65 +	MarkNativeAsOptional("PbAddVector");
   18.66 +	MarkNativeAsOptional("PbAddVector2D");
   18.67 +	
   18.68  	VerifyCoreVersion();
   18.69  }
   18.70  
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/plugins/include/protobuf.inc	Tue Jan 22 21:43:12 2013 -0500
    19.3 @@ -0,0 +1,433 @@
    19.4 +/**
    19.5 + * vim: set ts=4 :
    19.6 + * =============================================================================
    19.7 + * SourceMod (C)2013 AlliedModders LLC.  All rights reserved.
    19.8 + * =============================================================================
    19.9 + *
   19.10 + * This file is part of the SourceMod/SourcePawn SDK.
   19.11 + *
   19.12 + * This program is free software; you can redistribute it and/or modify it under
   19.13 + * the terms of the GNU General Public License, version 3.0, as published by the
   19.14 + * Free Software Foundation.
   19.15 + * 
   19.16 + * This program is distributed in the hope that it will be useful, but WITHOUT
   19.17 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   19.18 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
   19.19 + * details.
   19.20 + *
   19.21 + * You should have received a copy of the GNU General Public License along with
   19.22 + * this program.  If not, see <http://www.gnu.org/licenses/>.
   19.23 + *
   19.24 + * As a special exception, AlliedModders LLC gives you permission to link the
   19.25 + * code of this program (as well as its derivative works) to "Half-Life 2," the
   19.26 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
   19.27 + * by the Valve Corporation.  You must obey the GNU General Public License in
   19.28 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
   19.29 + * this exception to all derivative works.  AlliedModders LLC defines further
   19.30 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
   19.31 + * or <http://www.sourcemod.net/license.php>.
   19.32 + *
   19.33 + * Version: $Id$
   19.34 + */
   19.35 + 
   19.36 +#if defined _protobuf_included
   19.37 +#endinput
   19.38 +#endif
   19.39 +#define _protobuf_included
   19.40 +
   19.41 +/**
   19.42 + * Reads an int32, uint32, sint32, fixed32, or sfixed32 from a protobuf message.
   19.43 + *
   19.44 + * @param pb			protobuf handle.
   19.45 + * @param field			Field name.
   19.46 + * @return				Integer value read.
   19.47 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
   19.48 + */
   19.49 +native PbReadInt(Handle:pb, const String:field[]);
   19.50 +
   19.51 +/**
   19.52 + * Reads a float or downcasted double from a protobuf message.
   19.53 + *
   19.54 + * @param pb			protobuf handle.
   19.55 + * @param field			Field name.
   19.56 + * @return				Float value read.
   19.57 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
   19.58 + */
   19.59 +native Float:PbReadFloat(Handle:pb, const String:field[]);
   19.60 +
   19.61 +/**
   19.62 + * Reads a bool from a protobuf message.
   19.63 + *
   19.64 + * @param pb			protobuf handle.
   19.65 + * @param field			Field name.
   19.66 + * @return				Boolean value read.
   19.67 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
   19.68 + */
   19.69 +native bool:PbReadBool(Handle:pb, const String:field[]);
   19.70 +
   19.71 +/**
   19.72 + * Reads a string from a protobuf message.
   19.73 + *
   19.74 + * @param pb			protobuf handle.
   19.75 + * @param field			Field name.
   19.76 + * @param buffer		Destination string buffer.
   19.77 + * @param maxlength		Maximum length of output string buffer.
   19.78 + * @noreturn
   19.79 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
   19.80 + */
   19.81 +native PbReadString(Handle:pb, const String:field[], String:buffer[], maxlength);
   19.82 +
   19.83 +/**
   19.84 + * Reads an RGBA color value from a protobuf message.
   19.85 + *
   19.86 + * @param pb			protobuf handle.
   19.87 + * @param field			Field name.
   19.88 + * @param buffer		Destination color buffer.
   19.89 + * @noreturn
   19.90 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
   19.91 + */
   19.92 +native PbReadColor(Handle:pb, const String:field[], buffer[4]);
   19.93 +
   19.94 +/**
   19.95 + * Reads an XYZ angle value from a protobuf message.
   19.96 + *
   19.97 + * @param pb			protobuf handle.
   19.98 + * @param field			Field name.
   19.99 + * @param buffer		Destination angle buffer.
  19.100 + * @noreturn
  19.101 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.102 + */
  19.103 +native PbReadAngle(Handle:pb, const String:field[], Float:buffer[3]);
  19.104 +
  19.105 +/**
  19.106 + * Reads an XYZ vector value from a protobuf message.
  19.107 + *
  19.108 + * @param pb			protobuf handle.
  19.109 + * @param field			Field name.
  19.110 + * @param buffer		Destination vector buffer.
  19.111 + * @noreturn
  19.112 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.113 + */
  19.114 +native PbReadVector(Handle:pb, const String:field[], Float:buffer[3]);
  19.115 +
  19.116 +/**
  19.117 + * Reads an XY vector value from a protobuf message.
  19.118 + *
  19.119 + * @param pb			protobuf handle.
  19.120 + * @param field			Field name.
  19.121 + * @param buffer		Destination vector buffer.
  19.122 + * @noreturn
  19.123 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.124 + */
  19.125 +native PbReadVector2D(Handle:pb, const String:field[], Float:buffer[2]);
  19.126 +
  19.127 +/**
  19.128 + * Gets the number of elements in a repeated field of a protobuf message.
  19.129 + *
  19.130 + * @param pb			protobuf handle.
  19.131 + * @param field			Field name.
  19.132 + * @return				Number of elements in the field.
  19.133 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.134 + */
  19.135 +native PbGetRepeatedFieldCount(Handle:pb, const String:field[]);
  19.136 +
  19.137 +/**
  19.138 + * Reads an int32, uint32, sint32, fixed32, or sfixed32 from a protobuf message repeated field.
  19.139 + *
  19.140 + * @param pb			protobuf handle.
  19.141 + * @param field			Field name.
  19.142 + * @param index			Index in the repeated field.
  19.143 + * @return				Integer value read.
  19.144 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.145 + */
  19.146 +native PbReadRepeatedInt(Handle:pb, const String:field[], index);
  19.147 +
  19.148 +/**
  19.149 + * Reads a float or downcasted double from a protobuf message repeated field.
  19.150 + *
  19.151 + * @param pb			protobuf handle.
  19.152 + * @param field			Field name.
  19.153 + * @param index			Index in the repeated field.
  19.154 + * @return				Float value read.
  19.155 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.156 + */
  19.157 +native Float:PbReadRepeatedFloat(Handle:pb, const String:field[], index);
  19.158 +
  19.159 +/**
  19.160 + * Reads a bool from a protobuf message repeated field.
  19.161 + *
  19.162 + * @param pb			protobuf handle.
  19.163 + * @param field			Field name.
  19.164 + * @param index			Index in the repeated field.
  19.165 + * @return				Boolean value read.
  19.166 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.167 + */
  19.168 +native bool:PbReadRepeatedBool(Handle:pb, const String:field[], index);
  19.169 +
  19.170 +/**
  19.171 + * Reads a string from a protobuf message repeated field.
  19.172 + *
  19.173 + * @param pb			protobuf handle.
  19.174 + * @param field			Field name.
  19.175 + * @param index			Index in the repeated field.
  19.176 + * @param buffer		Destination string buffer.
  19.177 + * @param maxlength		Maximum length of output string buffer.
  19.178 + * @noreturn
  19.179 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.180 + */
  19.181 +native PbReadRepeatedString(Handle:pb, const String:field[], index, String:buffer[], size);
  19.182 +
  19.183 +/**
  19.184 + * Reads an RGBA color value from a protobuf message repeated field.
  19.185 + *
  19.186 + * @param pb			protobuf handle.
  19.187 + * @param field			Field name.
  19.188 + * @param index			Index in the repeated field.
  19.189 + * @param buffer		Destination color buffer.
  19.190 + * @noreturn
  19.191 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.192 + */
  19.193 +native PbReadRepeatedColor(Handle:pb, const String:field[], index, buffer[4]);
  19.194 +
  19.195 +/**
  19.196 + * Reads an XYZ angle value from a protobuf message repeated field.
  19.197 + *
  19.198 + * @param pb			protobuf handle.
  19.199 + * @param field			Field name.
  19.200 + * @param index			Index in the repeated field.
  19.201 + * @param buffer		Destination angle buffer.
  19.202 + * @noreturn
  19.203 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.204 + */
  19.205 +native PbReadRepeatedAngle(Handle:pb, const String:field[], index, Float:buffer[3]);
  19.206 +
  19.207 +/**
  19.208 + * Reads an XYZ vector value from a protobuf message repeated field.
  19.209 + *
  19.210 + * @param pb			protobuf handle.
  19.211 + * @param field			Field name.
  19.212 + * @param index			Index in the repeated field.
  19.213 + * @param buffer		Destination vector buffer.
  19.214 + * @noreturn
  19.215 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.216 + */
  19.217 +native PbReadRepeatedVector(Handle:pb, const String:field[], index, Float:buffer[3]);
  19.218 +
  19.219 +/**
  19.220 + * Reads an XY vector value from a protobuf message repeated field.
  19.221 + *
  19.222 + * @param pb			protobuf handle.
  19.223 + * @param field			Field name.
  19.224 + * @param index			Index in the repeated field.
  19.225 + * @param buffer		Destination vector buffer.
  19.226 + * @noreturn
  19.227 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.228 + */
  19.229 +native PbReadRepeatedVector2D(Handle:pb, const String:field[], index, Float:buffer[2]);
  19.230 +
  19.231 +/**
  19.232 + * Sets an int32, uint32, sint32, fixed32, or sfixed32  on a protobuf message.
  19.233 + *
  19.234 + * @param pb			protobuf handle.
  19.235 + * @param field			Field name.
  19.236 + * @param value			Integer value to set.
  19.237 + * @noreturn
  19.238 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.239 + */
  19.240 +native PbSetInt(Handle:pb, const String:field[], value);
  19.241 +
  19.242 +/**
  19.243 + * Sets a float or double on a protobuf message.
  19.244 + *
  19.245 + * @param pb			protobuf handle.
  19.246 + * @param field			Field name.
  19.247 + * @param value			Float value to set.
  19.248 + * @noreturn
  19.249 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.250 + */
  19.251 +native PbSetFloat(Handle:pb, const String:field[], Float:value);
  19.252 +
  19.253 +/**
  19.254 + * Sets a bool on a protobuf message.
  19.255 + *
  19.256 + * @param pb			protobuf handle.
  19.257 + * @param field			Field name.
  19.258 + * @param value			Boolean value to set.
  19.259 + * @noreturn
  19.260 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.261 + */
  19.262 +native PbSetBool(Handle:pb, const String:field[], bool:value);
  19.263 +
  19.264 +/**
  19.265 + * Sets a string on a protobuf message.
  19.266 + *
  19.267 + * @param pb			protobuf handle.
  19.268 + * @param field			Field name.
  19.269 + * @param value			String value to set.
  19.270 + * @noreturn
  19.271 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.272 + */
  19.273 +native PbSetString(Handle:pb, const String:field[], const String:value[]);
  19.274 +
  19.275 +/**
  19.276 + * Sets an RGBA color on a protobuf message.
  19.277 + *
  19.278 + * @param pb			protobuf handle.
  19.279 + * @param field			Field name.
  19.280 + * @param value			Color value to set.
  19.281 + * @noreturn
  19.282 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.283 + */
  19.284 +native PbSetColor(Handle:pb, const String:field[], const color[4]);
  19.285 +
  19.286 +/**
  19.287 + * Sets an XYZ angle on a protobuf message.
  19.288 + *
  19.289 + * @param pb			protobuf handle.
  19.290 + * @param field			Field name.
  19.291 + * @param value			Angle value to set.
  19.292 + * @noreturn
  19.293 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.294 + */
  19.295 +native PbSetAngle(Handle:pb, const String:field[], const Float:angle[3]);
  19.296 +
  19.297 +/**
  19.298 + * Sets an XYZ vector on a protobuf message.
  19.299 + *
  19.300 + * @param pb			protobuf handle.
  19.301 + * @param field			Field name.
  19.302 + * @param value			Vector value to set.
  19.303 + * @noreturn
  19.304 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.305 + */
  19.306 +native PbSetVector(Handle:pb, const String:field[], const Float:vec[3]);
  19.307 +
  19.308 +/**
  19.309 + * Sets an XY vector on a protobuf message.
  19.310 + *
  19.311 + * @param pb			protobuf handle.
  19.312 + * @param field			Field name.
  19.313 + * @param value			Vector value to set.
  19.314 + * @noreturn
  19.315 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.316 + */
  19.317 +native PbSetVector2D(Handle:pb, const String:field[], const Float:vec[2]);
  19.318 +
  19.319 +/**
  19.320 + * Add an int32, uint32, sint32, fixed32, or sfixed32 to a protobuf message repeated field.
  19.321 + *
  19.322 + * @param pb			protobuf handle.
  19.323 + * @param field			Field name.
  19.324 + * @param value			Integer value to add.
  19.325 + * @noreturn
  19.326 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.327 + */
  19.328 +native PbAddInt(Handle:pb, const String:field[], value);
  19.329 +
  19.330 +/**
  19.331 + * Add a float or double to a protobuf message repeated field.
  19.332 + *
  19.333 + * @param pb			protobuf handle.
  19.334 + * @param field			Field name.
  19.335 + * @param value			Float value to add.
  19.336 + * @noreturn
  19.337 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.338 + */
  19.339 +native PbAddFloat(Handle:pb, const String:field[], Float:value);
  19.340 +
  19.341 +/**
  19.342 + * Add a bool to a protobuf message repeated field.
  19.343 + *
  19.344 + * @param pb			protobuf handle.
  19.345 + * @param field			Field name.
  19.346 + * @param value			Boolean value to add.
  19.347 + * @noreturn
  19.348 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.349 + */
  19.350 +native PbAddBool(Handle:pb, const String:field[], bool:value);
  19.351 +
  19.352 +/**
  19.353 + * Add a string to a protobuf message repeated field.
  19.354 + *
  19.355 + * @param pb			protobuf handle.
  19.356 + * @param field			Field name.
  19.357 + * @param value			String value to add.
  19.358 + * @noreturn
  19.359 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.360 + */
  19.361 +native PbAddString(Handle:pb, const String:field[], const String:value[]);
  19.362 +
  19.363 +/**
  19.364 + * Add an RGBA color to a protobuf message repeated field.
  19.365 + *
  19.366 + * @param pb			protobuf handle.
  19.367 + * @param field			Field name.
  19.368 + * @param value			Color value to add.
  19.369 + * @noreturn
  19.370 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.371 + */
  19.372 +native PbAddColor(Handle:pb, const String:field[], const color[4]);
  19.373 +
  19.374 +/**
  19.375 + * Add an XYZ angle to a protobuf message repeated field.
  19.376 + *
  19.377 + * @param pb			protobuf handle.
  19.378 + * @param field			Field name.
  19.379 + * @param value			Angle value to add.
  19.380 + * @noreturn
  19.381 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.382 + */
  19.383 +native PbAddAngle(Handle:pb, const String:field[], const Float:angle[3]);
  19.384 +
  19.385 +/**
  19.386 + * Add an XYZ vector to a protobuf message repeated field.
  19.387 + *
  19.388 + * @param pb			protobuf handle.
  19.389 + * @param field			Field name.
  19.390 + * @param value			Vector value to add.
  19.391 + * @noreturn
  19.392 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.393 + */
  19.394 +native PbAddVector(Handle:pb, const String:field[], const Float:vec[3]);
  19.395 +
  19.396 +/**
  19.397 + * Add an XY vector to a protobuf message repeated field.
  19.398 + *
  19.399 + * @param pb			protobuf handle.
  19.400 + * @param field			Field name.
  19.401 + * @param value			Vector value to add.
  19.402 + * @noreturn
  19.403 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.404 + */
  19.405 +native PbAddVector2D(Handle:pb, const String:field[], const Float:vec[2]);
  19.406 +
  19.407 +/**
  19.408 + * Retrieve a handle to an embedded protobuf message in a protobuf message.
  19.409 + *
  19.410 + * @param pb			protobuf handle.
  19.411 + * @param field			Field name.
  19.412 + * @return				protobuf handle to embedded message.
  19.413 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.414 + */ 
  19.415 +native Handle:PbReadMessage(Handle:pb, const String:field[]);
  19.416 +
  19.417 +/**
  19.418 + * Retrieve a handle to an embedded protobuf message in a protobuf message repeated field.
  19.419 + *
  19.420 + * @param pb			protobuf handle.
  19.421 + * @param field			Field name.
  19.422 + * @param index			Index in the repeated field.
  19.423 + * @return				protobuf handle to embedded message.
  19.424 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.425 + */ 
  19.426 +native Handle:PbReadRepeatedMessage(Handle:pb, const String:field[], index);
  19.427 +
  19.428 +/**
  19.429 + * Adds an embedded protobuf message to a protobuf message repeated field.
  19.430 + *
  19.431 + * @param pb			protobuf handle.
  19.432 + * @param field			Field name.
  19.433 + * @return				protobuf handle to added, embedded message.
  19.434 + * @error				Invalid or incorrect Handle, non-existant field, or incorrect field type.
  19.435 + */ 
  19.436 +native Handle:PbAddMessage(Handle:pb, const String:field[]);
    20.1 --- a/plugins/include/sourcemod.inc	Mon Jan 07 09:09:14 2013 -0500
    20.2 +++ b/plugins/include/sourcemod.inc	Tue Jan 22 21:43:12 2013 -0500
    20.3 @@ -66,6 +66,7 @@
    20.4  #include <console>
    20.5  #include <events>
    20.6  #include <bitbuffer>
    20.7 +#include <protobuf>
    20.8  #include <usermessages>
    20.9  #include <menus>
   20.10  #include <halflife>
    21.1 --- a/plugins/include/usermessages.inc	Mon Jan 07 09:09:14 2013 -0500
    21.2 +++ b/plugins/include/usermessages.inc	Tue Jan 22 21:43:12 2013 -0500
    21.3 @@ -44,6 +44,15 @@
    21.4  };
    21.5  
    21.6  /**
    21.7 + * UserMsg message serialization formats
    21.8 + */
    21.9 +enum UserMessageType
   21.10 +{
   21.11 +	UM_BitBuf = 0,
   21.12 +	UM_Protobuf,
   21.13 +};
   21.14 +
   21.15 +/**
   21.16   * @section Message Flags.
   21.17   */
   21.18  #define USERMSG_RELIABLE		(1<<2)		/**< Message will be set on the reliable stream */
   21.19 @@ -55,6 +64,13 @@
   21.20   */
   21.21  
   21.22  /**
   21.23 + * Returns usermessage serialization type used for the current engine
   21.24 + *
   21.25 + * @return				The supported usermessage type.
   21.26 + */
   21.27 +native UserMessageType:GetUserMessageType();
   21.28 +
   21.29 +/**
   21.30   * Returns the ID of a given message, or -1 on failure.
   21.31   *
   21.32   * @param msg			String containing message name (case sensitive).
   21.33 @@ -115,7 +131,7 @@
   21.34   * Called when a message is hooked
   21.35   *
   21.36   * @param msg_id		Message index.
   21.37 - * @param bf			Handle to the input bit buffer of the message.
   21.38 + * @param msg			Handle to the input bit buffer or protobuf.
   21.39   * @param players		Array containing player indexes.
   21.40   * @param playersNum	Number of players in the array.
   21.41   * @param reliable		True if message is reliable, false otherwise.
   21.42 @@ -124,7 +140,7 @@
   21.43   *						blocks the message from being sent, and Plugin_Continue 
   21.44   *						resumes normal functionality.
   21.45   */
   21.46 -functag public Action:MsgHook(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init);
   21.47 +functag public Action:MsgHook(UserMsg:msg_id, Handle:msg, const players[], playersNum, bool:reliable, bool:init);
   21.48  
   21.49  /**
   21.50   * Called when a message hook has completed.
    22.1 --- a/public/IUserMessages.h	Mon Jan 07 09:09:14 2013 -0500
    22.2 +++ b/public/IUserMessages.h	Tue Jan 22 21:43:12 2013 -0500
    22.3 @@ -35,19 +35,30 @@
    22.4  #include <IShareSys.h>
    22.5  #include <sp_vm_api.h>
    22.6  #include <IForwardSys.h>
    22.7 -#include <bitbuf.h>
    22.8  #include <irecipientfilter.h>
    22.9  
   22.10 +namespace google { namespace protobuf {
   22.11 +	class Message;
   22.12 +} };
   22.13 +
   22.14 +class bf_write;
   22.15 +
   22.16  /**
   22.17   * @file IUserMessages.h
   22.18   * @brief Contains functions for advanced usermessage hooking.
   22.19   */
   22.20  
   22.21  #define SMINTERFACE_USERMSGS_NAME		"IUserMessages"
   22.22 -#define SMINTERFACE_USERMSGS_VERSION	3
   22.23 +#define SMINTERFACE_USERMSGS_VERSION	4
   22.24  
   22.25  namespace SourceMod
   22.26  {
   22.27 +	enum UserMessageType
   22.28 +	{
   22.29 +		UM_BitBuf,
   22.30 +		UM_Protobuf,
   22.31 +	};
   22.32 +	
   22.33  	/**
   22.34  	 * @brief Listens to user messages sent from the server.
   22.35  	 */
   22.36 @@ -55,31 +66,6 @@
   22.37  	{
   22.38  	public:
   22.39  		/**
   22.40 -		 * @brief Called when a hooked user message is being sent 
   22.41 -		 * and all interceptions have finished.
   22.42 -		 *
   22.43 -		 * @param msg_id		Message Id.
   22.44 -		 * @param bf			bf_write structure containing written bytes.
   22.45 -		 * @param pFilter		Recipient filter.
   22.46 -		 */
   22.47 -		virtual void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
   22.48 -		{
   22.49 -		}
   22.50 -
   22.51 -		/**
   22.52 -		 * @brief Called when a hooked user message is intercepted.
   22.53 -		 * 
   22.54 -		 * @param msg_id		Message Id.
   22.55 -		 * @param bf			bf_write structure containing written bytes.
   22.56 -		 * @param pFilter		Recipient filter.
   22.57 -		 * @return				Pl_Continue to allow message, Pl_Stop or Pl_Handled to scrap it.
   22.58 -		 */
   22.59 -		virtual ResultType InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
   22.60 -		{
   22.61 -			return Pl_Continue;
   22.62 -		}
   22.63 -
   22.64 -		/**
   22.65  		 * @brief Called when a hooked user message is sent, regardless of the hook type.
   22.66  		 *
   22.67  		 * Note: This is called regardless of the API version, though it only happens if the 
   22.68 @@ -110,6 +96,76 @@
   22.69  		virtual void OnPostUserMessage(int msg_id, bool sent)
   22.70  		{
   22.71  		}
   22.72 +		
   22.73 +		virtual UserMessageType GetUserMessageType() const =0;
   22.74 +	};
   22.75 +	
   22.76 +	class IBitBufUserMessageListener : public IUserMessageListener
   22.77 +	{
   22.78 +	public:
   22.79 +		/**
   22.80 +		 * @brief Called when a hooked user message is being sent 
   22.81 +		 * and all interceptions have finished.
   22.82 +		 *
   22.83 +		 * @param msg_id		Message Id.
   22.84 +		 * @param bf			bf_write structure containing written bytes.
   22.85 +		 * @param pFilter		Recipient filter.
   22.86 +		 */
   22.87 +		virtual void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
   22.88 +		{
   22.89 +		}
   22.90 +
   22.91 +		/**
   22.92 +		 * @brief Called when a hooked user message is intercepted.
   22.93 +		 * 
   22.94 +		 * @param msg_id		Message Id.
   22.95 +		 * @param bf			bf_write structure containing written bytes.
   22.96 +		 * @param pFilter		Recipient filter.
   22.97 +		 * @return				Pl_Continue to allow message, Pl_Stop or Pl_Handled to scrap it.
   22.98 +		 */
   22.99 +		virtual ResultType InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
  22.100 +		{
  22.101 +			return Pl_Continue;
  22.102 +		}
  22.103 +		
  22.104 +		virtual UserMessageType GetUserMessageType() const
  22.105 +		{
  22.106 +			return UM_BitBuf;
  22.107 +		}
  22.108 +	};
  22.109 +	
  22.110 +	class IProtobufUserMessageListener : public IUserMessageListener
  22.111 +	{
  22.112 +	public:
  22.113 +		/**
  22.114 +		 * @brief Called when a hooked user message is being sent 
  22.115 +		 * and all interceptions have finished.
  22.116 +		 *
  22.117 +		 * @param msg_id		Message Id.
  22.118 +		 * @param msg			Protobuf Message structure containing message data.
  22.119 +		 * @param pFilter		Recipient filter.
  22.120 +		 */
  22.121 +		virtual void OnUserMessage(int msg_id, google::protobuf::Message *msg, IRecipientFilter *pFilter)
  22.122 +		{
  22.123 +		}
  22.124 +
  22.125 +		/**
  22.126 +		 * @brief Called when a hooked user message is intercepted.
  22.127 +		 * 
  22.128 +		 * @param msg_id		Message Id.
  22.129 +		 * @param msg			Protobuf Message structure containing message data.
  22.130 +		 * @param pFilter		Recipient filter.
  22.131 +		 * @return				Pl_Continue to allow message, Pl_Stop or Pl_Handled to scrap it.
  22.132 +		 */
  22.133 +		virtual ResultType InterceptUserMessage(int msg_id, google::protobuf::Message *msg, IRecipientFilter *pFilter)
  22.134 +		{
  22.135 +			return Pl_Continue;
  22.136 +		}
  22.137 +		
  22.138 +		virtual UserMessageType GetUserMessageType() const
  22.139 +		{
  22.140 +			return UM_Protobuf;
  22.141 +		}
  22.142  	};
  22.143  
  22.144  	#define USERMSG_RELIABLE			(1<<2)		/**< Message will be set to reliable */
  22.145 @@ -173,7 +229,12 @@
  22.146  		 * @param flags			Flags to use for sending the message.
  22.147  		 * @return				bf_write structure to write message with, or NULL on failure.
  22.148  		 */
  22.149 -		virtual bf_write *StartMessage(int msg_id,
  22.150 +		virtual bf_write *StartBitBufMessage(int msg_id,
  22.151 +			const cell_t players[],
  22.152 +			unsigned int playersNum,
  22.153 +			int flags) =0;
  22.154 +
  22.155 +		virtual google::protobuf::Message *StartProtobufMessage(int msg_id,
  22.156  			const cell_t players[],
  22.157  			unsigned int playersNum,
  22.158  			int flags) =0;
  22.159 @@ -218,6 +279,13 @@
  22.160  		 * @return			A message index, or -1 on failure.
  22.161  		 */
  22.162  		virtual bool GetMessageName(int msgid, char *buffer, size_t maxlength) const =0;
  22.163 +		
  22.164 +		/**
  22.165 +		 * @brief Returns usermessage serialization type used for the current engine.
  22.166 +		 *
  22.167 +		 * @return			The supported usermessage type.
  22.168 +		 */
  22.169 +		virtual UserMessageType GetUserMessageType() const =0;
  22.170  	};
  22.171  }
  22.172