From 986279539fbb9ec0a98393edd757dafd7bba7abd Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Sat, 5 Mar 2022 00:39:36 -0500
Subject: [PATCH] A bunch of small fixes and changes to not instantly crash in
 opensim..

---
 indra/llmessage/llregionhandle.h      | 21 ++++++++
 indra/llrender/llimagegl.cpp          |  6 +++
 indra/newview/llagent.cpp             | 70 ++++++++++++++++++---------
 indra/newview/llestateinfomodel.cpp   |  1 +
 indra/newview/llpatchvertexarray.cpp  | 52 +++++++++-----------
 indra/newview/llviewermessage.cpp     |  4 --
 indra/newview/llviewerobject.cpp      |  4 +-
 indra/newview/llvoavatar.cpp          |  1 -
 indra/newview/llxmlrpctransaction.cpp |  9 ++++
 9 files changed, 109 insertions(+), 59 deletions(-)

diff --git a/indra/llmessage/llregionhandle.h b/indra/llmessage/llregionhandle.h
index 085757dcbc8..92c39dfdce7 100644
--- a/indra/llmessage/llregionhandle.h
+++ b/indra/llmessage/llregionhandle.h
@@ -39,6 +39,27 @@ inline U64 to_region_handle(const U32 x_origin, const U32 y_origin)
 	return region_handle;
 }
 
