From f38f2319326209a596d18af8e6634a0d1e2e78cc Mon Sep 17 00:00:00 2001 From: cloudwalk Date: Mon, 22 Jun 2020 15:15:49 +0000 Subject: [PATCH] First massive rename and move A lot of these functions belong on their respective side of the engine. host.c and host_cmd.c appear to be a dumping ground for misc functions that Quakeworld engines have a proper place for. This is part of the moving operation. There's still plenty more functions that need to be put in their respective places. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12717 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_demo.c | 2 +- cl_input.c | 2 +- cl_main.c | 2 +- darkplaces-sdl2-vs2017.vcxproj | 1 + darkplaces-sdl2-vs2019.vcxproj | 1 + host.c | 278 +-------------------------------- host_cmd.c | 6 +- libcurl.c | 2 +- makefile.inc | 1 + netconn.c | 4 +- quakedef.h | 4 +- sv_main.c | 196 +++++++++++++++++++++-- sv_send.c | 125 +++++++++++++++ sv_user.c | 2 +- svvm_cmds.c | 2 +- 15 files changed, 325 insertions(+), 303 deletions(-) create mode 100644 sv_send.c diff --git a/cl_demo.c b/cl_demo.c index da199ed4..137c1577 100644 --- a/cl_demo.c +++ b/cl_demo.c @@ -438,7 +438,7 @@ void CL_PlayDemo_f(cmd_state_t *cmd) // disconnect from server CL_Disconnect (); - Host_ShutdownServer (); + SV_Shutdown (); // update networking ports (this is mainly just needed at startup) NetConn_UpdateSockets(); diff --git a/cl_input.c b/cl_input.c index 77456350..8ccd3477 100644 --- a/cl_input.c +++ b/cl_input.c @@ -2152,7 +2152,7 @@ void CL_SendMove(void) Con_Print("CL_SendMove: lost server connection\n"); CL_Disconnect(); SV_LockThreadMutex(); - Host_ShutdownServer(); + SV_Shutdown(); SV_UnlockThreadMutex(); } } diff --git a/cl_main.c b/cl_main.c index e17cc44f..e62ae26f 100644 --- a/cl_main.c +++ b/cl_main.c @@ -407,7 +407,7 @@ void CL_Disconnect_f(cmd_state_t *cmd) { CL_Disconnect (); if (sv.active) - Host_ShutdownServer (); + SV_Shutdown (); } diff --git a/darkplaces-sdl2-vs2017.vcxproj b/darkplaces-sdl2-vs2017.vcxproj index e37753d0..e1ee97c9 100644 --- a/darkplaces-sdl2-vs2017.vcxproj +++ b/darkplaces-sdl2-vs2017.vcxproj @@ -279,6 +279,7 @@ + diff --git a/darkplaces-sdl2-vs2019.vcxproj b/darkplaces-sdl2-vs2019.vcxproj index 54db5da8..2d7f1864 100644 --- a/darkplaces-sdl2-vs2019.vcxproj +++ b/darkplaces-sdl2-vs2019.vcxproj @@ -280,6 +280,7 @@ + diff --git a/host.c b/host.c index 6265bbc9..5c9da7eb 100644 --- a/host.c +++ b/host.c @@ -149,7 +149,7 @@ void Host_Error (const char *error, ...) Cvar_SetValueQuick(&csqc_progsize, -1); SV_LockThreadMutex(); - Host_ShutdownServer (); + SV_Shutdown (); SV_UnlockThreadMutex(); if (cls.state == ca_dedicated) @@ -336,280 +336,6 @@ void Host_LoadConfig_f(cmd_state_t *cmd) Host_AddConfigText(&cmd_client); } -/* -================= -SV_ClientPrint - -Sends text across to be displayed -FIXME: make this just a stuffed echo? -================= -*/ -void SV_ClientPrint(const char *msg) -{ - if (host_client->netconnection) - { - MSG_WriteByte(&host_client->netconnection->message, svc_print); - MSG_WriteString(&host_client->netconnection->message, msg); - } -} - -/* -================= -SV_ClientPrintf - -Sends text across to be displayed -FIXME: make this just a stuffed echo? -================= -*/ -void SV_ClientPrintf(const char *fmt, ...) -{ - va_list argptr; - char msg[MAX_INPUTLINE]; - - va_start(argptr,fmt); - dpvsnprintf(msg,sizeof(msg),fmt,argptr); - va_end(argptr); - - SV_ClientPrint(msg); -} - -/* -================= -SV_BroadcastPrint - -Sends text to all active clients -================= -*/ -void SV_BroadcastPrint(const char *msg) -{ - int i; - client_t *client; - - for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++) - { - if (client->active && client->netconnection) - { - MSG_WriteByte(&client->netconnection->message, svc_print); - MSG_WriteString(&client->netconnection->message, msg); - } - } - - if (sv_echobprint.integer && cls.state == ca_dedicated) - Con_Print(msg); -} - -/* -================= -SV_BroadcastPrintf - -Sends text to all active clients -================= -*/ -void SV_BroadcastPrintf(const char *fmt, ...) -{ - va_list argptr; - char msg[MAX_INPUTLINE]; - - va_start(argptr,fmt); - dpvsnprintf(msg,sizeof(msg),fmt,argptr); - va_end(argptr); - - SV_BroadcastPrint(msg); -} - -/* -================= -Host_ClientCommands - -Send text over to the client to be executed -================= -*/ -void Host_ClientCommands(const char *fmt, ...) -{ - va_list argptr; - char string[MAX_INPUTLINE]; - - if (!host_client->netconnection) - return; - - va_start(argptr,fmt); - dpvsnprintf(string, sizeof(string), fmt, argptr); - va_end(argptr); - - MSG_WriteByte(&host_client->netconnection->message, svc_stufftext); - MSG_WriteString(&host_client->netconnection->message, string); -} - -/* -===================== -SV_DropClient - -Called when the player is getting totally kicked off the host -if (crash = true), don't bother sending signofs -===================== -*/ -void SV_DropClient(qboolean crash) -{ - prvm_prog_t *prog = SVVM_prog; - int i; - Con_Printf("Client \"%s\" dropped\n", host_client->name); - - SV_StopDemoRecording(host_client); - - // make sure edict is not corrupt (from a level change for example) - host_client->edict = PRVM_EDICT_NUM(host_client - svs.clients + 1); - - if (host_client->netconnection) - { - // tell the client to be gone - if (!crash) - { - // LadyHavoc: no opportunity for resending, so use unreliable 3 times - unsigned char bufdata[8]; - sizebuf_t buf; - memset(&buf, 0, sizeof(buf)); - buf.data = bufdata; - buf.maxsize = sizeof(bufdata); - MSG_WriteByte(&buf, svc_disconnect); - NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol, 10000, 0, false); - NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol, 10000, 0, false); - NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol, 10000, 0, false); - } - } - - // call qc ClientDisconnect function - // LadyHavoc: don't call QC if server is dead (avoids recursive - // Host_Error in some mods when they run out of edicts) - if (host_client->clientconnectcalled && sv.active && host_client->edict) - { - // call the prog function for removing a client - // this will set the body to a dead frame, among other things - int saveSelf = PRVM_serverglobaledict(self); - host_client->clientconnectcalled = false; - PRVM_serverglobalfloat(time) = sv.time; - PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict); - prog->ExecuteProgram(prog, PRVM_serverfunction(ClientDisconnect), "QC function ClientDisconnect is missing"); - PRVM_serverglobaledict(self) = saveSelf; - } - - if (host_client->netconnection) - { - // break the net connection - NetConn_Close(host_client->netconnection); - host_client->netconnection = NULL; - } - - // if a download is active, close it - if (host_client->download_file) - { - Con_DPrintf("Download of %s aborted when %s dropped\n", host_client->download_name, host_client->name); - FS_Close(host_client->download_file); - host_client->download_file = NULL; - host_client->download_name[0] = 0; - host_client->download_expectedposition = 0; - host_client->download_started = false; - } - - // remove leaving player from scoreboard - host_client->name[0] = 0; - host_client->colors = 0; - host_client->frags = 0; - // send notification to all clients - // get number of client manually just to make sure we get it right... - i = host_client - svs.clients; - MSG_WriteByte (&sv.reliable_datagram, svc_updatename); - MSG_WriteByte (&sv.reliable_datagram, i); - MSG_WriteString (&sv.reliable_datagram, host_client->name); - MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors); - MSG_WriteByte (&sv.reliable_datagram, i); - MSG_WriteByte (&sv.reliable_datagram, host_client->colors); - MSG_WriteByte (&sv.reliable_datagram, svc_updatefrags); - MSG_WriteByte (&sv.reliable_datagram, i); - MSG_WriteShort (&sv.reliable_datagram, host_client->frags); - - // free the client now - if (host_client->entitydatabase) - EntityFrame_FreeDatabase(host_client->entitydatabase); - if (host_client->entitydatabase4) - EntityFrame4_FreeDatabase(host_client->entitydatabase4); - if (host_client->entitydatabase5) - EntityFrame5_FreeDatabase(host_client->entitydatabase5); - - if (sv.active) - { - // clear a fields that matter to DP_SV_CLIENTNAME and DP_SV_CLIENTCOLORS, and also frags - PRVM_ED_ClearEdict(prog, host_client->edict); - } - - // clear the client struct (this sets active to false) - memset(host_client, 0, sizeof(*host_client)); - - // update server listing on the master because player count changed - // (which the master uses for filtering empty/full servers) - NetConn_Heartbeat(1); - - if (sv.loadgame) - { - for (i = 0;i < svs.maxclients;i++) - if (svs.clients[i].active && !svs.clients[i].spawned) - break; - if (i == svs.maxclients) - { - Con_Printf("Loaded game, everyone rejoined - unpausing\n"); - sv.paused = sv.loadgame = false; // we're basically done with loading now - } - } -} - -/* -================== -Host_ShutdownServer - -This only happens at the end of a game, not between levels -================== -*/ -void Host_ShutdownServer(void) -{ - prvm_prog_t *prog = SVVM_prog; - int i; - - Con_DPrintf("Host_ShutdownServer\n"); - - if (!sv.active) - return; - - NetConn_Heartbeat(2); - NetConn_Heartbeat(2); - -// make sure all the clients know we're disconnecting - World_End(&sv.world); - if(prog->loaded) - { - if(PRVM_serverfunction(SV_Shutdown)) - { - func_t s = PRVM_serverfunction(SV_Shutdown); - PRVM_serverglobalfloat(time) = sv.time; - PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again - prog->ExecuteProgram(prog, s,"SV_Shutdown() required"); - } - } - for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++) - if (host_client->active) - SV_DropClient(false); // server shutdown - - NetConn_CloseServerPorts(); - - sv.active = false; -// -// clear structures -// - memset(&sv, 0, sizeof(sv)); - memset(svs.clients, 0, svs.maxclients*sizeof(client_t)); - - cl.islocalgame = false; -} - - //============================================================================ /* @@ -1385,7 +1111,7 @@ void Host_Shutdown(void) // shut down local server if active SV_LockThreadMutex(); - Host_ShutdownServer (); + SV_Shutdown (); SV_UnlockThreadMutex(); #ifdef CONFIG_MENU diff --git a/host_cmd.c b/host_cmd.c index 5305629e..769c50f7 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -368,7 +368,7 @@ static void SV_Map_f(cmd_state_t *cmd) cls.demonum = -1; // stop demo loop in case this fails CL_Disconnect (); - Host_ShutdownServer(); + SV_Shutdown(); if(svs.maxclients != svs.maxclients_next) { @@ -2456,7 +2456,7 @@ static void CL_Stopdemo_f(cmd_state_t *cmd) if (!cls.demoplayback) return; CL_Disconnect (); - Host_ShutdownServer (); + SV_Shutdown (); } static void CL_SendCvar_f(cmd_state_t *cmd) @@ -2493,7 +2493,7 @@ static void CL_SendCvar_f(cmd_state_t *cmd) if(svs.clients[i].active && svs.clients[i].netconnection) { host_client = &svs.clients[i]; - Host_ClientCommands("sendcvar %s\n", cvarname); + SV_ClientCommands("sendcvar %s\n", cvarname); } host_client = old; } diff --git a/libcurl.c b/libcurl.c index 88563bad..77c4aa33 100644 --- a/libcurl.c +++ b/libcurl.c @@ -1827,7 +1827,7 @@ void Curl_SendRequirements(void) strlcat(sendbuffer, "curl --finish_autodownload\n", sizeof(sendbuffer)); if(strlen(sendbuffer) + 1 < sizeof(sendbuffer)) - Host_ClientCommands("%s", sendbuffer); + SV_ClientCommands("%s", sendbuffer); else Con_Printf("Could not initiate autodownload due to URL buffer overflow\n"); } diff --git a/makefile.inc b/makefile.inc index b2619027..4d9a11c5 100644 --- a/makefile.inc +++ b/makefile.inc @@ -146,6 +146,7 @@ OBJ_COMMON= \ sv_main.o \ sv_move.o \ sv_phys.o \ + sv_send.o \ sv_user.o \ svbsp.o \ svvm_cmds.o \ diff --git a/netconn.c b/netconn.c index a2b259b6..eb61cfed 100755 --- a/netconn.c +++ b/netconn.c @@ -1517,7 +1517,7 @@ static void NetConn_ConnectionEstablished(lhnetsocket_t *mysocket, lhnetaddress_ if (LHNETADDRESS_GetAddressType(peeraddress) != LHNETADDRESSTYPE_LOOP && sv.active) { SV_LockThreadMutex(); - Host_ShutdownServer (); + SV_Shutdown (); SV_UnlockThreadMutex(); } // allocate a net connection to keep track of things @@ -2482,7 +2482,7 @@ void NetConn_ClientFrame(void) Con_Print("Connection timed out\n"); CL_Disconnect(); SV_LockThreadMutex(); - Host_ShutdownServer (); + SV_Shutdown (); SV_UnlockThreadMutex(); } } diff --git a/quakedef.h b/quakedef.h index 5b73b2c0..50df5e0b 100644 --- a/quakedef.h +++ b/quakedef.h @@ -543,8 +543,8 @@ void Host_Shutdown(void); void Host_StartVideo(void); void Host_Error(const char *error, ...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN; void Host_Quit_f(cmd_state_t *cmd); -void Host_ClientCommands(const char *fmt, ...) DP_FUNC_PRINTF(1); -void Host_ShutdownServer(void); +void SV_ClientCommands(const char *fmt, ...) DP_FUNC_PRINTF(1); +void SV_Shutdown(void); void CL_Reconnect_f(cmd_state_t *cmd); void Host_NoOperation_f(cmd_state_t *cmd); void Host_LockSession(void); diff --git a/sv_main.c b/sv_main.c index 376d7fd8..19f45537 100644 --- a/sv_main.c +++ b/sv_main.c @@ -1152,6 +1152,126 @@ void SV_ConnectClient (int clientnum, netconn_t *netconnection) client->prespawned = client->spawned = client->begun = true; } +/* +===================== +SV_DropClient + +Called when the player is getting totally kicked off the host +if (crash = true), don't bother sending signofs +===================== +*/ +void SV_DropClient(qboolean crash) +{ + prvm_prog_t *prog = SVVM_prog; + int i; + Con_Printf("Client \"%s\" dropped\n", host_client->name); + + SV_StopDemoRecording(host_client); + + // make sure edict is not corrupt (from a level change for example) + host_client->edict = PRVM_EDICT_NUM(host_client - svs.clients + 1); + + if (host_client->netconnection) + { + // tell the client to be gone + if (!crash) + { + // LadyHavoc: no opportunity for resending, so use unreliable 3 times + unsigned char bufdata[8]; + sizebuf_t buf; + memset(&buf, 0, sizeof(buf)); + buf.data = bufdata; + buf.maxsize = sizeof(bufdata); + MSG_WriteByte(&buf, svc_disconnect); + NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol, 10000, 0, false); + NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol, 10000, 0, false); + NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol, 10000, 0, false); + } + } + + // call qc ClientDisconnect function + // LadyHavoc: don't call QC if server is dead (avoids recursive + // Host_Error in some mods when they run out of edicts) + if (host_client->clientconnectcalled && sv.active && host_client->edict) + { + // call the prog function for removing a client + // this will set the body to a dead frame, among other things + int saveSelf = PRVM_serverglobaledict(self); + host_client->clientconnectcalled = false; + PRVM_serverglobalfloat(time) = sv.time; + PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict); + prog->ExecuteProgram(prog, PRVM_serverfunction(ClientDisconnect), "QC function ClientDisconnect is missing"); + PRVM_serverglobaledict(self) = saveSelf; + } + + if (host_client->netconnection) + { + // break the net connection + NetConn_Close(host_client->netconnection); + host_client->netconnection = NULL; + } + + // if a download is active, close it + if (host_client->download_file) + { + Con_DPrintf("Download of %s aborted when %s dropped\n", host_client->download_name, host_client->name); + FS_Close(host_client->download_file); + host_client->download_file = NULL; + host_client->download_name[0] = 0; + host_client->download_expectedposition = 0; + host_client->download_started = false; + } + + // remove leaving player from scoreboard + host_client->name[0] = 0; + host_client->colors = 0; + host_client->frags = 0; + // send notification to all clients + // get number of client manually just to make sure we get it right... + i = host_client - svs.clients; + MSG_WriteByte (&sv.reliable_datagram, svc_updatename); + MSG_WriteByte (&sv.reliable_datagram, i); + MSG_WriteString (&sv.reliable_datagram, host_client->name); + MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors); + MSG_WriteByte (&sv.reliable_datagram, i); + MSG_WriteByte (&sv.reliable_datagram, host_client->colors); + MSG_WriteByte (&sv.reliable_datagram, svc_updatefrags); + MSG_WriteByte (&sv.reliable_datagram, i); + MSG_WriteShort (&sv.reliable_datagram, host_client->frags); + + // free the client now + if (host_client->entitydatabase) + EntityFrame_FreeDatabase(host_client->entitydatabase); + if (host_client->entitydatabase4) + EntityFrame4_FreeDatabase(host_client->entitydatabase4); + if (host_client->entitydatabase5) + EntityFrame5_FreeDatabase(host_client->entitydatabase5); + + if (sv.active) + { + // clear a fields that matter to DP_SV_CLIENTNAME and DP_SV_CLIENTCOLORS, and also frags + PRVM_ED_ClearEdict(prog, host_client->edict); + } + + // clear the client struct (this sets active to false) + memset(host_client, 0, sizeof(*host_client)); + + // update server listing on the master because player count changed + // (which the master uses for filtering empty/full servers) + NetConn_Heartbeat(1); + + if (sv.loadgame) + { + for (i = 0;i < svs.maxclients;i++) + if (svs.clients[i].active && !svs.clients[i].spawned) + break; + if (i == svs.maxclients) + { + Con_Printf("Loaded game, everyone rejoined - unpausing\n"); + sv.paused = sv.loadgame = false; // we're basically done with loading now + } + } +} /* =============================================================================== @@ -2725,7 +2845,7 @@ static void SV_Download_f(cmd_state_t *cmd) { // at this point we'll assume the previous download should be aborted Con_DPrintf("Download of %s aborted by %s starting a new download\n", host_client->download_name, host_client->name); - Host_ClientCommands("\nstopdownload\n"); + SV_ClientCommands("\nstopdownload\n"); // close the file and reset variables FS_Close(host_client->download_file); @@ -2740,7 +2860,7 @@ static void SV_Download_f(cmd_state_t *cmd) if (!sv_allowdownloads.integer && !is_csqc) { SV_ClientPrintf("Downloads are disabled on this server\n"); - Host_ClientCommands("\nstopdownload\n"); + SV_ClientCommands("\nstopdownload\n"); return; } @@ -2769,7 +2889,7 @@ static void SV_Download_f(cmd_state_t *cmd) host_client->download_file = FS_FileFromData(svs.csqc_progdata, sv.csqc_progsize, true); // no, no space is needed between %s and %s :P - Host_ClientCommands("\ncl_downloadbegin %i %s%s\n", (int)FS_FileSize(host_client->download_file), host_client->download_name, extensions); + SV_ClientCommands("\ncl_downloadbegin %i %s%s\n", (int)FS_FileSize(host_client->download_file), host_client->download_name, extensions); host_client->download_expectedposition = 0; host_client->download_started = false; @@ -2780,7 +2900,7 @@ static void SV_Download_f(cmd_state_t *cmd) if (!FS_FileExists(host_client->download_name)) { SV_ClientPrintf("Download rejected: server does not have the file \"%s\"\nYou may need to separately download or purchase the data archives for this game/mod to get this file\n", host_client->download_name); - Host_ClientCommands("\nstopdownload\n"); + SV_ClientCommands("\nstopdownload\n"); return; } @@ -2790,7 +2910,7 @@ static void SV_Download_f(cmd_state_t *cmd) if ((whichpack && whichpack2 && !strcasecmp(whichpack, whichpack2)) || FS_IsRegisteredQuakePack(host_client->download_name)) { SV_ClientPrintf("Download rejected: file \"%s\" is part of registered Quake(r)\nYou must purchase Quake(r) from id Software or a retailer to get this file\nPlease go to http://www.idsoftware.com/games/quake/quake/index.php?game_section=buy\n", host_client->download_name); - Host_ClientCommands("\nstopdownload\n"); + SV_ClientCommands("\nstopdownload\n"); return; } @@ -2801,7 +2921,7 @@ static void SV_Download_f(cmd_state_t *cmd) if (whichpack) { SV_ClientPrintf("Download rejected: file \"%s\" is in an archive (\"%s\")\nYou must separately download or purchase the data archives for this game/mod to get this file\n", host_client->download_name, whichpack); - Host_ClientCommands("\nstopdownload\n"); + SV_ClientCommands("\nstopdownload\n"); return; } } @@ -2811,7 +2931,7 @@ static void SV_Download_f(cmd_state_t *cmd) if (!strcasecmp(extension, "cfg")) { SV_ClientPrintf("Download rejected: file \"%s\" is a .cfg file which is forbidden for security reasons\nYou must separately download or purchase the data archives for this game/mod to get this file\n", host_client->download_name); - Host_ClientCommands("\nstopdownload\n"); + SV_ClientCommands("\nstopdownload\n"); return; } } @@ -2821,7 +2941,7 @@ static void SV_Download_f(cmd_state_t *cmd) if (!strncasecmp(host_client->download_name, "dlcache/", 8)) { SV_ClientPrintf("Download rejected: file \"%s\" is in the dlcache/ directory which is forbidden for security reasons\nYou must separately download or purchase the data archives for this game/mod to get this file\n", host_client->download_name); - Host_ClientCommands("\nstopdownload\n"); + SV_ClientCommands("\nstopdownload\n"); return; } } @@ -2831,7 +2951,7 @@ static void SV_Download_f(cmd_state_t *cmd) if (!strcasecmp(extension, "pak") || !strcasecmp(extension, "pk3")) { SV_ClientPrintf("Download rejected: file \"%s\" is an archive\nYou must separately download or purchase the data archives for this game/mod to get this file\n", host_client->download_name); - Host_ClientCommands("\nstopdownload\n"); + SV_ClientCommands("\nstopdownload\n"); return; } } @@ -2840,14 +2960,14 @@ static void SV_Download_f(cmd_state_t *cmd) if (!host_client->download_file) { SV_ClientPrintf("Download rejected: server could not open the file \"%s\"\n", host_client->download_name); - Host_ClientCommands("\nstopdownload\n"); + SV_ClientCommands("\nstopdownload\n"); return; } if (FS_FileSize(host_client->download_file) > 1<<30) { SV_ClientPrintf("Download rejected: file \"%s\" is very large\n", host_client->download_name); - Host_ClientCommands("\nstopdownload\n"); + SV_ClientCommands("\nstopdownload\n"); FS_Close(host_client->download_file); host_client->download_file = NULL; return; @@ -2856,7 +2976,7 @@ static void SV_Download_f(cmd_state_t *cmd) if (FS_FileSize(host_client->download_file) < 0) { SV_ClientPrintf("Download rejected: file \"%s\" is not a regular file\n", host_client->download_name); - Host_ClientCommands("\nstopdownload\n"); + SV_ClientCommands("\nstopdownload\n"); FS_Close(host_client->download_file); host_client->download_file = NULL; return; @@ -2875,10 +2995,10 @@ static void SV_Download_f(cmd_state_t *cmd) strlcat(extensions, " deflate", sizeof(extensions)); // no, no space is needed between %s and %s :P - Host_ClientCommands("\ncl_downloadbegin %i %s%s\n", (int)FS_FileSize(host_client->download_file), host_client->download_name, extensions); + SV_ClientCommands("\ncl_downloadbegin %i %s%s\n", (int)FS_FileSize(host_client->download_file), host_client->download_name, extensions); } */ - Host_ClientCommands("\ncl_downloadbegin %i %s\n", (int)FS_FileSize(host_client->download_file), host_client->download_name); + SV_ClientCommands("\ncl_downloadbegin %i %s\n", (int)FS_FileSize(host_client->download_file), host_client->download_name); host_client->download_expectedposition = 0; host_client->download_started = false; @@ -3596,6 +3716,54 @@ void SV_SpawnServer (const char *server) // SV_UnlockThreadMutex(); } +/* +================== +SV_Shutdown + +This only happens at the end of a game, not between levels +================== +*/ +void SV_Shutdown(void) +{ + prvm_prog_t *prog = SVVM_prog; + int i; + + Con_DPrintf("SV_Shutdown\n"); + + if (!sv.active) + return; + + NetConn_Heartbeat(2); + NetConn_Heartbeat(2); + +// make sure all the clients know we're disconnecting + World_End(&sv.world); + if(prog->loaded) + { + if(PRVM_serverfunction(SV_Shutdown)) + { + func_t s = PRVM_serverfunction(SV_Shutdown); + PRVM_serverglobalfloat(time) = sv.time; + PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again + prog->ExecuteProgram(prog, s,"SV_Shutdown() required"); + } + } + for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++) + if (host_client->active) + SV_DropClient(false); // server shutdown + + NetConn_CloseServerPorts(); + + sv.active = false; +// +// clear structures +// + memset(&sv, 0, sizeof(sv)); + memset(svs.clients, 0, svs.maxclients*sizeof(client_t)); + + cl.islocalgame = false; +} + ///////////////////////////////////////////////////// // SV VM stuff diff --git a/sv_send.c b/sv_send.c new file mode 100644 index 00000000..32b78e39 --- /dev/null +++ b/sv_send.c @@ -0,0 +1,125 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "quakedef.h" + +/* +================= +SV_ClientPrint + +Sends text across to be displayed +FIXME: make this just a stuffed echo? +================= +*/ +void SV_ClientPrint(const char *msg) +{ + if (host_client->netconnection) + { + MSG_WriteByte(&host_client->netconnection->message, svc_print); + MSG_WriteString(&host_client->netconnection->message, msg); + } +} + +/* +================= +SV_ClientPrintf + +Sends text across to be displayed +FIXME: make this just a stuffed echo? +================= +*/ +void SV_ClientPrintf(const char *fmt, ...) +{ + va_list argptr; + char msg[MAX_INPUTLINE]; + + va_start(argptr,fmt); + dpvsnprintf(msg,sizeof(msg),fmt,argptr); + va_end(argptr); + + SV_ClientPrint(msg); +} + +/* +================= +SV_BroadcastPrint + +Sends text to all active clients +================= +*/ +void SV_BroadcastPrint(const char *msg) +{ + int i; + client_t *client; + + for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++) + { + if (client->active && client->netconnection) + { + MSG_WriteByte(&client->netconnection->message, svc_print); + MSG_WriteString(&client->netconnection->message, msg); + } + } + + if (sv_echobprint.integer && cls.state == ca_dedicated) + Con_Print(msg); +} + +/* +================= +SV_BroadcastPrintf + +Sends text to all active clients +================= +*/ +void SV_BroadcastPrintf(const char *fmt, ...) +{ + va_list argptr; + char msg[MAX_INPUTLINE]; + + va_start(argptr,fmt); + dpvsnprintf(msg,sizeof(msg),fmt,argptr); + va_end(argptr); + + SV_BroadcastPrint(msg); +} + +/* +================= +SV_ClientCommands + +Send text over to the client to be executed +================= +*/ +void SV_ClientCommands(const char *fmt, ...) +{ + va_list argptr; + char string[MAX_INPUTLINE]; + + if (!host_client->netconnection) + return; + + va_start(argptr,fmt); + dpvsnprintf(string, sizeof(string), fmt, argptr); + va_end(argptr); + + MSG_WriteByte(&host_client->netconnection->message, svc_stufftext); + MSG_WriteString(&host_client->netconnection->message, string); +} \ No newline at end of file diff --git a/sv_user.c b/sv_user.c index 08b4aa27..e7e68c71 100644 --- a/sv_user.c +++ b/sv_user.c @@ -932,7 +932,7 @@ clc_stringcmd_invalid: Mem_Free(temp); // calculated crc, send the file info to the client // (so that it can verify the data) - Host_ClientCommands("\ncl_downloadfinished %i %i %s\n", size, crc, host_client->download_name); + SV_ClientCommands("\ncl_downloadfinished %i %i %s\n", size, crc, host_client->download_name); Con_DPrintf("Download of %s by %s has finished\n", host_client->download_name, host_client->name); FS_Close(host_client->download_file); host_client->download_file = NULL; diff --git a/svvm_cmds.c b/svvm_cmds.c index 48beda6a..12ef69da 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -969,7 +969,7 @@ static void VM_SV_stuffcmd(prvm_prog_t *prog) old = host_client; host_client = svs.clients + entnum-1; - Host_ClientCommands ("%s", string); + SV_ClientCommands ("%s", string); host_client = old; } -- 2.39.2