From 785a68d86b735cd34b7ae08b80a7ffba32e3c05a Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Fri, 4 Mar 2022 21:59:24 -0500
Subject: [PATCH] More var region support..

---
 indra/newview/llglsandbox.cpp       |  2 +-
 indra/newview/llviewerobject.cpp    |  2 +-
 indra/newview/llworldmap.cpp        | 55 ++++++++++++++++++++---------
 indra/newview/llworldmap.h          | 17 ++++++---
 indra/newview/llworldmapmessage.cpp | 20 +++++++++--
 indra/newview/llworldmapview.cpp    | 13 ++++---
 6 files changed, 80 insertions(+), 29 deletions(-)

diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index a80088b9179..c0554cbe254 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -496,7 +496,7 @@ void LLViewerParcelMgr::renderOneSegment(F32 x1, F32 y1, F32 x2, F32 y2, F32 hei
 {
 	// HACK: At edge of last region of world, we need to make sure the region
 	// resolves correctly so we can get a height value.
-	const F32 BORDER = REGION_WIDTH_METERS - 0.1f;
+	const F32 BORDER = regionp->getWidth() - 0.1f;
 
 	F32 clamped_x1 = x1;
 	F32 clamped_y1 = y1;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index f5ee448a85a..b8633f09390 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -1209,7 +1209,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 	U16 valswizzle[4];
 #endif
 	U16	*val;
-	const F32 size = worldInst.getRegionWidthInMeters();	
+	const F32 size = mRegionp->getWidth();	
 	const F32 MAX_HEIGHT = worldInst.getRegionMaxHeight();
 	const F32 MIN_HEIGHT = worldInst.getRegionMinHeight();
 	S32 length;
diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp
index c6cd5d43fb9..ae82550f4bc 100644
--- a/indra/newview/llworldmap.cpp
+++ b/indra/newview/llworldmap.cpp
@@ -35,9 +35,11 @@
 #include "llviewertexturelist.h"
 #include "lltrans.h"
 #include "llgltexture.h"
+#include "llappviewer.h"
+#include "lltexturecache.h"
 
 // Timers to temporise database requests
-const F32 AGENTS_UPDATE_TIMER = 60.0;			// Seconds between 2 agent requests for a region
+const F32 AGENTS_UPDATE_TIMER = 30.f;			// Seconds between 2 agent requests for a region
 const F32 REQUEST_ITEMS_TIMER = 10.f * 60.f;	// Seconds before we consider re-requesting item data for the grid
 
 //---------------------------------------------------------------------------
@@ -63,6 +65,8 @@ LLItemInfo::LLItemInfo(F32 global_x, F32 global_y,
 
 LLSimInfo::LLSimInfo(U64 handle)
 :	mHandle(handle),
+	mSizeX(REGION_WIDTH_UNITS),
+	mSizeY(REGION_WIDTH_UNITS),
 	mName(),
 	mAgentsUpdateTime(0),
 	mAccess(0x0),
@@ -74,12 +78,21 @@ LLSimInfo::LLSimInfo(U64 handle)
 
 void LLSimInfo::setLandForSaleImage (LLUUID image_id) 
 {
+	if (mMapImageID.isNull() && image_id.notNull())
+	{
+		mOverlayImage = LLViewerTextureManager::findFetchedTexture(image_id, TEX_LIST_STANDARD);
+		if(mOverlayImage.notNull())
+		{
+			LLAppViewer::getTextureCache()->removeFromCache(image_id);
+		}
+	}
 	mMapImageID = image_id;
 
 	// Fetch the image
 	if (mMapImageID.notNull())
 	{
 		mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE);
+		mOverlayImage->forceImmediateUpdate();
 		mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP);
 	}
 	else
@@ -230,7 +243,6 @@ LLWorldMap::LLWorldMap() :
 	mFirstRequest(true)
 {
 	//LL_INFOS("WorldMap") << "Creating the World Map -> LLWorldMap::LLWorldMap()" << LL_ENDL;
-	mMapBlockLoaded = new bool[MAP_BLOCK_RES*MAP_BLOCK_RES];
 	clearSimFlags();
 }
 
@@ -239,7 +251,6 @@ LLWorldMap::~LLWorldMap()
 {
 	//LL_INFOS("WorldMap") << "Destroying the World Map -> LLWorldMap::~LLWorldMap()" << LL_ENDL;
 	reset();
-	delete[] mMapBlockLoaded;
 }
 
 
@@ -298,10 +309,7 @@ void LLWorldMap::clearImageRefs()
 // Doesn't clear the already-loaded sim infos, just re-requests them
 void LLWorldMap::clearSimFlags()
 {
-	for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx)
-	{
-		mMapBlockLoaded[idx] = false;
-	}
+	mMapBlockLoaded.fill(false);
 }
 
 LLSimInfo* LLWorldMap::createSimInfoFromHandle(const U64 handle)
@@ -330,29 +338,41 @@ LLSimInfo* LLWorldMap::simInfoFromHandle(const U64 handle)
 	{
 		return it->second;
 	}
-	return NULL;
+	U32 x = 0, y = 0;
+	from_region_handle(handle, &x, &y);
+
+	for (const auto& sim_info_pair : mSimInfoMap)
+	{
+		U32 checkRegionX, checkRegionY;
+		from_region_handle(sim_info_pair.first, &checkRegionX, &checkRegionY);
+
+		LLSimInfo* info = sim_info_pair.second;
+		if (x >= checkRegionX && x < (checkRegionX + info->getSizeX()) &&
+			y >= checkRegionY && y < (checkRegionY + info->getSizeY()))
+		{
+			return info;
+		}
+	}
+	return nullptr;
 }
 
 
 LLSimInfo* LLWorldMap::simInfoFromName(const std::string& sim_name)
 {
-	LLSimInfo* sim_info = NULL;
+	LLSimInfo* sim_info = nullptr;
 	if (!sim_name.empty())
 	{
 		// Iterate through the entire sim info map and compare the name
-		sim_info_map_t::iterator it;
-		for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
+		for (const auto& sim_info_pair : mSimInfoMap)
 		{
-			sim_info = it->second;
-			if (sim_info && sim_info->isName(sim_name) )
+			auto temp_sim_info = sim_info_pair.second;
+			if (temp_sim_info && temp_sim_info->isName(sim_name) )
 			{
+				sim_info = temp_sim_info;
 				// break out of loop if success
 				break;
 			}
 		}
-		// If we got to the end, we haven't found the sim. Reset the ouput value to NULL.
-		if (it == mSimInfoMap.end())
-			sim_info = NULL;
 	}
 	return sim_info;
 }
