]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
Add spawn2, a new spawn builtin
[xonotic/darkplaces.git] / sv_main.c
index 0c1627035552341c07a80d91f123c455acb87234..85ca4fe50ddb1697e52ed5ec4561a9e6aa2e6439 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -123,6 +123,7 @@ cvar_t sv_gameplayfix_unstickplayers = {0, "sv_gameplayfix_unstickplayers", "1",
 cvar_t sv_gameplayfix_unstickentities = {0, "sv_gameplayfix_unstickentities", "1", "hack to check if entities are crossing world collision hull and try to move them to the right position"};
 cvar_t sv_gameplayfix_fixedcheckwatertransition = {0, "sv_gameplayfix_fixedcheckwatertransition", "1", "fix two very stupid bugs in SV_CheckWaterTransition when watertype is CONTENTS_EMPTY (the bugs causes waterlevel to be 1 on first frame, -1 on second frame - the fix makes it 0 on both frames)"};
 cvar_t sv_gravity = {CVAR_NOTIFY, "sv_gravity","800", "how fast you fall (512 = roughly earth gravity)"};
+cvar_t sv_init_frame_count = {0, "sv_init_frame_count", "2", "number of frames to run to allow everything to settle before letting clients connect"};
 cvar_t sv_idealpitchscale = {0, "sv_idealpitchscale","0.8", "how much to look up/down slopes and stairs when not using freelook"};
 cvar_t sv_jumpstep = {CVAR_NOTIFY, "sv_jumpstep", "0", "whether you can step up while jumping"};
 cvar_t sv_jumpvelocity = {0, "sv_jumpvelocity", "270", "cvar that can be used by QuakeC code for jump velocity"};
@@ -193,6 +194,8 @@ cvar_t sv_autodemo_perclient_nameformat = {CVAR_SAVE, "sv_autodemo_perclient_nam
 cvar_t sv_autodemo_perclient_discardable = {CVAR_SAVE, "sv_autodemo_perclient_discardable", "0", "Allow game code to decide whether a demo should be kept or discarded."};
 
 cvar_t halflifebsp = {0, "halflifebsp", "0", "indicates the current map is hlbsp format (useful to know because of different bounding box sizes)"};
+cvar_t sv_mapformat_is_quake2 = {0, "sv_mapformat_is_quake2", "0", "indicates the current map is q2bsp format (useful to know because of different entity behaviors, .frame on submodels and other things)"};
+cvar_t sv_mapformat_is_quake3 = {0, "sv_mapformat_is_quake3", "0", "indicates the current map is q2bsp format (useful to know because of different entity behaviors)"};
 
 server_t sv;
 server_static_t svs;
@@ -532,6 +535,7 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_gameplayfix_unstickentities);
        Cvar_RegisterVariable (&sv_gameplayfix_fixedcheckwatertransition);
        Cvar_RegisterVariable (&sv_gravity);
+       Cvar_RegisterVariable (&sv_init_frame_count);
        Cvar_RegisterVariable (&sv_idealpitchscale);
        Cvar_RegisterVariable (&sv_jumpstep);
        Cvar_RegisterVariable (&sv_jumpvelocity);
@@ -603,6 +607,8 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_autodemo_perclient_discardable);
 
        Cvar_RegisterVariable (&halflifebsp);
+       Cvar_RegisterVariable (&sv_mapformat_is_quake2);
+       Cvar_RegisterVariable (&sv_mapformat_is_quake3);
 
        sv_mempool = Mem_AllocPool("server", 0, NULL);
 }
@@ -704,7 +710,7 @@ Larger attenuations will drop off.  (max 4 attenuation)
 
 ==================
 */
