diff --git a/AMBuildScript b/AMBuildScript index 0dbcf335a8..6ada6eb9bf 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -627,7 +627,25 @@ class SMConfig(object): if compiler.target.platform == 'linux': if sdk.name in ['csgo', 'blade']: compiler.linkflags.remove('-static-libstdc++') + compiler.linkflags += ['-lstdc++'] compiler.defines += ['_GLIBCXX_USE_CXX11_ABI=0'] + elif compiler.target.platform == 'mac': + if sdk.name in ['csgo']: + # Switch libc++ to libstdc++ for protobuf linkage. + compiler.cxxflags.remove('-stdlib=libc++') + compiler.linkflags.remove('-stdlib=libc++') + compiler.linkflags.remove('-lc++') + + compiler.cxxflags += ['-stdlib=libstdc++'] + compiler.linkflags += ['-stdlib=libstdc++'] + compiler.linkflags += ['-lstdc++'] + + if 'c++1y' in compiler.cxxflags: + compiler.cxxflags.remove('-std=c++1y') + compiler.cxxflags += ['-std=c++11'] + elif 'c++14' in compiler.cxxflags: + compiler.cxxflags.remove('-std=c++14') + compiler.cxxflags += ['-std=c++11'] for path in paths: compiler.cxxincludes += [os.path.join(sdk.path, *path)] diff --git a/core/AMBuilder b/core/AMBuilder index b531379c00..a455622970 100644 --- a/core/AMBuilder +++ b/core/AMBuilder @@ -4,43 +4,42 @@ import os project = builder.LibraryProject('sourcemod') project.sources += [ + 'MenuStyle_Valve.cpp', + 'logic_bridge.cpp', + 'smn_entities.cpp', + 'sm_stringutil.cpp', + 'MenuVoting.cpp', + 'smn_events.cpp', + 'frame_hooks.cpp', + 'smn_nextmap.cpp', + 'sourcemm_api.cpp', 'ChatTriggers.cpp', + 'smn_player.cpp', + 'sourcemod.cpp', + 'concmd_cleaner.cpp', + 'HalfLife2.cpp', + 'NextMap.cpp', 'ConCmdManager.cpp', 'ConVarManager.cpp', - 'ConsoleDetours.cpp', + 'PlayerManager.cpp', + 'TimerSys.cpp', 'CoreConfig.cpp', - 'EventManager.cpp', - 'GameHooks.cpp', - 'HalfLife2.cpp', 'Logger.cpp', + 'smn_halflife.cpp', + 'smn_console.cpp', + 'UserMessages.cpp', 'MenuManager.cpp', + 'smn_hudtext.cpp', + 'smn_usermsgs.cpp', 'MenuStyle_Base.cpp', + 'smn_keyvalues.cpp', + 'smn_vector.cpp', + 'EventManager.cpp', 'MenuStyle_Radio.cpp', - 'MenuStyle_Valve.cpp', - 'MenuVoting.cpp', - 'NextMap.cpp', - 'PlayerManager.cpp', - 'TimerSys.cpp', - 'UserMessages.cpp', - 'concmd_cleaner.cpp', - 'frame_hooks.cpp', - 'logic_bridge.cpp', - 'pb_handle.cpp', 'sm_autonatives.cpp', - 'sm_stringutil.cpp', + 'ConsoleDetours.cpp', 'smn_commandline.cpp', - 'smn_console.cpp', - 'smn_entities.cpp', - 'smn_events.cpp', - 'smn_halflife.cpp', - 'smn_hudtext.cpp', - 'smn_keyvalues.cpp', - 'smn_nextmap.cpp', - 'smn_player.cpp', - 'smn_usermsgs.cpp', - 'smn_vector.cpp', - 'sourcemm_api.cpp', - 'sourcemod.cpp', + 'GameHooks.cpp', ] for sdk_name in SM.sdks: @@ -59,20 +58,18 @@ for sdk_name in SM.sdks: builder.sourcePath ] - pb_includes = [] if sdk.name == 'csgo': - pb_includes = [ + compiler.cxxincludes += [ os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'), os.path.join(sdk.path, 'public', 'engine', 'protobuf'), os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf') ] elif sdk.name == 'blade': - pb_includes = [ + compiler.cxxincludes += [ os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'), os.path.join(sdk.path, 'public', 'engine', 'protobuf'), os.path.join(sdk.path, 'public', 'game', 'shared', 'berimbau', 'protobuf') ] - compiler.cxxincludes += pb_includes if compiler.like('msvc'): compiler.defines += ['_ALLOW_KEYWORD_MACROS'] @@ -88,9 +85,9 @@ for sdk_name in SM.sdks: compiler.linkflags += ['-Wl,--exclude-libs=libprotobuf.a'] elif compiler.target.platform == 'mac': if compiler.target.arch == 'x86': - lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf-libcxx.a') + lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a') elif compiler.target.arch == 'x86_64': - lib_path = os.path.join(sdk.path, 'lib', 'osx64', 'release', 'libprotobuf-libcxx.a') + lib_path = os.path.join(sdk.path, 'lib', 'osx64', 'release', 'libprotobuf.a') elif compiler.target.platform == 'windows': msvc_ver = compiler.version vs_year = '' @@ -121,53 +118,18 @@ for sdk_name in SM.sdks: 'vprof_tool.cpp', ] - pb_sources = [] if sdk.name == 'csgo': - pb_sources = [ + binary.sources += [ os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'), os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'), os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'), ] elif sdk.name == 'blade': - pb_sources = [ + binary.sources += [ os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'), os.path.join(sdk.path, 'public', 'game', 'shared', 'berimbau', 'protobuf', 'berimbau_usermessages.pb.cc'), os.path.join(sdk.path, 'public', 'game', 'shared', 'berimbau', 'protobuf', 'berimbau_usermessage_helpers.cpp'), ] - if len(pb_sources): - binary.sources += pb_sources - binary.compiler.cxxdefines += ['PROTOBUF_ENABLE'] - - if cxx.target.platform == 'mac' and sdk.name in ['csgo']: - # We need a proxy library since the game uses libstdc++. - pb_binary = SM.HL2Library(builder, cxx, 'pbproxy.' + sdk.ext, sdk) - pb_binary.sources += pb_sources - pb_binary.sources += ['pb_proxy.cpp'] - pb_binary.compiler.cxxincludes += pb_includes - - # Switch from libc++ to libstdc++. - pb_binary.compiler.cxxflags.remove('-stdlib=libc++') - pb_binary.compiler.linkflags.remove('-lc++') - pb_binary.compiler.linkflags.remove('-stdlib=libc++') - pb_binary.compiler.cxxflags.append('-stdlib=libstdc++') - pb_binary.compiler.linkflags.append('-lstdc++') - pb_binary.compiler.linkflags.append('-stdlib=libstdc++') - if '-std=c++1y' in pb_binary.compiler.cxxflags: - pb_binary.compiler.cxxflags.remove('-std=c++1y') - elif '-std=c++14' in pb_binary.compiler.cxxflags: - pb_binary.compiler.cxxflags.remove('-std=c++14') - - if cxx.target.arch == 'x86': - pb_lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a') - elif cxx.target.arch == 'x86_64': - pb_lib_path = os.path.join(sdk.path, 'lib', 'osx64', 'release', 'libprotobuf.a') - pb_binary.compiler.linkflags.append(pb_lib_path) - - SM.binaries += [builder.Add(pb_binary)] - - binary.compiler.cxxdefines += [ - 'PROTOBUF_PROXY_ENABLE', - 'PROTOBUF_PROXY_BINARY_NAME="pbproxy.{}"'.format(sdk.ext), - ] SM.binaries += builder.Add(project) + diff --git a/core/UserMessages.cpp b/core/UserMessages.cpp index 48a10a8bc7..8c8d9b0dc2 100644 --- a/core/UserMessages.cpp +++ b/core/UserMessages.cpp @@ -42,10 +42,6 @@ UserMessages g_UserMsgs; -#ifdef USE_PROTOBUF_USERMESSAGES -const protobuf::Message *GetMessagePrototype(int msg_type); -#endif - #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &); #else @@ -62,7 +58,7 @@ UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500) { #else - : m_InterceptBuffer(nullptr) + : m_InterceptBuffer(NULL) { #endif m_HookCount = 0; @@ -237,7 +233,7 @@ google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const #ifndef USE_PROTOBUF_USERMESSAGES return NULL; #else - PbHandle buffer; + protobuf::Message *buffer; if (m_InExec || m_InHook) { @@ -266,9 +262,8 @@ google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const if (m_CurFlags & USERMSG_BLOCKHOOKS) { // direct message creation, return buffer "from engine". keep track - m_FakeEngineBuffer = - PbHandle(GetMessagePrototype(msg_id)->New(), PbHandle::Owned, PbHandle::Local); - buffer = m_FakeEngineBuffer.AsUnowned(); + m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New(); + buffer = m_FakeEngineBuffer; } else { char messageName[32]; if (!GetMessageName(msg_id, messageName, sizeof(messageName))) @@ -277,30 +272,27 @@ google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const return NULL; } - // The message returned here should always local. - auto msg = OnStartMessage_Pre(static_cast(&m_CellRecFilter), msg_id, messageName); + protobuf::Message *msg = OnStartMessage_Pre(static_cast(&m_CellRecFilter), msg_id, messageName); switch (m_FakeMetaRes) { case MRES_IGNORED: case MRES_HANDLED: - m_FakeEngineBuffer = - PbHandle(GetMessagePrototype(msg_id)->New(), PbHandle::Owned, PbHandle::Local); - buffer = m_FakeEngineBuffer.AsUnowned(); + m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New(); + buffer = m_FakeEngineBuffer; break; + case MRES_OVERRIDE: - m_FakeEngineBuffer = - PbHandle(GetMessagePrototype(msg_id)->New(), PbHandle::Owned, PbHandle::Local); + m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New(); // fallthrough case MRES_SUPERCEDE: - buffer = std::move(msg); + buffer = msg; break; } OnStartMessage_Post(static_cast(&m_CellRecFilter), msg_id, messageName); } - assert(!buffer.is_owned()); - return buffer.GetLocalMessage(); + return buffer; #endif // USE_PROTOBUF_USERMESSAGES } @@ -312,12 +304,11 @@ bool UserMessages::EndMessage() } #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE - PbHandle localBuffer = std::move(m_FakeEngineBuffer); if (m_CurFlags & USERMSG_BLOCKHOOKS) { - PbHandle priv = localBuffer.ToPrivate(m_CurId); - ENGINE_CALL(SendUserMessage)(static_cast(m_CellRecFilter), m_CurId, - *priv.GetPrivateMessage()); + ENGINE_CALL(SendUserMessage)(static_cast(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer); + delete m_FakeEngineBuffer; + m_FakeEngineBuffer = NULL; } else { OnMessageEnd_Pre(); @@ -326,12 +317,10 @@ bool UserMessages::EndMessage() case MRES_IGNORED: case MRES_HANDLED: case MRES_OVERRIDE: - { - PbHandle priv = localBuffer.ToPrivate(m_CurId); - engine->SendUserMessage(static_cast(m_CellRecFilter), m_CurId, - *priv.GetPrivateMessage()); + engine->SendUserMessage(static_cast(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer); + delete m_FakeEngineBuffer; + m_FakeEngineBuffer = NULL; break; - } //case MRES_SUPERCEDE: } @@ -451,7 +440,7 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene } #ifdef USE_PROTOBUF_USERMESSAGES -const protobuf::Message *GetMessagePrototype(int msg_type) +const protobuf::Message *UserMessages::GetMessagePrototype(int msg_type) { #if SOURCE_ENGINE == SE_CSGO return g_Cstrike15UsermessageHelpers.GetPrototype(msg_type); @@ -538,8 +527,7 @@ void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, } else { - m_FakeEngineBuffer = - PbHandle(&const_cast(msg), PbHandle::Unowned, PbHandle::Private); + m_FakeEngineBuffer = &const_cast(msg); } OnStartMessage_Post(&filter, msg_type, pszName); @@ -575,7 +563,7 @@ void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type #endif #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE -PbHandle UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name) +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 @@ -589,7 +577,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ || (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS))) { m_InHook = false; - UM_RETURN_META_VALUE(MRES_IGNORED, nullptr); + UM_RETURN_META_VALUE(MRES_IGNORED, NULL); } m_CurId = msg_type; @@ -600,20 +588,22 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ if (!is_intercept_empty) { #ifdef USE_PROTOBUF_USERMESSAGES - m_InterceptBuffer = - PbHandle(GetMessagePrototype(msg_type)->New(), PbHandle::Owned, PbHandle::Local); - UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer.AsUnowned()); + if (m_InterceptBuffer) + delete m_InterceptBuffer; + m_InterceptBuffer = GetMessagePrototype(msg_type)->New(); + + UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer); #else m_InterceptBuffer.Reset(); UM_RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer); #endif } - UM_RETURN_META_VALUE(MRES_IGNORED, nullptr); + UM_RETURN_META_VALUE(MRES_IGNORED, NULL); } #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE -void* UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name) +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 @@ -627,9 +617,9 @@ bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_ty #ifdef USE_PROTOBUF_USERMESSAGES if (m_FakeMetaRes == MRES_SUPERCEDE) - m_OrigBuffer = m_InterceptBuffer.AsUnowned(); + m_OrigBuffer = m_InterceptBuffer; else - m_OrigBuffer = m_FakeEngineBuffer.AsUnowned(); + m_OrigBuffer = m_FakeEngineBuffer; #else m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *); #endif @@ -725,11 +715,8 @@ void UserMessages::OnMessageEnd_Pre() { pInfo = (*iter); pInfo->IsHooked = true; - #ifdef USE_PROTOBUF_USERMESSAGES - PbHandle local = m_InterceptBuffer.ToLocal(m_CurId); - res = pInfo->Callback->InterceptUserMessage(m_CurId, local.GetLocalMessage(), m_CurRecFilter); - m_InterceptBuffer.CopyFrom(local); + res = pInfo->Callback->InterceptUserMessage(m_CurId, m_InterceptBuffer, m_CurRecFilter); #else res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter); #endif @@ -781,8 +768,7 @@ void UserMessages::OnMessageEnd_Pre() if (!handled && intercepted) { #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE - PbHandle priv = m_InterceptBuffer.ToPrivate(m_CurId); - ENGINE_CALL(SendUserMessage)(static_cast(*m_CurRecFilter), m_CurId, *priv.GetPrivateMessage()); + ENGINE_CALL(SendUserMessage)(static_cast(*m_CurRecFilter), m_CurId, *m_InterceptBuffer); #else bf_write *engine_bfw; #if SOURCE_ENGINE >= SE_LEFT4DEAD @@ -798,9 +784,12 @@ void UserMessages::OnMessageEnd_Pre() { #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE - PbHandle tmp_msg(GetMessagePrototype(m_CurId)->New(), PbHandle::Owned, PbHandle::Local); - tmp_msg.CopyFrom(m_OrigBuffer); - auto pTempMsg = tmp_msg.GetLocalMessage(); + int size = m_OrigBuffer->ByteSize(); + uint8 *data = (uint8 *)stackalloc(size); + m_OrigBuffer->SerializePartialToArray(data, size); + + protobuf::Message *pTempMsg = GetMessagePrototype(m_CurId)->New(); + pTempMsg->ParsePartialFromArray(data, size); #else bf_write *pTempMsg = m_OrigBuffer; #endif @@ -823,6 +812,10 @@ void UserMessages::OnMessageEnd_Pre() pInfo->IsHooked = false; iter++; } + +#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE + delete pTempMsg; +#endif } UM_RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED); diff --git a/core/UserMessages.h b/core/UserMessages.h index 96e218ae5e..7c1a2a9b85 100644 --- a/core/UserMessages.h +++ b/core/UserMessages.h @@ -52,7 +52,6 @@ using namespace SourceMod; #include #include #include -#include "pb_handle.h" using namespace google; #else @@ -109,8 +108,8 @@ class UserMessages : #endif #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE - PbHandle OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name); - void* OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name); + 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); @@ -122,6 +121,7 @@ class UserMessages : void OnMessageEnd_Post(); private: #ifdef USE_PROTOBUF_USERMESSAGES + const protobuf::Message *GetMessagePrototype(int msg_type); bool InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew); bool InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew); #else @@ -141,11 +141,11 @@ class UserMessages : bf_read m_ReadBuffer; #else // The engine used to provide this. Now we track it. - PbHandle m_OrigBuffer; - PbHandle m_FakeEngineBuffer; + protobuf::Message *m_OrigBuffer; + protobuf::Message *m_FakeEngineBuffer; META_RES m_FakeMetaRes; - PbHandle m_InterceptBuffer; + protobuf::Message *m_InterceptBuffer; #endif size_t m_HookCount; bool m_InHook; diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index 06930a7931..7ca246e914 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -51,9 +51,6 @@ #include #include #include -#if PROTOBUF_PROXY_ENABLE -# include "pb_handle.h" -#endif sm_logic_t logicore; @@ -657,41 +654,6 @@ void CoreProviderImpl::InitializeBridge() rootmenu = logicore.rootmenu; } -bool CoreProviderImpl::LoadProtobufProxy(char *error, size_t maxlength) -{ -#if !defined(PROTOBUF_PROXY_ENABLE) - return false; -#else - char file[PLATFORM_MAX_PATH]; - -#if !defined(PROTOBUF_PROXY_BINARY_NAME) -# error "No engine suffix defined" -#endif - - /* Now it's time to load the logic binary */ - g_SMAPI->PathFormat(file, - sizeof(file), - "%s/bin/" PLATFORM_ARCH_FOLDER PROTOBUF_PROXY_BINARY_NAME PLATFORM_LIB_EXT, - g_SourceMod.GetSourceModPath()); - - char myerror[255]; - pbproxy_ = ke::SharedLib::Open(file, myerror, sizeof(myerror)); - if (!pbproxy_) { - ke::SafeSprintf(error, maxlength, "failed to load %s: %s", file, myerror); - return false; - } - - auto fn = pbproxy_->get("GetProtobufProxy"); - if (!fn) { - ke::SafeStrcpy(error, maxlength, "could not find GetProtobufProxy function"); - return false; - } - - gProtobufProxy = fn(); - return true; -#endif -} - bool CoreProviderImpl::LoadBridge(char *error, size_t maxlength) { char file[PLATFORM_MAX_PATH]; diff --git a/core/pb_handle.cpp b/core/pb_handle.cpp deleted file mode 100644 index 85915fd7ed..0000000000 --- a/core/pb_handle.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ============================================================================= - * SourceMod - * Copyright (C) 2020 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 . - * - * 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 . - * - * Version: $Id$ - */ -#include "pb_handle.h" - -#if defined PROTOBUF_PROXY_ENABLE -IProtobufProxy* gProtobufProxy = nullptr; -#endif diff --git a/core/pb_handle.h b/core/pb_handle.h deleted file mode 100644 index 5951b7af7a..0000000000 --- a/core/pb_handle.h +++ /dev/null @@ -1,217 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ============================================================================= - * SourceMod - * Copyright (C) 2020 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 . - * - * 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 . - * - * Version: $Id$ - */ -#pragma once - -#if defined(PROTOBUF_ENABLE) -#include - -#if defined(PROTOBUF_PROXY_ENABLE) -# include "pb_proxy.h" - -extern IProtobufProxy* gProtobufProxy; -#endif - -const google::protobuf::Message *GetMessagePrototype(int msg_type); - -// On SDKs which use protobufs, the engine has objects compiled against a specific -// version of protobuf. Normally this is fine, we take care on Linux to use the -// same C++ ABI. On macOS however, we use libc++ to enable C++11 functionality, -// whereas the protobuf library has been compiled with libstc++. These ABIs are -// not compatible. -// -// To address the problem, we introduce PbHandle. PbHandle is a wrapper around -// protobuf::Message with two added pieces of state: whether or not the handle -// "owns" the message (and can free it in its destructor), and whether or not -// the handle was created by the engine (private) or created by SourceMod -// (local). -// -// Whenever we transfer a protobuf::Message pointer to SourceMod, we must take -// care to convert it to a Local version first. Whenever we transfer a protobuf -// pointer to the engine, we must convert it to a Private handle. -// -// For platforms with no ABI differences (almost all of them), the handle is a -// no-op. The private and local localities are compatible and no translation -// takes place. -// -// On macOS, CS:GO does require translation. SourceMod loads a tiny shim -// library that contains a copy of the protobuf sources compiled against the -// game's ABI. It then provides serialization and deserialization methods. -// SourceMod must not interact with the game's protobuf objects without first -// going through this proxy library. -// -// Note that PbHandle is not quite like unique_ptr_. It can be converted into a -// PbHandle that does not destroy the underlying object. This is mainly because -// UserMessages.cpp has rather complex state, so it is useful to track locality -// without destroying an object. An unowned PbHandle must not outlive the -// owning PbHandle. -class PbHandle -{ -public: - enum Ownership { - Owned, - Unowned, - }; - enum Locality { - Local, - Private, - }; - - PbHandle() : msg_(nullptr) {} - PbHandle(decltype(nullptr)) : msg_(nullptr) {} - PbHandle(google::protobuf::Message* msg, Ownership ownership, Locality locality) - : msg_(msg), - ownership_(ownership), - locality_(locality) - {} - PbHandle(PbHandle&& other) - : msg_(other.msg_), - ownership_(other.ownership_), - locality_(other.locality_) - { - other.msg_ = nullptr; - } - PbHandle(const PbHandle&) = delete; - - ~PbHandle() { - maybe_free(); - } - - PbHandle& operator =(PbHandle&& other) { - if (other.msg_ != msg_) - maybe_free(); - msg_ = other.msg_; - ownership_ = other.ownership_; - locality_ = other.locality_; - other.msg_ = nullptr; - return *this; - } - PbHandle& operator =(const PbHandle&) = delete; - - google::protobuf::Message* operator ->() const { return msg_; } - - google::protobuf::Message* GetLocalMessage() { - assert(locality_ == Local); - return msg_; - } - google::protobuf::Message* GetPrivateMessage() { - assert(locality_ == Private); - return msg_; - } - - PbHandle ToLocal(int msg_type) { - if (locality_ == Local) - return AsUnowned(); -#if defined(PROTOBUF_PROXY_ENABLE) - PbHandle local(GetMessagePrototype(msg_type)->New(), Owned, Local); - local.CopyFromPrivate(msg_); - return local; -#else - return PbHandle(msg_, Unowned, Local); -#endif - } - - PbHandle ToPrivate(int msg_type) { - if (locality_ == Private) - return AsUnowned(); -#if defined(PROTOBUF_PROXY_ENABLE) - PbHandle priv(gProtobufProxy->NewPrototype(msg_type), Owned, Private); - priv.CopyFromLocal(msg_); - return priv; -#else - return PbHandle(msg_, Unowned, Private); -#endif - } - - void CopyFrom(const PbHandle& other) { - if (other.msg_ == msg_) { - assert(other.locality_ == locality_); - return; - } -#if defined(PROTOBUF_PROXY_ENABLE) - if (other.locality_ == Local) - CopyFromLocal(other.msg_); - else if (other.locality_ == Private) - CopyFromPrivate(other.msg_); -#else - msg_->CopyFrom(*other.msg_); -#endif - } - - PbHandle AsUnowned() { - return PbHandle(msg_, Unowned, locality_); - } - - bool is_owned() const { return ownership_ == Owned; } - bool is_local() const { return locality_ == Local; } - -private: -#if defined(PROTOBUF_PROXY_ENABLE) - void CopyFromPrivate(google::protobuf::Message* message) { - void* out; - size_t len; - if (!gProtobufProxy->Serialize(message, &out, &len)) - return; - if (locality_ == Local) - msg_->ParsePartialFromArray(out, len); - else - gProtobufProxy->Deserialize(out, len, msg_); - gProtobufProxy->FreeBuffer(out); - } - - void CopyFromLocal(google::protobuf::Message* message) { - if (locality_ == Local) { - msg_->CopyFrom(*message); - } else { - auto data = message->SerializePartialAsString(); - gProtobufProxy->Deserialize(data.data(), data.size(), msg_); - } - } -#endif - - void maybe_free() { - if (ownership_ != Owned) - return; -#if defined(PROTOBUF_PROXY_ENABLE) - if (locality_ == Private) { - gProtobufProxy->FreeMessage(msg_); - return; - } -#endif - delete msg_; - } - -private: - google::protobuf::Message* msg_ = nullptr; - Ownership ownership_ = Unowned; - Locality locality_ = Local; -}; - -#endif // PROTOBUF_ENABLE diff --git a/core/pb_proxy.cpp b/core/pb_proxy.cpp deleted file mode 100644 index 695193300a..0000000000 --- a/core/pb_proxy.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ============================================================================= - * SourceMod - * Copyright (C) 2020 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 . - * - * 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 . - * - * Version: $Id$ - */ -#include "pb_proxy.h" - -#include -#include - -#if SOURCE_ENGINE == SE_CSGO -# include -#elif SOURCE_ENGINE == SE_BLADE -# include -#else -# error "No source engine compatibility" -#endif - -class ProtobufProxy : public IProtobufProxy -{ -public: - bool Serialize(const google::protobuf::Message* message, void** out, size_t* len); - void FreeBuffer(void* data); - bool Deserialize(const void* buffer, size_t len, google::protobuf::Message* message); - google::protobuf::Message* NewPrototype(int msg_type); - void FreeMessage(google::protobuf::Message* message); -}; - -static ProtobufProxy sProtobufProxy; - -PLATFORM_EXTERN_C IProtobufProxy* -GetProtobufProxy() -{ - return &sProtobufProxy; -} - -bool -ProtobufProxy::Serialize(const google::protobuf::Message* message, void** out, size_t* len) -{ - *len = message->ByteSize(); - *out = malloc(*len); - if (!*out) - return false; - if (!message->SerializePartialToArray(*out, *len)) { - free(*out); - return false; - } - return true; -} - -void -ProtobufProxy::FreeBuffer(void* data) -{ - free(data); -} - -bool -ProtobufProxy::Deserialize(const void* buffer, size_t len, google::protobuf::Message* message) -{ - return message->ParsePartialFromArray(buffer, len); -} - -google::protobuf::Message* -ProtobufProxy::NewPrototype(int msg_type) -{ -#if SOURCE_ENGINE == SE_CSGO - return g_Cstrike15UsermessageHelpers.GetPrototype(msg_type)->New(); -#elif SOURCE_ENGINE == SE_BLADE - return g_BerimbauUsermessageHelpers.GetPrototype(msg_type)->New(); -#else -# error "No source engine compatibility." -#endif -} - -void -ProtobufProxy::FreeMessage(google::protobuf::Message* message) -{ - delete message; -} diff --git a/core/pb_proxy.h b/core/pb_proxy.h deleted file mode 100644 index 5810c36df7..0000000000 --- a/core/pb_proxy.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ============================================================================= - * SourceMod - * Copyright (C) 2020 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 . - * - * 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 . - * - * Version: $Id$ - */ -#pragma once - -#include - -class IProtobufProxy -{ -public: - // Serialize the given message into a buffer. The buffer and its length are placed in |out|. - // The buffer must be freed with FreeBuffer. - virtual bool Serialize(const google::protobuf::Message* message, void** out, size_t* len) = 0; - virtual void FreeBuffer(void* data) = 0; - - // Deserialize the given buffer into a message. - virtual bool Deserialize(const void* buffer, size_t len, google::protobuf::Message* message) = 0; - - // Allocate/free a prototype. - virtual google::protobuf::Message* NewPrototype(int msg_type) = 0; - virtual void FreeMessage(google::protobuf::Message* message) = 0; - - bool Serialize(const google::protobuf::Message& message, void** out, size_t* len) { - return Serialize(&message, out, len); - } - bool Deserialize(const void* buffer, size_t len, google::protobuf::Message& message) { - return Deserialize(buffer, len, &message); - } -}; - -typedef IProtobufProxy*(*GetProtobufProxyFn)(); diff --git a/core/provider.h b/core/provider.h index 97fa3f4b0b..41ae71f20c 100644 --- a/core/provider.h +++ b/core/provider.h @@ -38,7 +38,6 @@ class CoreProviderImpl : public CoreProvider // Local functions. void InitializeBridge(); - bool LoadProtobufProxy(char *error, size_t maxlength); bool LoadBridge(char *error, size_t maxlength); void ShutdownBridge(); @@ -77,7 +76,6 @@ class CoreProviderImpl : public CoreProvider } private: - ke::RefPtr pbproxy_; ke::RefPtr logic_; LogicInitFunction logic_init_; GameHooks hooks_;