]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
sys_win: Remove pointless cls.state sets since we're calling Sys_Error immediately...
[xonotic/darkplaces.git] / sv_main.c
index 867c0bdffa4035940f5ae84886782a64953d86b2..37d085088feb3e6e2e15a21da89d905970bc7728 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -147,8 +147,8 @@ cvar_t sv_sound_watersplash = {CF_SERVER, "sv_sound_watersplash", "misc/h2ohit1.
 cvar_t sv_stepheight = {CF_SERVER | CF_NOTIFY, "sv_stepheight", "18", "how high you can step up (TW_SV_STEPCONTROL extension)"};
 cvar_t sv_stopspeed = {CF_SERVER | CF_NOTIFY, "sv_stopspeed","100", "how fast you come to a complete stop"};
 cvar_t sv_wallfriction = {CF_SERVER | CF_NOTIFY, "sv_wallfriction", "1", "how much you slow down when sliding along a wall"};
-cvar_t sv_wateraccelerate = {CF_SERVER, "sv_wateraccelerate", "-1", "rate at which a player accelerates to sv_maxspeed while in the air, if less than 0 the sv_accelerate variable is used instead"};
-cvar_t sv_waterfriction = {CF_SERVER | CF_NOTIFY, "sv_waterfriction","-1", "how fast you slow down, if less than 0 the sv_friction variable is used instead"};
+cvar_t sv_wateraccelerate = {CF_SERVER, "sv_wateraccelerate", "-1", "rate at which a player accelerates to sv_maxspeed while in water, if less than 0 the sv_accelerate variable is used instead"};
+cvar_t sv_waterfriction = {CF_SERVER | CF_NOTIFY, "sv_waterfriction","-1", "how fast you slow down in water, if less than 0 the sv_friction variable is used instead"};
 cvar_t sv_warsowbunny_airforwardaccel = {CF_SERVER, "sv_warsowbunny_airforwardaccel", "1.00001", "how fast you accelerate until you reach sv_maxspeed"};
 cvar_t sv_warsowbunny_accel = {CF_SERVER, "sv_warsowbunny_accel", "0.1585", "how fast you accelerate until after reaching sv_maxspeed (it gets harder as you near sv_warsowbunny_topspeed)"};
 cvar_t sv_warsowbunny_topspeed = {CF_SERVER, "sv_warsowbunny_topspeed", "925", "soft speed limit (can get faster with rjs and on ramps)"};
@@ -435,16 +435,16 @@ static void SV_AreaStats_f(cmd_state_t *cmd)
 static qbool SV_CanSave(void)
 {
        prvm_prog_t *prog = SVVM_prog;
-       if(SV_IsLocalGame() == 1)
+       if(SV_IsLocalServer() == 1)
        {
                // singleplayer checks
-               if (!(svs.clients[0].active && PRVM_serveredictfloat(svs.clients[0].edict, deadflag)))
+               if ((svs.clients[0].active && PRVM_serveredictfloat(svs.clients[0].edict, deadflag)))
                {
                        Con_Print("Can't savegame with a dead player\n");
                        return false;
                }
 
-               if(!host.hook.CL_Intermission || !host.hook.CL_Intermission())
+               if(host.hook.CL_Intermission && host.hook.CL_Intermission())
                {
                        Con_Print("Can't save in intermission.\n");
                        return false;
@@ -456,6 +456,56 @@ static qbool SV_CanSave(void)
        
 }
 
+static void SV_ServerOptions (void)
+{
+       int i;
+
+       // general default
+       svs.maxclients = 8;
+
+// COMMANDLINEOPTION: Server: -dedicated [playerlimit] starts a dedicated server (with a command console), default playerlimit is 8
+// COMMANDLINEOPTION: Server: -listen [playerlimit] starts a multiplayer server with graphical client, like singleplayer but other players can connect, default playerlimit is 8
+       // if no client is in the executable or -dedicated is specified on
+       // commandline, start a dedicated server
+       i = Sys_CheckParm ("-dedicated");
+       if (i || !cl_available)
+       {
+               cls.state = ca_dedicated;
+               // check for -dedicated specifying how many players
+               if (i && i + 1 < sys.argc && atoi (sys.argv[i+1]) >= 1)
+                       svs.maxclients = atoi (sys.argv[i+1]);
+               if (Sys_CheckParm ("-listen"))
+                       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(&cvars_all, "sv_public", 1);
+       }
+       else if (cl_available)
+       {
+               // client exists and not dedicated, check if -listen is specified
+               cls.state = ca_disconnected;
+               i = Sys_CheckParm ("-listen");
+               if (i)
+               {
+                       // default players unless specified
+                       if (i + 1 < sys.argc && atoi (sys.argv[i+1]) >= 1)
+                               svs.maxclients = atoi (sys.argv[i+1]);
+               }
+               else
+               {
+                       // default players in some games, singleplayer in most
+                       if (gamemode != GAME_GOODVSBAD2 && !IS_NEXUIZ_DERIVED(gamemode) && gamemode != GAME_BATTLEMECH)
+                               svs.maxclients = 1;
+               }
+       }
+
+       svs.maxclients = svs.maxclients_next = bound(1, svs.maxclients, MAX_SCOREBOARD);
+
+       svs.clients = (client_t *)Mem_Alloc(sv_mempool, sizeof(client_t) * svs.maxclients);
+
+       if (svs.maxclients > 1 && !deathmatch.integer && !coop.integer)
+               Cvar_SetValueQuick(&deathmatch, 1);
+}
+
 /*
 ===============
 SV_Init
@@ -659,6 +709,8 @@ void SV_Init (void)
        host.hook.SV_CanSave = SV_CanSave;
 
        sv_mempool = Mem_AllocPool("server", 0, NULL);
+
+       SV_ServerOptions();
 }
 
 static void SV_SaveEntFile_f(cmd_state_t *cmd)
@@ -1325,7 +1377,7 @@ SV_ModelIndex
 */
 int SV_ModelIndex(const char *s, int precachemode)
 {
-       int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) ? 256 : MAX_MODELS);
+       int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE) ? 256 : MAX_MODELS);
        char filename[MAX_QPATH];
        if (!s || !*s)
                return 0;
