mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-12-01 08:31:14 +00:00
- Game time is now frozen during screen wipes. This obsoletes the DEM_WIPEON
and DEM_WIPEOFF commands. Fixes multimap demos desyncing when played back or recorded with wipes enabled, and prevents multiplayer games from starting until all players' wipes have finished. SVN r1272 (trunk)
This commit is contained in:
parent
b9afb78523
commit
30ef6a0c2d
11 changed files with 98 additions and 35 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
October 20, 2008
|
||||||
|
- Game time is now frozen during screen wipes. This obsoletes the DEM_WIPEON
|
||||||
|
and DEM_WIPEOFF commands. Fixes multimap demos desyncing when played back
|
||||||
|
or recorded with wipes enabled, and prevents multiplayer games from
|
||||||
|
starting until all players' wipes have finished.
|
||||||
|
|
||||||
October 19, 2008 (Changes by Graf Zahl)
|
October 19, 2008 (Changes by Graf Zahl)
|
||||||
- Added native variables to expression evaluator and replaced the previous
|
- Added native variables to expression evaluator and replaced the previous
|
||||||
handling of actor variables in expressions with it.
|
handling of actor variables in expressions with it.
|
||||||
|
|
|
@ -724,32 +724,34 @@ void D_Display ()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// wipe update
|
// wipe update
|
||||||
int wipestart, nowtime, tics;
|
unsigned int wipestart, nowtime, diff;
|
||||||
bool done;
|
bool done;
|
||||||
|
|
||||||
GSnd->SetSfxPaused(true, 1);
|
GSnd->SetSfxPaused(true, 1);
|
||||||
|
I_FreezeTime(true);
|
||||||
screen->WipeEndScreen ();
|
screen->WipeEndScreen ();
|
||||||
|
|
||||||
wipestart = I_GetTime (false);
|
wipestart = I_MSTime();
|
||||||
|
NetUpdate(); // send out any new accumulation
|
||||||
Net_WriteByte (DEM_WIPEON);
|
|
||||||
NetUpdate (); // send out any new accumulation
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
nowtime = I_WaitForTic (wipestart);
|
do
|
||||||
tics = nowtime - wipestart;
|
{
|
||||||
|
I_WaitVBL(2);
|
||||||
|
nowtime = I_MSTime();
|
||||||
|
diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow.
|
||||||
|
} while (diff < 1);
|
||||||
wipestart = nowtime;
|
wipestart = nowtime;
|
||||||
done = screen->WipeDo (tics);
|
done = screen->WipeDo (1);
|
||||||
C_DrawConsole (hw2d); // console and
|
C_DrawConsole (hw2d); // console and
|
||||||
M_Drawer (); // menu are drawn even on top of wipes
|
M_Drawer (); // menu are drawn even on top of wipes
|
||||||
screen->Update (); // page flip or blit buffer
|
screen->Update (); // page flip or blit buffer
|
||||||
NetUpdate ();
|
NetUpdate (); // [RH] not sure this is needed anymore
|
||||||
} while (!done);
|
} while (!done);
|
||||||
screen->WipeCleanup();
|
screen->WipeCleanup();
|
||||||
|
I_FreezeTime(false);
|
||||||
GSnd->SetSfxPaused(false, 1);
|
GSnd->SetSfxPaused(false, 1);
|
||||||
|
|
||||||
Net_WriteByte (DEM_WIPEOFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cycles.Unclock();
|
cycles.Unclock();
|
||||||
|
|
|
@ -607,7 +607,6 @@ void PlayerIsGone (int netnode, int netconsole)
|
||||||
nodeingame[netnode] = false;
|
nodeingame[netnode] = false;
|
||||||
playeringame[netconsole] = false;
|
playeringame[netconsole] = false;
|
||||||
nodejustleft[netnode] = false;
|
nodejustleft[netnode] = false;
|
||||||
playerswiping &= ~(1 << netconsole);
|
|
||||||
|
|
||||||
if (deathmatch)
|
if (deathmatch)
|
||||||
{
|
{
|
||||||
|
@ -2316,14 +2315,6 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEM_WIPEON:
|
|
||||||
playerswiping |= 1 << player;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DEM_WIPEOFF:
|
|
||||||
playerswiping &= ~(1 << player);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DEM_ADDCONTROLLER:
|
case DEM_ADDCONTROLLER:
|
||||||
{
|
{
|
||||||
BYTE playernum = ReadByte (stream);
|
BYTE playernum = ReadByte (stream);
|
||||||
|
|
|
@ -372,7 +372,6 @@ public:
|
||||||
|
|
||||||
// Bookkeeping on players - state.
|
// Bookkeeping on players - state.
|
||||||
extern player_t players[MAXPLAYERS];
|
extern player_t players[MAXPLAYERS];
|
||||||
extern DWORD playerswiping;
|
|
||||||
|
|
||||||
inline FArchive &operator<< (FArchive &arc, player_t *&p)
|
inline FArchive &operator<< (FArchive &arc, player_t *&p)
|
||||||
{
|
{
|
||||||
|
|
|
@ -141,8 +141,8 @@ enum EDemoCommand
|
||||||
DEM_DOAUTOSAVE, // 42 An autosave should be made
|
DEM_DOAUTOSAVE, // 42 An autosave should be made
|
||||||
DEM_MORPHEX, // 43 String: The class to morph to.
|
DEM_MORPHEX, // 43 String: The class to morph to.
|
||||||
DEM_SUMMONFOE, // 44 String: Thing to fabricate
|
DEM_SUMMONFOE, // 44 String: Thing to fabricate
|
||||||
DEM_WIPEON, // 45 Player started a screen wipe
|
DEM_UNDONE9, // 45
|
||||||
DEM_WIPEOFF, // 46 Player finished a screen wipe
|
DEM_UNDONE10, // 46
|
||||||
DEM_TAKECHEAT, // 47 String: item to take, Word: quantity
|
DEM_TAKECHEAT, // 47 String: item to take, Word: quantity
|
||||||
DEM_ADDCONTROLLER, // 48 Player to add to the controller list.
|
DEM_ADDCONTROLLER, // 48 Player to add to the controller list.
|
||||||
DEM_DELCONTROLLER, // 49 Player to remove from the controller list.
|
DEM_DELCONTROLLER, // 49 Player to remove from the controller list.
|
||||||
|
|
|
@ -124,7 +124,6 @@ bool netgame; // only true if packets are broadcast
|
||||||
bool multiplayer;
|
bool multiplayer;
|
||||||
player_t players[MAXPLAYERS];
|
player_t players[MAXPLAYERS];
|
||||||
bool playeringame[MAXPLAYERS];
|
bool playeringame[MAXPLAYERS];
|
||||||
DWORD playerswiping;
|
|
||||||
|
|
||||||
int consoleplayer; // player taking events
|
int consoleplayer; // player taking events
|
||||||
int gametic;
|
int gametic;
|
||||||
|
@ -2148,7 +2147,6 @@ void G_ReadDemoTiccmd (ticcmd_t *cmd, int player)
|
||||||
if (i < MAXPLAYERS)
|
if (i < MAXPLAYERS)
|
||||||
{
|
{
|
||||||
playeringame[i] = false;
|
playeringame[i] = false;
|
||||||
playerswiping &= ~(1 << i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -77,11 +77,11 @@ void P_Ticker (void)
|
||||||
{
|
{
|
||||||
// This is a separate slot from the wipe in D_Display(), because this
|
// This is a separate slot from the wipe in D_Display(), because this
|
||||||
// is delayed slightly due to latency. (Even on a singleplayer game!)
|
// is delayed slightly due to latency. (Even on a singleplayer game!)
|
||||||
GSnd->SetSfxPaused(!!playerswiping, 2);
|
// GSnd->SetSfxPaused(!!playerswiping, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the tic
|
// run the tic
|
||||||
if (paused || (playerswiping && !demoplayback) || P_CheckTickerPaused())
|
if (paused || P_CheckTickerPaused())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// [RH] Frozen mode is only changed every 4 tics, to make it work with A_Tracer().
|
// [RH] Frozen mode is only changed every 4 tics, to make it work with A_Tracer().
|
||||||
|
|
|
@ -87,6 +87,7 @@ DWORD LanguageIDs[4] =
|
||||||
|
|
||||||
int (*I_GetTime) (bool saveMS);
|
int (*I_GetTime) (bool saveMS);
|
||||||
int (*I_WaitForTic) (int);
|
int (*I_WaitForTic) (int);
|
||||||
|
void (*I_FreezTime) (bool frozen);
|
||||||
|
|
||||||
void I_Tactile (int on, int off, int total)
|
void I_Tactile (int on, int off, int total)
|
||||||
{
|
{
|
||||||
|
@ -116,6 +117,7 @@ unsigned int I_MSTime (void)
|
||||||
|
|
||||||
static DWORD TicStart;
|
static DWORD TicStart;
|
||||||
static DWORD TicNext;
|
static DWORD TicNext;
|
||||||
|
static int TicFrozen;
|
||||||
|
|
||||||
//
|
//
|
||||||
// I_GetTime
|
// I_GetTime
|
||||||
|
@ -123,6 +125,11 @@ static DWORD TicNext;
|
||||||
//
|
//
|
||||||
int I_GetTimePolled (bool saveMS)
|
int I_GetTimePolled (bool saveMS)
|
||||||
{
|
{
|
||||||
|
if (TicFrozen != 0)
|
||||||
|
{
|
||||||
|
return TicFrozen;
|
||||||
|
}
|
||||||
|
|
||||||
DWORD tm = SDL_GetTicks ();
|
DWORD tm = SDL_GetTicks ();
|
||||||
|
|
||||||
if (saveMS)
|
if (saveMS)
|
||||||
|
@ -137,12 +144,30 @@ int I_WaitForTicPolled (int prevtic)
|
||||||
{
|
{
|
||||||
int time;
|
int time;
|
||||||
|
|
||||||
|
assert (TicFrozen == 0);
|
||||||
while ((time = I_GetTimePolled(false)) <= prevtic)
|
while ((time = I_GetTimePolled(false)) <= prevtic)
|
||||||
;
|
;
|
||||||
|
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I_FreezeTimePolled (bool frozen)
|
||||||
|
{
|
||||||
|
if (frozen)
|
||||||
|
{
|
||||||
|
assert(TicFrozen == 0);
|
||||||
|
TicFrozen = I_GetTimePolled(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(TicFrozen != 0);
|
||||||
|
int froze = TicFrozen;
|
||||||
|
TicFrozen = 0;
|
||||||
|
int now = I_GetTimePolled(false);
|
||||||
|
basetime += (now - froze) * 1000 / TICRATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the fractional amount of a tic passed since the most recent tic
|
// Returns the fractional amount of a tic passed since the most recent tic
|
||||||
fixed_t I_GetTimeFrac (uint32 *ms)
|
fixed_t I_GetTimeFrac (uint32 *ms)
|
||||||
{
|
{
|
||||||
|
@ -184,6 +209,7 @@ void I_Init (void)
|
||||||
|
|
||||||
I_GetTime = I_GetTimePolled;
|
I_GetTime = I_GetTimePolled;
|
||||||
I_WaitForTic = I_WaitForTicPolled;
|
I_WaitForTic = I_WaitForTicPolled;
|
||||||
|
I_FreezeTime = I_FreezeTimePolled;
|
||||||
atterm (I_ShutdownSound);
|
atterm (I_ShutdownSound);
|
||||||
I_InitSound ();
|
I_InitSound ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,8 +56,11 @@ extern int (*I_GetTime) (bool saveMS);
|
||||||
// like I_GetTime, except it waits for a new tic before returning
|
// like I_GetTime, except it waits for a new tic before returning
|
||||||
extern int (*I_WaitForTic) (int);
|
extern int (*I_WaitForTic) (int);
|
||||||
|
|
||||||
int I_GetTimePolled (bool saveMS);
|
// Freezes tic counting temporarily. While frozen, calls to I_GetTime()
|
||||||
int I_GetTimeFake (void);
|
// will always return the same value. This does not affect I_MSTime().
|
||||||
|
// You must also not call I_WaitForTic() while freezing time, since the
|
||||||
|
// tic will never arrive (unless it's the current one).
|
||||||
|
extern void (*I_FreezeTime) (bool frozen);
|
||||||
|
|
||||||
fixed_t I_GetTimeFrac (uint32 *ms);
|
fixed_t I_GetTimeFrac (uint32 *ms);
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ const IWADInfo *DoomStartupInfo;
|
||||||
|
|
||||||
int (*I_GetTime) (bool saveMS);
|
int (*I_GetTime) (bool saveMS);
|
||||||
int (*I_WaitForTic) (int);
|
int (*I_WaitForTic) (int);
|
||||||
|
void (*I_FreezeTime) (bool frozen);
|
||||||
|
|
||||||
os_t OSPlatform;
|
os_t OSPlatform;
|
||||||
|
|
||||||
|
@ -120,6 +121,7 @@ unsigned int I_MSTime (void)
|
||||||
|
|
||||||
static DWORD TicStart;
|
static DWORD TicStart;
|
||||||
static DWORD TicNext;
|
static DWORD TicNext;
|
||||||
|
static int TicFrozen;
|
||||||
|
|
||||||
//
|
//
|
||||||
// I_GetTime
|
// I_GetTime
|
||||||
|
@ -129,6 +131,11 @@ int I_GetTimePolled (bool saveMS)
|
||||||
{
|
{
|
||||||
DWORD tm;
|
DWORD tm;
|
||||||
|
|
||||||
|
if (TicFrozen != 0)
|
||||||
|
{
|
||||||
|
return TicFrozen;
|
||||||
|
}
|
||||||
|
|
||||||
tm = timeGetTime();
|
tm = timeGetTime();
|
||||||
if (!basetime)
|
if (!basetime)
|
||||||
basetime = tm;
|
basetime = tm;
|
||||||
|
@ -146,12 +153,30 @@ int I_WaitForTicPolled (int prevtic)
|
||||||
{
|
{
|
||||||
int time;
|
int time;
|
||||||
|
|
||||||
|
assert(TicFrozen == 0);
|
||||||
while ((time = I_GetTimePolled(false)) <= prevtic)
|
while ((time = I_GetTimePolled(false)) <= prevtic)
|
||||||
;
|
;
|
||||||
|
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I_FreezeTimePolled (bool frozen)
|
||||||
|
{
|
||||||
|
if (frozen)
|
||||||
|
{
|
||||||
|
assert(TicFrozen == 0);
|
||||||
|
TicFrozen = I_GetTimePolled(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(TicFrozen != 0);
|
||||||
|
int froze = TicFrozen;
|
||||||
|
TicFrozen = 0;
|
||||||
|
int now = I_GetTimePolled(false);
|
||||||
|
basetime += (now - froze) * 1000 / TICRATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int tics;
|
static int tics;
|
||||||
static DWORD ted_start, ted_next;
|
static DWORD ted_start, ted_next;
|
||||||
|
@ -168,6 +193,7 @@ int I_GetTimeEventDriven (bool saveMS)
|
||||||
|
|
||||||
int I_WaitForTicEvent (int prevtic)
|
int I_WaitForTicEvent (int prevtic)
|
||||||
{
|
{
|
||||||
|
assert(!TicFrozen);
|
||||||
while (prevtic >= tics)
|
while (prevtic >= tics)
|
||||||
{
|
{
|
||||||
WaitForSingleObject(NewTicArrived, 1000/TICRATE);
|
WaitForSingleObject(NewTicArrived, 1000/TICRATE);
|
||||||
|
@ -178,12 +204,20 @@ int I_WaitForTicEvent (int prevtic)
|
||||||
|
|
||||||
void CALLBACK TimerTicked (UINT id, UINT msg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2)
|
void CALLBACK TimerTicked (UINT id, UINT msg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2)
|
||||||
{
|
{
|
||||||
|
if (!TicFrozen)
|
||||||
|
{
|
||||||
tics++;
|
tics++;
|
||||||
|
}
|
||||||
ted_start = timeGetTime ();
|
ted_start = timeGetTime ();
|
||||||
ted_next = ted_start + MillisecondsPerTic;
|
ted_next = ted_start + MillisecondsPerTic;
|
||||||
SetEvent (NewTicArrived);
|
SetEvent (NewTicArrived);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I_FreezeTimeEventDriven(bool frozen)
|
||||||
|
{
|
||||||
|
TicFrozen = frozen;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the fractional amount of a tic passed since the most recent tic
|
// Returns the fractional amount of a tic passed since the most recent tic
|
||||||
fixed_t I_GetTimeFrac (uint32 *ms)
|
fixed_t I_GetTimeFrac (uint32 *ms)
|
||||||
{
|
{
|
||||||
|
@ -384,11 +418,13 @@ void I_Init (void)
|
||||||
{
|
{
|
||||||
I_GetTime = I_GetTimeEventDriven;
|
I_GetTime = I_GetTimeEventDriven;
|
||||||
I_WaitForTic = I_WaitForTicEvent;
|
I_WaitForTic = I_WaitForTicEvent;
|
||||||
|
I_FreezeTime = I_FreezeTimeEventDriven;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // If no timer event, busy-loop with timeGetTime
|
{ // If no timer event, busy-loop with timeGetTime
|
||||||
I_GetTime = I_GetTimePolled;
|
I_GetTime = I_GetTimePolled;
|
||||||
I_WaitForTic = I_WaitForTicPolled;
|
I_WaitForTic = I_WaitForTicPolled;
|
||||||
|
I_FreezeTime = I_FreezeTimePolled;
|
||||||
}
|
}
|
||||||
|
|
||||||
atterm (I_ShutdownSound);
|
atterm (I_ShutdownSound);
|
||||||
|
|
|
@ -54,15 +54,17 @@ extern os_t OSPlatform;
|
||||||
// Called by DoomMain.
|
// Called by DoomMain.
|
||||||
void I_Init (void);
|
void I_Init (void);
|
||||||
|
|
||||||
// Called by D_DoomLoop,
|
// Called by D_DoomLoop, returns current time in tics.
|
||||||
// returns current time in tics.
|
|
||||||
extern int (*I_GetTime) (bool saveMS);
|
extern int (*I_GetTime) (bool saveMS);
|
||||||
|
|
||||||
// like I_GetTime, except it waits for a new tic before returning
|
// like I_GetTime, except it waits for a new tic before returning
|
||||||
extern int (*I_WaitForTic) (int);
|
extern int (*I_WaitForTic) (int);
|
||||||
|
|
||||||
int I_GetTimePolled (bool saveMS);
|
// Freezes tic counting temporarily. While frozen, calls to I_GetTime()
|
||||||
int I_GetTimeFake (void);
|
// will always return the same value. This does not affect I_MSTime().
|
||||||
|
// You must also not call I_WaitForTic() while freezing time, since the
|
||||||
|
// tic will never arrive (unless it's the current one).
|
||||||
|
extern void (*I_FreezeTime) (bool frozen);
|
||||||
|
|
||||||
fixed_t I_GetTimeFrac (uint32 *ms);
|
fixed_t I_GetTimeFrac (uint32 *ms);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue