fixed demo playback that broke because of incorrect tokenizer usage

the breaking commit: c512071f2d
fixed using /demo when running a listen server (would load map and then abort)
This commit is contained in:
myT 2018-02-02 01:15:18 +01:00
parent e4e68a971c
commit f34c8b5001
2 changed files with 40 additions and 63 deletions

View file

@ -21,6 +21,8 @@ chg: on Windows, a fatal error will move the early console window to the foregro
chg: com_hunkMegs doesn't have a maximum value anymore
a value too high would reset it and the engine might fail to load with the default value
fix: using /demo when running a listen server would load the map and then abort playback
fix: no longer making local copies of all the system info cvars of the current server
this avoids undesired local changes to cvars such as sv_pure

View file

@ -341,86 +341,61 @@ void CL_ReadDemoMessage( void ) {
}
static const int demo_protocols[] = { 68, 67, 66, 0 };
static void CL_WalkDemoExt( const char* arg, char* name, fileHandle_t* fh )
static void CL_WalkDemoExt( const char* path, fileHandle_t* fh )
{
const int protocols[] = { 68, 67, 66 };
char fullPath[MAX_OSPATH];
*fh = 0;
for (int i = 0; demo_protocols[i]; ++i)
{
Com_sprintf( name, MAX_OSPATH, "demos/%s.dm_%d", arg, demo_protocols[i] );
FS_FOpenFileRead( name, fh, qtrue );
if (*fh)
{
Com_Printf("Demo file: %s\n", name);
for (int i = 0; i < ARRAY_LEN(protocols); ++i) {
Com_sprintf( fullPath, sizeof( fullPath ), "demos/%s.dm_%d", path, protocols[i] );
FS_FOpenFileRead( fullPath, fh, qtrue );
if (*fh) {
Com_Printf( "Demo file: %s\n", fullPath );
return;
}
}
Com_Printf( "No match: demos/%s.dm_*\n", arg );
Com_Printf( "No match: demos/%s.dm_*\n", path );
}
void CL_PlayDemo_f()
{
if (Cmd_Argc() != 2) {
Com_Printf ("demo <demoname>\n");
Com_Printf( "demo <demoname>\n" );
return;
}
const char* const demoPath = Cmd_Argv(1);
fileHandle_t fh;
CL_WalkDemoExt( demoPath, &fh );
if ( fh == 0 ) {
Com_Printf( "Couldn't open demo %s\n", demoPath );
return;
}
// make sure a local server is killed
Cvar_Set( "sv_killserver", "1" );
// CL_Disconnect uses the tokenizer, so we save the demo path now
char shortPath[MAX_OSPATH];
Q_strncpyz( shortPath, demoPath, sizeof( shortPath ) );
CL_Disconnect( qtrue );
char name[MAX_OSPATH];
// open the demo file
const char* arg = Cmd_Argv(1);
// check for an extension .dm_?? (?? is protocol)
const char* ext = arg + strlen(arg) - 6;
if ((strlen(arg) > 6) && (ext[0] == '.') && ((ext[1] == 'd') || (ext[1] == 'D')) && ((ext[2] == 'm') || (ext[2] == 'M')) && (ext[3] == '_'))
{
int protocol = atoi(ext + 4), i = 0;
while (demo_protocols[i]) {
if (demo_protocols[i] == protocol)
break;
++i;
}
if (demo_protocols[i])
{
Com_sprintf( name, sizeof(name), "demos/%s", arg );
FS_FOpenFileRead( name, &clc.demofile, qtrue );
} else {
char retry[MAX_OSPATH];
Com_Printf("Protocol %d not supported for demos\n", protocol);
Q_strncpyz(retry, arg, sizeof(retry));
retry[strlen(retry)-6] = 0;
CL_WalkDemoExt( retry, name, &clc.demofile );
}
} else {
CL_WalkDemoExt( arg, name, &clc.demofile );
}
if (!clc.demofile) {
Com_Error( ERR_DROP, "couldn't open %s", name);
return;
}
Q_strncpyz( clc.demoName, Cmd_Argv(1), sizeof( clc.demoName ) );
// CL_Disconnect closes clc.demofile, so we set it after the call
SV_Shutdown( "closing for demo playback" );
CL_Disconnect( qfalse );
clc.demofile = fh;
Q_strncpyz( clc.demoName, shortPath, sizeof( clc.demoName ) );
Con_Close();
cls.state = CA_CONNECTED;
clc.demoplaying = qtrue;
Q_strncpyz( cls.servername, Cmd_Argv(1), sizeof( cls.servername ) );
Q_strncpyz( cls.servername, shortPath, sizeof( cls.servername ) );
// read demo messages until connected
while (cls.state >= CA_CONNECTED && cls.state < CA_PRIMED && !CL_MapDownload_Active()) {
while ( cls.state >= CA_CONNECTED && cls.state < CA_PRIMED && !CL_MapDownload_Active() ) {
CL_ReadDemoMessage();
}
// don't get the first snapshot this frame, to prevent the long
// time from the gamestate load from messing causing a time skip
clc.firstDemoFrameSkipped = qfalse;
@ -1945,7 +1920,7 @@ static void CL_CompleteCallVote_f( int startArg, int compArg )
Field_AutoCompleteCustom( startArg, compArg, &Field_AutoCompleteMapName );
}
static void CL_PrintDownloadPakUsage()
{
Com_Printf( "Usage: %s checksum (signed decimal, '0x' or '0X' prefix for hex)\n", Cmd_Argv(0) );
@ -2026,8 +2001,8 @@ static void CL_CancelDownload_f()
{
CL_MapDownload_Cancel();
}
static const cvarTableItem_t cl_cvars[] =
{
{ &cl_timeout, "cl_timeout", "200", 0, CVART_INTEGER, "30", "300", "connection time-out, in seconds" },
@ -2085,7 +2060,7 @@ static const cmdTableItem_t cl_cmds[] =
// we use these until we get proper handling on the mod side
{ "cv", CL_CallVote_f, CL_CompleteCallVote_f, "calls a vote" },
{ "callvote", CL_CallVote_f, CL_CompleteCallVote_f, "calls a vote" }
};
};
void CL_Init()
@ -2099,9 +2074,9 @@ void CL_Init()
cls.state = CA_DISCONNECTED; // no longer CA_UNINITIALIZED
cls.realtime = 0;
Cvar_RegisterArray( cl_cvars, MODULE_CLIENT );
Cmd_RegisterArray( cl_cmds, MODULE_CLIENT );
Cmd_RegisterArray( cl_cmds, MODULE_CLIENT );
CL_InitRef();
CL_InitInput();
@ -2144,8 +2119,8 @@ void CL_Shutdown()
CL_ShutdownUI();
CL_MapDownload_Cancel();
Cmd_UnregisterModule( MODULE_CLIENT );
Cmd_UnregisterModule( MODULE_CLIENT );
CL_ConShutdown();