@@ -1388,7 +1440,7 @@ SV_SoundIndex
 */
 int SV_SoundIndex(const char *s, int precachemode)
 {
-       int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) ? 256 : MAX_SOUNDS);
+       int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP) ? 256 : MAX_SOUNDS);
        char filename[MAX_QPATH];
        if (!s || !*s)
                return 0;
@@ -1519,12 +1571,12 @@ int SV_ParticleEffectIndex(const char *name)
        return 0;
 }
 
-dp_model_t *SV_GetModelByIndex(int modelindex)
+model_t *SV_GetModelByIndex(int modelindex)
 {
        return (modelindex > 0 && modelindex < MAX_MODELS) ? sv.models[modelindex] : NULL;
 }
 
-dp_model_t *SV_GetModelFromEdict(prvm_edict_t *ed)
+model_t *SV_GetModelFromEdict(prvm_edict_t *ed)
 {
        prvm_prog_t *prog = SVVM_prog;
        int modelindex;
@@ -1694,11 +1746,10 @@ void SV_SaveSpawnparms (void)
        }
 }
 
-qbool SV_IsLocalServer(void)
+// Returns 1 if we're singleplayer, > 1 if we're a listen server
+int SV_IsLocalServer(void)
 {
-       if(host_isclient.integer && host_client && LHNETADDRESS_GetAddressType(&host_client->netconnection->peeraddress) == LHNETADDRESSTYPE_LOOP)
-               return true;
-       return false;
+       return (host_isclient.integer && sv.active ? svs.maxclients : 0);
 }
 
 /*
@@ -1715,7 +1766,7 @@ void SV_SpawnServer (const char *map)
        prvm_edict_t *ent;
        int i;
        char *entities;
-       dp_model_t *worldmodel;
+       model_t *worldmodel;
        char modelname[sizeof(sv.worldname)];
        char vabuf[1024];
 
@@ -2014,17 +2065,6 @@ void SV_SpawnServer (const char *map)
 //     SV_UnlockThreadMutex();
 }
 
-/*
- * Returns number of slots if we're a listen server.
- * Returns 0 if we're a dedicated server.
- */
-int SV_IsLocalGame(void)
-{
-       if (sv.active && LHNETADDRESS_GetAddressType(&host_client->netconnection->peeraddress) == LHNETADDRESSTYPE_LOOP)
-               return svs.maxclients;
-       return 0;
-}
-
 /*
 ==================
 SV_Shutdown
@@ -2415,6 +2455,21 @@ static void SV_VM_Setup(void)
        SV_Prepare_CSQC();
 }
 
+static void SV_CheckTimeouts(void)
+{
+       int i;
+
+       // never timeout loopback connections
+       for (i = (host_isclient.integer ? 1 : 0), host_client = &svs.clients[i]; i < svs.maxclients; i++, host_client++)
+       {
+               if (host_client->netconnection && host.realtime > host_client->netconnection->timeout)
+               {
+                       Con_Printf("Client \"%s\" connection timed out\n", host_client->name);
+                       SV_DropClient(false);
+               }
+       }
+}
+
 extern cvar_t host_maxwait;
 extern cvar_t host_framerate;
 extern cvar_t cl_maxphysicsframesperserverframe;
@@ -2468,7 +2523,10 @@ double SV_Frame(double time)
                 * be undersleeping due to select() detecting a new packet
                 */
                if (sv.active)
+               {
                        NetConn_ServerFrame();
+                       SV_CheckTimeouts();
+               }
        }
 
        /*
@@ -2647,7 +2705,10 @@ static int SV_ThreadFunc(void *voiddata)
 
                // get new packets
                if (sv.active)
+               {
                        NetConn_ServerFrame();
+                       SV_CheckTimeouts();
+               }
 
                // if the accumulators haven't become positive yet, wait a while
                wait = sv_timer * -1000000.0;