// get the next message
FS_Read(cls.demofile, &net_message.cursize, 4);
net_message.cursize = LittleLong(net_message.cursize);
+ if(net_message.cursize & DEMOMSG_CLIENT_TO_SERVER) // This is a client->server message! Ignore for now!
+ continue;
if (net_message.cursize > net_message.maxsize)
Host_Error("Demo message (%i) > net_message.maxsize (%i)", net_message.cursize, net_message.maxsize);
VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
void Sys_Shared_Init(void);
+// Flag in size field of demos to indicate a client->server packet. Demo
+// playback will ignore this, but it may be useful to make DP sniff packets to
+// debug protocol exploits.
+#define DEMOMSG_CLIENT_TO_SERVER 0x80000000
+
#endif
FS_Printf(client->sv_demo_file, "%i\n", forcetrack);
}
-void SV_WriteDemoMessage(client_t *client, sizebuf_t *sendbuffer)
+void SV_WriteDemoMessage(client_t *client, sizebuf_t *sendbuffer, qboolean clienttoserver)
{
int len, i;
float f;
if(sendbuffer->cursize == 0)
return;
- len = LittleLong(sendbuffer->cursize);
+ len = LittleLong(sendbuffer->cursize | (clienttoserver ? DEMOMSG_CLIENT_TO_SERVER : 0));
FS_Write(client->sv_demo_file, &len, 4);
for(i = 0; i < 3; ++i)
{
buf.maxsize = sizeof(bufdata);
SZ_Clear(&buf);
MSG_WriteByte(&buf, svc_disconnect);
- SV_WriteDemoMessage(client, &buf);
+ SV_WriteDemoMessage(client, &buf, false);
FS_Close(client->sv_demo_file);
client->sv_demo_file = NULL;
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);
+ SV_WriteDemoMessage(client, &buf, false);
}
#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_WriteDemoMessage(client_t *client, sizebuf_t *sendbuffer, qboolean clienttoserver);
void SV_StopDemoRecording(client_t *client);
void SV_WriteNetnameIntoDemo(client_t *client);
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 = {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); set it to 2 to also record client->server packets (for debugging)"};
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" };
// reliable only if none is in progress
if(client->sendsignon != 2 && !client->netconnection->sendMessageLength)
- SV_WriteDemoMessage(client, &(client->netconnection->message));
+ SV_WriteDemoMessage(client, &(client->netconnection->message), false);
// unreliable
- SV_WriteDemoMessage(client, &msg);
+ SV_WriteDemoMessage(client, &msg, false);
// send the datagram
NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate, client->sendsignon == 2);
// sv_user.c -- server code for moving users
#include "quakedef.h"
+#include "sv_demo.h"
#define DEBUGMOVES 0
static usercmd_t cmd;
+extern cvar_t sv_autodemo_perclient;
/*
===============
int cmd, num, start;
char *s, *p, *q;
+ if(sv_autodemo_perclient.integer >= 2)
+ SV_WriteDemoMessage(host_client, &(host_client->netconnection->message), true);
+
//MSG_BeginReading ();
sv_numreadmoves = 0;