]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
new cvar: sv_status_show_qcstatus
[xonotic/darkplaces.git] / sv_main.c
index fedd7c38bc53019e7ad821931ab212b2b40b88c8..4e541af0153185e5b643431b119174e230716519 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -31,7 +31,6 @@ static void SV_VM_Setup();
 
 void VM_CustomStats_Clear (void);
 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats);
-void EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numstates, const entity_state_t *states);
 
 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 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)"};
@@ -74,7 +73,7 @@ cvar_t sv_cullentities_trace_samples_extra = {0, "sv_cullentities_trace_samples_
 cvar_t sv_cullentities_trace_samples_players = {0, "sv_cullentities_trace_samples_players", "8", "number of samples to test for entity culling when the entity is a player entity"};
 cvar_t sv_debugmove = {CVAR_NOTIFY, "sv_debugmove", "0", "disables collision detection optimizations for debugging purposes"};
 cvar_t sv_echobprint = {CVAR_SAVE, "sv_echobprint", "1", "prints gamecode bprint() calls to server console"};
-cvar_t sv_edgefriction = {0, "edgefriction", "2", "how much you slow down when nearing a ledge you might fall off"};
+cvar_t sv_edgefriction = {0, "edgefriction", "1", "how much you slow down when nearing a ledge you might fall off, multiplier of sv_friction (Quake used 2, QuakeWorld used 1 due to a bug in physics code)"};
 cvar_t sv_entpatch = {0, "sv_entpatch", "1", "enables loading of .ent files to override entities in the bsp (for example Threewave CTF server pack contains .ent patch files enabling play of CTF on id1 maps)"};
 cvar_t sv_fixedframeratesingleplayer = {0, "sv_fixedframeratesingleplayer", "1", "allows you to use server-style timing system in singleplayer (don't run faster than sys_ticrate)"};
 cvar_t sv_freezenonclients = {CVAR_NOTIFY, "sv_freezenonclients", "0", "freezes time, except for players, allowing you to walk around and take screenshots of explosions"};
@@ -215,6 +214,7 @@ prvm_required_field_t reqfields[] =
        {ev_entity, "nodrawtoclient"},
        {ev_entity, "tag_entity"},
        {ev_entity, "viewmodelforclient"},
+       {ev_float, "SendFlags"},
        {ev_float, "Version"},
        {ev_float, "alpha"},
        {ev_float, "ammo_cells1"},
@@ -733,7 +733,19 @@ void SV_SendServerinfo (client_t *client)
        }
 
        // reset csqc entity versions
-       memset(client->csqcentityversion, 0, sizeof(client->csqcentityversion));
+       for (i = 0;i < prog->max_edicts;i++)
+       {
+               client->csqcentityscope[i] = 0;
+               client->csqcentitysendflags[i] = 0xFFFFFF;
+               client->csqcentityglobalhistory[i] = 0;
+       }
+       for (i = 0;i < NUM_CSQCENTITYDB_FRAMES;i++)
+       {
+               client->csqcentityframehistory[i].num = 0;
+               client->csqcentityframehistory[i].framenum = -1;
+       }
+       client->csqcnumedicts = 0;
+       client->csqcentityframehistory_next = 0;
 
        SZ_Clear (&client->netconnection->message);
        MSG_WriteByte (&client->netconnection->message, svc_print);