@@ -392,7 +412,7 @@ void LLWorldMap::reloadItems(bool force)
 // static public
 // Insert a region in the region map
 // returns true if region inserted, false otherwise
-bool LLWorldMap::insertRegion(U32 x_world, U32 y_world, std::string& name, LLUUID& image_id, U32 accesscode, U32 region_flags)
+bool LLWorldMap::insertRegion(U32 x_world, U32 y_world, U16 x_size, U16 y_size, std::string& name, LLUUID& image_id, U32 accesscode, U32 region_flags)
 {
 	// This region doesn't exist
 	if (accesscode == 255)
@@ -421,6 +441,7 @@ bool LLWorldMap::insertRegion(U32 x_world, U32 y_world, std::string& name, LLUUI
 		siminfo->setRegionFlags(region_flags);
 	//	siminfo->setWaterHeight((F32) water_height);
 		siminfo->setLandForSaleImage(image_id);
+		siminfo->setSize(x_size, y_size);
 
 		// Handle the location tracking (for teleport, UI feedback and info display)
 		if (isTrackingInRectangle( x_world, y_world, x_world + REGION_WIDTH_UNITS, y_world + REGION_WIDTH_UNITS))
diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h
index 9e4e4ac554a..4601de463e8 100644
--- a/indra/newview/llworldmap.h
+++ b/indra/newview/llworldmap.h
@@ -38,6 +38,8 @@
 #include "llviewertexture.h"
 #include "llgltexture.h"
 
+#include <array>
+
 // map item types
 const U32 MAP_ITEM_TELEHUB = 0x01;
 const U32 MAP_ITEM_PG_EVENT = 0x02;
@@ -114,6 +116,7 @@ class LLSimInfo
 
 	// Setters
 	void setName(std::string& name) { mName = name; }
+	void setSize(U16 sizeX, U16 sizeY) { mSizeX = sizeX; mSizeY = sizeY; }
 	void setAccess (U32 accesscode) { mAccess = accesscode; }
 	void setRegionFlags (U32 region_flags) { mRegionFlags = region_flags; }
 	void setLandForSaleImage (LLUUID image_id);
@@ -129,6 +132,10 @@ class LLSimInfo
 	const S32 getAgentCount() const;				// Compute the total agents count
 	LLPointer<LLViewerFetchedTexture> getLandForSaleImage();	// Get the overlay image, fetch it if necessary
 
+	const U64& getHandle() const { return mHandle; }
+	const U16 getSizeX() const { return mSizeX; }
+	const U16 getSizeY() const { return mSizeY; }
+
 	bool isName(const std::string& name) const;
 	bool isDown() { return (mAccess == SIM_ACCESS_DOWN); }
 	bool isPG() { return (mAccess <= SIM_ACCESS_PG); }
@@ -161,6 +168,8 @@ class LLSimInfo
 
 private:
 	U64 mHandle;				// This is a hash of the X and Y world coordinates of the SW corner of the sim
+	U16 mSizeX;
+	U16 mSizeY;
 	std::string mName;			// Region name
 
 	F64 mAgentsUpdateTime;		// Time stamp giving the last time the agents information was requested for that region
@@ -189,8 +198,8 @@ class LLSimInfo
 
 // We request region data on the world by "blocks" of (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) regions
 // This is to reduce the number of requests to the asset DB and get things in big "blocks"
-const S32 MAP_MAX_SIZE = 2048;
-const S32 MAP_BLOCK_SIZE = 4;
+const S32 MAP_MAX_SIZE = 16384;
+const S32 MAP_BLOCK_SIZE = 16;
 const S32 MAP_BLOCK_RES = (MAP_MAX_SIZE / MAP_BLOCK_SIZE);
 
 class LLWorldMap final : public LLSingleton<LLWorldMap>
@@ -213,7 +222,7 @@ class LLWorldMap final : public LLSingleton<LLWorldMap>
 
 	// Insert a region and items in the map global instance
 	// Note: x_world and y_world in world coordinates (meters)
-	bool insertRegion(U32 x_world, U32 y_world, std::string& name, LLUUID& uuid, U32 accesscode, U32 region_flags);
+	bool insertRegion(U32 x_world, U32 y_world, U16 x_size, U16 y_size, std::string& name, LLUUID& uuid, U32 accesscode, U32 region_flags);
 	bool insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID& uuid, U32 type, S32 extra, S32 extra2);
 
 	// Get info on sims (region) : note that those methods only search the range of loaded sims (the one that are being browsed)
@@ -267,7 +276,7 @@ class LLWorldMap final : public LLSingleton<LLWorldMap>
 	// This boolean table avoids "blocks" to be requested multiple times. 
 	// Issue: Not sure this scheme is foolproof though as I've seen
 	// cases where a block is never retrieved and, because of this boolean being set, never re-requested
-	bool *			mMapBlockLoaded;		// Telling us if the block of regions has been requested or not
+	std::array<bool, MAP_BLOCK_RES*MAP_BLOCK_RES>	mMapBlockLoaded;		// Telling us if the block of regions has been requested or not
 
 	// Track location data : used while there's nothing tracked yet by LLTracker
 	bool			mIsTrackingLocation;	// True when we're tracking a point
diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp
index cd2ac731fe5..9e92011815f 100644
--- a/indra/newview/llworldmapmessage.cpp
+++ b/indra/newview/llworldmapmessage.cpp
@@ -172,6 +172,8 @@ void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**)
 	{
 		U16 x_regions;
 		U16 y_regions;
+		U16 x_size = 256;
+		U16 y_size = 256;
 		std::string name;
 		U8 accesscode;
 		U32 region_flags;
@@ -186,15 +188,29 @@ void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**)
 //		msg->getU8Fast(_PREHASH_Data, _PREHASH_WaterHeight, water_height, block);
 //		msg->getU8Fast(_PREHASH_Data, _PREHASH_Agents, agents, block);
 		msg->getUUIDFast(_PREHASH_Data, _PREHASH_MapImageID, image_id, block);
