Skip to content

Fix bad streaming performance in some cases #4013

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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
1 change: 1 addition & 0 deletions Client/mods/deathmatch/logic/CClientStreamSector.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class CClientStreamSector
void Remove(CClientStreamElement* pElement) { m_Elements.remove(pElement); }
std::list<CClientStreamElement*>::iterator Begin() { return m_Elements.begin(); }
std::list<CClientStreamElement*>::iterator End() { return m_Elements.end(); }
std::list<CClientStreamElement*>& GetElements() { return m_Elements; }

void AddElements(std::list<CClientStreamElement*>* pList);
void RemoveElements(std::list<CClientStreamElement*>* pList);
Expand Down
1 change: 1 addition & 0 deletions Client/mods/deathmatch/logic/CClientStreamSectorRow.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class CClientStreamSectorRow
void Add(CClientStreamSector* pSector);
void Remove(CClientStreamSector* pSector);
unsigned int CountSectors() { return m_Sectors.size(); }
std::list<CClientStreamSector*>& GetList() noexcept { return m_Sectors; }

bool DoesContain(CVector& vecPosition);
bool DoesContain(float fY);
Expand Down
270 changes: 148 additions & 122 deletions Client/mods/deathmatch/logic/CClientStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
*****************************************************************************/

#include "StdInc.h"
#include "CClientGame.h"

extern CClientGame* g_pClientGame;
using std::list;

void* CClientStreamer::pAddingElement = NULL;
Expand Down Expand Up @@ -107,51 +110,8 @@ void CClientStreamer::ConnectRow(CClientStreamSectorRow* pRow)
pRow->m_pBottom->m_pTop = pRow;
}

#include "..\deathmatch\logic\CClientGame.h"
extern CClientGame* g_pClientGame;
void CClientStreamer::DoPulse(CVector& vecPosition)
void CClientStreamer::DoPulse(CVector& vecPosition)
{
/* Debug code
CClientStreamSector * pSector;
list < CClientStreamSector * > ::iterator iterSector;
list < CClientStreamSectorRow * > ::iterator iterRow = m_WorldRows.begin ();
for ( ; iterRow != m_WorldRows.end () ; iterRow++ )
{
iterSector = (*iterRow)->Begin ();
for ( ; iterSector != (*iterRow)->End () ; iterSector++ )
{
pSector = *iterSector;
if ( !pSector->m_pArea )
{
pSector->m_pArea = new CClientRadarArea ( g_pClientGame->GetManager (), INVALID_ELEMENT_ID );
pSector->m_pArea->SetPosition ( pSector->m_vecBottomLeft );
CVector2D vecSize ( pSector->m_vecTopRight.fX - pSector->m_vecBottomLeft.fX, pSector->m_vecTopRight.fY - pSector->m_vecBottomLeft.fY );
pSector->m_pArea->SetSize ( vecSize );
pSector->m_pArea->SetColor ( 255, 0, 0, 50 );
}
pSector->m_pArea->SetColor ( 255, 0, 0, 50 );
}
}
iterRow = m_ExtraRows.begin ();
for ( ; iterRow != m_ExtraRows.end () ; iterRow++ )
{
iterSector = (*iterRow)->Begin ();
for ( ; iterSector != (*iterRow)->End () ; iterSector++ )
{
pSector = *iterSector;
if ( !pSector->m_pArea )
{
pSector->m_pArea = new CClientRadarArea ( g_pClientGame->GetManager (), INVALID_ELEMENT_ID );
pSector->m_pArea->SetPosition ( pSector->m_vecBottomLeft );
CVector2D vecSize ( pSector->m_vecTopRight.fX - pSector->m_vecBottomLeft.fX, pSector->m_vecTopRight.fY - pSector->m_vecBottomLeft.fY );
pSector->m_pArea->SetSize ( vecSize );
pSector->m_pArea->SetColor ( 255, 0, 0, 50 );
}
pSector->m_pArea->SetColor ( 255, 0, 0, 50 );
}
}
*/

bool bMovedFar = false;
// Has our position changed?
if (vecPosition != m_vecPosition)
Expand Down Expand Up @@ -183,27 +143,62 @@ void CClientStreamer::DoPulse(CVector& vecPosition)
void CClientStreamer::SetDimension(unsigned short usDimension)
{
// Different dimension than before?
if (usDimension != m_usDimension)
if (usDimension == m_usDimension)
return;

// Set the new dimension
m_usDimension = usDimension;

const CClientStreamElement* lastOutsideElement = m_outsideCurrentDimensionElements.empty() ? nullptr : m_outsideCurrentDimensionElements.back();

auto filterElementInRows = [this](list<CClientStreamSectorRow*>& list)
{
// Set the new dimension
m_usDimension = usDimension;

// That means all of the currently streamed in elements will have to
// go. Unstream all elements that are streamed in.
CClientStreamElement* pElement = NULL;
list<CClientStreamElement*>::iterator iter = m_ActiveElements.begin();
for (; iter != m_ActiveElements.end(); iter++)
for (CClientStreamSectorRow* sectorRow : list)
{
pElement = *iter;
if (pElement->IsStreamedIn())
for (CClientStreamSector* sector : sectorRow->GetList())
{
if (!pElement->IsVisibleInAllDimensions())
auto& elements = sector->GetElements();
auto iter = elements.begin();
while (iter != sector->End())
{
// Unstream it
m_ToStreamOut.push_back(pElement);
CClientStreamElement* element = *iter;

if (IsElementShouldVisibleInCurrentDimesnion(element))
iter++;
else
{
iter = elements.erase(iter);
m_outsideCurrentDimensionElements.push_back(element);
element->SetStreamSector(nullptr);

if (element->IsStreamedIn())
m_ToStreamOut.push_back(element);
}
}
}
}
};

filterElementInRows(m_WorldRows);
filterElementInRows(m_ExtraRows);

if (!lastOutsideElement)
return;

auto iter = m_outsideCurrentDimensionElements.begin();

while (*iter != lastOutsideElement)
{
CClientStreamElement* element = *iter;
if (element->GetDimension() == usDimension)
{
iter = m_outsideCurrentDimensionElements.erase(iter);
AddElementInSectors(element);
}
else
{
iter++;
}
}
}

Expand Down Expand Up @@ -281,6 +276,9 @@ CClientStreamSectorRow* CClientStreamer::FindRow(float fY)

void CClientStreamer::OnUpdateStreamPosition(CClientStreamElement* pElement)
{
if (!pElement->GetStreamSector())
return;

CVector vecPosition = pElement->GetStreamPosition();
CClientStreamSectorRow* pRow = pElement->GetStreamRow();
CClientStreamSector* pSector = pElement->GetStreamSector();
Expand All @@ -305,7 +303,7 @@ void CClientStreamer::OnUpdateStreamPosition(CClientStreamElement* pElement)
}
}

