Added client-side Thinkers
Adds support for client-side Thinkers, Actors, and ACS scripts (ACS uses the existing CLIENTSIDE keyword). These will tick regardless of the network state allowing for localized client handling and are put in their own separate lists so they can't be accidentally accessed by server code. They currently aren't serialized since this would have no meaning for other clients in the game that would get saved. Other logic like the menu, console, HUD, and particles have also been moved to client-side ticking to prevent them from becoming locked up by poor network conditions. Additionally, screenshotting and the automap are now handled immediately instead of having to wait for any game tick to run first, making them free of net lag.
This commit is contained in:
parent
e4081df0db
commit
f7e62a8cd6
28 changed files with 507 additions and 215 deletions
|
|
@ -157,15 +157,6 @@ static TArray<AActor *> PredictionSectorListBackup;
|
|||
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;
|
||||
|
||||
struct
|
||||
{
|
||||
DVector3 Pos = {};
|
||||
|
|
@ -1381,19 +1372,9 @@ void BackupNodeList(AActor *act, nodetype *head, nodetype *linktype::*otherlist,
|
|||
}
|
||||
|
||||
template<class nodetype, class linktype>
|
||||
nodetype *RestoreNodeList(AActor *act, nodetype *head, nodetype *linktype::*otherlist, TArray<nodetype*, nodetype*> &prevbackup, TArray<linktype *, linktype *> &otherbackup)
|
||||
nodetype *RestoreNodeList(AActor *act, 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;
|
||||
nodetype* head = NULL;
|
||||
for (auto i = otherbackup.Size(); i-- > 0;)
|
||||
{
|
||||
head = P_AddSecnode(otherbackup[i], act, head, otherbackup[i]->*otherlist);
|
||||
|
|
@ -1402,7 +1383,7 @@ nodetype *RestoreNodeList(AActor *act, nodetype *head, nodetype *linktype::*othe
|
|||
//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;
|
||||
nodetype* node = head;
|
||||
while (node)
|
||||
{
|
||||
if (node->m_thing == NULL)
|
||||
|
|
@ -1496,9 +1477,6 @@ void P_PredictPlayer (player_t *player)
|
|||
player->cheats |= CF_PREDICTING;
|
||||
|
||||
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();
|
||||
|
|
@ -1637,15 +1615,15 @@ void P_UnPredictPlayer ()
|
|||
// could cause it to change during prediction.
|
||||
player->camera = savedcamera;
|
||||
|
||||
FLinkContext ctx;
|
||||
// Unlink from all list, including 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);
|
||||
// Unlink from all lists
|
||||
act->UnlinkFromWorld(nullptr);
|
||||
memcpy(&act->snext, PredictionActorBackupArray.Data(), PredictionActorBackupArray.Size() - ((uint8_t *)&act->snext - (uint8_t *)act));
|
||||
// Clear stale pointers. The blockmap node is kept since it's the one that will be relinked back into the blockmap. Given
|
||||
// it was removed from the list without being freed before predicting it's still valid.
|
||||
act->touching_lineportallist = nullptr;
|
||||
act->touching_rendersectors = act->touching_sectorlist = act->touching_sectorportallist = nullptr;
|
||||
act->sprev = (AActor**)(size_t)0xBeefCafe;
|
||||
act->snext = nullptr;
|
||||
|
||||
if (act->ViewPos != nullptr)
|
||||
{
|
||||
|
|
@ -1678,15 +1656,15 @@ void P_UnPredictPlayer ()
|
|||
*link = me;
|
||||
}
|
||||
|
||||
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);
|
||||
// Only the touching list actually needs to be restored to avoid impacting gameplay. The rest is just clientside fluff that can
|
||||
// be handled by relinking.
|
||||
act->touching_sectorlist = RestoreNodeList(act, §or_t::touching_thinglist, PredictionTouchingSectors_sprev_Backup, PredictionTouchingSectorsBackup);
|
||||
if (act->renderradius >= 0.0)
|
||||
act->touching_rendersectors = P_CreateSecNodeList(act, act->RenderRadius(), nullptr, §or_t::touching_renderthings);
|
||||
}
|
||||
|
||||
// Now fix the pointers in the blocknode chain
|
||||
FBlockNode *block = act->BlockNode;
|
||||
|
||||
while (block != NULL)
|
||||
{
|
||||
*(block->PrevActor) = block;
|
||||
|
|
@ -1697,6 +1675,8 @@ void P_UnPredictPlayer ()
|
|||
block = block->NextBlock;
|
||||
}
|
||||
|
||||
act->UpdateRenderSectorList();
|
||||
|
||||
actInvSel = InvSel;
|
||||
player->inventorytics = inventorytics;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue