Fix: Playing Demos With Multiple Maps

Discuss programming topics for the various GPL'd game engine sources.
Post Reply
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Fix: Playing Demos With Multiple Maps

Post by Baker »

In retrospect, there have been a number of very stupid methods to *avoid* Quake's inability to play to playback demos across maps [instead of actually solving the issue] ... at least in some old engines from around the 2000-2002 range.

Most involve ensuring that demo recording stops at the end of a map.

Since I plan to use the ability provided in the "QUAKE2" build of the Quake engine to be able to return to maps you exited, the idea of recording a demo on ONLY a single map is absolutely worthless.

What if you visit MAP A for 5 seconds, return to MAP B for 15 seconds to get something and then go back to MAP C to open a door?

Anyway, this will enable demo playback across multiple maps.

Open host_cmd.c ...

Code: Select all


#define I_WANT_WORKING_MULTIMAP_DEMOS
void Host_Reconnect_f (void)
{
#ifdef I_WANT_WORKING_MULTIMAP_DEMOS
	if (cls.demoplayback) {
		Con_DPrintf("Demo playing; ignoring reconnect\n");
		return;
	}
#endif	
	SCR_BeginLoadingPlaque ();
	cls.signon = 0;		// need new connection messages
}
I suspected "reconnect" was the problem after noticing some odd behavior [a mistake in my engine which I thought I had already addressed initiated the map download capability ... oops ... on the 2nd map of playback ... which told me that it was trying to load the map but that something makes it disconnect right after] and then loaded up a few engines and eventually DarkPlaces which I noticed already had this ability and it confirm this cutely with a message "Reconnect: To what?" on the map change. :D [DarkPlaces has had this ability since the June 22, 2003 build, btw.]

I'm sure an asterisk or 2 might remain ... I noticed centerprint carries over and I bet there a couple of other small issues that should be addressed.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Ranger366
Posts: 203
Joined: Thu Mar 18, 2010 5:51 pm

Re: Fix: Playing Demos With Multiple Maps

Post by Ranger366 »

THIS works? oh god, never thought that this is possible! trying it now.
szo
Posts: 132
Joined: Mon Dec 06, 2010 4:42 pm

Re: Fix: Playing Demos With Multiple Maps

Post by szo »

There has been an another solution which I had found in an old hexen2 source modification by Pa3PyX:

At top of cl_demo.c, add a new global:
int stufftext_frame;

In your CL_GetDemoMessage(), add this (marked yellow here) :

