From fa8c676e225398a6157e591248a12d6847cef9a4 Mon Sep 17 00:00:00 2001 From: divverent Date: Sun, 9 Sep 2007 08:54:14 +0000 Subject: [PATCH] sv_autodemo_perclient - record client-like demos on the server (same format, lagged (no support of cl_movement), so basically, just like spectating) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7564 d7cf8633-e32d-0410-b094-e92efae38249 --- host.c | 3 ++ host_cmd.c | 2 ++ makefile.inc | 3 +- server.h | 3 ++ sv_demo.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ sv_demo.h | 9 ++++++ sv_main.c | 37 ++++++++++++++++++++++++ 7 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 sv_demo.c create mode 100644 sv_demo.h diff --git a/host.c b/host.c index 521114be..7888bffd 100644 --- a/host.c +++ b/host.c @@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "cl_video.h" #include "progsvm.h" #include "csprogs.h" +#include "sv_demo.h" /* @@ -373,6 +374,8 @@ void SV_DropClient(qboolean crash) int i; Con_Printf("Client \"%s\" dropped\n", host_client->name); + SV_StopDemoRecording(host_client); + // make sure edict is not corrupt (from a level change for example) host_client->edict = PRVM_EDICT_NUM(host_client - svs.clients + 1); diff --git a/host_cmd.c b/host_cmd.c index 463fb729..dbd917dc 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "quakedef.h" +#include "sv_demo.h" int current_skill; cvar_t sv_cheats = {0, "sv_cheats", "0", "enables cheat commands in any game, and cheat impulses in dpmod"}; @@ -808,6 +809,7 @@ void Host_Name_f (void) MSG_WriteByte (&sv.reliable_datagram, svc_updatename); MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients); MSG_WriteString (&sv.reliable_datagram, host_client->name); + SV_WriteNetnameIntoDemo(host_client); } } diff --git a/makefile.inc b/makefile.inc index 8dc32881..41035ebd 100644 --- a/makefile.inc +++ b/makefile.inc @@ -128,7 +128,8 @@ OBJ_COMMON= \ view.o \ wad.o \ world.o \ - zone.o + zone.o \ + sv_demo.c # note that builddate.c is very intentionally not compiled to a .o before # being linked, because it should be recompiled every time an executable is diff --git a/server.h b/server.h index d7df3880..16ddb66a 100644 --- a/server.h +++ b/server.h @@ -242,6 +242,9 @@ typedef struct client_s // fixangle data qboolean fixangle_angles_set; vec3_t fixangle_angles; + + // demo recording + qfile_t *sv_demo_file; } client_t; diff --git a/sv_demo.c b/sv_demo.c new file mode 100644 index 00000000..3ba4349a --- /dev/null +++ b/sv_demo.c @@ -0,0 +1,82 @@ +#include "quakedef.h" +#include "sv_demo.h" + +void SV_StartDemoRecording(client_t *client, const char *filename, int forcetrack) +{ + char name[MAX_QPATH]; + + if(client->sv_demo_file != NULL) + return; // we already have a demo + + strlcpy(name, filename, sizeof(name)); + FS_DefaultExtension(name, ".dem", sizeof(name)); + + Con_Printf("Recording demo for # %d (%s) to %s\n", PRVM_NUM_FOR_EDICT(client->edict), client->netaddress, name); + + client->sv_demo_file = FS_Open(name, "wb", false, false); + if(!client->sv_demo_file) + { + Con_Print("ERROR: couldn't open.\n"); + return; + } + + FS_Printf(client->sv_demo_file, "%i\n", forcetrack); +} + +void SV_WriteDemoMessage(client_t *client, sizebuf_t *sendbuffer) +{ + int len, i; + float f; + + if(client->sv_demo_file == NULL) + return; + if(sendbuffer->cursize == 0) + return; + + len = LittleLong(sendbuffer->cursize); + FS_Write(client->sv_demo_file, &len, 4); + for(i = 0; i < 3; ++i) + { + f = LittleFloat(client->edict->fields.server->v_angle[i]); + FS_Write(client->sv_demo_file, &f, 4); + } + FS_Write(client->sv_demo_file, sendbuffer->data, sendbuffer->cursize); +} + +void SV_StopDemoRecording(client_t *client) +{ + sizebuf_t buf; + unsigned char bufdata[64]; + + if(client->sv_demo_file == NULL) + return; + + buf.data = bufdata; + buf.maxsize = sizeof(bufdata); + SZ_Clear(&buf); + MSG_WriteByte(&buf, svc_disconnect); + SV_WriteDemoMessage(client, &buf); + + FS_Close(client->sv_demo_file); + client->sv_demo_file = NULL; + Con_Printf("Stopped recording demo for # %d (%s)\n", PRVM_NUM_FOR_EDICT(client->edict), client->netaddress); +} + +void SV_WriteNetnameIntoDemo(client_t *client) +{ + // This "pseudo packet" is written so a program can easily find out whose demo this is + sizebuf_t buf; + unsigned char bufdata[128]; + + if(client->sv_demo_file == NULL) + return; + + buf.data = bufdata; + buf.maxsize = sizeof(bufdata); + SZ_Clear(&buf); + MSG_WriteByte(&buf, svc_stufftext); + MSG_WriteUnterminatedString(&buf, "\n// this demo contains the point of view of: "); + MSG_WriteUnterminatedString(&buf, client->name); + MSG_WriteString(&buf, "\n"); + SV_WriteDemoMessage(client, &buf); +} diff --git a/sv_demo.h b/sv_demo.h new file mode 100644 index 00000000..ad26d9d4 --- /dev/null +++ b/sv_demo.h @@ -0,0 +1,9 @@ +#ifndef SV_DEMO_H +#define SV_DEMO_H + +void SV_StartDemoRecording(client_t *client, const char *filename, int forcetrack); +void SV_WriteDemoMessage(client_t *client, sizebuf_t *sendbuffer); +void SV_StopDemoRecording(client_t *client); +void SV_WriteNetnameIntoDemo(client_t *client); + +#endif diff --git a/sv_main.c b/sv_main.c index 17dbf2c3..0db7e303 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); @@ -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) { @@ -797,6 +805,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); + } } /* @@ -1755,6 +1785,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 +1833,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 -- 2.39.2