diff --git a/Client/mods/deathmatch/logic/CClientStreamSector.h b/Client/mods/deathmatch/logic/CClientStreamSector.h index 10bd3db2f3a..bb20cd59379 100644 --- a/Client/mods/deathmatch/logic/CClientStreamSector.h +++ b/Client/mods/deathmatch/logic/CClientStreamSector.h @@ -37,6 +37,7 @@ class CClientStreamSector void Remove(CClientStreamElement* pElement) { m_Elements.remove(pElement); } std::list::iterator Begin() { return m_Elements.begin(); } std::list::iterator End() { return m_Elements.end(); } + std::list& GetElements() { return m_Elements; } void AddElements(std::list* pList); void RemoveElements(std::list* pList); diff --git a/Client/mods/deathmatch/logic/CClientStreamSectorRow.h b/Client/mods/deathmatch/logic/CClientStreamSectorRow.h index 0fa26750fa4..b06fd96a770 100644 --- a/Client/mods/deathmatch/logic/CClientStreamSectorRow.h +++ b/Client/mods/deathmatch/logic/CClientStreamSectorRow.h @@ -31,6 +31,7 @@ class CClientStreamSectorRow void Add(CClientStreamSector* pSector); void Remove(CClientStreamSector* pSector); unsigned int CountSectors() { return m_Sectors.size(); } + std::list& GetList() noexcept { return m_Sectors; } bool DoesContain(CVector& vecPosition); bool DoesContain(float fY); diff --git a/Client/mods/deathmatch/logic/CClientStreamer.cpp b/Client/mods/deathmatch/logic/CClientStreamer.cpp index e0aff6d3527..13c9f919e53 100644 --- a/Client/mods/deathmatch/logic/CClientStreamer.cpp +++ b/Client/mods/deathmatch/logic/CClientStreamer.cpp @@ -9,6 +9,9 @@ *****************************************************************************/ #include "StdInc.h" +#include "CClientGame.h" + +extern CClientGame* g_pClientGame; using std::list; void* CClientStreamer::pAddingElement = NULL; @@ -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) @@ -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& 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::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++; + } } } @@ -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(); @@ -305,7 +303,7 @@ void CClientStreamer::OnUpdateStreamPosition(CClientStreamElement* pElement) } } -void CClientStreamer::AddElement(CClientStreamElement* pElement) +void CClientStreamer::AddElementInSectors(CClientStreamElement* pElement) { assert(pAddingElement == NULL); pAddingElement = pElement; @@ -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* pList) { // Run through our list setting distances to world center @@ -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(pElement); - if (pVehicle && pVehicle->GetOccupant() && IS_PLAYER(pVehicle->GetOccupant())) - { - CClientPlayer* pPlayer = DynamicCast(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(pElement); + if (pVehicle && pVehicle->GetOccupant() && IS_PLAYER(pVehicle->GetOccupant())) { - CClientPlayer* pPlayer = DynamicCast(pElement); + CClientPlayer* pPlayer = DynamicCast(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(pElement->GetAttachedTo()); - if (pAttachedTo && !pAttachedTo->IsStreamedIn()) - { - // ...unless attached to low LOD version - CClientObject* pAttachedToObject = DynamicCast(pAttachedTo); - CClientObject* pObject = DynamicCast(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(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(pElement->GetAttachedTo()); + if (pAttachedTo && !pAttachedTo->IsStreamedIn()) + { + // ...unless attached to low LOD version + CClientObject* pAttachedToObject = DynamicCast(pAttachedTo); + CClientObject* pObject = DynamicCast(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; } } } @@ -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)) { @@ -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); } @@ -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); } } } diff --git a/Client/mods/deathmatch/logic/CClientStreamer.h b/Client/mods/deathmatch/logic/CClientStreamer.h index da690293871..875ba2ca325 100644 --- a/Client/mods/deathmatch/logic/CClientStreamer.h +++ b/Client/mods/deathmatch/logic/CClientStreamer.h @@ -47,6 +47,14 @@ class CClientStreamer void AddElement(CClientStreamElement* pElement); void RemoveElement(CClientStreamElement* pElement); + void AddElementInSectors(CClientStreamElement* pElement); + void RemoveElementFromSectors(CClientStreamElement* pElement); + + bool IsElementShouldVisibleInCurrentDimesnion(CClientStreamElement* pElement) const noexcept + { + return pElement->GetDimension() == m_usDimension || pElement->IsVisibleInAllDimensions(); + } + void SetExpDistances(std::list* pList); void AddToSortedList(std::list* pList, CClientStreamElement* pElement); @@ -72,6 +80,7 @@ class CClientStreamer unsigned short m_usDimension; std::list m_ActiveElements; std::list m_ToStreamOut; + std::list m_outsideCurrentDimensionElements; static void* pAddingElement; };