Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Client/mods/deathmatch/logic/CClientStreamElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ CClientStreamElement::CClientStreamElement(CClientStreamer* pStreamer, ElementID
m_fExpDistance = 0.0f;
m_bStreamedIn = false;
m_bAttemptingToStreamIn = false;
m_lastStreamOutTime = 0u;
m_usStreamReferences = 0;
m_usStreamReferencesScript = 0;
m_pStreamer->AddElement(this);
Expand Down Expand Up @@ -67,6 +68,7 @@ void CClientStreamElement::InternalStreamOut()
{
StreamOut();
m_bStreamedIn = false;
m_lastStreamOutTime = static_cast<std::uint32_t>(CClientTime::GetTime());

// Stream out attached elements
CClientObject* thisObject = DynamicCast<CClientObject>(this);
Expand Down
3 changes: 3 additions & 0 deletions Client/mods/deathmatch/logic/CClientStreamElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#pragma once

#include "CClientEntity.h"
#include <cstdint>
class CClientStreamer;
class CClientStreamSector;
class CClientStreamSectorRow;
Expand Down Expand Up @@ -39,6 +40,7 @@ class CClientStreamElement : public CClientEntity
void RemoveStreamReference(bool bScript = false);
unsigned short GetStreamReferences(bool bScript = false);
unsigned long GetTotalStreamReferences() { return m_usStreamReferences + m_usStreamReferencesScript; }
std::uint32_t GetLastStreamOutTime() const { return m_lastStreamOutTime; }
void StreamOutForABit();
void SetDimension(unsigned short usDimension) override;
float GetExpDistance() { return m_fExpDistance; }
Expand All @@ -64,6 +66,7 @@ class CClientStreamElement : public CClientEntity
CClientStreamer* m_pStreamer;
bool m_bStreamedIn;
bool m_bAttemptingToStreamIn;
std::uint32_t m_lastStreamOutTime;

public:
float m_fCachedRadius;
Expand Down
16 changes: 15 additions & 1 deletion Client/mods/deathmatch/logic/CClientStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*****************************************************************************/

#include "StdInc.h"
#include <cstdint>
using std::list;

void* CClientStreamer::pAddingElement = NULL;
Expand Down Expand Up @@ -375,6 +376,12 @@ bool CClientStreamer::IsActiveElement(CClientStreamElement* pElement)

void CClientStreamer::Restream(bool bMovedFar)
{
// Avoid swap ping-pong when two candidates are almost the same distance.
// Distances are squared, so compare against squared hysteresis too.
constexpr float swapHysteresisDistanceSq = 10.0f * 10.0f;
constexpr std::uint32_t minStreamInDelayAfterOutMs = 1200u;
const std::uint32_t currentTime = static_cast<std::uint32_t>(CClientTime::GetTime());

// Limit distance stream in/out rate
// Vehicles might have to ignore this to reduce blocking loads elsewhere.
int iMaxOut = 6;
Expand Down Expand Up @@ -524,6 +531,10 @@ void CClientStreamer::Restream(bool bMovedFar)
continue;
}

// Prevent rapid in/out thrashing of the same element.
if (!bMovedFar && (currentTime - pElement->GetLastStreamOutTime()) < minStreamInDelayAfterOutMs)
continue;

// Not room to stream in more elements?
if (bReachedLimit)
{
Expand Down Expand Up @@ -571,7 +582,7 @@ void CClientStreamer::Restream(bool bMovedFar)
// See if ClosestStreamedOut is nearer than FurthestStreamedIn
CClientStreamElement* pFurthestStreamedIn = FurthestStreamedInList[iFurthestStreamedInIndex];
CClientStreamElement* pClosestStreamedOut = ClosestStreamedOutList[uiClosestStreamedOutIndex];
if (pClosestStreamedOut->GetExpDistance() >= pFurthestStreamedIn->GetExpDistance())
if ((pClosestStreamedOut->GetExpDistance() + swapHysteresisDistanceSq) >= pFurthestStreamedIn->GetExpDistance())
break;

// Stream out FurthestStreamedIn candidate if possible
Expand All @@ -587,6 +598,9 @@ void CClientStreamer::Restream(bool bMovedFar)
// Stream in ClosestStreamedOut candidate if possible
if (!ReachedLimit())
{
if (!bMovedFar && (currentTime - pClosestStreamedOut->GetLastStreamOutTime()) < minStreamInDelayAfterOutMs)
continue;

// Stream in the new element. No need to do it instantly unless moved from far away.
pClosestStreamedOut->InternalStreamIn(bMovedFar);
iMaxIn--;
Expand Down
Loading