]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
no longer compresses embedded textures (in q1 and hl formats) because
[xonotic/darkplaces.git] / sv_main.c
index 4c46abae2fd3151343c110d0892c28523e7728d0..19f35f724e0bd5fbc2a78edbf516443e1d6920d0 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -76,9 +76,11 @@ cvar_t sv_fixedframeratesingleplayer = {0, "sv_fixedframeratesingleplayer", "0",
 cvar_t sv_freezenonclients = {CVAR_NOTIFY, "sv_freezenonclients", "0", "freezes time, except for players, allowing you to walk around and take screenshots of explosions"};
 cvar_t sv_friction = {CVAR_NOTIFY, "sv_friction","4", "how fast you slow down"};
 cvar_t sv_gameplayfix_blowupfallenzombies = {0, "sv_gameplayfix_blowupfallenzombies", "1", "causes findradius to detect SOLID_NOT entities such as zombies and corpses on the floor, allowing splash damage to apply to them"};
+cvar_t sv_gameplayfix_delayprojectiles = {0, "sv_gameplayfix_delayprojectiles", "1", "causes entities to not move on the same frame they are spawned, meaning that projectiles wait until the next frame to perform their first move, giving proper interpolation and rocket trails, but making weapons harder to use at low framerates"};
 cvar_t sv_gameplayfix_droptofloorstartsolid = {0, "sv_gameplayfix_droptofloorstartsolid", "1", "prevents items and monsters that start in a solid area from falling out of the level (makes droptofloor treat trace_startsolid as an acceptable outcome)"};
 cvar_t sv_gameplayfix_findradiusdistancetobox = {0, "sv_gameplayfix_findradiusdistancetobox", "1", "causes findradius to check the distance to the corner of a box rather than the center of the box, makes findradius detect bmodels such as very large doors that would otherwise be unaffected by splash damage"};
 cvar_t sv_gameplayfix_grenadebouncedownslopes = {0, "sv_gameplayfix_grenadebouncedownslopes", "1", "prevents MOVETYPE_BOUNCE (grenades) from getting stuck when fired down a downward sloping surface"};
+cvar_t sv_gameplayfix_multiplethinksperframe = {0, "sv_gameplayfix_multiplethinksperframe", "1", "allows entities to think more often than the server framerate, primarily useful for very high fire rate weapons"};
 cvar_t sv_gameplayfix_noairborncorpse = {0, "sv_gameplayfix_noairborncorpse", "1", "causes entities (corpses) sitting ontop of moving entities (players) to fall when the moving entity (player) is no longer supporting them"};
 cvar_t sv_gameplayfix_qwplayerphysics = {0, "sv_gameplayfix_qwplayerphysics", "1", "changes water jumping to make it easier to get out of water, and prevents friction on landing when bunnyhopping"};
 cvar_t sv_gameplayfix_setmodelrealbox = {0, "sv_gameplayfix_setmodelrealbox", "1", "fixes a bug in Quake that made setmodel always set the entity box to ('-16 -16 -16', '16 16 16') rather than properly checking the model box, breaks some poorly coded mods"};
@@ -91,7 +93,7 @@ cvar_t sv_idealpitchscale = {0, "sv_idealpitchscale","0.8", "how much to look up
 cvar_t sv_jumpstep = {CVAR_NOTIFY, "sv_jumpstep", "0", "whether you can step up while jumping (sv_gameplayfix_stepwhilejumping must also be 1)"};
 cvar_t sv_jumpvelocity = {0, "sv_jumpvelocity", "270", "cvar that can be used by QuakeC code for jump velocity"};
 cvar_t sv_maxairspeed = {0, "sv_maxairspeed", "30", "maximum speed a player can accelerate to when airborn (note that it is possible to completely stop by moving the opposite direction)"};
-cvar_t sv_maxrate = {CVAR_SAVE | CVAR_NOTIFY, "sv_maxrate", "10000", "upper limit on client rate cvar, should reflect your network connection quality"};
+cvar_t sv_maxrate = {CVAR_SAVE | CVAR_NOTIFY, "sv_maxrate", "1000000", "upper limit on client rate cvar, should reflect your network connection quality"};
 cvar_t sv_maxspeed = {CVAR_NOTIFY, "sv_maxspeed", "320", "maximum speed a player can accelerate to when on ground (can be exceeded by tricks)"};
 cvar_t sv_maxvelocity = {CVAR_NOTIFY, "sv_maxvelocity","2000", "universal speed limit on all entities"};
 cvar_t sv_newflymove = {CVAR_NOTIFY, "sv_newflymove", "0", "enables simpler/buggier player physics (not recommended)"};
@@ -340,9 +342,11 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_freezenonclients);
        Cvar_RegisterVariable (&sv_friction);
        Cvar_RegisterVariable (&sv_gameplayfix_blowupfallenzombies);
+       Cvar_RegisterVariable (&sv_gameplayfix_delayprojectiles);
        Cvar_RegisterVariable (&sv_gameplayfix_droptofloorstartsolid);
        Cvar_RegisterVariable (&sv_gameplayfix_findradiusdistancetobox);
        Cvar_RegisterVariable (&sv_gameplayfix_grenadebouncedownslopes);
+       Cvar_RegisterVariable (&sv_gameplayfix_multiplethinksperframe);
        Cvar_RegisterVariable (&sv_gameplayfix_noairborncorpse);
        Cvar_RegisterVariable (&sv_gameplayfix_qwplayerphysics);
        Cvar_RegisterVariable (&sv_gameplayfix_setmodelrealbox);
@@ -413,6 +417,18 @@ void SV_Init (void)
        }
        Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
 
