From c8ec95bd37ed0c3e16090ed0a15808bda6a2ee99 Mon Sep 17 00:00:00 2001 From: Alex <18037145+salcodes1@users.noreply.github.com> Date: Tue, 28 Dec 2021 03:26:44 +0200 Subject: [PATCH 1/6] Added backbone and some of the routes for r5net-ms (now Pylon) interactions --- r5dev/gameui/IBrowser.cpp | 715 ---------------------------- r5dev/gameui/IBrowser.h | 173 ------- r5dev/networksystem/net_structs.h | 93 ++++ r5dev/networksystem/r5net.cpp | 325 +------------ r5dev/networksystem/r5net.h | 57 ++- r5dev/networksystem/serverlisting.h | 14 - r5dev/r5dev.vcxproj | 4 +- r5dev/r5dev.vcxproj.filters | 12 +- r5dev/server/server.h | 1 - r5dev/windows/id3dx.cpp | 6 - 10 files changed, 141 insertions(+), 1259 deletions(-) delete mode 100644 r5dev/gameui/IBrowser.cpp delete mode 100644 r5dev/gameui/IBrowser.h create mode 100644 r5dev/networksystem/net_structs.h delete mode 100644 r5dev/networksystem/serverlisting.h diff --git a/r5dev/gameui/IBrowser.cpp b/r5dev/gameui/IBrowser.cpp deleted file mode 100644 index b2d61c53..00000000 --- a/r5dev/gameui/IBrowser.cpp +++ /dev/null @@ -1,715 +0,0 @@ -#include "core/stdafx.h" -#include "core/init.h" -#include "core/resource.h" -#include "tier0/IConVar.h" -#include "tier0/cvar.h" -#include "tier0/completion.h" -#include "windows/id3dx.h" -#include "windows/console.h" -#include "engine/net_chan.h" -#include "engine/sys_utils.h" -#include "engine/host_state.h" -#include "server/server.h" -#include "client/IVEngineClient.h" -#include "networksystem/serverlisting.h" -#include "networksystem/r5net.h" -#include "vpc/keyvalues.h" -#include "squirrel/sqinit.h" -#include "gameui/IBrowser.h" - -/****************************************************************************** -------------------------------------------------------------------------------- -File : IBrowser.cpp -Date : 09:06:2021 -Author : Sal -Purpose: Implements the in-game server browser frontend -------------------------------------------------------------------------------- -History: -- 09:06:2021 21:07 : Created by Sal -- 25:07:2021 14:26 : Implement private servers connect dialog and password field - -******************************************************************************/ - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -IBrowser::IBrowser() -{ - memset(m_chServerConnStringBuffer, 0, sizeof(m_chServerConnStringBuffer)); - - std::string path = "stbsp"; - for (const auto& entry : std::filesystem::directory_iterator(path)) - { - std::string filename = entry.path().string(); - int slashPos = filename.rfind("\\", std::string::npos); - filename = filename.substr(static_cast, std::allocator>::size_type>(slashPos) + 1, std::string::npos); - filename = filename.substr(0, filename.size() - 6); - - auto it = mapArray.find(filename); // Find MapName in mapArray. - if (it != mapArray.end()) - { - m_vszMapsList.push_back(it->second); - } - else - { - m_vszMapsList.push_back(filename); - } - } - - m_szMatchmakingHostName = r5net_matchmaking_hostname->m_pzsCurrentValue; - static std::thread hostingServerRequestThread([this]() - { - while (true) - { - UpdateHostingStatus(); - std::this_thread::sleep_for(std::chrono::milliseconds(5000)); - } - }); - - hostingServerRequestThread.detach(); - - /* Obtain handle to module */ - static HGLOBAL rcData = NULL; - HMODULE handle; - GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)"unnamed", &handle); - HRSRC rc = FindResource(handle, MAKEINTRESOURCE(IDB_PNG1), MAKEINTRESOURCE(PNG)); - /* Obtain assets from 'rsrc' */ - if (rc != NULL) - { rcData = LoadResource(handle, rc); } - else { assert(rc == NULL); } - if (rcData != NULL) { m_vucLockedIconBlob = (std::vector*)LockResource(rcData); } - else { assert(rcData == NULL); } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -IBrowser::~IBrowser() -{ - //delete r5net; -} - -//----------------------------------------------------------------------------- -// Purpose: updates the hoster's status -//----------------------------------------------------------------------------- -void IBrowser::UpdateHostingStatus() -{ - if (!g_pHostState || !g_pCvar) - { - return; - } - - eHostingStatus = g_pHostState->m_bActiveGame ? EHostStatus::HOSTING : EHostStatus::NOT_HOSTING; // Are we hosting a server? - switch (eHostingStatus) - { - case EHostStatus::NOT_HOSTING: - { - m_szHostRequestMessage.clear(); - m_iv4HostRequestMessageColor = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - break; - } - case EHostStatus::HOSTING: - { - if (eServerVisibility == EServerVisibility::OFFLINE) - { - break; - } - - if (*g_nRemoteFunctionCallsChecksum == NULL) // Check if script checksum is valid yet. - { - break; - } - - switch (eServerVisibility) - { - - case EServerVisibility::HIDDEN: - m_Server.bHidden = true; - break; - case EServerVisibility::PUBLIC: - m_Server.bHidden = false; - break; - default: - break; - } - - SendHostingPostRequest(); - break; - } - default: - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: refreshes the server browser list with available servers -//----------------------------------------------------------------------------- -void IBrowser::RefreshServerList() -{ - static bool bThreadLocked = false; - - m_vServerList.clear(); - m_szServerListMessage.clear(); - - if (!bThreadLocked) - { - std::thread t([this]() - { - DevMsg(eDLL_T::CLIENT, "Refreshing server list with string '%s'\n", r5net_matchmaking_hostname->m_pzsCurrentValue); - bThreadLocked = true; - m_vServerList = g_pR5net->GetServersList(m_szServerListMessage); - bThreadLocked = false; - }); - - t.detach(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: sends the hosting POST request to the comp server -//----------------------------------------------------------------------------- -void IBrowser::SendHostingPostRequest() -{ - m_szHostToken = std::string(); - DevMsg(eDLL_T::CLIENT, "Sending PostServerHost request\n"); - bool result = g_pR5net->PostServerHost(m_szHostRequestMessage, m_szHostToken, - ServerListing{ - m_Server.svServerName, - std::string(g_pHostState->m_levelName), - "", - g_pCvar->FindVar("hostport")->m_pzsCurrentValue, - g_pCvar->FindVar("mp_gamemode")->m_pzsCurrentValue, - m_Server.bHidden, - std::to_string(*g_nRemoteFunctionCallsChecksum), - - std::string(), - g_szNetKey.c_str() - } - ); - - if (result) - { - m_iv4HostRequestMessageColor = ImVec4(0.00f, 1.00f, 0.00f, 1.00f); - std::stringstream msg; - msg << "Broadcasting! "; - if (!m_szHostToken.empty()) - { - msg << "Share the following token for clients to connect: "; - } - m_szHostRequestMessage = msg.str().c_str(); - } - else - { - m_iv4HostRequestMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); - } -} - -//----------------------------------------------------------------------------- -// Purpose: draws the compmenu -//----------------------------------------------------------------------------- -void IBrowser::CompMenu() -{ - ImGui::BeginTabBar("CompMenu"); - if (ImGui::TabItemButton("Server Browser")) - { - SetSection(ESection::SERVER_BROWSER); - } - if (ImGui::TabItemButton("Host Server")) - { - SetSection(ESection::HOST_SERVER); - } - if (ImGui::TabItemButton("Settings")) - { - SetSection(ESection::SETTINGS); - } - ImGui::EndTabBar(); -} - -//----------------------------------------------------------------------------- -// Purpose: draws the server browser section -//----------------------------------------------------------------------------- -void IBrowser::ServerBrowserSection() -{ - ImGui::BeginGroup(); - m_imServerBrowserFilter.Draw(); - ImGui::SameLine(); - if (ImGui::Button("Refresh List")) - { - RefreshServerList(); - } - ImGui::EndGroup(); - ImGui::TextColored(ImVec4(1.00f, 0.00f, 0.00f, 1.00f), m_szServerListMessage.c_str()); - ImGui::Separator(); - - const float FooterHeight = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); - ImGui::BeginChild("ServerListChild", { 0, -FooterHeight }, true, ImGuiWindowFlags_AlwaysVerticalScrollbar); - if (ImGui::BeginTable("##ServerBrowser_ServerList", 5, ImGuiTableFlags_Resizable)) - { - ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 20); - ImGui::TableSetupColumn("Map", ImGuiTableColumnFlags_WidthStretch, 25); - ImGui::TableSetupColumn("Port", ImGuiTableColumnFlags_WidthStretch, 5); - ImGui::TableSetupColumn("Playlist", ImGuiTableColumnFlags_WidthStretch, 5); - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 5); - ImGui::TableHeadersRow(); - - for (ServerListing& server : m_vServerList) - { - const char* name = server.svServerName.c_str(); - const char* map = server.svMapName.c_str(); - const char* port = server.svPort.c_str(); - const char* playlist = server.svPlaylist.c_str(); - - if (m_imServerBrowserFilter.PassFilter(name) - || m_imServerBrowserFilter.PassFilter(map) - || m_imServerBrowserFilter.PassFilter(port)) - { - ImGui::TableNextColumn(); - ImGui::Text(name); - - ImGui::TableNextColumn(); - ImGui::Text(map); - - ImGui::TableNextColumn(); - ImGui::Text(port); - - ImGui::TableNextColumn(); - ImGui::Text(playlist); - - ImGui::TableNextColumn(); - std::string selectButtonText = "Connect##"; - selectButtonText += (server.svServerName + server.svIpAddress + server.svMapName); - - if (ImGui::Button(selectButtonText.c_str())) - { - ConnectToServer(server.svIpAddress, server.svPort, server.svEncryptionKey); - } - } - - } - ImGui::EndTable(); - } - ImGui::EndChild(); - - ImGui::Separator(); - ImGui::PushItemWidth(ImGui::GetWindowContentRegionWidth() / 4); - { - ImGui::InputTextWithHint("##ServerBrowser_ServerConnString", "Enter IP address or \"localhost\"", m_chServerConnStringBuffer, IM_ARRAYSIZE(m_chServerConnStringBuffer)); - - ImGui::SameLine(); - ImGui::InputTextWithHint("##ServerBrowser_ServerEncKey", "Enter encryption key", m_chServerEncKeyBuffer, IM_ARRAYSIZE(m_chServerEncKeyBuffer)); - - ImGui::SameLine(); - if (ImGui::Button("Connect##ServerBrowser_ConnectByIp", ImVec2(ImGui::GetWindowContentRegionWidth() / 4.2, 18.5))) - { - ConnectToServer(m_chServerConnStringBuffer, m_chServerEncKeyBuffer); - } - - ImGui::SameLine(); - if (ImGui::Button("Private Servers##ServerBrowser_HiddenServersButton", ImVec2(ImGui::GetWindowContentRegionWidth() / 4.2, 18.5))) - { - ImGui::OpenPopup("Connect to Private Server##HiddenServersConnectModal"); - } - HiddenServersModal(); - } - ImGui::PopItemWidth(); -} - -//----------------------------------------------------------------------------- -// Purpose: draws the hidden private server modal -//----------------------------------------------------------------------------- -void IBrowser::HiddenServersModal() -{ - bool modalOpen = true; - if (ImGui::BeginPopupModal("Connect to Private Server##HiddenServersConnectModal", &modalOpen)) - { - ImGui::SetWindowSize(ImVec2(400.f, 200.f), ImGuiCond_Always); - - if (!m_idLockedIcon) - { - bool ret = LoadTextureBuffer((unsigned char*)m_vucLockedIconBlob, 0x1000 /*TODO [ AMOS ]: Calculate size dynamically*/, &m_idLockedIcon, &m_nLockedIconWidth, &m_nLockedIconHeight); - IM_ASSERT(ret); - } - - ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.00f, 0.00f, 0.00f, 0.00f)); // Override the style color for child bg. - - ImGui::BeginChild("##HiddenServersConnectModal_IconParent", ImVec2(m_nLockedIconWidth, m_nLockedIconHeight)); - ImGui::Image(m_idLockedIcon, ImVec2(m_nLockedIconWidth, m_nLockedIconHeight)); // Display texture. - ImGui::EndChild(); - - ImGui::PopStyleColor(); // Pop the override for the child bg. - - ImGui::SameLine(); - ImGui::Text("Enter the token to connect"); - - ImGui::PushItemWidth(ImGui::GetWindowContentRegionWidth()); // Override item width. - ImGui::InputTextWithHint("##HiddenServersConnectModal_TokenInput", "Token", &m_szHiddenServerToken); - ImGui::PopItemWidth(); - - ImGui::Dummy(ImVec2(ImGui::GetWindowContentRegionWidth(), 19.f)); // Place a dummy, basically making space inserting a blank element. - - ImGui::TextColored(m_ivHiddenServerMessageColor, m_szHiddenServerRequestMessage.c_str()); - ImGui::Separator(); - - if (ImGui::Button("Connect##HiddenServersConnectModal_ConnectButton", ImVec2(ImGui::GetWindowContentRegionWidth() / 2, 24))) - { - m_szHiddenServerRequestMessage.clear(); - ServerListing server; - bool result = g_pR5net->GetServerByToken(server, m_szHiddenServerRequestMessage, m_szHiddenServerToken); // Send token connect request. - if (!server.svServerName.empty()) - { - ConnectToServer(server.svIpAddress, server.svPort, server.svEncryptionKey); // Connect to the server - m_szHiddenServerRequestMessage = "Found Server: " + server.svServerName; - m_ivHiddenServerMessageColor = ImVec4(0.00f, 1.00f, 0.00f, 1.00f); - ImGui::CloseCurrentPopup(); - } - else - { - m_szHiddenServerRequestMessage = "Error: " + m_szHiddenServerRequestMessage; - m_ivHiddenServerMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); - } - } - - ImGui::SameLine(); - if (ImGui::Button("Close##HiddenServersConnectModal_CloseButton", ImVec2(ImGui::GetWindowContentRegionWidth() / 2, 24))) - { - ImGui::CloseCurrentPopup(); - } - - ImGui::EndPopup(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: draws the host section -//----------------------------------------------------------------------------- -void IBrowser::HostServerSection() -{ - static std::string szServerNameErr = ""; - - ImGui::InputTextWithHint("##ServerHost_ServerName", "Server Name (Required)", &m_Server.svServerName); - ImGui::Spacing(); - - if (ImGui::BeginCombo("Playlist##ServerHost_PlaylistBox", m_Server.svPlaylist.c_str())) - { - for (auto& item : g_szAllPlaylists) - { - if (ImGui::Selectable(item.c_str(), item == m_Server.svPlaylist)) - { - m_Server.svPlaylist = item; - } - } - ImGui::EndCombo(); - } - - if (ImGui::BeginCombo("Map##ServerHost_MapListBox", m_Server.svMapName.c_str())) - { - for (auto& item : m_vszMapsList) - { - if (ImGui::Selectable(item.c_str(), item == m_Server.svMapName)) - { - m_Server.svMapName = item; - for (auto it = mapArray.begin(); it != mapArray.end(); ++it) - { - if (it->second.compare(m_Server.svMapName) == NULL) - { - m_Server.svMapName = it->first; - } - } - } - } - ImGui::EndCombo(); - } - - ImGui::Checkbox("Load Global Ban List##ServerHost_CheckCompBanDBCheckbox", &g_bCheckCompBanDB); - ImGui::Spacing(); - - ImGui::SameLine(); - ImGui::Text("Server Visiblity"); - - if (ImGui::SameLine(); ImGui::RadioButton("Offline##ServerHost_ServerChoice1", eServerVisibility == EServerVisibility::OFFLINE)) - { - eServerVisibility = EServerVisibility::OFFLINE; - } - if (ImGui::SameLine(); ImGui::RadioButton("Hidden##ServerHost_ServerChoice2", eServerVisibility == EServerVisibility::HIDDEN)) - { - eServerVisibility = EServerVisibility::HIDDEN; - } - if (ImGui::SameLine(); ImGui::RadioButton("Public##ServerHost_ServerChoice2", eServerVisibility == EServerVisibility::PUBLIC)) - { - eServerVisibility = EServerVisibility::PUBLIC; - } - - ImGui::Spacing(); - ImGui::Separator(); - - if (!g_pHostState->m_bActiveGame) - { - if (ImGui::Button("Start Server##ServerHost_StartServerButton", ImVec2(ImGui::GetWindowSize().x, 32))) - { - szServerNameErr.clear(); - if (!m_Server.svServerName.empty() && !m_Server.svPlaylist.empty() && !m_Server.svMapName.empty()) - { - DevMsg(eDLL_T::ENGINE, "Starting Server with name '%s', map '%s' and playlist '%s'\n", m_Server.svServerName.c_str(), m_Server.svMapName.c_str(), m_Server.svPlaylist.c_str()); - szServerNameErr = std::string(); - UpdateHostingStatus(); - - /* - * Playlist gets parsed in two instances, first in LoadPlaylist all the neccessary values. - * Then when you would normally call launchplaylist which calls StartPlaylist it would cmd call mp_gamemode which parses the gamemode specific part of the playlist.. - */ - KeyValues_LoadPlaylist(m_Server.svPlaylist.c_str()); - std::stringstream cgmd; - cgmd << "mp_gamemode " << m_Server.svPlaylist; - ProcessCommand(cgmd.str().c_str()); - - // This is to avoid a race condition. - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - std::stringstream cmd; - cmd << "map " << m_Server.svMapName; - ProcessCommand(cmd.str().c_str()); - } - else - { - if (m_Server.svServerName.empty()) - { - szServerNameErr = "No Server Name assigned."; - } - else if (m_Server.svPlaylist.empty()) - { - szServerNameErr = "No Playlist assigned."; - } - else if (m_Server.svMapName.empty()) - { - szServerNameErr = "'levelname' was empty."; - } - } - } - } - - if (ImGui::Button("Force Start##ServerHost_ForceStart", ImVec2(ImGui::GetWindowSize().x, 32))) - { - szServerNameErr.clear(); - if (!m_Server.svPlaylist.empty() && !m_Server.svMapName.empty()) - { - DevMsg(eDLL_T::ENGINE, "Starting Server with map '%s' and playlist '%s'\n", m_Server.svMapName.c_str(), m_Server.svPlaylist.c_str()); - szServerNameErr = std::string(); - UpdateHostingStatus(); - - /* - * Playlist gets parsed in two instances, first in LoadPlaylist all the neccessary values. - * Then when you would normally call launchplaylist which calls StartPlaylist it would cmd call mp_gamemode which parses the gamemode specific part of the playlist.. - */ - KeyValues_LoadPlaylist(m_Server.svPlaylist.c_str()); - std::stringstream cgmd; - cgmd << "mp_gamemode " << m_Server.svPlaylist; - ProcessCommand(cgmd.str().c_str()); - - // This is to avoid a race condition. - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - std::stringstream cmd; - cmd << "map " << m_Server.svMapName; - ProcessCommand(cmd.str().c_str()); - } - else - { - if (m_Server.svPlaylist.empty()) - { - szServerNameErr = "No Playlist assigned."; - } - else if (m_Server.svMapName.empty()) - { - szServerNameErr = "'levelname' was empty."; - } - } - } - - ImGui::TextColored(ImVec4(1.00f, 0.00f, 0.00f, 1.00f), szServerNameErr.c_str()); - ImGui::TextColored(m_iv4HostRequestMessageColor, m_szHostRequestMessage.c_str()); - if (!m_szHostToken.empty()) - { - ImGui::InputText("##ServerHost_HostToken", &m_szHostToken, ImGuiInputTextFlags_ReadOnly); - } - - if (g_pHostState->m_bActiveGame) - { - if (ImGui::Button("Reload Scripts##ServerHost_ReloadServerButton", ImVec2(ImGui::GetWindowSize().x, 32))) - { - DevMsg(eDLL_T::ENGINE, "Recompiling scripts\n"); - ProcessCommand("reparse_weapons"); - ProcessCommand("reload"); - } - - if (ImGui::Button("Change Level##ServerHost_ChangeLevel", ImVec2(ImGui::GetWindowSize().x, 32))) - { - if (!m_Server.svMapName.empty()) - { - strncpy_s(g_pHostState->m_levelName, m_Server.svMapName.c_str(), 64); // Copy new map into hoststate levelname. 64 is size of m_levelname. - g_pHostState->m_iNextState = HostStates_t::HS_CHANGE_LEVEL_MP; // Force CHostState::FrameUpdate to change the level. - } - else - { - szServerNameErr = "Failed to change level: 'levelname' was empty."; - } - } - - if (ImGui::Button("Stop Server##ServerHost_StopServerButton", ImVec2(ImGui::GetWindowSize().x, 32))) - { - ProcessCommand("LeaveMatch"); // TODO: use script callback instead. - g_pHostState->m_iNextState = HostStates_t::HS_GAME_SHUTDOWN; // Force CHostState::FrameUpdate to shutdown the server for dedicated. - } - } - else - { - if (ImGui::Button("Reload Playlist from Disk##ServerHost_ReloadPlaylist", ImVec2(ImGui::GetWindowSize().x, 32))) - { - DownloadPlaylists_Callback(); - CKeyValueSystem_InitPlaylist(); // Re-Init playlist. - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: draws the settings section -//----------------------------------------------------------------------------- -void IBrowser::SettingsSection() -{ - ImGui::InputTextWithHint("Hostname##MatchmakingServerString", "Matchmaking Server String", &m_szMatchmakingHostName); - if (ImGui::Button("Update Hostname")) - { - r5net_matchmaking_hostname->m_pzsCurrentValue = m_szMatchmakingHostName.c_str(); - if (g_pR5net) - { - delete g_pR5net; - g_pR5net = new R5Net::Client(r5net_matchmaking_hostname->m_pzsCurrentValue); - } - } - ImGui::InputText("Netkey##SettingsSection_EncKey", (char*)g_szNetKey.c_str(), ImGuiInputTextFlags_ReadOnly); - if (ImGui::Button("Regenerate Encryption Key##SettingsSection_RegenEncKey")) - { - RegenerateEncryptionKey(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: draws the main browser frontend -//----------------------------------------------------------------------------- -void IBrowser::Draw(const char* title, bool* bDraw) -{ - if (!m_bThemeSet) - { - SetStyleVar(); - m_bThemeSet = true; - } - - if (!ImGui::Begin(title, bDraw)) - { - ImGui::End(); - return; - } - ImGui::End(); - - if (*bDraw == NULL) - { - g_bShowBrowser = false; - } - - ImGui::SetNextWindowSize(ImVec2(840, 600), ImGuiCond_FirstUseEver); - ImGui::SetWindowPos(ImVec2(-500, 50), ImGuiCond_FirstUseEver); - - ImGui::Begin(title, NULL, ImGuiWindowFlags_NoScrollbar); - { - CompMenu(); - - switch (eCurrentSection) - { - case ESection::SERVER_BROWSER: - ServerBrowserSection(); - break; - case ESection::HOST_SERVER: - HostServerSection(); - break; - case ESection::SETTINGS: - SettingsSection(); - break; - default: - break; - } - } - ImGui::End(); -} - -//----------------------------------------------------------------------------- -// Purpose: executes submitted commands in a separate thread -//----------------------------------------------------------------------------- -void IBrowser::ProcessCommand(const char* command_line) -{ - std::thread t(IVEngineClient_CommandExecute, this, command_line); - t.detach(); // Detach from render thread. - - // This is to avoid a race condition. - std::this_thread::sleep_for(std::chrono::milliseconds(1)); -} - -//----------------------------------------------------------------------------- -// Purpose: connects to specified server -//----------------------------------------------------------------------------- -void IBrowser::ConnectToServer(const std::string ip, const std::string port, const std::string encKey) -{ - if (!encKey.empty()) - { - ChangeEncryptionKeyTo(encKey); - } - - std::stringstream cmd; - cmd << "connect " << ip << ":" << port; - ProcessCommand(cmd.str().c_str()); -} - -//----------------------------------------------------------------------------- -// Purpose: connects to specified server -//----------------------------------------------------------------------------- -void IBrowser::ConnectToServer(const std::string connString, const std::string encKey) -{ - if (!encKey.empty()) - { - ChangeEncryptionKeyTo(encKey); - } - - std::stringstream cmd; - cmd << "connect " << connString; - ProcessCommand(cmd.str().c_str()); -} - -//----------------------------------------------------------------------------- -// Purpose: regenerates encryption key -//----------------------------------------------------------------------------- -void IBrowser::RegenerateEncryptionKey() -{ - HNET_GenerateKey(); -} - -//----------------------------------------------------------------------------- -// Purpose: changes encryption key to specified one -//----------------------------------------------------------------------------- -void IBrowser::ChangeEncryptionKeyTo(const std::string str) -{ - HNET_SetKey(str); -} - -//############################################################################# -// ENTRYPOINT -//############################################################################# - -IBrowser* g_pServerBrowser = nullptr; -void DrawBrowser(bool* bDraw) -{ - static IBrowser browser; - static bool AssignPtr = []() - { - g_pServerBrowser = &browser; - return true; - } (); - browser.Draw("Server Browser", bDraw); -} diff --git a/r5dev/gameui/IBrowser.h b/r5dev/gameui/IBrowser.h deleted file mode 100644 index 6ff873e3..00000000 --- a/r5dev/gameui/IBrowser.h +++ /dev/null @@ -1,173 +0,0 @@ -#pragma once -#ifndef DEDICATED -#include "networksystem/serverlisting.h" -#include "networksystem/r5net.h" - -void DrawBrowser(bool* bDraw); - -class IBrowser -{ -private: - bool m_bThemeSet = false; -public: - IBrowser(); - ~IBrowser(); - - //////////////////// - // Enums // - //////////////////// - enum class ESection - { - SERVER_BROWSER, - HOST_SERVER, - SETTINGS - } eCurrentSection = ESection::SERVER_BROWSER; - - enum class EHostStatus - { - NOT_HOSTING, - HOSTING - } eHostingStatus = EHostStatus::NOT_HOSTING; - - enum class EServerVisibility - { - OFFLINE, - HIDDEN, - PUBLIC - } eServerVisibility = EServerVisibility::OFFLINE; - - //////////////////// - // Server Browser // - //////////////////// -public: - std::vector m_vServerList; - ImGuiTextFilter m_imServerBrowserFilter; - char m_chServerConnStringBuffer[256] = { 0 }; - char m_chServerEncKeyBuffer[30] = { 0 }; - std::string m_szServerListMessage = std::string(); - - std::map mapArray = - { - { "mp_rr_canyonlands_64k_x_64k", "King's Canyon Season 0" }, - { "mp_rr_desertlands_64k_x_64k", "World's Edge Season 3" }, - { "mp_rr_canyonlands_mu1", "King's Canyon Season 2" }, - { "mp_rr_canyonlands_mu1_night", "King's Canyon Season 2 After Dark" }, - { "mp_rr_desertlands_64k_x_64k_nx", "World's Edge Season 3 After Dark" }, - { "mp_lobby", "Lobby Season 3" }, - { "mp_rr_canyonlands_staging", "King's Canyon Firing Range" } - }; - - //////////////////// - // Settings // - //////////////////// - std::string m_szMatchmakingHostName; - - //////////////////// - // Host Server // - //////////////////// - ServerListing m_Server; - std::vector m_vszMapsList; - std::string m_szHostRequestMessage = ""; - std::string m_szHostToken = ""; - ImVec4 m_iv4HostRequestMessageColor = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - - //////////////////// - // Private Server // - //////////////////// - std::string m_szHiddenServerToken = ""; - std::string m_szHiddenServerRequestMessage = ""; - ImVec4 m_ivHiddenServerMessageColor = ImVec4(0.00f, 1.00f, 0.00f, 1.00f); - - /* Texture */ - ID3D11ShaderResourceView* m_idLockedIcon = nullptr; - int m_nLockedIconWidth = 0; - int m_nLockedIconHeight = 0; - std::vector* m_vucLockedIconBlob; - - void SetSection(ESection section) - { - eCurrentSection = section; - } - - //////////////////// - // Style // - //////////////////// - void SetStyleVar() - { - ImGuiStyle& style = ImGui::GetStyle(); - ImVec4* colors = style.Colors; - - colors[ImGuiCol_Text] = ImVec4(0.81f, 0.81f, 0.81f, 1.00f); - colors[ImGuiCol_TextDisabled] = ImVec4(0.56f, 0.56f, 0.56f, 1.00f); - colors[ImGuiCol_WindowBg] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f); - colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); - colors[ImGuiCol_PopupBg] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f); - colors[ImGuiCol_Border] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); - colors[ImGuiCol_BorderShadow] = ImVec4(0.04f, 0.04f, 0.04f, 0.64f); - colors[ImGuiCol_FrameBg] = ImVec4(0.13f, 0.13f, 0.13f, 1.00f); - colors[ImGuiCol_FrameBgHovered] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f); - colors[ImGuiCol_FrameBgActive] = ImVec4(0.24f, 0.24f, 0.24f, 1.00f); - colors[ImGuiCol_TitleBg] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f); - colors[ImGuiCol_TitleBgActive] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f); - colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); - colors[ImGuiCol_MenuBarBg] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f); - colors[ImGuiCol_ScrollbarBg] = ImVec4(0.10f, 0.10f, 0.10f, 1.00f); - colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); - colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f); - colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f); - colors[ImGuiCol_CheckMark] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); - colors[ImGuiCol_SliderGrab] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); - colors[ImGuiCol_SliderGrabActive] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f); - colors[ImGuiCol_Button] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f); - colors[ImGuiCol_ButtonHovered] = ImVec4(0.45f, 0.45f, 0.45f, 1.00f); - colors[ImGuiCol_ButtonActive] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f); - colors[ImGuiCol_Header] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f); - colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.45f, 1.00f); - colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f); - colors[ImGuiCol_Separator] = ImVec4(0.53f, 0.53f, 0.57f, 1.00f); - colors[ImGuiCol_SeparatorHovered] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f); - colors[ImGuiCol_SeparatorActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); - colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f); - colors[ImGuiCol_ResizeGripActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f); - colors[ImGuiCol_Tab] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f); - colors[ImGuiCol_TabHovered] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); - colors[ImGuiCol_TabActive] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); - - style.WindowBorderSize = 0.0f; - style.FrameBorderSize = 1.0f; - style.ChildBorderSize = 1.0f; - style.PopupBorderSize = 1.0f; - style.TabBorderSize = 1.0f; - - style.WindowRounding = 2.5f; - style.FrameRounding = 0.0f; - style.ChildRounding = 0.0f; - style.PopupRounding = 0.0f; - style.TabRounding = 1.0f; - style.ScrollbarRounding = 1.0f; - - style.ItemSpacing = ImVec2(4, 4); - style.WindowPadding = ImVec2(5, 5); - } - - void RefreshServerList(); - void SendHostingPostRequest(); - void CompMenu(); - void ServerBrowserSection(); - void SettingsSection(); - void HiddenServersModal(); - void HostServerSection(); - void Draw(const char* title, bool* bDraw); - void UpdateHostingStatus(); - void ProcessCommand(const char* command_line); - - void RegenerateEncryptionKey(); - void ChangeEncryptionKeyTo(const std::string str); - - void ConnectToServer(const std::string ip, const std::string port, const std::string encKey); - void ConnectToServer(const std::string connString, const std::string encKey); -}; - -extern IBrowser* g_pServerBrowser; -#endif diff --git a/r5dev/networksystem/net_structs.h b/r5dev/networksystem/net_structs.h new file mode 100644 index 00000000..56f50503 --- /dev/null +++ b/r5dev/networksystem/net_structs.h @@ -0,0 +1,93 @@ +#pragma once + +namespace R5Net { + + struct NetGameMod + { + std::string package; + int number; + bool requiredForClients; + std::string downloadLink; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(NetGameMod, package, number, requiredForClients, downloadLink) + + }; + + struct NetGameServer + { + std::string name; + std::string description; + std::string password; + + int playerCount; + int maxPlayerCount; + std::string playlist; + std::string mapName; + + std::vector mods; + + std::string ipAddress; + int gamePort; + std::string encryptionKey; + std::string remoteChecksum; + + std::string reloadedVersion; + + std::string publicRef; + + int lastPing = -1; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(NetGameServer, name, description, password, playerCount, maxPlayerCount, playlist, mapName, mods, ipAddress, gamePort, encryptionKey, remoteChecksum, reloadedVersion, publicRef) + }; + + + ////// Requests + struct UpdateGameServerMSRequest + { + NetGameServer gameServer; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(UpdateGameServerMSRequest, gameServer) + }; + + enum class EResponseStatus + { + NO_REACH, + SUCCESS, + FORBIDDEN, + NOT_FOUND, + MS_ERROR + }; + + /// + /// Responses + /// + struct DefaultMSResponse + { + EResponseStatus status = EResponseStatus::NO_REACH; + std::string error; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(DefaultMSResponse, error) + }; + + struct GetGlobalStatsMSResponse : DefaultMSResponse + { + int noPlayers; + int noServers; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(GetGlobalStatsMSResponse, noPlayers, noServers) + }; + + struct GetGameServersListMSResponse : DefaultMSResponse + { + std::vector publicServers; + std::vector privateServers; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(GetGameServersListMSResponse, publicServers, privateServers) + }; + + struct UpdateGameServerMSResponse : DefaultMSResponse + { + + }; + +} diff --git a/r5dev/networksystem/r5net.cpp b/r5dev/networksystem/r5net.cpp index 4f814233..46edaf34 100644 --- a/r5dev/networksystem/r5net.cpp +++ b/r5dev/networksystem/r5net.cpp @@ -2,327 +2,6 @@ // #include "core/stdafx.h" -#include "tier0/basetypes.h" -#include "tier0/cvar.h" -#include "engine/sys_utils.h" -#include "networksystem/r5net.h" +#include -//----------------------------------------------------------------------------- -// Purpose: returns the sdk version string. -//----------------------------------------------------------------------------- -std::string R5Net::Client::GetSDKVersion() -{ - return SDK_VERSION; -} - -//----------------------------------------------------------------------------- -// Purpose: returns a vector of hosted servers. -//----------------------------------------------------------------------------- -std::vector R5Net::Client::GetServersList(std::string& svOutMessage) -{ - std::vector vslList{}; - - nlohmann::json jsReqBody = nlohmann::json::object(); - jsReqBody["version"] = GetSDKVersion(); - - std::string reqBodyStr = jsReqBody.dump(); - - if (r5net_show_debug->m_pParent->m_iValue > 0) - { - DevMsg(eDLL_T::ENGINE, "Sending GetServerList post.\n"); - } - - httplib::Result htResults = m_HttpClient.Post("/servers", jsReqBody.dump().c_str(), jsReqBody.dump().length(), "application/json"); - - if (r5net_show_debug->m_pParent->m_iValue > 0) - { - DevMsg(eDLL_T::ENGINE, "GetServerList replied with '%d'.\n", htResults->status); - } - - if (htResults && htResults->status == 200) // STATUS_OK - { - nlohmann::json jsResultBody = nlohmann::json::parse(htResults->body); - if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get()) - { - for (auto &obj : jsResultBody["servers"]) - { - vslList.push_back( - ServerListing{ - obj.value("name",""), - obj.value("map", ""), - obj.value("ip", ""), - obj.value("port", ""), - obj.value("gamemode", ""), - obj.value("hidden", "false") == "true", - obj.value("remote_checksum", ""), - obj.value("version", GetSDKVersion()), - obj.value("encKey", "") - } - ); - } - } - else - { - if (jsResultBody["err"].is_string()) - { - svOutMessage = jsResultBody["err"].get(); - } - else - { - svOutMessage = "An unknown error occured!"; - } - } - } - else - { - if (htResults) - { - if (!htResults->body.empty()) - { - nlohmann::json jsResultBody = nlohmann::json::parse(htResults->body); - - if (jsResultBody["err"].is_string()) - { - svOutMessage = jsResultBody["err"].get(); - } - else - { - svOutMessage = std::string("Failed to reach comp-server ") + std::to_string(htResults->status); - } - - return vslList; - } - - svOutMessage = std::string("Failed to reach comp-server ") + std::to_string(htResults->status); - return vslList; - } - - svOutMessage = "Failed to reach comp-server. Unknown error code."; - return vslList; - } - - return vslList; -} - -//----------------------------------------------------------------------------- -// Purpose: Sends host server POST request. -// Input : &svOutMessage - -// &svOutToken - -// &slServerListing - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool R5Net::Client::PostServerHost(std::string& svOutMessage, std::string& svOutToken, const ServerListing& slServerListing) -{ - nlohmann::json jsRequestBody = nlohmann::json::object(); - jsRequestBody["name"] = slServerListing.svServerName; - jsRequestBody["map"] = slServerListing.svMapName; - jsRequestBody["port"] = slServerListing.svPort; - jsRequestBody["remote_checksum"] = slServerListing.svRemoteChecksum; - jsRequestBody["version"] = GetSDKVersion(); - jsRequestBody["gamemode"] = slServerListing.svPlaylist; - jsRequestBody["encKey"] = slServerListing.svEncryptionKey; - jsRequestBody["hidden"] = slServerListing.bHidden; - - std::string svRequestBody = jsRequestBody.dump(); - - if (r5net_show_debug->m_pParent->m_iValue > 0) - { - DevMsg(eDLL_T::ENGINE, "Sending PostServerHost post '%s'.\n", svRequestBody.c_str()); - } - - httplib::Result htResults = m_HttpClient.Post("/servers/add", svRequestBody.c_str(), svRequestBody.length(), "application/json"); - - if (r5net_show_debug->m_pParent->m_iValue > 0) - { - DevMsg(eDLL_T::ENGINE, "PostServerHost replied with '%d'.\n", htResults->status); - } - - if (htResults && htResults->status == 200) // STATUS_OK - { - nlohmann::json jsResultBody = nlohmann::json::parse(htResults->body); - if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get()) - { - if (jsResultBody["token"].is_string()) - { - svOutToken = jsResultBody["token"].get(); - } - else - { - svOutToken = std::string(); - } - - return true; - } - else - { - if (jsResultBody["err"].is_string()) - { - svOutMessage = jsResultBody["err"].get(); - } - else - { - svOutMessage = "An unknown error occured!"; - } - return false; - } - } - else - { - if (htResults) - { - if (!htResults->body.empty()) - { - nlohmann::json jsResultBody = nlohmann::json::parse(htResults->body); - - if (jsResultBody["err"].is_string()) - { - svOutMessage = jsResultBody["err"].get(); - } - else - { - svOutMessage = std::string("Failed to reach comp-server ") + std::to_string(htResults->status); - } - - svOutToken = std::string(); - return false; - } - - svOutToken = std::string(); - svOutMessage = std::string("Failed to reach comp-server ") + std::to_string(htResults->status); - return false; - } - - svOutToken = std::string(); - svOutMessage = "Failed to reach comp-server. Unknown error code."; - return false; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Gets the server by token string. -// Input : &slOutServer - -// &svOutMessage - -// svToken - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool R5Net::Client::GetServerByToken(ServerListing& slOutServer, std::string& svOutMessage, const std::string svToken) -{ - nlohmann::json jsRequestBody = nlohmann::json::object(); - - jsRequestBody["token"] = svToken; - - if (r5net_show_debug->m_pParent->m_iValue > 0) - { - DevMsg(eDLL_T::ENGINE, "Sending GetServerByToken post.\n"); - } - - httplib::Result htResults = m_HttpClient.Post("/server/byToken", jsRequestBody.dump().c_str(), jsRequestBody.dump().length(), "application/json"); - - if (r5net_show_debug->m_pParent->m_iValue > 0) - { - DevMsg(eDLL_T::ENGINE, "GetServerByToken replied with '%d'\n", htResults->status); - } - - if (htResults && htResults->status == 200) // STATUS_OK - { - if (!htResults->body.empty()) - { - nlohmann::json jsResultBody = nlohmann::json::parse(htResults->body); - - if (htResults && jsResultBody["success"].is_boolean() && jsResultBody["success"]) - { - slOutServer = ServerListing{ - jsResultBody["server"].value("name",""), - jsResultBody["server"].value("map", ""), - jsResultBody["server"].value("ip", ""), - jsResultBody["server"].value("port", ""), - jsResultBody["server"].value("gamemode", ""), - jsResultBody["server"].value("hidden", "false") == "true", - jsResultBody["server"].value("remote_checksum", ""), - jsResultBody["server"].value("version", GetSDKVersion()), - jsResultBody["server"].value("encKey", "") - }; - return true; - } - else - { - if (jsResultBody["err"].is_string()) - { - svOutMessage = jsResultBody["err"].get(); - } - else - { - svOutMessage = ""; - } - - slOutServer = ServerListing{}; - return false; - } - } - } - else - { - if (htResults) - { - if (!htResults->body.empty()) - { - nlohmann::json jsResultBody = nlohmann::json::parse(htResults->body); - - if (jsResultBody["err"].is_string()) - { - svOutMessage = jsResultBody["err"].get(); - } - else - { - svOutMessage = std::string("Failed to reach comp-server ") + std::to_string(htResults->status); - } - - return false; - } - - svOutMessage = std::string("Failed to reach comp-server ") + std::to_string(htResults->status); - return false; - } - - svOutMessage = "Failed to reach comp-server. Unknown error code."; - slOutServer = ServerListing{}; - return false; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Checks if client is banned on the comp server. -// Input : svIpAddress - -// nOriginID - -// &svOutErrCl - -// Output : Returns true if banned, false if not banned. -//----------------------------------------------------------------------------- -bool R5Net::Client::GetClientIsBanned(const std::string svIpAddress, std::int64_t nOriginID, std::string& svOutErrCl) -{ - nlohmann::json jsRequestBody = nlohmann::json::object(); - jsRequestBody["ip"] = svIpAddress; - jsRequestBody["orid"] = nOriginID; - - httplib::Result htResults = m_HttpClient.Post("/banlist/isBanned", jsRequestBody.dump().c_str(), jsRequestBody.dump().length(), "application/json"); - - if (htResults && htResults->status == 200) - { - nlohmann::json jsResultBody = nlohmann::json::parse(htResults->body); - - if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get()) - { - if (jsResultBody["isBanned"].is_boolean() && jsResultBody["isBanned"].get()) - { - svOutErrCl = jsResultBody.value("errCl", "Generic error (code:gen). Contact R5Reloaded developers."); - return true; - } - } - } - return false; -} -/////////////////////////////////////////////////////////////////////////////// -R5Net::Client* g_pR5net(new R5Net::Client("r5a-comp-sv.herokuapp.com")); +R5Net::Client* g_pR5net = new R5Net::Client("127.0.0.1:3000"); \ No newline at end of file diff --git a/r5dev/networksystem/r5net.h b/r5dev/networksystem/r5net.h index 072412a2..2a3d2fc6 100644 --- a/r5dev/networksystem/r5net.h +++ b/r5dev/networksystem/r5net.h @@ -1,27 +1,54 @@ #pragma once -#include "serverlisting.h" + +#include "net_structs.h" +#include "core/stdafx.h" namespace R5Net { - class Client +#define R5NET_GET_ENDPOINT(FuncName, Route, ResponseStructType) ResponseStructType FuncName() {\ + ResponseStructType result{};\ + httplib::Result response = HttpClient.Get(Route);\ + if(response == nullptr) return result;\ + nlohmann::json response_body = nlohmann::json::parse(response->body);\ + nlohmann::to_json(response_body, result);\ + return result;\ +}\ + +#define R5NET_POST_ENDPOINT(FuncName, Route, RequestStructType, ResponseStructType) ResponseStructType FuncName(RequestStructType& request) {\ + ResponseStructType result{};\ + nlohmann::json request_body;\ + nlohmann::to_json(request_body, request);\ + httplib::Result response = HttpClient.Post("/", request_body.dump(), "application/json");\ + if (response == nullptr) return result;\ + nlohmann::json response_body = nlohmann::json::parse(response->body);\ + nlohmann::to_json(response_body, result);\ + return result;\ +} + + + class Client { + httplib::Client HttpClient; + public: - Client(std::string serverString) : m_HttpClient(serverString.c_str()) + Client(std::string masterServerConnectionString) : HttpClient(masterServerConnectionString.c_str()) { - m_HttpClient.set_connection_timeout(10); + HttpClient.set_connection_timeout(25); } - - std::vector GetServersList(std::string& svOutMessage); - bool PostServerHost(std::string& svOutMessage, std::string& svOutToken, const ServerListing& slServerListing); - bool GetServerByToken(ServerListing& slOutServer, std::string& svOutMessage, const std::string svToken); - bool GetClientIsBanned(std::string svIpAddress, std::int64_t nOriginID, std::string& svOutErrCl); - std::string GetSDKVersion(); - Client* pR5net = nullptr; - Client* GetR5Net() { return pR5net; } - private: - httplib::Client m_HttpClient; + R5NET_GET_ENDPOINT(GetGlobalStats, "/api/stats", GetGlobalStatsMSResponse) + R5NET_GET_ENDPOINT(GetGameServersList, "/api/game_servers/list", GetGameServersListMSResponse) + + R5NET_POST_ENDPOINT(UpdateMyGameServer, "/api/game_servers/update", UpdateGameServerMSRequest, UpdateGameServerMSResponse) + + bool GetClientIsBanned(std::string stub, int stub2, std::string& outStub) + { + // TODO: implement + return false; + } + }; } -extern R5Net::Client* g_pR5net; + +extern R5Net::Client* g_pR5net; \ No newline at end of file diff --git a/r5dev/networksystem/serverlisting.h b/r5dev/networksystem/serverlisting.h deleted file mode 100644 index c0d1d760..00000000 --- a/r5dev/networksystem/serverlisting.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -struct ServerListing -{ - std::string svServerName; - std::string svMapName = "mp_rr_canyonlands_staging"; - std::string svIpAddress; - std::string svPort; - std::string svPlaylist = "survival_dev"; - bool bHidden{}; - std::string svRemoteChecksum; - std::string svVersion; - std::string svEncryptionKey; -}; diff --git a/r5dev/r5dev.vcxproj b/r5dev/r5dev.vcxproj index 58d193dd..3bd3fb18 100644 --- a/r5dev/r5dev.vcxproj +++ b/r5dev/r5dev.vcxproj @@ -40,7 +40,6 @@ - @@ -132,7 +131,6 @@ - @@ -141,8 +139,8 @@ + - diff --git a/r5dev/r5dev.vcxproj.filters b/r5dev/r5dev.vcxproj.filters index 78e557f1..d6f8246a 100644 --- a/r5dev/r5dev.vcxproj.filters +++ b/r5dev/r5dev.vcxproj.filters @@ -156,9 +156,6 @@ sdk\engine - - sdk\gameui - sdk\gameui @@ -341,9 +338,6 @@ sdk\engine - - sdk\gameui - sdk\gameui @@ -788,9 +782,6 @@ sdk\networksystem - - sdk\networksystem - sdk\mathlib @@ -839,6 +830,9 @@ sdk\engine + + sdk\networksystem + diff --git a/r5dev/server/server.h b/r5dev/server/server.h index bd3c78d0..4a0f50d4 100644 --- a/r5dev/server/server.h +++ b/r5dev/server/server.h @@ -33,7 +33,6 @@ namespace void CServer_Attach(); void CServer_Detach(); -void IsClientBanned(R5Net::Client* r5net, const std::string ipaddr, std::int64_t nucleus_id); void* HCServer_Authenticate(void* cserver, user_creds* inpacket); extern bool g_bCheckCompBanDB; diff --git a/r5dev/windows/id3dx.cpp b/r5dev/windows/id3dx.cpp index cf0e7ee3..aac2490e 100644 --- a/r5dev/windows/id3dx.cpp +++ b/r5dev/windows/id3dx.cpp @@ -6,7 +6,6 @@ #include "windows/id3dx.h" #include "windows/input.h" #include "gameui/IConsole.h" -#include "gameui/IBrowser.h" #include "engine/sys_utils.h" #include "inputsystem/inputsystem.h" #include "public/include/stb_image.h" @@ -280,11 +279,6 @@ void DrawImGui() g_pInputSystem->EnableInput(false); // Disable input to game when console is drawn. DrawConsole(&bShowConsole); } - if (g_bShowBrowser) - { - g_pInputSystem->EnableInput(false); // Disable input to game when browser is drawn. - DrawBrowser(&bShowBrowser); - } if (!g_bShowConsole && !g_bShowBrowser) { g_pInputSystem->EnableInput(true); // Enable input to game when both are not drawn. From 433f14c352a0ae366cff2cbe03753b2198a77848 Mon Sep 17 00:00:00 2001 From: Alex <18037145+salcodes1@users.noreply.github.com> Date: Tue, 28 Dec 2021 03:31:33 +0200 Subject: [PATCH 2/6] partial commit --- r5dev/core/stdafx.h | 2 ++ r5dev/networksystem/r5net.h | 22 ++++++++++------------ r5dev/server/server.cpp | 11 ++++++++++- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/r5dev/core/stdafx.h b/r5dev/core/stdafx.h index c910af11..1de1db21 100644 --- a/r5dev/core/stdafx.h +++ b/r5dev/core/stdafx.h @@ -45,6 +45,8 @@ #include "public/include/httplib.h" #include "public/include/json.hpp" +#include "networksystem/net_structs.h" + #ifndef SDKLAUNCHER namespace { diff --git a/r5dev/networksystem/r5net.h b/r5dev/networksystem/r5net.h index 072412a2..455a985a 100644 --- a/r5dev/networksystem/r5net.h +++ b/r5dev/networksystem/r5net.h @@ -6,22 +6,20 @@ namespace R5Net class Client { public: - Client(std::string serverString) : m_HttpClient(serverString.c_str()) + Client(std::string masterServerConnectionString) : HttpClient(masterServerConnectionString.c_str()) { - m_HttpClient.set_connection_timeout(10); + HttpClient.set_connection_timeout(25); } - - std::vector GetServersList(std::string& svOutMessage); - bool PostServerHost(std::string& svOutMessage, std::string& svOutToken, const ServerListing& slServerListing); - bool GetServerByToken(ServerListing& slOutServer, std::string& svOutMessage, const std::string svToken); - bool GetClientIsBanned(std::string svIpAddress, std::int64_t nOriginID, std::string& svOutErrCl); - std::string GetSDKVersion(); - Client* pR5net = nullptr; - Client* GetR5Net() { return pR5net; } - private: - httplib::Client m_HttpClient; + R5NET_GET_ENDPOINT(GetGlobalStats, "/api/stats", GetGlobalStatsMSResponse) + R5NET_GET_ENDPOINT(GetGameServersList, "/api/game_servers/list", GetGameServersListMSResponse) + + R5NET_POST_ENDPOINT(UpdateMyGameServer, "/api/game_servers/update", UpdateGameServerMSRequest, UpdateGameServerMSResponse) + R5NET_POST_ENDPOINT(GetClientIsBanned, "/api/ban_system/is_user_banned", GetIsUserBannedMSRequest, GetIsUserBannedMSResponse) + + + }; } extern R5Net::Client* g_pR5net; diff --git a/r5dev/server/server.cpp b/r5dev/server/server.cpp index 02f42d66..a877c52f 100644 --- a/r5dev/server/server.cpp +++ b/r5dev/server/server.cpp @@ -12,7 +12,16 @@ void IsClientBanned(R5Net::Client* pR5net, const std::string svIPAddr, std::int64_t nNucleusID) { std::string svError = std::string(); - bool bCompBanned = pR5net && pR5net->GetClientIsBanned(svIPAddr, nNucleusID, svError); + + R5Net::GetIsUserBannedMSRequest req{nNucleusID, svIPAddr}; + R5Net::GetIsUserBannedMSResponse res = pR5net->GetClientIsBanned(req); + + switch (res.status) + { + // TODO: EVENTUALLY IMPLEMENT SITUATIONS WHERE REQUEST DIDNT SUCCEED + } + + bool bCompBanned = res.isBanned; if (bCompBanned) { while (bCompBanned) From 2f2d01713fd38861f0e674641bf14b6afd25ecc6 Mon Sep 17 00:00:00 2001 From: Alex <18037145+salcodes1@users.noreply.github.com> Date: Tue, 28 Dec 2021 03:44:20 +0200 Subject: [PATCH 3/6] added get private game server info route --- r5dev/networksystem/net_structs.h | 50 ++++++++++++++++++++++++++----- r5dev/networksystem/r5net.h | 1 + 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/r5dev/networksystem/net_structs.h b/r5dev/networksystem/net_structs.h index 56f50503..4eea81cf 100644 --- a/r5dev/networksystem/net_structs.h +++ b/r5dev/networksystem/net_structs.h @@ -42,14 +42,37 @@ namespace R5Net { ////// Requests - struct UpdateGameServerMSRequest + struct UpdateGameServerMSRequest { NetGameServer gameServer; NLOHMANN_DEFINE_TYPE_INTRUSIVE(UpdateGameServerMSRequest, gameServer) }; - enum class EResponseStatus + struct GetIsUserBannedMSRequest + { + int oid; + std::string ipAddress; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(GetIsUserBannedMSRequest, oid, ipAddress) + }; + + struct GetPrivateGameServerInfoMSRequest + { + std::string publicRef; + std::string password; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(GetPrivateGameServerInfoMSRequest, publicRef, password) + }; + + + /// + /// Responses + /// + /// + /// + + enum class EResponseStatus { NO_REACH, SUCCESS, @@ -57,11 +80,9 @@ namespace R5Net { NOT_FOUND, MS_ERROR }; - - /// - /// Responses - /// - struct DefaultMSResponse + + + struct DefaultMSResponse { EResponseStatus status = EResponseStatus::NO_REACH; std::string error; @@ -90,4 +111,19 @@ namespace R5Net { }; + struct GetIsUserBannedMSResponse : DefaultMSResponse + { + bool isBanned; + std::string metaString; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(GetIsUserBannedMSResponse, isBanned, metaString) + }; + + struct GetPrivateGameServerInfoMSResponse : DefaultMSResponse + { + NetGameServer gameServer; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(GetPrivateGameServerInfoMSResponse, gameServer) + }; + } diff --git a/r5dev/networksystem/r5net.h b/r5dev/networksystem/r5net.h index a2a769d8..bfd21860 100644 --- a/r5dev/networksystem/r5net.h +++ b/r5dev/networksystem/r5net.h @@ -42,6 +42,7 @@ namespace R5Net R5NET_POST_ENDPOINT(UpdateMyGameServer, "/api/game_servers/update", UpdateGameServerMSRequest, UpdateGameServerMSResponse) R5NET_POST_ENDPOINT(GetClientIsBanned, "/api/ban_system/is_user_banned", GetIsUserBannedMSRequest, GetIsUserBannedMSResponse) + R5NET_POST_ENDPOINT(GetPrivateGameServerInfo, "/api/game_servers/game_server_private_info", GetPrivateGameServerInfoMSRequest, GetPrivateGameServerInfoMSResponse) From 00cd76f7b21476e054d3ead4a4c8d507f391c963 Mon Sep 17 00:00:00 2001 From: Alex <18037145+salcodes1@users.noreply.github.com> Date: Tue, 28 Dec 2021 03:45:41 +0200 Subject: [PATCH 4/6] Fixed post requests not using provided route --- r5dev/networksystem/r5net.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/networksystem/r5net.h b/r5dev/networksystem/r5net.h index bfd21860..cbc70115 100644 --- a/r5dev/networksystem/r5net.h +++ b/r5dev/networksystem/r5net.h @@ -18,7 +18,7 @@ namespace R5Net ResponseStructType result{};\ nlohmann::json request_body;\ nlohmann::to_json(request_body, request);\ - httplib::Result response = HttpClient.Post("/", request_body.dump(), "application/json");\ + httplib::Result response = HttpClient.Post(Route, request_body.dump(), "application/json");\ if (response == nullptr) return result;\ nlohmann::json response_body = nlohmann::json::parse(response->body);\ nlohmann::to_json(response_body, result);\ From a3946bb5ce4655665a763aeb3c2b016215bfa805 Mon Sep 17 00:00:00 2001 From: Alex <18037145+salcodes1@users.noreply.github.com> Date: Tue, 28 Dec 2021 22:07:02 +0200 Subject: [PATCH 5/6] Pylon C++ implementation actually working now --- r5dev/IDevPalette.h | 73 ++++++++++++++++++++++++++ r5dev/IDevPallete.cpp | 26 ++++++++++ r5dev/cpp.hint | 1 + r5dev/networksystem/net_structs.h | 5 +- r5dev/networksystem/r5net.h | 86 ++++++++++++++++++++++++++++--- r5dev/public/include/json.hpp | 2 +- r5dev/r5dev.vcxproj | 2 + r5dev/r5dev.vcxproj.filters | 6 +++ r5dev/windows/id3dx.cpp | 6 +++ 9 files changed, 198 insertions(+), 9 deletions(-) create mode 100644 r5dev/IDevPalette.h create mode 100644 r5dev/IDevPallete.cpp diff --git a/r5dev/IDevPalette.h b/r5dev/IDevPalette.h new file mode 100644 index 00000000..4ea4dc7c --- /dev/null +++ b/r5dev/IDevPalette.h @@ -0,0 +1,73 @@ +#pragma once + +#include "core/stdafx.h" +#include +#include +#include + +#ifndef DEDICATED + +class CDevPalette +{ +public: + void Draw(bool* bDraw) + { + + ImGui::SetNextWindowSize(ImVec2(1000, 600), ImGuiCond_FirstUseEver); + ImGui::SetWindowPos(ImVec2(-1000, 50), ImGuiCond_FirstUseEver); + + if (!ImGui::Begin("Dev Palette", bDraw)) + { + ImGui::End(); + return; + } + if (ImGui::Button("Get Stats")) + { + auto response = g_pR5net->GetGlobalStats(); + switch (response.status) + { + case R5Net::EResponseStatus::SUCCESS: + { + g_GameConsole->AddLog("SUCCESS: %d players, %d servers", response.noPlayers, response.noServers); + break; + } + default: + { + g_GameConsole->AddLog("ERROR: %s", response.error.c_str()); + } + } + } + if (ImGui::Button("Send Fake Server Request")) + { + R5Net::UpdateGameServerMSRequest request{}; + request.gameServer.name = "TestNameServer"; + request.gameServer.playlist = "yoopp"; + request.gameServer.gamePort = 8089; + + + auto response = g_pR5net->UpdateMyGameServer(request); + switch (response.status) + { + case R5Net::EResponseStatus::SUCCESS: + { + g_GameConsole->AddLog("SUCCESS: %s", response.gameServer.name.c_str()); + break; + } + default: + { + g_GameConsole->AddLog("ERROR: %s", response.error.c_str()); + } + } + } + if (*bDraw == NULL) + { + g_bShowBrowser = false; + } + ImGui::End(); + } +}; + +void DrawDevPalette(bool* bDraw); + +extern CDevPalette* g_DevPalette; +#endif \ No newline at end of file diff --git a/r5dev/IDevPallete.cpp b/r5dev/IDevPallete.cpp new file mode 100644 index 00000000..05e91fb6 --- /dev/null +++ b/r5dev/IDevPallete.cpp @@ -0,0 +1,26 @@ +#include "core/stdafx.h" + +#ifndef DEDICATED +#include "IDevPalette.h" + + + +//############################################################################# +// ENTRYPOINT +//############################################################################# + +CDevPalette* g_DevPalette = nullptr; + +void DrawDevPalette(bool* bDraw) +{ + static CDevPalette devPalette; + static bool AssignPtr = []() + { + g_DevPalette = &devPalette; + return true; + } (); + if (*bDraw) devPalette.Draw(bDraw); +} + +/////////////////////////////////////////////////////////////////////////// +#endif \ No newline at end of file diff --git a/r5dev/cpp.hint b/r5dev/cpp.hint index 15955c79..d5cc5ff0 100644 --- a/r5dev/cpp.hint +++ b/r5dev/cpp.hint @@ -7,3 +7,4 @@ #define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) #define IM_FMTARGS(FMT) __attribute__((format(gnu_printf, FMT, FMT+1))) #define IM_FMTARGS(FMT) +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, __VA_ARGS__) friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } diff --git a/r5dev/networksystem/net_structs.h b/r5dev/networksystem/net_structs.h index 4eea81cf..367c63ce 100644 --- a/r5dev/networksystem/net_structs.h +++ b/r5dev/networksystem/net_structs.h @@ -78,7 +78,8 @@ namespace R5Net { SUCCESS, FORBIDDEN, NOT_FOUND, - MS_ERROR + MS_ERROR, + UNKNOWN }; @@ -108,7 +109,9 @@ namespace R5Net { struct UpdateGameServerMSResponse : DefaultMSResponse { + NetGameServer gameServer; + NLOHMANN_DEFINE_TYPE_INTRUSIVE(UpdateGameServerMSResponse, gameServer) }; struct GetIsUserBannedMSResponse : DefaultMSResponse diff --git a/r5dev/networksystem/r5net.h b/r5dev/networksystem/r5net.h index cbc70115..d0741a73 100644 --- a/r5dev/networksystem/r5net.h +++ b/r5dev/networksystem/r5net.h @@ -5,25 +5,97 @@ namespace R5Net { -#define R5NET_GET_ENDPOINT(FuncName, Route, ResponseStructType) ResponseStructType FuncName() {\ +#define R5NET_GET_ENDPOINT(FuncName, Route, ResponseStructType)\ +ResponseStructType FuncName() {\ ResponseStructType result{};\ httplib::Result response = HttpClient.Get(Route);\ if(response == nullptr) return result;\ + switch(response->status)\ + {\ + case 403:\ + {\ + result.status = EResponseStatus::FORBIDDEN;\ + break;\ + }\ + case 404:\ + {\ + result.status = EResponseStatus::NOT_FOUND;\ + break;\ + }\ + case 500:\ + {\ + result.status = EResponseStatus::MS_ERROR;\ + break;\ + }\ + case 200:\ + {\ + result.status = EResponseStatus::SUCCESS;\ + break;\ + }\ + default: \ + {\ + result.status = EResponseStatus::UNKNOWN;\ + break;\ + }\ + }\ nlohmann::json response_body = nlohmann::json::parse(response->body);\ - nlohmann::to_json(response_body, result);\ + from_json(response_body, result);\ return result;\ }\ +\ +void FuncName##_Async(std::function Callback) {\ + std::thread t([&]() {\ + Callback(FuncName());\ + });\ + t.detach();\ +}\ -#define R5NET_POST_ENDPOINT(FuncName, Route, RequestStructType, ResponseStructType) ResponseStructType FuncName(RequestStructType& request) {\ +#define R5NET_POST_ENDPOINT(FuncName, Route, RequestStructType, ResponseStructType)\ + ResponseStructType FuncName(const RequestStructType& request) {\ ResponseStructType result{};\ nlohmann::json request_body;\ - nlohmann::to_json(request_body, request);\ + to_json(request_body, request);\ httplib::Result response = HttpClient.Post(Route, request_body.dump(), "application/json");\ if (response == nullptr) return result;\ + switch(response->status)\ + {\ + case 403:\ + {\ + result.status = EResponseStatus::FORBIDDEN;\ + break;\ + }\ + case 404:\ + {\ + result.status = EResponseStatus::NOT_FOUND;\ + break;\ + }\ + case 500:\ + {\ + result.status = EResponseStatus::MS_ERROR;\ + break;\ + }\ + case 200:\ + {\ + result.status = EResponseStatus::SUCCESS;\ + break;\ + }\ + default: \ + {\ + result.status = EResponseStatus::UNKNOWN;\ + break;\ + }\ + }\ nlohmann::json response_body = nlohmann::json::parse(response->body);\ - nlohmann::to_json(response_body, result);\ + from_json(response_body, result);\ return result;\ -} +}\ +\ +void FuncName##_Async(const RequestStructType& request, std::function Callback) {\ + std::thread t([&]() {\ + Callback(FuncName(request));\ + });\ + t.detach();\ +}\ class Client @@ -41,8 +113,8 @@ namespace R5Net R5NET_GET_ENDPOINT(GetGameServersList, "/api/game_servers/list", GetGameServersListMSResponse) R5NET_POST_ENDPOINT(UpdateMyGameServer, "/api/game_servers/update", UpdateGameServerMSRequest, UpdateGameServerMSResponse) - R5NET_POST_ENDPOINT(GetClientIsBanned, "/api/ban_system/is_user_banned", GetIsUserBannedMSRequest, GetIsUserBannedMSResponse) R5NET_POST_ENDPOINT(GetPrivateGameServerInfo, "/api/game_servers/game_server_private_info", GetPrivateGameServerInfoMSRequest, GetPrivateGameServerInfoMSResponse) + R5NET_POST_ENDPOINT(GetClientIsBanned, "/api/ban_system/is_user_banned", GetIsUserBannedMSRequest, GetIsUserBannedMSResponse) diff --git a/r5dev/public/include/json.hpp b/r5dev/public/include/json.hpp index cbe69ef4..1556fba2 100644 --- a/r5dev/public/include/json.hpp +++ b/r5dev/public/include/json.hpp @@ -2483,7 +2483,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; -#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM(v1) try { nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); } catch(...) {} /*! @brief macro diff --git a/r5dev/r5dev.vcxproj b/r5dev/r5dev.vcxproj index 3bd3fb18..2cd5b4ee 100644 --- a/r5dev/r5dev.vcxproj +++ b/r5dev/r5dev.vcxproj @@ -40,6 +40,7 @@ + @@ -131,6 +132,7 @@ + diff --git a/r5dev/r5dev.vcxproj.filters b/r5dev/r5dev.vcxproj.filters index d6f8246a..23bee5a2 100644 --- a/r5dev/r5dev.vcxproj.filters +++ b/r5dev/r5dev.vcxproj.filters @@ -300,6 +300,9 @@ sdk\engine + + sdk\gameui + @@ -833,6 +836,9 @@ sdk\networksystem + + sdk\gameui + diff --git a/r5dev/windows/id3dx.cpp b/r5dev/windows/id3dx.cpp index aac2490e..57be2920 100644 --- a/r5dev/windows/id3dx.cpp +++ b/r5dev/windows/id3dx.cpp @@ -9,6 +9,7 @@ #include "engine/sys_utils.h" #include "inputsystem/inputsystem.h" #include "public/include/stb_image.h" +#include /********************************************************************************** ----------------------------------------------------------------------------------- @@ -279,6 +280,11 @@ void DrawImGui() g_pInputSystem->EnableInput(false); // Disable input to game when console is drawn. DrawConsole(&bShowConsole); } + if (g_bShowBrowser) + { + g_pInputSystem->EnableInput(false); + DrawDevPalette(&bShowBrowser); + } if (!g_bShowConsole && !g_bShowBrowser) { g_pInputSystem->EnableInput(true); // Enable input to game when both are not drawn. From 09a8d8b12ddfa8b7959ee1e79a37e87dace2c370 Mon Sep 17 00:00:00 2001 From: Alex <18037145+salcodes1@users.noreply.github.com> Date: Wed, 19 Jan 2022 22:03:43 +0200 Subject: [PATCH 6/6] Initial pylon integration --- r5dev/IDevPalette.h | 9 +- r5dev/engine/host_state.cpp | 58 +++++++--- r5dev/gameui/IBrowser.cpp | 164 +++++++++++++++++++++++++++ r5dev/gameui/IBrowser.h | 69 +++++++++++ r5dev/networksystem/net_structs.h | 2 + r5dev/networksystem/r5net.cpp | 4 + r5dev/networksystem/r5net.h | 2 + r5dev/r5dev.vcxproj | 3 + r5dev/r5dev.vcxproj.filters | 11 ++ r5dev/squirrel/sqnativefunctions.cpp | 68 ++++++++--- r5dev/squirrel/sqnativefunctions.h | 3 + r5dev/squirrel/sqvm.cpp | 6 +- r5dev/windows/id3dx.cpp | 3 +- 13 files changed, 363 insertions(+), 39 deletions(-) create mode 100644 r5dev/gameui/IBrowser.cpp create mode 100644 r5dev/gameui/IBrowser.h diff --git a/r5dev/IDevPalette.h b/r5dev/IDevPalette.h index 4ea4dc7c..0fce209a 100644 --- a/r5dev/IDevPalette.h +++ b/r5dev/IDevPalette.h @@ -28,12 +28,12 @@ public: { case R5Net::EResponseStatus::SUCCESS: { - g_GameConsole->AddLog("SUCCESS: %d players, %d servers", response.noPlayers, response.noServers); + g_pIConsole->AddLog("SUCCESS: %d players, %d servers", response.noPlayers, response.noServers); break; } default: { - g_GameConsole->AddLog("ERROR: %s", response.error.c_str()); + g_pIConsole->AddLog("ERROR: %s", response.error.c_str()); } } } @@ -50,18 +50,17 @@ public: { case R5Net::EResponseStatus::SUCCESS: { - g_GameConsole->AddLog("SUCCESS: %s", response.gameServer.name.c_str()); + g_pIConsole->AddLog("SUCCESS: %s", response.gameServer.name.c_str()); break; } default: { - g_GameConsole->AddLog("ERROR: %s", response.error.c_str()); + g_pIConsole->AddLog("ERROR: %s", response.error.c_str()); } } } if (*bDraw == NULL) { - g_bShowBrowser = false; } ImGui::End(); } diff --git a/r5dev/engine/host_state.cpp b/r5dev/engine/host_state.cpp index 468f3333..b91fd0b4 100644 --- a/r5dev/engine/host_state.cpp +++ b/r5dev/engine/host_state.cpp @@ -9,6 +9,25 @@ #include "squirrel/sqinit.h" #include "public/include/bansystem.h" + + + +inline int GetLocalPlayersNum() +{ + int currPlayers = 0; + for (int i = 0; i < MAX_PLAYERS; i++) + { + CClient* client = g_pClient->GetClientInstance(i); // Get client instance. + if (client) + { + if (client->GetNetChan()) + currPlayers++; + } + } + return currPlayers; +} + + //----------------------------------------------------------------------------- // Purpose: Send keep alive request to Pylon Master Server. // NOTE: When Pylon update reaches indev remove this and implement properly. @@ -20,27 +39,28 @@ void KeepAliveToPylon() std::string m_szHostToken = std::string(); std::string m_szHostRequestMessage = std::string(); DevMsg(eDLL_T::CLIENT, "Sending PostServerHost request\n"); - bool result = g_pR5net->PostServerHost(m_szHostRequestMessage, m_szHostToken, - ServerListing{ - g_pCVar->FindVar("hostname")->GetString(), - std::string(g_pHostState->m_levelName), - "", - g_pCVar->FindVar("hostport")->GetString(), - g_pCVar->FindVar("mp_gamemode")->GetString(), - false, - // BUG BUG: Checksum is null on dedi - // ADDITIONAL NOTES: seems to be related to scripts, this also happens when the listen server is started but the client from the same process never connects. - // Checksum only gets set on the server if the client from its own process connects to it. - std::to_string(*g_nRemoteFunctionCallsChecksum), - std::string(), - g_szNetKey.c_str() - } - ); + R5Net::UpdateGameServerMSRequest Request; + + Request.gameServer = *(R5Net::LocalServer); + + if(Request.gameServer.name.empty()) + Request.gameServer.name = g_pCVar->FindVar("hostname")->GetString(); + + Request.gameServer.mapName = std::string(g_pHostState->m_levelName); + sscanf_s(g_pCVar->FindVar("hostport")->GetString(), "%d", &Request.gameServer.gamePort); + Request.gameServer.playlist = g_pCVar->FindVar("mp_gamemode")->GetString(); + Request.gameServer.remoteChecksum = std::to_string(*g_nRemoteFunctionCallsChecksum); + Request.gameServer.encryptionKey = g_szNetKey.c_str(); + Request.gameServer.playerCount = GetLocalPlayersNum(); + Request.gameServer.maxPlayerCount = MAX_PLAYERS; // TODO: replace with actual max_players + + auto Response = g_pR5net->UpdateMyGameServer(Request); + + } } - //----------------------------------------------------------------------------- // Purpose: Check refuse list and kill netchan connection. //----------------------------------------------------------------------------- @@ -164,6 +184,8 @@ void HCHostState_FrameUpdate(void* rcx, void* rdx, float time) } }); + PylonThread.detach(); + static std::thread BanlistThread([]() { while (true) @@ -173,6 +195,8 @@ void HCHostState_FrameUpdate(void* rcx, void* rdx, float time) } }); + BanlistThread.detach(); + if (net_userandomkey->GetBool()) { HNET_GenerateKey(); diff --git a/r5dev/gameui/IBrowser.cpp b/r5dev/gameui/IBrowser.cpp new file mode 100644 index 00000000..00a4d7c6 --- /dev/null +++ b/r5dev/gameui/IBrowser.cpp @@ -0,0 +1,164 @@ +/****************************************************************************** +------------------------------------------------------------------------------- +File : IBrowser.cpp +Date : 09:06:2021 +Author : Sal +Purpose: Implements the in-game server browser front-end +------------------------------------------------------------------------------- +History: +- 09:06:2021 21:07 : Created by Sal +- 25:07:2021 14:26 : Implement private servers connect dialog and password field + +******************************************************************************/ + +#include "core/stdafx.h" +#include "core/init.h" +#include "core/resource.h" +#include "tier0/IConVar.h" +#include "tier0/cvar.h" +#include "tier0/completion.h" +#include "windows/id3dx.h" +#include "windows/console.h" +#include "engine/net_chan.h" +#include "engine/sys_utils.h" +#include "engine/host_state.h" +#include "server/server.h" +#include "client/IVEngineClient.h" +#include "networksystem/net_structs.h" +#include "networksystem/r5net.h" +#include "vpc/keyvalues.h" +#include "squirrel/sqinit.h" +#include "gameui/IBrowser.h" +#include "squirrel/sqapi.h" + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +IBrowser::IBrowser() +{ + + std::string path = "stbsp"; + for (const auto& entry : std::filesystem::directory_iterator(path)) + { + std::string filename = entry.path().string(); + int slashPos = filename.rfind("\\", std::string::npos); + filename = filename.substr(static_cast, std::allocator>::size_type>(slashPos) + 1, std::string::npos); + filename = filename.substr(0, filename.size() - 6); + + auto it = mapArray.find(filename); // Find MapName in mapArray. + if (it != mapArray.end()) + { + m_vszMapsList.push_back(it->second); + } + else + { + m_vszMapsList.push_back(filename); + } + m_vszMapFileNameList.push_back(filename); + } + +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +IBrowser::~IBrowser() +{ + //delete r5net; +} + + +//----------------------------------------------------------------------------- +// Purpose: get server list from pylon. +//----------------------------------------------------------------------------- +void IBrowser::GetServerList() +{ + auto Response = g_pR5net->GetGameServersList(); + m_vServerList.clear(); + m_vServerList.insert(m_vServerList.end(), Response.publicServers.begin(), Response.publicServers.end()); + m_vServerList.insert(m_vServerList.end(), Response.privateServers.begin(), Response.privateServers.end()); +} + +//----------------------------------------------------------------------------- +// Purpose: connects to specified server +//----------------------------------------------------------------------------- +void IBrowser::ConnectToServer(const std::string& ip, const int port, const std::string& encKey) +{ + if (!encKey.empty()) + { + ChangeEncryptionKeyTo(encKey); + } + + std::stringstream cmd; + cmd << "connect " << ip << ":" << port; + ProcessCommand(cmd.str().c_str()); +} + +//----------------------------------------------------------------------------- +// Purpose: connects to specified server +//----------------------------------------------------------------------------- +void IBrowser::ConnectToServer(const std::string& connString, const std::string& encKey) +{ + if (!encKey.empty()) + { + ChangeEncryptionKeyTo(encKey); + } + + std::stringstream cmd; + cmd << "connect " << connString; + ProcessCommand(cmd.str().c_str()); +} + +//----------------------------------------------------------------------------- +// Purpose: Launch server with given parameters +//----------------------------------------------------------------------------- +void IBrowser::LaunchServer() +{ + DevMsg(eDLL_T::ENGINE, "Starting Server with name '%s', map '%s' and playlist '%s'\n", R5Net::LocalServer->name.c_str(), R5Net::LocalServer->mapName.c_str(), R5Net::LocalServer->playlist.c_str()); + + /* + * Playlist gets parsed in two instances, first in LoadPlaylist all the neccessary values. + * Then when you would normally call launchplaylist which calls StartPlaylist it would cmd call mp_gamemode which parses the gamemode specific part of the playlist.. + */ + KeyValues_LoadPlaylist(R5Net::LocalServer->playlist.c_str()); + std::stringstream cgmd; + cgmd << "mp_gamemode " << R5Net::LocalServer->playlist; + ProcessCommand(cgmd.str().c_str()); + + // This is to avoid a race condition. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + std::stringstream cmd; + cmd << "map " << R5Net::LocalServer->mapName; + ProcessCommand(cmd.str().c_str()); +} + +//----------------------------------------------------------------------------- +// Purpose: executes submitted commands in a separate thread +//----------------------------------------------------------------------------- +void IBrowser::ProcessCommand(const char* command_line) +{ + std::thread t(IVEngineClient_CommandExecute, this, command_line); + t.detach(); // Detach from render thread. + + // This is to avoid a race condition. + std::this_thread::sleep_for(std::chrono::milliseconds(1)); +} + +//----------------------------------------------------------------------------- +// Purpose: regenerates encryption key +//----------------------------------------------------------------------------- +void IBrowser::RegenerateEncryptionKey() +{ + HNET_GenerateKey(); +} + +//----------------------------------------------------------------------------- +// Purpose: changes encryption key to specified one +//----------------------------------------------------------------------------- +void IBrowser::ChangeEncryptionKeyTo(const std::string& str) +{ + HNET_SetKey(str); +} + +IBrowser* g_pIBrowser = new IBrowser(); \ No newline at end of file diff --git a/r5dev/gameui/IBrowser.h b/r5dev/gameui/IBrowser.h new file mode 100644 index 00000000..88cf6370 --- /dev/null +++ b/r5dev/gameui/IBrowser.h @@ -0,0 +1,69 @@ +#pragma once +#ifndef DEDICATED +#include "networksystem/net_structs.h" +#include "networksystem/r5net.h" + + +class IBrowser +{ +private: + bool m_bInitialized = false; +public: +public: + //////////////////// + // Funcs // + //////////////////// + IBrowser(); + ~IBrowser(); + + + void GetServerList(); + + void ConnectToServer(const std::string& ip, const int port, const std::string& encKey); + void ConnectToServer(const std::string& connString, const std::string& encKey); + + + void ProcessCommand(const char* command_line); + void LaunchServer(); + + void RegenerateEncryptionKey(); + void ChangeEncryptionKeyTo(const std::string& str); + + + //////////////////// + // Server Browser // + //////////////////// +public: + bool m_bActivate = false; + + std::vector m_vServerList; + ImGuiTextFilter m_imServerBrowserFilter; + std::string m_szServerListMessage = std::string(); + + std::map mapArray = + { + { "mp_rr_canyonlands_64k_x_64k", "King's Canyon Season 0" }, + { "mp_rr_desertlands_64k_x_64k", "World's Edge Season 3" }, + { "mp_rr_canyonlands_mu1", "King's Canyon Season 2" }, + { "mp_rr_canyonlands_mu1_night", "King's Canyon Season 2 After Dark" }, + { "mp_rr_desertlands_64k_x_64k_nx", "World's Edge Season 3 After Dark" }, + { "mp_lobby", "Lobby Season 3" }, + { "mp_rr_canyonlands_staging", "King's Canyon Firing Range" } + }; + + //////////////////// + // Settings // + //////////////////// + std::string m_szMatchmakingHostName; + + //////////////////// + // Host Server // + //////////////////// + std::vector m_vszMapsList; + std::vector m_vszMapFileNameList; + + +}; + +extern IBrowser* g_pIBrowser; +#endif \ No newline at end of file diff --git a/r5dev/networksystem/net_structs.h b/r5dev/networksystem/net_structs.h index 367c63ce..d1e17c5e 100644 --- a/r5dev/networksystem/net_structs.h +++ b/r5dev/networksystem/net_structs.h @@ -1,3 +1,5 @@ +#include "core/stdafx.h" + #pragma once namespace R5Net { diff --git a/r5dev/networksystem/r5net.cpp b/r5dev/networksystem/r5net.cpp index 8dea0311..0f018915 100644 --- a/r5dev/networksystem/r5net.cpp +++ b/r5dev/networksystem/r5net.cpp @@ -4,4 +4,8 @@ #include "core/stdafx.h" #include +namespace R5Net +{ + NetGameServer* LocalServer = new R5Net::NetGameServer{}; +} R5Net::Client* g_pR5net = new R5Net::Client("127.0.0.1:3000"); diff --git a/r5dev/networksystem/r5net.h b/r5dev/networksystem/r5net.h index d0741a73..b6a63652 100644 --- a/r5dev/networksystem/r5net.h +++ b/r5dev/networksystem/r5net.h @@ -119,6 +119,8 @@ void FuncName##_Async(const RequestStructType& request, std::function + @@ -234,6 +235,7 @@ + @@ -248,6 +250,7 @@ + diff --git a/r5dev/r5dev.vcxproj.filters b/r5dev/r5dev.vcxproj.filters index 07d9a8b5..3ccb7aff 100644 --- a/r5dev/r5dev.vcxproj.filters +++ b/r5dev/r5dev.vcxproj.filters @@ -405,6 +405,10 @@ sdk\squirrel + + + sdk\gameui + @@ -1043,6 +1047,13 @@ sdk\squirrel + + + sdk\networksystem + + + sdk\gameui + diff --git a/r5dev/squirrel/sqnativefunctions.cpp b/r5dev/squirrel/sqnativefunctions.cpp index 7c24f9cc..a85d5c89 100644 --- a/r5dev/squirrel/sqnativefunctions.cpp +++ b/r5dev/squirrel/sqnativefunctions.cpp @@ -3,6 +3,7 @@ #include "engine/sys_utils.h" #include "gameui/IBrowser.h" +#include namespace SQNativeFunctions { @@ -15,7 +16,17 @@ namespace SQNativeFunctions SQRESULT GetServerName(void* sqvm) { int svIndex = hsq_getinteger(sqvm, 1); - std::string szSvName = g_pIBrowser->m_vServerList[svIndex].svServerName; + std::string szSvName = g_pIBrowser->m_vServerList[svIndex].name; + + hsq_pushstring(sqvm, szSvName.c_str(), -1); + + return SQ_OK; + } + + SQRESULT GetServerDescription(void* sqvm) + { + int svIndex = hsq_getinteger(sqvm, 1); + std::string szSvName = g_pIBrowser->m_vServerList[svIndex].description; hsq_pushstring(sqvm, szSvName.c_str(), -1); @@ -28,7 +39,7 @@ namespace SQNativeFunctions SQRESULT GetServerPlaylist(void* sqvm) { int svIndex = hsq_getinteger(sqvm, 1); - std::string szSvPlaylist = g_pIBrowser->m_vServerList[svIndex].svPlaylist; + std::string szSvPlaylist = g_pIBrowser->m_vServerList[svIndex].playlist; hsq_pushstring(sqvm, szSvPlaylist.c_str(), -1); @@ -41,13 +52,33 @@ namespace SQNativeFunctions SQRESULT GetServerMap(void* sqvm) { int svIndex = hsq_getinteger(sqvm, 1); - std::string szSvMapName = g_pIBrowser->m_vServerList[svIndex].svMapName; + std::string szSvMapName = g_pIBrowser->m_vServerList[svIndex].mapName; hsq_pushstring(sqvm, szSvMapName.c_str(), -1); return SQ_OK; } + SQRESULT GetServerPlayersNum(void* sqvm) + { + int svIndex = hsq_getinteger(sqvm, 1); + int szSvPlayersNum = g_pIBrowser->m_vServerList[svIndex].playerCount; + + hsq_pushinteger(sqvm, szSvPlayersNum); + + return SQ_OK; + } + + SQRESULT GetServerMaxPlayersNum(void* sqvm) + { + int svIndex = hsq_getinteger(sqvm, 1); + int szSvMaxPlayersNum = g_pIBrowser->m_vServerList[svIndex].maxPlayerCount; + + hsq_pushinteger(sqvm, szSvMaxPlayersNum); + + return SQ_OK; + } + //---------------------------------------------------------------------------- // Purpose: get current server count from pylon //----------------------------------------------------------------------------- @@ -65,7 +96,7 @@ namespace SQNativeFunctions //----------------------------------------------------------------------------- SQRESULT GetSDKVersion(void* sqvm) { - hsq_pushstring(sqvm, g_pR5net->GetSDKVersion().c_str(), -1); + hsq_pushstring(sqvm, /*g_pR5net->GetSDKVersion().c_str()*/ "TEMP TEMP!!", -1); return SQ_OK; } @@ -140,7 +171,7 @@ namespace SQNativeFunctions { int svIndex = hsq_getinteger(sqvm, 1); - g_pIBrowser->ConnectToServer(g_pIBrowser->m_vServerList[svIndex].svIpAddress, g_pIBrowser->m_vServerList[svIndex].svPort, g_pIBrowser->m_vServerList[svIndex].svEncryptionKey); + g_pIBrowser->ConnectToServer(g_pIBrowser->m_vServerList[svIndex].ipAddress, g_pIBrowser->m_vServerList[svIndex].gamePort, g_pIBrowser->m_vServerList[svIndex].encryptionKey); return SQ_OK; } @@ -150,19 +181,24 @@ namespace SQNativeFunctions //----------------------------------------------------------------------------- SQRESULT CreateServerFromMenu(void* sqvm) { - std::string szSvName = hsq_getstring(sqvm, 1); - std::string szSvMapName = hsq_getstring(sqvm, 2); - std::string szSvPlaylist = hsq_getstring(sqvm, 3); - EServerVisibility eSvVisibility = (EServerVisibility)hsq_getinteger(sqvm, 4); + std::string szSvName = hsq_getstring(sqvm, 1); + std::string szSvDescription = hsq_getstring(sqvm, 2); + std::string szSvMapName = hsq_getstring(sqvm, 3); + std::string szSvPlaylist = hsq_getstring(sqvm, 4); + std::string szSvPassword = hsq_getstring(sqvm, 5); + + // Visibility got deprecated in favor of a password system. + //EServerVisibility eSvVisibility = (EServerVisibility)hsq_getinteger(sqvm, 4); if (szSvName.empty() || szSvMapName.empty() || szSvPlaylist.empty()) return SQ_OK; // Adjust browser settings. - g_pIBrowser->m_Server.svPlaylist = szSvPlaylist; - g_pIBrowser->m_Server.svMapName = szSvMapName; - g_pIBrowser->m_Server.svServerName = szSvName; - g_pIBrowser->eServerVisibility = eSvVisibility; + R5Net::LocalServer->playlist = szSvPlaylist; + R5Net::LocalServer->mapName = szSvMapName; + R5Net::LocalServer->name = szSvName; + R5Net::LocalServer->description = szSvDescription; + R5Net::LocalServer->password = szSvPassword; // Launch server. g_pIBrowser->LaunchServer(); @@ -175,7 +211,7 @@ namespace SQNativeFunctions //----------------------------------------------------------------------------- SQRESULT JoinPrivateServerFromMenu(void* sqvm) { - std::string szHiddenServerRequestMessage = std::string(); + /*std::string szHiddenServerRequestMessage = std::string(); std::string szToken = hsq_getstring(sqvm, 1); @@ -186,6 +222,7 @@ namespace SQNativeFunctions g_pIBrowser->ConnectToServer(svListing.svIpAddress, svListing.svPort, svListing.svEncryptionKey); } + return SQ_OK;*/ return SQ_OK; } @@ -194,7 +231,7 @@ namespace SQNativeFunctions //----------------------------------------------------------------------------- SQRESULT GetPrivateServerMessage(void* sqvm) { - std::string szHiddenServerRequestMessage = std::string(); + /*std::string szHiddenServerRequestMessage = std::string(); std::string szToken = hsq_getstring(sqvm, 1); @@ -215,6 +252,7 @@ namespace SQNativeFunctions DevMsg(eDLL_T::UI, "GetPrivateServeMessage response: %s\n", szHiddenServerRequestMessage.c_str()); + return SQ_OK;*/ return SQ_OK; } diff --git a/r5dev/squirrel/sqnativefunctions.h b/r5dev/squirrel/sqnativefunctions.h index 273f2e44..2feaa311 100644 --- a/r5dev/squirrel/sqnativefunctions.h +++ b/r5dev/squirrel/sqnativefunctions.h @@ -6,8 +6,11 @@ namespace SQNativeFunctions namespace IBrowser { SQRESULT GetServerName(void* sqvm); + SQRESULT GetServerDescription(void* sqvm); SQRESULT GetServerPlaylist(void* sqvm); SQRESULT GetServerMap(void* sqvm); + SQRESULT GetServerPlayersNum(void* sqvm); + SQRESULT GetServerMaxPlayersNum(void* sqvm); SQRESULT GetServerCount(void* sqvm); SQRESULT GetSDKVersion(void* sqvm); SQRESULT GetPromoData(void* sqvm); diff --git a/r5dev/squirrel/sqvm.cpp b/r5dev/squirrel/sqvm.cpp index cb009f6d..af866980 100644 --- a/r5dev/squirrel/sqvm.cpp +++ b/r5dev/squirrel/sqvm.cpp @@ -253,16 +253,20 @@ void RegisterUIScriptFunctions(void* sqvm) // functions for retrieving server browser data HSQVM_RegisterFunction(sqvm, "GetServerName", "get name of the server at the specified index of the server list", "string", "int", &SQNativeFunctions::IBrowser::GetServerName); + HSQVM_RegisterFunction(sqvm, "GetServerDescription", "get description of the server at the specified index of the server list", "string", "int", &SQNativeFunctions::IBrowser::GetServerDescription); HSQVM_RegisterFunction(sqvm, "GetServerPlaylist", "get playlist of the server at the specified index of the server list", "string", "int", &SQNativeFunctions::IBrowser::GetServerPlaylist); HSQVM_RegisterFunction(sqvm, "GetServerMap", "get map of the server at the specified index of the server list", "string", "int", &SQNativeFunctions::IBrowser::GetServerMap); + HSQVM_RegisterFunction(sqvm, "GetServerPlayersNum", "get num of connected players of the server at the specified index of the server list", "int", "int", &SQNativeFunctions::IBrowser::GetServerPlayersNum); + HSQVM_RegisterFunction(sqvm, "GetServerMaxPlayersNum", "get num of max players of the server at the specified index of the server list", "int", "int", &SQNativeFunctions::IBrowser::GetServerMaxPlayersNum); HSQVM_RegisterFunction(sqvm, "GetServerCount", "get number of public servers", "int", "", &SQNativeFunctions::IBrowser::GetServerCount); + // misc main menu functions HSQVM_RegisterFunction(sqvm, "GetSDKVersion", "get sdk version as a string", "string", "", &SQNativeFunctions::IBrowser::GetSDKVersion); HSQVM_RegisterFunction(sqvm, "GetPromoData", "get promo data for specified slot type", "string", "int", &SQNativeFunctions::IBrowser::GetPromoData); // functions for connecting to servers - HSQVM_RegisterFunction(sqvm, "CreateServer", "start server with the specified settings", "void", "string,string,string,int", &SQNativeFunctions::IBrowser::CreateServerFromMenu); + HSQVM_RegisterFunction(sqvm, "CreateServer", "start server with the specified settings", "void", "string,string,string,string,string", &SQNativeFunctions::IBrowser::CreateServerFromMenu); HSQVM_RegisterFunction(sqvm, "SetEncKeyAndConnect", "set the encryption key to that of the specified server and connects to it", "void", "int", &SQNativeFunctions::IBrowser::SetEncKeyAndConnect); HSQVM_RegisterFunction(sqvm, "JoinPrivateServerFromMenu", "join private server by token", "void", "string", &SQNativeFunctions::IBrowser::JoinPrivateServerFromMenu); HSQVM_RegisterFunction(sqvm, "GetPrivateServerMessage", "get private server join status message", "string", "string", &SQNativeFunctions::IBrowser::GetPrivateServerMessage); diff --git a/r5dev/windows/id3dx.cpp b/r5dev/windows/id3dx.cpp index b8d7a66e..515e1577 100644 --- a/r5dev/windows/id3dx.cpp +++ b/r5dev/windows/id3dx.cpp @@ -10,6 +10,7 @@ #include "inputsystem/inputsystem.h" #include "public/include/stb_image.h" #include +#include /********************************************************************************** ----------------------------------------------------------------------------------- @@ -274,7 +275,7 @@ void DrawImGui() if (g_pIBrowser->m_bActivate) { g_pInputSystem->EnableInput(false); // Disable input to game when browser is drawn. - g_pIBrowser->Draw("Server Browser", &g_pIBrowser->m_bActivate); + //g_pIBrowser->Draw("Server Browser", &g_pIBrowser->m_bActivate); } if (g_pIConsole->m_bActivate) {