- let the prediction code handle all 4 threaded lists an actor gets linked into.
This is mostly a straight refactoring of the existing code to work independently of specific member variables in the involved classes, using a bit of template magic to avoid redundancy and moving the work code into subfunctions. It still needs some testing to see if it a) helps fix the crash issues and b) doesn't break anything-
This commit is contained in:
parent
c52bc06e9b
commit
62ea83a35a
4 changed files with 173 additions and 127 deletions
209
src/p_user.cpp
209
src/p_user.cpp
|
|
@ -95,9 +95,19 @@ static int PredictionLerptics;
|
|||
|
||||
static player_t PredictionPlayerBackup;
|
||||
static BYTE PredictionActorBackup[sizeof(APlayerPawn)];
|
||||
static TArray<sector_t *> PredictionTouchingSectorsBackup;
|
||||
static TArray<AActor *> PredictionSectorListBackup;
|
||||
static TArray<msecnode_t *> PredictionSector_sprev_Backup;
|
||||
|
||||
static TArray<sector_t *> PredictionTouchingSectorsBackup;
|
||||
static TArray<msecnode_t *> PredictionTouchingSectors_sprev_Backup;
|
||||
|
||||
static TArray<sector_t *> PredictionRenderSectorsBackup;
|
||||
static TArray<msecnode_t *> PredictionRenderSectors_sprev_Backup;
|
||||
|
||||
static TArray<sector_t *> PredictionPortalSectorsBackup;
|
||||
static TArray<msecnode_t *> PredictionPortalSectors_sprev_Backup;
|
||||
|
||||
static TArray<FLinePortal *> PredictionPortalLinesBackup;
|
||||
static TArray<portnode_t *> PredictionPortalLines_sprev_Backup;
|
||||
|
||||
// [GRB] Custom player classes
|
||||
TArray<FPlayerClass> PlayerClasses;
|
||||
|
|
@ -2775,6 +2785,100 @@ bool P_LerpCalculate(AActor *pmo, PredictPos from, PredictPos to, PredictPos &re
|
|||
return (delta.LengthSquared() > cl_predict_lerpthreshold && scale <= 1.00f);
|
||||
}
|
||||
|
||||
template<class nodetype, class linktype>
|
||||
void BackupNodeList(AActor *act, nodetype *head, nodetype *linktype::*otherlist, TArray<nodetype*, nodetype*> &prevbackup, TArray<linktype *, linktype *> &otherbackup)
|
||||
{
|
||||
// The ordering of the touching_sectorlist needs to remain unchanged
|
||||
// Also store a copy of all previous sector_thinglist nodes
|
||||
prevbackup.Clear();
|
||||
otherbackup.Clear();
|
||||
|
||||
for (auto mnode = head; mnode != nullptr; mnode = mnode->m_tnext)
|
||||
{
|
||||
otherbackup.Push(mnode->m_sector);
|
||||
|
||||
for (auto snode = mnode->m_sector->*otherlist; snode; snode = snode->m_snext)
|
||||
{
|
||||
if (snode->m_thing == act)
|
||||
{
|
||||
prevbackup.Push(snode->m_sprev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class nodetype, class linktype>
|
||||
nodetype *RestoreNodeList(AActor *act, nodetype *head, nodetype *linktype::*otherlist, TArray<nodetype*, nodetype*> &prevbackup, TArray<linktype *, linktype *> &otherbackup)
|
||||
{
|
||||
// Destroy old refrences
|
||||
nodetype *node = head;
|
||||
while (node)
|
||||
{
|
||||
node->m_thing = NULL;
|
||||
node = node->m_tnext;
|
||||
}
|
||||
|
||||
// Make the sector_list match the player's touching_sectorlist before it got predicted.
|
||||
P_DelSeclist(head, otherlist);
|
||||
head = NULL;
|
||||
for (auto i = otherbackup.Size(); i-- > 0;)
|
||||
{
|
||||
head = P_AddSecnode(otherbackup[i], act, head, otherbackup[i]->*otherlist);
|
||||
}
|
||||
//act->touching_sectorlist = ctx.sector_list; // Attach to thing
|
||||
//ctx.sector_list = NULL; // clear for next time
|
||||
|
||||
// In the old code this block never executed because of the commented-out NULL assignment above. Needs to be checked
|
||||
node = head;
|
||||
while (node)
|
||||
{
|
||||
if (node->m_thing == NULL)
|
||||
{
|
||||
if (node == head)
|
||||
head = node->m_tnext;
|
||||
node = P_DelSecnode(node, otherlist);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = node->m_tnext;
|
||||
}
|
||||
}
|
||||
|
||||
nodetype *snode;
|
||||
|
||||
// Restore sector thinglist order
|
||||
for (auto i = otherbackup.Size(); i-- > 0;)
|
||||
{
|
||||
// If we were already the head node, then nothing needs to change
|
||||
if (prevbackup[i] == NULL)
|
||||
continue;
|
||||
|
||||
for (snode = otherbackup[i]->*otherlist; snode; snode = snode->m_snext)
|
||||
{
|
||||
if (snode->m_thing == act)
|
||||
{
|
||||
if (snode->m_sprev)
|
||||
snode->m_sprev->m_snext = snode->m_snext;
|
||||
else
|
||||
snode->m_sector->*otherlist = snode->m_snext;
|
||||
if (snode->m_snext)
|
||||
snode->m_snext->m_sprev = snode->m_sprev;
|
||||
|
||||
snode->m_sprev = prevbackup[i];
|
||||
|
||||
// At the moment, we don't exist in the list anymore, but we do know what our previous node is, so we set its current m_snext->m_sprev to us.
|
||||
if (snode->m_sprev->m_snext)
|
||||
snode->m_sprev->m_snext->m_sprev = snode;
|
||||
snode->m_snext = snode->m_sprev->m_snext;
|
||||
snode->m_sprev->m_snext = snode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
void P_PredictPlayer (player_t *player)
|
||||
{
|
||||
int maxtic;
|
||||
|
|
@ -2809,28 +2913,10 @@ void P_PredictPlayer (player_t *player)
|
|||
act->flags2 &= ~MF2_PUSHWALL;
|
||||
player->cheats |= CF_PREDICTING;
|
||||
|
||||
// The ordering of the touching_sectorlist needs to remain unchanged
|
||||
// Also store a copy of all previous sector_thinglist nodes
|
||||
msecnode_t *mnode = act->touching_sectorlist;
|
||||
msecnode_t *snode;
|
||||
PredictionSector_sprev_Backup.Clear();
|
||||
PredictionTouchingSectorsBackup.Clear ();
|
||||
|
||||
while (mnode != NULL)
|
||||
{
|
||||
PredictionTouchingSectorsBackup.Push (mnode->m_sector);
|
||||
|
||||
for (snode = mnode->m_sector->touching_thinglist; snode; snode = snode->m_snext)
|
||||
{
|
||||
if (snode->m_thing == act)
|
||||
{
|
||||
PredictionSector_sprev_Backup.Push(snode->m_sprev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mnode = mnode->m_tnext;
|
||||
}
|
||||
BackupNodeList(act, act->touching_sectorlist, §or_t::touching_thinglist, PredictionTouchingSectors_sprev_Backup, PredictionTouchingSectorsBackup);
|
||||
BackupNodeList(act, act->touching_rendersectors, §or_t::touching_renderthings, PredictionRenderSectors_sprev_Backup, PredictionRenderSectorsBackup);
|
||||
BackupNodeList(act, act->touching_sectorportallist, §or_t::sectorportal_thinglist, PredictionPortalSectors_sprev_Backup, PredictionPortalSectorsBackup);
|
||||
BackupNodeList(act, act->touching_lineportallist, &FLinePortal::lineportal_thinglist, PredictionPortalLines_sprev_Backup, PredictionPortalLinesBackup);
|
||||
|
||||
// Keep an ordered list off all actors in the linked sector.
|
||||
PredictionSectorListBackup.Clear();
|
||||
|
|
@ -2940,6 +3026,12 @@ void P_UnPredictPlayer ()
|
|||
player->camera = savedcamera;
|
||||
|
||||
FLinkContext ctx;
|
||||
// Unlink from all list, includeing those which are not being handled by UnlinkFromWorld.
|
||||
auto sectorportal_list = act->touching_sectorportallist;
|
||||
auto lineportal_list = act->touching_lineportallist;
|
||||
act->touching_sectorportallist = nullptr;
|
||||
act->touching_lineportallist = nullptr;
|
||||
|
||||
act->UnlinkFromWorld(&ctx);
|
||||
memcpy(&act->snext, PredictionActorBackup, sizeof(APlayerPawn) - ((BYTE *)&act->snext - (BYTE *)act));
|
||||
|
||||
|
|
@ -2968,71 +3060,10 @@ void P_UnPredictPlayer ()
|
|||
*link = me;
|
||||
}
|
||||
|
||||
// Destroy old refrences
|
||||
msecnode_t *node = ctx.sector_list;
|
||||
while (node)
|
||||
{
|
||||
node->m_thing = NULL;
|
||||
node = node->m_tnext;
|
||||
}
|
||||
|
||||
// Make the sector_list match the player's touching_sectorlist before it got predicted.
|
||||
P_DelSeclist(ctx.sector_list, §or_t::touching_thinglist);
|
||||
ctx.sector_list = NULL;
|
||||
for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;)
|
||||
{
|
||||
ctx.sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, ctx.sector_list, PredictionTouchingSectorsBackup[i]->touching_thinglist);
|
||||
}
|
||||
act->touching_sectorlist = ctx.sector_list; // Attach to thing
|
||||
ctx.sector_list = NULL; // clear for next time
|
||||
|
||||
// Huh???
|
||||
node = ctx.sector_list;
|
||||
while (node)
|
||||
{
|
||||
if (node->m_thing == NULL)
|
||||
{
|
||||
if (node == ctx.sector_list)
|
||||
ctx.sector_list = node->m_tnext;
|
||||
node = P_DelSecnode(node, §or_t::touching_thinglist);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = node->m_tnext;
|
||||
}
|
||||
}
|
||||
|
||||
msecnode_t *snode;
|
||||
|
||||
// Restore sector thinglist order
|
||||
for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;)
|
||||
{
|
||||
// If we were already the head node, then nothing needs to change
|
||||
if (PredictionSector_sprev_Backup[i] == NULL)
|
||||
continue;
|
||||
|
||||
for (snode = PredictionTouchingSectorsBackup[i]->touching_thinglist; snode; snode = snode->m_snext)
|
||||
{
|
||||
if (snode->m_thing == act)
|
||||
{
|
||||
if (snode->m_sprev)
|
||||
snode->m_sprev->m_snext = snode->m_snext;
|
||||
else
|
||||
snode->m_sector->touching_thinglist = snode->m_snext;
|
||||
if (snode->m_snext)
|
||||
snode->m_snext->m_sprev = snode->m_sprev;
|
||||
|
||||
snode->m_sprev = PredictionSector_sprev_Backup[i];
|
||||
|
||||
// At the moment, we don't exist in the list anymore, but we do know what our previous node is, so we set its current m_snext->m_sprev to us.
|
||||
if (snode->m_sprev->m_snext)
|
||||
snode->m_sprev->m_snext->m_sprev = snode;
|
||||
snode->m_snext = snode->m_sprev->m_snext;
|
||||
snode->m_sprev->m_snext = snode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
act->touching_sectorlist = RestoreNodeList(act, ctx.sector_list, §or_t::touching_thinglist, PredictionTouchingSectors_sprev_Backup, PredictionTouchingSectorsBackup);
|
||||
act->touching_rendersectors = RestoreNodeList(act, ctx.render_list, §or_t::touching_renderthings, PredictionRenderSectors_sprev_Backup, PredictionRenderSectorsBackup);
|
||||
act->touching_sectorportallist = RestoreNodeList(act, sectorportal_list, §or_t::sectorportal_thinglist, PredictionPortalSectors_sprev_Backup, PredictionPortalSectorsBackup);
|
||||
act->touching_lineportallist = RestoreNodeList(act, lineportal_list, &FLinePortal::lineportal_thinglist, PredictionPortalLines_sprev_Backup, PredictionPortalLinesBackup);
|
||||
}
|
||||
|
||||
// Now fix the pointers in the blocknode chain
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue