Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Super duper premium serverside demo pre-recording and demo metadata #2

Merged
merged 12 commits into from
Jun 23, 2023
Merged
22 changes: 22 additions & 0 deletions codemp/qcommon/msg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,28 @@ void MSG_Init( msg_t *buf, byte *data, int length ) {
buf->maxsize = length;
}

void MSG_ToBuffered(msg_t* src, bufferedMsg_t* dst) {
dst->allowoverflow = src->allowoverflow;
dst->overflowed = src->overflowed;
dst->oob = src->oob;
dst->maxsize = src->maxsize;
dst->cursize = src->cursize;
dst->readcount = src->readcount;
dst->bit = src->bit;
Com_Memcpy(dst->data, src->data, sizeof(dst->data));
}

void MSG_FromBuffered(msg_t* dst, bufferedMsg_t* src) {
dst->allowoverflow = src->allowoverflow;
dst->overflowed = src->overflowed;
dst->oob = src->oob;
dst->maxsize = src->maxsize;
dst->cursize = src->cursize;
dst->readcount = src->readcount;
dst->bit = src->bit;
Com_Memcpy(dst->data, src->data, sizeof(src->data));
}

void MSG_InitOOB( msg_t *buf, byte *data, int length ) {
if (!g_nOverrideChecked)
{
Expand Down
29 changes: 29 additions & 0 deletions codemp/qcommon/qcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ void MSG_Clear (msg_t *buf);
void MSG_WriteData (msg_t *buf, const void *data, int length);
void MSG_Bitstream( msg_t *buf );


struct usercmd_s;
struct entityState_s;
struct playerState_s;
Expand Down Expand Up @@ -170,6 +171,34 @@ void Sys_ShowIP(void);
#define MAX_DOWNLOAD_BLKSIZE 2048 // 2048 byte block chunks


/*
* Buffered messages (structs that actually contain the data array) for buffering/prerecording
*/

typedef struct {
qboolean allowoverflow; // if false, do a Com_Error
qboolean overflowed; // set to true if the buffer size failed (with allowoverflow set)
qboolean oob; // set to true if the buffer size failed (with allowoverflow set)
byte data[MAX_MSGLEN];
int maxsize;
int cursize;
int readcount;
int bit; // for bitwise reads and writes
} bufferedMsg_t;

typedef struct {
bufferedMsg_t msg;
int msgNum; // Message number
int lastClientCommand; // Need this if we are writing metadata with pre-recording as it is the first thing writen in any message.
int time; // So we can discard very old buffered messages. Or for clientside recording, so we don't have to wait infinitely for old messages to arrive (which they never may).
//qboolean containsFullSnapshot; // Doesn't matter for serverside pre-Recording because we have the keyframes. Comment back in for clientside buffered recording.
qboolean isKeyframe; // Is a gamestate message as typical for writing at the start of demos.
} bufferedMessageContainer_t;

void MSG_ToBuffered(msg_t* src, bufferedMsg_t* dst);
void MSG_FromBuffered(msg_t* dst, bufferedMsg_t* src);


/*
Netchan handles packet fragmentation and out of order / duplicate suppression
*/
Expand Down
27 changes: 27 additions & 0 deletions codemp/server/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ typedef enum {
} clientState_t;


#ifdef DEDICATED
// struct to hold demo data for a single demo
typedef struct {
char demoName[MAX_OSPATH];
Expand All @@ -132,8 +133,19 @@ typedef struct {
fileHandle_t demofile;
qboolean isBot;
int botReliableAcknowledge; // for bots, need to maintain a separate reliableAcknowledge to record server messages into the demo file
struct {
// this is basically the equivalent of the demowaiting and minDeltaFrame values above, except it's for the demo pre-record feature and will be done every sv_demoPreRecordKeyframeDistance seconds.
qboolean keyframeWaiting;
int minDeltaFrame;

int lastKeyframeTime; // When was the last keyframe (gamestate followed by non-delta frames) saved? If more than sv_demoPreRecordKeyframeDistance, we make a new keyframe.
} preRecord;
} demoInfo_t;
#endif

#ifdef DEDICATED
typedef std::vector<bufferedMessageContainer_t>::iterator demoPreRecordBufferIt;
#endif

typedef struct client_s {
clientState_t state;
Expand Down Expand Up @@ -193,7 +205,9 @@ typedef struct client_s {
int oldServerTime;
qboolean csUpdated[MAX_CONFIGSTRINGS];

#ifdef DEDICATED
demoInfo_t demo;
#endif

#ifdef DEDICATED
qboolean disableDuelCull; //set for clients with "Duel see others" option set in cp_pluginDisable on JA+ servers
Expand Down Expand Up @@ -293,14 +307,22 @@ extern cvar_t *sv_newfloodProtect;
extern cvar_t *sv_lanForceRate;
extern cvar_t *sv_needpass;
extern cvar_t *sv_filterCommands;
#ifdef DEDICATED
extern cvar_t *sv_autoDemo;
extern cvar_t *sv_autoDemoBots;
extern cvar_t *sv_autoDemoMaxMaps;
#endif
extern cvar_t *sv_legacyFixes;
extern cvar_t *sv_banFile;
extern cvar_t *sv_maxOOBRate;
extern cvar_t *sv_maxOOBRateIP;
extern cvar_t *sv_autoWhitelist;
#ifdef DEDICATED
extern cvar_t *sv_demoPreRecord;
extern cvar_t *sv_demoPreRecordTime;
extern cvar_t *sv_demoPreRecordKeyframeDistance;
extern cvar_t *sv_demoWriteMeta;
#endif

extern cvar_t *sv_snapShotDuelCull;

Expand Down Expand Up @@ -407,11 +429,16 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg );
// sv_ccmds.c
//
void SV_Heartbeat_f( void );
#ifdef DEDICATED
void SV_RecordDemo( client_t *cl, char *demoName );
void SV_StopRecordDemo( client_t *cl );
void SV_ClearClientDemoMeta( client_t *cl );
void SV_ClearClientDemoPreRecord( client_t *cl );
void SV_ClearAllDemoPreRecord( );
void SV_AutoRecordDemo( client_t *cl );
void SV_StopAutoRecordDemos();
void SV_BeginAutoRecordDemos();
#endif

//
// sv_snapshot.c
Expand Down
4 changes: 4 additions & 0 deletions codemp/server/sv_bot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,13 @@ void SV_BotFreeClient( int clientNum ) {
cl->gentity->r.svFlags &= ~SVF_BOT;
}

#ifdef DEDICATED
if ( cl->demo.demorecording ) {
SV_StopRecordDemo( cl );
}
SV_ClearClientDemoPreRecord(cl);
SV_ClearClientDemoMeta(cl);
#endif
}

/*
Expand Down
Loading