+		if(msg->getNumberOfBlocksFast(_PREHASH_Size) > 0)
+		{
+			msg->getU16Fast(_PREHASH_Size, _PREHASH_SizeX, x_size, block);
+			msg->getU16Fast(_PREHASH_Size, _PREHASH_SizeY, y_size, block);
+		}
+		if(x_size == 0 || (x_size % 16) != 0|| (y_size % 16) != 0)
+		{
+			x_size = 256;
+			y_size = 256;
+		}
 
 		U32 x_world = (U32)(x_regions) * REGION_WIDTH_UNITS;
 		U32 y_world = (U32)(y_regions) * REGION_WIDTH_UNITS;
 
 		// name shouldn't be empty, see EXT-4568
-		llassert(!name.empty());
+		if (name.empty() && accesscode != 255)
+		{
+			LL_WARNS("WorldMap") << "MapBlockReply returned an empty region name; not inserting in the world map" << LL_ENDL;
+			continue;
+		}
 
 		// Insert that region in the world map, if failure, flag it as a "null_sim"
-		if (!(world_map.insertRegion(x_world, y_world, name, image_id, (U32)accesscode, region_flags)))
+		if (!(world_map.insertRegion(x_world, y_world, x_size, y_size, name, image_id, (U32)accesscode, region_flags)))
 		{
 			found_null_sim = true;
 		}
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 3e1d1bf0174..679b28eb0e7 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -50,6 +50,7 @@
 #include "lltextureview.h"
 #include "lltracker.h"
 #include "llviewercamera.h"
