X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=sv_main.c;h=b2afd2637b4152126bac82dd6eebca8988932e96;hp=17dbf2c38bc57d2f7d6a62fc97153e98ce7bb5e1;hb=3869bc4ae01a780a71af98e2f49c5b2f9297c9ae;hpb=4ed0394dfb5ec223db2b82a53db57acc442c7fde diff --git a/sv_main.c b/sv_main.c index 17dbf2c3..b2afd263 100644 --- a/sv_main.c +++ b/sv_main.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // sv_main.c -- server main program #include "quakedef.h" +#include "sv_demo.h" #include "libcurl.h" static void SV_SaveEntFile_f(void); @@ -58,7 +59,7 @@ cvar_t sv_checkforpacketsduringsleep = {0, "sv_checkforpacketsduringsleep", "0", cvar_t sv_clmovement_enable = {0, "sv_clmovement_enable", "1", "whether to allow clients to use cl_movement prediction, which can cause choppy movement on the server which may annoy other players"}; cvar_t sv_clmovement_minping = {0, "sv_clmovement_minping", "0", "if client ping is below this time in milliseconds, then their ability to use cl_movement prediction is disabled for a while (as they don't need it)"}; cvar_t sv_clmovement_minping_disabletime = {0, "sv_clmovement_minping_disabletime", "1000", "when client falls below minping, disable their prediction for this many milliseconds (should be at least 1000 or else their prediction may turn on/off frequently)"}; -cvar_t sv_clmovement_waitforinput = {0, "sv_clmovement_waitforinput", "16", "when a client does not send input for this many frames, force them to move anyway (unlike QuakeWorld)"}; +cvar_t sv_clmovement_waitforinput = {0, "sv_clmovement_waitforinput", "4", "when a client does not send input for this many frames, force them to move anyway (unlike QuakeWorld)"}; cvar_t sv_cullentities_nevercullbmodels = {0, "sv_cullentities_nevercullbmodels", "0", "if enabled the clients are always notified of moving doors and lifts and other submodels of world (warning: eats a lot of network bandwidth on some levels!)"}; cvar_t sv_cullentities_pvs = {0, "sv_cullentities_pvs", "1", "fast but loose culling of hidden entities"}; cvar_t sv_cullentities_stats = {0, "sv_cullentities_stats", "0", "displays stats on network entities culled by various methods for each client"}; @@ -147,6 +148,10 @@ cvar_t nehx18 = {0, "nehx18", "0", "nehahra data storage cvar (used in singlepla cvar_t nehx19 = {0, "nehx19", "0", "nehahra data storage cvar (used in singleplayer)"}; cvar_t cutscene = {0, "cutscene", "1", "enables cutscenes in nehahra, can be used by other mods"}; +cvar_t sv_autodemo_perclient = {CVAR_SAVE, "sv_autodemo_perclient", "0", "set to 1 to enable autorecorded per-client demos (they'll start to record at the beginning of a match)"}; +cvar_t sv_autodemo_perclient_nameformat = {CVAR_SAVE, "sv_autodemo_perclient_nameformat", "sv_autodemos/%Y-%m-%d_%H-%M", "The format of the sv_autodemo_perclient filename, followed by the map name, the IP address + port number, and the client number, separated by underscores" }; + + server_t sv; server_static_t svs; @@ -417,6 +422,9 @@ void SV_Init (void) } Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well + Cvar_RegisterVariable (&sv_autodemo_perclient); + Cvar_RegisterVariable (&sv_autodemo_perclient_nameformat); + // any special defaults for gamemodes go here if (gamemode == GAME_HIPNOTIC) { @@ -586,7 +594,7 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v } else MSG_WriteShort (&sv.datagram, (ent<<3) | channel); - if (field_mask & SND_LARGESOUND) + if ((field_mask & SND_LARGESOUND) || sv.protocol == PROTOCOL_NEHAHRABJP2) MSG_WriteShort (&sv.datagram, sound_num); else MSG_WriteByte (&sv.datagram, sound_num); @@ -691,6 +699,9 @@ void SV_SendServerinfo (client_t *client) // LordHavoc: clear entityframe tracking client->latestframenum = 0; + // initialize the movetime, so a speedhack can't make use of the time before this client joined + client->cmd.time = sv.time; + if (client->entitydatabase) EntityFrame_FreeDatabase(client->entitydatabase); if (client->entitydatabase4) @@ -701,7 +712,7 @@ void SV_SendServerinfo (client_t *client) memset(client->stats, 0, sizeof(client->stats)); memset(client->statsdeltabits, 0, sizeof(client->statsdeltabits)); - if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE) + if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3) { if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3) client->entitydatabase = EntityFrame_AllocDatabase(sv_mempool); @@ -797,6 +808,28 @@ void SV_SendServerinfo (client_t *client) client->num_pings = 0; #endif client->ping = 0; + + SV_StopDemoRecording(client); // to split up demos into different files + if(sv_autodemo_perclient.integer && client->netconnection) + { + char demofile[MAX_OSPATH]; + char levelname[MAX_QPATH]; + char ipaddress[MAX_QPATH]; + size_t i; + + // start a new demo file + strlcpy(levelname, FS_FileWithoutPath(sv.worldmodel->name), sizeof(levelname)); + if (strrchr(levelname, '.')) + *(strrchr(levelname, '.')) = 0; + + LHNETADDRESS_ToString(&(client->netconnection->peeraddress), ipaddress, sizeof(ipaddress), true); + for(i = 0; ipaddress[i]; ++i) + if(!isalnum(ipaddress[i])) + ipaddress[i] = '-'; + dpsnprintf (demofile, sizeof(demofile), "%s_%s_%s_%d.dem", Sys_TimeString (sv_autodemo_perclient_nameformat.string), levelname, ipaddress, PRVM_NUM_FOR_EDICT(client->edict)); + + SV_StartDemoRecording(client, demofile, -1); + } } /* @@ -1266,7 +1299,7 @@ static void SV_WriteEntitiesToClient(client_t *client, prvm_edict_t *clent, size VectorAdd(clent->fields.server->origin, clent->fields.server->view_ofs, sv.writeentitiestoclient_testeye); sv.writeentitiestoclient_pvsbytes = 0; if (sv.worldmodel && sv.worldmodel->brush.FatPVS) - sv.writeentitiestoclient_pvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, sv.writeentitiestoclient_testeye, 8, sv.writeentitiestoclient_pvs, sizeof(sv.writeentitiestoclient_pvs)); + sv.writeentitiestoclient_pvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, sv.writeentitiestoclient_testeye, 8, sv.writeentitiestoclient_pvs, sizeof(sv.writeentitiestoclient_pvs), false); sv.writeentitiestoclient_cliententitynumber = PRVM_EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes @@ -1415,7 +1448,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t { if (ent->fields.server->punchangle[i]) bits |= (SU_PUNCH1<fields.server->velocity[i]) @@ -1467,7 +1500,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t 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) + if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5) { if (stats[STAT_VIEWHEIGHT] != DEFAULT_VIEWHEIGHT) bits |= SU_VIEWHEIGHT; bits |= SU_ITEMS; @@ -1503,7 +1536,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t { if (bits & (SU_PUNCH1<fields.server->punchangle[i]); else MSG_WriteAngle16i(msg, ent->fields.server->punchangle[i]); @@ -1517,7 +1550,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t } if (bits & (SU_VELOCITY1<fields.server->velocity[i] * (1.0f / 16.0f))); else MSG_WriteCoord32f(msg, ent->fields.server->velocity[i]); @@ -1545,14 +1578,19 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t if (bits & SU_VIEWZOOM) MSG_WriteShort (msg, bound(0, stats[STAT_VIEWZOOM], 65535)); } - else 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) + else if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4) { if (bits & SU_WEAPONFRAME) MSG_WriteByte (msg, stats[STAT_WEAPONFRAME]); if (bits & SU_ARMOR) MSG_WriteByte (msg, stats[STAT_ARMOR]); if (bits & SU_WEAPON) - MSG_WriteByte (msg, stats[STAT_WEAPON]); + { + if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + MSG_WriteShort (msg, stats[STAT_WEAPON]); + else + MSG_WriteByte (msg, stats[STAT_WEAPON]); + } MSG_WriteShort (msg, stats[STAT_HEALTH]); MSG_WriteByte (msg, stats[STAT_AMMO]); MSG_WriteByte (msg, stats[STAT_SHELLS]); @@ -1659,7 +1697,7 @@ static void SV_SendClientDatagram (client_t *client) maxsize = sizeof(sv_sendclientdatagram_buf); maxsize2 = sizeof(sv_sendclientdatagram_buf); } - else 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) + else if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4) { // no packet size limit support on older protocols because DP1-4 kick // the client off if they overflow, and quake protocol shows less than @@ -1755,6 +1793,12 @@ static void SV_SendClientDatagram (client_t *client) SZ_Write (&msg, data, downloadsize); } + // reliable only if none is in progress + if(client->sendsignon != 2 && !client->netconnection->sendMessageLength) + SV_WriteDemoMessage(client, &(client->netconnection->message)); + // unreliable + SV_WriteDemoMessage(client, &msg); + // send the datagram NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate, client->sendsignon == 2); if (client->sendsignon == 1 && !client->netconnection->message.cursize) @@ -1797,6 +1841,7 @@ static void SV_UpdateToReliableMessages (void) MSG_WriteByte (&sv.reliable_datagram, svc_updatename); MSG_WriteByte (&sv.reliable_datagram, i); MSG_WriteString (&sv.reliable_datagram, host_client->name); + SV_WriteNetnameIntoDemo(host_client); } // DP_SV_CLIENTCOLORS @@ -2047,7 +2092,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) ? 256 : MAX_MODELS); + 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); char filename[MAX_QPATH]; if (!s || !*s) return 0; @@ -2061,7 +2106,7 @@ int SV_ModelIndex(const char *s, int precachemode) { if (precachemode) { - if (sv.state != ss_loading && (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)) + if (sv.state != ss_loading && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)) { Con_Printf("SV_ModelIndex(\"%s\"): precache_model can only be done in spawn functions\n", filename); return 0; @@ -2096,7 +2141,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) ? 256 : MAX_SOUNDS); + 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); char filename[MAX_QPATH]; if (!s || !*s) return 0; @@ -2110,7 +2155,7 @@ int SV_SoundIndex(const char *s, int precachemode) { if (precachemode) { - if (sv.state != ss_loading && (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)) + if (sv.state != ss_loading && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)) { Con_Printf("SV_SoundIndex(\"%s\"): precache_sound can only be done in spawn functions\n", filename); return 0; @@ -2166,7 +2211,7 @@ int SV_ParticleEffectIndex(const char *name) argc = 0; for (;;) { - if (!COM_ParseToken_Simple(&text, true) || !strcmp(com_token, "\n")) + if (!COM_ParseToken_Simple(&text, true, false) || !strcmp(com_token, "\n")) break; if (argc < 16) { @@ -2258,7 +2303,11 @@ static void SV_CreateBaseline (void) large = false; if (svent->priv.server->baseline.modelindex & 0xFF00 || svent->priv.server->baseline.frame & 0xFF00) + { large = true; + if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + large = false; + } // add to the message if (large) @@ -2272,6 +2321,11 @@ static void SV_CreateBaseline (void) MSG_WriteShort (&sv.signon, svent->priv.server->baseline.modelindex); MSG_WriteShort (&sv.signon, svent->priv.server->baseline.frame); } + else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + { + MSG_WriteShort (&sv.signon, svent->priv.server->baseline.modelindex); + MSG_WriteByte (&sv.signon, svent->priv.server->baseline.frame); + } else { MSG_WriteByte (&sv.signon, svent->priv.server->baseline.modelindex); @@ -2534,7 +2588,7 @@ void SV_SpawnServer (const char *server) Mod_PurgeUnused(); // create a baseline for more efficient communications - if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE) + if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) SV_CreateBaseline (); // send serverinfo to all connected clients, and set up botclients coming back from a level change @@ -2727,6 +2781,8 @@ static void SV_VM_Setup(void) prog->limit_edicts = 2048; // guessing else if (sv.protocol == PROTOCOL_NEHAHRAMOVIE) prog->limit_edicts = 2048; // guessing! + else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + prog->limit_edicts = 4096; // guessing! else prog->limit_edicts = MAX_EDICTS; prog->reserved_edicts = svs.maxclients;