Skip to content

Commit 682b02b

Browse files
authored
Fix bad streaming performance in some cases (#4013)
Designed to fix #813 and #3985 (needs to be confirmed in practice)
1 parent dcf3ee6 commit 682b02b

File tree

4 files changed

+159
-122
lines changed

4 files changed

+159
-122
lines changed

Client/mods/deathmatch/logic/CClientStreamSector.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class CClientStreamSector
3737
void Remove(CClientStreamElement* pElement) { m_Elements.remove(pElement); }
3838
std::list<CClientStreamElement*>::iterator Begin() { return m_Elements.begin(); }
3939
std::list<CClientStreamElement*>::iterator End() { return m_Elements.end(); }
40+
std::list<CClientStreamElement*>& GetElements() { return m_Elements; }
4041

4142
void AddElements(std::list<CClientStreamElement*>* pList);
4243
void RemoveElements(std::list<CClientStreamElement*>* pList);

Client/mods/deathmatch/logic/CClientStreamSectorRow.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class CClientStreamSectorRow
3131
void Add(CClientStreamSector* pSector);
3232
void Remove(CClientStreamSector* pSector);
3333
unsigned int CountSectors() { return m_Sectors.size(); }
34+
std::list<CClientStreamSector*>& GetList() noexcept { return m_Sectors; }
3435

3536
bool DoesContain(CVector& vecPosition);
3637
bool DoesContain(float fY);

Client/mods/deathmatch/logic/CClientStreamer.cpp

Lines changed: 148 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
*****************************************************************************/
1010

1111
#include "StdInc.h"
12+
#include "CClientGame.h"
13+
14+
extern CClientGame* g_pClientGame;
1215
using std::list;
1316

1417
void* CClientStreamer::pAddingElement = NULL;
@@ -107,51 +110,8 @@ void CClientStreamer::ConnectRow(CClientStreamSectorRow* pRow)
107110
pRow->m_pBottom->m_pTop = pRow;
108111
}
109112