+#include "llviewernetwork.h"
 #include "llviewertexture.h"
 #include "llviewertexturelist.h"
 #include "llviewerregion.h"
@@ -363,8 +364,8 @@ void LLWorldMapView::draw()
 		// When the view isn't panned, 0,0 = center of rectangle
 		F32 bottom =    sPanY + half_height + relative_y;
 		F32 left =      sPanX + half_width + relative_x;
-		F32 top =       bottom + sMapScale ;
-		F32 right =     left + sMapScale ;
+		F32 top =		bottom+ (sMapScale * (info->getSizeY() / REGION_WIDTH_METERS));
+		F32 right =		left  + (sMapScale * (info->getSizeX() / REGION_WIDTH_METERS));
 
 		// Discard if region is outside the screen rectangle (not visible on screen)
 		if ((top < 0.f)   || (bottom > height) ||
@@ -425,8 +426,12 @@ void LLWorldMapView::draw()
 			if (overlayimage)
 			{
 				// Inform the fetch mechanism of the size we need
-				S32 draw_size = ll_round(sMapScale);
-				overlayimage->setKnownDrawSize(ll_round(draw_size * LLUI::getScaleFactor().mV[VX]), ll_round(draw_size * LLUI::getScaleFactor().mV[VY]));
+				S32 x_draw_size = ll_round(sMapScale);
+				S32 y_draw_size = ll_round(sMapScale);
+				x_draw_size *= (info->getSizeX() / REGION_WIDTH_METERS);
+				y_draw_size *= (info->getSizeY() / REGION_WIDTH_METERS);
+
+				overlayimage->setKnownDrawSize(ll_round(x_draw_size * LLUI::getScaleFactor().mV[VX]), ll_round(y_draw_size * LLUI::getScaleFactor().mV[VY]));
 				// Draw something whenever we have enough info
 				if (overlayimage->hasGLTexture())
 				{
-- 
GitLab