Skip to content

Commit e5b718b

Browse files
committed
WIP
1 parent a27368d commit e5b718b

File tree

5 files changed

+52
-3
lines changed

5 files changed

+52
-3
lines changed

NorthstarDLL/engine/hoststate.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ void ServerStartingOrChangingMap()
2929
{
3030
ConVar* Cvar_mp_gamemode = g_pCVar->FindVar("mp_gamemode");
3131

32+
if (g_pServerPresence->IsDraining())
33+
{
34+
spdlog::info("server drain complete (server is changing map/mode), quitting");
35+
Cbuf_AddText(Cbuf_GetCurrentPlayer(), "quit", cmd_source_t::kCommandSrcCode);
36+
Cbuf_Execute();
37+
return;
38+
}
39+
3240
// directly call _Cmd_Exec_f to avoid weirdness with ; being in mp_gamemode potentially
3341
// if we ran exec {mp_gamemode} and mp_gamemode contained semicolons, this could be used to execute more commands
3442
char* commandBuf[1040]; // assumedly this is the size of CCommand since we don't have an actual constructor

NorthstarDLL/masterserver/masterserver.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -817,8 +817,11 @@ void MasterServerManager::ProcessConnectionlessPacketSigreq1(std::string data)
817817
if (obj.HasMember("username") && obj["username"].IsString())
818818
username = obj["username"].GetString();
819819

820+
820821
std::string reject;
821-
if (!g_pBanSystem->IsUIDAllowed(uid))
822+
if (g_pServerPresence->IsDraining())
823+
reject = "Server is shutting down.";
824+
else if (!g_pBanSystem->IsUIDAllowed(uid))
822825
reject = "Banned from this server.";
823826

824827
std::string pdata;
@@ -1356,7 +1359,7 @@ void MasterServerPresenceReporter::InternalUpdateServer(const ServerPresence* pS
13561359
fmt::format(
13571360
"{}/server/"
13581361
"update_values?id={}&port={}&authPort=udp&name={}&description={}&map={}&playlist={}&playerCount={}&"
1359-
"maxPlayers={}&password={}",
1362+
"maxPlayers={}&isDraining={}&password={}",
13601363
hostname.c_str(),
13611364
serverId.c_str(),
13621365
threadedPresence.m_iPort,
@@ -1366,6 +1369,7 @@ void MasterServerPresenceReporter::InternalUpdateServer(const ServerPresence* pS
13661369
playlistEscaped,
13671370
threadedPresence.m_iPlayerCount,
13681371
threadedPresence.m_iMaxPlayers,
1372+
threadedPresence.m_bIsDraining,
13691373
passwordEscaped)
13701374
.c_str());
13711375

NorthstarDLL/server/auth/serverauthentication.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,9 @@ bool,, (R2::CBaseClient* self, char* pName, void* pNetChannel, char bFakePlayer,
248248

249249
if (!bFakePlayer)
250250
{
251-
if (!g_pServerAuthentication->VerifyPlayerName(pNextPlayerToken, pName, pVerifiedName))
251+
if (g_pServerPresence->IsDraining())
252+
pAuthenticationFailure = "Server is shutting down.";
253+
else if (!g_pServerAuthentication->VerifyPlayerName(pNextPlayerToken, pName, pVerifiedName))
252254
pAuthenticationFailure = "Invalid Name.";
253255
else if (!g_pBanSystem->IsUIDAllowed(iNextPlayerUid))
254256
pAuthenticationFailure = "Banned From server.";
@@ -328,6 +330,13 @@ void,, (R2::CBaseClient* self, uint32_t unknownButAlways1, const char* pReason,
328330

329331
g_pServerPresence->SetPlayerCount(g_pServerAuthentication->m_PlayerAuthenticationData.size());
330332

333+
if (g_pServerPresence->IsDraining() && !g_pServerAuthentication->m_PlayerAuthenticationData.size())
334+
{
335+
spdlog::info("server drain complete (server is empty), quitting");
336+
R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "quit", R2::cmd_source_t::kCommandSrcCode);
337+
R2::Cbuf_Execute();
338+
}
339+
331340
_CBaseClient__Disconnect(self, unknownButAlways1, buf);
332341
}
333342

NorthstarDLL/server/serverpresence.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,28 @@ void ServerPresenceManager::SetPlayerCount(const int iPlayerCount)
221221
m_ServerPresence.m_iPlayerCount = iPlayerCount;
222222
}
223223

224+
void ServerPresenceManager::SetIsDraining(bool bIsDraining)
225+
{
226+
m_ServerPresence.m_bIsDraining = bIsDraining;
227+
}
228+
229+
bool ServerPresenceManager::IsDraining() const
230+
{
231+
// TODO: is there a better place for this?
232+
return m_ServerPresence.m_bIsDraining;
233+
}
234+
224235
ON_DLL_LOAD_RELIESON("engine.dll", ServerPresence, ConVar, (CModule module))
225236
{
226237
g_pServerPresence->CreateConVars();
227238
Cvar_hostname = module.Offset(0x1315BAE8).Deref().RCast<ConVar*>();
228239
}
240+
241+
ADD_SQFUNC("void", NSDrainServer, "bool drain, int timeout", "", ScriptContext::SERVER) {
242+
bool drain = g_pSquirrel<ScriptContext::SERVER>->getbool(sqvm, 1);
243+
int timeout = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 2);
244+
g_pServerPresence->SetIsDraining(drain);
245+
// TODO: notify the connected clients when this is set?
246+
// TODO: auto exit after a timeout or match end or player count reaches zero (use the quit command for a graceful exit)
247+
return SQRESULT_NULL;
248+
}

NorthstarDLL/server/serverpresence.h

+8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ struct ServerPresence
1919
int m_iPlayerCount;
2020
int m_iMaxPlayers;
2121

22+
bool m_bIsDraining;
23+
2224
ServerPresence()
2325
{
2426
memset(this, 0, sizeof(this));
@@ -39,6 +41,8 @@ struct ServerPresence
3941

4042
m_iPlayerCount = obj->m_iPlayerCount;
4143
m_iMaxPlayers = obj->m_iMaxPlayers;
44+
45+
m_bIsDraining = obj->m_bIsDraining;
4246
}
4347
};
4448

@@ -72,6 +76,7 @@ class ServerPresenceManager
7276
ConVar* Cvar_ns_report_sp_server_to_masterserver;
7377

7478
public:
79+
7580
void AddPresenceReporter(ServerPresenceReporter* reporter);
7681

7782
void CreateConVars();
@@ -89,6 +94,9 @@ class ServerPresenceManager
8994
void SetMap(const char* pMapName, bool isInitialising = false);
9095
void SetPlaylist(const char* pPlaylistName);
9196
void SetPlayerCount(const int iPlayerCount);
97+
98+
void SetIsDraining(bool bIsDraining);
99+
bool IsDraining() const;
92100
};
93101

94102
extern ServerPresenceManager* g_pServerPresence;

0 commit comments

Comments
 (0)