mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
NetworkSystem: fix numerous issues
This patch splits host logic from CServerListManager. CServerListManager is actually meant for the client to manage the server list to which the client could connect to. The hosting logic has been moved to the new CServerHostManager class. Previously, we stored all the hosting details in CServerListManager, with connection criteria in CPylon, this data has been moved over to CServerHostManager as well. Previously, we also needed a mutex to access the server host data, function HostState_KeepAlive() has been refactored to the point this mutex is no longer necessary as the only threaded process is the actual request, the rest is being applied in the main thread. We also now only construct a NetGameServer_t struct if we actually plan to host. Access to CPylon::m_Language is now also protected by a mutex, as the change callback of cvar 'language' and the threaded method 'CPylon::QueryServer()' are competing for access.
This commit is contained in:
parent
1908efce96
commit
63237361e9
@ -268,8 +268,12 @@ void LanguageChanged_f(IConVar* pConVar, const char* pOldString)
|
||||
// if new text isn't valid but the old value is, reset the value
|
||||
if (Localize_IsLanguageSupported(pOldString))
|
||||
pNewString = pOldString;
|
||||
else // this shouldn't really happen, but if neither the old nor new values are valid, set to english
|
||||
else
|
||||
{
|
||||
// this shouldn't really happen, but if neither the old nor new values are valid, set to english
|
||||
Assert(0);
|
||||
pNewString = g_LanguageNames[0];
|
||||
}
|
||||
}
|
||||
|
||||
pConVarRef->SetValue(pNewString);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "engine/server/server.h"
|
||||
#include "engine/client/client.h"
|
||||
#ifndef CLIENT_DLL
|
||||
#include "networksystem/hostmanager.h"
|
||||
#include "jwt/include/decode.h"
|
||||
#include "mbedtls/include/mbedtls/sha256.h"
|
||||
#endif
|
||||
@ -162,7 +163,7 @@ bool CClient::Authenticate(const char* const playerName, char* const reasonBuf,
|
||||
const int idLen = snprintf(newId, sizeof(newId), "%llu-%s-%s",
|
||||
(NucleusID_t)this->m_DataBlock.userData,
|
||||
playerName,
|
||||
g_MasterServer.GetHostIP().c_str());
|
||||
g_ServerHostManager.GetHostIP().c_str());
|
||||
|
||||
if (idLen < 0)
|
||||
ERROR_AND_RETURN("Session ID stitching failed");
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "tier0/jobthread.h"
|
||||
#include "tier0/commandline.h"
|
||||
#include "tier0/fasttimer.h"
|
||||
#include "tier0/frametask.h"
|
||||
#include "tier1/cvar.h"
|
||||
#include "tier1/NetAdr.h"
|
||||
#include "tier2/socketcreator.h"
|
||||
@ -45,6 +46,7 @@
|
||||
#include "networksystem/pylon.h"
|
||||
#ifndef CLIENT_DLL
|
||||
#include "networksystem/bansystem.h"
|
||||
#include "networksystem/hostmanager.h"
|
||||
#endif // !CLIENT_DLL
|
||||
#include "networksystem/listmanager.h"
|
||||
#include "public/edict.h"
|
||||
@ -53,58 +55,85 @@
|
||||
#endif // !CLIENT_DLL
|
||||
#include "game/shared/vscript_shared.h"
|
||||
|
||||
#ifdef DEDICATED
|
||||
static ConVar hostdesc("hostdesc", "", FCVAR_RELEASE, "Host game server description.");
|
||||
#endif // DEDICATED
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
static ConVar sv_pylonVisibility("sv_pylonVisibility", "0", FCVAR_RELEASE, "Determines the visibility to the Pylon master server.", "0 = Offline, 1 = Hidden, 2 = Public.");
|
||||
static ConVar sv_pylonRefreshRate("sv_pylonRefreshRate", "5.0", FCVAR_DEVELOPMENTONLY, "Pylon host refresh rate (seconds).");
|
||||
|
||||
static ConVar sv_autoReloadRate("sv_autoReloadRate", "0", FCVAR_RELEASE, "Time in seconds between each server auto-reload (disabled if null).");
|
||||
#endif // !CLIENT_DLL
|
||||
|
||||
#ifdef DEDICATED
|
||||
static ConVar hostdesc("hostdesc", "", FCVAR_RELEASE, "Host game server description.");
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Send keep alive request to Pylon Master Server.
|
||||
// Input : &netGameServer -
|
||||
// Output : Returns true on success, false otherwise.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HostState_KeepAlive(const NetGameServer_t& netGameServer)
|
||||
static void HostState_KeepAlive()
|
||||
{
|
||||
if (!g_pServer->IsActive() || !sv_pylonVisibility.GetBool()) // Check for active game.
|
||||
{
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
string errorMsg;
|
||||
string hostToken;
|
||||
string hostIp;
|
||||
|
||||
const bool result = g_MasterServer.PostServerHost(errorMsg, hostToken, hostIp, netGameServer);
|
||||
if (!result)
|
||||
const NetGameServer_t gameServer
|
||||
{
|
||||
if (!errorMsg.empty() && g_MasterServer.GetCurrentError().compare(errorMsg) != NULL)
|
||||
{
|
||||
g_MasterServer.SetCurrentError(errorMsg);
|
||||
Error(eDLL_T::SERVER, NO_ERROR, "%s\n", errorMsg.c_str());
|
||||
}
|
||||
}
|
||||
else // Attempt to log the token, if there is one.
|
||||
{
|
||||
if (!hostToken.empty() && g_MasterServer.GetCurrentToken().compare(hostToken) != NULL)
|
||||
{
|
||||
g_MasterServer.SetCurrentToken(hostToken);
|
||||
Msg(eDLL_T::SERVER, "Published server with token: %s'%s%s%s'\n",
|
||||
g_svReset, g_svGreyB,
|
||||
hostToken.c_str(), g_svReset);
|
||||
}
|
||||
}
|
||||
hostname->GetString(),
|
||||
hostdesc.GetString(),
|
||||
sv_pylonVisibility.GetInt() == ServerVisibility_e::HIDDEN,
|
||||
g_pHostState->m_levelName,
|
||||
v_Playlists_GetCurrent(),
|
||||
hostip->GetString(),
|
||||
hostport->GetInt(),
|
||||
g_pNetKey->GetBase64NetKey(),
|
||||
*g_nServerRemoteChecksum,
|
||||
SDK_VERSION,
|
||||
g_pServer->GetNumClients(),
|
||||
g_ServerGlobalVariables->m_nMaxClients,
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()
|
||||
).count()
|
||||
};
|
||||
|
||||
if (hostIp.length() != 0)
|
||||
g_MasterServer.SetHostIP(hostIp);
|
||||
std::thread request([&, gameServer]
|
||||
{
|
||||
string errorMsg;
|
||||
string hostToken;
|
||||
string hostIp;
|
||||
|
||||
return result;
|
||||
const bool result = g_MasterServer.PostServerHost(errorMsg, hostToken, hostIp, gameServer);
|
||||
|
||||
// Apply the data the next frame
|
||||
g_TaskQueue.Dispatch([result, errorMsg, hostToken, hostIp]
|
||||
{
|
||||
if (!result)
|
||||
{
|
||||
if (!errorMsg.empty() && g_ServerHostManager.GetCurrentError().compare(errorMsg) != NULL)
|
||||
{
|
||||
g_ServerHostManager.SetCurrentError(errorMsg);
|
||||
Error(eDLL_T::SERVER, NO_ERROR, "%s\n", errorMsg.c_str());
|
||||
}
|
||||
}
|
||||
else // Attempt to log the token, if there is one.
|
||||
{
|
||||
if (!hostToken.empty() && g_ServerHostManager.GetCurrentToken().compare(hostToken) != NULL)
|
||||
{
|
||||
g_ServerHostManager.SetCurrentToken(hostToken);
|
||||
Msg(eDLL_T::SERVER, "Published server with token: %s'%s%s%s'\n",
|
||||
g_svReset, g_svGreyB,
|
||||
hostToken.c_str(), g_svReset);
|
||||
}
|
||||
}
|
||||
|
||||
if (hostIp.length() != 0)
|
||||
g_ServerHostManager.SetHostIP(hostIp);
|
||||
|
||||
}, 0);
|
||||
}
|
||||
);
|
||||
|
||||
request.detach();
|
||||
}
|
||||
#endif // !CLIENT_DLL
|
||||
#endif // DEDICATED
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: state machine's main processing loop
|
||||
@ -336,32 +365,13 @@ void CHostState::Think(void) const
|
||||
if (sv_globalBanlist.GetBool() &&
|
||||
banListTimer.GetDurationInProgress().GetSeconds() > sv_banlistRefreshRate.GetFloat())
|
||||
{
|
||||
SV_CheckForBan();
|
||||
SV_CheckClientsForBan();
|
||||
banListTimer.Start();
|
||||
}
|
||||
#ifdef DEDICATED
|
||||
if (pylonTimer.GetDurationInProgress().GetSeconds() > sv_pylonRefreshRate.GetFloat())
|
||||
{
|
||||
const NetGameServer_t netGameServer
|
||||
{
|
||||
hostname->GetString(),
|
||||
hostdesc.GetString(),
|
||||
sv_pylonVisibility.GetInt() == EServerVisibility_t::HIDDEN,
|
||||
g_pHostState->m_levelName,
|
||||
v_Playlists_GetCurrent(),
|
||||
hostip->GetString(),
|
||||
hostport->GetInt(),
|
||||
g_pNetKey->GetBase64NetKey(),
|
||||
*g_nServerRemoteChecksum,
|
||||
SDK_VERSION,
|
||||
g_pServer->GetNumClients(),
|
||||
g_ServerGlobalVariables->m_nMaxClients,
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()
|
||||
).count()
|
||||
};
|
||||
|
||||
std::thread(&HostState_KeepAlive, netGameServer).detach();
|
||||
HostState_KeepAlive();
|
||||
pylonTimer.Start();
|
||||
}
|
||||
#endif // DEDICATED
|
||||
|
@ -83,8 +83,10 @@ namespace VScriptCode
|
||||
SQRESULT RefreshServerList(HSQUIRRELVM v)
|
||||
{
|
||||
string serverMessage; // Refresh list.
|
||||
size_t iCount = g_ServerListManager.RefreshServerList(serverMessage);
|
||||
size_t iCount;
|
||||
|
||||
// TODO: return error string on failure?
|
||||
g_ServerListManager.RefreshServerList(serverMessage, iCount);
|
||||
sq_pushinteger(v, static_cast<SQInteger>(iCount));
|
||||
|
||||
return SQ_OK;
|
||||
@ -157,7 +159,7 @@ namespace VScriptCode
|
||||
//-----------------------------------------------------------------------------
|
||||
SQRESULT GetServerName(HSQUIRRELVM v)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(g_ServerListManager.m_Mutex);
|
||||
AUTO_LOCK(g_ServerListManager.m_Mutex);
|
||||
SQInteger iServer = sq_getinteger(v, 1);
|
||||
|
||||
if (!Script_CheckServerIndex(v, iServer))
|
||||
@ -176,7 +178,7 @@ namespace VScriptCode
|
||||
//-----------------------------------------------------------------------------
|
||||
SQRESULT GetServerDescription(HSQUIRRELVM v)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(g_ServerListManager.m_Mutex);
|
||||
AUTO_LOCK(g_ServerListManager.m_Mutex);
|
||||
SQInteger iServer = sq_getinteger(v, 1);
|
||||
|
||||
if (!Script_CheckServerIndex(v, iServer))
|
||||
@ -195,7 +197,7 @@ namespace VScriptCode
|
||||
//-----------------------------------------------------------------------------
|
||||
SQRESULT GetServerMap(HSQUIRRELVM v)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(g_ServerListManager.m_Mutex);
|
||||
AUTO_LOCK(g_ServerListManager.m_Mutex);
|
||||
SQInteger iServer = sq_getinteger(v, 1);
|
||||
|
||||
if (!Script_CheckServerIndex(v, iServer))
|
||||
@ -214,7 +216,7 @@ namespace VScriptCode
|
||||
//-----------------------------------------------------------------------------
|
||||
SQRESULT GetServerPlaylist(HSQUIRRELVM v)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(g_ServerListManager.m_Mutex);
|
||||
AUTO_LOCK(g_ServerListManager.m_Mutex);
|
||||
SQInteger iServer = sq_getinteger(v, 1);
|
||||
|
||||
if (!Script_CheckServerIndex(v, iServer))
|
||||
@ -233,7 +235,7 @@ namespace VScriptCode
|
||||
//-----------------------------------------------------------------------------
|
||||
SQRESULT GetServerCurrentPlayers(HSQUIRRELVM v)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(g_ServerListManager.m_Mutex);
|
||||
AUTO_LOCK(g_ServerListManager.m_Mutex);
|
||||
SQInteger iServer = sq_getinteger(v, 1);
|
||||
|
||||
if (!Script_CheckServerIndex(v, iServer))
|
||||
@ -252,7 +254,7 @@ namespace VScriptCode
|
||||
//-----------------------------------------------------------------------------
|
||||
SQRESULT GetServerMaxPlayers(HSQUIRRELVM v)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(g_ServerListManager.m_Mutex);
|
||||
AUTO_LOCK(g_ServerListManager.m_Mutex);
|
||||
SQInteger iServer = sq_getinteger(v, 1);
|
||||
|
||||
if (!Script_CheckServerIndex(v, iServer))
|
||||
@ -372,7 +374,7 @@ namespace VScriptCode
|
||||
//-----------------------------------------------------------------------------
|
||||
SQRESULT ConnectToListedServer(HSQUIRRELVM v)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(g_ServerListManager.m_Mutex);
|
||||
AUTO_LOCK(g_ServerListManager.m_Mutex);
|
||||
SQInteger iServer = sq_getinteger(v, 1);
|
||||
|
||||
if (!Script_CheckServerIndex(v, iServer))
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "vscript_server.h"
|
||||
#include <engine/host_state.h>
|
||||
#include <networksystem/listmanager.h>
|
||||
#include <networksystem/hostmanager.h>
|
||||
|
||||
/*
|
||||
=====================
|
||||
@ -51,7 +51,7 @@ namespace VScriptCode
|
||||
SQChar* serverDescription = sq_getstring(v, 2);
|
||||
SQChar* serverMapName = sq_getstring(v, 3);
|
||||
SQChar* serverPlaylist = sq_getstring(v, 4);
|
||||
EServerVisibility_t eServerVisibility = static_cast<EServerVisibility_t>(sq_getinteger(v, 5));
|
||||
ServerVisibility_e serverVisibility = static_cast<ServerVisibility_e>(sq_getinteger(v, 5));
|
||||
|
||||
if (!VALID_CHARSTAR(serverName) ||
|
||||
!VALID_CHARSTAR(serverMapName) ||
|
||||
@ -61,16 +61,16 @@ namespace VScriptCode
|
||||
}
|
||||
|
||||
// Adjust browser settings.
|
||||
std::lock_guard<std::mutex> l(g_ServerListManager.m_Mutex);
|
||||
NetGameServer_t& details = g_ServerHostManager.GetDetails();
|
||||
|
||||
g_ServerListManager.m_Server.name = serverName;
|
||||
g_ServerListManager.m_Server.description = serverDescription;
|
||||
g_ServerListManager.m_Server.map = serverMapName;
|
||||
g_ServerListManager.m_Server.playlist = serverPlaylist;
|
||||
g_ServerListManager.m_ServerVisibility = eServerVisibility;
|
||||
details.name = serverName;
|
||||
details.description = serverDescription;
|
||||
details.map = serverMapName;
|
||||
details.playlist = serverPlaylist;
|
||||
|
||||
// Launch server.
|
||||
g_ServerListManager.LaunchServer(g_pServer->IsActive());
|
||||
g_ServerHostManager.SetVisibility(serverVisibility);
|
||||
g_ServerHostManager.LaunchServer(g_pServer->IsActive());
|
||||
|
||||
return SQ_OK;
|
||||
|
||||
|
@ -30,6 +30,7 @@ History:
|
||||
#include "engine/client/clientstate.h"
|
||||
#include "networksystem/serverlisting.h"
|
||||
#include "networksystem/pylon.h"
|
||||
#include "networksystem/hostmanager.h"
|
||||
#include "networksystem/listmanager.h"
|
||||
#include "rtech/playlists/playlists.h"
|
||||
#include "common/callback.h"
|
||||
@ -256,7 +257,7 @@ void CBrowser::DrawBrowserPanel(void)
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 5);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
g_ServerListManager.m_Mutex.lock();
|
||||
g_ServerListManager.m_Mutex.Lock();
|
||||
vector<const NetGameServer_t*> filteredServers;
|
||||
|
||||
// Filter the server list first before running it over the ImGui list
|
||||
@ -321,7 +322,7 @@ void CBrowser::DrawBrowserPanel(void)
|
||||
}
|
||||
|
||||
filteredServers.clear();
|
||||
g_ServerListManager.m_Mutex.unlock();
|
||||
g_ServerListManager.m_Mutex.Unlock();
|
||||
|
||||
ImGui::EndTable();
|
||||
ImGui::PopStyleVar(frameStyleVars);
|
||||
@ -383,7 +384,8 @@ void CBrowser::RefreshServerList(void)
|
||||
std::thread request([&]
|
||||
{
|
||||
std::string serverListMessage;
|
||||
g_ServerListManager.RefreshServerList(serverListMessage);
|
||||
size_t numServers;
|
||||
g_ServerListManager.RefreshServerList(serverListMessage, numServers);
|
||||
|
||||
g_TaskQueue.Dispatch([&, serverListMessage]
|
||||
{
|
||||
@ -518,20 +520,20 @@ void CBrowser::HiddenServersModal(void)
|
||||
void CBrowser::DrawHostPanel(void)
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
std::lock_guard<std::mutex> l(g_ServerListManager.m_Mutex);
|
||||
NetGameServer_t& details = g_ServerHostManager.GetDetails();
|
||||
|
||||
ImGui::InputTextWithHint("##ServerHost_ServerName", "Server name (required)", &g_ServerListManager.m_Server.name);
|
||||
ImGui::InputTextWithHint("##ServerHost_ServerDesc", "Server description (optional)", &g_ServerListManager.m_Server.description);
|
||||
ImGui::InputTextWithHint("##ServerHost_ServerName", "Server name (required)", &details.name);
|
||||
ImGui::InputTextWithHint("##ServerHost_ServerDesc", "Server description (optional)", &details.description);
|
||||
ImGui::Spacing();
|
||||
|
||||
if (ImGui::BeginCombo("Mode", g_ServerListManager.m_Server.playlist.c_str()))
|
||||
if (ImGui::BeginCombo("Mode", details.playlist.c_str()))
|
||||
{
|
||||
g_PlaylistsVecMutex.lock();
|
||||
for (const string& svPlaylist : g_vAllPlaylists)
|
||||
{
|
||||
if (ImGui::Selectable(svPlaylist.c_str(), svPlaylist == g_ServerListManager.m_Server.playlist))
|
||||
if (ImGui::Selectable(svPlaylist.c_str(), svPlaylist == details.playlist))
|
||||
{
|
||||
g_ServerListManager.m_Server.playlist = svPlaylist;
|
||||
details.playlist = svPlaylist;
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,7 +541,7 @@ void CBrowser::DrawHostPanel(void)
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui::BeginCombo("Map", g_ServerListManager.m_Server.map.c_str()))
|
||||
if (ImGui::BeginCombo("Map", details.map.c_str()))
|
||||
{
|
||||
g_InstalledMapsMutex.lock();
|
||||
|
||||
@ -548,9 +550,9 @@ void CBrowser::DrawHostPanel(void)
|
||||
const CUtlString& mapName = g_InstalledMaps[i];
|
||||
|
||||
if (ImGui::Selectable(mapName.String(),
|
||||
mapName.IsEqual_CaseInsensitive(g_ServerListManager.m_Server.map.c_str())))
|
||||
mapName.IsEqual_CaseInsensitive(details.map.c_str())))
|
||||
{
|
||||
g_ServerListManager.m_Server.map = mapName.String();
|
||||
details.map = mapName.String();
|
||||
}
|
||||
}
|
||||
|
||||
@ -566,17 +568,17 @@ void CBrowser::DrawHostPanel(void)
|
||||
|
||||
ImGui::Text("Server visibility");
|
||||
|
||||
if (ImGui::SameLine(); ImGui::RadioButton("offline", g_ServerListManager.m_ServerVisibility == EServerVisibility_t::OFFLINE))
|
||||
if (ImGui::SameLine(); ImGui::RadioButton("offline", g_ServerHostManager.GetVisibility() == ServerVisibility_e::OFFLINE))
|
||||
{
|
||||
g_ServerListManager.m_ServerVisibility = EServerVisibility_t::OFFLINE;
|
||||
g_ServerHostManager.SetVisibility(ServerVisibility_e::OFFLINE);
|
||||
}
|
||||
if (ImGui::SameLine(); ImGui::RadioButton("hidden", g_ServerListManager.m_ServerVisibility == EServerVisibility_t::HIDDEN))
|
||||
if (ImGui::SameLine(); ImGui::RadioButton("hidden", g_ServerHostManager.GetVisibility() == ServerVisibility_e::HIDDEN))
|
||||
{
|
||||
g_ServerListManager.m_ServerVisibility = EServerVisibility_t::HIDDEN;
|
||||
g_ServerHostManager.SetVisibility(ServerVisibility_e::HIDDEN);
|
||||
}
|
||||
if (ImGui::SameLine(); ImGui::RadioButton("public", g_ServerListManager.m_ServerVisibility == EServerVisibility_t::PUBLIC))
|
||||
if (ImGui::SameLine(); ImGui::RadioButton("public", g_ServerHostManager.GetVisibility() == ServerVisibility_e::PUBLIC))
|
||||
{
|
||||
g_ServerListManager.m_ServerVisibility = EServerVisibility_t::PUBLIC;
|
||||
g_ServerHostManager.SetVisibility(ServerVisibility_e::PUBLIC);
|
||||
}
|
||||
|
||||
ImGui::TextColored(m_hostMessageColor, "%s", m_hostMessage.c_str());
|
||||
@ -596,27 +598,27 @@ void CBrowser::DrawHostPanel(void)
|
||||
{
|
||||
m_hostMessage.clear();
|
||||
|
||||
const bool enforceField = g_ServerListManager.m_ServerVisibility == EServerVisibility_t::OFFLINE
|
||||
const bool enforceField = g_ServerHostManager.GetVisibility() == ServerVisibility_e::OFFLINE
|
||||
? true
|
||||
: !g_ServerListManager.m_Server.name.empty();
|
||||
: !details.name.empty();
|
||||
|
||||
if (enforceField && !g_ServerListManager.m_Server.playlist.empty() && !g_ServerListManager.m_Server.map.empty())
|
||||
if (enforceField && !details.playlist.empty() && !details.map.empty())
|
||||
{
|
||||
g_ServerListManager.LaunchServer(serverActive); // Launch server.
|
||||
g_ServerHostManager.LaunchServer(serverActive); // Launch server.
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_ServerListManager.m_Server.name.empty())
|
||||
if (details.name.empty())
|
||||
{
|
||||
m_hostMessage = "Server name is required.";
|
||||
m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
|
||||
}
|
||||
else if (g_ServerListManager.m_Server.playlist.empty())
|
||||
else if (details.playlist.empty())
|
||||
{
|
||||
m_hostMessage = "Playlist is required.";
|
||||
m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
|
||||
}
|
||||
else if (g_ServerListManager.m_Server.map.empty())
|
||||
else if (details.map.empty())
|
||||
{
|
||||
m_hostMessage = "Level name is required.";
|
||||
m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
|
||||
@ -645,9 +647,9 @@ void CBrowser::DrawHostPanel(void)
|
||||
|
||||
if (ImGui::Button("Change level", ImVec2(contentRegionMax.x, 32)))
|
||||
{
|
||||
if (!g_ServerListManager.m_Server.map.empty())
|
||||
if (!details.map.empty())
|
||||
{
|
||||
g_ServerListManager.LaunchServer(serverActive);
|
||||
g_ServerHostManager.LaunchServer(serverActive);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -705,12 +707,15 @@ void CBrowser::UpdateHostingStatus(void)
|
||||
#ifndef CLIENT_DLL
|
||||
assert(g_pHostState && g_pCVar);
|
||||
|
||||
std::lock_guard<std::mutex> l(g_ServerListManager.m_Mutex);
|
||||
g_ServerListManager.m_HostingStatus = g_pServer->IsActive() ? EHostStatus_t::HOSTING : EHostStatus_t::NOT_HOSTING; // Are we hosting a server?
|
||||
const HostStatus_e hostStatus = g_pServer->IsActive()
|
||||
? HostStatus_e::HOSTING
|
||||
: HostStatus_e::NOT_HOSTING;
|
||||
|
||||
switch (g_ServerListManager.m_HostingStatus)
|
||||
g_ServerHostManager.SetHostStatus(hostStatus); // Are we hosting a server?
|
||||
|
||||
switch (hostStatus)
|
||||
{
|
||||
case EHostStatus_t::NOT_HOSTING:
|
||||
case HostStatus_e::NOT_HOSTING:
|
||||
{
|
||||
if (!m_hostToken.empty())
|
||||
{
|
||||
@ -726,9 +731,12 @@ void CBrowser::UpdateHostingStatus(void)
|
||||
|
||||
break;
|
||||
}
|
||||
case EHostStatus_t::HOSTING:
|
||||
case HostStatus_e::HOSTING:
|
||||
{
|
||||
if (g_ServerListManager.m_ServerVisibility == EServerVisibility_t::OFFLINE)
|
||||
const ServerVisibility_e serverVisibility = g_ServerHostManager.GetVisibility();
|
||||
NetGameServer_t& details = g_ServerHostManager.GetDetails();
|
||||
|
||||
if (serverVisibility == ServerVisibility_e::OFFLINE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -738,14 +746,14 @@ void CBrowser::UpdateHostingStatus(void)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (g_ServerListManager.m_ServerVisibility)
|
||||
switch (serverVisibility)
|
||||
{
|
||||
|
||||
case EServerVisibility_t::HIDDEN:
|
||||
g_ServerListManager.m_Server.hidden = true;
|
||||
case ServerVisibility_e::HIDDEN:
|
||||
details.hidden = true;
|
||||
break;
|
||||
case EServerVisibility_t::PUBLIC:
|
||||
g_ServerListManager.m_Server.hidden = false;
|
||||
case ServerVisibility_e::PUBLIC:
|
||||
details.hidden = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -753,9 +761,9 @@ void CBrowser::UpdateHostingStatus(void)
|
||||
|
||||
const NetGameServer_t netGameServer
|
||||
{
|
||||
g_ServerListManager.m_Server.name,
|
||||
g_ServerListManager.m_Server.description,
|
||||
g_ServerListManager.m_Server.hidden,
|
||||
details.name,
|
||||
details.description,
|
||||
details.hidden,
|
||||
g_pHostState->m_levelName,
|
||||
v_Playlists_GetCurrent(),
|
||||
hostip->GetString(),
|
||||
@ -820,7 +828,7 @@ void CBrowser::InstallHostingDetails(const bool postFailed, const char* const ho
|
||||
|
||||
if (!hostIp.empty())
|
||||
{
|
||||
g_MasterServer.SetHostIP(hostIp);
|
||||
g_ServerHostManager.SetHostIP(hostIp);
|
||||
}
|
||||
|
||||
if (postFailed)
|
||||
|
@ -6,6 +6,8 @@ start_sources()
|
||||
add_sources( SOURCE_GROUP "Private"
|
||||
"bansystem.cpp"
|
||||
"bansystem.h"
|
||||
"hostmanager.cpp"
|
||||
"hostmanager.h"
|
||||
"listmanager.cpp"
|
||||
"listmanager.h"
|
||||
"pylon.cpp"
|
||||
|
51
src/networksystem/hostmanager.cpp
Normal file
51
src/networksystem/hostmanager.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
//=============================================================================//
|
||||
//
|
||||
// Purpose: server host manager
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//=============================================================================//
|
||||
#include "tier0/frametask.h"
|
||||
#include "rtech/playlists/playlists.h"
|
||||
#include "engine/cmd.h"
|
||||
#include "hostmanager.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CServerHostManager::CServerHostManager(void)
|
||||
: m_HostingStatus(HostStatus_e::NOT_HOSTING)
|
||||
, m_ServerVisibility(ServerVisibility_e::OFFLINE)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Launch server with given parameters
|
||||
//-----------------------------------------------------------------------------
|
||||
void CServerHostManager::LaunchServer(const bool changeLevel) const
|
||||
{
|
||||
if (!ThreadInMainThread())
|
||||
{
|
||||
g_TaskQueue.Dispatch([this, changeLevel]()
|
||||
{
|
||||
this->LaunchServer(changeLevel);
|
||||
}, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
Msg(eDLL_T::ENGINE, "Starting server with name: \"%s\" map: \"%s\" playlist: \"%s\"\n",
|
||||
m_Server.name.c_str(), m_Server.map.c_str(), m_Server.playlist.c_str());
|
||||
|
||||
/*
|
||||
* Playlist gets parsed in two instances, first in Playlists_Parse() with all the necessary
|
||||
* 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..
|
||||
*/
|
||||
v_Playlists_Parse(m_Server.playlist.c_str());
|
||||
mp_gamemode->SetValue(m_Server.playlist.c_str());
|
||||
|
||||
const string command = Format("%s \"%s\"", changeLevel ? "changelevel" : "map", m_Server.map.c_str());
|
||||
Cbuf_AddText(Cbuf_GetCurrentPlayer(), command.c_str(), cmd_source_t::kCommandSrcCode);
|
||||
}
|
||||
|
||||
CServerHostManager g_ServerHostManager;
|
55
src/networksystem/hostmanager.h
Normal file
55
src/networksystem/hostmanager.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef HOSTMANAGER_H
|
||||
#define HOSTMANAGER_H
|
||||
#include <networksystem/serverlisting.h>
|
||||
|
||||
enum HostStatus_e
|
||||
{
|
||||
NOT_HOSTING,
|
||||
HOSTING
|
||||
};
|
||||
|
||||
enum ServerVisibility_e
|
||||
{
|
||||
OFFLINE,
|
||||
HIDDEN,
|
||||
PUBLIC
|
||||
};
|
||||
|
||||
class CServerHostManager
|
||||
{
|
||||
public:
|
||||
CServerHostManager();
|
||||
|
||||
void LaunchServer(const bool changeLevel) const;
|
||||
|
||||
inline HostStatus_e GetHostStatus(void) const { return m_HostingStatus; }
|
||||
inline void SetHostStatus(const HostStatus_e hostStatus) { m_HostingStatus = hostStatus; }
|
||||
|
||||
inline ServerVisibility_e GetVisibility(void) const { return m_ServerVisibility; }
|
||||
inline void SetVisibility(const ServerVisibility_e visibility) { m_ServerVisibility = visibility; }
|
||||
|
||||
inline NetGameServer_t& GetDetails() { return m_Server; }
|
||||
|
||||
inline void SetCurrentToken(const string& token) { m_Token = token; }
|
||||
inline const string& GetCurrentToken() const { return m_Token; }
|
||||
|
||||
inline void SetCurrentError(const string& error) { m_ErrorMsg = error; }
|
||||
inline const string& GetCurrentError() const { return m_ErrorMsg; }
|
||||
|
||||
inline void SetHostIP(const string& ip) { m_HostIP = ip; };
|
||||
inline const string& GetHostIP() const { return m_HostIP; };
|
||||
|
||||
private:
|
||||
HostStatus_e m_HostingStatus;
|
||||
ServerVisibility_e m_ServerVisibility;
|
||||
|
||||
NetGameServer_t m_Server;
|
||||
|
||||
string m_Token;
|
||||
string m_ErrorMsg;
|
||||
string m_HostIP;
|
||||
};
|
||||
|
||||
extern CServerHostManager g_ServerHostManager;
|
||||
|
||||
#endif // HOSTMANAGER_H
|
@ -1,6 +1,6 @@
|
||||
//=============================================================================//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// Purpose: server list manager
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
@ -22,25 +22,30 @@
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CServerListManager::CServerListManager(void)
|
||||
: m_HostingStatus(EHostStatus_t::NOT_HOSTING)
|
||||
, m_ServerVisibility(EServerVisibility_t::OFFLINE)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: get server list from pylon
|
||||
// Input : &svMessage -
|
||||
// Output : amount of servers found
|
||||
// Input : &outMessage -
|
||||
// &numServers -
|
||||
// Output : true on success, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
size_t CServerListManager::RefreshServerList(string& svMessage)
|
||||
bool CServerListManager::RefreshServerList(string& outMessage, size_t& numServers)
|
||||
{
|
||||
ClearServerList();
|
||||
vector<NetGameServer_t> vServerList = g_MasterServer.GetServerList(svMessage);
|
||||
|
||||
std::lock_guard<std::mutex> l(m_Mutex);
|
||||
m_vServerList = vServerList;
|
||||
vector<NetGameServer_t> serverList;
|
||||
const bool success = g_MasterServer.GetServerList(serverList, outMessage);
|
||||
|
||||
return m_vServerList.size();
|
||||
if (!success)
|
||||
return false;
|
||||
|
||||
AUTO_LOCK(m_Mutex);
|
||||
m_vServerList = serverList;
|
||||
|
||||
numServers = m_vServerList.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -48,38 +53,10 @@ size_t CServerListManager::RefreshServerList(string& svMessage)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CServerListManager::ClearServerList(void)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_Mutex);
|
||||
AUTO_LOCK(m_Mutex);
|
||||
m_vServerList.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Launch server with given parameters
|
||||
//-----------------------------------------------------------------------------
|
||||
void CServerListManager::LaunchServer(const bool bChangeLevel) const
|
||||
{
|
||||
if (!ThreadInMainThread())
|
||||
{
|
||||
g_TaskQueue.Dispatch([this, bChangeLevel]()
|
||||
{
|
||||
this->LaunchServer(bChangeLevel);
|
||||
}, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
Msg(eDLL_T::ENGINE, "Starting server with name: \"%s\" map: \"%s\" playlist: \"%s\"\n",
|
||||
m_Server.name.c_str(), m_Server.map.c_str(), m_Server.playlist.c_str());
|
||||
|
||||
/*
|
||||
* Playlist gets parsed in two instances, first in Playlists_Parse() with all the necessary
|
||||
* 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..
|
||||
*/
|
||||
v_Playlists_Parse(m_Server.playlist.c_str());
|
||||
mp_gamemode->SetValue(m_Server.playlist.c_str());
|
||||
|
||||
ProcessCommand(Format("%s \"%s\"", bChangeLevel ? "changelevel" : "map", m_Server.map.c_str()).c_str());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: connects to specified server
|
||||
// Input : &svIp -
|
||||
@ -101,7 +78,9 @@ void CServerListManager::ConnectToServer(const string& svIp, const int nPort, co
|
||||
{
|
||||
NET_SetKey(svNetKey);
|
||||
}
|
||||
ProcessCommand(Format("%s \"[%s]:%i\"", "connect", svIp.c_str(), nPort).c_str());
|
||||
|
||||
const string command = Format("%s \"[%s]:%i\"", "connect", svIp.c_str(), nPort);
|
||||
Cbuf_AddText(Cbuf_GetCurrentPlayer(), command.c_str(), cmd_source_t::kCommandSrcCode);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -124,16 +103,9 @@ void CServerListManager::ConnectToServer(const string& svServer, const string& s
|
||||
{
|
||||
NET_SetKey(svNetKey);
|
||||
}
|
||||
ProcessCommand(Format("%s \"%s\"", "connect", svServer.c_str()).c_str());
|
||||
|
||||
const string command = Format("%s \"%s\"", "connect", svServer.c_str()).c_str();
|
||||
Cbuf_AddText(Cbuf_GetCurrentPlayer(), command.c_str(), cmd_source_t::kCommandSrcCode);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: executes submitted commands in a separate thread
|
||||
// Input : *pszCommand -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CServerListManager::ProcessCommand(const char* pszCommand) const
|
||||
{
|
||||
Cbuf_AddText(Cbuf_GetCurrentPlayer(), pszCommand, cmd_source_t::kCommandSrcCode);
|
||||
}
|
||||
|
||||
CServerListManager g_ServerListManager;
|
||||
CServerListManager g_ServerListManager;
|
||||
|
@ -2,40 +2,20 @@
|
||||
#define LISTMANAGER_H
|
||||
#include <networksystem/serverlisting.h>
|
||||
|
||||
enum EHostStatus_t
|
||||
{
|
||||
NOT_HOSTING,
|
||||
HOSTING
|
||||
};
|
||||
|
||||
enum EServerVisibility_t
|
||||
{
|
||||
OFFLINE,
|
||||
HIDDEN,
|
||||
PUBLIC
|
||||
};
|
||||
|
||||
class CServerListManager
|
||||
{
|
||||
public:
|
||||
CServerListManager();
|
||||
|
||||
size_t RefreshServerList(string& svMessage);
|
||||
bool RefreshServerList(string& outMessage, size_t& numServers);
|
||||
void ClearServerList(void);
|
||||
|
||||
void LaunchServer(const bool bChangeLevel) const;
|
||||
void ConnectToServer(const string& svIp, const int nPort, const string& svNetKey) const;
|
||||
void ConnectToServer(const string& svServer, const string& svNetKey) const;
|
||||
|
||||
void ProcessCommand(const char* pszCommand) const;
|
||||
|
||||
EHostStatus_t m_HostingStatus;
|
||||
EServerVisibility_t m_ServerVisibility;
|
||||
|
||||
NetGameServer_t m_Server;
|
||||
// TODO: make private!
|
||||
vector<NetGameServer_t> m_vServerList;
|
||||
|
||||
mutable std::mutex m_Mutex;
|
||||
mutable CThreadFastMutex m_Mutex;
|
||||
};
|
||||
|
||||
extern CServerListManager g_ServerListManager;
|
||||
|
@ -46,12 +46,10 @@ static bool IsServerListingValid(const rapidjson::Value& value)
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: gets a vector of hosted servers.
|
||||
// Input : &outMessage -
|
||||
// Output : vector<NetGameServer_t>
|
||||
// Output : true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
vector<NetGameServer_t> CPylon::GetServerList(string& outMessage) const
|
||||
bool CPylon::GetServerList(vector<NetGameServer_t>& outServerList, string& outMessage) const
|
||||
{
|
||||
vector<NetGameServer_t> vecServers;
|
||||
|
||||
rapidjson::Document requestJson;
|
||||
requestJson.SetObject();
|
||||
requestJson.AddMember("version", SDK_VERSION, requestJson.GetAllocator());
|
||||
@ -65,13 +63,13 @@ vector<NetGameServer_t> CPylon::GetServerList(string& outMessage) const
|
||||
if (!SendRequest("/servers", requestJson, responseJson,
|
||||
outMessage, status, "server list error"))
|
||||
{
|
||||
return vecServers;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!responseJson.HasMember("servers"))
|
||||
{
|
||||
outMessage = Format("Invalid response with status: %d", int(status));
|
||||
return vecServers;
|
||||
return false;
|
||||
}
|
||||
|
||||
const rapidjson::Value& servers = responseJson["servers"];
|
||||
@ -87,7 +85,7 @@ vector<NetGameServer_t> CPylon::GetServerList(string& outMessage) const
|
||||
continue;
|
||||
}
|
||||
|
||||
vecServers.push_back(
|
||||
outServerList.push_back(
|
||||
NetGameServer_t
|
||||
{
|
||||
obj["name"].GetString(),
|
||||
@ -107,7 +105,7 @@ vector<NetGameServer_t> CPylon::GetServerList(string& outMessage) const
|
||||
);
|
||||
}
|
||||
|
||||
return vecServers;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -522,7 +520,7 @@ bool CPylon::QueryServer(const char* endpoint, const char* request,
|
||||
|
||||
string finalUrl;
|
||||
CURLFormatUrl(finalUrl, hostName, endpoint);
|
||||
finalUrl += Format("?language=%s", this->m_Language.c_str());
|
||||
finalUrl += Format("?language=%s", this->GetLanguage().c_str());
|
||||
|
||||
CURLParams params;
|
||||
|
||||
|
@ -18,9 +18,9 @@ struct MSEulaData_t
|
||||
class CPylon
|
||||
{
|
||||
public:
|
||||
CPylon() { m_Language = g_LanguageNames[0]; }
|
||||
CPylon() { SetLanguage(g_LanguageNames[0]); }
|
||||
|
||||
vector<NetGameServer_t> GetServerList(string& outMessage) const;
|
||||
bool GetServerList(vector<NetGameServer_t>& outServerList, string& outMessage) const;
|
||||
bool GetServerByToken(NetGameServer_t& slOutServer, string& outMessage, const string& svToken) const;
|
||||
bool PostServerHost(string& outMessage, string& svOutToken, string& outHostIp, const NetGameServer_t& netGameServer) const;
|
||||
|
||||
@ -38,22 +38,19 @@ public:
|
||||
bool SendRequest(const char* endpoint, const rapidjson::Document& requestJson, rapidjson::Document& responseJson, string& outMessage, CURLINFO& status, const char* errorText = nullptr, const bool checkEula = true) const;
|
||||
bool QueryServer(const char* endpoint, const char* request, string& outResponse, string& outMessage, CURLINFO& outStatus) const;
|
||||
|
||||
inline void SetCurrentToken(const string& token) { m_Token = token; }
|
||||
inline const string& GetCurrentToken() const { return m_Token; }
|
||||
|
||||
inline void SetCurrentError(const string& error) { m_ErrorMsg = error; }
|
||||
inline const string& GetCurrentError() const { return m_ErrorMsg; }
|
||||
|
||||
inline void SetHostIP(const string& ip) { m_HostIP = ip; };
|
||||
inline const string& GetHostIP() const { return m_HostIP; };
|
||||
|
||||
inline void SetLanguage(const char* lang) { m_Language = lang; };
|
||||
inline const string& GetLanguage() const { return m_Language; };
|
||||
inline void SetLanguage(const char* lang)
|
||||
{
|
||||
AUTO_LOCK(m_StringMutex);
|
||||
m_Language = lang;
|
||||
};
|
||||
inline const string& GetLanguage() const
|
||||
{
|
||||
AUTO_LOCK(m_StringMutex);
|
||||
return m_Language;
|
||||
};
|
||||
|
||||
private:
|
||||
string m_Token;
|
||||
string m_ErrorMsg;
|
||||
string m_HostIP;
|
||||
string m_Language;
|
||||
mutable CThreadFastMutex m_StringMutex;
|
||||
};
|
||||
extern CPylon g_MasterServer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user