Added initial support for protobuf usermessages on CS:GO (bug 5579, r=asherkin).
This commit is contained in:
parent
f757d5f09b
commit
312e26a5cf
@ -124,7 +124,6 @@ class SM:
|
||||
self.compiler.AddToListVar('CFLAGS', '-m32')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '-m32')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-fno-rtti')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-Wno-overloaded-virtual')
|
||||
|
@ -1,5 +1,6 @@
|
||||
# vim: set ts=2 sw=2 tw=99 noet ft=python:
|
||||
import os
|
||||
from ambuild.command import SymlinkCommand
|
||||
|
||||
for i in SM.sdkInfo:
|
||||
sdk = SM.sdkInfo[i]
|
||||
@ -10,9 +11,35 @@ for i in SM.sdkInfo:
|
||||
|
||||
compiler = SM.DefaultHL2Compiler('core', i)
|
||||
|
||||
if i == 'csgo':
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.cache[sdk['sdk']], 'common', 'protobuf-2.3.0', 'src'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.cache[sdk['sdk']], 'public', 'engine', 'protobuf'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.cache[sdk['sdk']], 'public', 'game', 'shared', 'csgo', 'protobuf'))
|
||||
|
||||
extension = AMBuild.AddJob(name)
|
||||
binary = Cpp.LibraryBuilder(name, AMBuild, extension, compiler)
|
||||
SM.PreSetupHL2Job(extension, binary, i)
|
||||
|
||||
if i == 'csgo':
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
link = os.path.join(os.path.join(AMBuild.outputFolder, extension.workFolder), 'libprotobuf.a')
|
||||
target = os.path.join(os.path.join(AMBuild.cache[sdk['sdk']], 'lib', 'linux32', 'release'), 'libprotobuf.a')
|
||||
try:
|
||||
os.lstat(link)
|
||||
except:
|
||||
extension.AddCommand(SymlinkCommand(link, target))
|
||||
elif AMBuild.target['platform'] == 'darwin':
|
||||
link = os.path.join(os.path.join(AMBuild.outputFolder, extension.workFolder), 'libprotobuf.a')
|
||||
target = os.path.join(os.path.join(AMBuild.cache[sdk['sdk']], 'lib', 'osx32', 'release'), 'libprotobuf.a')
|
||||
try:
|
||||
os.lstat(link)
|
||||
except:
|
||||
extension.AddCommand(SymlinkCommand(link, target))
|
||||
elif AMBuild.target['platform'] == 'windows':
|
||||
libPath = os.path.join(AMBuild.cache[sdk['sdk']], 'lib', 'win32', 'release', 'vs2010', 'libprotobuf.lib')
|
||||
binary.RebuildIfNewer(libPath)
|
||||
binary['POSTLINKFLAGS'].append(libPath)
|
||||
|
||||
files = [
|
||||
'AdminCache.cpp',
|
||||
'ExtensionSys.cpp',
|
||||
@ -49,7 +76,6 @@ for i in SM.sdkInfo:
|
||||
'CoreConfig.cpp',
|
||||
'Logger.cpp',
|
||||
'PluginInfoDatabase.cpp',
|
||||
'smn_bitbuffer.cpp',
|
||||
'smn_halflife.cpp',
|
||||
'PluginSys.cpp',
|
||||
'smn_console.cpp',
|
||||
@ -71,7 +97,22 @@ for i in SM.sdkInfo:
|
||||
'sm_srvcmds.cpp',
|
||||
'ConsoleDetours.cpp'
|
||||
]
|
||||
|
||||
if i == 'csgo':
|
||||
files.append('smn_protobuf.cpp')
|
||||
else:
|
||||
files.append('smn_bitbuffer.cpp')
|
||||
|
||||
binary.AddSourceFiles('core', files)
|
||||
|
||||
if i == 'csgo':
|
||||
files = [
|
||||
os.path.join('public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||
os.path.join('public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
|
||||
os.path.join('public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
|
||||
]
|
||||
binary.AddSourceFiles(AMBuild.cache[sdk['sdk']], files)
|
||||
|
||||
SM.PostSetupHL2Job(extension, binary, i)
|
||||
SM.AutoVersion('core', binary)
|
||||
binary.SendToJob()
|
||||
|
@ -42,6 +42,10 @@
|
||||
#include "logic_bridge.h"
|
||||
#include <tier0/mem.h>
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#include <cstrike15_usermessages.pb.h>
|
||||
#endif
|
||||
|
||||
|
||||
typedef ICommandLine *(*FakeGetCommandLine)();
|
||||
|
||||
@ -487,7 +491,9 @@ void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
|
||||
|
||||
bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
{
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
bf_write *pBitBuf = NULL;
|
||||
#endif
|
||||
cell_t players[] = {client};
|
||||
|
||||
if (dest == HUD_PRINTTALK)
|
||||
@ -500,7 +506,18 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
char buffer[192];
|
||||
UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg);
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_SayText *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pMsg->set_ent_idx(0);
|
||||
pMsg->set_text(buffer);
|
||||
pMsg->set_chat(false);
|
||||
#else
|
||||
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -508,6 +525,7 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
pBitBuf->WriteByte(0);
|
||||
pBitBuf->WriteString(buffer);
|
||||
pBitBuf->WriteByte(1);
|
||||
#endif
|
||||
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
@ -515,13 +533,29 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
}
|
||||
}
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_TextMsg *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Client tries to read all 5 'params' and will crash if less
|
||||
pMsg->set_msg_dst(dest);
|
||||
pMsg->add_params(msg);
|
||||
pMsg->add_params("");
|
||||
pMsg->add_params("");
|
||||
pMsg->add_params("");
|
||||
pMsg->add_params("");
|
||||
#else
|
||||
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pBitBuf->WriteByte(dest);
|
||||
pBitBuf->WriteString(msg);
|
||||
#endif
|
||||
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
@ -530,10 +564,20 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
|
||||
bool CHalfLife2::HintTextMsg(int client, const char *msg)
|
||||
{
|
||||
bf_write *pBitBuf = NULL;
|
||||
cell_t players[] = {client};
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_HintText *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pMsg->set_text(msg);
|
||||
#else
|
||||
bf_write *pBitBuf = NULL;
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -544,6 +588,7 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
|
||||
pBitBuf->WriteByte(1);
|
||||
}
|
||||
pBitBuf->WriteString(msg);
|
||||
#endif
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
return true;
|
||||
@ -551,9 +596,18 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
|
||||
|
||||
bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_HintText *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pMsg->set_text(msg);
|
||||
#else
|
||||
bf_write *pBitBuf = NULL;
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
|
||||
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -564,6 +618,8 @@ bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
|
||||
pBitBuf->WriteByte(1);
|
||||
}
|
||||
pBitBuf->WriteString(msg);
|
||||
#endif
|
||||
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
return true;
|
||||
@ -571,15 +627,23 @@ bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
|
||||
|
||||
bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show)
|
||||
{
|
||||
bf_write *pBitBuf = NULL;
|
||||
KeyValues *SubKey = NULL;
|
||||
int count = 0;
|
||||
cell_t players[] = {client};
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_VGUIMenu *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
bf_write *pBitBuf = NULL;
|
||||
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data)
|
||||
{
|
||||
@ -592,6 +656,18 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
|
||||
SubKey = data->GetFirstSubKey();
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
pMsg->set_name(name);
|
||||
pMsg->set_show(show);
|
||||
|
||||
while (SubKey)
|
||||
{
|
||||
CCSUsrMsg_VGUIMenu_Subkey *key = pMsg->add_subkeys();
|
||||
key->set_name(SubKey->GetName());
|
||||
key->set_str(SubKey->GetString());
|
||||
SubKey = SubKey->GetNextKey();
|
||||
}
|
||||
#else
|
||||
pBitBuf->WriteString(name);
|
||||
pBitBuf->WriteByte((show) ? 1 : 0);
|
||||
pBitBuf->WriteByte(count);
|
||||
@ -601,6 +677,8 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
|
||||
pBitBuf->WriteString(SubKey->GetString());
|
||||
SubKey = SubKey->GetNextKey();
|
||||
}
|
||||
#endif
|
||||
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
return true;
|
||||
|
@ -39,6 +39,14 @@
|
||||
#endif
|
||||
#include "logic_bridge.h"
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#include <game/shared/csgo/protobuf/cstrike15_usermessages.pb.h>
|
||||
#endif
|
||||
|
||||
extern const char *g_RadioNumTable[];
|
||||
CRadioStyle g_RadioMenuStyle;
|
||||
int g_ShowMenuId = -1;
|
||||
@ -155,13 +163,22 @@ static unsigned int g_last_holdtime = 0;
|
||||
static unsigned int g_last_client_count = 0;
|
||||
static int g_last_clients[256];
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
void CRadioStyle::OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter)
|
||||
#else
|
||||
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
||||
#endif
|
||||
{
|
||||
int count = pFilter->GetRecipientCount();
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
int c = ((CCSUsrMsg_ShowMenu &)msg).display_time();
|
||||
#else
|
||||
bf_read br(bf->GetBasePointer(), 3);
|
||||
|
||||
br.ReadWord();
|
||||
int c = br.ReadChar();
|
||||
#endif
|
||||
|
||||
g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
|
||||
|
||||
@ -472,6 +489,15 @@ void CRadioMenuPlayer::Radio_Refresh()
|
||||
time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
|
||||
}
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
// If or when we need to support multiple games per engine with this, we can switch to reflection
|
||||
// TODO: find what happens past 240 on CS:GO
|
||||
CCSUsrMsg_ShowMenu *msg = (CCSUsrMsg_ShowMenu *)g_UserMsgs.StartProtobufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
||||
msg->set_bits_valid_slots(display_keys);
|
||||
msg->set_display_time(time);
|
||||
msg->set_menu_string(ptr);
|
||||
g_UserMsgs.EndMessage();
|
||||
#else
|
||||
while (true)
|
||||
{
|
||||
if (len > 240)
|
||||
@ -479,7 +505,8 @@ void CRadioMenuPlayer::Radio_Refresh()
|
||||
save = ptr[240];
|
||||
ptr[240] = '\0';
|
||||
}
|
||||
bf_write *buffer = g_UserMsgs.StartMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
||||
|
||||
bf_write *buffer = g_UserMsgs.StartBitBufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
||||
buffer->WriteWord(display_keys);
|
||||
buffer->WriteChar(time ? time : -1);
|
||||
buffer->WriteByte( (len > 240) ? 1 : 0 );
|
||||
@ -496,6 +523,7 @@ void CRadioMenuPlayer::Radio_Refresh()
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
display_last_refresh = gpGlobals->curtime;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include "MenuStyle_Base.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include <IPlayerHelpers.h>
|
||||
#include <IUserMessages.h>
|
||||
#include "UserMessages.h"
|
||||
#include "sm_fastlink.h"
|
||||
#include <sh_stack.h>
|
||||
#include <compat_wrappers.h>
|
||||
@ -65,7 +65,11 @@ private:
|
||||
class CRadioStyle :
|
||||
public BaseMenuStyle,
|
||||
public SMGlobalClass,
|
||||
public IUserMessageListener
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
public IProtobufUserMessageListener
|
||||
#else
|
||||
public IBitBufUserMessageListener
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
CRadioStyle();
|
||||
@ -84,7 +88,11 @@ public: //IMenuStyle
|
||||
unsigned int GetMaxPageItems();
|
||||
unsigned int GetApproxMemUsage();
|
||||
public: //IUserMessageListener
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
void OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter);
|
||||
#else
|
||||
void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
|
||||
#endif
|
||||
void OnUserMessageSent(int msg_id);
|
||||
public:
|
||||
bool IsSupported();
|
||||
|
853
core/UserMessagePBHelpers.h
Normal file
853
core/UserMessagePBHelpers.h
Normal file
@ -0,0 +1,853 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2013 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_
|
||||
#define _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_
|
||||
|
||||
#include <sh_list.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
#define GETCHECK_FIELD() \
|
||||
const protobuf::FieldDescriptor *field = msg->GetDescriptor()->FindFieldByName(pszFieldName); \
|
||||
if (!field) \
|
||||
{ \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define CHECK_FIELD_TYPE(type) \
|
||||
if (field->cpp_type() != protobuf::FieldDescriptor::CPPTYPE_##type) \
|
||||
{ \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define CHECK_FIELD_TYPE2(type1, type2) \
|
||||
protobuf::FieldDescriptor::CppType fieldType = field->cpp_type(); \
|
||||
if (fieldType != protobuf::FieldDescriptor::CPPTYPE_##type1 \
|
||||
&& fieldType != protobuf::FieldDescriptor::CPPTYPE_##type2) \
|
||||
{ \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define CHECK_FIELD_REPEATED() \
|
||||
if (field->label() != protobuf::FieldDescriptor::LABEL_REPEATED) \
|
||||
{ \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define CHECK_FIELD_NOT_REPEATED() \
|
||||
if (field->label() == protobuf::FieldDescriptor::LABEL_REPEATED) \
|
||||
{ \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define CHECK_REPEATED_ELEMENT(idx) \
|
||||
int elemCount = msg->GetReflection()->FieldSize(*msg, field); \
|
||||
if (elemCount == 0 || idx >= elemCount || idx <= 0) \
|
||||
{ \
|
||||
return false; \
|
||||
}
|
||||
|
||||
typedef List<Handle_t> PBHandleList;
|
||||
|
||||
class SMProtobufMessage
|
||||
{
|
||||
public:
|
||||
SMProtobufMessage( protobuf::Message *message )
|
||||
{
|
||||
msg = message;
|
||||
}
|
||||
|
||||
~SMProtobufMessage()
|
||||
{
|
||||
PBHandleList::iterator iter = childHandles.begin();
|
||||
while (iter != childHandles.end())
|
||||
{
|
||||
Handle_t &hndl = (*iter);
|
||||
HandleSecurity sec;
|
||||
sec.pIdentity = g_pCoreIdent;
|
||||
g_HandleSys.FreeHandle(hndl, &sec);
|
||||
iter = childHandles.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
inline void AddChildHandle(Handle_t hndl)
|
||||
{
|
||||
childHandles.push_back(hndl);
|
||||
}
|
||||
|
||||
inline protobuf::Message *GetProtobufMessage()
|
||||
{
|
||||
return msg;
|
||||
}
|
||||
|
||||
inline bool GetInt32(const char *pszFieldName, int32 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(INT32);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
*out = msg->GetReflection()->GetInt32(*msg, field);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetInt32(const char *pszFieldName, int32 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(INT32);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
msg->GetReflection()->SetInt32(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedInt32(const char *pszFieldName, int index, int32 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(INT32);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
*out = msg->GetReflection()->GetRepeatedInt32(*msg, field, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddInt32(const char *pszFieldName, int32 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(INT32);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
msg->GetReflection()->AddInt32(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetInt64(const char *pszFieldName, int64 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(INT64);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
*out = msg->GetReflection()->GetInt64(*msg, field);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetInt64(const char *pszFieldName, int64 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(INT64);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
msg->GetReflection()->SetInt64(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedInt64(const char *pszFieldName, int index, int64 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(INT64);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
*out = msg->GetReflection()->GetRepeatedInt64(*msg, field, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddInt64(const char *pszFieldName, int64 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(INT64);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
msg->GetReflection()->AddInt64(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetUInt32(const char *pszFieldName, uint32 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(UINT32);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
*out = msg->GetReflection()->GetUInt32(*msg, field);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetUInt32(const char *pszFieldName, uint32 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(UINT32);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
msg->GetReflection()->SetUInt32(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedUInt32(const char *pszFieldName, int index, uint32 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(UINT32);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
*out = msg->GetReflection()->GetRepeatedUInt32(*msg, field, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddUInt32(const char *pszFieldName, uint32 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(UINT32);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
msg->GetReflection()->AddUInt32(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetUInt64(const char *pszFieldName, uint64 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(UINT64);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
*out = msg->GetReflection()->GetUInt64(*msg, field);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetUInt64(const char *pszFieldName, uint64 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(UINT64);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
msg->GetReflection()->SetUInt64(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedUInt64(const char *pszFieldName, int index, uint64 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(UINT64);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
*out = msg->GetReflection()->GetRepeatedUInt64(*msg, field, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddUInt64(const char *pszFieldName, uint64 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(UINT64);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
msg->GetReflection()->AddUInt32(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetInt32OrUnsigned(const char *pszFieldName, int32 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(INT32, UINT32);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
|
||||
*out = (int32)msg->GetReflection()->GetUInt32(*msg, field);
|
||||
else
|
||||
*out = msg->GetReflection()->GetInt32(*msg, field);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetInt32OrUnsigned(const char *pszFieldName, int32 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(INT32, UINT32);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
|
||||
msg->GetReflection()->SetUInt32(msg, field, (uint32)value);
|
||||
else
|
||||
msg->GetReflection()->SetInt32(msg, field, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedInt32OrUnsigned(const char *pszFieldName, int index, int32 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(INT32, UINT32);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
|
||||
*out = (int32)msg->GetReflection()->GetRepeatedUInt32(*msg, field, index);
|
||||
else
|
||||
*out = msg->GetReflection()->GetRepeatedInt32(*msg, field, index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddInt32OrUnsigned(const char *pszFieldName, int32 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(INT32, UINT32);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
|
||||
msg->GetReflection()->AddUInt32(msg, field, (uint32)value);
|
||||
else
|
||||
msg->GetReflection()->AddInt32(msg, field, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetBool(const char *pszFieldName, bool *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(BOOL);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
*out = msg->GetReflection()->GetBool(*msg, field);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetBool(const char *pszFieldName, bool value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(BOOL);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
msg->GetReflection()->SetBool(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedBool(const char *pszFieldName, int index, bool *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(BOOL);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
*out = msg->GetReflection()->GetRepeatedBool(*msg, field, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddBool(const char *pszFieldName, bool value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(BOOL);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
msg->GetReflection()->AddBool(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetFloat(const char *pszFieldName, float *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(FLOAT);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
*out = msg->GetReflection()->GetFloat(*msg, field);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetFloat(const char *pszFieldName, float value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(FLOAT);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
msg->GetReflection()->SetFloat(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedFloat(const char *pszFieldName, int index, float *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(FLOAT);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
*out = msg->GetReflection()->GetRepeatedFloat(*msg, field, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddFloat(const char *pszFieldName, float value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(FLOAT);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
msg->GetReflection()->AddFloat(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetDouble(const char *pszFieldName, double *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(DOUBLE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
*out = msg->GetReflection()->GetDouble(*msg, field);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetDouble(const char *pszFieldName, double value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(DOUBLE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
msg->GetReflection()->SetDouble(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedDouble(const char *pszFieldName, int index, double *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(DOUBLE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
*out = msg->GetReflection()->GetRepeatedDouble(*msg, field, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddDouble(const char *pszFieldName, double value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(DOUBLE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
msg->GetReflection()->AddDouble(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetFloatOrDouble(const char *pszFieldName, float *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
|
||||
*out = (float)msg->GetReflection()->GetDouble(*msg, field);
|
||||
else
|
||||
*out = msg->GetReflection()->GetFloat(*msg, field);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetFloatOrDouble(const char *pszFieldName, float value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
|
||||
msg->GetReflection()->SetDouble(msg, field, (double)value);
|
||||
else
|
||||
msg->GetReflection()->SetFloat(msg, field, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedFloatOrDouble(const char *pszFieldName, int index, float *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
|
||||
*out = (float)msg->GetReflection()->GetRepeatedDouble(*msg, field, index);
|
||||
else
|
||||
*out = msg->GetReflection()->GetRepeatedFloat(*msg, field, index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddFloatOrDouble(const char *pszFieldName, float value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(FLOAT, DOUBLE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_DOUBLE)
|
||||
msg->GetReflection()->AddDouble(msg, field, (double)value);
|
||||
else
|
||||
msg->GetReflection()->AddFloat(msg, field, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetString(const char *pszFieldName, char *out, int size)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(STRING);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
std::string scratch;
|
||||
strncopy(out, msg->GetReflection()->GetStringReference(*msg, field, &buffer).c_str(), size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetString(const char *pszFieldName, const char *value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(STRING);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
msg->GetReflection()->SetString(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedString(const char *pszFieldName, int index, char *out, int size)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(STRING);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
std::string scratch;
|
||||
strncopy(out, msg->GetReflection()->GetRepeatedStringReference(*msg, field, index, &scratch).c_str(), size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddString(const char *pszFieldName, const char *value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(STRING);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
msg->GetReflection()->AddString(msg, field, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetColor(const char *pszFieldName, Color *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
const CMsgRGBA &msgRGBA = (const CMsgRGBA &)msg->GetReflection()->GetMessage(*msg, field);
|
||||
out->SetColor(
|
||||
msgRGBA.r(),
|
||||
msgRGBA.g(),
|
||||
msgRGBA.b(),
|
||||
msgRGBA.a()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetColor(const char *pszFieldName, const Color &value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
CMsgRGBA *msgRGBA = (CMsgRGBA *)msg->GetReflection()->MutableMessage(msg, field);
|
||||
msgRGBA->set_r(value.r());
|
||||
msgRGBA->set_g(value.g());
|
||||
msgRGBA->set_b(value.b());
|
||||
msgRGBA->set_a(value.a());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedColor(const char *pszFieldName, int index, Color *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
const CMsgRGBA &msgRGBA = (const CMsgRGBA &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
|
||||
out->SetColor(
|
||||
msgRGBA.r(),
|
||||
msgRGBA.g(),
|
||||
msgRGBA.b(),
|
||||
msgRGBA.a()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddColor(const char *pszFieldName, const Color &value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
CMsgRGBA *msgRGBA = (CMsgRGBA *)msg->GetReflection()->AddMessage(msg, field);
|
||||
msgRGBA->set_r(value.r());
|
||||
msgRGBA->set_g(value.g());
|
||||
msgRGBA->set_b(value.b());
|
||||
msgRGBA->set_a(value.a());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetVector2D(const char *pszFieldName, Vector2D *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
const CMsgVector2D &msgVec2d = (const CMsgVector2D &)msg->GetReflection()->GetMessage(*msg, field);
|
||||
out->Init(
|
||||
msgVec2d.x(),
|
||||
msgVec2d.y()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetVector2D(const char *pszFieldName, Vector2D &vec)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
CMsgVector2D *msgVec2d = (CMsgVector2D *)msg->GetReflection()->MutableMessage(msg, field);
|
||||
msgVec2d->set_x(vec.x);
|
||||
msgVec2d->set_y(vec.y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedVector2D(const char *pszFieldName, int index, Vector2D *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
const CMsgVector2D &msgVec2d = (const CMsgVector2D &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
|
||||
out->Init(
|
||||
msgVec2d.x(),
|
||||
msgVec2d.y()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddVector2D(const char *pszFieldName, Vector2D &vec)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
CMsgVector2D *msgVec2d = (CMsgVector2D *)msg->GetReflection()->AddMessage(msg, field);
|
||||
msgVec2d->set_x(vec.x);
|
||||
msgVec2d->set_y(vec.y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetVector(const char *pszFieldName, Vector *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
const CMsgVector &msgVec = (const CMsgVector &)msg->GetReflection()->GetMessage(*msg, field);
|
||||
out->Init(
|
||||
msgVec.x(),
|
||||
msgVec.y(),
|
||||
msgVec.z()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetVector(const char *pszFieldName, Vector &vec)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
CMsgVector *msgVec = (CMsgVector *)msg->GetReflection()->MutableMessage(msg, field);
|
||||
msgVec->set_x(vec.x);
|
||||
msgVec->set_y(vec.y);
|
||||
msgVec->set_z(vec.z);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedVector(const char *pszFieldName, int index, Vector *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
const CMsgVector &msgVec = (const CMsgVector &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
|
||||
out->Init(
|
||||
msgVec.x(),
|
||||
msgVec.y(),
|
||||
msgVec.z()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddVector(const char *pszFieldName, Vector &vec)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
CMsgVector *msgVec = (CMsgVector *)msg->GetReflection()->AddMessage(msg, field);
|
||||
msgVec->set_x(vec.x);
|
||||
msgVec->set_y(vec.y);
|
||||
msgVec->set_z(vec.z);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetQAngle(const char *pszFieldName, QAngle *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
const CMsgQAngle &msgAng = (const CMsgQAngle &)msg->GetReflection()->GetMessage(*msg, field);
|
||||
out->Init(
|
||||
msgAng.x(),
|
||||
msgAng.y(),
|
||||
msgAng.z()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetQAngle(const char *pszFieldName, QAngle &vec)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
CMsgQAngle *msgAng = (CMsgQAngle *)msg->GetReflection()->MutableMessage(msg, field);
|
||||
msgAng->set_x(vec.x);
|
||||
msgAng->set_y(vec.y);
|
||||
msgAng->set_z(vec.z);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedQAngle(const char *pszFieldName, int index, QAngle *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
const CMsgQAngle &msgAng = (const CMsgQAngle &)msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
|
||||
out->Init(
|
||||
msgAng.x(),
|
||||
msgAng.y(),
|
||||
msgAng.z()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddQAngle(const char *pszFieldName, QAngle &vec)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
CMsgQAngle *msgAng = (CMsgQAngle *)msg->GetReflection()->AddMessage(msg, field);
|
||||
msgAng->set_x(vec.x);
|
||||
msgAng->set_y(vec.y);
|
||||
msgAng->set_z(vec.z);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetMessage(const char *pszFieldName, protobuf::Message **message)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
*message = msg->GetReflection()->MutableMessage(msg, field);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedMessage(const char *pszFieldName, int index, const protobuf::Message **message)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
const protobuf::Message *m = &msg->GetReflection()->GetRepeatedMessage(*msg, field, index);
|
||||
*message = m;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddMessage(const char *pszFieldName, protobuf::Message **message)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE(MESSAGE);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
*message = msg->GetReflection()->AddMessage(msg, field);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline int GetRepeatedFieldCount(const char *pszFieldName)
|
||||
{
|
||||
const protobuf::FieldDescriptor *field = msg->GetDescriptor()->FindFieldByName(pszFieldName); \
|
||||
if (!field)
|
||||
return -1;
|
||||
|
||||
if (field->label() != protobuf::FieldDescriptor::LABEL_REPEATED)
|
||||
return -1;
|
||||
|
||||
return msg->GetReflection()->FieldSize(*msg, field);
|
||||
}
|
||||
|
||||
private:
|
||||
protobuf::Message *msg;
|
||||
PBHandleList childHandles;
|
||||
};
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_
|
@ -32,18 +32,32 @@
|
||||
#include "UserMessages.h"
|
||||
#include "sm_stringutil.h"
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#include <cstrike15_usermessage_helpers.h>
|
||||
#endif
|
||||
|
||||
UserMessages g_UserMsgs;
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
|
||||
#else
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *);
|
||||
#else
|
||||
SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
|
||||
#endif
|
||||
SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
|
||||
#endif // ==SE_CSGO
|
||||
|
||||
UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
|
||||
UserMessages::UserMessages()
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
: m_InterceptBuffer(m_pBase, 2500)
|
||||
{
|
||||
m_Names = sm_trie_create();
|
||||
#else
|
||||
: m_InterceptBuffer(NULL)
|
||||
{
|
||||
#endif
|
||||
m_HookCount = 0;
|
||||
m_InExec = false;
|
||||
m_InHook = false;
|
||||
@ -53,7 +67,9 @@ UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
|
||||
|
||||
UserMessages::~UserMessages()
|
||||
{
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
sm_trie_destroy(m_Names);
|
||||
#endif
|
||||
|
||||
CStack<ListenerInfo *>::iterator iter;
|
||||
for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
|
||||
@ -65,8 +81,10 @@ UserMessages::~UserMessages()
|
||||
|
||||
void UserMessages::OnSourceModStartup(bool late)
|
||||
{
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
/* -1 means SourceMM was unable to get the user message list */
|
||||
m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void UserMessages::OnSourceModAllInitialized()
|
||||
@ -78,16 +96,25 @@ void UserMessages::OnSourceModAllShutdown()
|
||||
{
|
||||
if (m_HookCount)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
|
||||
#else
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
||||
#endif
|
||||
}
|
||||
m_HookCount = 0;
|
||||
}
|
||||
|
||||
int UserMessages::GetMessageIndex(const char *msg)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
// Can split this per engine and/or game later
|
||||
return g_Cstrike15UsermessageHelpers.GetIndex(msg);
|
||||
#else
|
||||
int msgid;
|
||||
|
||||
if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid)))
|
||||
@ -118,10 +145,19 @@ int UserMessages::GetMessageIndex(const char *msg)
|
||||
}
|
||||
|
||||
return msgid;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
|
||||
if (!pszName)
|
||||
return false;
|
||||
|
||||
strncopy(buffer, pszName, maxlength);
|
||||
return true;
|
||||
#else
|
||||
if (m_FallbackSearch)
|
||||
{
|
||||
int size;
|
||||
@ -137,10 +173,14 @@ bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) con
|
||||
}
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
|
||||
bf_write *UserMessages::StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
|
||||
{
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
return NULL;
|
||||
#else
|
||||
bf_write *buffer;
|
||||
|
||||
if (m_InExec || m_InHook)
|
||||
@ -182,6 +222,68 @@ bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigne
|
||||
}
|
||||
|
||||
return buffer;
|
||||
#endif // USE_PROTOBUF_USERMESSAGES
|
||||
}
|
||||
|
||||
google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
|
||||
{
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
return NULL;
|
||||
#else
|
||||
protobuf::Message *buffer;
|
||||
|
||||
if (m_InExec || m_InHook)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (msg_id < 0 || msg_id >= 255)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_CurId = msg_id;
|
||||
m_CellRecFilter.Initialize(players, playersNum);
|
||||
|
||||
m_CurFlags = flags;
|
||||
if (m_CurFlags & USERMSG_INITMSG)
|
||||
{
|
||||
m_CellRecFilter.SetToInit(true);
|
||||
}
|
||||
if (m_CurFlags & USERMSG_RELIABLE)
|
||||
{
|
||||
m_CellRecFilter.SetToReliable(true);
|
||||
}
|
||||
|
||||
m_InExec = true;
|
||||
|
||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||
{
|
||||
// direct message creation, return buffer "from engine". keep track
|
||||
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
|
||||
buffer = m_FakeEngineBuffer;
|
||||
} else {
|
||||
protobuf::Message *msg = OnStartMessage_Pre(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
|
||||
switch (m_FakeMetaRes)
|
||||
{
|
||||
case MRES_IGNORED:
|
||||
case MRES_HANDLED:
|
||||
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
|
||||
buffer = m_FakeEngineBuffer;
|
||||
break;
|
||||
|
||||
case MRES_OVERRIDE:
|
||||
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
|
||||
// fallthrough
|
||||
case MRES_SUPERCEDE:
|
||||
buffer = msg;
|
||||
break;
|
||||
}
|
||||
|
||||
OnStartMessage_Post(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
|
||||
}
|
||||
|
||||
return buffer;
|
||||
#endif // USE_PROTOBUF_USERMESSAGES
|
||||
}
|
||||
|
||||
bool UserMessages::EndMessage()
|
||||
@ -191,12 +293,37 @@ bool UserMessages::EndMessage()
|
||||
return false;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||
{
|
||||
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
|
||||
delete m_FakeEngineBuffer;
|
||||
m_FakeEngineBuffer = NULL;
|
||||
} else {
|
||||
OnMessageEnd_Pre();
|
||||
|
||||
switch (m_FakeMetaRes)
|
||||
{
|
||||
case MRES_IGNORED:
|
||||
case MRES_HANDLED:
|
||||
case MRES_OVERRIDE:
|
||||
engine->SendUserMessage(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
|
||||
delete m_FakeEngineBuffer;
|
||||
m_FakeEngineBuffer = NULL;
|
||||
break;
|
||||
//case MRES_SUPERCEDE:
|
||||
}
|
||||
|
||||
OnMessageEnd_Post();
|
||||
}
|
||||
#else
|
||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||
{
|
||||
ENGINE_CALL(MessageEnd)();
|
||||
} else {
|
||||
engine->MessageEnd();
|
||||
}
|
||||
#endif // SE_CSGO
|
||||
|
||||
m_InExec = false;
|
||||
m_CurFlags = 0;
|
||||
@ -205,31 +332,60 @@ bool UserMessages::EndMessage()
|
||||
return true;
|
||||
}
|
||||
|
||||
UserMessageType UserMessages::GetUserMessageType() const
|
||||
{
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
return UM_Protobuf;
|
||||
#else
|
||||
return UM_BitBuf;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UserMessages::HookUserMessage2(int msg_id,
|
||||
IUserMessageListener *pListener,
|
||||
bool intercept)
|
||||
{
|
||||
return InternalHook(msg_id, pListener, intercept, true);
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
|
||||
#else
|
||||
return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UserMessages::UnhookUserMessage2(int msg_id,
|
||||
IUserMessageListener *pListener,
|
||||
bool intercept)
|
||||
{
|
||||
return InternalUnhook(msg_id, pListener, intercept, true);
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
|
||||
#else
|
||||
return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
||||
{
|
||||
return InternalHook(msg_id, pListener, intercept, false);
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
|
||||
#else
|
||||
return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
||||
{
|
||||
return InternalUnhook(msg_id, pListener, intercept, false);
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
|
||||
#else
|
||||
return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
bool UserMessages::InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
#else
|
||||
bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
#endif
|
||||
{
|
||||
if (msg_id < 0 || msg_id >= 255)
|
||||
{
|
||||
@ -252,10 +408,15 @@ bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, boo
|
||||
|
||||
if (!m_HookCount++)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
|
||||
#else
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (intercept)
|
||||
@ -268,7 +429,11 @@ bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, boo
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UserMessages::InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
bool UserMessages::InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
#else
|
||||
bool UserMessages::InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
#endif
|
||||
{
|
||||
MsgList *pList;
|
||||
MsgIter iter;
|
||||
@ -309,14 +474,167 @@ void UserMessages::_DecRefCounter()
|
||||
{
|
||||
if (--m_HookCount == 0)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
|
||||
#else
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
// Unlike protobuf's Message::CopyFrom:
|
||||
// - Does not require to/from message descriptors to be identical.
|
||||
// - Fields are copied by name, rather than index.
|
||||
// - String fields are retrieved for copy with GetStringReference, to avoid destucting libprotobuf std::string in sm.
|
||||
// - Unknown fields in |from| message are not copied to |to| message.
|
||||
// - Copying Message fields recursively calls this function, rather than Message::MergeFrom.
|
||||
static void _CopyProtobufMessage(const protobuf::Message &from, protobuf::Message *to)
|
||||
{
|
||||
const protobuf::Descriptor* descriptor = from.GetDescriptor();
|
||||
|
||||
const protobuf::Reflection* from_reflection = from.GetReflection();
|
||||
const protobuf::Reflection* to_reflection = to->GetReflection();
|
||||
|
||||
protobuf::UnknownFieldSet toUnknownFields;
|
||||
|
||||
int fromFieldCount = descriptor->field_count();
|
||||
for (int i = 0; i < fromFieldCount; i++)
|
||||
{
|
||||
const protobuf::FieldDescriptor* fromField = descriptor->field(i);
|
||||
const protobuf::FieldDescriptor* toField = to->GetDescriptor()->FindFieldByName(fromField->name());
|
||||
|
||||
// This will stripped new fields off of intercepted usermessages.
|
||||
// TODO: fix that.
|
||||
if (!toField)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fromField->is_repeated())
|
||||
{
|
||||
int count = from_reflection->FieldSize(from, fromField);
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
switch (fromField->cpp_type())
|
||||
{
|
||||
#define HANDLE_TYPE(CPPTYPE, METHOD) \
|
||||
case protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
||||
to_reflection->Add##METHOD(to, toField, \
|
||||
from_reflection->GetRepeated##METHOD(from, fromField, j)); \
|
||||
break;
|
||||
HANDLE_TYPE(INT32 , Int32 );
|
||||
HANDLE_TYPE(INT64 , Int64 );
|
||||
HANDLE_TYPE(UINT32, UInt32);
|
||||
HANDLE_TYPE(UINT64, UInt64);
|
||||
HANDLE_TYPE(FLOAT , Float );
|
||||
HANDLE_TYPE(DOUBLE, Double);
|
||||
HANDLE_TYPE(BOOL , Bool );
|
||||
HANDLE_TYPE(ENUM , Enum );
|
||||
#undef HANDLE_TYPE
|
||||
case protobuf::FieldDescriptor::CPPTYPE_STRING:
|
||||
{
|
||||
std::string buffer;
|
||||
to_reflection->AddString(to, toField,
|
||||
from_reflection->GetRepeatedStringReference(from, fromField, j, &buffer));
|
||||
}
|
||||
break;
|
||||
case protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
_CopyProtobufMessage(
|
||||
from_reflection->GetRepeatedMessage(from, fromField, j),
|
||||
to_reflection->AddMessage(to, toField)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (fromField->cpp_type())
|
||||
{
|
||||
#define HANDLE_TYPE(CPPTYPE, METHOD) \
|
||||
case protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
||||
to_reflection->Set##METHOD(to, toField, \
|
||||
from_reflection->Get##METHOD(from, fromField)); \
|
||||
break;
|
||||
HANDLE_TYPE(INT32 , Int32 );
|
||||
HANDLE_TYPE(INT64 , Int64 );
|
||||
HANDLE_TYPE(UINT32, UInt32);
|
||||
HANDLE_TYPE(UINT64, UInt64);
|
||||
HANDLE_TYPE(FLOAT , Float );
|
||||
HANDLE_TYPE(DOUBLE, Double);
|
||||
HANDLE_TYPE(BOOL , Bool );
|
||||
HANDLE_TYPE(ENUM , Enum );
|
||||
#undef HANDLE_TYPE
|
||||
case protobuf::FieldDescriptor::CPPTYPE_STRING:
|
||||
{
|
||||
std::string buffer;
|
||||
to_reflection->SetString(to, toField,
|
||||
from_reflection->GetStringReference(from, fromField, &buffer));
|
||||
}
|
||||
break;
|
||||
case protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
_CopyProtobufMessage(
|
||||
from_reflection->GetMessage(from, fromField),
|
||||
to_reflection->MutableMessage(to, toField)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
|
||||
{
|
||||
OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
||||
if (m_FakeMetaRes == MRES_SUPERCEDE)
|
||||
{
|
||||
_CopyProtobufMessage(msg, m_InterceptBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
||||
}
|
||||
|
||||
OnMessageEnd_Pre();
|
||||
if (m_FakeMetaRes == MRES_SUPERCEDE)
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
|
||||
{
|
||||
OnMessageEnd_Post();
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
#define UM_RETURN_META_VALUE(res, val) \
|
||||
m_FakeMetaRes = res; \
|
||||
return val;
|
||||
|
||||
#define UM_RETURN_META(res) \
|
||||
m_FakeMetaRes = res; \
|
||||
return;
|
||||
#else
|
||||
#define UM_RETURN_META_VALUE(res, val) \
|
||||
RETURN_META_VALUE(res, val)
|
||||
|
||||
#define UM_RETURN_META(res) \
|
||||
RETURN_META(res)
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||
#else
|
||||
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type)
|
||||
@ -329,7 +647,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|
||||
|| (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
|
||||
{
|
||||
m_InHook = false;
|
||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
}
|
||||
|
||||
m_CurId = msg_type;
|
||||
@ -339,14 +657,23 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|
||||
|
||||
if (!is_intercept_empty)
|
||||
{
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
if (m_InterceptBuffer)
|
||||
delete m_InterceptBuffer;
|
||||
m_InterceptBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_type)->New();
|
||||
UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer);
|
||||
#else
|
||||
m_InterceptBuffer.Reset();
|
||||
RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
|
||||
UM_RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||
#else
|
||||
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type)
|
||||
@ -354,19 +681,24 @@ bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_ty
|
||||
{
|
||||
if (!m_InHook)
|
||||
{
|
||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
}
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_type)->New();
|
||||
m_OrigBuffer = m_FakeEngineBuffer;
|
||||
#else
|
||||
m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *);
|
||||
#endif
|
||||
|
||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
}
|
||||
|
||||
void UserMessages::OnMessageEnd_Post()
|
||||
{
|
||||
if (!m_InHook)
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
UM_RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
MsgList *pList;
|
||||
@ -434,7 +766,7 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
{
|
||||
if (!m_InHook)
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
UM_RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
MsgList *pList;
|
||||
@ -450,7 +782,11 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
{
|
||||
pInfo = (*iter);
|
||||
pInfo->IsHooked = true;
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
res = pInfo->Callback->InterceptUserMessage(m_CurId, m_InterceptBuffer, m_CurRecFilter);
|
||||
#else
|
||||
res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
|
||||
#endif
|
||||
|
||||
intercepted = true;
|
||||
|
||||
@ -498,8 +834,12 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
|
||||
if (!handled && intercepted)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
|
||||
delete m_InterceptBuffer;
|
||||
m_InterceptBuffer = NULL;
|
||||
#else
|
||||
bf_write *engine_bfw;
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId));
|
||||
#else
|
||||
@ -508,6 +848,7 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
|
||||
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
|
||||
ENGINE_CALL(MessageEnd)();
|
||||
#endif // SE_CSGO
|
||||
}
|
||||
|
||||
pList = &m_msgHooks[m_CurId];
|
||||
@ -529,8 +870,8 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
iter++;
|
||||
}
|
||||
|
||||
RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
|
||||
UM_RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
|
||||
supercede:
|
||||
m_BlockEndPost = true;
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
UM_RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
@ -36,16 +36,35 @@
|
||||
#include <IUserMessages.h>
|
||||
#include "sourcemm_api.h"
|
||||
#include "sm_trie.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "CellRecipientFilter.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
using namespace SourceMod;
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#define USE_PROTOBUF_USERMESSAGES
|
||||
#endif
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <netmessages.pb.h>
|
||||
|
||||
using namespace google;
|
||||
#else
|
||||
#include <bitbuf.h>
|
||||
#endif
|
||||
|
||||
#define INVALID_MESSAGE_ID -1
|
||||
|
||||
struct ListenerInfo
|
||||
{
|
||||
IUserMessageListener *Callback;
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
IProtobufUserMessageListener *Callback;
|
||||
#else
|
||||
IBitBufUserMessageListener *Callback;
|
||||
#endif
|
||||
bool IsHooked;
|
||||
bool KillMe;
|
||||
bool IsNew;
|
||||
@ -70,7 +89,8 @@ public: //IUserMessages
|
||||
bool GetMessageName(int msgid, char *buffer, size_t maxlength) const;
|
||||
bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
|
||||
bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
|
||||
bf_write *StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
|
||||
bf_write *StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
|
||||
google::protobuf::Message *StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
|
||||
bool EndMessage();
|
||||
bool HookUserMessage2(int msg_id,
|
||||
IUserMessageListener *pListener,
|
||||
@ -78,8 +98,17 @@ public: //IUserMessages
|
||||
bool UnhookUserMessage2(int msg_id,
|
||||
IUserMessageListener *pListener,
|
||||
bool intercept=false);
|
||||
UserMessageType GetUserMessageType() const;
|
||||
public:
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
void OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
|
||||
void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||
protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||
bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||
#else
|
||||
@ -89,8 +118,13 @@ public:
|
||||
void OnMessageEnd_Pre();
|
||||
void OnMessageEnd_Post();
|
||||
private:
|
||||
bool InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
bool InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
bool InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
bool InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
#else
|
||||
bool InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
bool InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
#endif
|
||||
void _DecRefCounter();
|
||||
private:
|
||||
List<ListenerInfo *> m_msgHooks[255];
|
||||
@ -98,15 +132,26 @@ private:
|
||||
CStack<ListenerInfo *> m_FreeListeners;
|
||||
unsigned char m_pBase[2500];
|
||||
IRecipientFilter *m_CurRecFilter;
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
bf_write m_InterceptBuffer;
|
||||
bf_write *m_OrigBuffer;
|
||||
bf_read m_ReadBuffer;
|
||||
#else
|
||||
// The engine used to provide this. Now we track it.
|
||||
protobuf::Message *m_OrigBuffer;
|
||||
protobuf::Message *m_FakeEngineBuffer;
|
||||
META_RES m_FakeMetaRes;
|
||||
|
||||
protobuf::Message *m_InterceptBuffer;
|
||||
#endif
|
||||
size_t m_HookCount;
|
||||
bool m_InHook;
|
||||
bool m_BlockEndPost;
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
bool m_FallbackSearch;
|
||||
|
||||
Trie *m_Names;
|
||||
#endif
|
||||
CellRecipientFilter m_CellRecFilter;
|
||||
bool m_InExec;
|
||||
int m_CurFlags;
|
||||
|
@ -29,11 +29,16 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "UserMessages.h"
|
||||
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
|
||||
#include "sourcemod.h"
|
||||
#include "HandleSys.h"
|
||||
#include <bitbuf.h>
|
||||
#include <vector.h>
|
||||
#include <HalfLife2.h>
|
||||
#include "smn_usermsgs.h"
|
||||
|
||||
static cell_t smn_BfWriteBool(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
@ -713,3 +718,5 @@ REGISTER_NATIVES(bitbufnatives)
|
||||
{"BfGetNumBytesLeft", smn_BfGetNumBytesLeft},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -48,6 +48,10 @@
|
||||
#include "ConsoleDetours.h"
|
||||
#include "ConCommandBaseIterator.h"
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#include <netmessages.pb.h>
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE >= SE_EYE
|
||||
#define NETMSG_BITS 6
|
||||
#else
|
||||
@ -1427,10 +1431,22 @@ static cell_t SendConVarValue(IPluginContext *pContext, const cell_t *params)
|
||||
char data[256];
|
||||
bf_write buffer(data, sizeof(data));
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CNETMsg_SetConVar msg;
|
||||
CMsg_CVars_CVar *cvar = msg.mutable_convars()->add_cvars();
|
||||
|
||||
cvar->set_name(pConVar->GetName());
|
||||
cvar->set_value(value);
|
||||
|
||||
buffer.WriteVarInt32(net_SetConVar);
|
||||
buffer.WriteVarInt32(msg.ByteSize());
|
||||
msg.SerializeWithCachedSizesToArray( (uint8 *)( buffer.GetBasePointer() + buffer.GetNumBytesWritten() ) );
|
||||
#else
|
||||
buffer.WriteUBitLong(NET_SETCONVAR, NETMSG_BITS);
|
||||
buffer.WriteByte(1);
|
||||
buffer.WriteString(pConVar->GetName());
|
||||
buffer.WriteString(value);
|
||||
#endif
|
||||
|
||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
|
||||
|
||||
|
@ -37,6 +37,10 @@
|
||||
#include "HandleSys.h"
|
||||
#include "logic_bridge.h"
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#include <game/shared/csgo/protobuf/cstrike15_usermessages.pb.h>
|
||||
#endif
|
||||
|
||||
#define MAX_HUD_CHANNELS 6
|
||||
|
||||
int g_HudMsgNum = -1;
|
||||
@ -308,12 +312,39 @@ static cell_t SetHudTextParamsEx(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
void UTIL_SendHudText(int client, const hud_text_parms &textparms, const char *pMessage)
|
||||
{
|
||||
bf_write *bf;
|
||||
cell_t players[1];
|
||||
|
||||
players[0] = client;
|
||||
|
||||
bf = g_UserMsgs.StartMessage(g_HudMsgNum, players, 1, 0);
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
// If or when we need to support multiple games per engine with this, we can switch to reflection
|
||||
CCSUsrMsg_HudMsg *msg = (CCSUsrMsg_HudMsg *)g_UserMsgs.StartProtobufMessage(g_HudMsgNum, players, 1, 0);
|
||||
msg->set_channel(textparms.channel & 0xFF);
|
||||
|
||||
CMsgVector2D *pos = msg->mutable_pos();
|
||||
pos->set_x(textparms.x);
|
||||
pos->set_y(textparms.y);
|
||||
|
||||
CMsgRGBA *color1 = msg->mutable_clr1();
|
||||
color1->set_r(textparms.r1);
|
||||
color1->set_g(textparms.g1);
|
||||
color1->set_b(textparms.b1);
|
||||
color1->set_a(textparms.a1);
|
||||
|
||||
CMsgRGBA *color2 = msg->mutable_clr2();
|
||||
color2->set_r(textparms.r2);
|
||||
color2->set_g(textparms.g2);
|
||||
color2->set_b(textparms.b2);
|
||||
color2->set_a(textparms.a2);
|
||||
|
||||
msg->set_effect(textparms.effect);
|
||||
msg->set_fade_in_time(textparms.fadeinTime);
|
||||
msg->set_fade_out_time(textparms.fadeoutTime);
|
||||
msg->set_hold_time(textparms.holdTime);
|
||||
msg->set_fx_time(textparms.fxTime);
|
||||
msg->set_text(pMessage);
|
||||
#else
|
||||
bf_write *bf = g_UserMsgs.StartBitBufMessage(g_HudMsgNum, players, 1, 0);
|
||||
bf->WriteByte(textparms.channel & 0xFF );
|
||||
bf->WriteFloat(textparms.x);
|
||||
bf->WriteFloat(textparms.y);
|
||||
@ -331,6 +362,7 @@ void UTIL_SendHudText(int client, const hud_text_parms &textparms, const char *p
|
||||
bf->WriteFloat(textparms.holdTime);
|
||||
bf->WriteFloat(textparms.fxTime);
|
||||
bf->WriteString(pMessage);
|
||||
#endif
|
||||
g_UserMsgs.EndMessage();
|
||||
}
|
||||
|
||||
|
823
core/smn_protobuf.cpp
Normal file
823
core/smn_protobuf.cpp
Normal file
@ -0,0 +1,823 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2013 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "UserMessages.h"
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
|
||||
#include "HandleSys.h"
|
||||
#include "UserMessagePBHelpers.h"
|
||||
#include "smn_usermsgs.h"
|
||||
|
||||
// Assumes pbuf message handle is param 1, gets message as msg
|
||||
#define GET_MSG_FROM_HANDLE_OR_ERR() \
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]); \
|
||||
HandleError herr; \
|
||||
HandleSecurity sec; \
|
||||
SMProtobufMessage *msg; \
|
||||
\
|
||||
sec.pOwner = NULL; \
|
||||
sec.pIdentity = g_pCoreIdent; \
|
||||
\
|
||||
if ((herr=g_HandleSys.ReadHandle(hndl, g_ProtobufType, &sec, (void **)&msg)) \
|
||||
!= HandleError_None) \
|
||||
{ \
|
||||
return pCtx->ThrowNativeError("Invalid protobuf message handle %x (error %d)", hndl, herr); \
|
||||
}
|
||||
|
||||
// Assumes message field name is param 2, gets as strField
|
||||
#define GET_FIELD_NAME_OR_ERR() \
|
||||
int err; \
|
||||
char *strField; \
|
||||
if ((err=pCtx->LocalToString(params[2], &strField)) != SP_ERROR_NONE) \
|
||||
{ \
|
||||
pCtx->ThrowNativeErrorEx(err, NULL); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadInt(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
int ret;
|
||||
if (!msg->GetInt32OrUnsigned(strField, &ret))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadFloat(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
float ret;
|
||||
if (!msg->GetFloatOrDouble(strField, &ret))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return sp_ftoc(ret);
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadBool(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
bool ret;
|
||||
if (!msg->GetBool(strField, &ret))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return ret ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadString(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
char *buf;
|
||||
pCtx->LocalToPhysAddr(params[3], (cell_t **)&buf);
|
||||
|
||||
if (!msg->GetString(strField, buf, params[4]))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadColor(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *out;
|
||||
pCtx->LocalToPhysAddr(params[3], &out);
|
||||
|
||||
Color clr;
|
||||
if (!msg->GetColor(strField, &clr))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
out[0] = clr.r();
|
||||
out[1] = clr.g();
|
||||
out[2] = clr.b();
|
||||
out[3] = clr.a();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadAngle(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *out;
|
||||
pCtx->LocalToPhysAddr(params[3], &out);
|
||||
|
||||
QAngle ang;
|
||||
if (!msg->GetQAngle(strField, &ang))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
out[0] = sp_ftoc(ang.x);
|
||||
out[1] = sp_ftoc(ang.y);
|
||||
out[2] = sp_ftoc(ang.z);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadVector(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *out;
|
||||
pCtx->LocalToPhysAddr(params[3], &out);
|
||||
|
||||
Vector vec;
|
||||
if (!msg->GetVector(strField, &vec))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
out[0] = sp_ftoc(vec.x);
|
||||
out[1] = sp_ftoc(vec.y);
|
||||
out[2] = sp_ftoc(vec.z);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadVector2D(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *out;
|
||||
pCtx->LocalToPhysAddr(params[3], &out);
|
||||
|
||||
Vector2D vec;
|
||||
if (!msg->GetVector2D(strField, &vec))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
out[0] = sp_ftoc(vec.x);
|
||||
out[1] = sp_ftoc(vec.y);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbGetRepeatedFieldCount(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
int cnt = msg->GetRepeatedFieldCount(strField);
|
||||
if (cnt == -1)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadRepeatedInt(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
int ret;
|
||||
if (!msg->GetRepeatedInt32OrUnsigned(strField, params[3], &ret))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadRepeatedFloat(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
float ret;
|
||||
if (!msg->GetRepeatedFloatOrDouble(strField, params[3], &ret))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return sp_ftoc(ret);
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadRepeatedBool(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
bool ret;
|
||||
if (!msg->GetRepeatedBool(strField, params[3], &ret))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return ret ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadRepeatedString(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
char *buf;
|
||||
pCtx->LocalToPhysAddr(params[4], (cell_t **)&buf);
|
||||
|
||||
if (!msg->GetRepeatedString(strField, params[3], buf, params[5]))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadRepeatedColor(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *out;
|
||||
pCtx->LocalToPhysAddr(params[4], &out);
|
||||
|
||||
Color clr;
|
||||
if (!msg->GetRepeatedColor(strField, params[3], &clr))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
out[0] = clr.r();
|
||||
out[1] = clr.g();
|
||||
out[2] = clr.b();
|
||||
out[3] = clr.a();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadRepeatedAngle(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *out;
|
||||
pCtx->LocalToPhysAddr(params[4], &out);
|
||||
|
||||
QAngle ang;
|
||||
if (!msg->GetRepeatedQAngle(strField, params[3], &ang))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
out[0] = sp_ftoc(ang.x);
|
||||
out[1] = sp_ftoc(ang.y);
|
||||
out[2] = sp_ftoc(ang.z);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadRepeatedVector(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *out;
|
||||
pCtx->LocalToPhysAddr(params[4], &out);
|
||||
|
||||
Vector vec;
|
||||
if (!msg->GetRepeatedVector(strField, params[3], &vec))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
out[0] = sp_ftoc(vec.x);
|
||||
out[1] = sp_ftoc(vec.y);
|
||||
out[2] = sp_ftoc(vec.z);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadRepeatedVector2D(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *out;
|
||||
pCtx->LocalToPhysAddr(params[4], &out);
|
||||
|
||||
Vector2D vec;
|
||||
if (!msg->GetRepeatedVector2D(strField, params[3], &vec))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
out[0] = sp_ftoc(vec.x);
|
||||
out[1] = sp_ftoc(vec.y);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbSetInt(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
if (!msg->SetInt32OrUnsigned(strField, params[3]))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbSetFloat(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
if (!msg->SetFloatOrDouble(strField, sp_ctof(params[3])))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbSetBool(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
bool value = (params[3] == 0 ? false : true);
|
||||
if (!msg->SetBool(strField, value))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbSetString(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
char *strValue;
|
||||
if ((err=pCtx->LocalToString(params[3], &strValue)) != SP_ERROR_NONE)
|
||||
{
|
||||
pCtx->ThrowNativeErrorEx(err, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!msg->SetString(strField, strValue))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbSetColor(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *clrParams;
|
||||
if ((err=pCtx->LocalToPhysAddr(params[3], &clrParams)) != SP_ERROR_NONE)
|
||||
{
|
||||
pCtx->ThrowNativeErrorEx(err, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Color clr(
|
||||
clrParams[0],
|
||||
clrParams[1],
|
||||
clrParams[2],
|
||||
clrParams[3]);
|
||||
|
||||
if (!msg->SetColor(strField, clr))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbSetAngle(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *angParams;
|
||||
if ((err=pCtx->LocalToPhysAddr(params[3], &angParams)) != SP_ERROR_NONE)
|
||||
{
|
||||
pCtx->ThrowNativeErrorEx(err, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
QAngle ang(
|
||||
sp_ctof(angParams[0]),
|
||||
sp_ctof(angParams[1]),
|
||||
sp_ctof(angParams[2]));
|
||||
|
||||
if (!msg->SetQAngle(strField, ang))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbSetVector(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *vecParams;
|
||||
if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
|
||||
{
|
||||
pCtx->ThrowNativeErrorEx(err, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Vector vec(
|
||||
sp_ctof(vecParams[0]),
|
||||
sp_ctof(vecParams[1]),
|
||||
sp_ctof(vecParams[2]));
|
||||
|
||||
if (!msg->SetVector(strField, vec))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbSetVector2D(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *vecParams;
|
||||
if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
|
||||
{
|
||||
pCtx->ThrowNativeErrorEx(err, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Vector2D vec(
|
||||
sp_ctof(vecParams[0]),
|
||||
sp_ctof(vecParams[1]));
|
||||
|
||||
if (!msg->SetVector2D(strField, vec))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbAddInt(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
if (!msg->AddInt32OrUnsigned(strField, params[3]))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbAddFloat(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
if (!msg->AddFloatOrDouble(strField, sp_ctof(params[3])))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbAddBool(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
bool value = (params[3] == 0 ? false : true);
|
||||
if (!msg->AddBool(strField, value))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbAddString(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
char *strValue;
|
||||
if ((err=pCtx->LocalToString(params[3], &strValue)) != SP_ERROR_NONE)
|
||||
{
|
||||
pCtx->ThrowNativeErrorEx(err, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!msg->AddString(strField, strValue))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbAddColor(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *clrParams;
|
||||
if ((err=pCtx->LocalToPhysAddr(params[3], &clrParams)) != SP_ERROR_NONE)
|
||||
{
|
||||
pCtx->ThrowNativeErrorEx(err, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Color clr(
|
||||
clrParams[0],
|
||||
clrParams[1],
|
||||
clrParams[2],
|
||||
clrParams[3]);
|
||||
|
||||
if (!msg->AddColor(strField, clr))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbAddAngle(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *angParams;
|
||||
if ((err=pCtx->LocalToPhysAddr(params[3], &angParams)) != SP_ERROR_NONE)
|
||||
{
|
||||
pCtx->ThrowNativeErrorEx(err, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
QAngle ang(
|
||||
sp_ctof(angParams[0]),
|
||||
sp_ctof(angParams[1]),
|
||||
sp_ctof(angParams[2]));
|
||||
|
||||
if (!msg->AddQAngle(strField, ang))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbAddVector(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *vecParams;
|
||||
if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
|
||||
{
|
||||
pCtx->ThrowNativeErrorEx(err, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Vector vec(
|
||||
sp_ctof(vecParams[0]),
|
||||
sp_ctof(vecParams[1]),
|
||||
sp_ctof(vecParams[2]));
|
||||
|
||||
if (!msg->AddVector(strField, vec))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbAddVector2D(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
cell_t *vecParams;
|
||||
if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
|
||||
{
|
||||
pCtx->ThrowNativeErrorEx(err, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Vector2D vec(
|
||||
sp_ctof(vecParams[0]),
|
||||
sp_ctof(vecParams[1]));
|
||||
|
||||
if (!msg->AddVector2D(strField, vec))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadMessage(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
protobuf::Message *innerMsg;
|
||||
if (!msg->GetMessage(strField, &innerMsg))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
Handle_t outHndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(innerMsg), NULL, g_pCoreIdent, NULL);
|
||||
msg->AddChildHandle(outHndl);
|
||||
|
||||
return outHndl;
|
||||
}
|
||||
|
||||
static cell_t smn_PbReadRepeatedMessage(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
const protobuf::Message *innerMsg;
|
||||
if (!msg->GetRepeatedMessage(strField, params[3], &innerMsg))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
Handle_t outHndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(const_cast<protobuf::Message *>(innerMsg)), NULL, g_pCoreIdent, NULL);
|
||||
msg->AddChildHandle(outHndl);
|
||||
|
||||
return outHndl;
|
||||
}
|
||||
|
||||
static cell_t smn_PbAddMessage(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
GET_MSG_FROM_HANDLE_OR_ERR();
|
||||
GET_FIELD_NAME_OR_ERR();
|
||||
|
||||
protobuf::Message *innerMsg;
|
||||
if (!msg->AddMessage(strField, &innerMsg))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
|
||||
}
|
||||
|
||||
Handle_t outHndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(innerMsg), NULL, g_pCoreIdent, NULL);
|
||||
msg->AddChildHandle(outHndl);
|
||||
|
||||
return outHndl;
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(protobufnatives)
|
||||
{
|
||||
{"PbReadInt", smn_PbReadInt},
|
||||
{"PbReadFloat", smn_PbReadFloat},
|
||||
{"PbReadBool", smn_PbReadBool},
|
||||
{"PbReadString", smn_PbReadString},
|
||||
{"PbReadColor", smn_PbReadColor},
|
||||
{"PbReadAngle", smn_PbReadAngle},
|
||||
{"PbReadVector", smn_PbReadVector},
|
||||
{"PbReadVector2D", smn_PbReadVector2D},
|
||||
{"PbGetRepeatedFieldCount", smn_PbGetRepeatedFieldCount},
|
||||
{"PbReadRepeatedInt", smn_PbReadRepeatedInt},
|
||||
{"PbReadRepeatedFloat", smn_PbReadRepeatedFloat},
|
||||
{"PbReadRepeatedBool", smn_PbReadRepeatedBool},
|
||||
{"PbReadRepeatedString", smn_PbReadRepeatedString},
|
||||
{"PbReadRepeatedColor", smn_PbReadRepeatedColor},
|
||||
{"PbReadRepeatedAngle", smn_PbReadRepeatedAngle},
|
||||
{"PbReadRepeatedVector", smn_PbReadRepeatedVector},
|
||||
{"PbReadRepeatedVector2D", smn_PbReadRepeatedVector2D},
|
||||
{"PbSetInt", smn_PbSetInt},
|
||||
{"PbSetFloat", smn_PbSetFloat},
|
||||
{"PbSetBool", smn_PbSetBool},
|
||||
{"PbSetString", smn_PbSetString},
|
||||
{"PbSetColor", smn_PbSetColor},
|
||||
{"PbSetAngle", smn_PbSetAngle},
|
||||
{"PbSetVector", smn_PbSetVector},
|
||||
{"PbSetVector2D", smn_PbSetVector2D},
|
||||
{"PbAddInt", smn_PbAddInt},
|
||||
{"PbAddFloat", smn_PbAddFloat},
|
||||
{"PbAddBool", smn_PbAddBool},
|
||||
{"PbAddString", smn_PbAddString},
|
||||
{"PbAddColor", smn_PbAddColor},
|
||||
{"PbAddAngle", smn_PbAddAngle},
|
||||
{"PbAddVector", smn_PbAddVector},
|
||||
{"PbAddVector2D", smn_PbAddVector2D},
|
||||
{"PbReadMessage", smn_PbReadMessage},
|
||||
{"PbReadRepeatedMessage", smn_PbReadRepeatedMessage},
|
||||
{"PbAddMessage", smn_PbAddMessage},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@ @@@@@@@@@@@@@
|
||||
@@@@@@@@ @@@@@@@@@@@@@
|
||||
@@@@@@ @@@@@@@@@@@@@@@
|
||||
0000 @@@@@@@@@@@@@@@@@@@@@
|
||||
000000000 @@@@@@@@@@@@@@@@@@@
|
||||
0000000000000000000 @@@@@@@@@@@@@@@
|
||||
00000000000000000000 @@@@@@@@@@@@@@@
|
||||
000000000 @@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@ @@@@
|
||||
@@@@@@@@@@@@@@@@@@@ @@@@@@@
|
||||
@@@ @@@@ @@@ @@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@ @@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@ @@@@@@@@ @@ @@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ @@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@ @@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@ @@@@ @@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@ @@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@ @@@@ @@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@ @@@ @@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@ @@@@@@ @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ @@@@ @@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@ @@@@@@ @@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@ @@@@@ @@@@@@
|
||||
@@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@ @@ @@@@@ @@@@@@@@
|
||||
@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@ @@@@@@ @@@@ @@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ @@@@@@ @@@@@@ @@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ @@@@@@@@ @@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@ @ @@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@ @@@@@ @@@@ ////
|
||||
//////////// @@@@@@@@@@@ @@@@@@ @@@@@@@@@@@@@@@@@@@@ @@ @@@@@@@@@ @@@@ //// ////////////
|
||||
///////////////// /// @@@@@ @@@@ @@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@ @@@@ ///// /////// /////////
|
||||
///////////////////// ///// @@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@ @@@@@@@ @ @@@@ ////// /////// ///////////////
|
||||
///////////////////////// /////// @@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@ @@@@@ @@@@ ////// //////// ////////////////////
|
||||
//////////////////////////// ////////// @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@ @@@ ////// ////////// ////////////////////////
|
||||
//////////////////// ////////// /////////// @@@@@@@@@@@@@@@@@ @@@@@@@@ @@@ @@@@@@ ////// //////////// //////////////////////////
|
||||
//////////////////// //////////// /////////// @@@@@@@@@@@@@@@@ @@@@ ///////////////////// /////////////////////////////
|
||||
///////////////////// ////////////// ////// @@@@@@@@@ ///////////////////////////////////////////////////////////
|
||||
//////////////////// ///////////////////////////////////// ///////////////////////////////////////////////////////////////////////
|
||||
///////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////
|
||||
*/
|
||||
#endif // USE_PROTOBUF_USERMESSAGES
|
@ -31,15 +31,22 @@
|
||||
|
||||
#include "HandleSys.h"
|
||||
#include "PluginSys.h"
|
||||
#include "UserMessages.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "smn_usermsgs.h"
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
#include "UserMessagePBHelpers.h"
|
||||
#endif
|
||||
|
||||
HandleType_t g_ProtobufType = NO_HANDLE_TYPE;
|
||||
HandleType_t g_WrBitBufType = NO_HANDLE_TYPE;
|
||||
HandleType_t g_RdBitBufType = NO_HANDLE_TYPE;
|
||||
|
||||
HandleType_t g_WrBitBufType;
|
||||
HandleType_t g_RdBitBufType;
|
||||
Handle_t g_CurMsgHandle;
|
||||
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
Handle_t g_ReadBufHandle;
|
||||
bf_read g_ReadBitBuf;
|
||||
#endif
|
||||
|
||||
int g_MsgPlayers[256];
|
||||
bool g_IsMsgInExec = false;
|
||||
@ -85,10 +92,14 @@ void UsrMessageNatives::OnSourceModAllInitialized()
|
||||
g_HandleSys.InitAccessDefaults(NULL, &sec);
|
||||
sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY;
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
g_ProtobufType = g_HandleSys.CreateType("ProtobufUM", this, 0, NULL, NULL, g_pCoreIdent, NULL);
|
||||
#else
|
||||
g_WrBitBufType = g_HandleSys.CreateType("BitBufWriter", this, 0, NULL, NULL, g_pCoreIdent, NULL);
|
||||
g_RdBitBufType = g_HandleSys.CreateType("BitBufReader", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
||||
|
||||
g_ReadBufHandle = g_HandleSys.CreateHandle(g_RdBitBufType, &g_ReadBitBuf, NULL, g_pCoreIdent, NULL);
|
||||
#endif
|
||||
|
||||
g_PluginSys.AddPluginsListener(this);
|
||||
}
|
||||
@ -98,6 +109,11 @@ void UsrMessageNatives::OnSourceModShutdown()
|
||||
HandleSecurity sec;
|
||||
sec.pIdentity = g_pCoreIdent;
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
g_HandleSys.RemoveType(g_ProtobufType, g_pCoreIdent);
|
||||
|
||||
g_ProtobufType = 0;
|
||||
#else
|
||||
g_HandleSys.FreeHandle(g_ReadBufHandle, &sec);
|
||||
|
||||
g_HandleSys.RemoveType(g_WrBitBufType, g_pCoreIdent);
|
||||
@ -105,15 +121,24 @@ void UsrMessageNatives::OnSourceModShutdown()
|
||||
|
||||
g_WrBitBufType = 0;
|
||||
g_RdBitBufType = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void UsrMessageNatives::OnHandleDestroy(HandleType_t type, void *object)
|
||||
{
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
delete (SMProtobufMessage *)object;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UsrMessageNatives::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
|
||||
{
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
// Different messages have different sizes, but this works as an approximate
|
||||
*pSize = sizeof(protobuf::Message) + sizeof(SMProtobufMessage);
|
||||
#else
|
||||
*pSize = sizeof(bf_read);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -275,37 +300,69 @@ IPluginFunction *MsgListenerWrapper::GetNotifyFunction() const
|
||||
return m_Notify;
|
||||
}
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
void MsgListenerWrapper::OnUserMessage(int msg_id, protobuf::Message *msg, IRecipientFilter *pFilter)
|
||||
#else
|
||||
void MsgListenerWrapper::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
||||
#endif
|
||||
{
|
||||
cell_t res;
|
||||
Handle_t hndl;
|
||||
size_t size = _FillInPlayers(g_MsgPlayers, pFilter);
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
hndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(msg), NULL, g_pCoreIdent, NULL);
|
||||
#else
|
||||
g_ReadBitBuf.StartReading(bf->GetBasePointer(), bf->GetNumBytesWritten());
|
||||
hndl = g_ReadBufHandle;
|
||||
#endif
|
||||
|
||||
m_Hook->PushCell(msg_id);
|
||||
m_Hook->PushCell(g_ReadBufHandle);
|
||||
m_Hook->PushCell(hndl);
|
||||
m_Hook->PushArray(g_MsgPlayers, size);
|
||||
m_Hook->PushCell(size);
|
||||
m_Hook->PushCell(pFilter->IsReliable());
|
||||
m_Hook->PushCell(pFilter->IsInitMessage());
|
||||
m_Hook->Execute(&res);
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
HandleSecurity sec;
|
||||
sec.pIdentity = g_pCoreIdent;
|
||||
g_HandleSys.FreeHandle(hndl, &sec);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
ResultType MsgListenerWrapper::InterceptUserMessage(int msg_id, protobuf::Message *msg, IRecipientFilter *pFilter)
|
||||
#else
|
||||
ResultType MsgListenerWrapper::InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
||||
#endif
|
||||
{
|
||||
Handle_t hndl;
|
||||
cell_t res = static_cast<cell_t>(Pl_Continue);
|
||||
size_t size = _FillInPlayers(g_MsgPlayers, pFilter);
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
hndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(msg), NULL, g_pCoreIdent, NULL);
|
||||
#else
|
||||
g_ReadBitBuf.StartReading(bf->GetBasePointer(), bf->GetNumBytesWritten());
|
||||
hndl = g_ReadBufHandle;
|
||||
#endif
|
||||
|
||||
m_Intercept->PushCell(msg_id);
|
||||
m_Intercept->PushCell(g_ReadBufHandle);
|
||||
m_Intercept->PushCell(hndl);
|
||||
m_Intercept->PushArray(g_MsgPlayers, size);
|
||||
m_Intercept->PushCell(size);
|
||||
m_Intercept->PushCell(pFilter->IsReliable());
|
||||
m_Intercept->PushCell(pFilter->IsInitMessage());
|
||||
m_Intercept->Execute(&res);
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
HandleSecurity sec;
|
||||
sec.pIdentity = g_pCoreIdent;
|
||||
g_HandleSys.FreeHandle(hndl, &sec);
|
||||
#endif
|
||||
|
||||
return static_cast<ResultType>(res);
|
||||
}
|
||||
|
||||
@ -330,6 +387,11 @@ void MsgListenerWrapper::OnPostUserMessage(int msg_id, bool sent)
|
||||
|
||||
static UsrMessageNatives s_UsrMessageNatives;
|
||||
|
||||
static cell_t smn_GetUserMessageType(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
return g_UserMsgs.GetUserMessageType();
|
||||
}
|
||||
|
||||
static cell_t smn_GetUserMessageId(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
char *msgname;
|
||||
@ -353,7 +415,6 @@ static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params)
|
||||
cell_t *cl_array;
|
||||
unsigned int numClients;
|
||||
int msgid;
|
||||
bf_write *pBitBuf;
|
||||
int client;
|
||||
CPlayer *pPlayer = NULL;
|
||||
|
||||
@ -387,13 +448,24 @@ static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params)
|
||||
}
|
||||
}
|
||||
|
||||
pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, numClients, params[4]);
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
protobuf::Message *msg = g_UserMsgs.StartProtobufMessage(msgid, cl_array, numClients, params[4]);
|
||||
if (!msg)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
|
||||
}
|
||||
|
||||
g_CurMsgHandle = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(msg), pCtx->GetIdentity(), g_pCoreIdent, NULL);
|
||||
#else
|
||||
bf_write *pBitBuf = g_UserMsgs.StartBitBufMessage(msgid, cl_array, numClients, params[4]);
|
||||
if (!pBitBuf)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
|
||||
}
|
||||
|
||||
g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
|
||||
#endif
|
||||
|
||||
g_IsMsgInExec = true;
|
||||
|
||||
return g_CurMsgHandle;
|
||||
@ -403,7 +475,6 @@ static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
cell_t *cl_array;
|
||||
unsigned int numClients;
|
||||
bf_write *pBitBuf;
|
||||
int client;
|
||||
CPlayer *pPlayer = NULL;
|
||||
int msgid = params[1];
|
||||
@ -436,13 +507,23 @@ static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params)
|
||||
}
|
||||
}
|
||||
|
||||
pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, numClients, params[4]);
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
protobuf::Message *msg = g_UserMsgs.StartProtobufMessage(msgid, cl_array, numClients, params[4]);
|
||||
if (!msg)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
|
||||
}
|
||||
|
||||
g_CurMsgHandle = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(msg), pCtx->GetIdentity(), g_pCoreIdent, NULL);
|
||||
#else
|
||||
bf_write *pBitBuf = g_UserMsgs.StartBitBufMessage(msgid, cl_array, numClients, params[4]);
|
||||
if (!pBitBuf)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
|
||||
}
|
||||
|
||||
g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
|
||||
#endif
|
||||
g_IsMsgInExec = true;
|
||||
|
||||
return g_CurMsgHandle;
|
||||
@ -534,6 +615,7 @@ static cell_t smn_UnhookUserMessage(IPluginContext *pCtx, const cell_t *params)
|
||||
|
||||
REGISTER_NATIVES(usrmsgnatives)
|
||||
{
|
||||
{"GetUserMessageType", smn_GetUserMessageType},
|
||||
{"GetUserMessageId", smn_GetUserMessageId},
|
||||
{"GetUserMessageName", smn_GetUserMessageName},
|
||||
{"StartMessage", smn_StartMessage},
|
||||
|
@ -32,9 +32,14 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_CMSGLISTENERWRAPPER_H_
|
||||
#define _INCLUDE_SOURCEMOD_CMSGLISTENERWRAPPER_H_
|
||||
|
||||
extern int g_MsgPlayers[256];
|
||||
#include "UserMessages.h"
|
||||
|
||||
class MsgListenerWrapper : public IUserMessageListener
|
||||
class MsgListenerWrapper
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
: public IProtobufUserMessageListener
|
||||
#else
|
||||
: public IBitBufUserMessageListener
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
void Initialize(int msgid, IPluginFunction *hook, IPluginFunction *notify, bool intercept);
|
||||
@ -43,8 +48,13 @@ public:
|
||||
IPluginFunction *GetHookedFunction() const;
|
||||
IPluginFunction *GetNotifyFunction() const;
|
||||
public: //IUserMessageListener
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
void OnUserMessage(int msg_id, protobuf::Message *msg, IRecipientFilter *pFilter);
|
||||
ResultType InterceptUserMessage(int msg_id, protobuf::Message *msg, IRecipientFilter *pFilter);
|
||||
#else
|
||||
void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
|
||||
ResultType InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
|
||||
#endif
|
||||
void OnPostUserMessage(int msg_id, bool sent);
|
||||
private:
|
||||
size_t _FillInPlayers(int *pl_array, IRecipientFilter *pFilter);
|
||||
@ -56,4 +66,8 @@ private:
|
||||
int m_MsgId;
|
||||
};
|
||||
|
||||
extern HandleType_t g_WrBitBufType;
|
||||
extern HandleType_t g_RdBitBufType;
|
||||
extern HandleType_t g_ProtobufType;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_CMSGLISTENERWRAPPER_H_
|
||||
|
@ -152,7 +152,5 @@ private:
|
||||
extern bool g_Loaded;
|
||||
extern bool sm_show_debug_spew;
|
||||
extern SourceModBase g_SourceMod;
|
||||
extern HandleType_t g_WrBitBufType; //:TODO: find a better place for this
|
||||
extern HandleType_t g_RdBitBufType; //:TODO: find a better place for this
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_GLOBALHEADER_H_
|
||||
|
@ -38,23 +38,39 @@ PerformBlind(client, target, amount)
|
||||
new targets[2];
|
||||
targets[0] = target;
|
||||
|
||||
new Handle:message = StartMessageEx(g_FadeUserMsgId, targets, 1);
|
||||
BfWriteShort(message, 1536);
|
||||
BfWriteShort(message, 1536);
|
||||
|
||||
new duration = 1536;
|
||||
new holdtime = 1536;
|
||||
new flags;
|
||||
if (amount == 0)
|
||||
{
|
||||
BfWriteShort(message, (0x0001 | 0x0010));
|
||||
flags = (0x0001 | 0x0010);
|
||||
}
|
||||
else
|
||||
{
|
||||
BfWriteShort(message, (0x0002 | 0x0008));
|
||||
flags = (0x0002 | 0x0008);
|
||||
}
|
||||
|
||||
BfWriteByte(message, 0);
|
||||
BfWriteByte(message, 0);
|
||||
BfWriteByte(message, 0);
|
||||
BfWriteByte(message, amount);
|
||||
new color[4] = { 0, 0, 0, 0 };
|
||||
color[3] = amount;
|
||||
|
||||
new Handle:message = StartMessageEx(g_FadeUserMsgId, targets, 1);
|
||||
if (GetUserMessageType() == UM_Protobuf)
|
||||
{
|
||||
PbSetInt(message, "duration", duration);
|
||||
PbSetInt(message, "hold_time", holdtime);
|
||||
PbSetInt(message, "flags", flags);
|
||||
PbSetColor(message, "clr", color);
|
||||
}
|
||||
else
|
||||
{
|
||||
BfWriteShort(message, duration);
|
||||
BfWriteShort(message, holdtime);
|
||||
BfWriteShort(message, flags);
|
||||
BfWriteByte(message, color[0]);
|
||||
BfWriteByte(message, color[1]);
|
||||
BfWriteByte(message, color[2]);
|
||||
BfWriteByte(message, color[3]);
|
||||
}
|
||||
|
||||
EndMessage();
|
||||
|
||||
|
@ -51,17 +51,34 @@ KillDrug(client)
|
||||
TeleportEntity(client, NULL_VECTOR, angs, NULL_VECTOR);
|
||||
|
||||
new clients[2];
|
||||
clients[0] = client;
|
||||
|
||||
clients[0] = client;
|
||||
|
||||
new duration = 1536;
|
||||
new holdtime = 1536;
|
||||
new flags = (0x0001 | 0x0010);
|
||||
new color[4] = { 0, 0, 0, 0 };
|
||||
|
||||
new Handle:message = StartMessageEx(g_FadeUserMsgId, clients, 1);
|
||||
BfWriteShort(message, 1536);
|
||||
BfWriteShort(message, 1536);
|
||||
BfWriteShort(message, (0x0001 | 0x0010));
|
||||
BfWriteByte(message, 0);
|
||||
BfWriteByte(message, 0);
|
||||
BfWriteByte(message, 0);
|
||||
BfWriteByte(message, 0);
|
||||
EndMessage();
|
||||
|
||||
if (GetUserMessageType() == UM_Protobuf)
|
||||
{
|
||||
PbSetInt(message, "duration", duration);
|
||||
PbSetInt(message, "hold_time", holdtime);
|
||||
PbSetInt(message, "flags", flags);
|
||||
PbSetColor(message, "clr", color);
|
||||
}
|
||||
else
|
||||
{
|
||||
BfWriteShort(message, duration);
|
||||
BfWriteShort(message, holdtime);
|
||||
BfWriteShort(message, flags);
|
||||
BfWriteByte(message, color[0]);
|
||||
BfWriteByte(message, color[1]);
|
||||
BfWriteByte(message, color[2]);
|
||||
BfWriteByte(message, color[3]);
|
||||
}
|
||||
|
||||
EndMessage();
|
||||
}
|
||||
|
||||
KillDrugTimer(client)
|
||||
@ -152,16 +169,35 @@ public Action:Timer_Drug(Handle:timer, any:client)
|
||||
new clients[2];
|
||||
clients[0] = client;
|
||||
|
||||
new duration = 255;
|
||||
new holdtime = 255;
|
||||
new flags = 0x0002;
|
||||
new color[4] = { 0, 0, 0, 128 };
|
||||
color[0] = GetRandomInt(0,255);
|
||||
color[1] = GetRandomInt(0,255);
|
||||
color[2] = GetRandomInt(0,255);
|
||||
|
||||
new Handle:message = StartMessageEx(g_FadeUserMsgId, clients, 1);
|
||||
BfWriteShort(message, 255);
|
||||
BfWriteShort(message, 255);
|
||||
BfWriteShort(message, (0x0002));
|
||||
BfWriteByte(message, GetRandomInt(0,255));
|
||||
BfWriteByte(message, GetRandomInt(0,255));
|
||||
BfWriteByte(message, GetRandomInt(0,255));
|
||||
BfWriteByte(message, 128);
|
||||
|
||||
EndMessage();
|
||||
if (GetUserMessageType() == UM_Protobuf)
|
||||
{
|
||||
PbSetInt(message, "duration", duration);
|
||||
PbSetInt(message, "hold_time", holdtime);
|
||||
PbSetInt(message, "flags", flags);
|
||||
PbSetColor(message, "clr", color);
|
||||
}
|
||||
else
|
||||
{
|
||||
BfWriteShort(message, duration);
|
||||
BfWriteShort(message, holdtime);
|
||||
BfWriteShort(message, flags);
|
||||
BfWriteByte(message, color[0]);
|
||||
BfWriteByte(message, color[1]);
|
||||
BfWriteByte(message, color[2]);
|
||||
BfWriteByte(message, color[3]);
|
||||
}
|
||||
|
||||
EndMessage();
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
@ -167,6 +167,67 @@ public __ext_core_SetNTVOptional()
|
||||
MarkNativeAsOptional("RequireFeature");
|
||||
MarkNativeAsOptional("AddCommandListener");
|
||||
MarkNativeAsOptional("RemoveCommandListener");
|
||||
|
||||
MarkNativeAsOptional("BfWriteBool");
|
||||
MarkNativeAsOptional("BfWriteByte");
|
||||
MarkNativeAsOptional("BfWriteChar");
|
||||
MarkNativeAsOptional("BfWriteShort");
|
||||
MarkNativeAsOptional("BfWriteWord");
|
||||
MarkNativeAsOptional("BfWriteNum");
|
||||
MarkNativeAsOptional("BfWriteFloat");
|
||||
MarkNativeAsOptional("BfWriteString");
|
||||
MarkNativeAsOptional("BfWriteEntity");
|
||||
MarkNativeAsOptional("BfWriteAngle");
|
||||
MarkNativeAsOptional("BfWriteCoord");
|
||||
MarkNativeAsOptional("BfWriteVecCoord");
|
||||
MarkNativeAsOptional("BfWriteVecNormal");
|
||||
MarkNativeAsOptional("BfWriteAngles");
|
||||
MarkNativeAsOptional("BfReadBool");
|
||||
MarkNativeAsOptional("BfReadByte");
|
||||
MarkNativeAsOptional("BfReadChar");
|
||||
MarkNativeAsOptional("BfReadShort");
|
||||
MarkNativeAsOptional("BfReadWord");
|
||||
MarkNativeAsOptional("BfReadNum");
|
||||
MarkNativeAsOptional("BfReadFloat");
|
||||
MarkNativeAsOptional("BfReadString");
|
||||
MarkNativeAsOptional("BfReadEntity");
|
||||
MarkNativeAsOptional("BfReadAngle");
|
||||
MarkNativeAsOptional("BfReadCoord");
|
||||
MarkNativeAsOptional("BfReadVecCoord");
|
||||
MarkNativeAsOptional("BfReadVecNormal");
|
||||
MarkNativeAsOptional("BfReadAngles");
|
||||
MarkNativeAsOptional("BfGetNumBytesLeft");
|
||||
|
||||
MarkNativeAsOptional("PbReadInt");
|
||||
MarkNativeAsOptional("PbReadFloat");
|
||||
MarkNativeAsOptional("PbReadString");
|
||||
MarkNativeAsOptional("PbReadColor");
|
||||
MarkNativeAsOptional("PbReadAngle");
|
||||
MarkNativeAsOptional("PbReadVector");
|
||||
MarkNativeAsOptional("PbReadVector2D");
|
||||
MarkNativeAsOptional("PbGetRepeatedFieldCount");
|
||||
MarkNativeAsOptional("PbReadRepeatedInt");
|
||||
MarkNativeAsOptional("PbReadRepeatedFloat");
|
||||
MarkNativeAsOptional("PbReadRepeatedString");
|
||||
MarkNativeAsOptional("PbReadRepeatedColor");
|
||||
MarkNativeAsOptional("PbReadRepeatedAngle");
|
||||
MarkNativeAsOptional("PbReadRepeatedVector");
|
||||
MarkNativeAsOptional("PbReadRepeatedVector2D");
|
||||
MarkNativeAsOptional("PbSetInt");
|
||||
MarkNativeAsOptional("PbSetFloat");
|
||||
MarkNativeAsOptional("PbSetString");
|
||||
MarkNativeAsOptional("PbSetColor");
|
||||
MarkNativeAsOptional("PbSetAngle");
|
||||
MarkNativeAsOptional("PbSetVector");
|
||||
MarkNativeAsOptional("PbSetVector2D");
|
||||
MarkNativeAsOptional("PbAddInt");
|
||||
MarkNativeAsOptional("PbAddFloat");
|
||||
MarkNativeAsOptional("PbAddString");
|
||||
MarkNativeAsOptional("PbAddColor");
|
||||
MarkNativeAsOptional("PbAddAngle");
|
||||
MarkNativeAsOptional("PbAddVector");
|
||||
MarkNativeAsOptional("PbAddVector2D");
|
||||
|
||||
VerifyCoreVersion();
|
||||
}
|
||||
|
||||
|
433
plugins/include/protobuf.inc
Normal file
433
plugins/include/protobuf.inc
Normal file
@ -0,0 +1,433 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod (C)2013 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This file is part of the SourceMod/SourcePawn SDK.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#if defined _protobuf_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _protobuf_included
|
||||
|
||||
/**
|
||||
* Reads an int32, uint32, sint32, fixed32, or sfixed32 from a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @return Integer value read.
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbReadInt(Handle:pb, const String:field[]);
|
||||
|
||||
/**
|
||||
* Reads a float or downcasted double from a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @return Float value read.
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native Float:PbReadFloat(Handle:pb, const String:field[]);
|
||||
|
||||
/**
|
||||
* Reads a bool from a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @return Boolean value read.
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native bool:PbReadBool(Handle:pb, const String:field[]);
|
||||
|
||||
/**
|
||||
* Reads a string from a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param buffer Destination string buffer.
|
||||
* @param maxlength Maximum length of output string buffer.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbReadString(Handle:pb, const String:field[], String:buffer[], maxlength);
|
||||
|
||||
/**
|
||||
* Reads an RGBA color value from a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param buffer Destination color buffer.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbReadColor(Handle:pb, const String:field[], buffer[4]);
|
||||
|
||||
/**
|
||||
* Reads an XYZ angle value from a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param buffer Destination angle buffer.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbReadAngle(Handle:pb, const String:field[], Float:buffer[3]);
|
||||
|
||||
/**
|
||||
* Reads an XYZ vector value from a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param buffer Destination vector buffer.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbReadVector(Handle:pb, const String:field[], Float:buffer[3]);
|
||||
|
||||
/**
|
||||
* Reads an XY vector value from a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param buffer Destination vector buffer.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbReadVector2D(Handle:pb, const String:field[], Float:buffer[2]);
|
||||
|
||||
/**
|
||||
* Gets the number of elements in a repeated field of a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @return Number of elements in the field.
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbGetRepeatedFieldCount(Handle:pb, const String:field[]);
|
||||
|
||||
/**
|
||||
* Reads an int32, uint32, sint32, fixed32, or sfixed32 from a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param index Index in the repeated field.
|
||||
* @return Integer value read.
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbReadRepeatedInt(Handle:pb, const String:field[], index);
|
||||
|
||||
/**
|
||||
* Reads a float or downcasted double from a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param index Index in the repeated field.
|
||||
* @return Float value read.
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native Float:PbReadRepeatedFloat(Handle:pb, const String:field[], index);
|
||||
|
||||
/**
|
||||
* Reads a bool from a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param index Index in the repeated field.
|
||||
* @return Boolean value read.
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native bool:PbReadRepeatedBool(Handle:pb, const String:field[], index);
|
||||
|
||||
/**
|
||||
* Reads a string from a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param index Index in the repeated field.
|
||||
* @param buffer Destination string buffer.
|
||||
* @param maxlength Maximum length of output string buffer.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbReadRepeatedString(Handle:pb, const String:field[], index, String:buffer[], size);
|
||||
|
||||
/**
|
||||
* Reads an RGBA color value from a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param index Index in the repeated field.
|
||||
* @param buffer Destination color buffer.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbReadRepeatedColor(Handle:pb, const String:field[], index, buffer[4]);
|
||||
|
||||
/**
|
||||
* Reads an XYZ angle value from a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param index Index in the repeated field.
|
||||
* @param buffer Destination angle buffer.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbReadRepeatedAngle(Handle:pb, const String:field[], index, Float:buffer[3]);
|
||||
|
||||
/**
|
||||
* Reads an XYZ vector value from a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param index Index in the repeated field.
|
||||
* @param buffer Destination vector buffer.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbReadRepeatedVector(Handle:pb, const String:field[], index, Float:buffer[3]);
|
||||
|
||||
/**
|
||||
* Reads an XY vector value from a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param index Index in the repeated field.
|
||||
* @param buffer Destination vector buffer.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbReadRepeatedVector2D(Handle:pb, const String:field[], index, Float:buffer[2]);
|
||||
|
||||
/**
|
||||
* Sets an int32, uint32, sint32, fixed32, or sfixed32 on a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Integer value to set.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbSetInt(Handle:pb, const String:field[], value);
|
||||
|
||||
/**
|
||||
* Sets a float or double on a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Float value to set.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbSetFloat(Handle:pb, const String:field[], Float:value);
|
||||
|
||||
/**
|
||||
* Sets a bool on a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Boolean value to set.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbSetBool(Handle:pb, const String:field[], bool:value);
|
||||
|
||||
/**
|
||||
* Sets a string on a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value String value to set.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbSetString(Handle:pb, const String:field[], const String:value[]);
|
||||
|
||||
/**
|
||||
* Sets an RGBA color on a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Color value to set.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbSetColor(Handle:pb, const String:field[], const color[4]);
|
||||
|
||||
/**
|
||||
* Sets an XYZ angle on a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Angle value to set.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbSetAngle(Handle:pb, const String:field[], const Float:angle[3]);
|
||||
|
||||
/**
|
||||
* Sets an XYZ vector on a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Vector value to set.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbSetVector(Handle:pb, const String:field[], const Float:vec[3]);
|
||||
|
||||
/**
|
||||
* Sets an XY vector on a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Vector value to set.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbSetVector2D(Handle:pb, const String:field[], const Float:vec[2]);
|
||||
|
||||
/**
|
||||
* Add an int32, uint32, sint32, fixed32, or sfixed32 to a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Integer value to add.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbAddInt(Handle:pb, const String:field[], value);
|
||||
|
||||
/**
|
||||
* Add a float or double to a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Float value to add.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbAddFloat(Handle:pb, const String:field[], Float:value);
|
||||
|
||||
/**
|
||||
* Add a bool to a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Boolean value to add.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbAddBool(Handle:pb, const String:field[], bool:value);
|
||||
|
||||
/**
|
||||
* Add a string to a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value String value to add.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbAddString(Handle:pb, const String:field[], const String:value[]);
|
||||
|
||||
/**
|
||||
* Add an RGBA color to a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Color value to add.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbAddColor(Handle:pb, const String:field[], const color[4]);
|
||||
|
||||
/**
|
||||
* Add an XYZ angle to a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Angle value to add.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbAddAngle(Handle:pb, const String:field[], const Float:angle[3]);
|
||||
|
||||
/**
|
||||
* Add an XYZ vector to a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Vector value to add.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbAddVector(Handle:pb, const String:field[], const Float:vec[3]);
|
||||
|
||||
/**
|
||||
* Add an XY vector to a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param value Vector value to add.
|
||||
* @noreturn
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native PbAddVector2D(Handle:pb, const String:field[], const Float:vec[2]);
|
||||
|
||||
/**
|
||||
* Retrieve a handle to an embedded protobuf message in a protobuf message.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @return protobuf handle to embedded message.
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native Handle:PbReadMessage(Handle:pb, const String:field[]);
|
||||
|
||||
/**
|
||||
* Retrieve a handle to an embedded protobuf message in a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @param index Index in the repeated field.
|
||||
* @return protobuf handle to embedded message.
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native Handle:PbReadRepeatedMessage(Handle:pb, const String:field[], index);
|
||||
|
||||
/**
|
||||
* Adds an embedded protobuf message to a protobuf message repeated field.
|
||||
*
|
||||
* @param pb protobuf handle.
|
||||
* @param field Field name.
|
||||
* @return protobuf handle to added, embedded message.
|
||||
* @error Invalid or incorrect Handle, non-existant field, or incorrect field type.
|
||||
*/
|
||||
native Handle:PbAddMessage(Handle:pb, const String:field[]);
|
@ -66,6 +66,7 @@ struct Plugin
|
||||
#include <console>
|
||||
#include <events>
|
||||
#include <bitbuffer>
|
||||
#include <protobuf>
|
||||
#include <usermessages>
|
||||
#include <menus>
|
||||
#include <halflife>
|
||||
|
@ -43,6 +43,15 @@ enum UserMsg
|
||||
INVALID_MESSAGE_ID = -1,
|
||||
};
|
||||
|
||||
/**
|
||||
* UserMsg message serialization formats
|
||||
*/
|
||||
enum UserMessageType
|
||||
{
|
||||
UM_BitBuf = 0,
|
||||
UM_Protobuf,
|
||||
};
|
||||
|
||||
/**
|
||||
* @section Message Flags.
|
||||
*/
|
||||
@ -54,6 +63,13 @@ enum UserMsg
|
||||
* @endsection
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns usermessage serialization type used for the current engine
|
||||
*
|
||||
* @return The supported usermessage type.
|
||||
*/
|
||||
native UserMessageType:GetUserMessageType();
|
||||
|
||||
/**
|
||||
* Returns the ID of a given message, or -1 on failure.
|
||||
*
|
||||
@ -115,7 +131,7 @@ native EndMessage();
|
||||
* Called when a message is hooked
|
||||
*
|
||||
* @param msg_id Message index.
|
||||
* @param bf Handle to the input bit buffer of the message.
|
||||
* @param msg Handle to the input bit buffer or protobuf.
|
||||
* @param players Array containing player indexes.
|
||||
* @param playersNum Number of players in the array.
|
||||
* @param reliable True if message is reliable, false otherwise.
|
||||
@ -124,7 +140,7 @@ native EndMessage();
|
||||
* blocks the message from being sent, and Plugin_Continue
|
||||
* resumes normal functionality.
|
||||
*/
|
||||
functag public Action:MsgHook(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init);
|
||||
functag public Action:MsgHook(UserMsg:msg_id, Handle:msg, const players[], playersNum, bool:reliable, bool:init);
|
||||
|
||||
/**
|
||||
* Called when a message hook has completed.
|
||||
|
@ -35,50 +35,36 @@
|
||||
#include <IShareSys.h>
|
||||
#include <sp_vm_api.h>
|
||||
#include <IForwardSys.h>
|
||||
#include <bitbuf.h>
|
||||
#include <irecipientfilter.h>
|
||||
|
||||
namespace google { namespace protobuf {
|
||||
class Message;
|
||||
} };
|
||||
|
||||
class bf_write;
|
||||
|
||||
/**
|
||||
* @file IUserMessages.h
|
||||
* @brief Contains functions for advanced usermessage hooking.
|
||||
*/
|
||||
|
||||
#define SMINTERFACE_USERMSGS_NAME "IUserMessages"
|
||||
#define SMINTERFACE_USERMSGS_VERSION 3
|
||||
#define SMINTERFACE_USERMSGS_VERSION 4
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
enum UserMessageType
|
||||
{
|
||||
UM_BitBuf,
|
||||
UM_Protobuf,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Listens to user messages sent from the server.
|
||||
*/
|
||||
class IUserMessageListener
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Called when a hooked user message is being sent
|
||||
* and all interceptions have finished.
|
||||
*
|
||||
* @param msg_id Message Id.
|
||||
* @param bf bf_write structure containing written bytes.
|
||||
* @param pFilter Recipient filter.
|
||||
*/
|
||||
virtual void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when a hooked user message is intercepted.
|
||||
*
|
||||
* @param msg_id Message Id.
|
||||
* @param bf bf_write structure containing written bytes.
|
||||
* @param pFilter Recipient filter.
|
||||
* @return Pl_Continue to allow message, Pl_Stop or Pl_Handled to scrap it.
|
||||
*/
|
||||
virtual ResultType InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
||||
{
|
||||
return Pl_Continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when a hooked user message is sent, regardless of the hook type.
|
||||
*
|
||||
@ -110,6 +96,76 @@ namespace SourceMod
|
||||
virtual void OnPostUserMessage(int msg_id, bool sent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual UserMessageType GetUserMessageType() const =0;
|
||||
};
|
||||
|
||||
class IBitBufUserMessageListener : public IUserMessageListener
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Called when a hooked user message is being sent
|
||||
* and all interceptions have finished.
|
||||
*
|
||||
* @param msg_id Message Id.
|
||||
* @param bf bf_write structure containing written bytes.
|
||||
* @param pFilter Recipient filter.
|
||||
*/
|
||||
virtual void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when a hooked user message is intercepted.
|
||||
*
|
||||
* @param msg_id Message Id.
|
||||
* @param bf bf_write structure containing written bytes.
|
||||
* @param pFilter Recipient filter.
|
||||
* @return Pl_Continue to allow message, Pl_Stop or Pl_Handled to scrap it.
|
||||
*/
|
||||
virtual ResultType InterceptUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
||||
{
|
||||
return Pl_Continue;
|
||||
}
|
||||
|
||||
virtual UserMessageType GetUserMessageType() const
|
||||
{
|
||||
return UM_BitBuf;
|
||||
}
|
||||
};
|
||||
|
||||
class IProtobufUserMessageListener : public IUserMessageListener
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Called when a hooked user message is being sent
|
||||
* and all interceptions have finished.
|
||||
*
|
||||
* @param msg_id Message Id.
|
||||
* @param msg Protobuf Message structure containing message data.
|
||||
* @param pFilter Recipient filter.
|
||||
*/
|
||||
virtual void OnUserMessage(int msg_id, google::protobuf::Message *msg, IRecipientFilter *pFilter)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when a hooked user message is intercepted.
|
||||
*
|
||||
* @param msg_id Message Id.
|
||||
* @param msg Protobuf Message structure containing message data.
|
||||
* @param pFilter Recipient filter.
|
||||
* @return Pl_Continue to allow message, Pl_Stop or Pl_Handled to scrap it.
|
||||
*/
|
||||
virtual ResultType InterceptUserMessage(int msg_id, google::protobuf::Message *msg, IRecipientFilter *pFilter)
|
||||
{
|
||||
return Pl_Continue;
|
||||
}
|
||||
|
||||
virtual UserMessageType GetUserMessageType() const
|
||||
{
|
||||
return UM_Protobuf;
|
||||
}
|
||||
};
|
||||
|
||||
#define USERMSG_RELIABLE (1<<2) /**< Message will be set to reliable */
|
||||
@ -173,7 +229,12 @@ namespace SourceMod
|
||||
* @param flags Flags to use for sending the message.
|
||||
* @return bf_write structure to write message with, or NULL on failure.
|
||||
*/
|
||||
virtual bf_write *StartMessage(int msg_id,
|
||||
virtual bf_write *StartBitBufMessage(int msg_id,
|
||||
const cell_t players[],
|
||||
unsigned int playersNum,
|
||||
int flags) =0;
|
||||
|
||||
virtual google::protobuf::Message *StartProtobufMessage(int msg_id,
|
||||
const cell_t players[],
|
||||
unsigned int playersNum,
|
||||
int flags) =0;
|
||||
@ -218,6 +279,13 @@ namespace SourceMod
|
||||
* @return A message index, or -1 on failure.
|
||||
*/
|
||||
virtual bool GetMessageName(int msgid, char *buffer, size_t maxlength) const =0;
|
||||
|
||||
/**
|
||||
* @brief Returns usermessage serialization type used for the current engine.
|
||||
*
|
||||
* @return The supported usermessage type.
|
||||
*/
|
||||
virtual UserMessageType GetUserMessageType() const =0;
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user