From cca85dea6755a90f9f6b4c3174743bb0abc4f73e Mon Sep 17 00:00:00 2001
From: Todd Stinson <stinson@lindenlab.com>
Date: Fri, 11 May 2012 19:39:44 -0700
Subject: [PATCH] EXP-1928: First pass at building the functionality to restart
 teleport after increasing the maturity preference level to match the intended
 teleport region.  There are probably still some cases that are broken and
 bugs.

---
 indra/newview/llagent.cpp         | 151 ++++++++++++++++++++++++++----
 indra/newview/llagent.h           |  31 +++++-
 indra/newview/llviewermessage.cpp |  32 +++++--
 3 files changed, 185 insertions(+), 29 deletions(-)

diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index d7c39ff78d8..fb217f21867 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -320,6 +320,12 @@ LLAgent::LLAgent() :
 	mAgentAccess(new LLAgentAccess(gSavedSettings)),
 	mCanEditParcel(false),
 	mTeleportSourceSLURL(new LLSLURL),
+	mCurrentTeleportRequest(),
+	mFailedTeleportRequest(),
+	mTeleportFinishedSlot(),
+	mTeleportFailedSlot(),
+	mIsMaturityRatingChangingDuringTeleport(false),
+	mMaturityRatingChange(0),
 	mTeleportState( TELEPORT_NONE ),
 	mRegionp(NULL),
 
@@ -406,7 +412,14 @@ void LLAgent::init()
 	gSavedSettings.getControl("PreferredMaturity")->getValidateSignal()->connect(boost::bind(&LLAgent::validateMaturity, this, _2));
 	gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLAgent::handleMaturity, this, _2));
 
-	LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&LLAgent::parcelChangedCallback));
+	if (!mTeleportFinishedSlot.connected())
+	{
+		mTeleportFinishedSlot = LLViewerParcelMgr::getInstance()->setTeleportFinishedCallback(boost::bind(&LLAgent::handleTeleportFinished, this));
+	}
+	if (!mTeleportFailedSlot.connected())
+	{
+		mTeleportFailedSlot = LLViewerParcelMgr::getInstance()->setTeleportFailedCallback(boost::bind(&LLAgent::handleTeleportFailed, this));
+	}
 
 	mInitialized = TRUE;
 }
@@ -417,6 +430,14 @@ void LLAgent::init()
 void LLAgent::cleanup()
 {
 	mRegionp = NULL;
+	if (mTeleportFinishedSlot.connected())
+	{
+		mTeleportFinishedSlot.disconnect();
+	}
+	if (mTeleportFailedSlot.connected())
+	{
+		mTeleportFailedSlot.disconnect();
+	}
 }
 
 //-----------------------------------------------------------------------------
@@ -2457,7 +2478,49 @@ int LLAgent::convertTextToMaturity(char text)
 	return LLAgentAccess::convertTextToMaturity(text);
 }
 
-bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity)
+class LLMaturityPreferencesResponder : public LLHTTPClient::Responder
+{
+public:
+	LLMaturityPreferencesResponder(LLAgent::maturity_preferences_callback_t pMaturityPreferencesCallback);
+	virtual ~LLMaturityPreferencesResponder();
+
+	virtual void result(const LLSD &pContent);
+	virtual void error(U32 pStatus, const std::string& pReason);
+
+protected:
+
+private:
+	LLAgent::maturity_preferences_callback_t mMaturityPreferencesCallback;
+};
+
+LLMaturityPreferencesResponder::LLMaturityPreferencesResponder(LLAgent::maturity_preferences_callback_t pMaturityPreferencesCallback)
+	: LLHTTPClient::Responder(),
+	mMaturityPreferencesCallback(pMaturityPreferencesCallback)
+{
+}
+
+LLMaturityPreferencesResponder::~LLMaturityPreferencesResponder()
+{
+}
+
+void LLMaturityPreferencesResponder::result(const LLSD &pContent)
+{
+	if (!mMaturityPreferencesCallback.empty())
+	{
+		mMaturityPreferencesCallback(pContent);
+	}
+}
+
+void LLMaturityPreferencesResponder::error(U32 pStatus, const std::string& pReason)
+{
+	if (!mMaturityPreferencesCallback.empty())
+	{
+		LLSD empty;
+		mMaturityPreferencesCallback(empty);
+	}
+}
+
+bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity, maturity_preferences_callback_t pMaturityPreferencesCallback)
 {
 	if (!getRegion())
 		return false;
@@ -2485,7 +2548,8 @@ bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity)
 		body["access_prefs"] = access_prefs;
 		llinfos << "Sending access prefs update to " << (access_prefs["max"].asString()) << " via capability to: "
 		<< url << llendl;