110-
#include "..\deathmatch\logic\CClientGame.h"
111-
extern CClientGame* g_pClientGame;
112-
void CClientStreamer::DoPulse(CVector& vecPosition)
113+
void CClientStreamer::DoPulse(CVector& vecPosition)
113114
{
114-
/* Debug code
115-
CClientStreamSector * pSector;
116-
list < CClientStreamSector * > ::iterator iterSector;
117-
list < CClientStreamSectorRow * > ::iterator iterRow = m_WorldRows.begin ();
118-
for ( ; iterRow != m_WorldRows.end () ; iterRow++ )
119-
{
120-
iterSector = (*iterRow)->Begin ();
121-
for ( ; iterSector != (*iterRow)->End () ; iterSector++ )
122-
{
123-
pSector = *iterSector;
124-
if ( !pSector->m_pArea )
125-
{
126-
pSector->m_pArea = new CClientRadarArea ( g_pClientGame->GetManager (), INVALID_ELEMENT_ID );
127-
pSector->m_pArea->SetPosition ( pSector->m_vecBottomLeft );
128-
CVector2D vecSize ( pSector->m_vecTopRight.fX - pSector->m_vecBottomLeft.fX, pSector->m_vecTopRight.fY - pSector->m_vecBottomLeft.fY );
129-
pSector->m_pArea->SetSize ( vecSize );
130-
pSector->m_pArea->SetColor ( 255, 0, 0, 50 );
131-
}
132-
pSector->m_pArea->SetColor ( 255, 0, 0, 50 );
133-
}
134-
}
135-
iterRow = m_ExtraRows.begin ();
136-
for ( ; iterRow != m_ExtraRows.end () ; iterRow++ )
137-
{
138-
iterSector = (*iterRow)->Begin ();
139-
for ( ; iterSector != (*iterRow)->End () ; iterSector++ )
140-
{
141-
pSector = *iterSector;
142-
if ( !pSector->m_pArea )
143-
{
144-
pSector->m_pArea = new CClientRadarArea ( g_pClientGame->GetManager (), INVALID_ELEMENT_ID );
145-
pSector->m_pArea->SetPosition ( pSector->m_vecBottomLeft );
146-
CVector2D vecSize ( pSector->m_vecTopRight.fX - pSector->m_vecBottomLeft.fX, pSector->m_vecTopRight.fY - pSector->m_vecBottomLeft.fY );
147-
pSector->m_pArea->SetSize ( vecSize );
148-
pSector->m_pArea->SetColor ( 255, 0, 0, 50 );
149-
}
150-
pSector->m_pArea->SetColor ( 255, 0, 0, 50 );
151-
}
152-
}
153-
*/
154-
155115
bool bMovedFar = false;
156116
// Has our position changed?
157117
if (vecPosition != m_vecPosition)
@@ -183,27 +143,62 @@ void CClientStreamer::DoPulse(CVector& vecPosition)
183143
void CClientStreamer::SetDimension(unsigned short usDimension)
184144
{
185145
// Different dimension than before?
186-
if (usDimension != m_usDimension)
146+
if (usDimension == m_usDimension)
147+
return;
148+
149+
// Set the new dimension
150+
m_usDimension = usDimension;
151+
152+
const CClientStreamElement* lastOutsideElement = m_outsideCurrentDimensionElements.empty() ? nullptr : m_outsideCurrentDimensionElements.back();
153+
154+
auto filterElementInRows = [this](list<CClientStreamSectorRow*>& list)
187155
{
188-
// Set the new dimension
189-
m_usDimension = usDimension;
190-
191-
// That means all of the currently streamed in elements will have to
192-
// go. Unstream all elements that are streamed in.
193-
CClientStreamElement* pElement = NULL;
194-
list<CClientStreamElement*>::iterator iter = m_ActiveElements.begin();
195-
for (; iter != m_ActiveElements.end(); iter++)
156+
for (CClientStreamSectorRow* sectorRow : list)
196157
{
197-
pElement = *iter;
198-
if (pElement->IsStreamedIn())
158+
for (CClientStreamSector* sector : sectorRow->GetList())
199159
{
200-
if (!pElement->IsVisibleInAllDimensions())
160+
auto& elements = sector->GetElements();
161+
auto iter = elements.begin();
162+
while (iter != sector->End())
201163
{
202-
// Unstream it
203-
m_ToStreamOut.push_back(pElement);
164+
CClientStreamElement* element = *iter;
165+
166+
if (IsElementShouldVisibleInCurrentDimesnion(element))
167+
iter++;
168+
else
169+
{
170+
iter = elements.erase(iter);
171+
m_outsideCurrentDimensionElements.push_back(element);
172+
element->SetStreamSector(nullptr);
173+
174+
if (element->IsStreamedIn())
175+
m_ToStreamOut.push_back(element);
176+
}
204177
}
205178
}
206179
}
180+
};
181+
182+
filterElementInRows(m_WorldRows);
183+
filterElementInRows(m_ExtraRows);
184+
185+
if (!lastOutsideElement)
186+
return;
187+
188+
auto iter = m_outsideCurrentDimensionElements.begin();
189+
190+
while (*iter != lastOutsideElement)
191+
{
192+
CClientStreamElement* element = *iter;
193+
if (element->GetDimension() == usDimension)
194+
{
195+
iter = m_outsideCurrentDimensionElements.erase(iter);
196+
AddElementInSectors(element);
197+
}
198+
else
199+
{
200+
iter++;
201+
}
207202
}
208203
}
209204

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

282277
void CClientStreamer::OnUpdateStreamPosition(CClientStreamElement* pElement)
283278
{
279+
if (!pElement->GetStreamSector())
280+
return;
281+
284282
CVector vecPosition = pElement->GetStreamPosition();
285283
CClientStreamSectorRow* pRow = pElement->GetStreamRow();
286284
CClientStreamSector* pSector = pElement->GetStreamSector();
@@ -305,7 +303,7 @@ void CClientStreamer::OnUpdateStreamPosition(CClientStreamElement* pElement)
305303
}
306304
}
307305

308-
void CClientStreamer::AddElement(CClientStreamElement* pElement)
306+
void CClientStreamer::AddElementInSectors(CClientStreamElement* pElement)
309307
{
310308
assert(pAddingElement == NULL);
311309
pAddingElement = pElement;
@@ -316,13 +314,28 @@ void CClientStreamer::AddElement(CClientStreamElement* pElement)
316314
pAddingElement = NULL;
317315
}
318316

