]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - host.c
renamed NetConn_UpdateServerStuff to NetConn_UpdateSockets and made it non-static...
[xonotic/darkplaces.git] / host.c
diff --git a/host.c b/host.c
index 67ee4c1621de8d7cb829571bd309c227ae957824..5cc6c41abd0756c364b317a54a602aa6c79ad3e7 100644 (file)
--- a/host.c
+++ b/host.c
@@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "cdaudio.h"
 #include "cl_video.h"
 #include "progsvm.h"
+#include "csprogs.h"
 
 /*
 
@@ -59,40 +60,41 @@ client_t *host_client;
 jmp_buf host_abortframe;
 
 // pretend frames take this amount of time (in seconds), 0 = realtime
-cvar_t host_framerate = {0, "host_framerate","0"};
+cvar_t host_framerate = {0, "host_framerate","0", "locks frame timing to this value in seconds, 0.05 is 20fps for example, note that this can easily run too fast, use host_maxfps if you want to limit your framerate instead, or sys_ticrate to limit server speed"};
 // shows time used by certain subsystems
-cvar_t host_speeds = {0, "host_speeds","0"};
+cvar_t host_speeds = {0, "host_speeds","0", "reports how much time is used in server/graphics/sound"};
 // LordHavoc: framerate independent slowmo
-cvar_t slowmo = {0, "slowmo", "1.0"};
+cvar_t slowmo = {0, "slowmo", "1.0", "controls game speed, 0.5 is half speed, 2 is double speed"};
 // LordHavoc: framerate upper cap
-cvar_t cl_maxfps = {CVAR_SAVE, "cl_maxfps", "1000"};
+cvar_t cl_maxfps = {CVAR_SAVE, "cl_maxfps", "1000", "maximum fps cap, if game is running faster than this it will wait before running another frame (useful to make cpu time available to other programs)"};
 
 // print broadcast messages in dedicated mode
-cvar_t sv_echobprint = {CVAR_SAVE, "sv_echobprint", "1"};
+cvar_t sv_echobprint = {CVAR_SAVE, "sv_echobprint", "1", "prints gamecode bprint() calls to server console"};
 
-cvar_t sys_ticrate = {CVAR_SAVE, "sys_ticrate","0.05"};
-cvar_t sv_fixedframeratesingleplayer = {0, "sv_fixedframeratesingleplayer", "0"};
-cvar_t serverprofile = {0, "serverprofile","0"};
+cvar_t sys_ticrate = {CVAR_SAVE, "sys_ticrate","0.05", "how long a server frame is in seconds, 0.05 is 20fps server rate, 0.1 is 10fps (can not be set higher than 0.1), 0 runs as many server frames as possible (makes games against bots a little smoother, overwhelms network players)"};
+cvar_t sv_fixedframeratesingleplayer = {0, "sv_fixedframeratesingleplayer", "0", "allows you to use server-style timing system in singleplayer (don't run faster than sys_ticrate)"};
+cvar_t serverprofile = {0, "serverprofile","0", "print some timings on server code"};
 
-cvar_t fraglimit = {CVAR_NOTIFY, "fraglimit","0"};
-cvar_t timelimit = {CVAR_NOTIFY, "timelimit","0"};
-cvar_t teamplay = {CVAR_NOTIFY, "teamplay","0"};
+cvar_t fraglimit = {CVAR_NOTIFY, "fraglimit","0", "ends level if this many frags is reached by any player"};
+cvar_t timelimit = {CVAR_NOTIFY, "timelimit","0", "ends level at this time (in minutes)"};
+cvar_t teamplay = {CVAR_NOTIFY, "teamplay","0", "teamplay mode, values depend on mod but typically 0 = no teams, 1 = no team damage no self damage, 2 = team damage and self damage, some mods support 3 = no team damage but can damage self"};
 
-cvar_t samelevel = {0, "samelevel","0"};
-cvar_t noexit = {CVAR_NOTIFY, "noexit","0"};
+cvar_t samelevel = {CVAR_NOTIFY, "samelevel","0", "repeats same level if level ends (due to timelimit or someone hitting an exit)"};
+cvar_t noexit = {CVAR_NOTIFY, "noexit","0", "kills anyone attempting to use an exit"};
 
-cvar_t developer = {0, "developer","0"};
+cvar_t developer = {0, "developer","0", "prints additional debugging messages and information (recommended for modders and level designers)"};
+cvar_t developer_entityparsing = {0, "developer_entityparsing", "0", "prints detailed network entities information each time a packet is received"};
 
-cvar_t skill = {0, "skill","1"};
-cvar_t deathmatch = {0, "deathmatch","0"};
-cvar_t coop = {0, "coop","0"};
+cvar_t skill = {0, "skill","1", "difficulty level of game, affects monster layouts in levels, 0 = easy, 1 = normal, 2 = hard, 3 = nightmare (same layout as hard but monsters fire twice)"};
+cvar_t deathmatch = {0, "deathmatch","0", "deathmatch mode, values depend on mod but typically 0 = no deathmatch, 1 = normal deathmatch with respawning weapons, 2 = weapons stay (players can only pick up new weapons)"};
+cvar_t coop = {0, "coop","0", "coop mode, 0 = no coop, 1 = coop mode, multiple players playing through the singleplayer game (coop mode also shuts off deathmatch)"};
 
-cvar_t pausable = {0, "pausable","1"};
+cvar_t pausable = {0, "pausable","1", "allow players to pause or not"};
 
-cvar_t temp1 = {0, "temp1","0"};
+cvar_t temp1 = {0, "temp1","0", "general cvar for mods to use, in stock id1 this selects which death animation to use on players (0 = random death, other values select specific death scenes)"};
 
-cvar_t timestamps = {CVAR_SAVE, "timestamps", "0"};
-cvar_t timeformat = {CVAR_SAVE, "timeformat", "[%b %e %X] "};
+cvar_t timestamps = {CVAR_SAVE, "timestamps", "0", "prints timestamps on console messages"};
+cvar_t timeformat = {CVAR_SAVE, "timeformat", "[%b %e %X] ", "time format to use on timestamped console messages"};
 
 /*
 ================
@@ -115,8 +117,8 @@ This shuts down both the client and server
 */
 void Host_Error (const char *error, ...)
 {
-       static char hosterrorstring1[4096];
-       static char hosterrorstring2[4096];
+       static char hosterrorstring1[MAX_INPUTLINE];
+       static char hosterrorstring2[MAX_INPUTLINE];
        static qboolean hosterror = false;
        va_list argptr;
 
@@ -145,10 +147,10 @@ void Host_Error (const char *error, ...)
        PRVM_Crash();
 
 
-       Host_ShutdownServer (false);
+       Host_ShutdownServer ();
 
        if (cls.state == ca_dedicated)
-               Sys_Error ("Host_Error: %s\n",hosterrorstring2);        // dedicated servers exit
+               Sys_Error ("Host_Error: %s",hosterrorstring2);  // dedicated servers exit
 
        CL_Disconnect ();
        cls.demonum = -1;
@@ -177,7 +179,7 @@ void Host_ServerOptions (void)
                if (i && i + 1 < com_argc && atoi (com_argv[i+1]) >= 1)
                        svs.maxclients = atoi (com_argv[i+1]);
                if (COM_CheckParm ("-listen"))
-                       Con_Printf ("Only one of -dedicated or -listen can be specified");
+                       Con_Printf ("Only one of -dedicated or -listen can be specified\n");
                // default sv_public on for dedicated servers (often hosted by serious administrators), off for listen servers (often hosted by clueless users)
                Cvar_SetValue("sv_public", 1);
        }
