mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Experimental: Improve level load processing
- P_PreTicker ("defrosting") is dead. Levels now actually start on tic 0 instead of tic 2.
- Netxcmds are ran before G_Ticker, instead of after.
- All netxcmds are required to be processed before the level will finish loading (up to 5 gametics, to prevent any possible lock-up from malicious clients).
This commit is contained in:
parent
cd7d4f23c7
commit
ffb65a3583
9 changed files with 122 additions and 152 deletions
|
|
@ -383,11 +383,13 @@ static UINT8* D_GetTextcmd(tic_t tic, INT32 playernum)
|
|||
return textcmdplayer->cmd;
|
||||
}
|
||||
|
||||
static void ExtraDataTicker(void)
|
||||
static boolean ExtraDataTicker(void)
|
||||
{
|
||||
boolean anyNetCmd = false;
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] || i == 0)
|
||||
{
|
||||
UINT8 *bufferstart = D_GetExistingTextcmd(gametic, i);
|
||||
|
|
@ -407,6 +409,7 @@ static void ExtraDataTicker(void)
|
|||
DEBFILE(va("executing x_cmd %s ply %u ", netxcmdnames[id - 1], i));
|
||||
(listnetxcmd[id])(&curpos, i);
|
||||
DEBFILE("done\n");
|
||||
anyNetCmd = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -421,12 +424,17 @@ static void ExtraDataTicker(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If you are a client, you can safely forget the net commands for this tic
|
||||
// If you are the server, you need to remember them until every client has been acknowledged,
|
||||
// because if you need to resend a PT_SERVERTICS packet, you will need to put the commands in it
|
||||
if (client)
|
||||
{
|
||||
D_FreeTextcmd(gametic);
|
||||
}
|
||||
|
||||
return anyNetCmd;
|
||||
}
|
||||
|
||||
static void D_Clearticcmd(tic_t tic)
|
||||
|
|
@ -5002,7 +5010,7 @@ static void GetPackets(void)
|
|||
|
||||
if (netbuffer->packettype == PT_CLIENTJOIN && server)
|
||||
{
|
||||
if (!levelloading) // Otherwise just ignore
|
||||
if (levelloading == false) // Otherwise just ignore
|
||||
{
|
||||
HandleConnect(node);
|
||||
}
|
||||
|
|
@ -5585,35 +5593,55 @@ boolean TryRunTics(tic_t realtics)
|
|||
|
||||
if (ticking)
|
||||
{
|
||||
// run the count * tics
|
||||
while (neededtic > gametic)
|
||||
{
|
||||
// run the count * tics
|
||||
while (neededtic > gametic)
|
||||
boolean dontRun = false;
|
||||
|
||||
DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic));
|
||||
|
||||
ps_tictime = I_GetPreciseTime();
|
||||
|
||||
dontRun = ExtraDataTicker();
|
||||
|
||||
if (levelloading == false
|
||||
|| gametic > levelstarttic + 5) // Don't lock-up if a malicious client is sending tons of netxcmds
|
||||
{
|
||||
DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic));
|
||||
// During level load, we want to pause
|
||||
// execution until we've finished loading
|
||||
// all of the netxcmds in our buffer.
|
||||
dontRun = false;
|
||||
}
|
||||
|
||||
ps_tictime = I_GetPreciseTime();
|
||||
|
||||
G_Ticker((gametic % NEWTICRATERATIO) == 0);
|
||||
if (Playing() && netgame && (gametic % TICRATE == 0))
|
||||
if (dontRun == false)
|
||||
{
|
||||
if (levelloading == true)
|
||||
{
|
||||
Schedule_Run();
|
||||
|
||||
if (cv_livestudioaudience.value)
|
||||
{
|
||||
LiveStudioAudience();
|
||||
}
|
||||
P_PostLoadLevel();
|
||||
}
|
||||
|
||||
ExtraDataTicker();
|
||||
G_Ticker((gametic % NEWTICRATERATIO) == 0);
|
||||
}
|
||||
|
||||
gametic++;
|
||||
consistancy[gametic%BACKUPTICS] = Consistancy();
|
||||
if (Playing() && netgame && (gametic % TICRATE == 0))
|
||||
{
|
||||
Schedule_Run();
|
||||
|
||||
ps_tictime = I_GetPreciseTime() - ps_tictime;
|
||||
if (cv_livestudioaudience.value)
|
||||
{
|
||||
LiveStudioAudience();
|
||||
}
|
||||
}
|
||||
|
||||
// Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame.
|
||||
if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value)
|
||||
break;
|
||||
gametic++;
|
||||
consistancy[gametic % BACKUPTICS] = Consistancy();
|
||||
|
||||
ps_tictime = I_GetPreciseTime() - ps_tictime;
|
||||
|
||||
// Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame.
|
||||
if (client && gamestate == GS_LEVEL && leveltime > 1 && neededtic <= gametic + cv_netticbuffer.value)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
32
src/g_game.c
32
src/g_game.c
|
|
@ -1589,30 +1589,30 @@ void G_StartTitleCard(void)
|
|||
void G_PreLevelTitleCard(void)
|
||||
{
|
||||
#ifndef NOWIPE
|
||||
tic_t strtime = I_GetTime();
|
||||
tic_t endtime = strtime + (PRELEVELTIME*NEWTICRATERATIO);
|
||||
tic_t nowtime = strtime;
|
||||
tic_t lasttime = strtime;
|
||||
while (nowtime < endtime)
|
||||
{
|
||||
// draw loop
|
||||
ST_runTitleCard();
|
||||
ST_preLevelTitleCardDrawer();
|
||||
I_FinishUpdate(); // page flip or blit buffer
|
||||
tic_t strtime = I_GetTime();
|
||||
tic_t endtime = strtime + (PRELEVELTIME*NEWTICRATERATIO);
|
||||
tic_t nowtime = strtime;
|
||||
tic_t lasttime = strtime;
|
||||
while (nowtime < endtime)
|
||||
{
|
||||
// draw loop
|
||||
ST_runTitleCard();
|
||||
ST_preLevelTitleCardDrawer();
|
||||
I_FinishUpdate(); // page flip or blit buffer
|
||||
NetKeepAlive(); // Prevent timeouts
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (moviemode && rendermode == render_opengl)
|
||||
M_LegacySaveFrame();
|
||||
if (moviemode && rendermode == render_opengl)
|
||||
M_LegacySaveFrame();
|
||||
#endif
|
||||
|
||||
while (!((nowtime = I_GetTime()) - lasttime))
|
||||
{
|
||||
while (!((nowtime = I_GetTime()) - lasttime))
|
||||
{
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
lasttime = nowtime;
|
||||
}
|
||||
lasttime = nowtime;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ static void K_SpawnDuelOnlyItems(void)
|
|||
|
||||
void K_TimerReset(void)
|
||||
{
|
||||
starttime = introtime = 3;
|
||||
starttime = introtime = 0;
|
||||
numbulbs = 1;
|
||||
inDuel = rainbowstartavailable = false;
|
||||
timelimitintics = extratimeintics = secretextratime = 0;
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ ENUM (STRING_HOOK);
|
|||
//#define LUA_HUDHOOK(type) LUA_HookHUD(HUD_HOOK(type))
|
||||
|
||||
extern boolean hook_cmd_running;
|
||||
extern int hook_defrosting;
|
||||
|
||||
void LUA_HookVoid(int hook);
|
||||
void LUA_HookHUD(huddrawlist_h, int hook);
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@
|
|||
|
||||
lua_State *gL = NULL;
|
||||
|
||||
int hook_defrosting;
|
||||
|
||||
// List of internal libraries to load from SRB2
|
||||
static lua_CFunction liblist[] = {
|
||||
LUA_EnumLib, // global metatable for enums
|
||||
|
|
@ -288,9 +286,6 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
} else if (fastcmp(word,"starttime")) {
|
||||
lua_pushinteger(L, starttime);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"defrosting")) {
|
||||
lua_pushinteger(L, hook_defrosting);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"curWeather")) {
|
||||
lua_pushinteger(L, curWeather);
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -10938,7 +10938,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
// Call action functions when the state is set
|
||||
if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC))
|
||||
{
|
||||
if (levelloading)
|
||||
if (levelloading == true)
|
||||
{
|
||||
// Cache actions in a linked list
|
||||
// with function pointer, and
|
||||
|
|
|
|||
|
|
@ -7064,6 +7064,8 @@ static void P_InitLevelSettings(void)
|
|||
leveltime = 0;
|
||||
modulothing = 0;
|
||||
|
||||
K_TimerReset();
|
||||
|
||||
// special stage tokens, emeralds, and ring total
|
||||
runemeraldmanager = false;
|
||||
emeraldspawndelay = 60*TICRATE;
|
||||
|
|
@ -7618,8 +7620,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
sector_t *ss;
|
||||
virtlump_t *encoreLump = NULL;
|
||||
|
||||
K_TimerReset();
|
||||
|
||||
levelloading = true;
|
||||
|
||||
// This is needed. Don't touch.
|
||||
|
|
@ -7999,10 +7999,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
|
||||
G_AddMapToBuffer(gamemap-1);
|
||||
|
||||
levelloading = false;
|
||||
|
||||
P_RunCachedActions();
|
||||
|
||||
P_MapEnd(); // tm.thing is no longer needed from this point onwards
|
||||
|
||||
// Took me 3 hours to figure out why my progression kept on getting overwritten with the titlemap...
|
||||
|
|
@ -8012,56 +8008,84 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
{
|
||||
// I'd love to do this in the menu code instead of here, but everything's a mess and I can't guarantee saving proper player struct info before the first act's started. You could probably refactor it, but it'd be a lot of effort. Easier to just work off known good code. ~toast 22/06/2020
|
||||
if (!(ultimatemode || netgame || multiplayer || demo.playback || demo.recording || metalrecording || modeattacking || marathonmode)
|
||||
&& !usedCheats && cursaveslot > 0)
|
||||
&& !usedCheats && cursaveslot > 0)
|
||||
{
|
||||
G_SaveGame((UINT32)cursaveslot, gamemap);
|
||||
}
|
||||
// If you're looking for saving sp file progression (distinct from G_SaveGameOver), check G_DoCompleted.
|
||||
}
|
||||
lastmaploaded = gamemap; // HAS to be set after saving!!
|
||||
}
|
||||
|
||||
if (!fromnetsave) // uglier hack
|
||||
{ // to make a newly loaded level start on the second frame.
|
||||
if (!fromnetsave)
|
||||
{
|
||||
INT32 buf = gametic % BACKUPTICS;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
|
||||
}
|
||||
}
|
||||
|
||||
P_PreTicker(2);
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
{
|
||||
postimgtype[i] = postimg_none;
|
||||
}
|
||||
|
||||
if (marathonmode & MA_INGAME)
|
||||
{
|
||||
marathonmode |= MA_INIT;
|
||||
}
|
||||
|
||||
P_MapStart(); // just in case MapLoad modifies tm.thing
|
||||
|
||||
ACS_RunLevelStartScripts();
|
||||
LUA_HookInt(gamemap, HOOK(MapLoad));
|
||||
|
||||
P_MapEnd(); // just in case MapLoad modifies tm.thing
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't run P_PostLoadLevel when loading netgames.
|
||||
levelloading = false;
|
||||
}
|
||||
|
||||
// No render mode or reloading gamestate, stop here.
|
||||
if (rendermode == render_none || reloadinggamestate)
|
||||
return true;
|
||||
if (rendermode != render_none && reloadinggamestate == false)
|
||||
{
|
||||
R_ResetViewInterpolation(0);
|
||||
R_ResetViewInterpolation(0);
|
||||
R_UpdateMobjInterpolators();
|
||||
|
||||
R_ResetViewInterpolation(0);
|
||||
R_ResetViewInterpolation(0);
|
||||
R_UpdateMobjInterpolators();
|
||||
// Title card!
|
||||
G_StartTitleCard();
|
||||
|
||||
// Title card!
|
||||
G_StartTitleCard();
|
||||
|
||||
// Can the title card actually run, though?
|
||||
if (!WipeStageTitle)
|
||||
return true;
|
||||
if (ranspecialwipe == 2)
|
||||
return true;
|
||||
|
||||
// If so...
|
||||
// but not if joining because the fade may time us out
|
||||
if (!fromnetsave)
|
||||
G_PreLevelTitleCard();
|
||||
// Can the title card actually run, though?
|
||||
if (WipeStageTitle && ranspecialwipe != 2 && fromnetsave == false)
|
||||
{
|
||||
G_PreLevelTitleCard();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void P_PostLoadLevel(void)
|
||||
{
|
||||
K_TimerInit();
|
||||
|
||||
P_RunCachedActions();
|
||||
|
||||
if (marathonmode & MA_INGAME)
|
||||
{
|
||||
marathonmode &= ~MA_INIT;
|
||||
}
|
||||
|
||||
// We're now done loading the level.
|
||||
levelloading = false;
|
||||
}
|
||||
|
||||
//
|
||||
// P_RunSOC
|
||||
//
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ extern mapthing_t *mapthings;
|
|||
void P_SetupLevelSky(const char *skytexname, boolean global);
|
||||
void P_RespawnThings(void);
|
||||
boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate);
|
||||
void P_PostLoadLevel(void);
|
||||
#ifdef HWRENDER
|
||||
void HWR_LoadLevel(void);
|
||||
#endif
|
||||
|
|
|
|||
77
src/p_tick.c
77
src/p_tick.c
|
|
@ -832,86 +832,9 @@ void P_Ticker(boolean run)
|
|||
if (demo.playback)
|
||||
G_StoreRewindInfo();
|
||||
|
||||
if (leveltime == 2)
|
||||
{
|
||||
// The values needed to set this properly are not correct at map load,
|
||||
// so we have to do it at the second tick instead...
|
||||
K_TimerInit();
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
G_CopyTiccmd(&players[i].oldcmd, &players[i].cmd, 1);
|
||||
}
|
||||
|
||||
// Z_CheckMemCleanup();
|
||||
}
|
||||
|
||||
// Abbreviated ticker for pre-loading, calls thinkers and assorted things
|
||||
void P_PreTicker(INT32 frames)
|
||||
{
|
||||
INT32 i;
|
||||
ticcmd_t temptic;
|
||||
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
postimgtype[i] = postimg_none;
|
||||
|
||||
if (marathonmode & MA_INGAME)
|
||||
marathonmode |= MA_INIT;
|
||||
|
||||
hook_defrosting = frames;
|
||||
|
||||
while (hook_defrosting)
|
||||
{
|
||||
P_MapStart();
|
||||
|
||||
R_UpdateMobjInterpolators();
|
||||
|
||||
LUA_HOOK(PreThinkFrame);
|
||||
|
||||
K_UpdateAllPlayerPositions();
|
||||
|
||||
// OK! Now that we got all of that sorted, players can think!
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
|
||||
{
|
||||
// stupid fucking cmd hack
|
||||
// if it isn't for this, players can move in preticker time
|
||||
// (and disrupt demo recording and other things !!)
|
||||
memcpy(&temptic, &players[i].cmd, sizeof(ticcmd_t));
|
||||
memset(&players[i].cmd, 0, sizeof(ticcmd_t));
|
||||
|
||||
P_PlayerThink(&players[i]);
|
||||
|
||||
memcpy(&players[i].cmd, &temptic, sizeof(ticcmd_t));
|
||||
}
|
||||
|
||||
P_RunThinkers();
|
||||
|
||||
// Run any "after all the other thinkers" stuff
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
|
||||
P_PlayerAfterThink(&players[i]);
|
||||
|
||||
LUA_HOOK(ThinkFrame);
|
||||
|
||||
// Run shield positioning
|
||||
P_RunOverlays();
|
||||
|
||||
P_UpdateSpecials();
|
||||
P_RespawnSpecials();
|
||||
|
||||
LUA_HOOK(PostThinkFrame);
|
||||
|
||||
R_UpdateLevelInterpolators();
|
||||
R_UpdateViewInterpolation();
|
||||
R_ResetViewInterpolation(0);
|
||||
|
||||
P_MapEnd();
|
||||
|
||||
hook_defrosting--;
|
||||
}
|
||||
|
||||
if (marathonmode & MA_INGAME)
|
||||
marathonmode &= ~MA_INIT;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue