diff --git a/NetConsole/NetConsole.vcxproj b/NetConsole/NetConsole.vcxproj
new file mode 100644
index 000000000..264973b4b
--- /dev/null
+++ b/NetConsole/NetConsole.vcxproj
@@ -0,0 +1,122 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {abb29780-5fea-4108-8793-fa50fb9cdafa}
+ NetConsole
+ 10.0
+
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ netcon
+
+
+ false
+ netcon
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)NorthstarDedicatedTest\;$(SolutionDir)NorthstarDedicatedTest\Include\;$(SolutionDir)NorthstarDedicatedTest\Include\protobuf\;%(AdditionalIncludeDirectories)
+ Use
+ pch.h
+ stdcpp17
+
+
+ Console
+ true
+ Ws2_32.lib;$(SolutionDir)$(Platform)\$(Configuration)\libprotobuf_x64.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)NorthstarDedicatedTest\;$(SolutionDir)NorthstarDedicatedTest\Include\;$(SolutionDir)NorthstarDedicatedTest\Include\protobuf\;%(AdditionalIncludeDirectories)
+ Use
+ pch.h
+ stdcpp17
+
+
+ Console
+ true
+ true
+ true
+ Ws2_32.lib;$(SolutionDir)$(Platform)\$(Configuration)\libprotobuf_x64.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NotUsing
+ NotUsing
+
+
+
+
+
+ NotUsing
+ NotUsing
+
+
+
+ Create
+ Create
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetConsole/NetConsole.vcxproj.filters b/NetConsole/NetConsole.vcxproj.filters
new file mode 100644
index 000000000..617ef8c77
--- /dev/null
+++ b/NetConsole/NetConsole.vcxproj.filters
@@ -0,0 +1,63 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/NetConsole/cl_rcon.proto b/NetConsole/cl_rcon.proto
new file mode 100644
index 000000000..c8ba8dbfa
--- /dev/null
+++ b/NetConsole/cl_rcon.proto
@@ -0,0 +1,21 @@
+syntax = "proto3";
+package cl_rcon;
+option optimize_for = LITE_RUNTIME;
+
+enum request_t
+{
+ SERVERDATA_REQUEST_VALUE = 0;
+ SERVERDATA_REQUEST_SETVALUE = 1;
+ SERVERDATA_REQUEST_EXECCOMMAND = 2;
+ SERVERDATA_REQUEST_AUTH = 3;
+ SERVERDATA_REQUEST_SEND_CONSOLE_LOG = 4;
+ SERVERDATA_REQUEST_SEND_REMOTEBUG = 5;
+}
+
+message request
+{
+ optional int32 requestID = 1;
+ optional request_t requestType = 2;
+ optional string requestBuf = 3;
+ optional string requestVal = 4;
+}
diff --git a/NetConsole/netconsole.cpp b/NetConsole/netconsole.cpp
new file mode 100644
index 000000000..892f61922
--- /dev/null
+++ b/NetConsole/netconsole.cpp
@@ -0,0 +1,491 @@
+//=====================================================================================//
+//
+// Purpose: Lightweight netconsole client.
+//
+//=====================================================================================//
+
+#include "pch.h"
+#include "NetAdr2.h"
+#include "socketcreator.h"
+#include "sv_rcon.pb.h"
+#include "cl_rcon.pb.h"
+#include "net.h"
+#include "netconsole.h"
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CNetCon::CNetCon(void)
+ : m_bInitialized(false), m_bNoColor(false), m_bQuitApplication(false), m_abPromptConnect(true), m_abConnEstablished(false)
+{
+ m_pNetAdr2 = new CNetAdr2("localhost", "37015");
+ m_pSocket = new CSocketCreator();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CNetCon::~CNetCon(void)
+{
+ delete m_pNetAdr2;
+ delete m_pSocket;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: WSA and NETCON systems init
+// Output : true on success, false otherwise
+//-----------------------------------------------------------------------------
+bool CNetCon::Init(void)
+{
+ WSAData wsaData {};
+ int nError = ::WSAStartup(MAKEWORD(2, 2), &wsaData);
+
+ if (nError != 0)
+ {
+ spdlog::error("Failed to start Winsock via WSAStartup: ({:s})", NET_ErrorString(WSAGetLastError()));
+ return false;
+ }
+
+ this->TermSetup();
+
+ std::thread tFrame(&CNetCon::RunFrame, this);
+ tFrame.detach();
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: WSA and NETCON systems shutdown
+// Output : true on success, false otherwise
+//-----------------------------------------------------------------------------
+bool CNetCon::Shutdown(void)
+{
+ m_pSocket->CloseAllAcceptedSockets();
+ m_abConnEstablished = false;
+
+ int nError = ::WSACleanup();
+ if (nError != 0)
+ {
+ spdlog::error("Failed to stop winsock via WSACleanup: ({:s})", NET_ErrorString(WSAGetLastError()));
+ return false;
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: terminal setup
+//-----------------------------------------------------------------------------
+void CNetCon::TermSetup(void)
+{
+ DWORD dwMode = NULL;
+ HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
+ HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ CONSOLE_SCREEN_BUFFER_INFOEX sbInfoEx {};
+ COLORREF storedBG = sbInfoEx.ColorTable[0];
+ sbInfoEx.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
+
+ GetConsoleScreenBufferInfoEx(hOutput, &sbInfoEx);
+ sbInfoEx.ColorTable[0] = 0x0000;
+ SetConsoleScreenBufferInfoEx(hOutput, &sbInfoEx);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: gets input IP and port for initialization
+//-----------------------------------------------------------------------------
+void CNetCon::UserInput(void)
+{
+ std::string svInput;
+
+ if (std::getline(std::cin, svInput))
+ {
+ if (svInput.compare("nquit") == 0)
+ {
+ m_bQuitApplication = true;
+ return;
+ }
+ if (m_abConnEstablished)
+ {
+ if (svInput.compare("disconnect") == 0)
+ {
+ this->Disconnect();
+ return;
+ }
+
+ std::vector vSubStrings = StringSplit(svInput, ' ', 2);
+ if (vSubStrings.size() > 1)
+ {
+ if (vSubStrings[0].compare("PASS") == 0) // Auth with RCON server.
+ {
+ std::string svSerialized = this->Serialize(vSubStrings[1], "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH);
+ this->Send(svSerialized);
+ }
+ else if (vSubStrings[0].compare("SET") == 0) // Set value query.
+ {
+ if (vSubStrings.size() > 2)
+ {
+ std::string svSerialized =
+ this->Serialize(vSubStrings[1], vSubStrings[2], cl_rcon::request_t::SERVERDATA_REQUEST_SETVALUE);
+ this->Send(svSerialized);
+ }
+ }
+ else // Execute command query.
+ {
+ std::string svSerialized = this->Serialize(svInput, "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND);
+ this->Send(svSerialized);
+ }
+ }
+ else if (!svInput.empty()) // Single arg command query.
+ {
+ std::string svSerialized = this->Serialize(svInput, "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND);
+ this->Send(svSerialized);
+ }
+ }
+ else // Setup connection from input.
+ {
+ if (!svInput.empty())
+ {
+ std::string::size_type nPos = svInput.find(' ');
+ if (nPos > 0 && nPos < svInput.size() && nPos != svInput.size())
+ {
+ std::string svInPort = svInput.substr(nPos + 1);
+ std::string svInAdr = svInput.erase(svInput.find(' '));
+
+ if (!this->Connect(svInAdr, svInPort))
+ {
+ m_abPromptConnect = true;
+ return;
+ }
+ }
+ }
+ else // Initialize as [127.0.0.1]:37015.
+ {
+ if (!this->Connect("", ""))
+ {
+ m_abPromptConnect = true;
+ return;
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: client's main processing loop
+//-----------------------------------------------------------------------------
+void CNetCon::RunFrame(void)
+{
+ for (;;)
+ {
+ if (m_abConnEstablished)
+ {
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ this->Recv();
+ }
+ else if (m_abPromptConnect)
+ {
+ std::cout << "Enter : ";
+ m_abPromptConnect = false;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: checks if application should be terminated
+// Output : true for termination, false otherwise
+//-----------------------------------------------------------------------------
+bool CNetCon::ShouldQuit(void) const
+{
+ return this->m_bQuitApplication;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: connect to specified address and port
+// Input : *svInAdr -
+// *svInPort -
+// Output : true if connection succeeds, false otherwise
+//-----------------------------------------------------------------------------
+bool CNetCon::Connect(const std::string& svInAdr, const std::string& svInPort)
+{
+ if (svInAdr.size() > 0 && svInPort.size() > 0)
+ {
+ // Default is [127.0.0.1]:37015
+ m_pNetAdr2->SetIPAndPort(svInAdr, svInPort);
+ }
+
+ if (m_pSocket->ConnectSocket(*m_pNetAdr2, true) == SOCKET_ERROR)
+ {
+ spdlog::warn("Failed to connect. Error: (SOCKET_ERROR). Verify IP and PORT.");
+ return false;
+ }
+ spdlog::info("Connected to: {:s}", m_pNetAdr2->GetIPAndPort());
+
+ m_abConnEstablished = true;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: disconnect from current session
+//-----------------------------------------------------------------------------
+void CNetCon::Disconnect(void)
+{
+ m_pSocket->CloseAcceptedSocket(0);
+ m_abPromptConnect = true;
+ m_abConnEstablished = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: send message
+// Input : *svMessage -
+//-----------------------------------------------------------------------------
+void CNetCon::Send(const std::string& svMessage) const
+{
+ std::ostringstream ssSendBuf;
+
+ ssSendBuf << static_cast(static_cast(svMessage.size()) >> 24);
+ ssSendBuf << static_cast(static_cast(svMessage.size()) >> 16);
+ ssSendBuf << static_cast(static_cast(svMessage.size()) >> 8);
+ ssSendBuf << static_cast(static_cast(svMessage.size()));
+ ssSendBuf << svMessage;
+
+ int nSendResult = ::send(
+ m_pSocket->GetAcceptedSocketData(0)->m_hSocket, ssSendBuf.str().data(), static_cast(ssSendBuf.str().size()), MSG_NOSIGNAL);
+ if (nSendResult == SOCKET_ERROR)
+ {
+ spdlog::warn("Failed to send message: (SOCKET_ERROR)");
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: receive message
+//-----------------------------------------------------------------------------
+void CNetCon::Recv(void)
+{
+ static char szRecvBuf[1024];
+ CConnectedNetConsoleData* pData = m_pSocket->GetAcceptedSocketData(0);
+
+ { //////////////////////////////////////////////
+ int nPendingLen = ::recv(pData->m_hSocket, szRecvBuf, sizeof(char), MSG_PEEK);
+ if (nPendingLen == SOCKET_ERROR && m_pSocket->IsSocketBlocking())
+ {
+ return;
+ }
+ if (nPendingLen <= 0 && m_abConnEstablished) // EOF or error.
+ {
+ this->Disconnect();
+ spdlog::info("Server closed connection");
+ return;
+ }
+ } //////////////////////////////////////////////
+
+ u_long nReadLen; // Find out how much we have to read.
+ ::ioctlsocket(pData->m_hSocket, FIONREAD, &nReadLen);
+
+ while (nReadLen > 0)
+ {
+ int nRecvLen = ::recv(pData->m_hSocket, szRecvBuf, MIN(sizeof(szRecvBuf), nReadLen), MSG_NOSIGNAL);
+ if (nRecvLen == 0 && m_abConnEstablished) // Socket was closed.
+ {
+ this->Disconnect();
+ spdlog::info("Server closed connection");
+ break;
+ }
+ if (nRecvLen < 0 && !m_pSocket->IsSocketBlocking())
+ {
+ spdlog::error("RCON Cmd: recv error ({:s})", NET_ErrorString(WSAGetLastError()));
+ break;
+ }
+
+ nReadLen -= nRecvLen; // Process what we've got.
+ this->ProcessBuffer(szRecvBuf, nRecvLen, pData);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: parses input response buffer using length-prefix framing
+// Input : *pRecvBuf -
+// nRecvLen -
+// *pData -
+//-----------------------------------------------------------------------------
+void CNetCon::ProcessBuffer(const char* pRecvBuf, int nRecvLen, CConnectedNetConsoleData* pData)
+{
+ while (nRecvLen > 0)
+ {
+ if (pData->m_nPayloadLen)
+ {
+ if (pData->m_nPayloadRead < pData->m_nPayloadLen)
+ {
+ pData->m_RecvBuffer[pData->m_nPayloadRead++] = *pRecvBuf;
+
+ pRecvBuf++;
+ nRecvLen--;
+ }
+ if (pData->m_nPayloadRead == pData->m_nPayloadLen)
+ {
+ this->ProcessMessage(
+ this->Deserialize(std::string(reinterpret_cast(pData->m_RecvBuffer.data()), pData->m_nPayloadLen)));
+
+ pData->m_nPayloadLen = 0;
+ pData->m_nPayloadRead = 0;
+ }
+ }
+ else if (pData->m_nPayloadRead < sizeof(int)) // Read size field.
+ {
+ pData->m_RecvBuffer[pData->m_nPayloadRead++] = *pRecvBuf;
+
+ pRecvBuf++;
+ nRecvLen--;
+ }
+ else // Build prefix.
+ {
+ pData->m_nPayloadLen = static_cast(
+ pData->m_RecvBuffer[0] << 24 | pData->m_RecvBuffer[1] << 16 | pData->m_RecvBuffer[2] << 8 | pData->m_RecvBuffer[3]);
+ pData->m_nPayloadRead = 0;
+
+ if (pData->m_nPayloadLen < 0)
+ {
+ spdlog::error("RCON Cmd: sync error ({:d})", pData->m_nPayloadLen);
+ this->Disconnect(); // Out of sync (irrecoverable).
+
+ break;
+ }
+ else
+ {
+ pData->m_RecvBuffer.resize(pData->m_nPayloadLen);
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: processes received message
+// Input : *sv_response -
+//-----------------------------------------------------------------------------
+void CNetCon::ProcessMessage(const sv_rcon::response& sv_response) const
+{
+ switch (sv_response.responsetype())
+ {
+ case sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH:
+ case sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG:
+ {
+ std::string svOut = sv_response.responsebuf();
+ svOut.erase(std::remove(svOut.begin(), svOut.end(), '\n'), svOut.end());
+ spdlog::info(svOut);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: serializes input
+// Input : *svReqBuf -
+// *svReqVal -
+// request_t -
+// Output : serialized results as string
+//-----------------------------------------------------------------------------
+std::string CNetCon::Serialize(const std::string& svReqBuf, const std::string& svReqVal, cl_rcon::request_t request_t) const
+{
+ cl_rcon::request cl_request;
+
+ cl_request.set_requestid(-1);
+ cl_request.set_requesttype(request_t);
+
+ switch (request_t)
+ {
+ case cl_rcon::request_t::SERVERDATA_REQUEST_SETVALUE:
+ case cl_rcon::request_t::SERVERDATA_REQUEST_AUTH:
+ {
+ cl_request.set_requestbuf(svReqBuf);
+ cl_request.set_requestval(svReqVal);
+ break;
+ }
+ case cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND:
+ {
+ cl_request.set_requestbuf(svReqBuf);
+ break;
+ }
+ }
+ return cl_request.SerializeAsString();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: de-serializes input
+// Input : *svBuf -
+// Output : de-serialized object
+//-----------------------------------------------------------------------------
+sv_rcon::response CNetCon::Deserialize(const std::string& svBuf) const
+{
+ sv_rcon::response sv_response;
+ sv_response.ParseFromArray(svBuf.data(), static_cast(svBuf.size()));
+
+ return sv_response;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: entrypoint
+// Input : argc -
+// *argv -
+//-----------------------------------------------------------------------------
+int main(int argc, char* argv[])
+{
+ CNetCon* pNetCon = new CNetCon();
+ std::cout << "Northstar TCP net console [Version " << NETCON_VERSION << "]" << std::endl;
+ spdlog::default_logger()->set_pattern("[%H:%M:%S] [%l] %v");
+
+ if (!pNetCon->Init())
+ {
+ return EXIT_FAILURE;
+ }
+
+ if (argc >= 3) // Get IP and Port from command line.
+ {
+ if (!pNetCon->Connect(argv[1], argv[2]))
+ {
+ return EXIT_FAILURE;
+ }
+ }
+
+ while (!pNetCon->ShouldQuit())
+ {
+ pNetCon->UserInput();
+ }
+
+ if (!pNetCon->Shutdown())
+ {
+ return EXIT_FAILURE;
+ }
+
+ return ERROR_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// For splitting a string into substrings by delimiter.
+std::vector
+StringSplit(std::string svInput, char cDelim, size_t nMax) // Move this to a dedicated string util file if one ever gets created.
+{
+ std::string svSubString;
+ std::vector vSubStrings;
+
+ svInput = svInput + cDelim;
+
+ for (size_t i = 0; i < svInput.size(); i++)
+ {
+ if (i != (svInput.size() - 1) && vSubStrings.size() >= nMax || svInput[i] != cDelim)
+ {
+ svSubString += svInput[i];
+ }
+ else
+ {
+ if (svSubString.size() != 0)
+ {
+ vSubStrings.push_back(svSubString);
+ }
+ svSubString.clear();
+ }
+ }
+ return vSubStrings;
+}
\ No newline at end of file
diff --git a/NetConsole/netconsole.h b/NetConsole/netconsole.h
new file mode 100644
index 000000000..729c37b02
--- /dev/null
+++ b/NetConsole/netconsole.h
@@ -0,0 +1,50 @@
+//===========================================================================//
+//
+// Purpose:
+//
+//===========================================================================//
+#pragma once
+#include "cl_rcon.pb.h"
+#include "sv_rcon.pb.h"
+
+constexpr const char* NETCON_VERSION = "2.0.0.1";
+
+class CNetCon
+{
+ public:
+ CNetCon(void);
+ ~CNetCon(void);
+
+ bool Init(void);
+ bool Shutdown(void);
+
+ void TermSetup(void);
+ void UserInput(void);
+
+ void RunFrame(void);
+ bool ShouldQuit(void) const;
+
+ bool Connect(const std::string& svInAdr, const std::string& svInPort);
+ void Disconnect(void);
+
+ void Send(const std::string& svMessage) const;
+ void Recv(void);
+
+ void ProcessBuffer(const char* pRecvBuf, int nRecvLen, CConnectedNetConsoleData* pData);
+ void ProcessMessage(const sv_rcon::response& sv_response) const;
+
+ std::string Serialize(const std::string& svReqBuf, const std::string& svReqVal, cl_rcon::request_t request_t) const;
+ sv_rcon::response Deserialize(const std::string& svBuf) const;
+
+ private:
+ CNetAdr2* m_pNetAdr2;
+ CSocketCreator* m_pSocket;
+
+ bool m_bInitialized;
+ bool m_bNoColor;
+ bool m_bQuitApplication;
+ std::atomic m_abPromptConnect;
+ std::atomic m_abConnEstablished;
+};
+
+std::vector StringSplit(std::string svInput, char cDelim, size_t nMax);
\ No newline at end of file
diff --git a/NetConsole/pch.cpp b/NetConsole/pch.cpp
new file mode 100644
index 000000000..64b7eef6d
--- /dev/null
+++ b/NetConsole/pch.cpp
@@ -0,0 +1,5 @@
+// pch.cpp: source file corresponding to the pre-compiled header
+
+#include "pch.h"
+
+// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
diff --git a/NetConsole/pch.h b/NetConsole/pch.h
new file mode 100644
index 000000000..5e917f101
--- /dev/null
+++ b/NetConsole/pch.h
@@ -0,0 +1,33 @@
+#ifndef PCH_H
+#define PCH_H
+
+#define WIN32_LEAN_AND_MEAN
+#define _CRT_SECURE_NO_WARNINGS
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+// add headers that you want to pre-compile here
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "spdlog/spdlog.h"
+#endif
diff --git a/NetConsole/sv_rcon.proto b/NetConsole/sv_rcon.proto
new file mode 100644
index 000000000..ce2e9e35f
--- /dev/null
+++ b/NetConsole/sv_rcon.proto
@@ -0,0 +1,21 @@
+syntax = "proto3";
+package sv_rcon;
+option optimize_for = LITE_RUNTIME;
+
+enum response_t
+{
+ SERVERDATA_RESPONSE_VALUE = 0;
+ SERVERDATA_RESPONSE_UPDATE = 1;
+ SERVERDATA_RESPONSE_AUTH = 2;
+ SERVERDATA_RESPONSE_CONSOLE_LOG = 3;
+ SERVERDATA_RESPONSE_STRING = 4;
+ SERVERDATA_RESPONSE_REMOTEBUG = 5;
+}
+
+message response
+{
+ optional int32 responseID = 1;
+ optional response_t responseType = 2;
+ optional string responseBuf = 3;
+ optional string responseVal = 4;
+}
diff --git a/NorthstarDedicatedTest/NetAdr2.cpp b/NorthstarDedicatedTest/NetAdr2.cpp
new file mode 100644
index 000000000..e493700fc
--- /dev/null
+++ b/NorthstarDedicatedTest/NetAdr2.cpp
@@ -0,0 +1,665 @@
+//===========================================================================//
+//
+// Purpose: Protocol-agnostic implementation of the CNetAdr class.
+//
+//===========================================================================//
+
+#include "pch.h"
+#include "NetAdr2.h"
+
+//-----------------------------------------------------------------------------
+// Purpose: constructor (use this when string contains <[IP]:PORT>).
+// Input : svInAdr -
+//-----------------------------------------------------------------------------
+CNetAdr2::CNetAdr2(const std::string& svInAdr)
+{
+ SetIPAndPort(svInAdr);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: constructor (expects string format ).
+// Input : svInAdr -
+// svInPort -
+//-----------------------------------------------------------------------------
+CNetAdr2::CNetAdr2(const std::string& svInAdr, const std::string& svInPort)
+{
+ SetIPAndPort(svInAdr, svInPort);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: destructor.
+//-----------------------------------------------------------------------------
+CNetAdr2::~CNetAdr2(void)
+{
+ Clear();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets the IP address.
+// Input : *svInAdr -
+//-----------------------------------------------------------------------------
+void CNetAdr2::SetIP(const std::string& svInAdr)
+{
+ m_svip = "[" + svInAdr + "]";
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets the port.
+// Input : *svInPort -
+//-----------------------------------------------------------------------------
+void CNetAdr2::SetPort(const std::string& svInPort)
+{
+ m_svip += ":" + svInPort;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets the IP address and port.
+// Input : *svInAdr -
+//-----------------------------------------------------------------------------
+void CNetAdr2::SetIPAndPort(std::string svInAdr)
+{
+ SetType(netadrtype_t::NA_IP);
+ if (strstr(svInAdr.c_str(), "loopback") || strstr(svInAdr.c_str(), "::1"))
+ {
+ SetType(netadrtype_t::NA_LOOPBACK);
+ svInAdr = "[127.0.0.1]:" + GetPort(svInAdr);
+ }
+ else if (strstr(svInAdr.c_str(), "localhost"))
+ {
+ svInAdr = "[127.0.0.1]:" + GetPort(svInAdr);
+ }
+ // [IP]:PORT
+ m_svip = svInAdr;
+ SetVersion();
+
+ if (GetVersion() == netadrversion_t::NA_V4)
+ {
+ reinterpret_cast(&m_sadr)->sin_port = htons(stoi(GetPort()));
+ }
+ else if (GetVersion() == netadrversion_t::NA_V6)
+ {
+ reinterpret_cast(&m_sadr)->sin6_port = htons(stoi(GetPort()));
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets the IP address and port.
+// Input : *svInAdr -
+// *svInPort -
+//-----------------------------------------------------------------------------
+void CNetAdr2::SetIPAndPort(std::string svInAdr, std::string svInPort)
+{
+ SetType(netadrtype_t::NA_IP);
+
+ if (strcmp(svInAdr.c_str(), "loopback") == 0 || strcmp(svInAdr.c_str(), "::1") == 0)
+ {
+ SetType(netadrtype_t::NA_LOOPBACK);
+ }
+ else if (strcmp(svInAdr.c_str(), "localhost") == 0)
+ {
+ svInAdr = "127.0.0.1";
+ }
+
+ if (strstr(svInAdr.c_str(), "[") || strstr(svInAdr.c_str(), "]"))
+ {
+ svInAdr = GetBase(svInAdr);
+ }
+
+ m_svip = "[" + svInAdr + "]:" + svInPort;
+ SetVersion();
+
+ if (m_version == netadrversion_t::NA_V4)
+ {
+ reinterpret_cast(&m_sadr)->sin_port = htons(stoi(GetPort()));
+ }
+ else if (m_version == netadrversion_t::NA_V6)
+ {
+ reinterpret_cast(&m_sadr)->sin6_port = htons(stoi(GetPort()));
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets the type.
+// Input : *type -
+//-----------------------------------------------------------------------------
+void CNetAdr2::SetType(const netadrtype_t& type)
+{
+ m_type = type;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets the IP version (IPv4/IPv6/INVALID) based on input.
+//-----------------------------------------------------------------------------
+void CNetAdr2::SetVersion(void)
+{
+ if (inet_pton(
+ reinterpret_cast(&m_sadr)->sin_family, GetBase().c_str(), &reinterpret_cast(m_sadr)->sin_addr) &&
+ !strstr(GetBase().c_str(), "::"))
+ {
+ m_version = netadrversion_t::NA_V4;
+ return;
+ }
+ else if (inet_pton(
+ reinterpret_cast(&m_sadr)->sin6_family,
+ GetBase().c_str(),
+ &reinterpret_cast(m_sadr)->sin6_addr))
+ {
+ m_version = netadrversion_t::NA_V6;
+ return;
+ }
+ m_version = netadrversion_t::NA_INVALID;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets IP address and port from sockaddr struct.
+// Input : hSocket -
+//-----------------------------------------------------------------------------
+void CNetAdr2::SetFromSocket(const int& hSocket)
+{
+ Clear();
+ m_type = netadrtype_t::NA_IP;
+
+ sockaddr_storage address {};
+ socklen_t namelen = sizeof(address);
+ if (getsockname(hSocket, (sockaddr*)&address, &namelen) == 0)
+ {
+ SetFromSockadr(&address);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets fields based on 'sockaddr' input.
+// Input : *s -
+//-----------------------------------------------------------------------------
+bool CNetAdr2::SetFromSockadr(sockaddr_storage* s)
+{
+ if (reinterpret_cast(s)->sin_family == AF_INET)
+ {
+ char szAdrv4[INET_ADDRSTRLEN] {};
+ sockaddr_in* pAdrv4 = reinterpret_cast(s);
+
+ inet_ntop(pAdrv4->sin_family, &pAdrv4->sin_addr, szAdrv4, sizeof(sockaddr_in));
+ SetIPAndPort(szAdrv4, std::to_string(ntohs(pAdrv4->sin_port)));
+ return true;
+ }
+ else if (reinterpret_cast(s)->sin6_family == AF_INET6)
+ {
+ char szAdrv6[INET6_ADDRSTRLEN] {};
+ sockaddr_in6* pAdrv6 = reinterpret_cast(s);
+
+ inet_ntop(pAdrv6->sin6_family, &pAdrv6->sin6_addr, szAdrv6, sizeof(sockaddr_in6));
+ SetIPAndPort(szAdrv6, std::to_string(ntohs(pAdrv6->sin6_port)));
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: removes brackets and port from IP address.
+//-----------------------------------------------------------------------------
+std::string CNetAdr2::GetBase(void) const
+{
+ static std::regex rx("[^\\[]*.(.*)(\\]).*");
+ std::smatch smRegexMatches;
+ std::regex_search(m_svip, smRegexMatches, rx);
+
+ if (smRegexMatches.size() > 0)
+ {
+ return smRegexMatches[1].str();
+ }
+ else
+ {
+ return "127.0.0.1";
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: removes brackets and port from IP address.
+// Input : svInAdr -
+//-----------------------------------------------------------------------------
+std::string CNetAdr2::GetBase(const std::string& svInAdr) const
+{
+ static std::regex rx("[^\\[]*.(.*)(\\]).*");
+ std::smatch smRegexMatches;
+ std::regex_search(svInAdr, smRegexMatches, rx);
+
+ if (smRegexMatches.size() > 0)
+ {
+ return smRegexMatches[1].str();
+ }
+ else
+ {
+ return "127.0.0.1";
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: gets the IP address.
+// Input : bBaseOnly -
+//-----------------------------------------------------------------------------
+std::string CNetAdr2::GetIP(bool bBaseOnly) const
+{
+ if (GetType() == netadrtype_t::NA_LOOPBACK)
+ {
+ return "loopback";
+ }
+ else if (GetType() == netadrtype_t::NA_IP)
+ {
+ if (bBaseOnly)
+ {
+ return GetBase();
+ }
+ else
+ {
+ return m_svip;
+ }
+ }
+ else
+ {
+ return "unknown";
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: removes brackets and IP address from port.
+//-----------------------------------------------------------------------------
+std::string CNetAdr2::GetPort(void) const
+{
+ std::string svport = m_svip;
+ static std::regex rx(".*\\]:");
+ svport = std::regex_replace(svport, rx, "");
+
+ if (!IsValidPort(svport))
+ {
+ return "37015";
+ }
+
+ return svport;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: removes brackets and IP address from port.
+// Input : svInPort -
+//-----------------------------------------------------------------------------
+std::string CNetAdr2::GetPort(std::string svInPort) const
+{
+ static std::regex rx(".*\\]:");
+ svInPort = std::regex_replace(svInPort, rx, "");
+
+ if (!IsValidPort(svInPort))
+ {
+ return "37015";
+ }
+
+ return svInPort;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the IP address and port.
+//-----------------------------------------------------------------------------
+std::string CNetAdr2::GetIPAndPort(void) const
+{
+ return m_svip;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the address type.
+//-----------------------------------------------------------------------------
+netadrtype_t CNetAdr2::GetType(void) const
+{
+ return m_type;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the IP version.
+//-----------------------------------------------------------------------------
+netadrversion_t CNetAdr2::GetVersion(void) const
+{
+ return m_version;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: splits IP address into parts by their delimiters.
+// Output : string vector containing IP parts.
+//-----------------------------------------------------------------------------
+std::vector CNetAdr2::GetParts(void) const
+{
+ std::vector results;
+
+ // Make sure we have a valid address.
+ if (m_version == netadrversion_t::NA_INVALID || m_type != netadrtype_t::NA_IP)
+ {
+ assert(m_version == netadrversion_t::NA_INVALID && "Invalid IP address for 'GetParts()'.");
+ return results;
+ }
+
+ std::string svIpAdr = m_svip, svDelim;
+ std::string::size_type prev_pos = 0, curr_pos = 0;
+
+ // 000.000.000.000 -> vparts.
+ if (m_version == netadrversion_t::NA_V4)
+ {
+ svDelim = ".";
+ }
+ // 0000:0000:0000:0000:0000:0000:0000:0000 -> vparts.
+ else if (m_version == netadrversion_t::NA_V6)
+ {
+ svDelim = ":";
+ StringReplace(svIpAdr, "::", ":");
+ }
+
+ while ((curr_pos = svIpAdr.find(svDelim, curr_pos)) != std::string::npos)
+ {
+ std::string substr(svIpAdr.substr(prev_pos, curr_pos - prev_pos));
+
+ results.push_back(substr);
+ prev_pos = ++curr_pos;
+ }
+ results.push_back(m_svip.substr(prev_pos, curr_pos - prev_pos));
+
+ return results;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the size of the network family struct.
+//-----------------------------------------------------------------------------
+int CNetAdr2::GetSize(void) const
+{
+ if (GetVersion() == netadrversion_t::NA_V4)
+ {
+ return sizeof(sockaddr_in);
+ }
+ else if (GetVersion() == netadrversion_t::NA_V6)
+ {
+ return sizeof(sockaddr_in6);
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the network family version.
+//-----------------------------------------------------------------------------
+int CNetAdr2::GetFamily(void) const
+{
+ if (GetVersion() == netadrversion_t::NA_V4)
+ {
+ return AF_INET;
+ }
+ else if (GetVersion() == netadrversion_t::NA_V6)
+ {
+ return AF_INET6;
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets fields from 'sockaddr'.
+// Input : *pSadr -
+//-----------------------------------------------------------------------------
+void CNetAdr2::ToSockadr(sockaddr_storage* pSadr) const
+{
+ if (GetVersion() == netadrversion_t::NA_V4)
+ {
+ if (GetType() == netadrtype_t::NA_IP)
+ {
+ reinterpret_cast(pSadr)->sin_family = AF_INET;
+ reinterpret_cast(pSadr)->sin_port = htons(stoi(GetPort()));
+ inet_pton(AF_INET, GetBase().c_str(), &reinterpret_cast(pSadr)->sin_addr.s_addr);
+ }
+ else if (GetType() == netadrtype_t::NA_LOOPBACK)
+ {
+ reinterpret_cast(pSadr)->sin_family = AF_INET;
+ reinterpret_cast(pSadr)->sin_port = htons(stoi(GetPort()));
+ reinterpret_cast(pSadr)->sin_addr.s_addr = INADDR_LOOPBACK;
+ }
+ }
+ else if (GetVersion() == netadrversion_t::NA_V6)
+ {
+ if (GetType() == netadrtype_t::NA_IP)
+ {
+ reinterpret_cast(pSadr)->sin6_family = AF_INET6;
+ reinterpret_cast(pSadr)->sin6_port = htons(stoi(GetPort()));
+ inet_pton(AF_INET6, GetBase().c_str(), &reinterpret_cast(pSadr)->sin6_addr);
+ }
+ else if (GetType() == netadrtype_t::NA_LOOPBACK)
+ {
+ reinterpret_cast(pSadr)->sin6_family = AF_INET6;
+ reinterpret_cast(pSadr)->sin6_port = htons(stoi(GetPort()));
+ reinterpret_cast(pSadr)->sin6_addr = in6addr_loopback;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets fields from 'addrinfo'.
+// Input : *pHint -
+//-----------------------------------------------------------------------------
+void CNetAdr2::ToAdrinfo(addrinfo* pHint) const
+{
+ int results {};
+ addrinfo hint {}; // <-- TODO: Pass these instead.
+ if (GetVersion() == netadrversion_t::NA_V4)
+ {
+ hint.ai_flags = AI_PASSIVE;
+ hint.ai_family = AF_INET;
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_TCP;
+
+ results = getaddrinfo(GetBase().c_str(), GetPort().c_str(), &hint, &pHint);
+ if (results != 0)
+ {
+ WCHAR* wszError = gai_strerror(results);
+ _bstr_t b(wszError);
+ const char* pszError = b;
+ spdlog::warn("Address info translation failed ({})", pszError);
+ }
+ }
+ else if (GetVersion() == netadrversion_t::NA_V6)
+ {
+ hint.ai_flags = AI_PASSIVE;
+ hint.ai_family = AF_INET6;
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_TCP;
+
+ results = getaddrinfo(GetBase().c_str(), GetPort().c_str(), &hint, &pHint);
+ if (results != 0)
+ {
+ WCHAR* wszError = gai_strerror(results);
+ _bstr_t b(wszError);
+ const char* pszError = b;
+ spdlog::warn("Address info translation failed ({})", pszError);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if this is a valid port string.
+//-----------------------------------------------------------------------------
+bool CNetAdr2::IsValidPort(const std::string& svInPort) const
+{
+ for (char const& c : svInPort)
+ {
+ if (std::isdigit(c) == 0)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if we are localhost.
+//-----------------------------------------------------------------------------
+bool CNetAdr2::IsLocalhost(void) const
+{
+ return (strcmp(GetBase().c_str(), "127.0.0.1") == 0);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if we use the loopback buffers.
+//-----------------------------------------------------------------------------
+bool CNetAdr2::IsLoopback(void) const
+{
+ return GetType() == netadrtype_t::NA_LOOPBACK;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: check if address is reserved and not routable.
+//-----------------------------------------------------------------------------
+bool CNetAdr2::IsReservedAdr(void) const
+{
+ if (GetType() == netadrtype_t::NA_LOOPBACK)
+ {
+ return true;
+ }
+
+ if (GetType() == netadrtype_t::NA_IP)
+ {
+ std::vector ip_parts = GetParts();
+
+ int n0 = stoi(ip_parts[0]);
+ int n1 = stoi(ip_parts[1]);
+
+ if ((n0 == 10) || // 10.x.x.x is reserved
+ (n0 == 127) || // 127.x.x.x
+ (n0 == 172 && n1 >= 16 && n1 <= 31) || // 172.16.x.x - 172.31.x.x
+ (n0 == 192 && n1 >= 168)) // 192.168.x.x
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: compares IP for equality (IPv4/IPv6).
+// Input : *netAdr2 -
+// bBaseOnly -
+// Output : true if equal, false otherwise.
+//-----------------------------------------------------------------------------
+bool CNetAdr2::CompareAdr(const CNetAdr2& netAdr2, bool bBaseOnly) const
+{
+ if (netAdr2.GetType() != GetType())
+ {
+ return false;
+ }
+
+ if (GetType() == netadrtype_t::NA_LOOPBACK)
+ {
+ return true;
+ }
+
+ if (GetType() == netadrtype_t::NA_IP)
+ {
+ if (!bBaseOnly && (strcmp(netAdr2.GetPort().c_str(), GetPort().c_str()) != 0))
+ {
+ return false;
+ }
+
+ if (strcmp(netAdr2.GetBase().c_str(), GetBase().c_str()) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: compares Class-B IP for equality.
+// Input : *netAdr2 -
+// Output : true if equal, false otherwise.
+//-----------------------------------------------------------------------------
+bool CNetAdr2::CompareClassBAdr(const CNetAdr2& netAdr2) const
+{
+ if (netAdr2.m_version != netadrversion_t::NA_V4 && m_version != netadrversion_t::NA_V4)
+ {
+ return false;
+ }
+
+ if (netAdr2.GetType() != GetType())
+ {
+ return false;
+ }
+
+ if (GetType() == netadrtype_t::NA_LOOPBACK)
+ {
+ return true;
+ }
+
+ if (GetType() == netadrtype_t::NA_IP)
+ {
+ std::vector v0 = netAdr2.GetParts();
+ std::vector v1 = GetParts();
+
+ if (strcmp(v0[0].c_str(), v1[0].c_str()) == 0 && strcmp(v0[1].c_str(), v1[1].c_str()) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: compares Class-C IP for equality.
+// Input : *netAdr2 -
+// Output : true if equal, false otherwise.
+//-----------------------------------------------------------------------------
+bool CNetAdr2::CompareClassCAdr(const CNetAdr2& netAdr2) const
+{
+ if (netAdr2.GetVersion() != netadrversion_t::NA_V4 && GetVersion() != netadrversion_t::NA_V4)
+ {
+ return false;
+ }
+
+ if (netAdr2.GetType() != GetType())
+ {
+ return false;
+ }
+
+ if (GetType() == netadrtype_t::NA_LOOPBACK)
+ {
+ return true;
+ }
+
+ if (GetType() == netadrtype_t::NA_IP)
+ {
+ std::vector v0 = netAdr2.GetParts();
+ std::vector v1 = GetParts();
+
+ if (strcmp(v0[0].c_str(), v1[0].c_str()) == 0 && strcmp(v0[1].c_str(), v1[1].c_str()) == 0 &&
+ strcmp(v0[2].c_str(), v1[2].c_str()) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: for replacing string occurence in given string
+//-----------------------------------------------------------------------------
+bool CNetAdr2::StringReplace(std::string& svStr, std::string svFrom, std::string svTo) const
+{
+ size_t start_pos = svStr.find(svFrom);
+ if (start_pos == std::string::npos)
+ {
+ return false;
+ }
+
+ svStr.replace(start_pos, svFrom.length(), svTo);
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: clears IP address.
+//-----------------------------------------------------------------------------
+void CNetAdr2::Clear(void)
+{
+ m_svip.clear();
+ m_type = netadrtype_t::NA_NULL;
+ m_version = netadrversion_t::NA_INVALID;
+ m_sadr = {};
+}
diff --git a/NorthstarDedicatedTest/NetAdr2.h b/NorthstarDedicatedTest/NetAdr2.h
new file mode 100644
index 000000000..b37e6b481
--- /dev/null
+++ b/NorthstarDedicatedTest/NetAdr2.h
@@ -0,0 +1,94 @@
+#pragma once
+constexpr int MAX_NETCONSOLE_INPUT_LEN = 4096;
+constexpr int MSG_NOSIGNAL = 0;
+
+// typedef struct netpacket_s netpacket_t;
+// typedef struct __declspec(align(8)) netpacket_s
+//{
+// DWORD family_maybe;
+// sockaddr_in sin;
+// WORD sin_port;
+// char gap16;
+// char byte17;
+// DWORD source;
+// double received;
+// std::uint8_t* data;
+// std::uint64_t label;
+// BYTE byte38;
+// std::uint64_t qword40;
+// std::uint64_t qword48;
+// BYTE gap50[8];
+// std::uint64_t qword58;
+// std::uint64_t qword60;
+// std::uint64_t qword68;
+// int less_than_12;
+// DWORD wiresize;
+// BYTE gap78[8];
+// struct netpacket_s* pNext;
+//} netpacket_t;
+
+enum class netadrtype_t
+{
+ NA_NULL = 0,
+ NA_LOOPBACK,
+ NA_IP,
+};
+
+enum class netadrversion_t
+{
+ NA_INVALID = -1,
+ NA_V4 = 4,
+ NA_V6 = 6,
+};
+
+class CNetAdr2
+{
+ public:
+ CNetAdr2(void) {};
+ CNetAdr2(const std::string& svInAdr);
+ CNetAdr2(const std::string& svInAdr, const std::string& svInPort);
+ ~CNetAdr2(void);
+
+ void SetIP(const std::string& svInAdr);
+ void SetPort(const std::string& svInPort);
+ void SetIPAndPort(std::string svInAdr);
+ void SetIPAndPort(std::string svInAdr, std::string svInPort);
+ void SetType(const netadrtype_t& type);
+ void SetVersion(void);
+ void SetFromSocket(const int& hSocket);
+ bool SetFromSockadr(sockaddr_storage* s);
+
+ std::string GetIP(bool bBaseOnly) const;
+ std::string GetPort(void) const;
+ std::string GetPort(std::string svInPort) const;
+ std::string GetIPAndPort(void) const;
+ netadrtype_t GetType(void) const;
+ netadrversion_t GetVersion(void) const;
+ std::string GetBase(void) const;
+ std::string GetBase(const std::string& svInAdr) const;
+ std::vector GetParts(void) const;
+ int GetSize(void) const;
+ int GetFamily(void) const;
+
+ void ToSockadr(sockaddr_storage* pSadr) const;
+ void ToAdrinfo(addrinfo* pHint) const;
+
+ bool IsValidPort(const std::string& svInPort) const;
+ bool IsLocalhost(void) const;
+ bool IsLoopback(void) const;
+ bool IsReservedAdr(void) const;
+
+ bool CompareAdr(const CNetAdr2& adr2, bool bBaseOnly) const;
+ bool CompareClassBAdr(const CNetAdr2& adr2) const;
+ bool CompareClassCAdr(const CNetAdr2& adr2) const;
+
+ bool StringReplace(std::string& svStr, std::string svFrom, std::string svTo) const;
+
+ void Clear(void);
+
+ private:
+ std::string m_svip;
+ netadrtype_t m_type {};
+ netadrversion_t m_version {};
+ sockaddr_storage* m_sadr {};
+};
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
index 06ca7af4b..2b14cad37 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
@@ -60,13 +60,13 @@
Use
pch.h
stdcpp20
- $(ProjectDir)include;%(AdditionalIncludeDirectories)
+ $(ProjectDir)include;$(ProjectDir)include\protobuf;%(AdditionalIncludeDirectories)
Windows
true
false
- $(ProjectDir)include\MinHook.x64.lib;$(ProjectDir)include\libcurl\lib\libcurl_a.lib;dbghelp.lib;Wldap32.lib;Normaliz.lib;version.lib;%(AdditionalDependencies)
+ $(ProjectDir)include\MinHook.x64.lib;$(ProjectDir)include\libcurl\lib\libcurl_a.lib;$(SolutionDir)$(Platform)\$(Configuration)\libprotobuf_x64.lib;dbghelp.lib;Wldap32.lib;Normaliz.lib;version.lib;%(AdditionalDependencies)
%(AdditionalLibraryDirectories)
@@ -87,7 +87,7 @@
Use
pch.h
stdcpp20
- $(ProjectDir)include;%(AdditionalIncludeDirectories)
+ $(ProjectDir)include;$(ProjectDir)include\protobuf;%(AdditionalIncludeDirectories)
MultiThreadedDLL
@@ -96,7 +96,7 @@
true
true
false
- $(ProjectDir)include\MinHook.x64.lib;$(ProjectDir)include\libcurl\lib\libcurl_a.lib;dbghelp.lib;Wldap32.lib;Normaliz.lib;version.lib;%(AdditionalDependencies)
+ $(ProjectDir)include\MinHook.x64.lib;$(ProjectDir)include\libcurl\lib\libcurl_a.lib;$(SolutionDir)$(Platform)\$(Configuration)\libprotobuf_x64.lib;dbghelp.lib;Wldap32.lib;Normaliz.lib;version.lib;%(AdditionalDependencies)
%(AdditionalLibraryDirectories)
@@ -114,6 +114,10 @@
+
+
+
+
@@ -121,6 +125,9 @@
+
+
+
@@ -558,12 +565,16 @@
+
+
+
+
@@ -577,6 +588,11 @@
+
+
+ NotUsing
+ NotUsing
+
@@ -592,6 +608,7 @@
+
@@ -605,6 +622,8 @@
+
+
Create
Create
@@ -612,6 +631,7 @@
+
@@ -623,11 +643,18 @@
+
+
+
+
+ NotUsing
+ NotUsing
+
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
index 6496c7966..2a7c7bb92 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
@@ -1491,6 +1491,39 @@
Header Files
+
+ Header Files\Server
+
+
+ Header Files\Shared
+
+
+ Header Files\Shared
+
+
+ Header Files\Client
+
+
+ Header Files\Client
+
+
+ Header Files\Server
+
+
+ Header Files\Shared
+
+
+ Header Files\Shared\Math
+
+
+ Header Files\Shared
+
+
+ Header Files\Shared
+
+
+ Header Files\Shared
+
Header Files\Client
@@ -1673,6 +1706,36 @@
Source Files
+
+ Source Files\Server
+
+
+ Source Files\Shared
+
+
+ Source Files\Shared
+
+
+ Source Files\Client
+
+
+ Source Files\Client
+
+
+ Source Files\Server
+
+
+ Source Files\Shared\Math
+
+
+ Source Files\Shared
+
+
+ Source Files\Shared
+
+
+ Source Files\Shared
+
Source Files\Client
diff --git a/NorthstarDedicatedTest/cl_rcon.cpp b/NorthstarDedicatedTest/cl_rcon.cpp
new file mode 100644
index 000000000..247a7a2cf
--- /dev/null
+++ b/NorthstarDedicatedTest/cl_rcon.cpp
@@ -0,0 +1,365 @@
+//===========================================================================//
+//
+// Purpose: Implementation of the rcon client.
+//
+//===========================================================================//
+
+#include "pch.h"
+#include "convar.h"
+#include "concommand.h"
+#include "cvar.h"
+#include "net.h"
+#include "rcon_shared.h"
+#include "sv_rcon.pb.h"
+#include "cl_rcon.pb.h"
+#include "cl_rcon.h"
+#include "igameserverdata.h"
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CRConClient::CRConClient() : m_bInitialized(false), m_bConnEstablished(false)
+{
+ m_pNetAdr2 = new CNetAdr2("localhost", "37015");
+ m_pSocket = new CSocketCreator();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CRConClient::~CRConClient(void)
+{
+ delete m_pNetAdr2;
+ delete m_pSocket;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: NETCON systems init
+//-----------------------------------------------------------------------------
+void CRConClient::Init(void)
+{
+ if (!m_bInitialized)
+ {
+ this->SetPassword(CVar_rcon_password->GetString());
+ }
+ m_bInitialized = true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: NETCON systems shutdown
+//-----------------------------------------------------------------------------
+void CRConClient::Shutdown(void)
+{
+ if (m_bConnEstablished)
+ {
+ this->Disconnect();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: changes the password
+// Input : *pszPassword -
+// Output : true on success, false otherwise
+//-----------------------------------------------------------------------------
+bool CRConClient::SetPassword(const char* pszPassword)
+{
+ if (std::strlen(pszPassword) < 8)
+ {
+ if (std::strlen(pszPassword) > 0)
+ {
+ spdlog::info("Remote server access requires a password of at least 8 characters");
+ }
+ return false;
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: client rcon main processing loop
+//-----------------------------------------------------------------------------
+void CRConClient::RunFrame(void)
+{
+ if (m_bInitialized && m_bConnEstablished)
+ {
+ this->Recv();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: connect to address and port stored in 'rcon_address' cvar
+// Output : true if connection succeeds, false otherwise
+//-----------------------------------------------------------------------------
+bool CRConClient::Connect(void)
+{
+ if (strlen(CVar_rcon_address->GetString()) > 0)
+ {
+ // Default is [127.0.0.1]:37015
+ m_pNetAdr2->SetIPAndPort(CVar_rcon_address->GetString());
+ }
+
+ if (m_pSocket->ConnectSocket(*m_pNetAdr2, true) == SOCKET_ERROR)
+ {
+ spdlog::info("Connection to RCON server '{:s}' failed: (SOCKET_ERROR)", m_pNetAdr2->GetIPAndPort());
+ return false;
+ }
+ spdlog::info("Connected to: {:s}", m_pNetAdr2->GetIPAndPort());
+
+ m_bConnEstablished = true;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: connect to specified address and port
+// Input : *svInAdr -
+// *svInPort -
+// Output : true if connection succeeds, false otherwise
+//-----------------------------------------------------------------------------
+bool CRConClient::Connect(const std::string& svInAdr, const std::string& svInPort)
+{
+ if (svInAdr.size() > 0 && svInPort.size() > 0)
+ {
+ // Default is [127.0.0.1]:37015
+ m_pNetAdr2->SetIPAndPort(svInAdr, svInPort);
+ }
+
+ if (m_pSocket->ConnectSocket(*m_pNetAdr2, true) == SOCKET_ERROR)
+ {
+ spdlog::info("Connection to RCON server '{:s}' failed: (SOCKET_ERROR)", m_pNetAdr2->GetIPAndPort());
+ return false;
+ }
+ spdlog::info("Connected to: {:s}", m_pNetAdr2->GetIPAndPort());
+
+ m_bConnEstablished = true;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: disconnect from current session
+//-----------------------------------------------------------------------------
+void CRConClient::Disconnect(void)
+{
+ m_pSocket->CloseAcceptedSocket(0);
+ m_bConnEstablished = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: send message
+// Input : *svMessage -
+//-----------------------------------------------------------------------------
+void CRConClient::Send(const std::string& svMessage) const
+{
+ std::ostringstream ssSendBuf;
+
+ ssSendBuf << static_cast(static_cast(svMessage.size()) >> 24);
+ ssSendBuf << static_cast(static_cast(svMessage.size()) >> 16);
+ ssSendBuf << static_cast(static_cast(svMessage.size()) >> 8);
+ ssSendBuf << static_cast(static_cast(svMessage.size()));
+ ssSendBuf << svMessage;
+
+ int nSendResult = ::send(
+ m_pSocket->GetAcceptedSocketData(0)->m_hSocket, ssSendBuf.str().data(), static_cast(ssSendBuf.str().size()), MSG_NOSIGNAL);
+ if (nSendResult == SOCKET_ERROR)
+ {
+ spdlog::info("Failed to send RCON message: (SOCKET_ERROR)");
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: receive message
+//-----------------------------------------------------------------------------
+void CRConClient::Recv(void)
+{
+ static char szRecvBuf[1024];
+ CConnectedNetConsoleData* pData = m_pSocket->GetAcceptedSocketData(0);
+
+ { //////////////////////////////////////////////
+ int nPendingLen = ::recv(pData->m_hSocket, szRecvBuf, sizeof(char), MSG_PEEK);
+ if (nPendingLen == SOCKET_ERROR && m_pSocket->IsSocketBlocking())
+ {
+ return;
+ }
+ if (nPendingLen <= 0 && m_bConnEstablished) // EOF or error.
+ {
+ this->Disconnect();
+ spdlog::info("Server closed RCON connection");
+ return;
+ }
+ } //////////////////////////////////////////////
+
+ u_long nReadLen; // Find out how much we have to read.
+ ::ioctlsocket(pData->m_hSocket, FIONREAD, &nReadLen);
+
+ while (nReadLen > 0)
+ {
+ int nRecvLen = ::recv(pData->m_hSocket, szRecvBuf, MIN(sizeof(szRecvBuf), nReadLen), MSG_NOSIGNAL);
+ if (nRecvLen == 0 && m_bConnEstablished) // Socket was closed.
+ {
+ this->Disconnect();
+ spdlog::info("Server closed RCON connection");
+ break;
+ }
+ if (nRecvLen < 0 && !m_pSocket->IsSocketBlocking())
+ {
+ spdlog::error("RCON Cmd: recv error ({:s})", NET_ErrorString(WSAGetLastError()));
+ break;
+ }
+
+ nReadLen -= nRecvLen; // Process what we've got.
+ this->ProcessBuffer(szRecvBuf, nRecvLen, pData);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: parses input response buffer using length-prefix framing
+// Input : *pszIn -
+// nRecvLen -
+// *pData -
+//-----------------------------------------------------------------------------
+void CRConClient::ProcessBuffer(const char* pRecvBuf, int nRecvLen, CConnectedNetConsoleData* pData)
+{
+ while (nRecvLen > 0)
+ {
+ if (pData->m_nPayloadLen)
+ {
+ if (pData->m_nPayloadRead < pData->m_nPayloadLen)
+ {
+ pData->m_RecvBuffer[pData->m_nPayloadRead++] = *pRecvBuf;
+
+ pRecvBuf++;
+ nRecvLen--;
+ }
+ if (pData->m_nPayloadRead == pData->m_nPayloadLen)
+ {
+ this->ProcessMessage(
+ this->Deserialize(std::string(reinterpret_cast(pData->m_RecvBuffer.data()), pData->m_nPayloadLen)));
+
+ pData->m_nPayloadLen = 0;
+ pData->m_nPayloadRead = 0;
+ }
+ }
+ else if (pData->m_nPayloadRead < sizeof(int)) // Read size field.
+ {
+ pData->m_RecvBuffer[pData->m_nPayloadRead++] = *pRecvBuf;
+
+ pRecvBuf++;
+ nRecvLen--;
+ }
+ else // Build prefix.
+ {
+ pData->m_nPayloadLen = static_cast(
+ pData->m_RecvBuffer[0] << 24 | pData->m_RecvBuffer[1] << 16 | pData->m_RecvBuffer[2] << 8 | pData->m_RecvBuffer[3]);
+ pData->m_nPayloadRead = 0;
+
+ if (pData->m_nPayloadLen < 0)
+ {
+ spdlog::error("RCON Cmd: sync error ({:d})", pData->m_nPayloadLen);
+ this->Disconnect(); // Out of sync (irrecoverable).
+
+ break;
+ }
+ else
+ {
+ pData->m_RecvBuffer.resize(pData->m_nPayloadLen);
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: processes received message
+// Input : *sv_response -
+//-----------------------------------------------------------------------------
+void CRConClient::ProcessMessage(const sv_rcon::response& sv_response) const
+{
+ std::string svOut = sv_response.responsebuf();
+
+ switch (sv_response.responsetype())
+ {
+ case sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH:
+ {
+ svOut.erase(std::remove(svOut.begin(), svOut.end(), '\n'), svOut.end());
+ spdlog::info("{:s}", svOut);
+ break;
+ }
+ case sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG:
+ {
+ // !TODO: Network the enum to differentiate script/engine logs.
+ svOut.erase(std::remove(svOut.begin(), svOut.end(), '\n'), svOut.end());
+ spdlog::info("{:s}", svOut);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: serializes input
+// Input : *svReqBuf -
+// *svReqVal -
+// request_t -
+// Output : serialized results as string
+//-----------------------------------------------------------------------------
+std::string CRConClient::Serialize(const std::string& svReqBuf, const std::string& svReqVal, cl_rcon::request_t request_t) const
+{
+ cl_rcon::request cl_request;
+
+ cl_request.set_requestid(-1);
+ cl_request.set_requesttype(request_t);
+
+ switch (request_t)
+ {
+ case cl_rcon::request_t::SERVERDATA_REQUEST_SETVALUE:
+ case cl_rcon::request_t::SERVERDATA_REQUEST_AUTH:
+ {
+ cl_request.set_requestbuf(svReqBuf);
+ cl_request.set_requestval(svReqVal);
+ break;
+ }
+ case cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND:
+ {
+ cl_request.set_requestbuf(svReqBuf);
+ break;
+ }
+ }
+ return cl_request.SerializeAsString();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: de-serializes input
+// Input : *svBuf -
+// Output : de-serialized object
+//-----------------------------------------------------------------------------
+sv_rcon::response CRConClient::Deserialize(const std::string& svBuf) const
+{
+ sv_rcon::response sv_response;
+ sv_response.ParseFromArray(svBuf.data(), static_cast(svBuf.size()));
+
+ return sv_response;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: checks if client rcon is initialized
+// Output : true if initialized, false otherwise
+//-----------------------------------------------------------------------------
+bool CRConClient::IsInitialized(void) const
+{
+ return m_bInitialized;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: checks if client rcon is connected
+// Output : true if connected, false otherwise
+//-----------------------------------------------------------------------------
+bool CRConClient::IsConnected(void) const
+{
+ return m_bConnEstablished;
+}
+///////////////////////////////////////////////////////////////////////////////
+CRConClient* g_pRConClient = new CRConClient();
+CRConClient* RCONClient()
+{
+ return g_pRConClient;
+}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/cl_rcon.h b/NorthstarDedicatedTest/cl_rcon.h
new file mode 100644
index 000000000..aedc579e6
--- /dev/null
+++ b/NorthstarDedicatedTest/cl_rcon.h
@@ -0,0 +1,43 @@
+#pragma once
+#include "NetAdr2.h"
+#include "SocketCreator.h"
+#include "sv_rcon.pb.h"
+#include "cl_rcon.pb.h"
+
+class CRConClient
+{
+ public:
+ CRConClient(void);
+ ~CRConClient(void);
+
+ void Init(void);
+ void Shutdown(void);
+
+ bool SetPassword(const char* pszPassword);
+ void RunFrame(void);
+
+ bool Connect(void);
+ bool Connect(const std::string& svInAdr, const std::string& svInPort);
+ void Disconnect(void);
+
+ void Send(const std::string& svMessage) const;
+ void Recv(void);
+
+ void ProcessBuffer(const char* pRecvBuf, int nRecvLen, CConnectedNetConsoleData* pData);
+ void ProcessMessage(const sv_rcon::response& sv_response) const;
+
+ std::string Serialize(const std::string& svReqBuf, const std::string& svReqVal, cl_rcon::request_t request_t) const;
+ sv_rcon::response Deserialize(const std::string& svBuf) const;
+
+ bool IsInitialized(void) const;
+ bool IsConnected(void) const;
+
+ private:
+ CNetAdr2* m_pNetAdr2;
+ CSocketCreator* m_pSocket;
+
+ bool m_bInitialized = false;
+ bool m_bConnEstablished = false;
+};
+extern CRConClient* g_pRConClient;
+CRConClient* RCONClient();
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/cl_rcon.pb.cc b/NorthstarDedicatedTest/cl_rcon.pb.cc
new file mode 100644
index 000000000..4076cc342
--- /dev/null
+++ b/NorthstarDedicatedTest/cl_rcon.pb.cc
@@ -0,0 +1,492 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: cl_rcon.proto
+
+#include "cl_rcon.pb.h"
+
+#include
+
+#include
+#include
+#include
+#include
+// @@protoc_insertion_point(includes)
+#include
+
+PROTOBUF_PRAGMA_INIT_SEG
+namespace cl_rcon
+{
+ constexpr request::request(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+ : requestbuf_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string),
+ requestval_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string), requestid_(0), requesttype_(0)
+ {
+ }
+ struct requestDefaultTypeInternal
+ {
+ constexpr requestDefaultTypeInternal() : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized {}) {}
+ ~requestDefaultTypeInternal() {}
+ union
+ {
+ request _instance;
+ };
+ };
+ PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT requestDefaultTypeInternal _request_default_instance_;
+} // namespace cl_rcon
+namespace cl_rcon
+{
+ bool request_t_IsValid(int value)
+ {
+ switch (value)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ static ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed request_t_strings[6] = {};
+
+ static const char request_t_names[] = "SERVERDATA_REQUEST_AUTH"
+ "SERVERDATA_REQUEST_EXECCOMMAND"
+ "SERVERDATA_REQUEST_SEND_CONSOLE_LOG"
+ "SERVERDATA_REQUEST_SEND_REMOTEBUG"
+ "SERVERDATA_REQUEST_SETVALUE"
+ "SERVERDATA_REQUEST_VALUE";
+
+ static const ::PROTOBUF_NAMESPACE_ID::internal::EnumEntry request_t_entries[] = {
+ {{request_t_names + 0, 23}, 3},
+ {{request_t_names + 23, 30}, 2},
+ {{request_t_names + 53, 35}, 4},
+ {{request_t_names + 88, 33}, 5},
+ {{request_t_names + 121, 27}, 1},
+ {{request_t_names + 148, 24}, 0},
+ };
+
+ static const int request_t_entries_by_number[] = {
+ 5, // 0 -> SERVERDATA_REQUEST_VALUE
+ 4, // 1 -> SERVERDATA_REQUEST_SETVALUE
+ 1, // 2 -> SERVERDATA_REQUEST_EXECCOMMAND
+ 0, // 3 -> SERVERDATA_REQUEST_AUTH
+ 2, // 4 -> SERVERDATA_REQUEST_SEND_CONSOLE_LOG
+ 3, // 5 -> SERVERDATA_REQUEST_SEND_REMOTEBUG
+ };
+
+ const std::string& request_t_Name(request_t value)
+ {
+ static const bool dummy =
+ ::PROTOBUF_NAMESPACE_ID::internal::InitializeEnumStrings(request_t_entries, request_t_entries_by_number, 6, request_t_strings);
+ (void)dummy;
+ int idx = ::PROTOBUF_NAMESPACE_ID::internal::LookUpEnumName(request_t_entries, request_t_entries_by_number, 6, value);
+ return idx == -1 ? ::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString() : request_t_strings[idx].get();
+ }
+ bool request_t_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, request_t* value)
+ {
+ int int_value;
+ bool success = ::PROTOBUF_NAMESPACE_ID::internal::LookUpEnumValue(request_t_entries, 6, name, &int_value);
+ if (success)
+ {
+ *value = static_cast(int_value);
+ }
+ return success;
+ }
+
+ // ===================================================================
+
+ class request::_Internal
+ {
+ public:
+ using HasBits = decltype(std::declval()._has_bits_);
+ static void set_has_requestid(HasBits* has_bits)
+ {
+ (*has_bits)[0] |= 4u;
+ }
+ static void set_has_requesttype(HasBits* has_bits)
+ {
+ (*has_bits)[0] |= 8u;
+ }
+ static void set_has_requestbuf(HasBits* has_bits)
+ {
+ (*has_bits)[0] |= 1u;
+ }
+ static void set_has_requestval(HasBits* has_bits)
+ {
+ (*has_bits)[0] |= 2u;
+ }
+ };
+
+ request::request(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned)
+ : ::PROTOBUF_NAMESPACE_ID::MessageLite(arena, is_message_owned)
+ {
+ SharedCtor();
+ if (!is_message_owned)
+ {
+ RegisterArenaDtor(arena);
+ }
+ // @@protoc_insertion_point(arena_constructor:cl_rcon.request)
+ }
+ request::request(const request& from) : ::PROTOBUF_NAMESPACE_ID::MessageLite(), _has_bits_(from._has_bits_)
+ {
+ _internal_metadata_.MergeFrom(from._internal_metadata_);
+ requestbuf_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ requestbuf_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (from._internal_has_requestbuf())
+ {
+ requestbuf_.Set(
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault {}, from._internal_requestbuf(), GetArenaForAllocation());
+ }
+ requestval_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ requestval_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (from._internal_has_requestval())
+ {
+ requestval_.Set(
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault {}, from._internal_requestval(), GetArenaForAllocation());
+ }
+ ::memcpy(
+ &requestid_,
+ &from.requestid_,
+ static_cast(reinterpret_cast(&requesttype_) - reinterpret_cast(&requestid_)) + sizeof(requesttype_));
+ // @@protoc_insertion_point(copy_constructor:cl_rcon.request)
+ }
+
+ inline void request::SharedCtor()
+ {
+ requestbuf_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ requestbuf_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ requestval_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ requestval_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ ::memset(
+ reinterpret_cast(this) + static_cast(reinterpret_cast(&requestid_) - reinterpret_cast(this)),
+ 0,
+ static_cast(reinterpret_cast(&requesttype_) - reinterpret_cast(&requestid_)) + sizeof(requesttype_));
+ }
+
+ request::~request()
+ {
+ // @@protoc_insertion_point(destructor:cl_rcon.request)
+ if (GetArenaForAllocation() != nullptr)
+ return;
+ SharedDtor();
+ _internal_metadata_.Delete();
+ }
+
+ inline void request::SharedDtor()
+ {
+ GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
+ requestbuf_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ requestval_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ }
+
+ void request::ArenaDtor(void* object)
+ {
+ request* _this = reinterpret_cast(object);
+ (void)_this;
+ }
+ void request::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {}
+ void request::SetCachedSize(int size) const
+ {
+ _cached_size_.Set(size);
+ }
+
+ void request::Clear()
+ {
+ // @@protoc_insertion_point(message_clear_start:cl_rcon.request)
+ uint32_t cached_has_bits = 0;
+ // Prevent compiler warnings about cached_has_bits being unused
+ (void)cached_has_bits;
+
+ cached_has_bits = _has_bits_[0];
+ if (cached_has_bits & 0x00000003u)
+ {
+ if (cached_has_bits & 0x00000001u)
+ {
+ requestbuf_.ClearNonDefaultToEmpty();
+ }
+ if (cached_has_bits & 0x00000002u)
+ {
+ requestval_.ClearNonDefaultToEmpty();
+ }
+ }
+ if (cached_has_bits & 0x0000000cu)
+ {
+ ::memset(
+ &requestid_,
+ 0,
+ static_cast(reinterpret_cast(&requesttype_) - reinterpret_cast(&requestid_)) + sizeof(requesttype_));
+ }
+ _has_bits_.Clear();
+ _internal_metadata_.Clear();
+ }
+
+ const char* request::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx)
+ {
+#define CHK_(x) \
+ if (PROTOBUF_PREDICT_FALSE(!(x))) \
+ goto failure
+ _Internal::HasBits has_bits {};
+ while (!ctx->Done(&ptr))
+ {
+ uint32_t tag;
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+ switch (tag >> 3)
+ {
+ // optional int32 requestID = 1;
+ case 1:
+ if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8))
+ {
+ _Internal::set_has_requestid(&has_bits);
+ requestid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
+ CHK_(ptr);
+ }
+ else
+ goto handle_unusual;
+ continue;
+ // optional .cl_rcon.request_t requestType = 2;
+ case 2:
+ if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16))
+ {
+ uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+ CHK_(ptr);
+ _internal_set_requesttype(static_cast<::cl_rcon::request_t>(val));
+ }
+ else
+ goto handle_unusual;
+ continue;
+ // optional string requestBuf = 3;
+ case 3:
+ if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 26))
+ {
+ auto str = _internal_mutable_requestbuf();
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
+ CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, nullptr));
+ CHK_(ptr);
+ }
+ else
+ goto handle_unusual;
+ continue;
+ // optional string requestVal = 4;
+ case 4:
+ if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 34))
+ {
+ auto str = _internal_mutable_requestval();
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
+ CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, nullptr));
+ CHK_(ptr);
+ }
+ else
+ goto handle_unusual;
+ continue;
+ default:
+ goto handle_unusual;
+ } // switch
+ handle_unusual:
+ if ((tag == 0) || ((tag & 7) == 4))
+ {
+ CHK_(ptr);
+ ctx->SetLastTag(tag);
+ goto message_done;
+ }
+ ptr = UnknownFieldParse(tag, _internal_metadata_.mutable_unknown_fields(), ptr, ctx);
+ CHK_(ptr != nullptr);
+ } // while
+ message_done:
+ _has_bits_.Or(has_bits);
+ return ptr;
+ failure:
+ ptr = nullptr;
+ goto message_done;
+#undef CHK_
+ }
+
+ uint8_t* request::_InternalSerialize(uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const
+ {
+ // @@protoc_insertion_point(serialize_to_array_start:cl_rcon.request)
+ uint32_t cached_has_bits = 0;
+ (void)cached_has_bits;
+
+ // optional int32 requestID = 1;
+ if (_internal_has_requestid())
+ {
+ target = stream->EnsureSpace(target);
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_requestid(), target);
+ }
+
+ // optional .cl_rcon.request_t requestType = 2;
+ if (_internal_has_requesttype())
+ {
+ target = stream->EnsureSpace(target);
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(2, this->_internal_requesttype(), target);
+ }
+
+ // optional string requestBuf = 3;
+ if (_internal_has_requestbuf())
+ {
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
+ this->_internal_requestbuf().data(),
+ static_cast(this->_internal_requestbuf().length()),
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
+ "cl_rcon.request.requestBuf");
+ target = stream->WriteStringMaybeAliased(3, this->_internal_requestbuf(), target);
+ }
+
+ // optional string requestVal = 4;
+ if (_internal_has_requestval())
+ {
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
+ this->_internal_requestval().data(),
+ static_cast(this->_internal_requestval().length()),
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
+ "cl_rcon.request.requestVal");
+ target = stream->WriteStringMaybeAliased(4, this->_internal_requestval(), target);
+ }
+
+ if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields()))
+ {
+ target = stream->WriteRaw(
+ _internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).data(),
+ static_cast(_internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).size()),
+ target);
+ }
+ // @@protoc_insertion_point(serialize_to_array_end:cl_rcon.request)
+ return target;
+ }
+
+ size_t request::ByteSizeLong() const
+ {
+ // @@protoc_insertion_point(message_byte_size_start:cl_rcon.request)
+ size_t total_size = 0;
+
+ uint32_t cached_has_bits = 0;
+ // Prevent compiler warnings about cached_has_bits being unused
+ (void)cached_has_bits;
+
+ cached_has_bits = _has_bits_[0];
+ if (cached_has_bits & 0x0000000fu)
+ {
+ // optional string requestBuf = 3;
+ if (cached_has_bits & 0x00000001u)
+ {
+ total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(this->_internal_requestbuf());
+ }
+
+ // optional string requestVal = 4;
+ if (cached_has_bits & 0x00000002u)
+ {
+ total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(this->_internal_requestval());
+ }
+
+ // optional int32 requestID = 1;
+ if (cached_has_bits & 0x00000004u)
+ {
+ total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32SizePlusOne(this->_internal_requestid());
+ }
+
+ // optional .cl_rcon.request_t requestType = 2;
+ if (cached_has_bits & 0x00000008u)
+ {
+ total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_requesttype());
+ }
+ }
+ if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields()))
+ {
+ total_size += _internal_metadata_.unknown_fields(::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString).size();
+ }
+ int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
+ SetCachedSize(cached_size);
+ return total_size;
+ }
+
+ void request::CheckTypeAndMergeFrom(const ::PROTOBUF_NAMESPACE_ID::MessageLite& from)
+ {
+ MergeFrom(*::PROTOBUF_NAMESPACE_ID::internal::DownCast(&from));
+ }
+
+ void request::MergeFrom(const request& from)
+ {
+ // @@protoc_insertion_point(class_specific_merge_from_start:cl_rcon.request)
+ GOOGLE_DCHECK_NE(&from, this);
+ uint32_t cached_has_bits = 0;
+ (void)cached_has_bits;
+
+ cached_has_bits = from._has_bits_[0];
+ if (cached_has_bits & 0x0000000fu)
+ {
+ if (cached_has_bits & 0x00000001u)
+ {
+ _internal_set_requestbuf(from._internal_requestbuf());
+ }
+ if (cached_has_bits & 0x00000002u)
+ {
+ _internal_set_requestval(from._internal_requestval());
+ }
+ if (cached_has_bits & 0x00000004u)
+ {
+ requestid_ = from.requestid_;
+ }
+ if (cached_has_bits & 0x00000008u)
+ {
+ requesttype_ = from.requesttype_;
+ }
+ _has_bits_[0] |= cached_has_bits;
+ }
+ _internal_metadata_.MergeFrom(from._internal_metadata_);
+ }
+
+ void request::CopyFrom(const request& from)
+ {
+ // @@protoc_insertion_point(class_specific_copy_from_start:cl_rcon.request)
+ if (&from == this)
+ return;
+ Clear();
+ MergeFrom(from);
+ }
+
+ bool request::IsInitialized() const
+ {
+ return true;
+ }
+
+ void request::InternalSwap(request* other)
+ {
+ using std::swap;
+ auto* lhs_arena = GetArenaForAllocation();
+ auto* rhs_arena = other->GetArenaForAllocation();
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+ swap(_has_bits_[0], other->_has_bits_[0]);
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+ &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), &requestbuf_, lhs_arena, &other->requestbuf_, rhs_arena);
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+ &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), &requestval_, lhs_arena, &other->requestval_, rhs_arena);
+ ::PROTOBUF_NAMESPACE_ID::internal::memswap<
+ PROTOBUF_FIELD_OFFSET(request, requesttype_) + sizeof(request::requesttype_) - PROTOBUF_FIELD_OFFSET(request, requestid_)>(
+ reinterpret_cast(&requestid_), reinterpret_cast(&other->requestid_));
+ }
+
+ std::string request::GetTypeName() const
+ {
+ return "cl_rcon.request";
+ }
+
+ // @@protoc_insertion_point(namespace_scope)
+} // namespace cl_rcon
+PROTOBUF_NAMESPACE_OPEN
+template <> PROTOBUF_NOINLINE ::cl_rcon::request* Arena::CreateMaybeMessage<::cl_rcon::request>(Arena* arena)
+{
+ return Arena::CreateMessageInternal<::cl_rcon::request>(arena);
+}
+PROTOBUF_NAMESPACE_CLOSE
+
+// @@protoc_insertion_point(global_scope)
+#include
diff --git a/NorthstarDedicatedTest/cl_rcon.pb.h b/NorthstarDedicatedTest/cl_rcon.pb.h
new file mode 100644
index 000000000..082520a14
--- /dev/null
+++ b/NorthstarDedicatedTest/cl_rcon.pb.h
@@ -0,0 +1,582 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: cl_rcon.proto
+
+#ifndef GOOGLE_PROTOBUF_INCLUDED_cl_5frcon_2eproto
+#define GOOGLE_PROTOBUF_INCLUDED_cl_5frcon_2eproto
+
+#include
+#include
+
+#include
+#if PROTOBUF_VERSION < 3019000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3019004 < PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include // IWYU pragma: export
+#include // IWYU pragma: export
+#include
+// @@protoc_insertion_point(includes)
+#include
+#define PROTOBUF_INTERNAL_EXPORT_cl_5frcon_2eproto
+PROTOBUF_NAMESPACE_OPEN
+namespace internal
+{
+ class AnyMetadata;
+} // namespace internal
+PROTOBUF_NAMESPACE_CLOSE
+
+// Internal implementation detail -- do not use these members.
+struct TableStruct_cl_5frcon_2eproto
+{
+ static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+ static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+ static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1] PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+ static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[];
+ static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
+ static const uint32_t offsets[];
+};
+namespace cl_rcon
+{
+ class request;
+ struct requestDefaultTypeInternal;
+ extern requestDefaultTypeInternal _request_default_instance_;
+} // namespace cl_rcon
+PROTOBUF_NAMESPACE_OPEN
+template <>::cl_rcon::request* Arena::CreateMaybeMessage<::cl_rcon::request>(Arena*);
+PROTOBUF_NAMESPACE_CLOSE
+namespace cl_rcon
+{
+
+ enum request_t : int
+ {
+ SERVERDATA_REQUEST_VALUE = 0,
+ SERVERDATA_REQUEST_SETVALUE = 1,
+ SERVERDATA_REQUEST_EXECCOMMAND = 2,
+ SERVERDATA_REQUEST_AUTH = 3,
+ SERVERDATA_REQUEST_SEND_CONSOLE_LOG = 4,
+ SERVERDATA_REQUEST_SEND_REMOTEBUG = 5,
+ request_t_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits::min(),
+ request_t_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits::max()
+ };
+ bool request_t_IsValid(int value);
+ constexpr request_t request_t_MIN = SERVERDATA_REQUEST_VALUE;
+ constexpr request_t request_t_MAX = SERVERDATA_REQUEST_SEND_REMOTEBUG;
+ constexpr int request_t_ARRAYSIZE = request_t_MAX + 1;
+
+ const std::string& request_t_Name(request_t value);
+ template inline const std::string& request_t_Name(T enum_t_value)
+ {
+ static_assert(
+ ::std::is_same::value || ::std::is_integral::value, "Incorrect type passed to function request_t_Name.");
+ return request_t_Name(static_cast(enum_t_value));
+ }
+ bool request_t_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, request_t* value);
+ // ===================================================================
+
+ class request final : public ::PROTOBUF_NAMESPACE_ID::MessageLite /* @@protoc_insertion_point(class_definition:cl_rcon.request) */
+ {
+ public:
+ inline request() : request(nullptr) {}
+ ~request() override;
+ explicit constexpr request(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+ request(const request& from);
+ request(request&& from) noexcept : request()
+ {
+ *this = ::std::move(from);
+ }
+
+ inline request& operator=(const request& from)
+ {
+ CopyFrom(from);
+ return *this;
+ }
+ inline request& operator=(request&& from) noexcept
+ {
+ if (this == &from)
+ return *this;
+ if (GetOwningArena() == from.GetOwningArena()
+#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
+ && GetOwningArena() != nullptr
+#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
+ )
+ {
+ InternalSwap(&from);
+ }
+ else
+ {
+ CopyFrom(from);
+ }
+ return *this;
+ }
+
+ static const request& default_instance()
+ {
+ return *internal_default_instance();
+ }
+ static inline const request* internal_default_instance()
+ {
+ return reinterpret_cast(&_request_default_instance_);
+ }
+ static constexpr int kIndexInFileMessages = 0;
+
+ friend void swap(request& a, request& b)
+ {
+ a.Swap(&b);
+ }
+ inline void Swap(request* other)
+ {
+ if (other == this)
+ return;
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+ if (GetOwningArena() != nullptr && GetOwningArena() == other->GetOwningArena())
+ {
+#else // PROTOBUF_FORCE_COPY_IN_SWAP
+ if (GetOwningArena() == other->GetOwningArena())
+ {
+#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
+ InternalSwap(other);
+ }
+ else
+ {
+ ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+ }
+ }
+ void UnsafeArenaSwap(request* other)
+ {
+ if (other == this)
+ return;
+ GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
+ InternalSwap(other);
+ }
+
+ // implements Message ----------------------------------------------
+
+ request* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final
+ {
+ return CreateMaybeMessage(arena);
+ }
+ void CheckTypeAndMergeFrom(const ::PROTOBUF_NAMESPACE_ID::MessageLite& from) final;
+ void CopyFrom(const request& from);
+ void MergeFrom(const request& from);
+ PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+ bool IsInitialized() const final;
+
+ size_t ByteSizeLong() const final;
+ const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+ uint8_t* _InternalSerialize(uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+ int GetCachedSize() const final
+ {
+ return _cached_size_.Get();
+ }
+
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(request* other);
+
+ private:
+ friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+ static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName()
+ {
+ return "cl_rcon.request";
+ }
+
+ protected:
+ explicit request(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned = false);
+
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+
+ public:
+ std::string GetTypeName() const final;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ enum : int
+ {
+ kRequestBufFieldNumber = 3,
+ kRequestValFieldNumber = 4,
+ kRequestIDFieldNumber = 1,
+ kRequestTypeFieldNumber = 2,
+ };
+ // optional string requestBuf = 3;
+ bool has_requestbuf() const;
+
+ private:
+ bool _internal_has_requestbuf() const;
+
+ public:
+ void clear_requestbuf();
+ const std::string& requestbuf() const;
+ template void set_requestbuf(ArgT0&& arg0, ArgT... args);
+ std::string* mutable_requestbuf();
+ PROTOBUF_NODISCARD std::string* release_requestbuf();
+ void set_allocated_requestbuf(std::string* requestbuf);
+
+ private:
+ const std::string& _internal_requestbuf() const;
+ inline PROTOBUF_ALWAYS_INLINE void _internal_set_requestbuf(const std::string& value);
+ std::string* _internal_mutable_requestbuf();
+
+ public:
+ // optional string requestVal = 4;
+ bool has_requestval() const;
+
+ private:
+ bool _internal_has_requestval() const;
+
+ public:
+ void clear_requestval();
+ const std::string& requestval() const;
+ template void set_requestval(ArgT0&& arg0, ArgT... args);
+ std::string* mutable_requestval();
+ PROTOBUF_NODISCARD std::string* release_requestval();
+ void set_allocated_requestval(std::string* requestval);
+
+ private:
+ const std::string& _internal_requestval() const;
+ inline PROTOBUF_ALWAYS_INLINE void _internal_set_requestval(const std::string& value);
+ std::string* _internal_mutable_requestval();
+
+ public:
+ // optional int32 requestID = 1;
+ bool has_requestid() const;
+
+ private:
+ bool _internal_has_requestid() const;
+
+ public:
+ void clear_requestid();
+ int32_t requestid() const;
+ void set_requestid(int32_t value);
+
+ private:
+ int32_t _internal_requestid() const;
+ void _internal_set_requestid(int32_t value);
+
+ public:
+ // optional .cl_rcon.request_t requestType = 2;
+ bool has_requesttype() const;
+
+ private:
+ bool _internal_has_requesttype() const;
+
+ public:
+ void clear_requesttype();
+ ::cl_rcon::request_t requesttype() const;
+ void set_requesttype(::cl_rcon::request_t value);
+
+ private:
+ ::cl_rcon::request_t _internal_requesttype() const;
+ void _internal_set_requesttype(::cl_rcon::request_t value);
+
+ public:
+ // @@protoc_insertion_point(class_scope:cl_rcon.request)
+ private:
+ class _Internal;
+
+ template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
+ mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr requestbuf_;
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr requestval_;
+ int32_t requestid_;
+ int requesttype_;
+ friend struct ::TableStruct_cl_5frcon_2eproto;
+ };
+ // ===================================================================
+
+ // ===================================================================
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif // __GNUC__
+ // request
+
+ // optional int32 requestID = 1;
+ inline bool request::_internal_has_requestid() const
+ {
+ bool value = (_has_bits_[0] & 0x00000004u) != 0;
+ return value;
+ }
+ inline bool request::has_requestid() const
+ {
+ return _internal_has_requestid();
+ }
+ inline void request::clear_requestid()
+ {
+ requestid_ = 0;
+ _has_bits_[0] &= ~0x00000004u;
+ }
+ inline int32_t request::_internal_requestid() const
+ {
+ return requestid_;
+ }
+ inline int32_t request::requestid() const
+ {
+ // @@protoc_insertion_point(field_get:cl_rcon.request.requestID)
+ return _internal_requestid();
+ }
+ inline void request::_internal_set_requestid(int32_t value)
+ {
+ _has_bits_[0] |= 0x00000004u;
+ requestid_ = value;
+ }
+ inline void request::set_requestid(int32_t value)
+ {
+ _internal_set_requestid(value);
+ // @@protoc_insertion_point(field_set:cl_rcon.request.requestID)
+ }
+
+ // optional .cl_rcon.request_t requestType = 2;
+ inline bool request::_internal_has_requesttype() const
+ {
+ bool value = (_has_bits_[0] & 0x00000008u) != 0;
+ return value;
+ }
+ inline bool request::has_requesttype() const
+ {
+ return _internal_has_requesttype();
+ }
+ inline void request::clear_requesttype()
+ {
+ requesttype_ = 0;
+ _has_bits_[0] &= ~0x00000008u;
+ }
+ inline ::cl_rcon::request_t request::_internal_requesttype() const
+ {
+ return static_cast<::cl_rcon::request_t>(requesttype_);
+ }
+ inline ::cl_rcon::request_t request::requesttype() const
+ {
+ // @@protoc_insertion_point(field_get:cl_rcon.request.requestType)
+ return _internal_requesttype();
+ }
+ inline void request::_internal_set_requesttype(::cl_rcon::request_t value)
+ {
+ _has_bits_[0] |= 0x00000008u;
+ requesttype_ = value;
+ }
+ inline void request::set_requesttype(::cl_rcon::request_t value)
+ {
+ _internal_set_requesttype(value);
+ // @@protoc_insertion_point(field_set:cl_rcon.request.requestType)
+ }
+
+ // optional string requestBuf = 3;
+ inline bool request::_internal_has_requestbuf() const
+ {
+ bool value = (_has_bits_[0] & 0x00000001u) != 0;
+ return value;
+ }
+ inline bool request::has_requestbuf() const
+ {
+ return _internal_has_requestbuf();
+ }
+ inline void request::clear_requestbuf()
+ {
+ requestbuf_.ClearToEmpty();
+ _has_bits_[0] &= ~0x00000001u;
+ }
+ inline const std::string& request::requestbuf() const
+ {
+ // @@protoc_insertion_point(field_get:cl_rcon.request.requestBuf)
+ return _internal_requestbuf();
+ }
+ template inline PROTOBUF_ALWAYS_INLINE void request::set_requestbuf(ArgT0&& arg0, ArgT... args)
+ {
+ _has_bits_[0] |= 0x00000001u;
+ requestbuf_.Set(
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault {},
+ static_cast(arg0),
+ args...,
+ GetArenaForAllocation());
+ // @@protoc_insertion_point(field_set:cl_rcon.request.requestBuf)
+ }
+ inline std::string* request::mutable_requestbuf()
+ {
+ std::string* _s = _internal_mutable_requestbuf();
+ // @@protoc_insertion_point(field_mutable:cl_rcon.request.requestBuf)
+ return _s;
+ }
+ inline const std::string& request::_internal_requestbuf() const
+ {
+ return requestbuf_.Get();
+ }
+ inline void request::_internal_set_requestbuf(const std::string& value)
+ {
+ _has_bits_[0] |= 0x00000001u;
+ requestbuf_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault {}, value, GetArenaForAllocation());
+ }
+ inline std::string* request::_internal_mutable_requestbuf()
+ {
+ _has_bits_[0] |= 0x00000001u;
+ return requestbuf_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault {}, GetArenaForAllocation());
+ }
+ inline std::string* request::release_requestbuf()
+ {
+ // @@protoc_insertion_point(field_release:cl_rcon.request.requestBuf)
+ if (!_internal_has_requestbuf())
+ {
+ return nullptr;
+ }
+ _has_bits_[0] &= ~0x00000001u;
+ auto* p = requestbuf_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (requestbuf_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()))
+ {
+ requestbuf_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ return p;
+ }
+ inline void request::set_allocated_requestbuf(std::string* requestbuf)
+ {
+ if (requestbuf != nullptr)
+ {
+ _has_bits_[0] |= 0x00000001u;
+ }
+ else
+ {
+ _has_bits_[0] &= ~0x00000001u;
+ }
+ requestbuf_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), requestbuf, GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (requestbuf_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()))
+ {
+ requestbuf_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ // @@protoc_insertion_point(field_set_allocated:cl_rcon.request.requestBuf)
+ }
+
+ // optional string requestVal = 4;
+ inline bool request::_internal_has_requestval() const
+ {
+ bool value = (_has_bits_[0] & 0x00000002u) != 0;
+ return value;
+ }
+ inline bool request::has_requestval() const
+ {
+ return _internal_has_requestval();
+ }
+ inline void request::clear_requestval()
+ {
+ requestval_.ClearToEmpty();
+ _has_bits_[0] &= ~0x00000002u;
+ }
+ inline const std::string& request::requestval() const
+ {
+ // @@protoc_insertion_point(field_get:cl_rcon.request.requestVal)
+ return _internal_requestval();
+ }
+ template inline PROTOBUF_ALWAYS_INLINE void request::set_requestval(ArgT0&& arg0, ArgT... args)
+ {
+ _has_bits_[0] |= 0x00000002u;
+ requestval_.Set(
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault {},
+ static_cast(arg0),
+ args...,
+ GetArenaForAllocation());
+ // @@protoc_insertion_point(field_set:cl_rcon.request.requestVal)
+ }
+ inline std::string* request::mutable_requestval()
+ {
+ std::string* _s = _internal_mutable_requestval();
+ // @@protoc_insertion_point(field_mutable:cl_rcon.request.requestVal)
+ return _s;
+ }
+ inline const std::string& request::_internal_requestval() const
+ {
+ return requestval_.Get();
+ }
+ inline void request::_internal_set_requestval(const std::string& value)
+ {
+ _has_bits_[0] |= 0x00000002u;
+ requestval_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault {}, value, GetArenaForAllocation());
+ }
+ inline std::string* request::_internal_mutable_requestval()
+ {
+ _has_bits_[0] |= 0x00000002u;
+ return requestval_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault {}, GetArenaForAllocation());
+ }
+ inline std::string* request::release_requestval()
+ {
+ // @@protoc_insertion_point(field_release:cl_rcon.request.requestVal)
+ if (!_internal_has_requestval())
+ {
+ return nullptr;
+ }
+ _has_bits_[0] &= ~0x00000002u;
+ auto* p = requestval_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (requestval_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()))
+ {
+ requestval_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ return p;
+ }
+ inline void request::set_allocated_requestval(std::string* requestval)
+ {
+ if (requestval != nullptr)
+ {
+ _has_bits_[0] |= 0x00000002u;
+ }
+ else
+ {
+ _has_bits_[0] &= ~0x00000002u;
+ }
+ requestval_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), requestval, GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (requestval_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()))
+ {
+ requestval_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ // @@protoc_insertion_point(field_set_allocated:cl_rcon.request.requestVal)
+ }
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif // __GNUC__
+
+ // @@protoc_insertion_point(namespace_scope)
+
+} // namespace cl_rcon
+
+PROTOBUF_NAMESPACE_OPEN
+
+template <> struct is_proto_enum<::cl_rcon::request_t> : ::std::true_type
+{
+};
+
+PROTOBUF_NAMESPACE_CLOSE
+
+// @@protoc_insertion_point(global_scope)
+
+#include
+#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_cl_5frcon_2eproto
diff --git a/NorthstarDedicatedTest/concommand.cpp b/NorthstarDedicatedTest/concommand.cpp
index 1bdda91bc..6ddc68815 100644
--- a/NorthstarDedicatedTest/concommand.cpp
+++ b/NorthstarDedicatedTest/concommand.cpp
@@ -38,7 +38,7 @@ bool ConCommand::IsCommand(void) const
//-----------------------------------------------------------------------------
bool ConCommandBase::IsCommand(void) const
{
- return true;
+ return m_pConCommandBaseVTable != g_pConVar_Vtable;
}
//-----------------------------------------------------------------------------
diff --git a/NorthstarDedicatedTest/convar.h b/NorthstarDedicatedTest/convar.h
index b1424fb7f..90e38e943 100644
--- a/NorthstarDedicatedTest/convar.h
+++ b/NorthstarDedicatedTest/convar.h
@@ -5,6 +5,7 @@
#include "concommand.h"
// taken directly from iconvar.h
+extern void* g_pConVar_Vtable;
// The default, no flags at all
#define FCVAR_NONE 0
diff --git a/NorthstarDedicatedTest/dedicated.cpp b/NorthstarDedicatedTest/dedicated.cpp
index 5099a6d23..199cf759f 100644
--- a/NorthstarDedicatedTest/dedicated.cpp
+++ b/NorthstarDedicatedTest/dedicated.cpp
@@ -4,6 +4,7 @@
#include "gameutils.h"
#include "serverauthentication.h"
#include "masterserver.h"
+#include "host_state.h"
bool IsDedicated()
{
diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp
index 3954991bc..7993da65f 100644
--- a/NorthstarDedicatedTest/dllmain.cpp
+++ b/NorthstarDedicatedTest/dllmain.cpp
@@ -39,14 +39,13 @@
#include "scriptservertoclientstringcommand.h"
#include "plugin_abi.h"
#include "plugins.h"
+#include "host_state.h"
+#include "rcon_shared.h"
#include "debugoverlay.h"
#include "clientvideooverrides.h"
#include "clientruihooks.h"
-#include
#include "version.h"
-#include "pch.h"
#include "scriptutility.h"
-
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
@@ -274,6 +273,9 @@ bool InitialiseNorthstar()
AddDllLoadCallback("server.dll", InitialiseServerSquirrelUtilityFunctions);
AddDllLoadCallback("server.dll", InitialiseServerSquirrelJson);
+ AddDllLoadCallback("engine.dll", InitializeCHostStateHooks);
+ AddDllLoadCallback("engine.dll", InitializeRconSystems);
+
AddDllLoadCallback("engine.dll", InitialisePlaylistHooks);
AddDllLoadCallback("filesystem_stdio.dll", InitialiseFilesystem);
diff --git a/NorthstarDedicatedTest/gameutils.cpp b/NorthstarDedicatedTest/gameutils.cpp
index 792d8bf2f..9c0878d10 100644
--- a/NorthstarDedicatedTest/gameutils.cpp
+++ b/NorthstarDedicatedTest/gameutils.cpp
@@ -1,5 +1,9 @@
#include "pch.h"
#include "convar.h"
+#include "concommand.h"
+#include "sv_rcon.h"
+#include "cl_rcon.h"
+#include "dedicated.h"
#include "gameutils.h"
// memory
@@ -12,9 +16,6 @@ Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer;
Cbuf_AddTextType Cbuf_AddText;
Cbuf_ExecuteType Cbuf_Execute;
-// hoststate stuff
-CHostState* g_pHostState;
-
// cengine stuff
CEngine* g_pEngine;
server_state_t* sv_m_State;
@@ -48,7 +49,6 @@ void InitialiseEngineGameUtilFunctions(HMODULE baseAddress)
Cbuf_AddText = (Cbuf_AddTextType)((char*)baseAddress + 0x1203B0);
Cbuf_Execute = (Cbuf_ExecuteType)((char*)baseAddress + 0x1204B0);
- g_pHostState = (CHostState*)((char*)baseAddress + 0x7CF180);
g_pEngine = *(CEngine**)((char*)baseAddress + 0x7D70C8);
sv_m_State = (server_state_t*)((char*)baseAddress + 0x12A53D48);
diff --git a/NorthstarDedicatedTest/gameutils.h b/NorthstarDedicatedTest/gameutils.h
index 6d625c160..692dbefbe 100644
--- a/NorthstarDedicatedTest/gameutils.h
+++ b/NorthstarDedicatedTest/gameutils.h
@@ -112,47 +112,6 @@ class CCommandLine
// virtual const char** GetParms() const {}
};
-// hoststate stuff
-enum HostState_t
-{
- HS_NEW_GAME = 0,
- HS_LOAD_GAME,
- HS_CHANGE_LEVEL_SP,
- HS_CHANGE_LEVEL_MP,
- HS_RUN,
- HS_GAME_SHUTDOWN,
- HS_SHUTDOWN,
- HS_RESTART,
-};
-
-struct CHostState
-{
- public:
- HostState_t m_iCurrentState;
- HostState_t m_iNextState;
-
- float m_vecLocation[3];
- float m_angLocation[3];
-
- char m_levelName[32];
- char m_mapGroupName[32];
- char m_landmarkName[32];
- char m_saveName[32];
- float m_flShortFrameTime; // run a few one-tick frames to avoid large timesteps while loading assets
-
- bool m_activeGame;
- bool m_bRememberLocation;
- bool m_bBackgroundLevel;
- bool m_bWaitingForConnection;
- bool m_bLetToolsOverrideLoadGameEnts; // During a load game, this tells Foundry to override ents that are selected in Hammer.
- bool m_bSplitScreenConnect;
- bool m_bGameHasShutDownAndFlushedMemory; // This is false once we load a map into memory, and set to true once the map is unloaded and
- // all memory flushed
- bool m_bWorkshopMapDownloadPending;
-};
-
-extern CHostState* g_pHostState;
-
// cengine stuff
enum EngineQuitState
{
diff --git a/NorthstarDedicatedTest/host_state.cpp b/NorthstarDedicatedTest/host_state.cpp
new file mode 100644
index 000000000..39fb931d5
--- /dev/null
+++ b/NorthstarDedicatedTest/host_state.cpp
@@ -0,0 +1,51 @@
+#include "pch.h"
+#include "gameutils.h"
+#include "host_state.h"
+#include "sv_rcon.h"
+#include "cl_rcon.h"
+#include "dedicated.h"
+
+typedef void (*CHostState_FrameUpdateType)(CHostState* thisptr);
+CHostState_FrameUpdateType CHostState__FrameUpdate;
+CHostState* g_pHostState;
+
+void CHostState__FrameUpdateHook(CHostState* thisptr)
+{
+ static bool bInitialized = false;
+
+ if (!bInitialized)
+ {
+ if (IsDedicated())
+ {
+ Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec rcon_server", cmd_source_t::kCommandSrcCode);
+ Cbuf_Execute();
+ RCONServer()->Init();
+ }
+ else
+ {
+ Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec rcon_client", cmd_source_t::kCommandSrcCode);
+ Cbuf_Execute();
+ RCONClient()->Init();
+ }
+ bInitialized = true;
+ }
+
+ if (IsDedicated())
+ {
+ RCONServer()->RunFrame();
+ }
+ else
+ {
+ RCONClient()->RunFrame();
+ }
+ CHostState__FrameUpdate(thisptr);
+}
+
+void InitializeCHostStateHooks(HMODULE baseAddress)
+{
+ g_pHostState = (CHostState*)((char*)baseAddress + 0x7CF180);
+
+ HookEnabler hook;
+ ENABLER_CREATEHOOK(
+ hook, (char*)baseAddress + 0x16DB00, &CHostState__FrameUpdateHook, reinterpret_cast(&CHostState__FrameUpdate));
+}
diff --git a/NorthstarDedicatedTest/host_state.h b/NorthstarDedicatedTest/host_state.h
new file mode 100644
index 000000000..1f3f60a62
--- /dev/null
+++ b/NorthstarDedicatedTest/host_state.h
@@ -0,0 +1,46 @@
+#pragma once
+#include "gameutils.h"
+
+// hoststate stuff
+enum HostState_t
+{
+ HS_NEW_GAME = 0,
+ HS_LOAD_GAME,
+ HS_CHANGE_LEVEL_SP,
+ HS_CHANGE_LEVEL_MP,
+ HS_RUN,
+ HS_GAME_SHUTDOWN,
+ HS_SHUTDOWN,
+ HS_RESTART,
+};
+
+struct CHostState
+{
+ public:
+ HostState_t m_iCurrentState;
+ HostState_t m_iNextState;
+
+ float m_vecLocation[3];
+ float m_angLocation[3];
+
+ char m_levelName[32];
+ char m_mapGroupName[32];
+ char m_landmarkName[32];
+ char m_saveName[32];
+ float m_flShortFrameTime; // run a few one-tick frames to avoid large timesteps while loading assets
+
+ bool m_activeGame;
+ bool m_bRememberLocation;
+ bool m_bBackgroundLevel;
+ bool m_bWaitingForConnection;
+ bool m_bLetToolsOverrideLoadGameEnts; // During a load game, this tells Foundry to override ents that are selected in Hammer.
+ bool m_bSplitScreenConnect;
+ bool m_bGameHasShutDownAndFlushedMemory; // This is false once we load a map into memory, and set to true once the map is unloaded and
+ // all memory flushed
+ bool m_bWorkshopMapDownloadPending;
+};
+
+extern CHostState* g_pHostState;
+
+void CHostState__FrameUpdateHook(CHostState* thisptr);
+void InitializeCHostStateHooks(HMODULE baseAddress);
diff --git a/NorthstarDedicatedTest/igameserverdata.h b/NorthstarDedicatedTest/igameserverdata.h
new file mode 100644
index 000000000..ca6b9a9ac
--- /dev/null
+++ b/NorthstarDedicatedTest/igameserverdata.h
@@ -0,0 +1,71 @@
+//===========================================================================//
+//
+// Purpose: Enumerations for writing out the requests.
+//
+//===========================================================================//
+#pragma once
+
+typedef int SocketHandle_t;
+
+enum class ServerDataRequestType_t : int
+{
+ SERVERDATA_REQUEST_VALUE = 0,
+ SERVERDATA_REQUEST_SETVALUE,
+ SERVERDATA_REQUEST_EXECCOMMAND,
+ SERVERDATA_REQUEST_AUTH,
+ SERVERDATA_REQUEST_SEND_CONSOLE_LOG,
+ SERVERDATA_REQUEST_SEND_REMOTEBUG,
+};
+
+enum class ServerDataResponseType_t : int
+{
+ SERVERDATA_RESPONSE_VALUE = 0,
+ SERVERDATA_RESPONSE_UPDATE,
+ SERVERDATA_RESPONSE_AUTH,
+ SERVERDATA_RESPONSE_CONSOLE_LOG,
+ SERVERDATA_RESPONSE_STRING,
+ SERVERDATA_RESPONSE_REMOTEBUG,
+};
+
+class CConnectedNetConsoleData
+{
+ public:
+ SocketHandle_t m_hSocket;
+ int m_nPayloadLen; // Num bytes for this message.
+ int m_nPayloadRead; // Num read bytes from input buffer.
+ int m_nFailedAttempts; // Num failed authentication attempts.
+ int m_nIgnoredMessage; // Count how many times client ignored the no-auth message.
+ bool m_bValidated; // Revalidates netconsole if false.
+ bool m_bAuthorized; // Set to true after successfull netconsole auth.
+ bool m_bInputOnly; // If set, don't send spew to this net console.
+ std::vector m_RecvBuffer;
+
+ CConnectedNetConsoleData(SocketHandle_t hSocket = -1)
+ {
+ m_hSocket = hSocket;
+ m_nPayloadLen = 0;
+ m_nPayloadRead = 0;
+ m_nFailedAttempts = 0;
+ m_nIgnoredMessage = 0;
+ m_bValidated = false;
+ m_bAuthorized = false;
+ m_bInputOnly = false;
+ m_RecvBuffer.resize(sizeof(int)); // Reserve enough for length-prefix.
+ }
+};
+
+/* PACKET FORMAT **********************************
+
+REQUEST:
+ int requestID;
+ int ServerDataRequestType_t;
+ NullTerminatedString (variable or command)
+ NullTerminatedString (value)
+
+RESPONSE:
+ int requestID;
+ int ServerDataResponseType_t;
+ NullTerminatedString (variable)
+ NullTerminatedString (value)
+
+***************************************************/
diff --git a/NorthstarDedicatedTest/include/protobuf/any.cc b/NorthstarDedicatedTest/include/protobuf/any.cc
new file mode 100644
index 000000000..a492d8b8e
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/any.cc
@@ -0,0 +1,83 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+bool AnyMetadata::PackFrom(Arena* arena, const Message& message) {
+ return PackFrom(arena, message, kTypeGoogleApisComPrefix);
+}
+
+bool AnyMetadata::PackFrom(Arena* arena, const Message& message,
+ StringPiece type_url_prefix) {
+ type_url_->Set(
+ &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString(),
+ GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix), arena);
+ return message.SerializeToString(
+ value_->Mutable(ArenaStringPtr::EmptyDefault{}, arena));
+}
+
+bool AnyMetadata::UnpackTo(Message* message) const {
+ if (!InternalIs(message->GetDescriptor()->full_name())) {
+ return false;
+ }
+ return message->ParseFromString(value_->Get());
+}
+
+bool GetAnyFieldDescriptors(const Message& message,
+ const FieldDescriptor** type_url_field,
+ const FieldDescriptor** value_field) {
+ const Descriptor* descriptor = message.GetDescriptor();
+ if (descriptor->full_name() != kAnyFullTypeName) {
+ return false;
+ }
+ *type_url_field = descriptor->FindFieldByNumber(1);
+ *value_field = descriptor->FindFieldByNumber(2);
+ return (*type_url_field != nullptr &&
+ (*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
+ *value_field != nullptr &&
+ (*value_field)->type() == FieldDescriptor::TYPE_BYTES);
+}
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+#include
diff --git a/NorthstarDedicatedTest/include/protobuf/any.h b/NorthstarDedicatedTest/include/protobuf/any.h
new file mode 100644
index 000000000..3745d2c86
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/any.h
@@ -0,0 +1,156 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_ANY_H__
+#define GOOGLE_PROTOBUF_ANY_H__
+
+#include
+
+#include
+#include
+#include
+
+#include
+
+namespace google {
+namespace protobuf {
+
+class FieldDescriptor;
+class Message;
+
+namespace internal {
+
+extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
+extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
+extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/".
+
+std::string GetTypeUrl(StringPiece message_name,
+ StringPiece type_url_prefix);
+
+// Helper class used to implement google::protobuf::Any.
+class PROTOBUF_EXPORT AnyMetadata {
+ typedef ArenaStringPtr UrlType;
+ typedef ArenaStringPtr ValueType;
+ public:
+ // AnyMetadata does not take ownership of "type_url" and "value".
+ constexpr AnyMetadata(UrlType* type_url, ValueType* value)
+ : type_url_(type_url), value_(value) {}
+
+ // Packs a message using the default type URL prefix: "type.googleapis.com".
+ // The resulted type URL will be "type.googleapis.com/".
+ // Returns false if serializing the message failed.
+ template
+ bool PackFrom(Arena* arena, const T& message) {
+ return InternalPackFrom(arena, message, kTypeGoogleApisComPrefix,
+ T::FullMessageName());
+ }
+
+ bool PackFrom(Arena* arena, const Message& message);
+
+ // Packs a message using the given type URL prefix. The type URL will be
+ // constructed by concatenating the message type's full name to the prefix
+ // with an optional "/" separator if the prefix doesn't already end with "/".
+ // For example, both PackFrom(message, "type.googleapis.com") and
+ // PackFrom(message, "type.googleapis.com/") yield the same result type
+ // URL: "type.googleapis.com/".
+ // Returns false if serializing the message failed.
+ template
+ bool PackFrom(Arena* arena, const T& message,
+ StringPiece type_url_prefix) {
+ return InternalPackFrom(arena, message, type_url_prefix,
+ T::FullMessageName());
+ }
+
+ bool PackFrom(Arena* arena, const Message& message,
+ StringPiece type_url_prefix);
+
+ // Unpacks the payload into the given message. Returns false if the message's
+ // type doesn't match the type specified in the type URL (i.e., the full
+ // name after the last "/" of the type URL doesn't match the message's actual
+ // full name) or parsing the payload has failed.
+ template
+ bool UnpackTo(T* message) const {
+ return InternalUnpackTo(T::FullMessageName(), message);
+ }
+
+ bool UnpackTo(Message* message) const;
+
+ // Checks whether the type specified in the type URL matches the given type.
+ // A type is considered matching if its full name matches the full name after
+ // the last "/" in the type URL.
+ template
+ bool Is() const {
+ return InternalIs(T::FullMessageName());
+ }
+
+ private:
+ bool InternalPackFrom(Arena* arena, const MessageLite& message,
+ StringPiece type_url_prefix,
+ StringPiece type_name);
+ bool InternalUnpackTo(StringPiece type_name,
+ MessageLite* message) const;
+ bool InternalIs(StringPiece type_name) const;
+
+ UrlType* type_url_;
+ ValueType* value_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata);
+};
+
+// Get the proto type name from Any::type_url value. For example, passing
+// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
+// *full_type_name. Returns false if the type_url does not have a "/"
+// in the type url separating the full type name.
+//
+// NOTE: this function is available publicly as:
+// google::protobuf::Any() // static method on the generated message type.
+bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name);
+
+// Get the proto type name and prefix from Any::type_url value. For example,
+// passing "type.googleapis.com/rpc.QueryOrigin" will return
+// "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in
+// *full_type_name. Returns false if the type_url does not have a "/" in the
+// type url separating the full type name.
+bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
+ std::string* full_type_name);
+
+// See if message is of type google.protobuf.Any, if so, return the descriptors
+// for "type_url" and "value" fields.
+bool GetAnyFieldDescriptors(const Message& message,
+ const FieldDescriptor** type_url_field,
+ const FieldDescriptor** value_field);
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+#include
+
+#endif // GOOGLE_PROTOBUF_ANY_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/any.pb.cc b/NorthstarDedicatedTest/include/protobuf/any.pb.cc
new file mode 100644
index 000000000..a1ec23911
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/any.pb.cc
@@ -0,0 +1,352 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/any.proto
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+// @@protoc_insertion_point(includes)
+#include
+
+PROTOBUF_PRAGMA_INIT_SEG
+PROTOBUF_NAMESPACE_OPEN
+constexpr Any::Any(
+ ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+ : type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+ , value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+ , _any_metadata_(&type_url_, &value_){}
+struct AnyDefaultTypeInternal {
+ constexpr AnyDefaultTypeInternal()
+ : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+ ~AnyDefaultTypeInternal() {}
+ union {
+ Any _instance;
+ };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT AnyDefaultTypeInternal _Any_default_instance_;
+PROTOBUF_NAMESPACE_CLOSE
+static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fany_2eproto[1];
+static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
+static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
+
+const uint32_t TableStruct_google_2fprotobuf_2fany_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+ ~0u, // no _has_bits_
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, _internal_metadata_),
+ ~0u, // no _extensions_
+ ~0u, // no _oneof_case_
+ ~0u, // no _weak_field_map_
+ ~0u, // no _inlined_string_donated_
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, type_url_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, value_),
+};
+static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+ { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Any)},
+};
+
+static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
+ reinterpret_cast(&::PROTOBUF_NAMESPACE_ID::_Any_default_instance_),
+};
+
+const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
+ "\n\031google/protobuf/any.proto\022\017google.prot"
+ "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
+ " \001(\014Bv\n\023com.google.protobufB\010AnyProtoP\001Z"
+ ",google.golang.org/protobuf/types/known/"
+ "anypb\242\002\003GPB\252\002\036Google.Protobuf.WellKnownT"
+ "ypesb\006proto3"
+ ;
+static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fany_2eproto_once;
+const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto = {
+ false, false, 212, descriptor_table_protodef_google_2fprotobuf_2fany_2eproto, "google/protobuf/any.proto",
+ &descriptor_table_google_2fprotobuf_2fany_2eproto_once, nullptr, 0, 1,
+ schemas, file_default_instances, TableStruct_google_2fprotobuf_2fany_2eproto::offsets,
+ file_level_metadata_google_2fprotobuf_2fany_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, file_level_service_descriptors_google_2fprotobuf_2fany_2eproto,
+};
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fany_2eproto_getter() {
+ return &descriptor_table_google_2fprotobuf_2fany_2eproto;
+}
+
+// Force running AddDescriptors() at dynamic initialization time.
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fany_2eproto(&descriptor_table_google_2fprotobuf_2fany_2eproto);
+PROTOBUF_NAMESPACE_OPEN
+
+// ===================================================================
+
+bool Any::GetAnyFieldDescriptors(
+ const ::PROTOBUF_NAMESPACE_ID::Message& message,
+ const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field,
+ const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field) {
+ return ::PROTOBUF_NAMESPACE_ID::internal::GetAnyFieldDescriptors(
+ message, type_url_field, value_field);
+}
+bool Any::ParseAnyTypeUrl(
+ ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,
+ std::string* full_type_name) {
+ return ::PROTOBUF_NAMESPACE_ID::internal::ParseAnyTypeUrl(type_url,
+ full_type_name);
+}
+
+class Any::_Internal {
+ public:
+};
+
+Any::Any(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+ bool is_message_owned)
+ : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
+ _any_metadata_(&type_url_, &value_) {
+ SharedCtor();
+ if (!is_message_owned) {
+ RegisterArenaDtor(arena);
+ }
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.Any)
+}
+Any::Any(const Any& from)
+ : ::PROTOBUF_NAMESPACE_ID::Message(),
+ _any_metadata_(&type_url_, &value_) {
+ _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+ type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (!from._internal_type_url().empty()) {
+ type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_type_url(),
+ GetArenaForAllocation());
+ }
+ value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (!from._internal_value().empty()) {
+ value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_value(),
+ GetArenaForAllocation());
+ }
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
+}
+
+inline void Any::SharedCtor() {
+type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+}
+
+Any::~Any() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Any)
+ if (GetArenaForAllocation() != nullptr) return;
+ SharedDtor();
+ _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+inline void Any::SharedDtor() {
+ GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
+ type_url_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+}
+
+void Any::ArenaDtor(void* object) {
+ Any* _this = reinterpret_cast< Any* >(object);
+ (void)_this;
+}
+void Any::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+}
+void Any::SetCachedSize(int size) const {
+ _cached_size_.Set(size);
+}
+
+void Any::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
+ uint32_t cached_has_bits = 0;
+ // Prevent compiler warnings about cached_has_bits being unused
+ (void) cached_has_bits;
+
+ type_url_.ClearToEmpty();
+ value_.ClearToEmpty();
+ _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* Any::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+ while (!ctx->Done(&ptr)) {
+ uint32_t tag;
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+ switch (tag >> 3) {
+ // string type_url = 1;
+ case 1:
+ if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 10)) {
+ auto str = _internal_mutable_type_url();
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
+ CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.Any.type_url"));
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ // bytes value = 2;
+ case 2:
+ if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 18)) {
+ auto str = _internal_mutable_value();
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ default:
+ goto handle_unusual;
+ } // switch
+ handle_unusual:
+ if ((tag == 0) || ((tag & 7) == 4)) {
+ CHK_(ptr);
+ ctx->SetLastTag(tag);
+ goto message_done;
+ }
+ ptr = UnknownFieldParse(
+ tag,
+ _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+ ptr, ctx);
+ CHK_(ptr != nullptr);
+ } // while
+message_done:
+ return ptr;
+failure:
+ ptr = nullptr;
+ goto message_done;
+#undef CHK_
+}
+
+uint8_t* Any::_InternalSerialize(
+ uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
+ uint32_t cached_has_bits = 0;
+ (void) cached_has_bits;
+
+ // string type_url = 1;
+ if (!this->_internal_type_url().empty()) {
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
+ this->_internal_type_url().data(), static_cast(this->_internal_type_url().length()),
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
+ "google.protobuf.Any.type_url");
+ target = stream->WriteStringMaybeAliased(
+ 1, this->_internal_type_url(), target);
+ }
+
+ // bytes value = 2;
+ if (!this->_internal_value().empty()) {
+ target = stream->WriteBytesMaybeAliased(
+ 2, this->_internal_value(), target);
+ }
+
+ if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
+ _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+ }
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any)
+ return target;
+}
+
+size_t Any::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any)
+ size_t total_size = 0;
+
+ uint32_t cached_has_bits = 0;
+ // Prevent compiler warnings about cached_has_bits being unused
+ (void) cached_has_bits;
+
+ // string type_url = 1;
+ if (!this->_internal_type_url().empty()) {
+ total_size += 1 +
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+ this->_internal_type_url());
+ }
+
+ // bytes value = 2;
+ if (!this->_internal_value().empty()) {
+ total_size += 1 +
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize(
+ this->_internal_value());
+ }
+
+ return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);
+}
+
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Any::_class_data_ = {
+ ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+ Any::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Any::GetClassData() const { return &_class_data_; }
+
+void Any::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to,
+ const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+ static_cast(to)->MergeFrom(
+ static_cast(from));
+}
+
+
+void Any::MergeFrom(const Any& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any)
+ GOOGLE_DCHECK_NE(&from, this);
+ uint32_t cached_has_bits = 0;
+ (void) cached_has_bits;
+
+ if (!from._internal_type_url().empty()) {
+ _internal_set_type_url(from._internal_type_url());
+ }
+ if (!from._internal_value().empty()) {
+ _internal_set_value(from._internal_value());
+ }
+ _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+}
+
+void Any::CopyFrom(const Any& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Any)
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Any::IsInitialized() const {
+ return true;
+}
+
+void Any::InternalSwap(Any* other) {
+ using std::swap;
+ auto* lhs_arena = GetArenaForAllocation();
+ auto* rhs_arena = other->GetArenaForAllocation();
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+ &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+ &type_url_, lhs_arena,
+ &other->type_url_, rhs_arena
+ );
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+ &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+ &value_, lhs_arena,
+ &other->value_, rhs_arena
+ );
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata Any::GetMetadata() const {
+ return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+ &descriptor_table_google_2fprotobuf_2fany_2eproto_getter, &descriptor_table_google_2fprotobuf_2fany_2eproto_once,
+ file_level_metadata_google_2fprotobuf_2fany_2eproto[0]);
+}
+
+// @@protoc_insertion_point(namespace_scope)
+PROTOBUF_NAMESPACE_CLOSE
+PROTOBUF_NAMESPACE_OPEN
+template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Any >(Arena* arena) {
+ return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Any >(arena);
+}
+PROTOBUF_NAMESPACE_CLOSE
+
+// @@protoc_insertion_point(global_scope)
+#include
diff --git a/NorthstarDedicatedTest/include/protobuf/any.pb.h b/NorthstarDedicatedTest/include/protobuf/any.pb.h
new file mode 100644
index 000000000..47513dbae
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/any.pb.h
@@ -0,0 +1,391 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/any.proto
+
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
+
+#include
+#include
+
+#include
+#if PROTOBUF_VERSION < 3019000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3019004 < PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include // IWYU pragma: export
+#include // IWYU pragma: export
+#include
+// @@protoc_insertion_point(includes)
+#include
+#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fany_2eproto PROTOBUF_EXPORT
+PROTOBUF_NAMESPACE_OPEN
+namespace internal {
+class AnyMetadata;
+} // namespace internal
+PROTOBUF_NAMESPACE_CLOSE
+
+// Internal implementation detail -- do not use these members.
+struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fany_2eproto {
+ static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
+ PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+ static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
+ PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+ static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1]
+ PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+ static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[];
+ static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
+ static const uint32_t offsets[];
+};
+PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto;
+PROTOBUF_NAMESPACE_OPEN
+class Any;
+struct AnyDefaultTypeInternal;
+PROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
+PROTOBUF_NAMESPACE_CLOSE
+PROTOBUF_NAMESPACE_OPEN
+template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Any>(Arena*);
+PROTOBUF_NAMESPACE_CLOSE
+PROTOBUF_NAMESPACE_OPEN
+
+// ===================================================================
+
+class PROTOBUF_EXPORT Any final :
+ public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ {
+ public:
+ inline Any() : Any(nullptr) {}
+ ~Any() override;
+ explicit constexpr Any(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+ Any(const Any& from);
+ Any(Any&& from) noexcept
+ : Any() {
+ *this = ::std::move(from);
+ }
+
+ inline Any& operator=(const Any& from) {
+ CopyFrom(from);
+ return *this;
+ }
+ inline Any& operator=(Any&& from) noexcept {
+ if (this == &from) return *this;
+ if (GetOwningArena() == from.GetOwningArena()
+ #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
+ && GetOwningArena() != nullptr
+ #endif // !PROTOBUF_FORCE_COPY_IN_MOVE
+ ) {
+ InternalSwap(&from);
+ } else {
+ CopyFrom(from);
+ }
+ return *this;
+ }
+
+ static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+ return GetDescriptor();
+ }
+ static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+ return default_instance().GetMetadata().descriptor;
+ }
+ static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+ return default_instance().GetMetadata().reflection;
+ }
+ static const Any& default_instance() {
+ return *internal_default_instance();
+ }
+ static inline const Any* internal_default_instance() {
+ return reinterpret_cast(
+ &_Any_default_instance_);
+ }
+ static constexpr int kIndexInFileMessages =
+ 0;
+
+ // implements Any -----------------------------------------------
+
+ bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message) {
+ return _any_metadata_.PackFrom(GetArena(), message);
+ }
+ bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message,
+ ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
+ return _any_metadata_.PackFrom(GetArena(), message, type_url_prefix);
+ }
+ bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const {
+ return _any_metadata_.UnpackTo(message);
+ }
+ static bool GetAnyFieldDescriptors(
+ const ::PROTOBUF_NAMESPACE_ID::Message& message,
+ const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field,
+ const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field);
+ template ::value>::type>
+ bool PackFrom(const T& message) {
+ return _any_metadata_.PackFrom(GetArena(), message);
+ }
+ template ::value>::type>
+ bool PackFrom(const T& message,
+ ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
+ return _any_metadata_.PackFrom(GetArena(), message, type_url_prefix);}
+ template ::value>::type>
+ bool UnpackTo(T* message) const {
+ return _any_metadata_.UnpackTo(message);
+ }
+ template bool Is() const {
+ return _any_metadata_.Is();
+ }
+ static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,
+ std::string* full_type_name);
+ friend void swap(Any& a, Any& b) {
+ a.Swap(&b);
+ }
+ inline void Swap(Any* other) {
+ if (other == this) return;
+ #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+ if (GetOwningArena() != nullptr &&
+ GetOwningArena() == other->GetOwningArena()) {
+ #else // PROTOBUF_FORCE_COPY_IN_SWAP
+ if (GetOwningArena() == other->GetOwningArena()) {
+ #endif // !PROTOBUF_FORCE_COPY_IN_SWAP
+ InternalSwap(other);
+ } else {
+ ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+ }
+ }
+ void UnsafeArenaSwap(Any* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
+ InternalSwap(other);
+ }
+
+ // implements Message ----------------------------------------------
+
+ Any* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
+ return CreateMaybeMessage(arena);
+ }
+ using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
+ void CopyFrom(const Any& from);
+ using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
+ void MergeFrom(const Any& from);
+ private:
+ static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from);
+ public:
+ PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+ bool IsInitialized() const final;
+
+ size_t ByteSizeLong() const final;
+ const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+ uint8_t* _InternalSerialize(
+ uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+ int GetCachedSize() const final { return _cached_size_.Get(); }
+
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const final;
+ void InternalSwap(Any* other);
+
+ private:
+ friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+ static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+ return "google.protobuf.Any";
+ }
+ protected:
+ explicit Any(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+ bool is_message_owned = false);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+ public:
+
+ static const ClassData _class_data_;
+ const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
+
+ ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ enum : int {
+ kTypeUrlFieldNumber = 1,
+ kValueFieldNumber = 2,
+ };
+ // string type_url = 1;
+ void clear_type_url();
+ const std::string& type_url() const;
+ template
+ void set_type_url(ArgT0&& arg0, ArgT... args);
+ std::string* mutable_type_url();
+ PROTOBUF_NODISCARD std::string* release_type_url();
+ void set_allocated_type_url(std::string* type_url);
+ private:
+ const std::string& _internal_type_url() const;
+ inline PROTOBUF_ALWAYS_INLINE void _internal_set_type_url(const std::string& value);
+ std::string* _internal_mutable_type_url();
+ public:
+
+ // bytes value = 2;
+ void clear_value();
+ const std::string& value() const;
+ template
+ void set_value(ArgT0&& arg0, ArgT... args);
+ std::string* mutable_value();
+ PROTOBUF_NODISCARD std::string* release_value();
+ void set_allocated_value(std::string* value);
+ private:
+ const std::string& _internal_value() const;
+ inline PROTOBUF_ALWAYS_INLINE void _internal_set_value(const std::string& value);
+ std::string* _internal_mutable_value();
+ public:
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Any)
+ private:
+ class _Internal;
+
+ template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr type_url_;
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr value_;
+ mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+ ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata _any_metadata_;
+ friend struct ::TableStruct_google_2fprotobuf_2fany_2eproto;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif // __GNUC__
+// Any
+
+// string type_url = 1;
+inline void Any::clear_type_url() {
+ type_url_.ClearToEmpty();
+}
+inline const std::string& Any::type_url() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
+ return _internal_type_url();
+}
+template
+inline PROTOBUF_ALWAYS_INLINE
+void Any::set_type_url(ArgT0&& arg0, ArgT... args) {
+
+ type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast(arg0), args..., GetArenaForAllocation());
+ // @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
+}
+inline std::string* Any::mutable_type_url() {
+ std::string* _s = _internal_mutable_type_url();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
+ return _s;
+}
+inline const std::string& Any::_internal_type_url() const {
+ return type_url_.Get();
+}
+inline void Any::_internal_set_type_url(const std::string& value) {
+
+ type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
+}
+inline std::string* Any::_internal_mutable_type_url() {
+
+ return type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
+}
+inline std::string* Any::release_type_url() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
+ return type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
+}
+inline void Any::set_allocated_type_url(std::string* type_url) {
+ if (type_url != nullptr) {
+
+ } else {
+
+ }
+ type_url_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), type_url,
+ GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (type_url_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
+}
+
+// bytes value = 2;
+inline void Any::clear_value() {
+ value_.ClearToEmpty();
+}
+inline const std::string& Any::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Any.value)
+ return _internal_value();
+}
+template
+inline PROTOBUF_ALWAYS_INLINE
+void Any::set_value(ArgT0&& arg0, ArgT... args) {
+
+ value_.SetBytes(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast(arg0), args..., GetArenaForAllocation());
+ // @@protoc_insertion_point(field_set:google.protobuf.Any.value)
+}
+inline std::string* Any::mutable_value() {
+ std::string* _s = _internal_mutable_value();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
+ return _s;
+}
+inline const std::string& Any::_internal_value() const {
+ return value_.Get();
+}
+inline void Any::_internal_set_value(const std::string& value) {
+
+ value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
+}
+inline std::string* Any::_internal_mutable_value() {
+
+ return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
+}
+inline std::string* Any::release_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Any.value)
+ return value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
+}
+inline void Any::set_allocated_value(std::string* value) {
+ if (value != nullptr) {
+
+ } else {
+
+ }
+ value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value,
+ GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (value_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
+}
+
+#ifdef __GNUC__
+ #pragma GCC diagnostic pop
+#endif // __GNUC__
+
+// @@protoc_insertion_point(namespace_scope)
+
+PROTOBUF_NAMESPACE_CLOSE
+
+// @@protoc_insertion_point(global_scope)
+
+#include
+#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
diff --git a/NorthstarDedicatedTest/include/protobuf/any.proto b/NorthstarDedicatedTest/include/protobuf/any.proto
new file mode 100644
index 000000000..6ed8a23cf
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/any.proto
@@ -0,0 +1,158 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "google.golang.org/protobuf/types/known/anypb";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "AnyProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+// `Any` contains an arbitrary serialized protocol buffer message along with a
+// URL that describes the type of the serialized message.
+//
+// Protobuf library provides support to pack/unpack Any values in the form
+// of utility functions or additional generated methods of the Any type.
+//
+// Example 1: Pack and unpack a message in C++.
+//
+// Foo foo = ...;
+// Any any;
+// any.PackFrom(foo);
+// ...
+// if (any.UnpackTo(&foo)) {
+// ...
+// }
+//
+// Example 2: Pack and unpack a message in Java.
+//
+// Foo foo = ...;
+// Any any = Any.pack(foo);
+// ...
+// if (any.is(Foo.class)) {
+// foo = any.unpack(Foo.class);
+// }
+//
+// Example 3: Pack and unpack a message in Python.
+//
+// foo = Foo(...)
+// any = Any()
+// any.Pack(foo)
+// ...
+// if any.Is(Foo.DESCRIPTOR):
+// any.Unpack(foo)
+// ...
+//
+// Example 4: Pack and unpack a message in Go
+//
+// foo := &pb.Foo{...}
+// any, err := anypb.New(foo)
+// if err != nil {
+// ...
+// }
+// ...
+// foo := &pb.Foo{}
+// if err := any.UnmarshalTo(foo); err != nil {
+// ...
+// }
+//
+// The pack methods provided by protobuf library will by default use
+// 'type.googleapis.com/full.type.name' as the type URL and the unpack
+// methods only use the fully qualified type name after the last '/'
+// in the type URL, for example "foo.bar.com/x/y.z" will yield type
+// name "y.z".
+//
+//
+// JSON
+// ====
+// The JSON representation of an `Any` value uses the regular
+// representation of the deserialized, embedded message, with an
+// additional field `@type` which contains the type URL. Example:
+//
+// package google.profile;
+// message Person {
+// string first_name = 1;
+// string last_name = 2;
+// }
+//
+// {
+// "@type": "type.googleapis.com/google.profile.Person",
+// "firstName": ,
+// "lastName":
+// }
+//
+// If the embedded message type is well-known and has a custom JSON
+// representation, that representation will be embedded adding a field
+// `value` which holds the custom JSON in addition to the `@type`
+// field. Example (for message [google.protobuf.Duration][]):
+//
+// {
+// "@type": "type.googleapis.com/google.protobuf.Duration",
+// "value": "1.212s"
+// }
+//
+message Any {
+ // A URL/resource name that uniquely identifies the type of the serialized
+ // protocol buffer message. This string must contain at least
+ // one "/" character. The last segment of the URL's path must represent
+ // the fully qualified name of the type (as in
+ // `path/google.protobuf.Duration`). The name should be in a canonical form
+ // (e.g., leading "." is not accepted).
+ //
+ // In practice, teams usually precompile into the binary all types that they
+ // expect it to use in the context of Any. However, for URLs which use the
+ // scheme `http`, `https`, or no scheme, one can optionally set up a type
+ // server that maps type URLs to message definitions as follows:
+ //
+ // * If no scheme is provided, `https` is assumed.
+ // * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+ // value in binary format, or produce an error.
+ // * Applications are allowed to cache lookup results based on the
+ // URL, or have them precompiled into a binary to avoid any
+ // lookup. Therefore, binary compatibility needs to be preserved
+ // on changes to types. (Use versioned type names to manage
+ // breaking changes.)
+ //
+ // Note: this functionality is not currently available in the official
+ // protobuf release, and it is not used for type URLs beginning with
+ // type.googleapis.com.
+ //
+ // Schemes other than `http`, `https` (or the empty scheme) might be
+ // used with implementation specific semantics.
+ //
+ string type_url = 1;
+
+ // Must be a valid serialized protocol buffer of the above specified type.
+ bytes value = 2;
+}
diff --git a/NorthstarDedicatedTest/include/protobuf/any_lite.cc b/NorthstarDedicatedTest/include/protobuf/any_lite.cc
new file mode 100644
index 000000000..9ac548622
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/any_lite.cc
@@ -0,0 +1,99 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include
+
+#include
+#include
+#include
+#include
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+std::string GetTypeUrl(StringPiece message_name,
+ StringPiece type_url_prefix) {
+ if (!type_url_prefix.empty() &&
+ type_url_prefix[type_url_prefix.size() - 1] == '/') {
+ return StrCat(type_url_prefix, message_name);
+ } else {
+ return StrCat(type_url_prefix, "/", message_name);
+ }
+}
+
+const char kAnyFullTypeName[] = "google.protobuf.Any";
+const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
+const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
+
+bool AnyMetadata::InternalPackFrom(Arena* arena, const MessageLite& message,
+ StringPiece type_url_prefix,
+ StringPiece type_name) {
+ type_url_->Set(&::google::protobuf::internal::GetEmptyString(),
+ GetTypeUrl(type_name, type_url_prefix), arena);
+ return message.SerializeToString(
+ value_->Mutable(ArenaStringPtr::EmptyDefault{}, arena));
+}
+
+bool AnyMetadata::InternalUnpackTo(StringPiece type_name,
+ MessageLite* message) const {
+ if (!InternalIs(type_name)) {
+ return false;
+ }
+ return message->ParseFromString(value_->Get());
+}
+
+bool AnyMetadata::InternalIs(StringPiece type_name) const {
+ StringPiece type_url = type_url_->Get();
+ return type_url.size() >= type_name.size() + 1 &&
+ type_url[type_url.size() - type_name.size() - 1] == '/' &&
+ HasSuffixString(type_url, type_name);
+}
+
+bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
+ std::string* full_type_name) {
+ size_t pos = type_url.find_last_of('/');
+ if (pos == std::string::npos || pos + 1 == type_url.size()) {
+ return false;
+ }
+ if (url_prefix) {
+ *url_prefix = std::string(type_url.substr(0, pos + 1));
+ }
+ *full_type_name = std::string(type_url.substr(pos + 1));
+ return true;
+}
+
+bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name) {
+ return ParseAnyTypeUrl(type_url, nullptr, full_type_name);
+}
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/any_test.cc b/NorthstarDedicatedTest/include/protobuf/any_test.cc
new file mode 100644
index 000000000..27cca96b2
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/any_test.cc
@@ -0,0 +1,184 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include
+#include
+#include
+
+
+// Must be included last.
+#include
+
+namespace google {
+namespace protobuf {
+namespace {
+
+TEST(AnyMetadataTest, ConstInit) {
+ PROTOBUF_CONSTINIT static internal::AnyMetadata metadata(nullptr, nullptr);
+ (void)metadata;
+}
+
+TEST(AnyTest, TestPackAndUnpack) {
+ protobuf_unittest::TestAny submessage;
+ submessage.set_int32_value(12345);
+ protobuf_unittest::TestAny message;
+ ASSERT_TRUE(message.mutable_any_value()->PackFrom(submessage));
+
+ std::string data = message.SerializeAsString();
+
+ ASSERT_TRUE(message.ParseFromString(data));
+ EXPECT_TRUE(message.has_any_value());
+ submessage.Clear();
+ ASSERT_TRUE(message.any_value().UnpackTo(&submessage));
+ EXPECT_EQ(12345, submessage.int32_value());
+}
+
+TEST(AnyTest, TestPackFromSerializationExceedsSizeLimit) {
+ protobuf_unittest::TestAny submessage;
+ submessage.mutable_text()->resize(INT_MAX, 'a');
+ protobuf_unittest::TestAny message;
+ EXPECT_FALSE(message.mutable_any_value()->PackFrom(submessage));
+}
+
+TEST(AnyTest, TestUnpackWithTypeMismatch) {
+ protobuf_unittest::TestAny payload;
+ payload.set_int32_value(13);
+ google::protobuf::Any any;
+ any.PackFrom(payload);
+
+ // Attempt to unpack into the wrong type.
+ protobuf_unittest::TestAllTypes dest;
+ EXPECT_FALSE(any.UnpackTo(&dest));
+}
+
+TEST(AnyTest, TestPackAndUnpackAny) {
+ // We can pack a Any message inside another Any message.
+ protobuf_unittest::TestAny submessage;
+ submessage.set_int32_value(12345);
+ google::protobuf::Any any;
+ any.PackFrom(submessage);
+ protobuf_unittest::TestAny message;
+ message.mutable_any_value()->PackFrom(any);
+
+ std::string data = message.SerializeAsString();
+
+ ASSERT_TRUE(message.ParseFromString(data));
+ EXPECT_TRUE(message.has_any_value());
+ any.Clear();
+ submessage.Clear();
+ ASSERT_TRUE(message.any_value().UnpackTo(&any));
+ ASSERT_TRUE(any.UnpackTo(&submessage));
+ EXPECT_EQ(12345, submessage.int32_value());
+}
+
+TEST(AnyTest, TestPackWithCustomTypeUrl) {
+ protobuf_unittest::TestAny submessage;
+ submessage.set_int32_value(12345);
+ google::protobuf::Any any;
+ // Pack with a custom type URL prefix.
+ any.PackFrom(submessage, "type.myservice.com");
+ EXPECT_EQ("type.myservice.com/protobuf_unittest.TestAny", any.type_url());
+ // Pack with a custom type URL prefix ending with '/'.
+ any.PackFrom(submessage, "type.myservice.com/");
+ EXPECT_EQ("type.myservice.com/protobuf_unittest.TestAny", any.type_url());
+ // Pack with an empty type URL prefix.
+ any.PackFrom(submessage, "");
+ EXPECT_EQ("/protobuf_unittest.TestAny", any.type_url());
+
+ // Test unpacking the type.
+ submessage.Clear();
+ EXPECT_TRUE(any.UnpackTo(&submessage));
+ EXPECT_EQ(12345, submessage.int32_value());
+}
+
+TEST(AnyTest, TestIs) {
+ protobuf_unittest::TestAny submessage;
+ submessage.set_int32_value(12345);
+ google::protobuf::Any any;
+ any.PackFrom(submessage);
+ ASSERT_TRUE(any.ParseFromString(any.SerializeAsString()));
+ EXPECT_TRUE(any.Is());
+ EXPECT_FALSE(any.Is());
+
+ protobuf_unittest::TestAny message;
+ message.mutable_any_value()->PackFrom(any);
+ ASSERT_TRUE(message.ParseFromString(message.SerializeAsString()));
+ EXPECT_FALSE(message.any_value().Is());
+ EXPECT_TRUE(message.any_value().Is());
+
+ any.set_type_url("/protobuf_unittest.TestAny");
+ EXPECT_TRUE(any.Is());
+ // The type URL must contain at least one "/".
+ any.set_type_url("protobuf_unittest.TestAny");
+ EXPECT_FALSE(any.Is());
+ // The type name after the slash must be fully qualified.
+ any.set_type_url("/TestAny");
+ EXPECT_FALSE(any.Is());
+}
+
+TEST(AnyTest, MoveConstructor) {
+ protobuf_unittest::TestAny payload;
+ payload.set_int32_value(12345);
+
+ google::protobuf::Any src;
+ src.PackFrom(payload);
+
+ const char* type_url = src.type_url().data();
+
+ google::protobuf::Any dst(std::move(src));
+ EXPECT_EQ(type_url, dst.type_url().data());
+ payload.Clear();
+ ASSERT_TRUE(dst.UnpackTo(&payload));
+ EXPECT_EQ(12345, payload.int32_value());
+}
+
+TEST(AnyTest, MoveAssignment) {
+ protobuf_unittest::TestAny payload;
+ payload.set_int32_value(12345);
+
+ google::protobuf::Any src;
+ src.PackFrom(payload);
+
+ const char* type_url = src.type_url().data();
+
+ google::protobuf::Any dst;
+ dst = std::move(src);
+ EXPECT_EQ(type_url, dst.type_url().data());
+ payload.Clear();
+ ASSERT_TRUE(dst.UnpackTo(&payload));
+ EXPECT_EQ(12345, payload.int32_value());
+}
+
+
+} // namespace
+} // namespace protobuf
+} // namespace google
+
+#include
diff --git a/NorthstarDedicatedTest/include/protobuf/any_test.proto b/NorthstarDedicatedTest/include/protobuf/any_test.proto
new file mode 100644
index 000000000..256035b44
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/any_test.proto
@@ -0,0 +1,44 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package protobuf_unittest;
+
+import "google/protobuf/any.proto";
+
+option java_outer_classname = "TestAnyProto";
+
+message TestAny {
+ int32 int32_value = 1;
+ google.protobuf.Any any_value = 2;
+ repeated google.protobuf.Any repeated_any_value = 3;
+ string text = 4;
+}
diff --git a/NorthstarDedicatedTest/include/protobuf/api.pb.cc b/NorthstarDedicatedTest/include/protobuf/api.pb.cc
new file mode 100644
index 000000000..a485aa1b5
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/api.pb.cc
@@ -0,0 +1,1291 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/api.proto
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include