@@ -216,7 +218,7 @@ Host_InitLocal
 void Host_SaveConfig_f(void);
 void Host_InitLocal (void)
 {
-       Cmd_AddCommand("saveconfig", Host_SaveConfig_f);
+       Cmd_AddCommand("saveconfig", Host_SaveConfig_f, "save settings to config.cfg immediately (also automatic when quitting)");
 
        Cvar_RegisterVariable (&host_framerate);
        Cvar_RegisterVariable (&host_speeds);
@@ -238,6 +240,7 @@ void Host_InitLocal (void)
        Cvar_RegisterVariable (&developer);
        if (forcedeveloper) // make it real now that the cvar is registered
                Cvar_SetValue("developer", 1);
+       Cvar_RegisterVariable (&developer_entityparsing);
        Cvar_RegisterVariable (&deathmatch);
        Cvar_RegisterVariable (&coop);
 
@@ -291,8 +294,11 @@ FIXME: make this just a stuffed echo?
 */
 void SV_ClientPrint(const char *msg)
 {
-       MSG_WriteByte(&host_client->message, svc_print);
-       MSG_WriteString(&host_client->message, msg);
+       if (host_client->netconnection)
+       {
+               MSG_WriteByte(&host_client->netconnection->message, svc_print);
+               MSG_WriteString(&host_client->netconnection->message, msg);
+       }
 }
 
 /*
@@ -306,7 +312,7 @@ FIXME: make this just a stuffed echo?
 void SV_ClientPrintf(const char *fmt, ...)
 {
        va_list argptr;
-       char msg[4096];
+       char msg[MAX_INPUTLINE];
 
        va_start(argptr,fmt);
        dpvsnprintf(msg,sizeof(msg),fmt,argptr);
@@ -329,10 +335,10 @@ void SV_BroadcastPrint(const char *msg)
 
        for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++)
        {
-               if (client->spawned)
+               if (client->spawned && client->netconnection)
                {
-                       MSG_WriteByte(&client->message, svc_print);
-                       MSG_WriteString(&client->message, msg);
+                       MSG_WriteByte(&client->netconnection->message, svc_print);
+                       MSG_WriteString(&client->netconnection->message, msg);
                }
        }
 
@@ -350,7 +356,7 @@ Sends text to all active clients
 void SV_BroadcastPrintf(const char *fmt, ...)
 {
        va_list argptr;
-       char msg[4096];
+       char msg[MAX_INPUTLINE];
 
        va_start(argptr,fmt);
        dpvsnprintf(msg,sizeof(msg),fmt,argptr);
@@ -369,14 +375,17 @@ Send text over to the client to be executed
 void Host_ClientCommands(const char *fmt, ...)
 {
        va_list argptr;
-       char string[1024];
+       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->message, svc_stufftext);
-       MSG_WriteString(&host_client->message, string);
+       MSG_WriteByte(&host_client->netconnection->message, svc_stufftext);
+       MSG_WriteString(&host_client->netconnection->message, string);
 }
 
 /*
@@ -401,10 +410,15 @@ void SV_DropClient(qboolean crash)
                if (!crash)
                {
                        // LordHavoc: no opportunity for resending, so use unreliable 3 times
-                       MSG_WriteByte(&host_client->message, svc_disconnect);
-                       NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message);
-                       NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message);
-                       NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message);
+                       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);
+                       NetConn_SendUnreliableMessage(host_client->netconnection, &buf);
+                       NetConn_SendUnreliableMessage(host_client->netconnection, &buf);
                }
                // break the net connection
                NetConn_Close(host_client->netconnection);
@@ -475,35 +489,24 @@ Host_ShutdownServer
 This only happens at the end of a game, not between levels
 ==================
 */
-void Host_ShutdownServer(qboolean crash)
+void Host_ShutdownServer(void)
 {
-       int i, count;
-       sizebuf_t buf;
-       qbyte message[4];
+       int i;
 
        Con_DPrintf("Host_ShutdownServer\n");
 
        if (!sv.active)
                return;
 
-       SV_VM_Begin();
-
        NetConn_Heartbeat(2);
        NetConn_Heartbeat(2);
 
 // make sure all the clients know we're disconnecting
-       buf.data = message;
-       buf.maxsize = 4;
-       buf.cursize = 0;
-       MSG_WriteByte(&buf, svc_disconnect);
-       count = NetConn_SendToAll(&buf, 5);
-       if (count)
-               Con_Printf("Host_ShutdownServer: NetConn_SendToAll failed for %u clients\n", count);
-
+       SV_VM_Begin();
        for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
-               if (host_client->active) {
-                       SV_DropClient(crash); // server shutdown
-               }
+               if (host_client->active)
+                       SV_DropClient(false); // server shutdown
+       SV_VM_End();
 
        NetConn_CloseServerPorts();
 
@@ -513,8 +516,6 @@ void Host_ShutdownServer(qboolean crash)
 //
        memset(&sv, 0, sizeof(sv));
        memset(svs.clients, 0, svs.maxclients*sizeof(client_t));
-
-       SV_VM_End();
 }
 
 
@@ -654,8 +655,11 @@ Host_ServerFrame
 */
 void Host_ServerFrame (void)
 {
-       // never run more than 5 frames at a time as a sanity limit
-       int framecount, framelimit = 5;
+       // never run more than 1 frame per call because multiple frames per call it
+       // does not handle overload gracefully, slowing down is better than a
+       // sudden significant drop in framerate (or worse, freezing until the
+       // problem goes away)
+       int framecount, framelimit = 1;
        double advancetime;
        if (!sv.active)
        {
@@ -799,7 +803,13 @@ void _Host_Frame (float time)
                time2 = Sys_DoubleTime();
 
        // update audio
-       S_Update(&r_refdef.viewentitymatrix);
+       if(csqc_usecsqclistener)
+       {
+               S_Update(&csqc_listenermatrix);
+               csqc_usecsqclistener = false;
+       }
+       else
+               S_Update(&r_refdef.viewentitymatrix);
 
        CDAudio_Update();
 
@@ -1101,7 +1111,7 @@ void Host_Shutdown(void)
        CL_Disconnect();
 
        // shut down local server if active
-       Host_ShutdownServer (false);
+       Host_ShutdownServer ();
 
        // Shutdown menu
        if(MR_Shutdown)