+inline U64 to_region_handle(const LLVector3d& pos_global, const LLVector3d& agent_region_origin, const F32 width)
+{
+	U32 global_x { static_cast<U32>( pos_global.mdV[VX] ) };
+	U32 global_y { static_cast<U32>( pos_global.mdV[VY] ) };
+
+	U32 agent_region_origin_x { static_cast<U32>( agent_region_origin.mdV[VX] ) };
+	U32 agent_region_origin_y { static_cast<U32>( agent_region_origin.mdV[VY] ) };
+
+	if(	agent_region_origin_x <  global_x && ( agent_region_origin_x + width ) > global_x &&
+		agent_region_origin_y <  global_y && ( agent_region_origin_y + width ) > global_y )
+	{
+		// target is local to current region we can make a more informed guess
+		return to_region_handle( agent_region_origin_x, agent_region_origin_y );
+	}
+	// fallback to legacy 256m tile-based guess and let the region server / map work it out.
+	global_x -= global_x % 256;
+	global_y -= global_y % 256;
+
+	return to_region_handle( global_x, global_y );
+}
+
 inline U64 to_region_handle(const LLVector3d& pos_global)
 {
 	U32 global_x = (U32)pos_global.mdV[VX];
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 92a82e71045..38482edd225 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -537,12 +537,14 @@ bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve
 {
 	if (width != mWidth || height != mHeight || ncomponents != mComponents)
 	{
+#ifdef NO_STUPID
 		// Check if dimensions are a power of two!
 		if (!checkSize(width,height))
 		{
 			LL_WARNS() << llformat("Texture has non power of two dimension: %dx%d",width,height) << LL_ENDL;
 			return false;
 		}
+#endif
 		
 		if (mTexName)
 		{
@@ -1419,11 +1421,15 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
 	S32 h = raw_h << discard_level;
 
 	// setSize may call destroyGLTexture if the size does not match
+#ifdef NO_STUPID
 	if (!setSize(w, h, imageraw->getComponents(), discard_level))
 	{
 		LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL;
 		return FALSE;
 	}
+#else
+	setSize(w, h, imageraw->getComponents(), discard_level);	
+#endif
 
 	if (mHasExplicitFormat && 
 		((mFormatPrimary == GL_RGBA && mComponents < 4) ||
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 6870dd0605a..f2fa426282a 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -4463,6 +4463,11 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global)
 // [RLVa:KB] - Checked: RLVa-2.0.0
 	if ( (RlvActions::isRlvEnabled()) && (!RlvUtil::isForceTp()) )
 	{
+		if (LLStartUp::getStartupState() < STATE_STARTED)
+		{
+			return;
+		}
+
 		if ( (RlvActions::isLocalTp(pos_global)) ? !RlvActions::canTeleportToLocal(pos_global) : !RlvActions::canTeleportToLocation() )
 		{
 			RlvUtil::notifyBlocked(RlvStringKeys::Blocked::Teleport);
@@ -4489,19 +4494,42 @@ void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global)
 		return;
 	}
 
-	U64 handle = to_region_handle(pos_global);
-	LLSimInfo* info = LLWorldMap::getInstanceFast()->simInfoFromHandle(handle);
-	if(regionp && info)
+	auto region_origin { regionp->getOriginGlobal() };
+	LLVector3 pos_local{};
+	U64 handle { to_region_handle(pos_global, region_origin, regionp->getWidth()) };
+	bool is_local { regionp->getHandle() == handle };
+	if(is_local)
 	{
-		LLVector3d region_origin = info->getGlobalOrigin();
-		LLVector3 pos_local(
+		pos_local.set(
 			(F32)(pos_global.mdV[VX] - region_origin.mdV[VX]),
 			(F32)(pos_global.mdV[VY] - region_origin.mdV[VY]),
 			(F32)(pos_global.mdV[VZ]));
-		teleportRequest(handle, pos_local);
+		LL_INFOS("Teleport") << "Local in-region TP:"
+							 << " pos_global " << pos_global
+							 << " region " << region_origin
+							 << " local " << pos_local
+							 << " region_handle " << handle
+							 << LL_ENDL;
+	}
+	else
+	{
+		// determine non-local region location as best we can using global coords
+		// In SL we have uniform region size. This is normal.
+		// In opensim the handle will resolve to a 256m quantised world tile which the server maps back to a region
+		// it "should" also compensate for the local coords. Handle has been "correctly" determined already so we use global % 256
+		static const F32 width = REGION_WIDTH_METERS;// Note: reverted back to previous hardcode 256 for non-local. Whilst this appears incorrect server side logic expects %256 and will overshoot otherwise.
+		pos_local.set( fmod((F32)pos_global.mdV[VX], width),
+					   fmod((F32)pos_global.mdV[VY], width),
+					   (F32)pos_global.mdV[VZ] );
+		LL_INFOS("Teleport") << "Non-local TP:"
+							 << " pos_global " << pos_global
+							 << " region " << region_origin
+							 << " local " << pos_local
+							 << " region_handle " << handle
+							 << LL_ENDL;
 	}
-	else if(regionp && 
-		teleportCore(regionp->getHandle() == to_region_handle_global((F32)pos_global.mdV[VX], (F32)pos_global.mdV[VY])))
+
+	if(teleportCore(is_local)) // Rather a pointless if as teleportCore currently always returns true
 	{
 		// send the message
 		LLMessageSystem* msg = gMessageSystem;
@@ -4511,26 +4539,20 @@ void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global)
 		msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
 
 		msg->nextBlockFast(_PREHASH_Info);
-		F32 width = regionp->getWidth();
-		LLVector3 pos(fmod((F32)pos_global.mdV[VX], width),
-					  fmod((F32)pos_global.mdV[VY], width),
-					  (F32)pos_global.mdV[VZ]);
-		F32 region_x = (F32)(pos_global.mdV[VX]);
-		F32 region_y = (F32)(pos_global.mdV[VY]);
-		U64 region_handle = to_region_handle_global(region_x, region_y);
-		msg->addU64Fast(_PREHASH_RegionHandle, region_handle);
-		msg->addVector3Fast(_PREHASH_Position, pos);
-		pos.mV[VX] += 1;
-		msg->addVector3Fast(_PREHASH_LookAt, pos);
+		msg->addU64Fast(_PREHASH_RegionHandle, handle);
+		msg->addVector3Fast(_PREHASH_Position, pos_local);
+		pos_local.mV[VX] += 1;
+		msg->addVector3Fast(_PREHASH_LookAt, pos_local);
 
-		LL_WARNS("Teleport") << "Sending deprecated(?) TeleportLocationRequest."
+		sendReliableMessage();
+		LL_INFOS("Teleport") << "Sending deprecated TeleportLocationRequest."
 							 << " pos_global " << pos_global
-							 << " region_x " << region_x
-							 << " region_y " << region_y
-							 << " region_handle " << region_handle
+							 << " region coord (" << (pos_global.mdV[VX] - pos_local.mV[VX])
+							 << "," << (pos_global.mdV[VY] - pos_local.mV[VY])
+							 << " pos_local " << pos_local
+							 << ") region_handle " << handle
 							 << LL_ENDL; 
 
-		sendReliableMessage();
 	}
 }
 
diff --git a/indra/newview/llestateinfomodel.cpp b/indra/newview/llestateinfomodel.cpp
index 227998f61d2..cfaed4bd139 100644
--- a/indra/newview/llestateinfomodel.cpp
+++ b/indra/newview/llestateinfomodel.cpp
@@ -151,6 +151,7 @@ void LLEstateInfoModel::commitEstateInfoCapsCoro(std::string url)
     body["allow_voice_chat"] = getAllowVoiceChat();
     body["override_public_access"] = getAllowAccessOverride();
 
+    body["override_environment"] = getAllowEnvironmentOverride();
     body["invoice"] = LLFloaterRegionInfo::getLastInvoice();
 
     LL_DEBUGS("WindlightSync") << "Sending estate caps: "
diff --git a/indra/newview/llpatchvertexarray.cpp b/indra/newview/llpatchvertexarray.cpp
index 6e3e3754884..4b79458c07d 100644
--- a/indra/newview/llpatchvertexarray.cpp
+++ b/indra/newview/llpatchvertexarray.cpp
@@ -76,43 +76,37 @@ void LLPatchVertexArray::create(U32 surface_width, U32 patch_width, F32 meters_p
 		surface_order += 1;
 	}
 
-	if (power_of_two == (surface_width-1))
+	if (power_of_two != (surface_width-1))
 	{
-		mSurfaceWidth = surface_width;
+		surface_width = power_of_two + 1;
+	}
+
+	mSurfaceWidth = surface_width;
 
-		// Make sure patch_width is a factor of (surface_width - 1)
-		U32 ratio = (surface_width - 1) / patch_width;
-		F32 fratio = ((float)(surface_width - 1)) / ((float)(patch_width));
-		if ( fratio == (float)(ratio))
+	// Make sure patch_width is a factor of (surface_width - 1)
+	U32 ratio = (surface_width - 1) / patch_width;
+	F32 fratio = ((float)(surface_width - 1)) / ((float)(patch_width));
+	if ( fratio == (float)(ratio))
+	{
+		// Make sure patch_width is a power of two
+		power_of_two = 1;
+		U32 patch_order = 0;
+		while (power_of_two < patch_width)
 		{
-			// Make sure patch_width is a power of two
-			power_of_two = 1;
-			U32 patch_order = 0;
-			while (power_of_two < patch_width)
-			{
-				power_of_two *= 2;
-				patch_order += 1;
-			}
-			if (power_of_two == patch_width)
-			{
-				mPatchWidth = patch_width;
-				mPatchOrder = patch_order;
-			}
-			else // patch_width is not a power of two...
-			{
-				mPatchWidth = 0;
-				mPatchOrder = 0;
-			}
+			power_of_two *= 2;
+			patch_order += 1;
 		}
-		else // patch_width is not a factor of (surface_width - 1)...
+
+		if (power_of_two != patch_width)
 		{
-			mPatchWidth = 0;
-			mPatchOrder = 0;
+			patch_width = power_of_two;
 		}
+
+		mPatchWidth = patch_width;
+		mPatchOrder = patch_order;
 	}
-	else // surface_width is not a power of two...
+	else // patch_width is not a factor of (surface_width - 1)...
 	{
-		mSurfaceWidth = 0;
 		mPatchWidth = 0;
 		mPatchOrder = 0;
 	}
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index d3c9120523d..0965d21dde0 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -4316,10 +4316,6 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data)
 		{
 			measurementp->sample(stat_value);
 		}
-		else
-		{
-			LL_WARNS() << "Unknown sim stat identifier: " << stat_id << LL_ENDL;
-		}
 	}
 
 	//
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index b8633f09390..1ae35a67a46 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -4961,8 +4961,10 @@ void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep)
 
 S32 LLViewerObject::setTETextureCore(const U8 te, LLViewerTexture *image)
 {
+	if (!image)
+		return 0;
 	LLUUID old_image_id = getTE(te)->getID();
-	const LLUUID& uuid = image->getID();
+	const LLUUID& uuid = image ? image->getID() : LLUUID::null;
 	S32 retval = 0;
 	if (uuid != getTE(te)->getID() ||
 		uuid.isNull())
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 2860f912ede..94aa251d000 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -9647,7 +9647,6 @@ void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& conte
 
 	updateMeshTextures();
 	updateMeshVisibility();
-
 }
 
 LLViewerTexture* LLVOAvatar::getBakedTexture(const U8 te)
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index af61b8cdf37..e596f68ace3 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -265,6 +265,15 @@ void LLXMLRPCTransaction::Handler::onCompleted(LLCore::HttpHandle handle,
 	// the contents of a buffer array are potentially noncontiguous, so we
 	// will need to copy them into an contiguous block of memory for XMLRPC.
 	LLCore::BufferArray *body = response->getBody();
+    if (!body)
+    {
+        mImpl->setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
+        LL_WARNS() << "LLXMLRPCTransaction XMLRPC error:"
+            << "Response has no body! OpenSim grid admins screw the pooch again!" << LL_ENDL;
+        LL_WARNS() << "LLXMLRPCTransaction request URI: "
+            << mImpl->mURI << LL_ENDL;
+        return;
+    }
 	char * bodydata = new char[body->size()];
 
 	body->read(0, bodydata, body->size());
-- 
GitLab