-		LLHTTPClient::post(url, body, new LLHTTPClient::Responder());    // Ignore response
+		LLHTTPClient::ResponderPtr responderPtr = LLHTTPClient::ResponderPtr(new LLMaturityPreferencesResponder(pMaturityPreferencesCallback));
+		LLHTTPClient::post(url, body, responderPtr);
 		return true;
 	}
 	return false;
@@ -3538,6 +3602,62 @@ bool LLAgent::teleportCore(bool is_local)
 	return true;
 }
 
+void LLAgent::restartFailedTeleportRequest()
+{
+	// XXX stinson 05/11/2012 llassert(hasFailedTeleportRequest());
+	if (hasFailedTeleportRequest())
+	{
+		mFailedTeleportRequest->doTeleport();
+	}
+}
+
+void LLAgent::clearFailedTeleportRequest()
+{
+	// XXX stinson 05/11/2012 llassert(hasFailedTeleportRequest());
+	if (hasFailedTeleportRequest())
+	{
+		mFailedTeleportRequest.reset();
+	}
+}
+
+void LLAgent::setMaturityRatingChangeDuringTeleport(int pMaturityRatingChange)
+{
+	mIsMaturityRatingChangingDuringTeleport = true;
+	mMaturityRatingChange = pMaturityRatingChange;
+}
+
+void LLAgent::handleTeleportFinished()
+{
+	// XXX stinson 05/11/2012 llassert(hasCurrentTeleportRequest());
+	if (hasCurrentTeleportRequest())
+	{
+		mCurrentTeleportRequest.reset();
+	}
+	if (hasFailedTeleportRequest())
+	{
+		clearFailedTeleportRequest();
+	}
+	if (mIsMaturityRatingChangingDuringTeleport)
+	{
+		// notify user that the maturity preference has been changed
+		LLSD args;
+		args["RATING"] = LLViewerRegion::accessToString(mMaturityRatingChange);
+		LLNotificationsUtil::add("PreferredMaturityChanged", args);
+		mIsMaturityRatingChangingDuringTeleport = false;
+	}
+}
+
+void LLAgent::handleTeleportFailed()
+{
+	// XXX stinson 05/11/2012 llassert(hasCurrentTeleportRequest());
+	// XXX stinson 05/11/2012 llassert(!hasFailedTeleportRequest());
+	if (hasCurrentTeleportRequest())
+	{
+		mFailedTeleportRequest = mCurrentTeleportRequest;
+	}
+	mIsMaturityRatingChangingDuringTeleport = false;
+}
+
 void LLAgent::teleportRequest(
 	const U64& region_handle,
 	const LLVector3& pos_local,
@@ -3570,9 +3690,9 @@ void LLAgent::teleportRequest(
 // Landmark ID = LLUUID::null means teleport home
 void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id)
 {
-	llassert(mTeleportRequest == NULL);
-	mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLandmark(landmark_asset_id));
-	mTeleportRequest->doTeleport();
+	// XXX stinson 05/11/2012 llassert(!hasCurrentTeleportRequest());
+	mCurrentTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLandmark(landmark_asset_id));
+	mCurrentTeleportRequest->doTeleport();
 }
 
 void LLAgent::doTeleportViaLandmark(const LLUUID& landmark_asset_id)
