From e2e2bddfa31b3375995ffbbeb988545480dffa97 Mon Sep 17 00:00:00 2001 From: Yamagi Date: Sun, 25 Jul 2021 09:45:51 +0200 Subject: [PATCH] Fix demo loop after changing the game through the menu. Injecting the demo loop right after the `game` cvar was changed cannot work: The demo loop is implemented through aliases, aliases are expended as soon as they're added to the command buffer. However, the game isn't changed as soon as the cvar is set, but the next time when the control flow enters the file system. Therefor the aliases get expanded to the wrong game and the demo loops breaks. This closes #719. --- src/client/menu/menu.c | 5 ++++- src/common/filesystem.c | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/client/menu/menu.c b/src/client/menu/menu.c index d5891804..1508fa8e 100644 --- a/src/client/menu/menu.c +++ b/src/client/menu/menu.c @@ -39,6 +39,9 @@ static int m_main_cursor; /* Number of the frames of the spinning quake logo */ #define NUM_CURSOR_FRAMES 15 +/* Signals the file system to start the demo loop. */ +qboolean menu_startdemoloop; + static char *menu_in_sound = "misc/menu1.wav"; static char *menu_move_sound = "misc/menu2.wav"; static char *menu_out_sound = "misc/menu3.wav"; @@ -2193,7 +2196,7 @@ ModsApplyActionFunc(void *unused) Cbuf_AddText(va("game %s\n", modnames[s_mods_list.curvalue])); // start the demo cycle in the new game directory - Cbuf_AddText("d1\n"); + menu_startdemoloop = true; M_ForceMenuOff(); } diff --git a/src/common/filesystem.c b/src/common/filesystem.c index 486b2a3c..bbac8d0a 100644 --- a/src/common/filesystem.c +++ b/src/common/filesystem.c @@ -1715,7 +1715,18 @@ void FS_BuildGenericSearchPath(void) { Sys_Mkdir(path); } +// filesystem.c is used by the client and the server, +// it includes common.h only. Not the client not the +// server header. The game reset logic messes with +// client state, so we need some forwar declarations +// here. +#ifndef DEDICATED_ONLY +// Variables +extern qboolean menu_startdemoloop; + +// Functions void CL_WriteConfiguration(void); +#endif void FS_BuildGameSpecificSearchPath(char *dir) @@ -1819,6 +1830,21 @@ FS_BuildGameSpecificSearchPath(char *dir) free(mapnames); mapnames = NULL; } + + // Start the demoloop, if requested. This is kind of hacky: Normaly the + // demo loop would be started by the menu, after changeing the 'game' + // cvar. However, the demo loop is implemented by aliases. Since the + // game isn't changed right after the cvar is set (but when the control + // flow enters this function) the aliases evaulate to the wrong game. + // Work around that by injection the demo loop into the command buffer + // here, right after the game was changed. Do it only when the game was + // changed though the menu, otherwise we might break into the demo loop + // after we've received a latched cvar from the server. + if (menu_startdemoloop) + { + Cbuf_AddText("d1\n"); + menu_startdemoloop = false; + } #endif }