319-
void CClientStreamer::RemoveElement(CClientStreamElement* pElement)
317+
void CClientStreamer::RemoveElementFromSectors(CClientStreamElement* pElement)
320318
{
321-
OnElementEnterSector(pElement, NULL);
322-
m_ActiveElements.remove(pElement);
319+
OnElementEnterSector(pElement, nullptr);
323320
m_ToStreamOut.remove(pElement);
324321
}
325322

323+
void CClientStreamer::AddElement(CClientStreamElement* pElement)
324+
{
325+
if (IsElementShouldVisibleInCurrentDimesnion(pElement))
326+
AddElementInSectors(pElement);
327+
else
328+
m_outsideCurrentDimensionElements.push_back(pElement);
329+
}
330+
331+
void CClientStreamer::RemoveElement(CClientStreamElement* pElement)
332+
{
333+
if (pElement->GetStreamSector())
334+
RemoveElementFromSectors(pElement);
335+
else
336+
m_outsideCurrentDimensionElements.remove(pElement);
337+
}
338+
326339
void CClientStreamer::SetExpDistances(list<CClientStreamElement*>* pList)
327340
{
328341
// Run through our list setting distances to world center
@@ -489,71 +502,67 @@ void CClientStreamer::Restream(bool bMovedFar)
489502
}
490503
else
491504
{
492-
// Same dimension as us?
493-
if (pElement->GetDimension() == m_usDimension || pElement->IsVisibleInAllDimensions())
494-
{
495-
// Too far away? Stop here.
496-
if (fElementDistanceExp > m_fMaxDistanceExp)
497-
continue;
505+
// Too far away? Stop here.
506+
if (fElementDistanceExp > m_fMaxDistanceExp)
507+
continue;
498508

499-
if (IS_VEHICLE(pElement))
500-
{
501-
CClientVehicle* pVehicle = DynamicCast<CClientVehicle>(pElement);
502-
if (pVehicle && pVehicle->GetOccupant() && IS_PLAYER(pVehicle->GetOccupant()))
503-
{
504-
CClientPlayer* pPlayer = DynamicCast<CClientPlayer>(pVehicle->GetOccupant());
505-
if (pPlayer->GetLastPuresyncType() == PURESYNC_TYPE_LIGHTSYNC)
506-
{
507-
// if the last packet was ls he isn't streaming in soon.
508-
continue;
509-
}
510-
}
511-
512-
if (pVehicle && pVehicle->GetTowedByVehicle())
513-
{
514-
// Streaming in of towed vehicles is done in CClientVehicle::StreamIn by the towing vehicle
515-
continue;
516-
}
517-
}
518-
if (IS_PLAYER(pElement))
509+
if (IS_VEHICLE(pElement))
510+
{
511+
CClientVehicle* pVehicle = DynamicCast<CClientVehicle>(pElement);
512+
if (pVehicle && pVehicle->GetOccupant() && IS_PLAYER(pVehicle->GetOccupant()))
519513
{
520-
CClientPlayer* pPlayer = DynamicCast<CClientPlayer>(pElement);
514+
CClientPlayer* pPlayer = DynamicCast<CClientPlayer>(pVehicle->GetOccupant());
521515
if (pPlayer->GetLastPuresyncType() == PURESYNC_TYPE_LIGHTSYNC)
522516
{
523517
// if the last packet was ls he isn't streaming in soon.
524518
continue;
525519
}
526520
}
527-
// If attached and attached-to is streamed out, don't consider for streaming in
528-
CClientStreamElement* pAttachedTo = DynamicCast<CClientStreamElement>(pElement->GetAttachedTo());
529-
if (pAttachedTo && !pAttachedTo->IsStreamedIn())
530-
{
531-
// ...unless attached to low LOD version
532-
CClientObject* pAttachedToObject = DynamicCast<CClientObject>(pAttachedTo);
533-
CClientObject* pObject = DynamicCast<CClientObject>(pElement);
534-
if (!pObject || !pAttachedToObject || pObject->IsLowLod() == pAttachedToObject->IsLowLod())
535-
continue;
536-
}
537521

538-
// Not room to stream in more elements?
539-
if (bReachedLimit)
522+
if (pVehicle && pVehicle->GetTowedByVehicle())
540523
{
541-
// Add to the list that might be streamed in during the final phase
542-
if ((int)ClosestStreamedOutList.size() < iMaxIn) // (only add if there is a chance it will be used)
543-
ClosestStreamedOutList.push_back(pElement);
524+
// Streaming in of towed vehicles is done in CClientVehicle::StreamIn by the towing vehicle
525+
continue;
544526
}
545-
else
527+
}
528+
if (IS_PLAYER(pElement))
529+
{
530+
CClientPlayer* pPlayer = DynamicCast<CClientPlayer>(pElement);
531+
if (pPlayer->GetLastPuresyncType() == PURESYNC_TYPE_LIGHTSYNC)
546532
{
547-
// Stream in the new element. Don't do it instantly unless moved from far away.
548-
pElement->InternalStreamIn(bMovedFar);
549-
bReachedLimit = ReachedLimit();
533+
// if the last packet was ls he isn't streaming in soon.
534+
continue;
535+
}
536+
}
537+
// If attached and attached-to is streamed out, don't consider for streaming in
538+
CClientStreamElement* pAttachedTo = DynamicCast<CClientStreamElement>(pElement->GetAttachedTo());
539+
if (pAttachedTo && !pAttachedTo->IsStreamedIn())
540+
{
541+
// ...unless attached to low LOD version
542+
CClientObject* pAttachedToObject = DynamicCast<CClientObject>(pAttachedTo);
543+
CClientObject* pObject = DynamicCast<CClientObject>(pElement);
544+
if (!pObject || !pAttachedToObject || pObject->IsLowLod() == pAttachedToObject->IsLowLod())
545+
continue;
546+
}
550547

551-
if (!bReachedLimit)
552-
{
553-
iMaxIn--;
554-
if (iMaxIn <= 0)
555-
break;
556-
}
548+
// Not room to stream in more elements?
549+
if (bReachedLimit)
550+
{
551+
// Add to the list that might be streamed in during the final phase
552+
if ((int)ClosestStreamedOutList.size() < iMaxIn) // (only add if there is a chance it will be used)
553+
ClosestStreamedOutList.push_back(pElement);
554+
}
555+
else
556+
{
557+
// Stream in the new element. Don't do it instantly unless moved from far away.
558+
pElement->InternalStreamIn(bMovedFar);
559+
bReachedLimit = ReachedLimit();
560+
561+
if (!bReachedLimit)
562+
{
563+
iMaxIn--;
564+
if (iMaxIn <= 0)
565+
break;
557566
}
558567
}
559568
}
@@ -692,6 +701,10 @@ void CClientStreamer::OnElementEnterSector(CClientStreamElement* pElement, CClie
692701
}
693702
else
694703
{
704+
// Should we deactivate the element?
705+
if (pPreviousSector && pPreviousSector->IsActivated())
706+
m_ActiveElements.remove(pElement);
707+
695708
// Should we activate this sector?
696709
if (pSector->IsExtra() && (m_pSector->IsMySurroundingSector(pSector) || m_pSector == pSector))
697710
{
@@ -705,6 +718,12 @@ void CClientStreamer::OnElementEnterSector(CClientStreamElement* pElement, CClie
705718
}
706719
}
707720
}
721+
else if (pPreviousSector && pPreviousSector->IsActivated())
722+
{
723+
// The element was removed from sectors.
724+
// Remove it from active elements too.
725+
m_ActiveElements.remove(pElement);
726+
}
708727
pElement->SetStreamSector(pSector);
709728
}
710729

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

726745
void CClientStreamer::OnElementDimension(CClientStreamElement* pElement)
727746
{
728-
// Grab its new dimenson
729-
unsigned short usDimension = pElement->GetDimension();
730-
// Is it streamed in?
731-
if (pElement->IsStreamedIn())
747+
if (IsElementShouldVisibleInCurrentDimesnion(pElement))
748+
{
749+
if (!pElement->GetStreamSector())
750+
{
751+
AddElementInSectors(pElement);
752+
m_outsideCurrentDimensionElements.remove(pElement);
753+
}
754+
}
755+
else
732756
{
733-
// Has it moved to a different dimension to us?
734-
if (usDimension != m_usDimension)
757+
if (pElement->GetStreamSector())
735758
{
736-
// Stream it out
737-
m_ToStreamOut.push_back(pElement);
759+
m_outsideCurrentDimensionElements.push_back(pElement);
760+
RemoveElementFromSectors(pElement);
761+
762+
if (pElement->IsStreamedIn())
763+
m_ToStreamOut.push_back(pElement);
738764
}
739765
}
740766
}

0 commit comments

Comments
 (0)