+       // any special defaults for gamemodes go here
+       if (gamemode == GAME_HIPNOTIC)
+       {
+               // hipnotic mission pack has issues in their 'friendly monster' ai, which seem to attempt to attack themselves for some reason when findradius() returns non-solid entities.
+               Cvar_SetValueQuick (&sv_gameplayfix_blowupfallenzombies, 0);
+       }
+       if (gamemode == GAME_ROGUE)
+       {
+               // rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area
+               Cvar_SetValueQuick (&sv_gameplayfix_findradiusdistancetobox, 0);
+       }
+
        sv_mempool = Mem_AllocPool("server", 0, NULL);
 }
 
@@ -707,6 +723,7 @@ void SV_SendServerinfo (client_t *client)
        MSG_WriteByte (&client->netconnection->message, 1);
 
        client->spawned = false;                // need prespawn, spawn, etc
+       client->sendsignon = 1;                 // send this message, and increment to 2, 2 will be set to 0 by the prespawn command
 
        // clear movement info until client enters the new level properly
        memset(&client->cmd, 0, sizeof(client->cmd));
@@ -753,8 +770,8 @@ void SV_ConnectClient (int clientnum, netconn_t *netconnection)
        // prepare the unreliable message buffer
        client->unreliablemsg.data = client->unreliablemsg_data;
        client->unreliablemsg.maxsize = sizeof(client->unreliablemsg_data);
-       // updated by receiving "rate" command from client
-       client->rate = NET_MINRATE;
+       // updated by receiving "rate" command from client, this is also the default if not using a DP client
+       client->rate = 1000000000;
        // no limits for local player
        if (client->netconnection && LHNETADDRESS_GetAddressType(&client->netconnection->peeraddress) == LHNETADDRESSTYPE_LOOP)
                client->rate = 1000000000;
@@ -1364,6 +1381,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
        //stats[STAT_MONSTERS] = prog->globals.server->killed_monsters;
 
        // movement settings for prediction
+       // note: these are not sent in protocols with lower MAX_CL_STATS limits
        statsf[STAT_MOVEVARS_TICRATE] = sys_ticrate.value;
        statsf[STAT_MOVEVARS_TIMESCALE] = slowmo.value;
        statsf[STAT_MOVEVARS_GRAVITY] = sv_gravity.value;
@@ -1374,7 +1392,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
        statsf[STAT_MOVEVARS_AIRACCELERATE] = sv_airaccelerate.value >= 0 ? sv_airaccelerate.value : sv_accelerate.value;
        statsf[STAT_MOVEVARS_WATERACCELERATE] = sv_wateraccelerate.value >= 0 ? sv_wateraccelerate.value : sv_accelerate.value;
        val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.gravity);
-       statsf[STAT_MOVEVARS_ENTGRAVITY] = val ? val->_float : 1.0f;
+       statsf[STAT_MOVEVARS_ENTGRAVITY] = (val && val->_float != 0) ? val->_float : 1.0f;
        statsf[STAT_MOVEVARS_JUMPVELOCITY] = sv_jumpvelocity.value;
        statsf[STAT_MOVEVARS_EDGEFRICTION] = sv_edgefriction.value;
        statsf[STAT_MOVEVARS_MAXAIRSPEED] = sv_maxairspeed.value;
@@ -1383,6 +1401,8 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
        statsf[STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION] = sv_airaccel_sideways_friction.value;
        statsf[STAT_MOVEVARS_FRICTION] = sv_friction.value;
        statsf[STAT_MOVEVARS_WATERFRICTION] = sv_waterfriction.value >= 0 ? sv_waterfriction.value : sv_friction.value;
