From b916e115433203c5840b3047b359670f4b082aff Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 3 Apr 2024 01:26:53 +0200 Subject: [PATCH] RTech: implement custom events and slight adjustments/improvements Implemented CustomEvent in code, which supports: - bool|int|float|string|vector|array|table - nested arrays and tables, up to a depth of 64 Also improved foundation code for LiveAPI: - added ability to log liveapi events to a file on the disk (rotates between each match or round, depending on how the abstracted functions are called in scripts) - when the system is enabled through cvars, code will be invoked on the fly - when the system is disabled through cvars, the system will be shutdown properly on the fly (properly handling socket closing, log file finishing, etc) - if the socket system is enabled/disabled on the fly using cvars, related code will be called to initiate or shutdown the connections. The generated proto.cpp/h file has been moved to the protoc project as it was causing some compiler warnings that we suppress on the thirdparty (vendored) code. --- src/core/CMakeLists.txt | 1 + src/game/CMakeLists.txt | 2 - src/game/server/liveapi/liveapi.cpp | 241 ++++++- src/protoc/CMakeLists.txt | 12 + .../server/liveapi => protoc}/events.pb.cc | 594 ++++++++++-------- .../server/liveapi => protoc}/events.pb.h | 209 ++++-- src/resource/protobuf/events.proto | 46 +- src/rtech/liveapi/liveapi.cpp | 193 +++++- src/rtech/liveapi/liveapi.h | 26 +- 9 files changed, 934 insertions(+), 390 deletions(-) rename src/{game/server/liveapi => protoc}/events.pb.cc (97%) rename src/{game/server/liveapi => protoc}/events.pb.h (99%) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index bf387d5d..d8f575bf 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -58,6 +58,7 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE "vphysics" "SigCache_Pb" + "LiveAPI_Pb" "SV_RCon_Pb" "CL_RCon_Pb" diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt index 015b5d71..8eae5857 100644 --- a/src/game/CMakeLists.txt +++ b/src/game/CMakeLists.txt @@ -100,8 +100,6 @@ add_sources( SOURCE_GROUP "Utility" ) add_sources( SOURCE_GROUP "LiveAPI" - "server/liveapi/events.pb.cc" - "server/liveapi/events.pb.h" "server/liveapi/liveapi.cpp" "server/liveapi/liveapi.h" ) diff --git a/src/game/server/liveapi/liveapi.cpp b/src/game/server/liveapi/liveapi.cpp index b9e338c3..7ad96c52 100644 --- a/src/game/server/liveapi/liveapi.cpp +++ b/src/game/server/liveapi/liveapi.cpp @@ -8,7 +8,7 @@ // - Add code callback for player weapon switched ( event WeaponSwitched ) // //=============================================================================// -#include "tier1/utlsymbol.h" +#include "tier1/depthcounter.h" #include "vscript/languages/squirrel_re/include/sqtable.h" #include "vscript/languages/squirrel_re/include/sqarray.h" #include "game/server/vscript_server.h" @@ -16,8 +16,13 @@ #include "liveapi.h" #include "engine/sys_utils.h" -#include "events.pb.h" -#include "protobuf/util/json_util.h" +#pragma warning(push) +#pragma warning(disable : 4505) +#include "protoc/events.pb.h" +#pragma warning(pop) + +// The total nesting depth cannot exceed this number +#define LIVEAPI_MAX_ITEM_DEPTH 64 /* @@ -50,6 +55,7 @@ static rtech::liveapi::CharacterSelected s_characterSelected; //static rtech::liveapi::CustomMatch_SetSettings s_customMatch_SetSettings; //static rtech::liveapi::CustomMatch_SetTeam s_customMatch_SetTeam; //static rtech::liveapi::CustomMatch_SetTeamName s_customMatch_SetTeamName; +static rtech::liveapi::CustomEvent s_customEvent; static rtech::liveapi::GameStateChanged s_gameStateChanged; static rtech::liveapi::GibraltarShieldAbsorbed s_gibraltarShieldAbsorbed; static rtech::liveapi::GrenadeThrown s_grenadeThrown; @@ -125,7 +131,7 @@ enum class eLiveAPI_EventTypes //customMatch_SetSettings, //customMatch_SetTeam, //customMatch_SetTeamName, - + customEvent, datacenter, //gameConVar, gameStateChanged, @@ -221,6 +227,7 @@ static const char* LiveAPI_EventTypeToString(const eLiveAPI_EventTypes eventType //case eLiveAPI_EventTypes::customMatch_SetSettings: return "customMatch_SetSettings"; //case eLiveAPI_EventTypes::customMatch_SetTeam: return "customMatch_SetTeam"; //case eLiveAPI_EventTypes::customMatch_SetTeamName: return "customMatch_SetTeamName"; + case eLiveAPI_EventTypes::customEvent: return "customEvent"; case eLiveAPI_EventTypes::datacenter: return "datacenter"; //case eLiveAPI_EventTypes::gameConVar: return "gameConVar"; case eLiveAPI_EventTypes::gameStateChanged: return "gameStateChanged"; @@ -319,9 +326,11 @@ static bool LiveAPI_CheckSwitchType(HSQUIRRELVM const v, const SQObjectPtr& obj) } #define LIVEAPI_ENSURE_TYPE(v, obj, expectType, eventMsg, fieldNum) { if (!LiveAPI_EnsureType(v, obj, expectType, eventMsg, fieldNum)) return false; } -#define LIVEAPI_EMPTY_TABLE_ERROR(v, eventMsg) { v_SQVM_RaiseError(v, "Empty table on message \"%s\".", eventMsg->GetTypeName().c_str()); return false; } +#define LIVEAPI_EMPTY_TABLE_ERROR(v, eventMsg) { v_SQVM_RaiseError(v, "Empty iterable on message \"%s\".", eventMsg->GetTypeName().c_str()); return false; } #define LIVEAPI_FIELD_ERROR(v, fieldNum, eventMsg) { v_SQVM_RaiseError(v, "Field \"%d\" doesn't exist in message \"%s\".", fieldNum, eventMsg->GetTypeName().c_str()); return false; } #define LIVEAPI_ONEOF_FIELD_ERROR(v, fieldNum, eventMsg) { v_SQVM_RaiseError(v, "Tried to set member \"%d\" of oneof field in message \"%s\" while another has already been set.", fieldNum, eventMsg->GetTypeName().c_str()); return false; } +#define LIVEAPI_UNSUPPORTED_TYPE_ERROR(v, gotType, eventMsg) {v_SQVM_RaiseError(v, "Value type \"%s\" is not supported for message \"%s\".\n", IdType2Name(gotType), eventMsg->GetTypeName().c_str()); return false; } +#define LIVEAPI_CHECK_RECURSION_DEPTH(v, currDepth) { if (currDepth > LIVEAPI_MAX_ITEM_DEPTH) { v_SQVM_RaiseError(v, "Exceeded nesting depth limit of \"%i\".", LIVEAPI_MAX_ITEM_DEPTH); return false; }} uint64_t GetUnixTimeStamp() // TODO: move elsewhere { @@ -1743,6 +1752,185 @@ static bool LiveAPI_HandlePlayerStatChanged(HSQUIRRELVM const v, const SQObject& return true; } +static void LiveAPI_SetCustomVectorField(google::protobuf::Struct* const structData, const Vector3D* const vecData) +{ + google::protobuf::Map* const fieldData = structData->mutable_fields(); + + (*fieldData)["x"].set_number_value(vecData->x); + (*fieldData)["y"].set_number_value(vecData->y); + (*fieldData)["z"].set_number_value(vecData->z); +} + +static bool LiveAPI_SetCustomTableFields(HSQUIRRELVM const v, google::protobuf::Struct* const structData, const SQTable* const tableData); +static bool LiveAPI_SetCustomArrayFields(HSQUIRRELVM const v, google::protobuf::ListValue* const listData, const SQArray* const arrayData); + +static int s_currentDepth = 0; + +static bool LiveAPI_SetCustomArrayFields(HSQUIRRELVM const v, google::protobuf::ListValue* const listData, const SQArray* const arrayData) +{ + CDepthCounter counter(s_currentDepth); + bool ranLoop = false; + + for (SQInteger i = 0; i < arrayData->Size(); i++) + { + const SQObject& valueObj = arrayData->_values[i]; + + if (sq_isnull(valueObj)) + continue; + + if (!ranLoop) + ranLoop = true; + + const SQObjectType valueType = sq_type(valueObj); + + switch (valueType) + { + case OT_BOOL: + listData->add_values()->set_bool_value(_bool(valueObj)); + break; + case OT_INTEGER: + listData->add_values()->set_number_value(_integer(valueObj)); + break; + case OT_FLOAT: + listData->add_values()->set_number_value(_float(valueObj)); + break; + case OT_STRING: + listData->add_values()->set_string_value(_string(valueObj)->_val); + break; + case OT_VECTOR: + LiveAPI_SetCustomVectorField(listData->add_values()->mutable_struct_value(), _vector3d(valueObj)); + break; + case OT_ARRAY: + LIVEAPI_CHECK_RECURSION_DEPTH(v, counter.Get()); + + if (arrayData == _array(valueObj)) + { + v_SQVM_RaiseError(v, "Attempted to nest array \"%i\" into itself at index \"%i\".", counter.Get(), i); + return false; + } + + if (!LiveAPI_SetCustomArrayFields(v, listData->add_values()->mutable_list_value(), _array(valueObj))) + return false; + + break; + case OT_TABLE: + LIVEAPI_CHECK_RECURSION_DEPTH(v, counter.Get()); + + if (!LiveAPI_SetCustomTableFields(v, listData->add_values()->mutable_struct_value(), _table(valueObj))) + return false; + + break; + default: + LIVEAPI_UNSUPPORTED_TYPE_ERROR(v, valueType, listData); + } + } + + if (!ranLoop) + LIVEAPI_EMPTY_TABLE_ERROR(v, listData); + + return true; +} + +static bool LiveAPI_SetCustomTableFields(HSQUIRRELVM const v, google::protobuf::Struct* const structData, const SQTable* const tableData) +{ + CDepthCounter counter(s_currentDepth); + bool ranLoop = false; + + SQ_FOR_EACH_TABLE(tableData, i) + { + const SQTable::_HashNode& node = tableData->_nodes[i]; + + if (sq_isnull(node.key)) + continue; + + if (!ranLoop) + ranLoop = true; + + const SQObjectType keyType = sq_type(node.key); + + if (keyType != OT_STRING) + { + v_SQVM_RaiseError(v, "Key must be a \"%s\", got \"%s\" for message \"%s\" in table \"%i\" at index \"%i\".", + IdType2Name(OT_STRING), IdType2Name(keyType), structData->GetTypeName().c_str(), counter.Get(), i); + + return false; + } + + const SQObjectType valueType = sq_type(node.val); + + switch (valueType) + { + case OT_BOOL: + (*structData->mutable_fields())[_string(node.key)->_val].set_bool_value(_bool(node.val)); + break; + case OT_INTEGER: + (*structData->mutable_fields())[_string(node.key)->_val].set_number_value(_integer(node.val)); + break; + case OT_FLOAT: + (*structData->mutable_fields())[_string(node.key)->_val].set_number_value(_float(node.val)); + break; + case OT_STRING: + (*structData->mutable_fields())[_string(node.key)->_val].set_string_value(_string(node.val)->_val); + break; + case OT_VECTOR: + LiveAPI_SetCustomVectorField((*structData->mutable_fields())[_string(node.key)->_val].mutable_struct_value(), _vector3d(node.val)); + break; + case OT_ARRAY: + LIVEAPI_CHECK_RECURSION_DEPTH(v, counter.Get()); + + if (!LiveAPI_SetCustomArrayFields(v, (*structData->mutable_fields())[_string(node.key)->_val].mutable_list_value(), _array(node.val))) + return false; + + break; + case OT_TABLE: + LIVEAPI_CHECK_RECURSION_DEPTH(v, counter.Get()); + + if (tableData == _table(node.val)) + { + v_SQVM_RaiseError(v, "Attempted to nest table \"%i\" into itself at index \"%i\".", counter.Get(), i); + return false; + } + + if (!LiveAPI_SetCustomTableFields(v, (*structData->mutable_fields())[_string(node.key)->_val].mutable_struct_value(), _table(node.val))) + return false; + + break; + default: + LIVEAPI_UNSUPPORTED_TYPE_ERROR(v, valueType, structData); + } + } + + if (!ranLoop) + LIVEAPI_EMPTY_TABLE_ERROR(v, structData); + + return true; +} + +static bool LiveAPI_HandleCustomEvent(HSQUIRRELVM const v, const SQObject& obj, rtech::liveapi::CustomEvent* const event, + const eLiveAPI_EventTypes eventType, const SQInteger fieldNum) +{ + LiveAPI_SetCommonMessageFields(event, eventType); + + switch (fieldNum) + { + case rtech::liveapi::CustomEvent::kNameFieldNumber: + LIVEAPI_ENSURE_TYPE(v, obj, OT_STRING, event, fieldNum); + event->set_name(_string(obj)->_val); + + break; + case rtech::liveapi::CustomEvent::kDataFieldNumber: + LIVEAPI_ENSURE_TYPE(v, obj, OT_TABLE, event, fieldNum); + if (!LiveAPI_SetCustomTableFields(v, event->mutable_data(), _table(obj))) + return false; + + break; + default: + LIVEAPI_FIELD_ERROR(v, fieldNum, event); + } + + return true; +} + /* ███████╗██╗ ██╗███████╗███╗ ██╗████████╗ ██████╗ ██╗███████╗██████╗ █████╗ ████████╗ ██████╗██╗ ██╗███████╗██████╗ ██╔════╝██║ ██║██╔════╝████╗ ██║╚══██╔══╝ ██╔══██╗██║██╔════╝██╔══██╗██╔══██╗╚══██╔══╝██╔════╝██║ ██║██╔════╝██╔══██╗ @@ -1757,19 +1945,7 @@ static void LiveAPI_SendEvent(const google::protobuf::Message* const msg) s_liveAPIEvent.set_event_size(msg->ByteSize()); s_liveAPIEvent.mutable_gamemessage()->PackFrom(*msg); - const string data = s_liveAPIEvent.SerializeAsString(); - LiveAPISystem()->LogEvent(data.c_str(), (int)data.size()); - - std::string jsonStr; - - google::protobuf::util::JsonPrintOptions options; - options.add_whitespace = true; - options.always_print_primitive_fields = true; - - google::protobuf::util::MessageToJsonString(s_liveAPIEvent, &jsonStr, options); - - Msg(eDLL_T::ENGINE, "%s\n", jsonStr.c_str()); - + LiveAPISystem()->LogEvent(&s_liveAPIEvent, &s_liveAPIEvent.gamemessage()); s_liveAPIEvent.Clear(); } @@ -1818,6 +1994,10 @@ static bool LiveAPI_HandleEventByCategory(HSQUIRRELVM const v, const SQTable* co msg = &s_bannerCollected; ret = LiveAPI_HandleBannerCollected(v, obj, &s_bannerCollected, eventType, fieldNum); break; + case eLiveAPI_EventTypes::customEvent: + msg = &s_customEvent; + ret = LiveAPI_HandleCustomEvent(v, obj, &s_customEvent, eventType, fieldNum); + break; case eLiveAPI_EventTypes::inventoryPickUp: msg = &s_inventoryPickUp; ret = LiveAPI_HandleInventoryChange(v, obj, &s_inventoryPickUp, eventType, fieldNum); @@ -1984,12 +2164,15 @@ namespace VScriptCode { SQRESULT LiveAPI_IsValidToRun(HSQUIRRELVM v); SQRESULT LiveAPI_LogRaw(HSQUIRRELVM v); + + SQRESULT LiveAPI_StartLogging(HSQUIRRELVM v); + SQRESULT LiveAPI_StopLogging(HSQUIRRELVM v); } } SQRESULT VScriptCode::Server::LiveAPI_IsValidToRun(HSQUIRRELVM v) { - sq_pushbool(v, liveapi_enabled.GetBool()); + sq_pushbool(v, LiveAPISystem()->IsValidToRun()); SCRIPT_CHECK_AND_RETURN(v, SQ_OK); } @@ -1999,11 +2182,11 @@ SQRESULT VScriptCode::Server::LiveAPI_LogRaw(HSQUIRRELVM v) SCRIPT_CHECK_AND_RETURN(v, SQ_OK); SQRESULT result = SQ_OK; - SQObjectPtr& object = v->GetUp(-2); + const SQObjectPtr& object = v->GetUp(-2); if (sq_istable(object)) { - SQTable* const table = object._unVal.pTable; + const SQTable* const table = object._unVal.pTable; const eLiveAPI_EventTypes eventType = eLiveAPI_EventTypes(sq_getinteger(v, 2)); if (!LiveAPI_HandleEventByCategory(v, table, eventType)) @@ -2018,10 +2201,25 @@ SQRESULT VScriptCode::Server::LiveAPI_LogRaw(HSQUIRRELVM v) SCRIPT_CHECK_AND_RETURN(v, result); } +SQRESULT VScriptCode::Server::LiveAPI_StartLogging(HSQUIRRELVM v) +{ + LiveAPISystem()->CreateLogger(); + SCRIPT_CHECK_AND_RETURN(v, SQ_OK); +} + +SQRESULT VScriptCode::Server::LiveAPI_StopLogging(HSQUIRRELVM v) +{ + LiveAPISystem()->DestroyLogger(); + SCRIPT_CHECK_AND_RETURN(v, SQ_OK); +} + void Script_RegisterLiveAPIFunctions(CSquirrelVM* const s) { DEFINE_SERVER_SCRIPTFUNC_NAMED(s, LiveAPI_IsValidToRun, "Whether the LiveAPI system is enabled and able to run", "bool", ""); DEFINE_SERVER_SCRIPTFUNC_NAMED(s, LiveAPI_LogRaw, "VM bridge to the LiveAPI logger from scripts", "void", "table< int, var > data, int eventType"); + + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, LiveAPI_StartLogging, "Start the LiveAPI session logger", "void", ""); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, LiveAPI_StopLogging, "Stop the LiveAPI session logger", "void", ""); } void Script_RegisterLiveAPIEnums(CSquirrelVM* const s) @@ -2050,6 +2248,7 @@ void Script_RegisterLiveAPIEnums(CSquirrelVM* const s) //"customMatch_SetSettings", //"customMatch_SetTeam", //"customMatch_SetTeamName", + "customEvent", "datacenter", //"gameConVar", "gameStateChanged", diff --git a/src/protoc/CMakeLists.txt b/src/protoc/CMakeLists.txt index 88ff5c7f..8e78d772 100644 --- a/src/protoc/CMakeLists.txt +++ b/src/protoc/CMakeLists.txt @@ -1,4 +1,16 @@ cmake_minimum_required( VERSION 3.16 ) +add_module( "lib" "LiveAPI_Pb" "vpc" ${FOLDER_CONTEXT} FALSE TRUE ) + +start_sources() + +add_sources( SOURCE_GROUP "Runtime" + "events.pb.cc" + "events.pb.h" +) + +end_sources() +thirdparty_suppress_warnings() + add_module( "lib" "SigCache_Pb" "vpc" ${FOLDER_CONTEXT} FALSE TRUE ) start_sources() diff --git a/src/game/server/liveapi/events.pb.cc b/src/protoc/events.pb.cc similarity index 97% rename from src/game/server/liveapi/events.pb.cc rename to src/protoc/events.pb.cc index fe2791ab..a64f40cb 100644 --- a/src/game/server/liveapi/events.pb.cc +++ b/src/protoc/events.pb.cc @@ -777,8 +777,9 @@ struct WeaponSwitchedDefaultTypeInternal { PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 WeaponSwitchedDefaultTypeInternal _WeaponSwitched_default_instance_; PROTOBUF_CONSTEXPR CustomEvent::CustomEvent( ::_pbi::ConstantInitialized): _impl_{ - /*decltype(_impl_.customdata_)*/{} - , /*decltype(_impl_.category_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + /*decltype(_impl_.category_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.data_)*/nullptr , /*decltype(_impl_.timestamp_)*/uint64_t{0u} , /*decltype(_impl_._cached_size_)*/{}} {} struct CustomEventDefaultTypeInternal { @@ -1531,7 +1532,8 @@ const uint32_t TableStruct_events_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(p ~0u, // no _inlined_string_donated_ PROTOBUF_FIELD_OFFSET(::rtech::liveapi::CustomEvent, _impl_.timestamp_), PROTOBUF_FIELD_OFFSET(::rtech::liveapi::CustomEvent, _impl_.category_), - PROTOBUF_FIELD_OFFSET(::rtech::liveapi::CustomEvent, _impl_.customdata_), + PROTOBUF_FIELD_OFFSET(::rtech::liveapi::CustomEvent, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::rtech::liveapi::CustomEvent, _impl_.data_), ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(::rtech::liveapi::ChangeCamera, _internal_metadata_), ~0u, // no _extensions_ @@ -1731,24 +1733,24 @@ static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protode { 461, -1, -1, sizeof(::rtech::liveapi::AmmoUsed)}, { 474, -1, -1, sizeof(::rtech::liveapi::WeaponSwitched)}, { 485, -1, -1, sizeof(::rtech::liveapi::CustomEvent)}, - { 494, -1, -1, sizeof(::rtech::liveapi::ChangeCamera)}, - { 503, -1, -1, sizeof(::rtech::liveapi::PauseToggle)}, - { 510, -1, -1, sizeof(::rtech::liveapi::CustomMatch_CreateLobby)}, - { 516, -1, -1, sizeof(::rtech::liveapi::CustomMatch_JoinLobby)}, - { 523, -1, -1, sizeof(::rtech::liveapi::CustomMatch_LeaveLobby)}, - { 529, -1, -1, sizeof(::rtech::liveapi::CustomMatch_SetReady)}, - { 536, -1, -1, sizeof(::rtech::liveapi::CustomMatch_GetLobbyPlayers)}, - { 542, -1, -1, sizeof(::rtech::liveapi::CustomMatch_SetMatchmaking)}, - { 549, -1, -1, sizeof(::rtech::liveapi::CustomMatch_SetTeam)}, - { 558, -1, -1, sizeof(::rtech::liveapi::CustomMatch_KickPlayer)}, - { 566, -1, -1, sizeof(::rtech::liveapi::CustomMatch_SetSettings)}, - { 578, -1, -1, sizeof(::rtech::liveapi::CustomMatch_GetSettings)}, - { 584, -1, -1, sizeof(::rtech::liveapi::CustomMatch_SetTeamName)}, - { 592, -1, -1, sizeof(::rtech::liveapi::CustomMatch_SendChat)}, - { 599, -1, -1, sizeof(::rtech::liveapi::Request)}, - { 622, -1, -1, sizeof(::rtech::liveapi::RequestStatus)}, - { 629, -1, -1, sizeof(::rtech::liveapi::Response)}, - { 637, -1, -1, sizeof(::rtech::liveapi::LiveAPIEvent)}, + { 495, -1, -1, sizeof(::rtech::liveapi::ChangeCamera)}, + { 504, -1, -1, sizeof(::rtech::liveapi::PauseToggle)}, + { 511, -1, -1, sizeof(::rtech::liveapi::CustomMatch_CreateLobby)}, + { 517, -1, -1, sizeof(::rtech::liveapi::CustomMatch_JoinLobby)}, + { 524, -1, -1, sizeof(::rtech::liveapi::CustomMatch_LeaveLobby)}, + { 530, -1, -1, sizeof(::rtech::liveapi::CustomMatch_SetReady)}, + { 537, -1, -1, sizeof(::rtech::liveapi::CustomMatch_GetLobbyPlayers)}, + { 543, -1, -1, sizeof(::rtech::liveapi::CustomMatch_SetMatchmaking)}, + { 550, -1, -1, sizeof(::rtech::liveapi::CustomMatch_SetTeam)}, + { 559, -1, -1, sizeof(::rtech::liveapi::CustomMatch_KickPlayer)}, + { 567, -1, -1, sizeof(::rtech::liveapi::CustomMatch_SetSettings)}, + { 579, -1, -1, sizeof(::rtech::liveapi::CustomMatch_GetSettings)}, + { 585, -1, -1, sizeof(::rtech::liveapi::CustomMatch_SetTeamName)}, + { 593, -1, -1, sizeof(::rtech::liveapi::CustomMatch_SendChat)}, + { 600, -1, -1, sizeof(::rtech::liveapi::Request)}, + { 623, -1, -1, sizeof(::rtech::liveapi::RequestStatus)}, + { 630, -1, -1, sizeof(::rtech::liveapi::Response)}, + { 638, -1, -1, sizeof(::rtech::liveapi::LiveAPIEvent)}, }; static const ::_pb::Message* const file_default_instances[] = { @@ -1819,224 +1821,227 @@ static const ::_pb::Message* const file_default_instances[] = { }; const char descriptor_table_protodef_events_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = - "\n\014events.proto\022\rrtech.liveapi\032\031google/pr" - "otobuf/any.proto\"*\n\007Vector3\022\t\n\001x\030\001 \001(\002\022\t" - "\n\001y\030\002 \001(\002\022\t\n\001z\030\003 \001(\002\"\276\002\n\006Player\022\014\n\004name\030" - "\001 \001(\t\022\016\n\006teamId\030\002 \001(\r\022#\n\003pos\030\003 \001(\0132\026.rte" - "ch.liveapi.Vector3\022&\n\006angles\030\004 \001(\0132\026.rte" - "ch.liveapi.Vector3\022\025\n\rcurrentHealth\030\005 \001(" - "\r\022\021\n\tmaxHealth\030\006 \001(\r\022\024\n\014shieldHealth\030\007 \001" - "(\r\022\027\n\017shieldMaxHealth\030\010 \001(\r\022\023\n\013nucleusHa" - "sh\030\t \001(\t\022\024\n\014hardwareName\030\n \001(\t\022\020\n\010teamNa" - "me\030\013 \001(\t\022\022\n\nsquadIndex\030\014 \001(\r\022\021\n\tcharacte" - "r\030\r \001(\t\022\014\n\004skin\030\016 \001(\t\"b\n\027CustomMatch_Lob" - "byPlayer\022\014\n\004name\030\001 \001(\t\022\016\n\006teamId\030\002 \001(\r\022\023" - "\n\013nucleusHash\030\003 \001(\t\022\024\n\014hardwareName\030\004 \001(" - "\t\"\?\n\nDatacenter\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010ca" - "tegory\030\002 \001(\t\022\014\n\004name\030\003 \001(\t\"V\n\007Version\022\021\n" - "\tmajor_num\030\001 \001(\r\022\021\n\tminor_num\030\002 \001(\r\022\023\n\013b" - "uild_stamp\030\003 \001(\r\022\020\n\010revision\030\004 \001(\t\"B\n\rIn" - "ventoryItem\022\020\n\010quantity\030\001 \001(\005\022\014\n\004item\030\002 " - "\001(\t\022\021\n\textraData\030\003 \001(\t\"v\n\024LoadoutConfigu" - "ration\022-\n\007weapons\030\001 \003(\0132\034.rtech.liveapi." - "InventoryItem\022/\n\tequipment\030\002 \003(\0132\034.rtech" - ".liveapi.InventoryItem\"\214\001\n\004Init\022\021\n\ttimes" - "tamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\023\n\013gameVers" - "ion\030\003 \001(\t\022*\n\napiVersion\030\004 \001(\0132\026.rtech.li" - "veapi.Version\022\020\n\010platform\030\005 \001(\t\022\014\n\004name\030" - "\006 \001(\t\"h\n\030CustomMatch_LobbyPlayers\022\023\n\013pla" - "yerToken\030\001 \001(\t\0227\n\007players\030\002 \003(\0132&.rtech." - "liveapi.CustomMatch_LobbyPlayer\"\262\001\n\020Obse" - "rverSwitched\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010categ" - "ory\030\002 \001(\t\022\'\n\010observer\030\003 \001(\0132\025.rtech.live" - "api.Player\022%\n\006target\030\004 \001(\0132\025.rtech.livea" - "pi.Player\022)\n\ntargetTeam\030\005 \003(\0132\025.rtech.li" - "veapi.Player\"S\n\022ObserverAnnotation\022\021\n\tti" - "mestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\030\n\020annot" - "ationSerial\030\003 \001(\005\"\225\002\n\nMatchSetup\022\021\n\ttime" - "stamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\013\n\003map\030\003 \001" - "(\t\022\024\n\014playlistName\030\004 \001(\t\022\024\n\014playlistDesc" - "\030\005 \001(\t\022-\n\ndatacenter\030\006 \001(\0132\031.rtech.livea" - "pi.Datacenter\022\023\n\013aimAssistOn\030\007 \001(\010\022\025\n\ran" - "onymousMode\030\010 \001(\010\022\020\n\010serverId\030\t \001(\t\022<\n\017s" - "tartingLoadout\030\n \001(\0132#.rtech.liveapi.Loa" - "doutConfiguration\"F\n\020GameStateChanged\022\021\n" - "\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\r\n\005st" - "ate\030\003 \001(\t\"_\n\021CharacterSelected\022\021\n\ttimest" - "amp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006player\030\003 " - "\001(\0132\025.rtech.liveapi.Player\"k\n\rMatchState" - "End\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t" - "\022\r\n\005state\030\003 \001(\t\022&\n\007winners\030\004 \003(\0132\025.rtech" - ".liveapi.Player\"\260\001\n\020RingStartClosing\022\021\n\t" - "timestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\r\n\005sta" - "ge\030\003 \001(\r\022&\n\006center\030\004 \001(\0132\026.rtech.liveapi" - ".Vector3\022\025\n\rcurrentRadius\030\005 \001(\002\022\021\n\tendRa" - "dius\030\006 \001(\002\022\026\n\016shrinkDuration\030\007 \001(\002\"\240\001\n\023R" - "ingFinishedClosing\022\021\n\ttimestamp\030\001 \001(\004\022\020\n" - "\010category\030\002 \001(\t\022\r\n\005stage\030\003 \001(\r\022&\n\006center" - "\030\004 \001(\0132\026.rtech.liveapi.Vector3\022\025\n\rcurren" - "tRadius\030\005 \001(\002\022\026\n\016shrinkDuration\030\007 \001(\002\"]\n" - "\017PlayerConnected\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010c" - "ategory\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.li" - "veapi.Player\"\207\001\n\022PlayerDisconnected\022\021\n\tt" - "imestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006play" - "er\030\003 \001(\0132\025.rtech.liveapi.Player\022\024\n\014canRe" - "connect\030\004 \001(\010\022\017\n\007isAlive\030\005 \001(\010\"\274\001\n\021Playe" - "rStatChanged\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010categ" - "ory\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.liveap" - "i.Player\022\020\n\010statName\030\004 \001(\t\022\022\n\010intValue\030\005" - " \001(\rH\000\022\024\n\nfloatValue\030\006 \001(\002H\000\022\023\n\tboolValu" - "e\030\007 \001(\010H\000B\n\n\010newValue\"u\n\030PlayerUpgradeTi" - "erChanged\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category" - "\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.liveapi.P" - "layer\022\r\n\005level\030\004 \001(\005\"\255\001\n\rPlayerDamaged\022\021" - "\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\'\n\010a" - "ttacker\030\003 \001(\0132\025.rtech.liveapi.Player\022%\n\006" - "victim\030\004 \001(\0132\025.rtech.liveapi.Player\022\016\n\006w" - "eapon\030\005 \001(\t\022\027\n\017damageInflicted\030\006 \001(\r\"\275\001\n" - "\014PlayerKilled\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010cate" - "gory\030\002 \001(\t\022\'\n\010attacker\030\003 \001(\0132\025.rtech.liv" - "eapi.Player\022%\n\006victim\030\004 \001(\0132\025.rtech.live" - "api.Player\022(\n\tawardedTo\030\005 \001(\0132\025.rtech.li" - "veapi.Player\022\016\n\006weapon\030\006 \001(\t\"\223\001\n\014PlayerD" - "owned\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001" - "(\t\022\'\n\010attacker\030\003 \001(\0132\025.rtech.liveapi.Pla" - "yer\022%\n\006victim\030\004 \001(\0132\025.rtech.liveapi.Play" - "er\022\016\n\006weapon\030\005 \001(\t\"\224\001\n\014PlayerAssist\022\021\n\tt" - "imestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022(\n\tassi" - "stant\030\003 \001(\0132\025.rtech.liveapi.Player\022%\n\006vi" - "ctim\030\004 \001(\0132\025.rtech.liveapi.Player\022\016\n\006wea" - "pon\030\005 \001(\t\"^\n\017SquadEliminated\022\021\n\ttimestam" - "p\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022&\n\007players\030\003 \003" - "(\0132\025.rtech.liveapi.Player\"\247\001\n\027GibraltarS" - "hieldAbsorbed\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010cate" - "gory\030\002 \001(\t\022\'\n\010attacker\030\003 \001(\0132\025.rtech.liv" - "eapi.Player\022%\n\006victim\030\004 \001(\0132\025.rtech.live" - "api.Player\022\027\n\017damageInflicted\030\006 \001(\r\"\253\001\n\033" - "RevenantForgedShadowDamaged\022\021\n\ttimestamp" - "\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\'\n\010attacker\030\003 \001" - "(\0132\025.rtech.liveapi.Player\022%\n\006victim\030\004 \001(" - "\0132\025.rtech.liveapi.Player\022\027\n\017damageInflic" - "ted\030\006 \001(\r\"\211\001\n\021PlayerRespawnTeam\022\021\n\ttimes" - "tamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006player\030\003" - " \001(\0132\025.rtech.liveapi.Player\022(\n\trespawned" - "\030\004 \003(\0132\025.rtech.liveapi.Player\"\202\001\n\014Player" - "Revive\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 " - "\001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.liveapi.Play" - "er\022&\n\007revived\030\004 \001(\0132\025.rtech.liveapi.Play" - "er\"\200\001\n\022ArenasItemSelected\022\021\n\ttimestamp\030\001" - " \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025" - ".rtech.liveapi.Player\022\014\n\004item\030\004 \001(\t\022\020\n\010q" - "uantity\030\005 \001(\005\"\202\001\n\024ArenasItemDeselected\022\021" - "\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006p" - "layer\030\003 \001(\0132\025.rtech.liveapi.Player\022\014\n\004it" - "em\030\004 \001(\t\022\020\n\010quantity\030\005 \001(\005\"}\n\017InventoryP" - "ickUp\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001" - "(\t\022%\n\006player\030\003 \001(\0132\025.rtech.liveapi.Playe" - "r\022\014\n\004item\030\004 \001(\t\022\020\n\010quantity\030\005 \001(\005\"\216\001\n\rIn" - "ventoryDrop\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010catego" - "ry\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.liveapi" - ".Player\022\014\n\004item\030\004 \001(\t\022\020\n\010quantity\030\005 \001(\005\022" - "\021\n\textraData\030\006 \003(\t\"z\n\014InventoryUse\022\021\n\tti" - "mestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006playe" - "r\030\003 \001(\0132\025.rtech.liveapi.Player\022\014\n\004item\030\004" - " \001(\t\022\020\n\010quantity\030\005 \001(\005\"\207\001\n\017BannerCollect" + "\n\014events.proto\022\rrtech.liveapi\032\034google/pr" + "otobuf/struct.proto\032\031google/protobuf/any" + ".proto\"*\n\007Vector3\022\t\n\001x\030\001 \001(\002\022\t\n\001y\030\002 \001(\002\022" + "\t\n\001z\030\003 \001(\002\"\276\002\n\006Player\022\014\n\004name\030\001 \001(\t\022\016\n\006t" + "eamId\030\002 \001(\r\022#\n\003pos\030\003 \001(\0132\026.rtech.liveapi" + ".Vector3\022&\n\006angles\030\004 \001(\0132\026.rtech.liveapi" + ".Vector3\022\025\n\rcurrentHealth\030\005 \001(\r\022\021\n\tmaxHe" + "alth\030\006 \001(\r\022\024\n\014shieldHealth\030\007 \001(\r\022\027\n\017shie" + "ldMaxHealth\030\010 \001(\r\022\023\n\013nucleusHash\030\t \001(\t\022\024" + "\n\014hardwareName\030\n \001(\t\022\020\n\010teamName\030\013 \001(\t\022\022" + "\n\nsquadIndex\030\014 \001(\r\022\021\n\tcharacter\030\r \001(\t\022\014\n" + "\004skin\030\016 \001(\t\"b\n\027CustomMatch_LobbyPlayer\022\014" + "\n\004name\030\001 \001(\t\022\016\n\006teamId\030\002 \001(\r\022\023\n\013nucleusH" + "ash\030\003 \001(\t\022\024\n\014hardwareName\030\004 \001(\t\"\?\n\nDatac" + "enter\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001" + "(\t\022\014\n\004name\030\003 \001(\t\"V\n\007Version\022\021\n\tmajor_num" + "\030\001 \001(\r\022\021\n\tminor_num\030\002 \001(\r\022\023\n\013build_stamp" + "\030\003 \001(\r\022\020\n\010revision\030\004 \001(\t\"B\n\rInventoryIte" + "m\022\020\n\010quantity\030\001 \001(\005\022\014\n\004item\030\002 \001(\t\022\021\n\text" + "raData\030\003 \001(\t\"v\n\024LoadoutConfiguration\022-\n\007" + "weapons\030\001 \003(\0132\034.rtech.liveapi.InventoryI" + "tem\022/\n\tequipment\030\002 \003(\0132\034.rtech.liveapi.I" + "nventoryItem\"\214\001\n\004Init\022\021\n\ttimestamp\030\001 \001(\004" + "\022\020\n\010category\030\002 \001(\t\022\023\n\013gameVersion\030\003 \001(\t\022" + "*\n\napiVersion\030\004 \001(\0132\026.rtech.liveapi.Vers" + "ion\022\020\n\010platform\030\005 \001(\t\022\014\n\004name\030\006 \001(\t\"h\n\030C" + "ustomMatch_LobbyPlayers\022\023\n\013playerToken\030\001" + " \001(\t\0227\n\007players\030\002 \003(\0132&.rtech.liveapi.Cu" + "stomMatch_LobbyPlayer\"\262\001\n\020ObserverSwitch" "ed\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022" - "%\n\006player\030\003 \001(\0132\025.rtech.liveapi.Player\022(" - "\n\tcollected\030\004 \001(\0132\025.rtech.liveapi.Player" - "\"u\n\021PlayerAbilityUsed\022\021\n\ttimestamp\030\001 \001(\004" - "\022\020\n\010category\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rte" - "ch.liveapi.Player\022\024\n\014linkedEntity\030\004 \001(\t\"" - "\234\001\n\025LegendUpgradeSelected\022\021\n\ttimestamp\030\001" + "\'\n\010observer\030\003 \001(\0132\025.rtech.liveapi.Player" + "\022%\n\006target\030\004 \001(\0132\025.rtech.liveapi.Player\022" + ")\n\ntargetTeam\030\005 \003(\0132\025.rtech.liveapi.Play" + "er\"S\n\022ObserverAnnotation\022\021\n\ttimestamp\030\001 " + "\001(\004\022\020\n\010category\030\002 \001(\t\022\030\n\020annotationSeria" + "l\030\003 \001(\005\"\225\002\n\nMatchSetup\022\021\n\ttimestamp\030\001 \001(" + "\004\022\020\n\010category\030\002 \001(\t\022\013\n\003map\030\003 \001(\t\022\024\n\014play" + "listName\030\004 \001(\t\022\024\n\014playlistDesc\030\005 \001(\t\022-\n\n" + "datacenter\030\006 \001(\0132\031.rtech.liveapi.Datacen" + "ter\022\023\n\013aimAssistOn\030\007 \001(\010\022\025\n\ranonymousMod" + "e\030\010 \001(\010\022\020\n\010serverId\030\t \001(\t\022<\n\017startingLoa" + "dout\030\n \001(\0132#.rtech.liveapi.LoadoutConfig" + "uration\"F\n\020GameStateChanged\022\021\n\ttimestamp" + "\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\r\n\005state\030\003 \001(\t\"" + "_\n\021CharacterSelected\022\021\n\ttimestamp\030\001 \001(\004\022" + "\020\n\010category\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rtec" + "h.liveapi.Player\"k\n\rMatchStateEnd\022\021\n\ttim" + "estamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\r\n\005state\030" + "\003 \001(\t\022&\n\007winners\030\004 \003(\0132\025.rtech.liveapi.P" + "layer\"\260\001\n\020RingStartClosing\022\021\n\ttimestamp\030" + "\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\r\n\005stage\030\003 \001(\r\022&" + "\n\006center\030\004 \001(\0132\026.rtech.liveapi.Vector3\022\025" + "\n\rcurrentRadius\030\005 \001(\002\022\021\n\tendRadius\030\006 \001(\002" + "\022\026\n\016shrinkDuration\030\007 \001(\002\"\240\001\n\023RingFinishe" + "dClosing\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030" + "\002 \001(\t\022\r\n\005stage\030\003 \001(\r\022&\n\006center\030\004 \001(\0132\026.r" + "tech.liveapi.Vector3\022\025\n\rcurrentRadius\030\005 " + "\001(\002\022\026\n\016shrinkDuration\030\007 \001(\002\"]\n\017PlayerCon" + "nected\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 " + "\001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.liveapi.Play" + "er\"\207\001\n\022PlayerDisconnected\022\021\n\ttimestamp\030\001" " \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025" - ".rtech.liveapi.Player\022\023\n\013upgradeName\030\004 \001" - "(\t\022\023\n\013upgradeDesc\030\005 \001(\t\022\r\n\005level\030\006 \001(\005\"o" - "\n\013ZiplineUsed\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010cate" - "gory\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.livea" - "pi.Player\022\024\n\014linkedEntity\030\004 \001(\t\"q\n\rGrena" - "deThrown\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030" - "\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.liveapi.Pl" - "ayer\022\024\n\014linkedEntity\030\004 \001(\t\"m\n\021BlackMarke" - "tAction\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002" - " \001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.liveapi.Pla" - "yer\022\014\n\004item\030\004 \001(\t\"Z\n\014WraithPortal\022\021\n\ttim" - "estamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006player" - "\030\003 \001(\0132\025.rtech.liveapi.Player\"Z\n\014WarpGat" - "eUsed\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001" - "(\t\022%\n\006player\030\003 \001(\0132\025.rtech.liveapi.Playe" - "r\"\250\001\n\010AmmoUsed\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010cat" - "egory\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.live" - "api.Player\022\020\n\010ammoType\030\004 \001(\t\022\022\n\namountUs" - "ed\030\005 \001(\r\022\024\n\014oldAmmoCount\030\006 \001(\r\022\024\n\014newAmm" - "oCount\030\007 \001(\r\"\202\001\n\016WeaponSwitched\022\021\n\ttimes" - "tamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006player\030\003" - " \001(\0132\025.rtech.liveapi.Player\022\021\n\toldWeapon" - "\030\004 \001(\t\022\021\n\tnewWeapon\030\005 \001(\t\"\\\n\013CustomEvent" - "\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022(\n" - "\ncustomData\030\003 \003(\0132\024.google.protobuf.Any\"" - "X\n\014ChangeCamera\022.\n\003poi\030\001 \001(\0162\037.rtech.liv" - "eapi.PlayerOfInterestH\000\022\016\n\004name\030\002 \001(\tH\000B" - "\010\n\006target\"\037\n\013PauseToggle\022\020\n\010preTimer\030\001 \001" - "(\002\"\031\n\027CustomMatch_CreateLobby\"*\n\025CustomM" - "atch_JoinLobby\022\021\n\troleToken\030\001 \001(\t\"\030\n\026Cus" - "tomMatch_LeaveLobby\"\'\n\024CustomMatch_SetRe" - "ady\022\017\n\007isReady\030\001 \001(\010\"\035\n\033CustomMatch_GetL" - "obbyPlayers\"-\n\032CustomMatch_SetMatchmakin" - "g\022\017\n\007enabled\030\001 \001(\010\"\\\n\023CustomMatch_SetTea" - "m\022\016\n\006teamId\030\001 \001(\005\022\032\n\022targetHardwareName\030" - "\002 \001(\t\022\031\n\021targetNucleusHash\030\003 \001(\t\"O\n\026Cust" - "omMatch_KickPlayer\022\032\n\022targetHardwareName" - "\030\001 \001(\t\022\031\n\021targetNucleusHash\030\002 \001(\t\"\217\001\n\027Cu" - "stomMatch_SetSettings\022\024\n\014playlistName\030\001 " - "\001(\t\022\021\n\tadminChat\030\002 \001(\010\022\022\n\nteamRename\030\003 \001" - "(\010\022\022\n\nselfAssign\030\004 \001(\010\022\021\n\taimAssist\030\005 \001(" - "\010\022\020\n\010anonMode\030\006 \001(\010\"\031\n\027CustomMatch_GetSe" - "ttings\";\n\027CustomMatch_SetTeamName\022\016\n\006tea" - "mId\030\001 \001(\005\022\020\n\010teamName\030\002 \001(\t\"$\n\024CustomMat" - "ch_SendChat\022\014\n\004text\030\001 \001(\t\"\226\010\n\007Request\022\017\n" - "\007withAck\030\001 \001(\010\022\024\n\014preSharedKey\030\002 \001(\t\0220\n\t" - "changeCam\030\004 \001(\0132\033.rtech.liveapi.ChangeCa" - "meraH\000\0221\n\013pauseToggle\030\005 \001(\0132\032.rtech.live" - "api.PauseToggleH\000\022I\n\027customMatch_CreateL" - "obby\030\n \001(\0132&.rtech.liveapi.CustomMatch_C" - "reateLobbyH\000\022E\n\025customMatch_JoinLobby\030\013 " - "\001(\0132$.rtech.liveapi.CustomMatch_JoinLobb" - "yH\000\022G\n\026customMatch_LeaveLobby\030\014 \001(\0132%.rt" - "ech.liveapi.CustomMatch_LeaveLobbyH\000\022C\n\024" - "customMatch_SetReady\030\r \001(\0132#.rtech.livea" - "pi.CustomMatch_SetReadyH\000\022O\n\032customMatch" - "_SetMatchmaking\030\016 \001(\0132).rtech.liveapi.Cu" - "stomMatch_SetMatchmakingH\000\022A\n\023customMatc" - "h_SetTeam\030\017 \001(\0132\".rtech.liveapi.CustomMa" - "tch_SetTeamH\000\022G\n\026customMatch_KickPlayer\030" - "\020 \001(\0132%.rtech.liveapi.CustomMatch_KickPl" - "ayerH\000\022I\n\027customMatch_SetSettings\030\021 \001(\0132" - "&.rtech.liveapi.CustomMatch_SetSettingsH" - "\000\022C\n\024customMatch_SendChat\030\022 \001(\0132#.rtech." - "liveapi.CustomMatch_SendChatH\000\022Q\n\033custom" - "Match_GetLobbyPlayers\030\023 \001(\0132*.rtech.live" - "api.CustomMatch_GetLobbyPlayersH\000\022I\n\027cus" - "tomMatch_SetTeamName\030\024 \001(\0132&.rtech.livea" - "pi.CustomMatch_SetTeamNameH\000\022I\n\027customMa" - "tch_GetSettings\030\025 \001(\0132&.rtech.liveapi.Cu" - "stomMatch_GetSettingsH\000B\t\n\007actions\"\037\n\rRe" - "questStatus\022\016\n\006status\030\001 \001(\t\"A\n\010Response\022" - "\017\n\007success\030\001 \001(\010\022$\n\006result\030\002 \001(\0132\024.googl" - "e.protobuf.Any\"M\n\014LiveAPIEvent\022\022\n\nevent_" - "size\030\001 \001(\007\022)\n\013gameMessage\030\003 \001(\0132\024.google" - ".protobuf.Any*\210\001\n\020PlayerOfInterest\022\017\n\013UN" - "SPECIFIED\020\000\022\010\n\004NEXT\020\001\022\014\n\010PREVIOUS\020\002\022\017\n\013K" - "ILL_LEADER\020\003\022\021\n\rCLOSEST_ENEMY\020\004\022\022\n\016CLOSE" - "ST_PLAYER\020\005\022\023\n\017LATEST_ATTACKER\020\006b\006proto3" + ".rtech.liveapi.Player\022\024\n\014canReconnect\030\004 " + "\001(\010\022\017\n\007isAlive\030\005 \001(\010\"\274\001\n\021PlayerStatChang" + "ed\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022" + "%\n\006player\030\003 \001(\0132\025.rtech.liveapi.Player\022\020" + "\n\010statName\030\004 \001(\t\022\022\n\010intValue\030\005 \001(\rH\000\022\024\n\n" + "floatValue\030\006 \001(\002H\000\022\023\n\tboolValue\030\007 \001(\010H\000B" + "\n\n\010newValue\"u\n\030PlayerUpgradeTierChanged\022" + "\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006" + "player\030\003 \001(\0132\025.rtech.liveapi.Player\022\r\n\005l" + "evel\030\004 \001(\005\"\255\001\n\rPlayerDamaged\022\021\n\ttimestam" + "p\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\'\n\010attacker\030\003 " + "\001(\0132\025.rtech.liveapi.Player\022%\n\006victim\030\004 \001" + "(\0132\025.rtech.liveapi.Player\022\016\n\006weapon\030\005 \001(" + "\t\022\027\n\017damageInflicted\030\006 \001(\r\"\275\001\n\014PlayerKil" + "led\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t" + "\022\'\n\010attacker\030\003 \001(\0132\025.rtech.liveapi.Playe" + "r\022%\n\006victim\030\004 \001(\0132\025.rtech.liveapi.Player" + "\022(\n\tawardedTo\030\005 \001(\0132\025.rtech.liveapi.Play" + "er\022\016\n\006weapon\030\006 \001(\t\"\223\001\n\014PlayerDowned\022\021\n\tt" + "imestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\'\n\010atta" + "cker\030\003 \001(\0132\025.rtech.liveapi.Player\022%\n\006vic" + "tim\030\004 \001(\0132\025.rtech.liveapi.Player\022\016\n\006weap" + "on\030\005 \001(\t\"\224\001\n\014PlayerAssist\022\021\n\ttimestamp\030\001" + " \001(\004\022\020\n\010category\030\002 \001(\t\022(\n\tassistant\030\003 \001(" + "\0132\025.rtech.liveapi.Player\022%\n\006victim\030\004 \001(\013" + "2\025.rtech.liveapi.Player\022\016\n\006weapon\030\005 \001(\t\"" + "^\n\017SquadEliminated\022\021\n\ttimestamp\030\001 \001(\004\022\020\n" + "\010category\030\002 \001(\t\022&\n\007players\030\003 \003(\0132\025.rtech" + ".liveapi.Player\"\247\001\n\027GibraltarShieldAbsor" + "bed\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t" + "\022\'\n\010attacker\030\003 \001(\0132\025.rtech.liveapi.Playe" + "r\022%\n\006victim\030\004 \001(\0132\025.rtech.liveapi.Player" + "\022\027\n\017damageInflicted\030\006 \001(\r\"\253\001\n\033RevenantFo" + "rgedShadowDamaged\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010" + "category\030\002 \001(\t\022\'\n\010attacker\030\003 \001(\0132\025.rtech" + ".liveapi.Player\022%\n\006victim\030\004 \001(\0132\025.rtech." + "liveapi.Player\022\027\n\017damageInflicted\030\006 \001(\r\"" + "\211\001\n\021PlayerRespawnTeam\022\021\n\ttimestamp\030\001 \001(\004" + "\022\020\n\010category\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rte" + "ch.liveapi.Player\022(\n\trespawned\030\004 \003(\0132\025.r" + "tech.liveapi.Player\"\202\001\n\014PlayerRevive\022\021\n\t" + "timestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006pla" + "yer\030\003 \001(\0132\025.rtech.liveapi.Player\022&\n\007revi" + "ved\030\004 \001(\0132\025.rtech.liveapi.Player\"\200\001\n\022Are" + "nasItemSelected\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010ca" + "tegory\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.liv" + "eapi.Player\022\014\n\004item\030\004 \001(\t\022\020\n\010quantity\030\005 " + "\001(\005\"\202\001\n\024ArenasItemDeselected\022\021\n\ttimestam" + "p\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006player\030\003 \001(" + "\0132\025.rtech.liveapi.Player\022\014\n\004item\030\004 \001(\t\022\020" + "\n\010quantity\030\005 \001(\005\"}\n\017InventoryPickUp\022\021\n\tt" + "imestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006play" + "er\030\003 \001(\0132\025.rtech.liveapi.Player\022\014\n\004item\030" + "\004 \001(\t\022\020\n\010quantity\030\005 \001(\005\"\216\001\n\rInventoryDro" + "p\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%" + "\n\006player\030\003 \001(\0132\025.rtech.liveapi.Player\022\014\n" + "\004item\030\004 \001(\t\022\020\n\010quantity\030\005 \001(\005\022\021\n\textraDa" + "ta\030\006 \003(\t\"z\n\014InventoryUse\022\021\n\ttimestamp\030\001 " + "\001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025." + "rtech.liveapi.Player\022\014\n\004item\030\004 \001(\t\022\020\n\010qu" + "antity\030\005 \001(\005\"\207\001\n\017BannerCollected\022\021\n\ttime" + "stamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006player\030" + "\003 \001(\0132\025.rtech.liveapi.Player\022(\n\tcollecte" + "d\030\004 \001(\0132\025.rtech.liveapi.Player\"u\n\021Player" + "AbilityUsed\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010catego" + "ry\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.liveapi" + ".Player\022\024\n\014linkedEntity\030\004 \001(\t\"\234\001\n\025Legend" + "UpgradeSelected\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010ca" + "tegory\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rtech.liv" + "eapi.Player\022\023\n\013upgradeName\030\004 \001(\t\022\023\n\013upgr" + "adeDesc\030\005 \001(\t\022\r\n\005level\030\006 \001(\005\"o\n\013ZiplineU" + "sed\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t" + "\022%\n\006player\030\003 \001(\0132\025.rtech.liveapi.Player\022" + "\024\n\014linkedEntity\030\004 \001(\t\"q\n\rGrenadeThrown\022\021" + "\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006p" + "layer\030\003 \001(\0132\025.rtech.liveapi.Player\022\024\n\014li" + "nkedEntity\030\004 \001(\t\"m\n\021BlackMarketAction\022\021\n" + "\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006pl" + "ayer\030\003 \001(\0132\025.rtech.liveapi.Player\022\014\n\004ite" + "m\030\004 \001(\t\"Z\n\014WraithPortal\022\021\n\ttimestamp\030\001 \001" + "(\004\022\020\n\010category\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.r" + "tech.liveapi.Player\"Z\n\014WarpGateUsed\022\021\n\tt" + "imestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022%\n\006play" + "er\030\003 \001(\0132\025.rtech.liveapi.Player\"\250\001\n\010Ammo" + "Used\022\021\n\ttimestamp\030\001 \001(\004\022\020\n\010category\030\002 \001(" + "\t\022%\n\006player\030\003 \001(\0132\025.rtech.liveapi.Player" + "\022\020\n\010ammoType\030\004 \001(\t\022\022\n\namountUsed\030\005 \001(\r\022\024" + "\n\014oldAmmoCount\030\006 \001(\r\022\024\n\014newAmmoCount\030\007 \001" + "(\r\"\202\001\n\016WeaponSwitched\022\021\n\ttimestamp\030\001 \001(\004" + "\022\020\n\010category\030\002 \001(\t\022%\n\006player\030\003 \001(\0132\025.rte" + "ch.liveapi.Player\022\021\n\toldWeapon\030\004 \001(\t\022\021\n\t" + "newWeapon\030\005 \001(\t\"g\n\013CustomEvent\022\021\n\ttimest" + "amp\030\001 \001(\004\022\020\n\010category\030\002 \001(\t\022\014\n\004name\030\003 \001(" + "\t\022%\n\004data\030\004 \001(\0132\027.google.protobuf.Struct" + "\"X\n\014ChangeCamera\022.\n\003poi\030\001 \001(\0162\037.rtech.li" + "veapi.PlayerOfInterestH\000\022\016\n\004name\030\002 \001(\tH\000" + "B\010\n\006target\"\037\n\013PauseToggle\022\020\n\010preTimer\030\001 " + "\001(\002\"\031\n\027CustomMatch_CreateLobby\"*\n\025Custom" + "Match_JoinLobby\022\021\n\troleToken\030\001 \001(\t\"\030\n\026Cu" + "stomMatch_LeaveLobby\"\'\n\024CustomMatch_SetR" + "eady\022\017\n\007isReady\030\001 \001(\010\"\035\n\033CustomMatch_Get" + "LobbyPlayers\"-\n\032CustomMatch_SetMatchmaki" + "ng\022\017\n\007enabled\030\001 \001(\010\"\\\n\023CustomMatch_SetTe" + "am\022\016\n\006teamId\030\001 \001(\005\022\032\n\022targetHardwareName" + "\030\002 \001(\t\022\031\n\021targetNucleusHash\030\003 \001(\t\"O\n\026Cus" + "tomMatch_KickPlayer\022\032\n\022targetHardwareNam" + "e\030\001 \001(\t\022\031\n\021targetNucleusHash\030\002 \001(\t\"\217\001\n\027C" + "ustomMatch_SetSettings\022\024\n\014playlistName\030\001" + " \001(\t\022\021\n\tadminChat\030\002 \001(\010\022\022\n\nteamRename\030\003 " + "\001(\010\022\022\n\nselfAssign\030\004 \001(\010\022\021\n\taimAssist\030\005 \001" + "(\010\022\020\n\010anonMode\030\006 \001(\010\"\031\n\027CustomMatch_GetS" + "ettings\";\n\027CustomMatch_SetTeamName\022\016\n\006te" + "amId\030\001 \001(\005\022\020\n\010teamName\030\002 \001(\t\"$\n\024CustomMa" + "tch_SendChat\022\014\n\004text\030\001 \001(\t\"\226\010\n\007Request\022\017" + "\n\007withAck\030\001 \001(\010\022\024\n\014preSharedKey\030\002 \001(\t\0220\n" + "\tchangeCam\030\004 \001(\0132\033.rtech.liveapi.ChangeC" + "ameraH\000\0221\n\013pauseToggle\030\005 \001(\0132\032.rtech.liv" + "eapi.PauseToggleH\000\022I\n\027customMatch_Create" + "Lobby\030\n \001(\0132&.rtech.liveapi.CustomMatch_" + "CreateLobbyH\000\022E\n\025customMatch_JoinLobby\030\013" + " \001(\0132$.rtech.liveapi.CustomMatch_JoinLob" + "byH\000\022G\n\026customMatch_LeaveLobby\030\014 \001(\0132%.r" + "tech.liveapi.CustomMatch_LeaveLobbyH\000\022C\n" + "\024customMatch_SetReady\030\r \001(\0132#.rtech.live" + "api.CustomMatch_SetReadyH\000\022O\n\032customMatc" + "h_SetMatchmaking\030\016 \001(\0132).rtech.liveapi.C" + "ustomMatch_SetMatchmakingH\000\022A\n\023customMat" + "ch_SetTeam\030\017 \001(\0132\".rtech.liveapi.CustomM" + "atch_SetTeamH\000\022G\n\026customMatch_KickPlayer" + "\030\020 \001(\0132%.rtech.liveapi.CustomMatch_KickP" + "layerH\000\022I\n\027customMatch_SetSettings\030\021 \001(\013" + "2&.rtech.liveapi.CustomMatch_SetSettings" + "H\000\022C\n\024customMatch_SendChat\030\022 \001(\0132#.rtech" + ".liveapi.CustomMatch_SendChatH\000\022Q\n\033custo" + "mMatch_GetLobbyPlayers\030\023 \001(\0132*.rtech.liv" + "eapi.CustomMatch_GetLobbyPlayersH\000\022I\n\027cu" + "stomMatch_SetTeamName\030\024 \001(\0132&.rtech.live" + "api.CustomMatch_SetTeamNameH\000\022I\n\027customM" + "atch_GetSettings\030\025 \001(\0132&.rtech.liveapi.C" + "ustomMatch_GetSettingsH\000B\t\n\007actions\"\037\n\rR" + "equestStatus\022\016\n\006status\030\001 \001(\t\"A\n\010Response" + "\022\017\n\007success\030\001 \001(\010\022$\n\006result\030\002 \001(\0132\024.goog" + "le.protobuf.Any\"M\n\014LiveAPIEvent\022\022\n\nevent" + "_size\030\001 \001(\007\022)\n\013gameMessage\030\003 \001(\0132\024.googl" + "e.protobuf.Any*\210\001\n\020PlayerOfInterest\022\017\n\013U" + "NSPECIFIED\020\000\022\010\n\004NEXT\020\001\022\014\n\010PREVIOUS\020\002\022\017\n\013" + "KILL_LEADER\020\003\022\021\n\rCLOSEST_ENEMY\020\004\022\022\n\016CLOS" + "EST_PLAYER\020\005\022\023\n\017LATEST_ATTACKER\020\006b\006proto" + "3" ; -static const ::_pbi::DescriptorTable* const descriptor_table_events_2eproto_deps[1] = { +static const ::_pbi::DescriptorTable* const descriptor_table_events_2eproto_deps[2] = { &::descriptor_table_google_2fprotobuf_2fany_2eproto, + &::descriptor_table_google_2fprotobuf_2fstruct_2eproto, }; static ::_pbi::once_flag descriptor_table_events_2eproto_once; const ::_pbi::DescriptorTable descriptor_table_events_2eproto = { - false, false, 8360, descriptor_table_protodef_events_2eproto, + false, false, 8401, descriptor_table_protodef_events_2eproto, "events.proto", - &descriptor_table_events_2eproto_once, descriptor_table_events_2eproto_deps, 1, 64, + &descriptor_table_events_2eproto_once, descriptor_table_events_2eproto_deps, 2, 64, schemas, file_default_instances, TableStruct_events_2eproto::offsets, file_level_metadata_events_2eproto, file_level_enum_descriptors_events_2eproto, file_level_service_descriptors_events_2eproto, @@ -17582,10 +17587,18 @@ void WeaponSwitched::InternalSwap(WeaponSwitched* other) { class CustomEvent::_Internal { public: + static const ::PROTOBUF_NAMESPACE_ID::Struct& data(const CustomEvent* msg); }; -void CustomEvent::clear_customdata() { - _impl_.customdata_.Clear(); +const ::PROTOBUF_NAMESPACE_ID::Struct& +CustomEvent::_Internal::data(const CustomEvent* msg) { + return *msg->_impl_.data_; +} +void CustomEvent::clear_data() { + if (GetArenaForAllocation() == nullptr && _impl_.data_ != nullptr) { + delete _impl_.data_; + } + _impl_.data_ = nullptr; } CustomEvent::CustomEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned) @@ -17597,8 +17610,9 @@ CustomEvent::CustomEvent(const CustomEvent& from) : ::PROTOBUF_NAMESPACE_ID::Message() { CustomEvent* const _this = this; (void)_this; new (&_impl_) Impl_{ - decltype(_impl_.customdata_){from._impl_.customdata_} - , decltype(_impl_.category_){} + decltype(_impl_.category_){} + , decltype(_impl_.name_){} + , decltype(_impl_.data_){nullptr} , decltype(_impl_.timestamp_){} , /*decltype(_impl_._cached_size_)*/{}}; @@ -17611,6 +17625,17 @@ CustomEvent::CustomEvent(const CustomEvent& from) _this->_impl_.category_.Set(from._internal_category(), _this->GetArenaForAllocation()); } + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_name().empty()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_data()) { + _this->_impl_.data_ = new ::PROTOBUF_NAMESPACE_ID::Struct(*from._impl_.data_); + } _this->_impl_.timestamp_ = from._impl_.timestamp_; // @@protoc_insertion_point(copy_constructor:rtech.liveapi.CustomEvent) } @@ -17620,8 +17645,9 @@ inline void CustomEvent::SharedCtor( (void)arena; (void)is_message_owned; new (&_impl_) Impl_{ - decltype(_impl_.customdata_){arena} - , decltype(_impl_.category_){} + decltype(_impl_.category_){} + , decltype(_impl_.name_){} + , decltype(_impl_.data_){nullptr} , decltype(_impl_.timestamp_){uint64_t{0u}} , /*decltype(_impl_._cached_size_)*/{} }; @@ -17629,6 +17655,10 @@ inline void CustomEvent::SharedCtor( #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING _impl_.category_.Set("", GetArenaForAllocation()); #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING } CustomEvent::~CustomEvent() { @@ -17642,8 +17672,9 @@ CustomEvent::~CustomEvent() { inline void CustomEvent::SharedDtor() { GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); - _impl_.customdata_.~RepeatedPtrField(); _impl_.category_.Destroy(); + _impl_.name_.Destroy(); + if (this != internal_default_instance()) delete _impl_.data_; } void CustomEvent::SetCachedSize(int size) const { @@ -17656,8 +17687,12 @@ void CustomEvent::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - _impl_.customdata_.Clear(); _impl_.category_.ClearToEmpty(); + _impl_.name_.ClearToEmpty(); + if (GetArenaForAllocation() == nullptr && _impl_.data_ != nullptr) { + delete _impl_.data_; + } + _impl_.data_ = nullptr; _impl_.timestamp_ = uint64_t{0u}; _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } @@ -17686,16 +17721,21 @@ const char* CustomEvent::_InternalParse(const char* ptr, ::_pbi::ParseContext* c } else goto handle_unusual; continue; - // repeated .google.protobuf.Any customData = 3; + // string name = 3; case 3: if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 26)) { - ptr -= 1; - do { - ptr += 1; - ptr = ctx->ParseMessage(_internal_add_customdata(), ptr); - CHK_(ptr); - if (!ctx->DataAvailable(ptr)) break; - } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr)); + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "rtech.liveapi.CustomEvent.name")); + } else + goto handle_unusual; + continue; + // .google.protobuf.Struct data = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 34)) { + ptr = ctx->ParseMessage(_internal_mutable_data(), ptr); + CHK_(ptr); } else goto handle_unusual; continue; @@ -17744,12 +17784,21 @@ uint8_t* CustomEvent::_InternalSerialize( 2, this->_internal_category(), target); } - // repeated .google.protobuf.Any customData = 3; - for (unsigned i = 0, - n = static_cast(this->_internal_customdata_size()); i < n; i++) { - const auto& repfield = this->_internal_customdata(i); + // string name = 3; + if (!this->_internal_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "rtech.liveapi.CustomEvent.name"); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_name(), target); + } + + // .google.protobuf.Struct data = 4; + if (this->_internal_has_data()) { target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: - InternalWriteMessage(3, repfield, repfield.GetCachedSize(), target, stream); + InternalWriteMessage(4, _Internal::data(this), + _Internal::data(this).GetCachedSize(), target, stream); } if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { @@ -17768,13 +17817,6 @@ size_t CustomEvent::ByteSizeLong() const { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - // repeated .google.protobuf.Any customData = 3; - total_size += 1UL * this->_internal_customdata_size(); - for (const auto& msg : this->_impl_.customdata_) { - total_size += - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); - } - // string category = 2; if (!this->_internal_category().empty()) { total_size += 1 + @@ -17782,6 +17824,20 @@ size_t CustomEvent::ByteSizeLong() const { this->_internal_category()); } + // string name = 3; + if (!this->_internal_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // .google.protobuf.Struct data = 4; + if (this->_internal_has_data()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.data_); + } + // uint64 timestamp = 1; if (this->_internal_timestamp() != 0) { total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne(this->_internal_timestamp()); @@ -17805,10 +17861,16 @@ void CustomEvent::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PR uint32_t cached_has_bits = 0; (void) cached_has_bits; - _this->_impl_.customdata_.MergeFrom(from._impl_.customdata_); if (!from._internal_category().empty()) { _this->_internal_set_category(from._internal_category()); } + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } + if (from._internal_has_data()) { + _this->_internal_mutable_data()->::PROTOBUF_NAMESPACE_ID::Struct::MergeFrom( + from._internal_data()); + } if (from._internal_timestamp() != 0) { _this->_internal_set_timestamp(from._internal_timestamp()); } @@ -17831,12 +17893,20 @@ void CustomEvent::InternalSwap(CustomEvent* other) { auto* lhs_arena = GetArenaForAllocation(); auto* rhs_arena = other->GetArenaForAllocation(); _internal_metadata_.InternalSwap(&other->_internal_metadata_); - _impl_.customdata_.InternalSwap(&other->_impl_.customdata_); ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( &_impl_.category_, lhs_arena, &other->_impl_.category_, rhs_arena ); - swap(_impl_.timestamp_, other->_impl_.timestamp_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(CustomEvent, _impl_.timestamp_) + + sizeof(CustomEvent::_impl_.timestamp_) + - PROTOBUF_FIELD_OFFSET(CustomEvent, _impl_.data_)>( + reinterpret_cast(&_impl_.data_), + reinterpret_cast(&other->_impl_.data_)); } ::PROTOBUF_NAMESPACE_ID::Metadata CustomEvent::GetMetadata() const { diff --git a/src/game/server/liveapi/events.pb.h b/src/protoc/events.pb.h similarity index 99% rename from src/game/server/liveapi/events.pb.h rename to src/protoc/events.pb.h index 29844715..e59b7327 100644 --- a/src/game/server/liveapi/events.pb.h +++ b/src/protoc/events.pb.h @@ -32,6 +32,7 @@ #include // IWYU pragma: export #include #include +#include #include // @@protoc_insertion_point(includes) #include @@ -9909,28 +9910,11 @@ class CustomEvent final : // accessors ------------------------------------------------------- enum : int { - kCustomDataFieldNumber = 3, kCategoryFieldNumber = 2, + kNameFieldNumber = 3, + kDataFieldNumber = 4, kTimestampFieldNumber = 1, }; - // repeated .google.protobuf.Any customData = 3; - int customdata_size() const; - private: - int _internal_customdata_size() const; - public: - void clear_customdata(); - ::PROTOBUF_NAMESPACE_ID::Any* mutable_customdata(int index); - ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Any >* - mutable_customdata(); - private: - const ::PROTOBUF_NAMESPACE_ID::Any& _internal_customdata(int index) const; - ::PROTOBUF_NAMESPACE_ID::Any* _internal_add_customdata(); - public: - const ::PROTOBUF_NAMESPACE_ID::Any& customdata(int index) const; - ::PROTOBUF_NAMESPACE_ID::Any* add_customdata(); - const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Any >& - customdata() const; - // string category = 2; void clear_category(); const std::string& category() const; @@ -9945,6 +9929,38 @@ class CustomEvent final : std::string* _internal_mutable_category(); public: + // string name = 3; + void clear_name(); + const std::string& name() const; + template + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // .google.protobuf.Struct data = 4; + bool has_data() const; + private: + bool _internal_has_data() const; + public: + void clear_data(); + const ::PROTOBUF_NAMESPACE_ID::Struct& data() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::Struct* release_data(); + ::PROTOBUF_NAMESPACE_ID::Struct* mutable_data(); + void set_allocated_data(::PROTOBUF_NAMESPACE_ID::Struct* data); + private: + const ::PROTOBUF_NAMESPACE_ID::Struct& _internal_data() const; + ::PROTOBUF_NAMESPACE_ID::Struct* _internal_mutable_data(); + public: + void unsafe_arena_set_allocated_data( + ::PROTOBUF_NAMESPACE_ID::Struct* data); + ::PROTOBUF_NAMESPACE_ID::Struct* unsafe_arena_release_data(); + // uint64 timestamp = 1; void clear_timestamp(); uint64_t timestamp() const; @@ -9962,8 +9978,9 @@ class CustomEvent final : typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; struct Impl_ { - ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Any > customdata_; ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr category_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::Struct* data_; uint64_t timestamp_; mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; }; @@ -23499,41 +23516,139 @@ inline void CustomEvent::set_allocated_category(std::string* category) { // @@protoc_insertion_point(field_set_allocated:rtech.liveapi.CustomEvent.category) } -// repeated .google.protobuf.Any customData = 3; -inline int CustomEvent::_internal_customdata_size() const { - return _impl_.customdata_.size(); +// string name = 3; +inline void CustomEvent::clear_name() { + _impl_.name_.ClearToEmpty(); } -inline int CustomEvent::customdata_size() const { - return _internal_customdata_size(); +inline const std::string& CustomEvent::name() const { + // @@protoc_insertion_point(field_get:rtech.liveapi.CustomEvent.name) + return _internal_name(); } -inline ::PROTOBUF_NAMESPACE_ID::Any* CustomEvent::mutable_customdata(int index) { - // @@protoc_insertion_point(field_mutable:rtech.liveapi.CustomEvent.customData) - return _impl_.customdata_.Mutable(index); +template +inline PROTOBUF_ALWAYS_INLINE +void CustomEvent::set_name(ArgT0&& arg0, ArgT... args) { + + _impl_.name_.Set(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:rtech.liveapi.CustomEvent.name) } -inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Any >* -CustomEvent::mutable_customdata() { - // @@protoc_insertion_point(field_mutable_list:rtech.liveapi.CustomEvent.customData) - return &_impl_.customdata_; +inline std::string* CustomEvent::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:rtech.liveapi.CustomEvent.name) + return _s; } -inline const ::PROTOBUF_NAMESPACE_ID::Any& CustomEvent::_internal_customdata(int index) const { - return _impl_.customdata_.Get(index); +inline const std::string& CustomEvent::_internal_name() const { + return _impl_.name_.Get(); } -inline const ::PROTOBUF_NAMESPACE_ID::Any& CustomEvent::customdata(int index) const { - // @@protoc_insertion_point(field_get:rtech.liveapi.CustomEvent.customData) - return _internal_customdata(index); +inline void CustomEvent::_internal_set_name(const std::string& value) { + + _impl_.name_.Set(value, GetArenaForAllocation()); } -inline ::PROTOBUF_NAMESPACE_ID::Any* CustomEvent::_internal_add_customdata() { - return _impl_.customdata_.Add(); +inline std::string* CustomEvent::_internal_mutable_name() { + + return _impl_.name_.Mutable(GetArenaForAllocation()); } -inline ::PROTOBUF_NAMESPACE_ID::Any* CustomEvent::add_customdata() { - ::PROTOBUF_NAMESPACE_ID::Any* _add = _internal_add_customdata(); - // @@protoc_insertion_point(field_add:rtech.liveapi.CustomEvent.customData) - return _add; +inline std::string* CustomEvent::release_name() { + // @@protoc_insertion_point(field_release:rtech.liveapi.CustomEvent.name) + return _impl_.name_.Release(); } -inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Any >& -CustomEvent::customdata() const { - // @@protoc_insertion_point(field_list:rtech.liveapi.CustomEvent.customData) - return _impl_.customdata_; +inline void CustomEvent::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:rtech.liveapi.CustomEvent.name) +} + +// .google.protobuf.Struct data = 4; +inline bool CustomEvent::_internal_has_data() const { + return this != internal_default_instance() && _impl_.data_ != nullptr; +} +inline bool CustomEvent::has_data() const { + return _internal_has_data(); +} +inline const ::PROTOBUF_NAMESPACE_ID::Struct& CustomEvent::_internal_data() const { + const ::PROTOBUF_NAMESPACE_ID::Struct* p = _impl_.data_; + return p != nullptr ? *p : reinterpret_cast( + ::PROTOBUF_NAMESPACE_ID::_Struct_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::Struct& CustomEvent::data() const { + // @@protoc_insertion_point(field_get:rtech.liveapi.CustomEvent.data) + return _internal_data(); +} +inline void CustomEvent::unsafe_arena_set_allocated_data( + ::PROTOBUF_NAMESPACE_ID::Struct* data) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.data_); + } + _impl_.data_ = data; + if (data) { + + } else { + + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:rtech.liveapi.CustomEvent.data) +} +inline ::PROTOBUF_NAMESPACE_ID::Struct* CustomEvent::release_data() { + + ::PROTOBUF_NAMESPACE_ID::Struct* temp = _impl_.data_; + _impl_.data_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::Struct* CustomEvent::unsafe_arena_release_data() { + // @@protoc_insertion_point(field_release:rtech.liveapi.CustomEvent.data) + + ::PROTOBUF_NAMESPACE_ID::Struct* temp = _impl_.data_; + _impl_.data_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::Struct* CustomEvent::_internal_mutable_data() { + + if (_impl_.data_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Struct>(GetArenaForAllocation()); + _impl_.data_ = p; + } + return _impl_.data_; +} +inline ::PROTOBUF_NAMESPACE_ID::Struct* CustomEvent::mutable_data() { + ::PROTOBUF_NAMESPACE_ID::Struct* _msg = _internal_mutable_data(); + // @@protoc_insertion_point(field_mutable:rtech.liveapi.CustomEvent.data) + return _msg; +} +inline void CustomEvent::set_allocated_data(::PROTOBUF_NAMESPACE_ID::Struct* data) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.data_); + } + if (data) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena( + reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(data)); + if (message_arena != submessage_arena) { + data = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, data, submessage_arena); + } + + } else { + + } + _impl_.data_ = data; + // @@protoc_insertion_point(field_set_allocated:rtech.liveapi.CustomEvent.data) } // ------------------------------------------------------------------- diff --git a/src/resource/protobuf/events.proto b/src/resource/protobuf/events.proto index 65acc2b7..d52d0231 100644 --- a/src/resource/protobuf/events.proto +++ b/src/resource/protobuf/events.proto @@ -25,31 +25,31 @@ message Vector3 message Player { - string name = 1; - uint32 teamId = 2; - Vector3 pos = 3; - Vector3 angles = 4; + string name = 1; + uint32 teamId = 2; + Vector3 pos = 3; + Vector3 angles = 4; - uint32 currentHealth = 5; - uint32 maxHealth = 6; - uint32 shieldHealth = 7; - uint32 shieldMaxHealth = 8; + uint32 currentHealth = 5; + uint32 maxHealth = 6; + uint32 shieldHealth = 7; + uint32 shieldMaxHealth = 8; - string nucleusHash = 9; - string hardwareName = 10; + string nucleusHash = 9; + string hardwareName = 10; - string teamName = 11; - uint32 squadIndex = 12; - string character = 13; - string skin = 14; + string teamName = 11; + uint32 squadIndex = 12; + string character = 13; + string skin = 14; } message CustomMatch_LobbyPlayer { - string name = 1; - uint32 teamId = 2; + string name = 1; + uint32 teamId = 2; - string nucleusHash = 3; + string nucleusHash = 3; string hardwareName = 4; } @@ -66,7 +66,7 @@ message Version uint32 major_num = 1; uint32 minor_num = 2; uint32 build_stamp = 3; - string revision = 4; + string revision = 4; } message InventoryItem @@ -551,16 +551,18 @@ message WeaponSwitched // Custom events ///////////////////////////////////////// +import "google/protobuf/struct.proto"; + // Event defining custom user data that is otherwise too specific to create dedicated messages for message CustomEvent { - uint64 timestamp = 1; - string category = 2; + uint64 timestamp = 1; + string category = 2; - repeated google.protobuf.Any customData = 3; + string name = 3; + google.protobuf.Struct data = 4; } - ////////////////////////////////////////////////////////////////////// // Input messages: // Used by observers to programmatically interact with the game diff --git a/src/rtech/liveapi/liveapi.cpp b/src/rtech/liveapi/liveapi.cpp index e48b49cd..6bf5d4ce 100644 --- a/src/rtech/liveapi/liveapi.cpp +++ b/src/rtech/liveapi/liveapi.cpp @@ -4,6 +4,7 @@ // //===========================================================================// #include "liveapi.h" +#include "protobuf/util/json_util.h" #include "DirtySDK/dirtysock.h" #include "DirtySDK/dirtysock/netconn.h" @@ -11,29 +12,33 @@ #include "DirtySDK/proto/protowebsocket.h" //----------------------------------------------------------------------------- -// +// change callbacks //----------------------------------------------------------------------------- +static void LiveAPI_EnabledChangedCallback(IConVar* var, const char* pOldValue) +{ + LiveAPISystem()->ToggleInit(); +} +static void LiveAPI_WebSocketEnabledChangedCallback(IConVar* var, const char* pOldValue) +{ + LiveAPISystem()->ToggleInitWebSocket(); +} static void LiveAPI_ParamsChangedCallback(IConVar* var, const char* pOldValue) { LiveAPISystem()->UpdateParams(); } - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- static void LiveAPI_AddressChangedCallback(IConVar* var, const char* pOldValue) { - LiveAPISystem()->InstallAddressList(); + LiveAPISystem()->RebootWebSocket(); } //----------------------------------------------------------------------------- // console variables //----------------------------------------------------------------------------- -ConVar liveapi_enabled("liveapi_enabled", "1", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Enable LiveAPI functionality"); +ConVar liveapi_enabled("liveapi_enabled", "1", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Enable LiveAPI functionality", &LiveAPI_EnabledChangedCallback); ConVar liveapi_session_name("liveapi_session_name", "liveapi_session", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "LiveAPI session name to identify this connection"); // WebSocket core -static ConVar liveapi_use_websocket("liveapi_use_websocket", "1", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Use WebSocket to transmit LiveAPI events"); +static ConVar liveapi_websocket_enabled("liveapi_websocket_enabled", "1", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Whether to use WebSocket to transmit LiveAPI events", &LiveAPI_WebSocketEnabledChangedCallback); static ConVar liveapi_servers("liveapi_servers", "ws://127.0.0.1:7777", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Comma separated list of addresses to connect to", &LiveAPI_AddressChangedCallback, "ws://domain.suffix:port"); // WebSocket connection base parameters @@ -45,10 +50,23 @@ static ConVar liveapi_timeout("liveapi_timeout", "300", FCVAR_RELEASE | FCVAR_SE static ConVar liveapi_keepalive("liveapi_keepalive", "30", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Interval of time to send Pong to any connected server", &LiveAPI_ParamsChangedCallback); static ConVar liveapi_lax_ssl("liveapi_lax_ssl", "1", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Skip SSL certificate validation for all WSS connections (allows the use of self-signed certificates)", &LiveAPI_ParamsChangedCallback); +// Print core +static ConVar liveapi_print_enabled("liveapi_print_enabled", "0", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Whether to enable the printing of all events to a LiveAPI JSON file"); + +// Print parameters +static ConVar liveapi_print_pretty("liveapi_print_pretty", "0", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Whether to print events in a formatted manner to the LiveAPI JSON file"); +static ConVar liveapi_print_primitive("liveapi_print_primitive", "0", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Whether to print primitive event fields to the LiveAPI JSON file"); + //----------------------------------------------------------------------------- // constructors/destructors //----------------------------------------------------------------------------- LiveAPI::LiveAPI() +{ + matchLogCount = 0; + initialLog = false; + initialized = false; +} +LiveAPI::~LiveAPI() { } @@ -60,16 +78,8 @@ void LiveAPI::Init() if (!liveapi_enabled.GetBool()) return; - if (liveapi_use_websocket.GetBool()) - { - const char* initError = nullptr; - - if (!InitWebSocket(initError)) - { - Error(eDLL_T::RTECH, 0, "LiveAPI: WebSocket initialization failed! [%s]\n", initError); - return; - } - } + InitWebSocket(); + initialized = true; } //----------------------------------------------------------------------------- @@ -78,10 +88,26 @@ void LiveAPI::Init() void LiveAPI::Shutdown() { webSocketSystem.Shutdown(); + DestroyLogger(); + initialized = false; } //----------------------------------------------------------------------------- -// +// Toggle between init or deinit depending on current init state and the value +// of the cvar 'liveapi_enabled' +//----------------------------------------------------------------------------- +void LiveAPI::ToggleInit() +{ + const bool enabled = liveapi_enabled.GetBool(); + + if (enabled && !initialized) + Init(); + else if (!enabled && initialized) + Shutdown(); +} + +//----------------------------------------------------------------------------- +// Populate the connection params structure //----------------------------------------------------------------------------- void LiveAPI::CreateParams(CWebSocket::ConnParams_s& params) { @@ -96,7 +122,7 @@ void LiveAPI::CreateParams(CWebSocket::ConnParams_s& params) } //----------------------------------------------------------------------------- -// +// Update the websocket parameters and apply them on all connections //----------------------------------------------------------------------------- void LiveAPI::UpdateParams() { @@ -107,23 +133,91 @@ void LiveAPI::UpdateParams() } //----------------------------------------------------------------------------- -// +// Initialize the websocket system //----------------------------------------------------------------------------- -bool LiveAPI::InitWebSocket(const char*& initError) +void LiveAPI::InitWebSocket() { + if (!liveapi_websocket_enabled.GetBool()) + return; + CWebSocket::ConnParams_s connParams; CreateParams(connParams); - return webSocketSystem.Init(liveapi_servers.GetString(), connParams, initError); + const char* initError = nullptr; + + if (!webSocketSystem.Init(liveapi_servers.GetString(), connParams, initError)) + { + Error(eDLL_T::RTECH, 0, "LiveAPI: WebSocket initialization failed! [%s]\n", initError); + return; + } } //----------------------------------------------------------------------------- -// +// Shutdown the websocket system //----------------------------------------------------------------------------- -void LiveAPI::InstallAddressList() +void LiveAPI::ShutdownWebSocket() { - webSocketSystem.ClearAll(); - webSocketSystem.UpdateAddressList(liveapi_servers.GetString()); + webSocketSystem.Shutdown(); +} + +//----------------------------------------------------------------------------- +// Toggle between init or deinit depending on current init state and the value +// of the cvar 'liveapi_websocket_enabled' +//----------------------------------------------------------------------------- +void LiveAPI::ToggleInitWebSocket() +{ + const bool enabled = liveapi_websocket_enabled.GetBool(); + + if (enabled && !WebSocketInitialized()) + InitWebSocket(); + else if (!enabled && WebSocketInitialized()) + ShutdownWebSocket(); +} + +//----------------------------------------------------------------------------- +// Reboot the websocket system and reconnect to addresses specified in cvar +// 'liveapi_servers' +//----------------------------------------------------------------------------- +void LiveAPI::RebootWebSocket() +{ + ShutdownWebSocket(); + InitWebSocket(); +} + +//----------------------------------------------------------------------------- +// Create the file logger +//----------------------------------------------------------------------------- +void LiveAPI::CreateLogger() +{ + // Its possible that one was already created but never closed, this is + // possible if the game scripts crashed or something along those lines. + DestroyLogger(); + + if (!liveapi_print_enabled.GetBool()) + return; // Logging is disabled + + matchLogger = spdlog::basic_logger_mt("match_logger", + Format("platform/liveapi/logs/%s/match_%d.json", g_LogSessionUUID.c_str(), matchLogCount++)); + + matchLogger.get()->set_pattern("%v"); + matchLogger.get()->info("[\n"); +} + +//----------------------------------------------------------------------------- +// Destroy the file logger +//----------------------------------------------------------------------------- +void LiveAPI::DestroyLogger() +{ + if (initialLog) + initialLog = false; + + if (!matchLogger) + return; // Nothing to drop + + matchLogger.get()->info("\n]\n"); + matchLogger.reset(); + + spdlog::drop("match_logger"); } //----------------------------------------------------------------------------- @@ -134,30 +228,65 @@ void LiveAPI::RunFrame() if (!IsEnabled()) return; - if (liveapi_use_websocket.GetBool()) + if (WebSocketInitialized()) webSocketSystem.Update(); } //----------------------------------------------------------------------------- // Send an event to all sockets //----------------------------------------------------------------------------- -void LiveAPI::LogEvent(const char* const dataBuf, const int32_t dataSize) +void LiveAPI::LogEvent(const google::protobuf::Message* const toTransmit, const google::protobuf::Message* toPrint) { if (!IsEnabled()) return; - if (liveapi_use_websocket.GetBool()) - webSocketSystem.SendData(dataBuf, dataSize); + if (WebSocketInitialized()) + { + const string data = toTransmit->SerializeAsString(); + webSocketSystem.SendData(data.c_str(), (int)data.size()); + } + + // NOTE: we don't check on the cvar 'liveapi_print_enabled' here because if + // this cvar gets disabled on the fly and we check it here, the output will + // be truncated and thus invalid! Log for as long as the SpdLog instance is + // valid. + if (matchLogger) + { + std::string jsonStr(initialLog ? ",\n" : ""); + google::protobuf::util::JsonPrintOptions options; + + options.add_whitespace = liveapi_print_pretty.GetBool(); + options.always_print_primitive_fields = liveapi_print_primitive.GetBool(); + + google::protobuf::util::MessageToJsonString(*toPrint, &jsonStr, options); + + // Remove the trailing newline character + if (options.add_whitespace && !jsonStr.empty()) + jsonStr.pop_back(); + + matchLogger.get()->info(jsonStr); + + if (!initialLog) + initialLog = true; + } } //----------------------------------------------------------------------------- -// Returns whether the system is enabled and able to run +// Returns whether the system is enabled //----------------------------------------------------------------------------- bool LiveAPI::IsEnabled() const { return liveapi_enabled.GetBool(); } +//----------------------------------------------------------------------------- +// Returns whether the system is able to run +//----------------------------------------------------------------------------- +bool LiveAPI::IsValidToRun() const +{ + return (IsEnabled() && (WebSocketInitialized() || FileLoggerInitialized())); +} + static LiveAPI s_liveApi; //----------------------------------------------------------------------------- diff --git a/src/rtech/liveapi/liveapi.h b/src/rtech/liveapi/liveapi.h index 17ffc5e8..ebd8e2dd 100644 --- a/src/rtech/liveapi/liveapi.h +++ b/src/rtech/liveapi/liveapi.h @@ -1,6 +1,7 @@ #ifndef RTECH_LIVEAPI_H #define RTECH_LIVEAPI_H #include "tier2/websocket.h" +#include "thirdparty/protobuf/message.h" #define LIVE_API_MAX_FRAME_BUFFER_SIZE 0x8000 @@ -13,26 +14,43 @@ typedef void (*LiveAPISendCallback_t)(ProtoWebSocketRefT* webSocket); class LiveAPI { public: - LiveAPI(); + ~LiveAPI(); void Init(); void Shutdown(); + void ToggleInit(); + void CreateParams(CWebSocket::ConnParams_s& params); void UpdateParams(); - bool InitWebSocket(const char*& initError); - void InstallAddressList(); + void InitWebSocket(); + void ShutdownWebSocket(); + + void ToggleInitWebSocket(); + + void RebootWebSocket(); + + void CreateLogger(); + void DestroyLogger(); void RunFrame(); - void LogEvent(const char* const dataBuf, const int32_t dataSize); + void LogEvent(const google::protobuf::Message* const toTransmit, const google::protobuf::Message* toPrint); bool IsEnabled() const; + bool IsValidToRun() const; + inline bool WebSocketInitialized() const { return webSocketSystem.IsInitialized(); } + inline bool FileLoggerInitialized() const { return matchLogger != nullptr; } private: CWebSocket webSocketSystem; + + std::shared_ptr matchLogger; + int matchLogCount; + bool initialLog; + bool initialized; }; LiveAPI* LiveAPISystem();