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

Server side demos #265

Open
wants to merge 9 commits into
base: master
from

Better autorecord hooks + partial fix for tournament < 2 players auto…

…join for E+

Signed-off-by: Stephen L. <lrq3000@gmail.com>
  • Loading branch information...
lrq3000 committed Mar 7, 2017
commit 63b73eecd89d3e5c156a57dec99812ba48aae615
@@ -200,12 +200,6 @@ static void SV_Map_f( void ) {
}
}

// stop any demos
if (sv.demoState == DS_RECORDING)
SV_DemoStopRecord();
if (sv.demoState == DS_PLAYBACK)
SV_DemoStopPlayback();

// save the map name here cause on a map restart we reload the q3config.cfg
// and thus nuke the arguments of the map command
Q_strncpyz(mapname, map, sizeof(mapname));
@@ -279,12 +273,6 @@ static void SV_MapRestart_f( void ) {
return;
}

// stop any demos
if (sv.demoState == DS_RECORDING)
SV_DemoStopRecord();
if (sv.demoState == DS_PLAYBACK)
SV_DemoStopPlayback();

// toggle the server bit so clients can detect that a
// map_restart has happened
svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;
@@ -365,11 +353,6 @@ static void SV_MapRestart_f( void ) {
VM_Call (gvm, GAME_RUN_FRAME, sv.time);
sv.time += 100;
svs.time += 100;

// start recording a demo
if ( sv_autoDemo->integer ) {
SV_DemoAutoDemoRecord();
}
}