@@ -954,12 +966,14 @@ crosses a waterline.
 static qboolean SV_PrepareEntityForSending (prvm_edict_t *ent, entity_state_t *cs, int enumber)
 {
        int i;
+       unsigned int sendflags;
+       unsigned int version;
        unsigned int modelindex, effects, flags, glowsize, lightstyle, lightpflags, light[4], specialvisibilityradius;
        unsigned int customizeentityforclient;
        float f;
        vec3_t cullmins, cullmaxs;
        dp_model_t *model;
-       prvm_eval_t *val;
+       prvm_eval_t *val, *val2;
 
        // this 2 billion unit check is actually to detect NAN origins
        // (we really don't want to send those)
@@ -1136,7 +1150,7 @@ static qboolean SV_PrepareEntityForSending (prvm_edict_t *ent, entity_state_t *c
        // calculate the visible box of this entity (don't use the physics box
        // as that is often smaller than a model, and would not count
        // specialvisibilityradius)
-       if ((model = sv.models[modelindex]))
+       if ((model = sv.models[modelindex]) && (model->type != mod_null))
        {
                float scale = cs->scale * (1.0f / 16.0f);
                if (cs->angles[0] || cs->angles[2]) // pitch and roll
@@ -1192,6 +1206,30 @@ static qboolean SV_PrepareEntityForSending (prvm_edict_t *ent, entity_state_t *c
                }
        }
 
+       // we need to do some csqc entity upkeep here
+       // get self.SendFlags and clear them
+       // (to let the QC know that they've been read)
+       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.SendEntity);
+       if (val->function)
+       {
+               val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.SendFlags);
+               sendflags = (unsigned int)val->_float;
+               val->_float = 0;
+               // legacy self.Version system
+               val2 = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.Version);
+               if (val2->_float)
+               {
+                       version = (unsigned int)val2->_float;
+                       if (sv.csqcentityversion[enumber] != version)
+                               sendflags = 0xFFFFFF;
+                       sv.csqcentityversion[enumber] = version;
+               }
+               // move sendflags into the per-client sendflags
+               if (sendflags)
+                       for (i = 0;i < svs.maxclients;i++)
+                               svs.clients[i].csqcentitysendflags[enumber] |= sendflags;
+       }
+
        return true;
 }
 
@@ -1416,7 +1454,10 @@ void SV_WriteEntitiesToClient(client_t *client, prvm_edict_t *clent, sizebuf_t *
        if (sv_cullentities_stats.integer)
                Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d trace\n", client->name, sv.writeentitiestoclient_stats_totalentities, sv.writeentitiestoclient_stats_visibleentities, sv.writeentitiestoclient_stats_culled_pvs + sv.writeentitiestoclient_stats_culled_trace, sv.writeentitiestoclient_stats_culled_pvs, sv.writeentitiestoclient_stats_culled_trace);
 
-       EntityFrameCSQC_WriteFrame(msg, maxsize, numsendstates, sv.writeentitiestoclient_sendstates);
+       if(client->entitydatabase5)
+               EntityFrameCSQC_WriteFrame(msg, maxsize, numsendstates, sv.writeentitiestoclient_sendstates, client->entitydatabase5->latestframenum + 1);
+       else
+               EntityFrameCSQC_WriteFrame(msg, maxsize, numsendstates, sv.writeentitiestoclient_sendstates, 0);
 
        if (client->entitydatabase5)
                EntityFrame5_WriteFrame(msg, maxsize, client->entitydatabase5, numsendstates, sv.writeentitiestoclient_sendstates, client - svs.clients + 1, client->movesequence);
@@ -1957,7 +1998,7 @@ static void SV_UpdateToReliableMessages (void)
                if (strcmp(host_client->old_name, host_client->name))
                {
                        if (host_client->spawned)
-                               SV_BroadcastPrintf("%s changed name to %s\n", host_client->old_name, host_client->name);
+                               SV_BroadcastPrintf("%s ^7changed 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);
@@ -2190,7 +2231,7 @@ static void SV_Download_f(void)
                }
        }
 
-       host_client->download_file = FS_Open(host_client->download_name, "rb", true, false);
+       host_client->download_file = FS_OpenVirtualFile(host_client->download_name, true);
        if (!host_client->download_file)
        {
                SV_ClientPrintf("Download rejected: server could not open the file \"%s\"\n", host_client->download_name);
@@ -2850,6 +2891,9 @@ static void SV_VM_CB_InitEdict(prvm_edict_t *e)
 
 static void SV_VM_CB_FreeEdict(prvm_edict_t *ed)
 {
+       int i;
+       int e;
+
        World_UnlinkEdict(ed);          // unlink from world bsp
 
        ed->fields.server->model = 0;
@@ -2862,6 +2906,16 @@ static void SV_VM_CB_FreeEdict(prvm_edict_t *ed)
        VectorClear(ed->fields.server->angles);
        ed->fields.server->nextthink = -1;
        ed->fields.server->solid = 0;
+
+       // make sure csqc networking is aware of the removed entity
+       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 SV_VM_CB_CountEdicts(void)