@@ -3592,9 +3712,9 @@ void LLAgent::doTeleportViaLandmark(const LLUUID& landmark_asset_id)
 
 void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike)
 {
-	llassert(mTeleportRequest == NULL);
-	mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLure(lure_id, godlike));
-	mTeleportRequest->doTeleport();
+	// XXX stinson 05/11/2012 llassert(!hasCurrentTeleportRequest());
+	mCurrentTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLure(lure_id, godlike));
+	mCurrentTeleportRequest->doTeleport();
 }
 
 void LLAgent::doTeleportViaLure(const LLUUID& lure_id, BOOL godlike)
@@ -3648,9 +3768,9 @@ void LLAgent::teleportCancel()
 
 void LLAgent::teleportViaLocation(const LLVector3d& pos_global)
 {
-	llassert(mTeleportRequest == NULL);
-	mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocation(pos_global));
-	mTeleportRequest->doTeleport();
+	// XXX stinson 05/11/2012 llassert(!hasCurrentTeleportRequest());
+	mCurrentTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocation(pos_global));
+	mCurrentTeleportRequest->doTeleport();
 }
 
 void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global)
@@ -3697,9 +3817,9 @@ void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global)
 // Teleport to global position, but keep facing in the same direction 
 void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global)
 {
-	llassert(mTeleportRequest == NULL);
-	mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocationLookAt(pos_global));
-	mTeleportRequest->doTeleport();
+	// XXX stinson 05/11/2012 llassert(!hasCurrentTeleportRequest());
+	mCurrentTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocationLookAt(pos_global));
+	mCurrentTeleportRequest->doTeleport();
 }
 
 void LLAgent::doTeleportViaLocationLookAt(const LLVector3d& pos_global)
@@ -3723,7 +3843,6 @@ void LLAgent::setTeleportState(ETeleportState state)
 	{
 		case TELEPORT_NONE:
 			mbTeleportKeepsLookAt = false;
-			mTeleportRequest.reset();
 			break;
 
 		case TELEPORT_MOVING:
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 3b27d48928a..07ceaf11b10 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -35,6 +35,7 @@
 #include "llcoordframe.h"			// for mFrameAgent
 #include "llvoavatardefines.h"
 
+#include <boost/function.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/signals2.hpp>
 
@@ -570,12 +571,32 @@ class LLAgent : public LLOldEvents::LLObservable
 protected:
 	bool 			teleportCore(bool is_local = false); 					// Stuff for all teleports; returns true if the teleport can proceed
 
+	//--------------------------------------------------------------------
+	// Teleport State
+	//--------------------------------------------------------------------
+
+public:
+	inline bool     hasCurrentTeleportRequest() {return (mCurrentTeleportRequest != NULL);};
+	inline bool     hasFailedTeleportRequest() {return (mFailedTeleportRequest != NULL);};
+	void            restartFailedTeleportRequest();
+	void            clearFailedTeleportRequest();
+	void            setMaturityRatingChangeDuringTeleport(int pMaturityRatingChange);
+
 private:
 	friend class LLTeleportRequest;
 	friend class LLTeleportRequestViaLandmark;
 	friend class LLTeleportRequestViaLure;
 	friend class LLTeleportRequestViaLocation;
 	friend class LLTeleportRequestViaLocationLookAt;
+
+	LLTeleportRequestPtr mCurrentTeleportRequest;
+	LLTeleportRequestPtr mFailedTeleportRequest;
+	boost::signals2::connection mTeleportFinishedSlot;
+	boost::signals2::connection mTeleportFailedSlot;
+
+	bool            mIsMaturityRatingChangingDuringTeleport;
+	int             mMaturityRatingChange;
+
 	void 			teleportRequest(const U64& region_handle,
 									const LLVector3& pos_local,				// Go to a named location home
 									bool look_at_from_camera = false);
@@ -584,6 +605,9 @@ class LLAgent : public LLOldEvents::LLObservable
 	void 			doTeleportViaLocation(const LLVector3d& pos_global);		// To a global location - this will probably need to be deprecated
 	void			doTeleportViaLocationLookAt(const LLVector3d& pos_global);// To a global location, preserving camera rotation
 
+	void            handleTeleportFinished();
+	void            handleTeleportFailed();
+
 	//--------------------------------------------------------------------
 	// Teleport State
 	//--------------------------------------------------------------------
@@ -592,7 +616,6 @@ class LLAgent : public LLOldEvents::LLObservable
 	void			setTeleportState(ETeleportState state);
 private:
 	ETeleportState	mTeleportState;
-	LLTeleportRequestPtr mTeleportRequest;
 
 	//--------------------------------------------------------------------
 	// Teleport Message
@@ -668,8 +691,10 @@ class LLAgent : public LLOldEvents::LLObservable
 	bool 			isAdult() const;
 	void 			setTeen(bool teen);
 	void 			setMaturity(char text);
-	static int 		convertTextToMaturity(char text); 
-	bool 			sendMaturityPreferenceToServer(int preferredMaturity); // ! "U8" instead of "int"?
+	static int 		convertTextToMaturity(char text);
+
+	typedef boost::function<void (const LLSD &pResponse)> maturity_preferences_callback_t;
+	bool 			sendMaturityPreferenceToServer(int preferredMaturity, maturity_preferences_callback_t pMaturityPreferencesCallback = NULL); // ! "U8" instead of "int"?
 
 	// Maturity callbacks for PreferredMaturity control variable
 	void 			handleMaturity(const LLSD& newvalue);
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 2917fee62e9..3712e56f7c3 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -5385,7 +5385,20 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
 	}
 }
 