+       statsf[STAT_FRAGLIMIT] = fraglimit.value;
+       statsf[STAT_TIMELIMIT] = timelimit.value;
 
        if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
        {
@@ -1434,7 +1454,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
                }
                if (bits & (SU_VELOCITY1<<i))
                {
-                       if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
+                       if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
                                MSG_WriteChar(msg, (int)(ent->fields.server->velocity[i] * (1.0f / 16.0f)));
                        else
                                MSG_WriteCoord32f(msg, ent->fields.server->velocity[i]);
@@ -1479,12 +1499,12 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
                if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_NEXUIZ)
                {
                        for (i = 0;i < 32;i++)
-                               if (stats[STAT_WEAPON] & (1<<i))
+                               if (stats[STAT_ACTIVEWEAPON] & (1<<i))
                                        break;
                        MSG_WriteByte (msg, i);
                }
                else
-                       MSG_WriteByte (msg, stats[STAT_WEAPON]);
+                       MSG_WriteByte (msg, stats[STAT_ACTIVEWEAPON]);
                if (bits & SU_VIEWZOOM)
                {
                        if (sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
@@ -1581,8 +1601,9 @@ static void SV_SendClientDatagram (client_t *client)
                // no packet size limit support on older protocols because DP1-4 kick
                // the client off if they overflow, and quake protocol shows less than
                // the full entity set if rate limited
-               maxsize = 1400;
-               maxsize2 = 1400;
+               clientrate = max(NET_MINRATE, client->rate);
+               maxsize = 1024;
+               maxsize2 = 1024;
        }
        else
        {
@@ -1611,7 +1632,7 @@ static void SV_SendClientDatagram (client_t *client)
        if (!NetConn_CanSend(client->netconnection))
        {
                // send the datagram
-               //NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate);
+               //NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate, true);
                return;
        }
        else if (host_client->spawned)
@@ -1672,7 +1693,9 @@ static void SV_SendClientDatagram (client_t *client)
        }
 
 // send the datagram
-       NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate);
+       NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate, client->sendsignon == 2);
+       if (client->sendsignon == 1 && !client->netconnection->message.cursize)
+               client->sendsignon = 2; // prevent reliable until client sends prespawn (this is the keepalive phase)
 }
 
 /*
@@ -1705,7 +1728,7 @@ static void SV_UpdateToReliableMessages (void)
                if (strcmp(host_client->old_name, host_client->name))
                {
                        if (host_client->spawned)
-                               SV_BroadcastPrintf("%s^%i changed name to %s\n", host_client->old_name, STRING_COLOR_DEFAULT, host_client->name);
+                               SV_BroadcastPrintf("%s changed name to %s\n", host_client->old_name, host_client->name);
                        strlcpy(host_client->old_name, host_client->name, sizeof(host_client->old_name));
                        // send notification to all clients
                        MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
@@ -1936,6 +1959,7 @@ static void SV_Download_f(void)
 
        host_client->download_expectedposition = 0;
        host_client->download_started = false;
+       host_client->sendsignon = true; // make sure this message is sent
 
        // the rest of the download process is handled in SV_SendClientDatagram
        // and other code dealing with svc_downloaddata and clc_ackdownloaddata
@@ -2247,7 +2271,10 @@ void SV_SpawnServer (const char *server)
        Con_DPrintf("SpawnServer: %s\n", server);
 
        if (cls.state != ca_dedicated)
+       {
                SCR_BeginLoadingPlaque();
+               S_StopAllSounds();
+       }
 
        dpsnprintf (modelname, sizeof(modelname), "maps/%s.bsp", server);
        worldmodel = Mod_ForName(modelname, false, true, true);
@@ -2631,7 +2658,14 @@ static void SV_VM_Setup(void)
        prog->numbuiltins = vm_sv_numbuiltins;
        prog->headercrc = PROGHEADER_CRC;
        prog->max_edicts = 512;
-       prog->limit_edicts = MAX_EDICTS;
+       if (sv.protocol == PROTOCOL_QUAKE)
+               prog->limit_edicts = 640; // before quake mission pack 1 this was 512
+       else if (sv.protocol == PROTOCOL_QUAKEDP)
+               prog->limit_edicts = 2048; // guessing
+       else if (sv.protocol == PROTOCOL_NEHAHRAMOVIE)
+               prog->limit_edicts = 2048; // guessing!
+       else
+               prog->limit_edicts = MAX_EDICTS;
        prog->reserved_edicts = svs.maxclients;
        prog->edictprivate_size = sizeof(edict_engineprivate_t);
        prog->name = "server";