//===============================================================
@@ -791,6 +791,12 @@ void SV_ClientEnterWorld( client_t *client, usercmd_t *cmd ) {
// server-side demo playback: prevent players from joining the game when a demo is replaying (particularly if the gametype is non-team based, by default the gamecode force players to join in)
if (sv.demoState == DS_PLAYBACK &&
( (client - svs.clients) >= sv_democlients->integer ) && ( (client - svs.clients) < sv_maxclients->integer ) ) { // check that it's a real player
// Specific to excessiveplus mod, this is just a safeguard in case the demo bugs (eg, Tournament gametype but one democlient is not rendered correctly because of ping, then the gamecode will consider it's normal to force another player to join)
//if ( !Q_stricmp(Cvar_VariableString("fs_game"), "excessiveplus") ) {
Cmd_TokenizeString( va("speconly") );
VM_Call( gvm, GAME_CLIENT_COMMAND, client - svs.clients ); // force SV_ExecuteClientCommand
//}
// Force client to spectator
SV_ExecuteClientCommand(client, "team spectator", qtrue);
}

@@ -84,6 +84,13 @@ static qboolean keepSaved = qfalse; // var that memorizes if we keep the new max
static int demoTeamAutoJoin = -1; // load the g_teamAutoJoin value from the demo recording


/***********************************************
* AUXILIARY FUNCTIONS: MANIPULATING CLIENT COMMANDS
*
* Functions used to manipulate clients commands and communicate with the gamecode.
***********************************************/


/***********************************************
* AUXILIARY FUNCTIONS: CHECKING, FILTERING AND CLEANING
*
@@ -787,7 +794,7 @@ void SV_DemoReadClientConfigString( msg_t *msg )
SV_SetConfigstring(CS_PLAYERS + num, configstring);

// Set some infos about this user:
svs.clients[num].demoClient = qtrue; // to check if a client is a democlient, you can either rely on this variable, either you can check if num (index of client) is >= CS_PLAYERS + sv_democlients->integer && < CS_PLAYERS + sv_maxclients->integer (if it's not a configstring, remove CS_PLAYERS from your if)
svs.clients[num].demoClient = qtrue; // to check if a client is a democlient, you can either rely on this variable, either you can check if it's a real client num (index of client) is >= CS_PLAYERS + sv_democlients->integer && < CS_PLAYERS + sv_maxclients->integer (if it's not a configstring, remove CS_PLAYERS from your if)
Q_strncpyz( svs.clients[num].name, Info_ValueForKey( configstring, "n" ), MAX_NAME_LENGTH ); // set the name (useful for internal functions such as status_f). Anyway userinfo will automatically set both name (server-side) and netname (gamecode-side).


@@ -1225,8 +1232,12 @@ void SV_DemoAutoDemoRecord(void)
qtime_t now;
Com_RealTime( &now );
char *demoname = malloc ( MAX_QPATH * sizeof * demoname );


// Break if a demo is already being recorded - FIXME: this should not happen, this is a failsafe but if it's used it means there are redundant calls that we can maybe remove
if (sv.demoState == DS_RECORDING)
return;

// Generate the demo filename
Q_strncpyz(demoname, va( "%s_%04d-%02d-%02d-%02d-%02d-%02d_%s",
SV_CleanFilename(va("%s", sv_hostname->string)),
1900 + now.tm_year,
@@ -1238,11 +1249,14 @@ void SV_DemoAutoDemoRecord(void)
SV_CleanFilename(Cvar_VariableString( "mapname" )) ),
MAX_QPATH);

// Print a message
Com_Printf("DEMO: automatic recording server-side demo to: %s/svdemos/%s.%s%d\n", strlen(Cvar_VariableString("fs_game")) ? Cvar_VariableString("fs_game") : BASEGAME, demoname, SVDEMOEXT, PROTOCOL_VERSION);
SV_SendServerCommand( NULL, "chat \"^3DEMO: automatic recording server-side demo to: %s.%s%d.\"", demoname, SVDEMOEXT, PROTOCOL_VERSION );

// Launch the demo recording
Cbuf_AddText( va("demo_record %s\n", demoname ) );

// Free memory of the filename
free(demoname);
}

@@ -1649,6 +1663,13 @@ void SV_DemoStartPlayback(void)
// Force all real clients already connected before the demo begins to be set to spectator team
for (i = sv_democlients->integer; i < sv_maxclients->integer; i++) {
if (svs.clients[i].state >= CS_CONNECTED) { // Only set as spectator a player that is at least connected (or primed or active)
// Specific to excessiveplus mod, this is just a safeguard in case the demo bugs (eg, Tournament gametype but one democlient is not rendered correctly because of ping, then the gamecode will consider it's normal to force another player to join)
//if ( !Q_stricmp(Cvar_VariableString("fs_game"), "excessiveplus") ) {
Cmd_TokenizeString( va("speconly") );
VM_Call( gvm, GAME_CLIENT_COMMAND, i ); // force SV_ExecuteClientCommand
//SV_ExecuteClientCommand(&svs.clients[i], "speconly", qtrue);
//}
// Force client to spectator
SV_ExecuteClientCommand(&svs.clients[i], "team spectator", qtrue); // should be more interoperable than a forceteam
Cbuf_ExecuteText(EXEC_NOW, va("forceteam %i spectator", i)); // sometimes team spectator does not work when a demo is replayed client-side with some mods (eg: ExcessivePlus), in this case we also issue a forceteam (even if it's less interoperable)
}
@@ -865,6 +865,12 @@ void SV_ShutdownGameProgs( void ) {
if ( !gvm ) {
return;
}
// stop any demos
if (sv.demoState == DS_RECORDING)
SV_DemoStopRecord();
if (sv.demoState == DS_PLAYBACK)
SV_DemoStopPlayback();
// shutdown game
VM_Call( gvm, GAME_SHUTDOWN, qfalse );
VM_Free( gvm );
gvm = NULL;
@@ -894,6 +900,17 @@ static void SV_InitGameVM( qboolean restart ) {
// use the current msec count for a random seed
// init for this gamestate
VM_Call (gvm, GAME_INIT, sv.time, Com_Milliseconds(), restart);

// start recording a demo
if ( sv_autoDemo->integer ) {
// stop any demos
if (sv.demoState == DS_RECORDING)
SV_DemoStopRecord();
if (sv.demoState == DS_PLAYBACK)
SV_DemoStopPlayback();
// start an auto demo recording
SV_DemoAutoDemoRecord();
}
}


ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.