void CClientStreamer::AddElement(CClientStreamElement* pElement)
void CClientStreamer::AddElementInSectors(CClientStreamElement* pElement)
{
assert(pAddingElement == NULL);
pAddingElement = pElement;
Expand All @@ -316,13 +314,28 @@ void CClientStreamer::AddElement(CClientStreamElement* pElement)
pAddingElement = NULL;
}

void CClientStreamer::RemoveElement(CClientStreamElement* pElement)
void CClientStreamer::RemoveElementFromSectors(CClientStreamElement* pElement)
{
OnElementEnterSector(pElement, NULL);
m_ActiveElements.remove(pElement);
OnElementEnterSector(pElement, nullptr);
m_ToStreamOut.remove(pElement);
}

void CClientStreamer::AddElement(CClientStreamElement* pElement)
{
if (IsElementShouldVisibleInCurrentDimesnion(pElement))
AddElementInSectors(pElement);
else
m_outsideCurrentDimensionElements.push_back(pElement);
}

void CClientStreamer::RemoveElement(CClientStreamElement* pElement)
{
if (pElement->GetStreamSector())
RemoveElementFromSectors(pElement);
else
m_outsideCurrentDimensionElements.remove(pElement);
}

void CClientStreamer::SetExpDistances(list<CClientStreamElement*>* pList)
{
// Run through our list setting distances to world center
Expand Down Expand Up @@ -489,71 +502,67 @@ void CClientStreamer::Restream(bool bMovedFar)
}
else
{
// Same dimension as us?
if (pElement->GetDimension() == m_usDimension || pElement->IsVisibleInAllDimensions())
{
// Too far away? Stop here.
if (fElementDistanceExp > m_fMaxDistanceExp)
continue;
// Too far away? Stop here.
if (fElementDistanceExp > m_fMaxDistanceExp)
continue;

if (IS_VEHICLE(pElement))
{
CClientVehicle* pVehicle = DynamicCast<CClientVehicle>(pElement);
if (pVehicle && pVehicle->GetOccupant() && IS_PLAYER(pVehicle->GetOccupant()))
{
CClientPlayer* pPlayer = DynamicCast<CClientPlayer>(pVehicle->GetOccupant());
if (pPlayer->GetLastPuresyncType() == PURESYNC_TYPE_LIGHTSYNC)
{
// if the last packet was ls he isn't streaming in soon.
continue;
}
}

if (pVehicle && pVehicle->GetTowedByVehicle())
{
// Streaming in of towed vehicles is done in CClientVehicle::StreamIn by the towing vehicle
continue;
}
}
if (IS_PLAYER(pElement))
if (IS_VEHICLE(pElement))
{
CClientVehicle* pVehicle = DynamicCast<CClientVehicle>(pElement);
if (pVehicle && pVehicle->GetOccupant() && IS_PLAYER(pVehicle->GetOccupant()))
{
CClientPlayer* pPlayer = DynamicCast<CClientPlayer>(pElement);
CClientPlayer* pPlayer = DynamicCast<CClientPlayer>(pVehicle->GetOccupant());
if (pPlayer->GetLastPuresyncType() == PURESYNC_TYPE_LIGHTSYNC)
{
// if the last packet was ls he isn't streaming in soon.
continue;
}
}
// If attached and attached-to is streamed out, don't consider for streaming in
CClientStreamElement* pAttachedTo = DynamicCast<CClientStreamElement>(pElement->GetAttachedTo());
if (pAttachedTo && !pAttachedTo->IsStreamedIn())
{
// ...unless attached to low LOD version
CClientObject* pAttachedToObject = DynamicCast<CClientObject>(pAttachedTo);
CClientObject* pObject = DynamicCast<CClientObject>(pElement);
if (!pObject || !pAttachedToObject || pObject->IsLowLod() == pAttachedToObject->IsLowLod())
continue;
}

// Not room to stream in more elements?
if (bReachedLimit)
if (pVehicle && pVehicle->GetTowedByVehicle())
{
// Add to the list that might be streamed in during the final phase
if ((int)ClosestStreamedOutList.size() < iMaxIn) // (only add if there is a chance it will be used)
ClosestStreamedOutList.push_back(pElement);
// Streaming in of towed vehicles is done in CClientVehicle::StreamIn by the towing vehicle
continue;
}
else
}
if (IS_PLAYER(pElement))
{
CClientPlayer* pPlayer = DynamicCast<CClientPlayer>(pElement);
if (pPlayer->GetLastPuresyncType() == PURESYNC_TYPE_LIGHTSYNC)
{
// Stream in the new element. Don't do it instantly unless moved from far away.
pElement->InternalStreamIn(bMovedFar);
bReachedLimit = ReachedLimit();
// if the last packet was ls he isn't streaming in soon.
continue;
}
}
// If attached and attached-to is streamed out, don't consider for streaming in
CClientStreamElement* pAttachedTo = DynamicCast<CClientStreamElement>(pElement->GetAttachedTo());
if (pAttachedTo && !pAttachedTo->IsStreamedIn())
{
// ...unless attached to low LOD version
CClientObject* pAttachedToObject = DynamicCast<CClientObject>(pAttachedTo);
CClientObject* pObject = DynamicCast<CClientObject>(pElement);
if (!pObject || !pAttachedToObject || pObject->IsLowLod() == pAttachedToObject->IsLowLod())
continue;
}

if (!bReachedLimit)
{
iMaxIn--;
if (iMaxIn <= 0)
break;
}
// Not room to stream in more elements?
if (bReachedLimit)
{
// Add to the list that might be streamed in during the final phase
if ((int)ClosestStreamedOutList.size() < iMaxIn) // (only add if there is a chance it will be used)
ClosestStreamedOutList.push_back(pElement);
}
else
{
// Stream in the new element. Don't do it instantly unless moved from far away.
pElement->InternalStreamIn(bMovedFar);
bReachedLimit = ReachedLimit();

if (!bReachedLimit)
{
iMaxIn--;
if (iMaxIn <= 0)
break;
}
}
}
Expand Down Expand Up @@ -692,6 +701,10 @@ void CClientStreamer::OnElementEnterSector(CClientStreamElement* pElement, CClie
}
else
{
// Should we deactivate the element?
if (pPreviousSector && pPreviousSector->IsActivated())
m_ActiveElements.remove(pElement);

// Should we activate this sector?
if (pSector->IsExtra() && (m_pSector->IsMySurroundingSector(pSector) || m_pSector == pSector))
{
Expand All @@ -705,6 +718,12 @@ void CClientStreamer::OnElementEnterSector(CClientStreamElement* pElement, CClie
}
}
}
else if (pPreviousSector && pPreviousSector->IsActivated())
{
// The element was removed from sectors.
// Remove it from active elements too.
m_ActiveElements.remove(pElement);
}
pElement->SetStreamSector(pSector);
}

Expand All @@ -725,16 +744,23 @@ void CClientStreamer::OnElementForceStreamOut(CClientStreamElement* pElement)

void CClientStreamer::OnElementDimension(CClientStreamElement* pElement)
{
// Grab its new dimenson
unsigned short usDimension = pElement->GetDimension();
// Is it streamed in?
if (pElement->IsStreamedIn())
if (IsElementShouldVisibleInCurrentDimesnion(pElement))
{
if (!pElement->GetStreamSector())
{
AddElementInSectors(pElement);
m_outsideCurrentDimensionElements.remove(pElement);
}
}
else
{
// Has it moved to a different dimension to us?
if (usDimension != m_usDimension)
if (pElement->GetStreamSector())
{
// Stream it out
m_ToStreamOut.push_back(pElement);
m_outsideCurrentDimensionElements.push_back(pElement);
RemoveElementFromSectors(pElement);

if (pElement->IsStreamedIn())
m_ToStreamOut.push_back(pElement);
}
}
}
Loading
Loading