2022-01-12 02:53:07 +01:00
/******************************************************************************
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-12-25 22:36:38 +01:00
# include "core/stdafx.h"
# include "core/init.h"
# include "core/resource.h"
2022-01-18 11:23:14 +01:00
# include "tier0/commandline.h"
2022-04-09 16:16:40 +02:00
# include "tier1/IConVar.h"
# include "tier1/cvar.h"
2021-12-25 22:36:38 +01:00
# include "windows/id3dx.h"
# include "windows/console.h"
2022-04-26 20:24:51 +02:00
# include "windows/resource.h"
2022-04-02 02:48:54 +02:00
# include "engine/net.h"
2022-05-27 02:08:51 +02:00
# include "engine/cmodel_bsp.h"
2021-12-25 22:36:38 +01:00
# include "engine/host_state.h"
2022-05-20 20:14:39 +02:00
# ifndef CLIENT_DLL
2022-05-20 11:52:19 +02:00
# include "engine/server/server.h"
2022-05-20 20:14:39 +02:00
# endif // CLIENT_DLL
2021-12-25 22:36:38 +01:00
# include "networksystem/serverlisting.h"
# include "networksystem/r5net.h"
# include "squirrel/sqinit.h"
2022-01-15 15:25:19 +01:00
# include "squirrel/sqapi.h"
2022-04-02 12:27:35 +02:00
# include "client/vengineclient_impl.h"
2022-03-04 12:22:17 +01:00
# include "vpc/keyvalues.h"
2022-05-16 21:15:25 +02:00
# include "vstdlib/callback.h"
2022-03-04 12:22:17 +01:00
# include "vpklib/packedstore.h"
# include "gameui/IBrowser.h"
2022-06-28 00:47:01 +02:00
# include "public/include/edict.h"
2021-12-25 22:36:38 +01:00
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
CBrowser : : CBrowser ( void )
2021-12-25 22:36:38 +01:00
{
2022-05-27 02:39:08 +02:00
memset ( m_szServerAddressBuffer , ' \0 ' , sizeof ( m_szServerAddressBuffer ) ) ;
2022-03-27 22:17:30 +02:00
# ifndef CLIENT_DLL
2021-12-25 22:36:38 +01:00
static std : : thread hostingServerRequestThread ( [ this ] ( )
{
while ( true )
{
UpdateHostingStatus ( ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5000 ) ) ;
}
} ) ;
hostingServerRequestThread . detach ( ) ;
2022-06-09 02:22:01 +02:00
std : : thread think ( & CBrowser : : Think , this ) ;
think . detach ( ) ;
2022-03-27 22:17:30 +02:00
# endif // !CLIENT_DLL
2022-06-09 02:22:01 +02:00
m_pszBrowserTitle = " Server Browser " ;
2022-04-26 20:24:51 +02:00
m_rLockedIconBlob = GetModuleResource ( IDB_PNG2 ) ;
2021-12-25 22:36:38 +01:00
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
CBrowser : : ~ CBrowser ( void )
2021-12-25 22:36:38 +01:00
{
//delete r5net;
}
//-----------------------------------------------------------------------------
2022-01-12 02:53:07 +01:00
// Purpose: draws the main browser front-end
2021-12-25 22:36:38 +01:00
//-----------------------------------------------------------------------------
2022-06-09 02:22:01 +02:00
void CBrowser : : Draw ( void )
2021-12-25 22:36:38 +01:00
{
2022-01-12 02:53:07 +01:00
if ( ! m_bInitialized )
2021-12-25 22:36:38 +01:00
{
2022-01-12 02:53:07 +01:00
SetStyleVar ( ) ;
m_szMatchmakingHostName = r5net_matchmaking_hostname - > GetString ( ) ;
m_bInitialized = true ;
2021-12-25 22:36:38 +01:00
}
2022-01-28 12:56:51 +01:00
{
//ImGui::ShowStyleEditor();
//ImGui::ShowDemoWindow();
}
2022-06-09 02:22:01 +02:00
int nVars = 0 ;
2022-06-24 12:22:04 +02:00
ImGui : : PushStyleVar ( ImGuiStyleVar_Alpha , m_flFadeAlpha ) ; nVars + + ;
2022-06-27 16:54:40 +02:00
ImGui : : PushStyleVar ( ImGuiStyleVar_WindowMinSize , ImVec2 ( 750 , 524 ) ) ; nVars + + ;
2022-06-24 12:22:04 +02:00
2022-06-24 12:45:47 +02:00
if ( ! m_bModernTheme )
{
ImGui : : PushStyleVar ( ImGuiStyleVar_ChildBorderSize , 1.0f ) ; nVars + + ;
}
2022-06-27 16:54:40 +02:00
if ( ! ImGui : : Begin ( m_pszBrowserTitle , & m_bActivate , ImGuiWindowFlags_NoScrollbar ) )
2021-12-25 22:36:38 +01:00
{
2022-01-12 02:53:07 +01:00
ImGui : : End ( ) ;
2022-06-09 02:22:01 +02:00
ImGui : : PopStyleVar ( nVars ) ;
2022-01-12 02:53:07 +01:00
return ;
}
2022-06-27 16:54:40 +02:00
BasePanel ( ) ;
2022-01-12 02:53:07 +01:00
ImGui : : End ( ) ;
2022-06-09 02:22:01 +02:00
ImGui : : PopStyleVar ( nVars ) ;
}
//-----------------------------------------------------------------------------
// Purpose: runs tasks for the browser while not being drawn
//-----------------------------------------------------------------------------
void CBrowser : : Think ( void )
{
for ( ; ; ) // Loop running at 100-tps.
{
if ( m_bActivate )
{
if ( m_flFadeAlpha < = 1.f )
{
m_flFadeAlpha + = 0.05 ;
}
}
else // Reset to full transparent.
{
m_flFadeAlpha = 0.f ;
}
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 10 ) ) ;
}
2021-12-25 22:36:38 +01:00
}
//-----------------------------------------------------------------------------
// Purpose: draws the compmenu
//-----------------------------------------------------------------------------
2022-06-27 15:01:39 +02:00
void CBrowser : : BasePanel ( void )
2021-12-25 22:36:38 +01:00
{
ImGui : : BeginTabBar ( " CompMenu " ) ;
2022-06-27 16:54:40 +02:00
if ( ImGui : : BeginTabItem ( " Browsing " ) )
2021-12-25 22:36:38 +01:00
{
2022-06-27 15:01:39 +02:00
BrowserPanel ( ) ;
ImGui : : EndTabItem ( ) ;
2021-12-25 22:36:38 +01:00
}
2022-03-27 22:17:30 +02:00
# ifndef CLIENT_DLL
2022-06-27 16:54:40 +02:00
if ( ImGui : : BeginTabItem ( " Hosting " ) )
2021-12-25 22:36:38 +01:00
{
2022-06-27 15:01:39 +02:00
HostPanel ( ) ;
ImGui : : EndTabItem ( ) ;
2021-12-25 22:36:38 +01:00
}
2022-03-27 22:17:30 +02:00
# endif // !CLIENT_DLL
2022-06-27 15:01:39 +02:00
if ( ImGui : : BeginTabItem ( " Settings " ) )
2021-12-25 22:36:38 +01:00
{
2022-06-27 15:01:39 +02:00
SettingsPanel ( ) ;
ImGui : : EndTabItem ( ) ;
2021-12-25 22:36:38 +01:00
}
ImGui : : EndTabBar ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: draws the server browser section
//-----------------------------------------------------------------------------
2022-06-27 15:01:39 +02:00
void CBrowser : : BrowserPanel ( void )
2021-12-25 22:36:38 +01:00
{
ImGui : : BeginGroup ( ) ;
m_imServerBrowserFilter . Draw ( ) ;
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Refresh List " ) )
{
RefreshServerList ( ) ;
}
ImGui : : EndGroup ( ) ;
2022-05-27 02:39:08 +02:00
ImGui : : TextColored ( ImVec4 ( 1.00f , 0.00f , 0.00f , 1.00f ) , m_svServerListMessage . c_str ( ) ) ;
2021-12-25 22:36:38 +01:00
ImGui : : Separator ( ) ;
2022-03-04 12:22:17 +01:00
const float fFooterHeight = ImGui : : GetStyle ( ) . ItemSpacing . y + ImGui : : GetFrameHeightWithSpacing ( ) ;
2022-05-08 16:20:48 +02:00
ImGui : : BeginChild ( " ##ServerBrowser_ServerList " , { 0 , - fFooterHeight } , true , ImGuiWindowFlags_AlwaysVerticalScrollbar ) ;
2022-01-22 15:51:09 +01:00
2022-06-09 02:22:01 +02:00
int nVars = 0 ;
2022-06-24 12:22:04 +02:00
if ( m_bModernTheme )
2022-06-09 02:22:01 +02:00
{
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 { 8.f , 0.f } ) ; nVars + + ;
}
else
{
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 4.f , 0.f ) ) ; nVars + + ;
}
2022-01-28 12:56:51 +01:00
2022-05-08 16:20:48 +02:00
if ( ImGui : : BeginTable ( " ##ServerBrowser_ServerListTable " , 5 , ImGuiTableFlags_Resizable ) )
2021-12-25 22:36:38 +01:00
{
2022-01-22 15:51:09 +01:00
ImGui : : TableSetupColumn ( " Name " , ImGuiTableColumnFlags_WidthStretch , 25 ) ;
ImGui : : TableSetupColumn ( " Map " , ImGuiTableColumnFlags_WidthStretch , 20 ) ;
ImGui : : TableSetupColumn ( " Playlist " , ImGuiTableColumnFlags_WidthStretch , 10 ) ;
2022-06-27 16:54:40 +02:00
ImGui : : TableSetupColumn ( " Players " , ImGuiTableColumnFlags_WidthStretch , 5 ) ;
ImGui : : TableSetupColumn ( " Port " , ImGuiTableColumnFlags_WidthStretch , 5 ) ;
2021-12-25 22:36:38 +01:00
ImGui : : TableHeadersRow ( ) ;
2022-06-27 16:54:40 +02:00
for ( NetGameServer_t & server : m_vServerList )
2021-12-25 22:36:38 +01:00
{
2022-06-28 00:47:01 +02:00
const char * pszHostName = server . m_svHostName . c_str ( ) ;
const char * pszHostMap = server . m_svMapName . c_str ( ) ;
const char * pszPlaylist = server . m_svPlaylist . c_str ( ) ;
const char * pszHostPort = std : : to_string ( server . m_nGamePort ) . c_str ( ) ;
const char * pszPlayers = std : : to_string ( server . m_nPlayerCount ) . c_str ( ) ;
2022-03-04 12:22:17 +01:00
if ( m_imServerBrowserFilter . PassFilter ( pszHostName )
| | m_imServerBrowserFilter . PassFilter ( pszHostMap )
| | m_imServerBrowserFilter . PassFilter ( pszHostPort ) )
2021-12-25 22:36:38 +01:00
{
ImGui : : TableNextColumn ( ) ;
2022-03-04 12:22:17 +01:00
ImGui : : Text ( pszHostName ) ;
2021-12-25 22:36:38 +01:00
ImGui : : TableNextColumn ( ) ;
2022-03-04 12:22:17 +01:00
ImGui : : Text ( pszHostMap ) ;
2021-12-25 22:36:38 +01:00
2022-06-27 16:54:40 +02:00
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( pszPlaylist ) ;
2021-12-25 22:36:38 +01:00
ImGui : : TableNextColumn ( ) ;
2022-03-04 12:22:17 +01:00
ImGui : : Text ( pszHostPort ) ;
2021-12-25 22:36:38 +01:00
ImGui : : TableNextColumn ( ) ;
2022-06-27 16:54:40 +02:00
ImGui : : Text ( pszPlayers ) ;
2021-12-25 22:36:38 +01:00
ImGui : : TableNextColumn ( ) ;
2022-05-27 02:39:08 +02:00
string svConnectBtn = " Connect## " ;
2022-06-28 00:47:01 +02:00
svConnectBtn . append ( server . m_svHostName + server . m_svIpAddress + server . m_svMapName ) ;
2021-12-25 22:36:38 +01:00
2022-03-04 12:22:17 +01:00
if ( ImGui : : Button ( svConnectBtn . c_str ( ) ) )
2021-12-25 22:36:38 +01:00
{
2022-06-28 00:47:01 +02:00
ConnectToServer ( server . m_svIpAddress , pszHostPort , server . m_svEncryptionKey ) ;
2021-12-25 22:36:38 +01:00
}
}
}
2022-06-09 02:22:01 +02:00
ImGui : : PopStyleVar ( nVars ) ;
2021-12-25 22:36:38 +01:00
ImGui : : EndTable ( ) ;
}
ImGui : : EndChild ( ) ;
ImGui : : Separator ( ) ;
ImGui : : PushItemWidth ( ImGui : : GetWindowContentRegionWidth ( ) / 4 ) ;
{
2022-05-27 02:39:08 +02:00
ImGui : : InputTextWithHint ( " ##ServerBrowser_ServerConnString " , " Enter IP address or \" localhost \" " , m_szServerAddressBuffer , IM_ARRAYSIZE ( m_szServerAddressBuffer ) ) ;
2021-12-25 22:36:38 +01:00
ImGui : : SameLine ( ) ;
2022-05-27 02:39:08 +02:00
ImGui : : InputTextWithHint ( " ##ServerBrowser_ServerEncKey " , " Enter encryption key " , m_szServerEncKeyBuffer , IM_ARRAYSIZE ( m_szServerEncKeyBuffer ) ) ;
2021-12-25 22:36:38 +01:00
ImGui : : SameLine ( ) ;
2022-06-27 14:48:03 +02:00
if ( ImGui : : Button ( " Connect " , ImVec2 ( ImGui : : GetWindowContentRegionWidth ( ) / 4.3 , ImGui : : GetFrameHeight ( ) ) ) )
2021-12-25 22:36:38 +01:00
{
2022-05-27 02:39:08 +02:00
ConnectToServer ( m_szServerAddressBuffer , m_szServerEncKeyBuffer ) ;
2021-12-25 22:36:38 +01:00
}
ImGui : : SameLine ( ) ;
2022-06-27 14:48:03 +02:00
if ( ImGui : : Button ( " Private Servers " , ImVec2 ( ImGui : : GetWindowContentRegionWidth ( ) / 4.3 , ImGui : : GetFrameHeight ( ) ) ) )
2021-12-25 22:36:38 +01:00
{
2022-05-08 16:20:48 +02:00
ImGui : : OpenPopup ( " Connect to Private Server " ) ;
2021-12-25 22:36:38 +01:00
}
HiddenServersModal ( ) ;
}
ImGui : : PopItemWidth ( ) ;
}
2022-01-12 02:53:07 +01:00
//-----------------------------------------------------------------------------
// Purpose: refreshes the server browser list with available servers
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
void CBrowser : : RefreshServerList ( void )
2022-01-12 02:53:07 +01:00
{
static bool bThreadLocked = false ;
m_vServerList . clear ( ) ;
2022-05-27 02:39:08 +02:00
m_svServerListMessage . clear ( ) ;
2022-01-12 02:53:07 +01:00
if ( ! bThreadLocked )
{
std : : thread t ( [ this ] ( )
{
DevMsg ( eDLL_T : : CLIENT , " Refreshing server list with matchmaking host '%s' \n " , r5net_matchmaking_hostname - > GetString ( ) ) ;
bThreadLocked = true ;
2022-05-27 02:39:08 +02:00
m_vServerList = g_pR5net - > GetServersList ( m_svServerListMessage ) ;
2022-01-12 02:53:07 +01:00
bThreadLocked = false ;
} ) ;
t . detach ( ) ;
}
}
2022-01-15 15:25:19 +01:00
//-----------------------------------------------------------------------------
// Purpose: get server list from pylon.
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
void CBrowser : : GetServerList ( void )
2022-01-15 15:25:19 +01:00
{
m_vServerList . clear ( ) ;
2022-05-27 02:39:08 +02:00
m_svServerListMessage . clear ( ) ;
m_vServerList = g_pR5net - > GetServersList ( m_svServerListMessage ) ;
2022-01-15 15:25:19 +01:00
}
2022-01-12 02:53:07 +01:00
//-----------------------------------------------------------------------------
// Purpose: connects to specified server
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
void CBrowser : : ConnectToServer ( const string & svIp , const string & svPort , const string & svNetKey )
2022-01-12 02:53:07 +01:00
{
2022-03-04 12:22:17 +01:00
if ( ! svNetKey . empty ( ) )
2022-01-12 02:53:07 +01:00
{
2022-06-24 12:22:04 +02:00
ChangeEncryptionKey ( svNetKey ) ;
2022-01-12 02:53:07 +01:00
}
2022-05-27 02:39:08 +02:00
stringstream ssCommand ;
ssCommand < < " connect " < < svIp < < " : " < < svPort ;
ProcessCommand ( ssCommand . str ( ) . c_str ( ) ) ;
2022-01-12 02:53:07 +01:00
}
//-----------------------------------------------------------------------------
// Purpose: connects to specified server
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
void CBrowser : : ConnectToServer ( const string & svServer , const string & svNetKey )
2022-01-12 02:53:07 +01:00
{
2022-03-04 12:22:17 +01:00
if ( ! svNetKey . empty ( ) )
2022-01-12 02:53:07 +01:00
{
2022-06-24 12:22:04 +02:00
ChangeEncryptionKey ( svNetKey ) ;
2022-01-12 02:53:07 +01:00
}
2022-05-27 02:39:08 +02:00
stringstream ssCommand ;
ssCommand < < " connect " < < svServer ;
ProcessCommand ( ssCommand . str ( ) . c_str ( ) ) ;
2022-01-12 02:53:07 +01:00
}
2022-01-15 15:25:19 +01:00
//-----------------------------------------------------------------------------
2022-01-15 20:13:11 +01:00
// Purpose: Launch server with given parameters
2022-01-15 15:25:19 +01:00
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
void CBrowser : : LaunchServer ( void )
2022-01-15 15:25:19 +01:00
{
2022-03-27 22:17:30 +02:00
# ifndef CLIENT_DLL
2022-06-28 00:47:01 +02:00
DevMsg ( eDLL_T : : ENGINE , " Starting server with name: \" %s \" map: \" %s \" playlist: \" %s \" \n " , m_Server . m_svHostName . c_str ( ) , m_Server . m_svMapName . c_str ( ) , m_Server . m_svPlaylist . c_str ( ) ) ;
2022-01-15 20:13:11 +01:00
/*
2022-05-28 17:07:30 +02:00
* Playlist gets parsed in two instances , first in KeyValues : : ParsePlaylists with all the neccessary values .
2022-01-15 20:13:11 +01:00
* 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 . .
*/
2022-06-28 00:47:01 +02:00
KeyValues : : ParsePlaylists ( m_Server . m_svPlaylist . c_str ( ) ) ;
2022-05-27 02:39:08 +02:00
stringstream ssModeCommand ;
2022-06-28 00:47:01 +02:00
ssModeCommand < < " mp_gamemode " < < m_Server . m_svPlaylist ;
2022-05-27 02:39:08 +02:00
ProcessCommand ( ssModeCommand . str ( ) . c_str ( ) ) ;
2022-01-15 20:13:11 +01:00
// This is to avoid a race condition.
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 100 ) ) ;
2022-05-27 02:39:08 +02:00
stringstream ssMapCommand ;
2022-06-28 00:47:01 +02:00
ssMapCommand < < " map " < < m_Server . m_svMapName ;
2022-05-27 02:39:08 +02:00
ProcessCommand ( ssMapCommand . str ( ) . c_str ( ) ) ;
2022-03-27 22:17:30 +02:00
# endif // !CLIENT_DLL
2022-01-15 15:25:19 +01:00
}
2021-12-25 22:36:38 +01:00
//-----------------------------------------------------------------------------
// Purpose: draws the hidden private server modal
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
void CBrowser : : HiddenServersModal ( void )
2021-12-25 22:36:38 +01:00
{
bool modalOpen = true ;
2022-05-08 16:28:20 +02:00
if ( ImGui : : BeginPopupModal ( " Connect to Private Server " , & modalOpen ) )
2021-12-25 22:36:38 +01:00
{
ImGui : : SetWindowSize ( ImVec2 ( 400.f , 200.f ) , ImGuiCond_Always ) ;
if ( ! m_idLockedIcon )
{
2022-04-26 20:24:51 +02:00
bool ret = LoadTextureBuffer ( reinterpret_cast < unsigned char * > ( m_rLockedIconBlob . m_pData ) , static_cast < int > ( m_rLockedIconBlob . m_nSize ) ,
& m_idLockedIcon , & m_rLockedIconBlob . m_nWidth , & m_rLockedIconBlob . m_nHeight ) ;
2021-12-25 22:36:38 +01:00
IM_ASSERT ( ret ) ;
}
ImGui : : PushStyleColor ( ImGuiCol_ChildBg , ImVec4 ( 0.00f , 0.00f , 0.00f , 0.00f ) ) ; // Override the style color for child bg.
2022-04-26 20:24:51 +02:00
ImGui : : BeginChild ( " ##HiddenServersConnectModal_IconParent " , ImVec2 ( m_rLockedIconBlob . m_nWidth , m_rLockedIconBlob . m_nHeight ) ) ;
ImGui : : Image ( m_idLockedIcon , ImVec2 ( m_rLockedIconBlob . m_nWidth , m_rLockedIconBlob . m_nHeight ) ) ; // Display texture.
2021-12-25 22:36:38 +01:00
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.
2022-05-27 02:39:08 +02:00
ImGui : : InputTextWithHint ( " ##HiddenServersConnectModal_TokenInput " , " Token " , & m_svHiddenServerToken ) ;
2021-12-25 22:36:38 +01:00
ImGui : : PopItemWidth ( ) ;
ImGui : : Dummy ( ImVec2 ( ImGui : : GetWindowContentRegionWidth ( ) , 19.f ) ) ; // Place a dummy, basically making space inserting a blank element.
2022-05-27 02:39:08 +02:00
ImGui : : TextColored ( m_ivHiddenServerMessageColor , m_svHiddenServerRequestMessage . c_str ( ) ) ;
2021-12-25 22:36:38 +01:00
ImGui : : Separator ( ) ;
2022-05-08 16:20:48 +02:00
if ( ImGui : : Button ( " Connect " , ImVec2 ( ImGui : : GetWindowContentRegionWidth ( ) / 2 , 24 ) ) )
2021-12-25 22:36:38 +01:00
{
2022-05-27 02:39:08 +02:00
m_svHiddenServerRequestMessage . clear ( ) ;
2022-06-27 16:54:40 +02:00
NetGameServer_t server ;
2022-05-27 02:39:08 +02:00
bool result = g_pR5net - > GetServerByToken ( server , m_svHiddenServerRequestMessage , m_svHiddenServerToken ) ; // Send token connect request.
2022-06-28 00:47:01 +02:00
if ( ! server . m_svHostName . empty ( ) )
2021-12-25 22:36:38 +01:00
{
2022-06-28 00:47:01 +02:00
ConnectToServer ( server . m_svIpAddress , std : : to_string ( server . m_nGamePort ) , server . m_svEncryptionKey ) ; // Connect to the server
m_svHiddenServerRequestMessage = " Found Server: " + server . m_svHostName ;
2021-12-25 22:36:38 +01:00
m_ivHiddenServerMessageColor = ImVec4 ( 0.00f , 1.00f , 0.00f , 1.00f ) ;
ImGui : : CloseCurrentPopup ( ) ;
}
else
{
2022-05-27 02:39:08 +02:00
m_svHiddenServerRequestMessage = " Error: " + m_svHiddenServerRequestMessage ;
2021-12-25 22:36:38 +01:00
m_ivHiddenServerMessageColor = ImVec4 ( 1.00f , 0.00f , 0.00f , 1.00f ) ;
}
}
ImGui : : SameLine ( ) ;
2022-05-08 16:20:48 +02:00
if ( ImGui : : Button ( " Close " , ImVec2 ( ImGui : : GetWindowContentRegionWidth ( ) / 2 , 24 ) ) )
2021-12-25 22:36:38 +01:00
{
ImGui : : CloseCurrentPopup ( ) ;
}
ImGui : : EndPopup ( ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: draws the host section
//-----------------------------------------------------------------------------
2022-06-27 15:01:39 +02:00
void CBrowser : : HostPanel ( void )
2021-12-25 22:36:38 +01:00
{
2022-03-27 22:17:30 +02:00
# ifndef CLIENT_DLL
2022-05-27 02:39:08 +02:00
static string svServerNameErr = " " ;
2021-12-25 22:36:38 +01:00
2022-06-28 00:47:01 +02:00
ImGui : : InputTextWithHint ( " ##ServerHost_ServerName " , " Server Name (Required) " , & m_Server . m_svHostName ) ;
2021-12-25 22:36:38 +01:00
ImGui : : Spacing ( ) ;
2022-06-28 00:47:01 +02:00
if ( ImGui : : BeginCombo ( " Playlist " , m_Server . m_svPlaylist . c_str ( ) ) )
2021-12-25 22:36:38 +01:00
{
2022-05-27 02:08:51 +02:00
for ( auto & item : g_vAllPlaylists )
2021-12-25 22:36:38 +01:00
{
2022-06-28 00:47:01 +02:00
if ( ImGui : : Selectable ( item . c_str ( ) , item = = m_Server . m_svPlaylist ) )
2021-12-25 22:36:38 +01:00
{
2022-06-28 00:47:01 +02:00
m_Server . m_svPlaylist = item ;
2021-12-25 22:36:38 +01:00
}
}
ImGui : : EndCombo ( ) ;
}
2022-06-28 00:47:01 +02:00
if ( ImGui : : BeginCombo ( " Map##ServerHost_MapListBox " , m_Server . m_svMapName . c_str ( ) ) )
2021-12-25 22:36:38 +01:00
{
2022-05-27 02:08:51 +02:00
for ( auto & item : g_vAllMaps )
2021-12-25 22:36:38 +01:00
{
2022-06-28 00:47:01 +02:00
if ( ImGui : : Selectable ( item . c_str ( ) , item = = m_Server . m_svMapName ) )
2021-12-25 22:36:38 +01:00
{
2022-06-28 00:47:01 +02:00
m_Server . m_svMapName = item ;
2021-12-25 22:36:38 +01:00
}
}
ImGui : : EndCombo ( ) ;
}
2022-05-08 16:20:48 +02:00
ImGui : : Checkbox ( " Load Global Ban List " , & g_bCheckCompBanDB ) ;
2021-12-25 22:36:38 +01:00
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " Server Visiblity " ) ;
2022-05-08 16:20:48 +02:00
if ( ImGui : : SameLine ( ) ; ImGui : : RadioButton ( " Offline " , eServerVisibility = = EServerVisibility : : OFFLINE ) )
2021-12-25 22:36:38 +01:00
{
eServerVisibility = EServerVisibility : : OFFLINE ;
}
2022-05-08 16:20:48 +02:00
if ( ImGui : : SameLine ( ) ; ImGui : : RadioButton ( " Hidden " , eServerVisibility = = EServerVisibility : : HIDDEN ) )
2021-12-25 22:36:38 +01:00
{
eServerVisibility = EServerVisibility : : HIDDEN ;
}
2022-05-08 16:20:48 +02:00
if ( ImGui : : SameLine ( ) ; ImGui : : RadioButton ( " Public " , eServerVisibility = = EServerVisibility : : PUBLIC ) )
2021-12-25 22:36:38 +01:00
{
eServerVisibility = EServerVisibility : : PUBLIC ;
}
ImGui : : Spacing ( ) ;
ImGui : : Separator ( ) ;
if ( ! g_pHostState - > m_bActiveGame )
{
2022-05-08 16:20:48 +02:00
if ( ImGui : : Button ( " Start Server " , ImVec2 ( ImGui : : GetWindowSize ( ) . x , 32 ) ) )
2021-12-25 22:36:38 +01:00
{
2022-03-04 12:22:17 +01:00
svServerNameErr . clear ( ) ;
2022-06-28 00:47:01 +02:00
if ( ! m_Server . m_svHostName . empty ( ) & & ! m_Server . m_svPlaylist . empty ( ) & & ! m_Server . m_svMapName . empty ( ) )
2021-12-25 22:36:38 +01:00
{
2022-01-15 20:13:11 +01:00
LaunchServer ( ) ; // Launch server.
UpdateHostingStatus ( ) ; // Update hosting status.
2021-12-25 22:36:38 +01:00
}
else
{
2022-06-28 00:47:01 +02:00
if ( m_Server . m_svHostName . empty ( ) )
2021-12-25 22:36:38 +01:00
{
2022-06-27 14:48:03 +02:00
svServerNameErr = " No server name assigned. " ;
2021-12-25 22:36:38 +01:00
}
2022-06-28 00:47:01 +02:00
else if ( m_Server . m_svPlaylist . empty ( ) )
2021-12-25 22:36:38 +01:00
{
2022-06-27 14:48:03 +02:00
svServerNameErr = " No playlist assigned. " ;
2021-12-25 22:36:38 +01:00
}
2022-06-28 00:47:01 +02:00
else if ( m_Server . m_svMapName . empty ( ) )
2021-12-25 22:36:38 +01:00
{
2022-06-27 14:48:03 +02:00
svServerNameErr = " No level name assigned. " ;
2021-12-25 22:36:38 +01:00
}
}
}
}
2022-05-08 16:20:48 +02:00
if ( ImGui : : Button ( " Force Start " , ImVec2 ( ImGui : : GetWindowSize ( ) . x , 32 ) ) )
2021-12-25 22:36:38 +01:00
{
2022-03-04 12:22:17 +01:00
svServerNameErr . clear ( ) ;
2022-06-28 00:47:01 +02:00
if ( ! m_Server . m_svPlaylist . empty ( ) & & ! m_Server . m_svMapName . empty ( ) )
2021-12-25 22:36:38 +01:00
{
2022-01-15 20:13:11 +01:00
LaunchServer ( ) ; // Launch server.
UpdateHostingStatus ( ) ; // Update hosting status.
2021-12-25 22:36:38 +01:00
}
else
{
2022-06-28 00:47:01 +02:00
if ( m_Server . m_svPlaylist . empty ( ) )
2021-12-25 22:36:38 +01:00
{
2022-06-27 14:48:03 +02:00
svServerNameErr = " No playlist assigned. " ;
2021-12-25 22:36:38 +01:00
}
2022-06-28 00:47:01 +02:00
else if ( m_Server . m_svMapName . empty ( ) )
2021-12-25 22:36:38 +01:00
{
2022-06-27 14:48:03 +02:00
svServerNameErr = " No level name assigned. " ;
2021-12-25 22:36:38 +01:00
}
}
}
2022-03-04 12:22:17 +01:00
ImGui : : TextColored ( ImVec4 ( 1.00f , 0.00f , 0.00f , 1.00f ) , svServerNameErr . c_str ( ) ) ;
2022-06-27 16:54:40 +02:00
ImGui : : TextColored ( m_HostRequestMessageColor , m_svHostRequestMessage . c_str ( ) ) ;
2022-05-27 02:39:08 +02:00
if ( ! m_svHostToken . empty ( ) )
2021-12-25 22:36:38 +01:00
{
2022-05-27 02:39:08 +02:00
ImGui : : InputText ( " ##ServerHost_HostToken " , & m_svHostToken , ImGuiInputTextFlags_ReadOnly ) ;
2021-12-25 22:36:38 +01:00
}
if ( g_pHostState - > m_bActiveGame )
{
2022-05-08 16:20:48 +02:00
if ( ImGui : : Button ( " Weapon Reparse " , ImVec2 ( ImGui : : GetWindowSize ( ) . x , 32 ) ) )
2021-12-25 22:36:38 +01:00
{
2022-05-08 16:20:48 +02:00
DevMsg ( eDLL_T : : ENGINE , " Reparsing weapon data on %s \n " , " server and client " ) ;
2022-04-08 23:03:09 +02:00
ProcessCommand ( " weapon_reparse " ) ;
2021-12-25 22:36:38 +01:00
ProcessCommand ( " reload " ) ;
}
2022-05-08 16:20:48 +02:00
if ( ImGui : : Button ( " Change Level " , ImVec2 ( ImGui : : GetWindowSize ( ) . x , 32 ) ) )
2021-12-25 22:36:38 +01:00
{
2022-06-28 00:47:01 +02:00
if ( ! m_Server . m_svMapName . empty ( ) )
2021-12-25 22:36:38 +01:00
{
2022-06-28 00:47:01 +02:00
strncpy_s ( g_pHostState - > m_levelName , m_Server . m_svMapName . c_str ( ) , 64 ) ; // Copy new map into hoststate levelname. 64 is size of m_levelname.
2021-12-25 22:36:38 +01:00
g_pHostState - > m_iNextState = HostStates_t : : HS_CHANGE_LEVEL_MP ; // Force CHostState::FrameUpdate to change the level.
}
else
{
2022-03-04 12:22:17 +01:00
svServerNameErr = " Failed to change level: 'levelname' was empty. " ;
2021-12-25 22:36:38 +01:00
}
}
2022-05-08 16:20:48 +02:00
if ( ImGui : : Button ( " Stop Server " , ImVec2 ( ImGui : : GetWindowSize ( ) . x , 32 ) ) )
2021-12-25 22:36:38 +01:00
{
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
{
2022-05-08 16:20:48 +02:00
if ( ImGui : : Button ( " Reload Playlist " , ImVec2 ( ImGui : : GetWindowSize ( ) . x , 32 ) ) )
2021-12-25 22:36:38 +01:00
{
2022-05-16 21:15:25 +02:00
_DownloadPlaylists_f ( ) ;
2022-05-28 02:05:54 +02:00
KeyValues : : InitPlaylists ( ) ; // Re-Init playlist.
2021-12-25 22:36:38 +01:00
}
}
2022-03-27 22:17:30 +02:00
# endif // !CLIENT_DLL
2021-12-25 22:36:38 +01:00
}
//-----------------------------------------------------------------------------
2022-01-12 02:53:07 +01:00
// Purpose: updates the hoster's status
2021-12-25 22:36:38 +01:00
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
void CBrowser : : UpdateHostingStatus ( void )
2021-12-25 22:36:38 +01:00
{
2022-03-27 22:17:30 +02:00
# ifndef CLIENT_DLL
2022-01-12 02:53:07 +01:00
if ( ! g_pHostState | | ! g_pCVar )
2021-12-25 22:36:38 +01:00
{
return ;
}
2021-12-26 02:30:20 +01:00
2022-03-04 12:22:17 +01:00
eHostingStatus = g_pHostState - > m_bActiveGame ? eHostStatus : : HOSTING : eHostStatus : : NOT_HOSTING ; // Are we hosting a server?
2022-01-12 02:53:07 +01:00
switch ( eHostingStatus )
{
2022-03-04 12:22:17 +01:00
case eHostStatus : : NOT_HOSTING :
2021-12-25 22:36:38 +01:00
{
2022-05-27 02:39:08 +02:00
m_svHostRequestMessage . clear ( ) ;
2022-06-27 16:54:40 +02:00
m_HostRequestMessageColor = ImVec4 ( 1.00f , 1.00f , 1.00f , 1.00f ) ;
2022-01-12 02:53:07 +01:00
break ;
2021-12-25 22:36:38 +01:00
}
2022-03-04 12:22:17 +01:00
case eHostStatus : : HOSTING :
2021-12-25 22:36:38 +01:00
{
2022-01-12 02:53:07 +01:00
if ( eServerVisibility = = EServerVisibility : : OFFLINE )
{
break ;
}
2021-12-25 22:36:38 +01:00
2022-01-20 16:04:10 +01:00
if ( * g_nClientRemoteChecksum = = NULL ) // Check if script checksum is valid yet.
2021-12-25 22:36:38 +01:00
{
break ;
2022-01-12 02:53:07 +01:00
}
switch ( eServerVisibility )
{
case EServerVisibility : : HIDDEN :
2022-06-28 00:47:01 +02:00
m_Server . m_bHidden = true ;
2021-12-25 22:36:38 +01:00
break ;
2022-01-12 02:53:07 +01:00
case EServerVisibility : : PUBLIC :
2022-06-28 00:47:01 +02:00
m_Server . m_bHidden = false ;
2021-12-25 22:36:38 +01:00
break ;
default :
break ;
}
2022-01-12 02:53:07 +01:00
SendHostingPostRequest ( ) ;
break ;
}
default :
break ;
}
2022-03-27 22:17:30 +02:00
# endif // !CLIENT_DLL
2022-01-12 02:53:07 +01:00
}
//-----------------------------------------------------------------------------
// Purpose: sends the hosting POST request to the comp server
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
void CBrowser : : SendHostingPostRequest ( void )
2022-01-12 02:53:07 +01:00
{
2022-03-27 22:17:30 +02:00
# ifndef CLIENT_DLL
2022-05-27 02:39:08 +02:00
m_svHostToken . clear ( ) ;
bool result = g_pR5net - > PostServerHost ( m_svHostRequestMessage , m_svHostToken ,
2022-06-27 16:54:40 +02:00
NetGameServer_t
2022-03-04 12:22:17 +01:00
{
2022-06-28 00:47:01 +02:00
m_Server . m_svHostName . c_str ( ) ,
" " , // description.
" " , // password.
m_Server . m_bHidden ,
g_pHostState - > m_levelName ,
2022-03-26 18:06:54 +01:00
mp_gamemode - > GetString ( ) ,
2022-06-28 00:47:01 +02:00
hostip - > GetString ( ) ,
hostport - > GetInt ( ) ,
g_svNetKey . c_str ( ) ,
std : : to_string ( * g_nServerRemoteChecksum ) ,
SDK_VERSION ,
" " ,
g_pServer - > GetNumHumanPlayers ( ) + g_pServer - > GetNumFakeClients ( ) ,
g_ServerGlobalVariables - > m_nMaxClients
2022-01-12 02:53:07 +01:00
}
) ;
if ( result )
{
2022-06-27 16:54:40 +02:00
m_HostRequestMessageColor = ImVec4 ( 0.00f , 1.00f , 0.00f , 1.00f ) ;
2022-05-27 02:39:08 +02:00
stringstream ssMessage ;
ssMessage < < " Broadcasting! " ;
if ( ! m_svHostToken . empty ( ) )
2022-01-12 02:53:07 +01:00
{
2022-05-27 02:39:08 +02:00
ssMessage < < " Share the following token for clients to connect: " ;
2022-01-12 02:53:07 +01:00
}
2022-05-27 02:39:08 +02:00
m_svHostRequestMessage = ssMessage . str ( ) . c_str ( ) ;
DevMsg ( eDLL_T : : CLIENT , " PostServerHost replied with: %s \n " , m_svHostRequestMessage . c_str ( ) ) ;
2022-01-12 02:53:07 +01:00
}
else
{
2022-06-27 16:54:40 +02:00
m_HostRequestMessageColor = ImVec4 ( 1.00f , 0.00f , 0.00f , 1.00f ) ;
2021-12-25 22:36:38 +01:00
}
2022-03-27 22:17:30 +02:00
# endif // !CLIENT_DLL
2021-12-25 22:36:38 +01:00
}
//-----------------------------------------------------------------------------
// Purpose: executes submitted commands in a separate thread
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
void CBrowser : : ProcessCommand ( const char * pszCommand )
2021-12-25 22:36:38 +01:00
{
2022-05-06 00:34:46 +02:00
std : : thread t ( CEngineClient_CommandExecute , this , pszCommand ) ;
2021-12-25 22:36:38 +01:00
t . detach ( ) ; // Detach from render thread.
// This is to avoid a race condition.
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1 ) ) ;
}
//-----------------------------------------------------------------------------
2022-01-12 02:53:07 +01:00
// Purpose: draws the settings section
2021-12-25 22:36:38 +01:00
//-----------------------------------------------------------------------------
2022-06-27 15:01:39 +02:00
void CBrowser : : SettingsPanel ( void )
2021-12-25 22:36:38 +01:00
{
2022-05-08 16:20:48 +02:00
ImGui : : InputTextWithHint ( " Hostname " , " Matchmaking Server String " , & m_szMatchmakingHostName ) ;
2022-01-12 02:53:07 +01:00
if ( ImGui : : Button ( " Update Hostname " ) )
2021-12-25 22:36:38 +01:00
{
2022-01-12 02:53:07 +01:00
r5net_matchmaking_hostname - > SetValue ( m_szMatchmakingHostName . c_str ( ) ) ;
if ( g_pR5net )
{
delete g_pR5net ;
g_pR5net = new R5Net : : Client ( r5net_matchmaking_hostname - > GetString ( ) ) ;
}
2021-12-25 22:36:38 +01:00
}
2022-06-27 16:54:40 +02:00
ImGui : : InputText ( " Netkey " , const_cast < char * > ( g_svNetKey . c_str ( ) ) , ImGuiInputTextFlags_ReadOnly ) ;
2022-05-08 16:20:48 +02:00
if ( ImGui : : Button ( " Regenerate Encryption Key " ) )
2021-12-25 22:36:38 +01:00
{
2022-01-12 02:53:07 +01:00
RegenerateEncryptionKey ( ) ;
2021-12-25 22:36:38 +01:00
}
}
//-----------------------------------------------------------------------------
// Purpose: regenerates encryption key
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
void CBrowser : : RegenerateEncryptionKey ( void ) const
2021-12-25 22:36:38 +01:00
{
2022-04-02 02:48:54 +02:00
NET_GenerateKey ( ) ;
2021-12-25 22:36:38 +01:00
}
//-----------------------------------------------------------------------------
// Purpose: changes encryption key to specified one
//-----------------------------------------------------------------------------
2022-06-24 12:22:04 +02:00
void CBrowser : : ChangeEncryptionKey ( const string & svNetKey ) const
2021-12-25 22:36:38 +01:00
{
2022-04-02 02:48:54 +02:00
NET_SetKey ( svNetKey ) ;
2021-12-25 22:36:38 +01:00
}
2022-01-12 02:53:07 +01:00
//-----------------------------------------------------------------------------
// Purpose: sets the browser front-end style
//-----------------------------------------------------------------------------
2022-05-27 02:44:36 +02:00
void CBrowser : : SetStyleVar ( void )
2021-12-25 22:36:38 +01:00
{
2022-06-27 14:48:03 +02:00
int nStyle = g_pImGuiConfig - > InitStyle ( ) ;
m_bModernTheme = nStyle = = 0 ;
m_bLegacyTheme = nStyle = = 1 ;
m_bDefaultTheme = nStyle = = 2 ;
2022-06-24 12:22:04 +02:00
2022-06-27 14:48:03 +02:00
ImGui : : SetNextWindowSize ( ImVec2 ( 910 , 524 ) , ImGuiCond_FirstUseEver ) ;
2022-06-24 12:22:04 +02:00
ImGui : : SetWindowPos ( ImVec2 ( - 500 , 50 ) , ImGuiCond_FirstUseEver ) ;
2021-12-25 22:36:38 +01:00
}
2022-01-12 02:53:07 +01:00
2022-05-27 02:44:36 +02:00
CBrowser * g_pBrowser = new CBrowser ( ) ;