// decide if it is time to grab the next message
if (cls.signon == SIGNONS) // always grab until fully connected
{
// Always wait for full frame update on stuff messages.
// If the server stuffs a reconnect, we must wait for
// the client to re-initialize before accepting further
// messages. Otherwise demo playback may freeze.
if (stufftext_frame == host_framecount)
return 0;

if (cls.timedemo)
{
if (host_framecount == cls.td_lastframe)

And move this code:

Code: Select all

cls.td_lastframe = -1;	// get a new message this frame
from end of CL_TimeDemo_f() to the end of CL_PlayDemo_f()

Open cl_parse.c, somewhere at the top add an extern declaration or the new global, like
extern int stufftext_frame;

Then find the place where the svc_stufftext message is handled and add this (marked yellow here) :

case svc_stufftext:
stufftext_frame = host_framecount; // allow full frame update
// on stuff messages.

Cbuf_AddText (MSG_ReadString ());
break;

Has always worked just fine for me.
szo
Posts: 132
Joined: Mon Dec 06, 2010 4:42 pm

Re: Fix: Playing Demos With Multiple Maps

Post by szo »

szo wrote:There has been an another solution which I had found in an old hexen2 source modification by Pa3PyX
... which I just added to quakespasm: http://quakespasm.svn.sourceforge.net/v ... vision=604
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Fix: Playing Demos With Multiple Maps

Post by Baker »

Hmmm ... I wish I were more familiar with Hexen 2. I bet that is written to avoid some other commands that only matter when the server is really connected.

Hexen 2 has intermap travel, right? Like the ability to go back and forth between levels. I really should take a look at the save game structure to see what other improvements they did in addition to the ones that you have mentioned. I did an experiment enabling intermap travel in Quake, but that code was a Carmack experiment and the code and mechanics in Hexen 2 would be far more thorough.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Fix: Playing Demos With Multiple Maps

Post by Baker »

szo wrote:
szo wrote:There has been an another solution which I had found in an old hexen2 source modification by Pa3PyX
... which I just added to quakespasm: http://quakespasm.svn.sourceforge.net/v ... vision=604
Heh, you might consider responding to the post @ Func asking what engines can playback multi map demos :D :D It is funny to update code that quick, really.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
ericw
Posts: 92
Joined: Sat Jan 18, 2014 2:11 am

Re: Fix: Playing Demos With Multiple Maps

Post by ericw »

Ran in to a weird issue with the cross-map demo support in QS:

Given a mod that sends svc_stufftext messages every frame (yes, it's ugly, but e.g. "honey" does send a "fog" command every frame), the special handling of svc_stufftext commands that enables cross-map demo playback to work also breaks the demo playback speed mechanism. In particular, if the client can't keep up with the rate of demo messages, the demo will play back in slow-motion. This can happen if the client doing playback is a slow computer / has a low host_maxfps, or if the demo was recorded with an unusually high host_maxfps.

for a test case, play a demo from: http://www.quaketastic.com/upload/files ... ney100.zip
for the honey map pack: http://www.quaketastic.com/upload/files ... /honey.zip
on a slow pc that gets signifigantly less than 72fps on honey.bsp, or with host_maxfps lowered (e.g. set to 33).

With QS 0.85.9, the demo will play in slow-motion; with QS 0.85.6 (without the cross-map demo support) or other engines it plays normally.

Admittedly this is a fringe scenario, but it's imo a legitimate bug in the Pa3PyX cross-map demo playback code.

I put in a hacky workaround that only does the waiting if the stufftext contains 'reconnect': https://sourceforge.net/p/quakespasm/code/974/
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Fix: Playing Demos With Multiple Maps

Post by Baker »

Watched the entire demo of onetruepurple honey [in Mark V]. Not sure at the moment how this pertains to "reconnect" as it was a demo of a single map???

Did you link the right demo?

[I didn't happen to notice a speed issue, but the demo was so long ...]

Update: Nevermind, I saw your changelog in Quakespasm. The method outlined in the first post of this thread is simple and works fine and has years of testing.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Fix: Playing Demos With Multiple Maps

Post by Spike »

the otp_saint100 demo appears to be multi-map, but not enough so for anyone to normally care. the second map lasts only briefly.
Baker wrote:Running the command once per frame, while annoying, is not going to be very taxing.
actually, that can be quite significant if you have some feature like demo jumping/skipping/rewinding where you're reading 5000 packets at a time between Cbuf_Executes (not quite the same as fast-forward, which would be much more sane). the memmove calls to consume the commands end up having to move a LOT of data, and can be exponentially slow. when you have 1mb of console commands queued up, each individual command will move on average 500kb around until the buffer is cleared, which is a not insignificant amount.
I assume that's the issue he was talking about?

obviously, any mod that stuffcmds each char of a fog command in a single stufftext packet is stupid, but there you go... BAD mod, BAD!... or at least wasteful (zipping it drops it to 10% of the filesize, although I'm not sure how well other single player demos compress).
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Fix: Playing Demos With Multiple Maps

Post by Baker »

Spike wrote:obviously, any mod that stuffcmds each char of a fog command in a single stufftext packet is stupid, but there you go... BAD mod, BAD!... or at least wasteful (zipping it drops it to 10% of the filesize, although I'm not sure how well other single player demos compress).
I agree, it is terrible but you can't control the QuakeC. But in this case, not what was causing the issue with Quakespasm 0.85.9

Mark V played the demo noted without issue. Quakespasm 0.85.6 does too, it appears to be type of reconnect fix QuakeSpasm 0.85.9 used that was causing the problem.

Sadly, I've seen other mods stuffing fog commands and other commands every frame :( Inefficient? Yes. But nowhere near as inefficient as the NQ protocol which wastes far more than 20 bytes per frame.

I'm not excusing bad mod behavior, but there are other things like QuakeC rain that are criminal offenses too.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
ericw
Posts: 92
Joined: Sat Jan 18, 2014 2:11 am

Re: Fix: Playing Demos With Multiple Maps

Post by ericw »

Yeah, sorry my post wasn't totally clear.

That otp honey demo has nothing in particular to do with multi-map demo playback, except that the Pa3PyX version of multi-map support (that was used in QS) works by intentionally "slowing" all frames that have a stuffcmd in them, which is every frame for that demo. (I guess it waits for the frame to be rendered before grabbing the next packet from the demo, not sure of the precise details.)

Anyway szo suggested we try changing QS to use your original method, Baker, so I did that here:
http://sf.net/p/quakespasm/code/976

At first I struggled a bit to prevent the console from re-appearing and scrolling away when the map change happens in a demo. Tried various things like putting a SCR_BeginLoadingPlaque() + SCR_EndLoadingPlaque() pair in Host_Reconnect_f(), which sort of worked, but not on timedemo's.

Finally found a clean solution, at least as far as I can tell... just added this to the beginning of CL_ParseServerInfo().

Code: Select all

if (cls.demoplayback)
      SCR_BeginLoadingPlaque();
From what I can see, svc_serverinfo is always the first sign in a demo that a map is loading, and svc_signonnum with the number 4 is the last step. The handler for svc_signonnum already calls SCR_EndLoadingPlaque for signon number 4, so it seemed logical to throw up the loading plaque in CL_ParseServerInfo() which would be the start of the map switch. So if my reasoning is correct, it's better to do it there than in Host_Reconnect_f () which seems to run at random times (sometimes after svc_signonnum 4) depending on whether you do a playdemo or timedemo, etc.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Fix: Playing Demos With Multiple Maps

Post by Baker »

ericw wrote:At first I struggled a bit to prevent the console from re-appearing and scrolling away when the map change happens in a demo. Tried various things like putting a SCR_BeginLoadingPlaque() + SCR_EndLoadingPlaque() pair in Host_Reconnect_f(), which sort of worked, but not on timedemo's.
I've been fighting that for a long a time.

(Ironically, the code you have above is real close what the next Mark V uses ...]

Code: Select all

/*
==================
Host_Reconnect_f

This command causes the client to wait for the signon messages again.
This is sent just before a server changes levels
==================
*/
// This can have 2 different scenarios.  Entry might be at 0, in that case 4 should clear plaque
//If signon is 4, that is death or changelevel. 
void Host_Reconnect_f (void)
{
	// Baker: Clear sound so if new map takes a long to load isn't playing ...
	S_ClearBuffer (); // Baker: Clear sound so if new map takes a long to load isn't playing ...

	if (cls.demoplayback)
	{
		Con_DPrintf("Demo playing; ignoring reconnect\n");
		SCR_EndLoadingPlaque (); // reconnect happens before signon reply #4
		return;
	} else 
	{
		SCR_BeginLoadingPlaque_Force_Transition ();
		cls.signon = 0;		// need new connection messages
	}
}
The loading plague is complicated and annoying the way original Quake code was written.

Most engines avoid the issue by instant or high console speed -- by avoid, I mean don't deal with the issue because it hard to address and not rewarding.

And it is complicated because of the messed up and redundant pathways the Quake source code does for everything.

1) Timedemo
2) Demo
3) Coop play / Online play
4) Single player
5) Load game, reconnect, save game, die during play, single player -> new game

But to verify, I'll also need to try some other conditions ...
6) Multiplayer deathmatch reconnect.
7) Multiplayer deathmatch reconnect, failed (can happen)
8 ) Single player changelevel failed.

(sigh ... there are extra variations of those too --- connected, error, already running a map, start from menu)

[The myriad of situations are a bit annoying ...]

Anyway, in the next Mark V I haven't encountered a situation it handles incorrectly. Almost no engine I've seen has it 100% perfect so far.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Post Reply