-void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int volume, float attenuation, qboolean reliable, float speed)
+void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int nvolume, float attenuation, qboolean reliable, float speed)
 {
        prvm_prog_t *prog = SVVM_prog;
        sizebuf_t *dest;
@@ -712,9 +718,9 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v
 
        dest = (reliable ? &sv.reliable_datagram : &sv.datagram);
 
-       if (volume < 0 || volume > 255)
+       if (nvolume < 0 || nvolume > 255)
        {
-               Con_Printf ("SV_StartSound: volume = %i\n", volume);
+               Con_Printf ("SV_StartSound: volume = %i\n", nvolume);
                return;
        }
 
@@ -744,7 +750,7 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v
 
        speed4000 = (int)floor(speed * 4000.0f + 0.5f);
        field_mask = 0;
-       if (volume != DEFAULT_SOUND_PACKET_VOLUME)
+       if (nvolume != DEFAULT_SOUND_PACKET_VOLUME)
                field_mask |= SND_VOLUME;
        if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
                field_mask |= SND_ATTENUATION;
@@ -759,7 +765,7 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v
        MSG_WriteByte (dest, svc_sound);
        MSG_WriteByte (dest, field_mask);
        if (field_mask & SND_VOLUME)
-               MSG_WriteByte (dest, volume);
+               MSG_WriteByte (dest, nvolume);
        if (field_mask & SND_ATTENUATION)
                MSG_WriteByte (dest, (int)(attenuation*64));
        if (field_mask & SND_SPEEDUSHORT4000)
@@ -796,13 +802,13 @@ function, therefore the check for it is omitted.
 
 ==================
 */
-void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float attenuation, float speed)
+void SV_StartPointSound (vec3_t origin, const char *sample, int nvolume, float attenuation, float speed)
 {
        int sound_num, field_mask, i, speed4000;
 
-       if (volume < 0 || volume > 255)
+       if (nvolume < 0 || nvolume > 255)
        {
-               Con_Printf ("SV_StartPointSound: volume = %i\n", volume);
+               Con_Printf ("SV_StartPointSound: volume = %i\n", nvolume);
                return;
        }
 
@@ -822,7 +828,7 @@ void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float at
 
        speed4000 = (int)(speed * 40.0f);
        field_mask = 0;
-       if (volume != DEFAULT_SOUND_PACKET_VOLUME)
+       if (nvolume != DEFAULT_SOUND_PACKET_VOLUME)
                field_mask |= SND_VOLUME;
        if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
                field_mask |= SND_ATTENUATION;
@@ -835,7 +841,7 @@ void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float at
        MSG_WriteByte (&sv.datagram, svc_sound);
        MSG_WriteByte (&sv.datagram, field_mask);
        if (field_mask & SND_VOLUME)
-               MSG_WriteByte (&sv.datagram, volume);
+               MSG_WriteByte (&sv.datagram, nvolume);
        if (field_mask & SND_ATTENUATION)
                MSG_WriteByte (&sv.datagram, (int)(attenuation*64));
        if (field_mask & SND_SPEEDUSHORT4000)
@@ -914,7 +920,6 @@ void SV_SendServerinfo (client_t *client)
        {
                client->csqcentityscope[i] = 0;
                client->csqcentitysendflags[i] = 0xFFFFFF;
-               client->csqcentityglobalhistory[i] = 0;
        }
        for (i = 0;i < NUM_CSQCENTITYDB_FRAMES;i++)
        {
@@ -930,17 +935,17 @@ void SV_SendServerinfo (client_t *client)
        MSG_WriteString (&client->netconnection->message,message);
 
        SV_StopDemoRecording(client); // to split up demos into different files
-       if(sv_autodemo_perclient.integer && client->netconnection)
+       if(sv_autodemo_perclient.integer)
        {
                char demofile[MAX_OSPATH];
                char ipaddress[MAX_QPATH];
-               size_t i;
+               size_t j;
 
                // start a new demo file
                LHNETADDRESS_ToString(&(client->netconnection->peeraddress), ipaddress, sizeof(ipaddress), true);
-               for(i = 0; ipaddress[i]; ++i)
-                       if(!isalnum(ipaddress[i]))
-                               ipaddress[i] = '-';
+               for(j = 0; ipaddress[j]; ++j)
+                       if(!isalnum(ipaddress[j]))
+                               ipaddress[j] = '-';
                dpsnprintf (demofile, sizeof(demofile), "%s_%s_%d_%s.dem", Sys_TimeString (sv_autodemo_perclient_nameformat.string), sv.worldbasename, PRVM_NUM_FOR_EDICT(client->edict), ipaddress);
 
                SV_StartDemoRecording(client, demofile, -1);
@@ -959,14 +964,14 @@ void SV_SendServerinfo (client_t *client)
 
                if(client->sv_demo_file != NULL)
                {
-                       int i;
+                       int k;
                        static char buf[NET_MAXMESSAGE];
                        sizebuf_t sb;
 
                        sb.data = (unsigned char *) buf;
                        sb.maxsize = sizeof(buf);
-                       i = 0;
-                       while(MakeDownloadPacket(sv.csqc_progname, svs.csqc_progdata, sv.csqc_progsize, sv.csqc_progcrc, i++, &sb, sv.protocol))
+                       k = 0;
+                       while(MakeDownloadPacket(sv.csqc_progname, svs.csqc_progdata, sv.csqc_progsize, sv.csqc_progcrc, k++, &sb, sv.protocol))
                                SV_WriteDemoMessage(client, &sb, false);
                }
 
@@ -1082,12 +1087,14 @@ void SV_ConnectClient (int clientnum, netconn_t *netconnection)
 
        if(client->netconnection && client->netconnection->crypto.authenticated)
        {
-               Con_Printf("%s connection to %s has been established: client is %s@%.*s, I am %.*s@%.*s\n",
+               Con_Printf("%s connection to %s has been established: client is %s@%s%.*s, I am %.*s@%s%.*s\n",
                                client->netconnection->crypto.use_aes ? "Encrypted" : "Authenticated",
                                client->netconnection->address,
                                client->netconnection->crypto.client_idfp[0] ? client->netconnection->crypto.client_idfp : "-",
+                               (client->netconnection->crypto.client_issigned || !client->netconnection->crypto.client_keyfp[0]) ? "" : "~",
                                crypto_keyfp_recommended_length, client->netconnection->crypto.client_keyfp[0] ? client->netconnection->crypto.client_keyfp : "-",
                                crypto_keyfp_recommended_length, client->netconnection->crypto.server_idfp[0] ? client->netconnection->crypto.server_idfp : "-",
+                               (client->netconnection->crypto.server_issigned || !client->netconnection->crypto.server_keyfp[0]) ? "" : "~",
                                crypto_keyfp_recommended_length, client->netconnection->crypto.server_keyfp[0] ? client->netconnection->crypto.server_keyfp : "-"
                                );
        }
@@ -1681,7 +1688,7 @@ static void SV_MarkWriteEntityStateToClient(entity_state_t *s)
                        }
 
                        // or not seen by random tracelines
-                       if (sv_cullentities_trace.integer && !isbmodel && sv.worldmodel->brush.TraceLineOfSight && !r_trippy.integer)
+                       if (sv_cullentities_trace.integer && !isbmodel && sv.worldmodel && sv.worldmodel->brush.TraceLineOfSight && !r_trippy.integer)
                        {
                                int samples =
                                        s->number <= svs.maxclients
@@ -2209,7 +2216,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
                MSG_WriteByte (msg, stats[STAT_NAILS]);
                MSG_WriteByte (msg, stats[STAT_ROCKETS]);
                MSG_WriteByte (msg, stats[STAT_CELLS]);
-               if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_QUOTH || gamemode == GAME_NEXUIZ)
+               if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_QUOTH || IS_OLDNEXUIZ_DERIVED(gamemode))
                {
                        for (i = 0;i < 32;i++)
                                if (stats[STAT_ACTIVEWEAPON] & (1<<i))
@@ -2474,7 +2481,9 @@ static void SV_UpdateToReliableMessages (void)
                if (name == NULL)
                        name = "";
                // always point the string back at host_client->name to keep it safe
-               strlcpy (host_client->name, name, sizeof (host_client->name));
+               //strlcpy (host_client->name, name, sizeof (host_client->name));
+               if (name != host_client->name) // prevent buffer overlap SIGABRT on Mac OSX
+                       strlcpy (host_client->name, name, sizeof (host_client->name));
                PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(prog, host_client->name);
                if (strcmp(host_client->old_name, host_client->name))
                {
@@ -2504,7 +2513,9 @@ static void SV_UpdateToReliableMessages (void)
                if (model == NULL)
                        model = "";
                // always point the string back at host_client->name to keep it safe
-               strlcpy (host_client->playermodel, model, sizeof (host_client->playermodel));
+               //strlcpy (host_client->playermodel, model, sizeof (host_client->playermodel));
+               if (model != host_client->playermodel) // prevent buffer overlap SIGABRT on Mac OSX
+                       strlcpy (host_client->playermodel, model, sizeof (host_client->playermodel));
                PRVM_serveredictstring(host_client->edict, playermodel) = PRVM_SetEngineString(prog, host_client->playermodel);
 
                // NEXUIZ_PLAYERSKIN
@@ -2512,7 +2523,9 @@ static void SV_UpdateToReliableMessages (void)
                if (skin == NULL)
                        skin = "";
                // always point the string back at host_client->name to keep it safe
-               strlcpy (host_client->playerskin, skin, sizeof (host_client->playerskin));
+               //strlcpy (host_client->playerskin, skin, sizeof (host_client->playerskin));
+               if (skin != host_client->playerskin) // prevent buffer overlap SIGABRT on Mac OSX
+                       strlcpy (host_client->playerskin, skin, sizeof (host_client->playerskin));
                PRVM_serveredictstring(host_client->edict, playerskin) = PRVM_SetEngineString(prog, host_client->playerskin);
 
                // TODO: add an extension name for this [1/17/2008 Black]
@@ -2533,7 +2546,7 @@ static void SV_UpdateToReliableMessages (void)
 
                // frags
                host_client->frags = (int)PRVM_serveredictfloat(host_client->edict, frags);
-               if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
+               if(IS_OLDNEXUIZ_DERIVED(gamemode))
                        if(!host_client->begun && host_client->netconnection)
                                host_client->frags = -666;
                if (host_client->old_frags != host_client->frags)
@@ -3012,7 +3025,7 @@ int SV_ParticleEffectIndex(const char *name)
                                {
                                        if (argc == 2)
                                        {
-                                               for (effectnameindex = 1;effectnameindex < SV_MAX_PARTICLEEFFECTNAME;effectnameindex++)
+                                               for (effectnameindex = 1;effectnameindex < MAX_PARTICLEEFFECTNAME;effectnameindex++)
                                                {
                                                        if (sv.particleeffectname[effectnameindex][0])
                                                        {
@@ -3026,7 +3039,7 @@ int SV_ParticleEffectIndex(const char *name)
                                                        }
                                                }
                                                // if we run out of names, abort
-                                               if (effectnameindex == SV_MAX_PARTICLEEFFECTNAME)
+                                               if (effectnameindex == MAX_PARTICLEEFFECTNAME)
                                                {
                                                        Con_Printf("%s:%i: too many effects!\n", filename, linenumber);
                                                        break;
@@ -3038,7 +3051,7 @@ int SV_ParticleEffectIndex(const char *name)
                }
        }
        // search for the name
-       for (effectnameindex = 1;effectnameindex < SV_MAX_PARTICLEEFFECTNAME && sv.particleeffectname[effectnameindex][0];effectnameindex++)
+       for (effectnameindex = 1;effectnameindex < MAX_PARTICLEEFFECTNAME && sv.particleeffectname[effectnameindex][0];effectnameindex++)
                if (!strcmp(sv.particleeffectname[effectnameindex], name))
                        return effectnameindex;
        // return 0 if we couldn't find it
@@ -3344,6 +3357,8 @@ void SV_SpawnServer (const char *server)
        cls.signon = 0;
 
        Cvar_SetValue("halflifebsp", worldmodel->brush.ishlbsp);
+       Cvar_SetValue("sv_mapformat_is_quake2", worldmodel->brush.isq2bsp);
+       Cvar_SetValue("sv_mapformat_is_quake3", worldmodel->brush.isq3bsp);
 
        if(*sv_random_seed.string)
        {
@@ -3479,12 +3494,15 @@ void SV_SpawnServer (const char *server)
 
 // run two frames to allow everything to settle
        sv.time = 1.0001;
-       for (i = 0;i < 2;i++)
+       for (i = 0;i < sv_init_frame_count.integer;i++)
        {
                sv.frametime = 0.1;
                SV_Physics ();
        }
 
+       // Once all init frames have been run, we consider svqc code fully initialized.
+       prog->inittime = realtime;
+
        if (cls.state == ca_dedicated)
                Mod_PurgeUnused();
 
@@ -3588,6 +3606,7 @@ static void SVVM_init_edict(prvm_prog_t *prog, prvm_edict_t *e)
                        PRVM_serveredictstring(e, crypto_idfp) = PRVM_SetEngineString(prog, svs.clients[num].netconnection->crypto.client_idfp);
                else
                        PRVM_serveredictstring(e, crypto_idfp) = 0;
+               PRVM_serveredictfloat(e, crypto_idfp_signed) = (svs.clients[num].netconnection != NULL && svs.clients[num].netconnection->crypto.authenticated && svs.clients[num].netconnection->crypto.client_issigned);
                if(svs.clients[num].netconnection != NULL && svs.clients[num].netconnection->crypto.authenticated && svs.clients[num].netconnection->crypto.client_keyfp[0])
                        PRVM_serveredictstring(e, crypto_keyfp) = PRVM_SetEngineString(prog, svs.clients[num].netconnection->crypto.client_keyfp);
                else
@@ -3633,11 +3652,7 @@ static void SVVM_free_edict(prvm_prog_t *prog, prvm_edict_t *ed)
        e = PRVM_NUM_FOR_EDICT(ed);
        sv.csqcentityversion[e] = 0;
        for (i = 0;i < svs.maxclients;i++)
-       {
-               if (svs.clients[i].csqcentityscope[e])
-                       svs.clients[i].csqcentityscope[e] = 1; // removed, awaiting send
                svs.clients[i].csqcentitysendflags[e] = 0xFFFFFF;
-       }
 }
 
 static void SVVM_count_edicts(prvm_prog_t *prog)