-
+void handle_maturity_preference_change(const LLSD &pResponse, int pMaturityRatingChange)
+{
+	if (pResponse.isUndefined())
+	{
+		// XXX stinson 05/11/2012 llinfos << "Maturity response ==> <null>" << llendl;
+		gAgent.clearFailedTeleportRequest();
+	}
+	else
+	{
+		// XXX stinson 05/11/2012 linfos << "Maturity response ==> '" << pResponse << "'" << llendl;
+		gAgent.setMaturityRatingChangeDuringTeleport(pMaturityRatingChange);
+		gAgent.restartFailedTeleportRequest();
+	}
+}
 
 bool handle_special_notification_callback(const LLSD& notification, const LLSD& response)
 {
@@ -5396,12 +5409,11 @@ bool handle_special_notification_callback(const LLSD& notification, const LLSD&
 		// set the preference to the maturity of the region we're calling
 		int preferredMaturity = notification["payload"]["_region_access"].asInteger();
 		gSavedSettings.setU32("PreferredMaturity", preferredMaturity);
-		gAgent.sendMaturityPreferenceToServer(preferredMaturity);
-
-		// notify user that the maturity preference has been changed
-		LLSD args;
-		args["RATING"] = LLViewerRegion::accessToString(preferredMaturity);
-		LLNotificationsUtil::add("PreferredMaturityChanged", args);
+		gAgent.sendMaturityPreferenceToServer(preferredMaturity, boost::bind(&handle_maturity_preference_change, _1, preferredMaturity));
+	}
+	else
+	{
+		gAgent.clearFailedTeleportRequest();
 	}
 	
 	return false;
@@ -6147,6 +6159,9 @@ void process_teleport_failed(LLMessageSystem *msg, void**)
 	std::string big_reason;
 	LLSD args;
 
+	// Let the interested parties know that teleport failed.
+	LLViewerParcelMgr::getInstance()->onTeleportFailed();
+
 	// if we have additional alert data
 	if (msg->has(_PREHASH_AlertInfo) && msg->getSizeFast(_PREHASH_AlertInfo, _PREHASH_Message) > 0)
 	{
@@ -6205,9 +6220,6 @@ void process_teleport_failed(LLMessageSystem *msg, void**)
 
 	LLNotificationsUtil::add("CouldNotTeleportReason", args);
 
-	// Let the interested parties know that teleport failed.
-	LLViewerParcelMgr::getInstance()->onTeleportFailed();
-
 	if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE )
 	{
 		gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
-- 
GitLab