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

ghost: support marathon demos #63

Closed
matthewearl opened this issue Oct 14, 2022 · 1 comment · Fixed by #64
Closed

ghost: support marathon demos #63

matthewearl opened this issue Oct 14, 2022 · 1 comment · Fixed by #64

Comments

@matthewearl
Copy link
Contributor

As the title suggests. Specifically the type where all the levels are in a single .dem file (the kind that JoeQuake now produces). In terms of implementation it will be easiest to have the ghost start in sync with the player at the start of each level, rather than carrying over time delta from the previous level. It'd be nice to have the option of carrying the time delta over, though.

@matthewearl
Copy link
Contributor Author

I reckon the easiest way to do this would be on map change, scan through the whole demo file looking for a server info message with a map that matches the current map. If found, start reading the ghost info immediately, if not print an error message (like the current one).

The skipping could be made fairly fast since when in "scanning for map" mode we can avoid parsing most of the updates. For instance, here's what pyquake dumps for a level transition:

(False, [-1.7424052953720093, 197.896728515625, 0.0], ServerMessagePrint(string='\nQdQ Stats patch v1.8\nThe recorded time was '))
(False, [-1.7424052953720093, 197.896728515625, 0.0], ServerMessagePrint(string='7'))                                    
(False, [-1.7424052953720093, 197.896728515625, 0.0], ServerMessagePrint(string='.'))                                    
(False, [-1.7424052953720093, 197.896728515625, 0.0], ServerMessagePrint(string='1'))                                    
(False, [-1.7424052953720093, 197.896728515625, 0.0], ServerMessagePrint(string='3'))                                    
(False, [-1.7424052953720093, 197.896728515625, 0.0], ServerMessagePrint(string='3'))                                    
(False, [-1.7424052953720093, 197.896728515625, 0.0], ServerMessagePrint(string='4'))                                    
(False, [-1.7424052953720093, 197.896728515625, 0.0], ServerMessagePrint(string='1'))                                    
(False, [-1.7424052953720093, 197.896728515625, 0.0], ServerMessagePrint(string='\n'))                                   
(False, [-1.7424052953720093, 197.896728515625, 0.0], ServerMessagePrint(string='\n'))                                   
(True, [-1.7424052953720093, 197.896728515625, 0.0], ServerMessageStuffText(string='net_messagetimeout 77157674313357435540\n'))
--------- PACKET BOUNDARY ---------
(True, [0.0, 0.0, 0.0], ServerMessageStuffText(string='reconnect\n'))                                
--------- PACKET BOUNDARY ---------                    
(False, [0.0, 0.0, 0.0], ServerMessagePrint(string='\x02\nVERSION 1.09 SERVER (5336 CRC)'))                              
(False, [0.0, 0.0, 0.0], ServerMessageServerInfo(protocol=Protocol(version=<ProtocolVersion.NETQUAKE: 15>, flags=<ProtocolFlags.0: 0>), max_clients=1, game_type=0, level_name='the Slipgate Complex', models=['maps/e1m1.bsp', '*1', '*2', '*3', '*4', '*5', '*6', ...]))
(False, [0.0, 0.0, 0.0], ServerMessageCdTrack(track=6, loop=6))                                                          
(False, [0.0, 0.0, 0.0], ServerMessageSetView(viewentity=1))                                                             
(False, [0.0, 0.0, 0.0], ServerMessageSetPause(paused=0))                                                                
(True, [0.0, 0.0, 0.0], ServerMessageSignOnNum(num=1))         
--------- PACKET BOUNDARY ---------                                                          
(False, [0.0, -0.04839999973773956, 0.0], ServerMessageSpawnStaticSound(origin=(688.0, 192.0, 80.0), sound_num=65, vol=127, atten=192))
(False, [0.0, -0.04839999973773956, 0.0], ServerMessageSpawnStaticSound(origin=(592.0, 544.0, 88.0), sound_num=71, vol=127, atten=192))
(False, [0.0, -0.04839999973773956, 0.0], ServerMessageSpawnStaticSound(origin=(176.0, 1744.0, -152.0), sound_num=71, vol=127, atten=192))
(False, [0.0, -0.04839999973773956, 0.0], ServerMessageSpawnStaticSound(origin=(80.0, 1744.0, -152.0), sound_num=71, vol=127, atten=192))
(False, [0.0, -0.04839999973773956, 0.0], ServerMessageSpawnStaticSound(origin=(416.0, 2064.0, -112.0), sound_num=71, vol=127, atten=192))
(False, [0.0, -0.04839999973773956, 0.0], ServerMessageSpawnStaticSound(origin=(416.0, 1968.0, -112.0), sound_num=71, vol=127, atten=192))
....
--------- PACKET BOUNDARY ---------                                                          
(False, [0.04839999973773956, -0.4114000201225281, 0.0], ServerMessageTime(time=1.4109539985656738))
...usual update messages go here...
--------- PACKET BOUNDARY ---------                                                          
(False, [-0.02419999986886978, 89.806396484375, 0.0], ServerMessageTime(time=1.4387319087982178))
...usual update messages go here...
--------- PACKET BOUNDARY ---------
(False, [0.04840000346302986, 89.51541137695312, 0.0], ServerMessageTime(time=1.4526207447052002))
...usual update messages go here...
--------- PACKET BOUNDARY ---------

...and so on.

If we haven't yet found a server info message with our map, we can return DP_CBR_SKIP_PACKET in the time callback which will mean we won't waste time parsing most of the demo file. I reckon this would be plenty fast enough for id1 marathons (at least on a modern machine) so certainly a feature worth having.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant