reworked PRVM_EDICTFIELD* and PRVM_GLOBALFIELD* usage to have more
[xonotic/darkplaces.git] / sv_demo.c
1 #include "quakedef.h"
2 #include "sv_demo.h"
3
4 extern cvar_t sv_autodemo_perclient_discardable;
5
6 void SV_StartDemoRecording(client_t *client, const char *filename, int forcetrack)
7 {
8         char name[MAX_QPATH];
9
10         if(client->sv_demo_file != NULL)
11                 return; // we already have a demo
12
13         strlcpy(name, filename, sizeof(name));
14         FS_DefaultExtension(name, ".dem", sizeof(name));
15
16         Con_Printf("Recording demo for # %d (%s) to %s\n", PRVM_NUM_FOR_EDICT(client->edict), client->netaddress, name);
17
18         // Reset discardable flag for every new demo.
19         PRVM_serveredictfloat(client->edict, discardabledemo) = 0;
20
21         client->sv_demo_file = FS_OpenRealFile(name, "wb", false);
22         if(!client->sv_demo_file)
23         {
24                 Con_Print("ERROR: couldn't open.\n");
25                 return;
26         }
27
28         FS_Printf(client->sv_demo_file, "%i\n", forcetrack);
29 }
30
31 void SV_WriteDemoMessage(client_t *client, sizebuf_t *sendbuffer, qboolean clienttoserver)
32 {
33         int len, i;
34         float f;
35         int temp;
36
37         if(client->sv_demo_file == NULL)
38                 return;
39         if(sendbuffer->cursize == 0)
40                 return;
41         
42         temp = sendbuffer->cursize | (clienttoserver ? DEMOMSG_CLIENT_TO_SERVER : 0);
43         len = LittleLong(temp);
44         FS_Write(client->sv_demo_file, &len, 4);
45         for(i = 0; i < 3; ++i)
46         {
47                 f = LittleFloat(client->edict->fields.server->v_angle[i]);
48                 FS_Write(client->sv_demo_file, &f, 4);
49         }
50         FS_Write(client->sv_demo_file, sendbuffer->data, sendbuffer->cursize);
51 }
52
53 void SV_StopDemoRecording(client_t *client)
54 {
55         sizebuf_t buf;
56         unsigned char bufdata[64];
57
58         if(client->sv_demo_file == NULL)
59                 return;
60         
61         buf.data = bufdata;
62         buf.maxsize = sizeof(bufdata);
63         SZ_Clear(&buf);
64         MSG_WriteByte(&buf, svc_disconnect);
65         SV_WriteDemoMessage(client, &buf, false);
66
67         if (sv_autodemo_perclient_discardable.integer && PRVM_serveredictfloat(client->edict, discardabledemo))
68         {
69                 FS_RemoveOnClose(client->sv_demo_file);
70                 Con_Printf("Stopped recording discardable demo for # %d (%s)\n", PRVM_NUM_FOR_EDICT(client->edict), client->netaddress);
71         }
72         else
73                 Con_Printf("Stopped recording demo for # %d (%s)\n", PRVM_NUM_FOR_EDICT(client->edict), client->netaddress);
74
75         FS_Close(client->sv_demo_file);
76         client->sv_demo_file = NULL;
77 }
78
79 void SV_WriteNetnameIntoDemo(client_t *client)
80 {
81         // This "pseudo packet" is written so a program can easily find out whose demo this is
82         sizebuf_t buf;
83         unsigned char bufdata[128];
84
85         if(client->sv_demo_file == NULL)
86                 return;
87
88         buf.data = bufdata;
89         buf.maxsize = sizeof(bufdata);
90         SZ_Clear(&buf);
91         MSG_WriteByte(&buf, svc_stufftext);
92         MSG_WriteUnterminatedString(&buf, "\n// this demo contains the point of view of: ");
93         MSG_WriteUnterminatedString(&buf, client->name);
94         MSG_WriteString(&buf, "\n");
95         SV_WriteDemoMessage(client, &buf, false);
96 }