diff options
Diffstat (limited to 'indra/newview/llpathfindingmanager.cpp')
| -rw-r--r-- | indra/newview/llpathfindingmanager.cpp | 1836 |
1 files changed, 918 insertions, 918 deletions
diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp index ed141d3920..5e7bc4fb3b 100644 --- a/indra/newview/llpathfindingmanager.cpp +++ b/indra/newview/llpathfindingmanager.cpp @@ -1,918 +1,918 @@ -/**
-* @file llpathfindingmanager.cpp
-* @brief Implementation of llpathfindingmanager
-* @author Stinson@lindenlab.com
-*
-* $LicenseInfo:firstyear=2012&license=viewerlgpl$
-* Second Life Viewer Source Code
-* Copyright (C) 2012, Linden Research, Inc.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public
-* License as published by the Free Software Foundation;
-* version 2.1 of the License only.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this library; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*
-* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-* $/LicenseInfo$
-*/
-
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llpathfindingmanager.h"
-
-#include <string>
-#include <map>
-
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/signals2.hpp>
-
-#include "llagent.h"
-#include "llhttpnode.h"
-#include "llnotificationsutil.h"
-#include "llpathfindingcharacterlist.h"
-#include "llpathfindinglinkset.h"
-#include "llpathfindinglinksetlist.h"
-#include "llpathfindingnavmesh.h"
-#include "llpathfindingnavmeshstatus.h"
-#include "llpathfindingobject.h"
-#include "llpathinglib.h"
-#include "llsingleton.h"
-#include "llsd.h"
-#include "lltrans.h"
-#include "lluuid.h"
-#include "llviewerregion.h"
-#include "llweb.h"
-#include "llcorehttputil.h"
-#include "llworld.h"
-
-#define CAP_SERVICE_RETRIEVE_NAVMESH "RetrieveNavMeshSrc"
-
-#define CAP_SERVICE_NAVMESH_STATUS "NavMeshGenerationStatus"
-
-#define CAP_SERVICE_GET_OBJECT_LINKSETS "RegionObjects"
-#define CAP_SERVICE_SET_OBJECT_LINKSETS "ObjectNavMeshProperties"
-#define CAP_SERVICE_TERRAIN_LINKSETS "TerrainNavMeshProperties"
-
-#define CAP_SERVICE_CHARACTERS "CharacterProperties"
-
-#define SIM_MESSAGE_NAVMESH_STATUS_UPDATE "/message/NavMeshStatusUpdate"
-#define SIM_MESSAGE_AGENT_STATE_UPDATE "/message/AgentStateUpdate"
-#define SIM_MESSAGE_BODY_FIELD "body"
-
-#define CAP_SERVICE_AGENT_STATE "AgentState"
-
-#define AGENT_STATE_CAN_REBAKE_REGION_FIELD "can_modify_navmesh"
-
-//---------------------------------------------------------------------------
-// LLNavMeshSimStateChangeNode
-//---------------------------------------------------------------------------
-
-class LLNavMeshSimStateChangeNode : public LLHTTPNode
-{
-public:
- virtual void post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const;
-};
-
-LLHTTPRegistration<LLNavMeshSimStateChangeNode> gHTTPRegistrationNavMeshSimStateChangeNode(SIM_MESSAGE_NAVMESH_STATUS_UPDATE);
-
-
-//---------------------------------------------------------------------------
-// LLAgentStateChangeNode
-//---------------------------------------------------------------------------
-class LLAgentStateChangeNode : public LLHTTPNode
-{
-public:
- virtual void post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const;
-};
-
-LLHTTPRegistration<LLAgentStateChangeNode> gHTTPRegistrationAgentStateChangeNode(SIM_MESSAGE_AGENT_STATE_UPDATE);
-
-//---------------------------------------------------------------------------
-// LinksetsResponder
-//---------------------------------------------------------------------------
-
-class LinksetsResponder
-{
-public:
- LinksetsResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pLinksetsCallback, bool pIsObjectRequested, bool pIsTerrainRequested);
- virtual ~LinksetsResponder();
-
- void handleObjectLinksetsResult(const LLSD &pContent);
- void handleObjectLinksetsError();
- void handleTerrainLinksetsResult(const LLSD &pContent);
- void handleTerrainLinksetsError();
-
- typedef std::shared_ptr<LinksetsResponder> ptr_t;
-
-protected:
-
-private:
- void sendCallback();
-
- typedef enum
- {
- kNotRequested,
- kWaiting,
- kReceivedGood,
- kReceivedError
- } EMessagingState;
-
- LLPathfindingManager::request_id_t mRequestId;
- LLPathfindingManager::object_request_callback_t mLinksetsCallback;
-
- EMessagingState mObjectMessagingState;
- EMessagingState mTerrainMessagingState;
-
- LLPathfindingObjectListPtr mObjectLinksetListPtr;
- LLPathfindingObjectPtr mTerrainLinksetPtr;
-};
-
-typedef std::shared_ptr<LinksetsResponder> LinksetsResponderPtr;
-
-//---------------------------------------------------------------------------
-// LLPathfindingManager
-//---------------------------------------------------------------------------
-
-LLPathfindingManager::LLPathfindingManager():
- mNavMeshMap(),
- mAgentStateSignal()
-{
-}
-
-LLPathfindingManager::~LLPathfindingManager()
-{
- quitSystem();
-}
-
-void LLPathfindingManager::initSystem()
-{
- if (LLPathingLib::getInstance() == NULL)
- {
- LLPathingLib::initSystem();
- }
-}
-
-void LLPathfindingManager::quitSystem()
-{
- if (LLPathingLib::getInstance() != NULL)
- {
- LLPathingLib::quitSystem();
- }
-}
-
-bool LLPathfindingManager::isPathfindingViewEnabled() const
-{
- return (LLPathingLib::getInstance() != NULL);
-}
-
-bool LLPathfindingManager::isPathfindingEnabledForCurrentRegion() const
-{
- return isPathfindingEnabledForRegion(getCurrentRegion());
-}
-
-bool LLPathfindingManager::isPathfindingEnabledForRegion(LLViewerRegion *pRegion) const
-{
- std::string retrieveNavMeshURL = getRetrieveNavMeshURLForRegion(pRegion);
- return !retrieveNavMeshURL.empty();
-}
-
-bool LLPathfindingManager::isAllowViewTerrainProperties() const
-{
- LLViewerRegion* region = getCurrentRegion();
- return (gAgent.isGodlike() || ((region != NULL) && region->canManageEstate()));
-}
-
-LLPathfindingNavMesh::navmesh_slot_t LLPathfindingManager::registerNavMeshListenerForRegion(LLViewerRegion *pRegion, LLPathfindingNavMesh::navmesh_callback_t pNavMeshCallback)
-{
- LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(pRegion);
- return navMeshPtr->registerNavMeshListener(pNavMeshCallback);
-}
-
-void LLPathfindingManager::requestGetNavMeshForRegion(LLViewerRegion *pRegion, bool pIsGetStatusOnly)
-{
- LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(pRegion);
-
- if (pRegion == NULL)
- {
- navMeshPtr->handleNavMeshNotEnabled();
- }
- else if (!pRegion->capabilitiesReceived())
- {
- navMeshPtr->handleNavMeshWaitForRegionLoad();
- pRegion->setCapabilitiesReceivedCallback(boost::bind(&LLPathfindingManager::handleDeferredGetNavMeshForRegion, this, _1, pIsGetStatusOnly));
- }
- else if (!isPathfindingEnabledForRegion(pRegion))
- {
- navMeshPtr->handleNavMeshNotEnabled();
- }
- else
- {
- std::string navMeshStatusURL = getNavMeshStatusURLForRegion(pRegion);
- llassert(!navMeshStatusURL.empty());
- navMeshPtr->handleNavMeshCheckVersion();
-
- U64 regionHandle = pRegion->getHandle();
- std::string coroname = LLCoros::instance().launch("LLPathfindingManager::navMeshStatusRequestCoro",
- boost::bind(&LLPathfindingManager::navMeshStatusRequestCoro, this, navMeshStatusURL, regionHandle, pIsGetStatusOnly));
- }
-}
-
-void LLPathfindingManager::requestGetLinksets(request_id_t pRequestId, object_request_callback_t pLinksetsCallback) const
-{
- LLPathfindingObjectListPtr emptyLinksetListPtr;
- LLViewerRegion *currentRegion = getCurrentRegion();
-
- if (currentRegion == NULL)
- {
- pLinksetsCallback(pRequestId, kRequestNotEnabled, emptyLinksetListPtr);
- }
- else if (!currentRegion->capabilitiesReceived())
- {
- pLinksetsCallback(pRequestId, kRequestStarted, emptyLinksetListPtr);
- currentRegion->setCapabilitiesReceivedCallback(boost::bind(&LLPathfindingManager::handleDeferredGetLinksetsForRegion, this, _1, pRequestId, pLinksetsCallback));
- }
- else
- {
- std::string objectLinksetsURL = getRetrieveObjectLinksetsURLForCurrentRegion();
- std::string terrainLinksetsURL = getTerrainLinksetsURLForCurrentRegion();
- if (objectLinksetsURL.empty() || terrainLinksetsURL.empty())
- {
- pLinksetsCallback(pRequestId, kRequestNotEnabled, emptyLinksetListPtr);
- }
- else
- {
- pLinksetsCallback(pRequestId, kRequestStarted, emptyLinksetListPtr);
-
- bool doRequestTerrain = isAllowViewTerrainProperties();
- LinksetsResponder::ptr_t linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, true, doRequestTerrain));
-
- std::string coroname = LLCoros::instance().launch("LLPathfindingManager::linksetObjectsCoro",
- boost::bind(&LLPathfindingManager::linksetObjectsCoro, this, objectLinksetsURL, linksetsResponderPtr, LLSD()));
-
- if (doRequestTerrain)
- {
- std::string coroname = LLCoros::instance().launch("LLPathfindingManager::linksetTerrainCoro",
- boost::bind(&LLPathfindingManager::linksetTerrainCoro, this, terrainLinksetsURL, linksetsResponderPtr, LLSD()));
- }
- }
- }
-}
-
-void LLPathfindingManager::requestSetLinksets(request_id_t pRequestId, const LLPathfindingObjectListPtr &pLinksetListPtr, LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD, object_request_callback_t pLinksetsCallback) const
-{
- LLPathfindingObjectListPtr emptyLinksetListPtr;
-
- std::string objectLinksetsURL = getChangeObjectLinksetsURLForCurrentRegion();
- std::string terrainLinksetsURL = getTerrainLinksetsURLForCurrentRegion();
- if (objectLinksetsURL.empty() || terrainLinksetsURL.empty())
- {
- pLinksetsCallback(pRequestId, kRequestNotEnabled, emptyLinksetListPtr);
- }
- else if ((pLinksetListPtr == NULL) || pLinksetListPtr->isEmpty())
- {
- pLinksetsCallback(pRequestId, kRequestCompleted, emptyLinksetListPtr);
- }
- else
- {
- const LLPathfindingLinksetList *linksetList = dynamic_cast<const LLPathfindingLinksetList *>(pLinksetListPtr.get());
-
- LLSD objectPostData = linksetList->encodeObjectFields(pLinksetUse, pA, pB, pC, pD);
- LLSD terrainPostData;
- if (isAllowViewTerrainProperties())
- {
- terrainPostData = linksetList->encodeTerrainFields(pLinksetUse, pA, pB, pC, pD);
- }
-
- if (objectPostData.isUndefined() && terrainPostData.isUndefined())
- {
- pLinksetsCallback(pRequestId, kRequestCompleted, emptyLinksetListPtr);
- }
- else
- {
- pLinksetsCallback(pRequestId, kRequestStarted, emptyLinksetListPtr);
-
- LinksetsResponder::ptr_t linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, !objectPostData.isUndefined(), !terrainPostData.isUndefined()));
-
- if (!objectPostData.isUndefined())
- {
- std::string coroname = LLCoros::instance().launch("LLPathfindingManager::linksetObjectsCoro",
- boost::bind(&LLPathfindingManager::linksetObjectsCoro, this, objectLinksetsURL, linksetsResponderPtr, objectPostData));
- }
-
- if (!terrainPostData.isUndefined())
- {
- std::string coroname = LLCoros::instance().launch("LLPathfindingManager::linksetTerrainCoro",
- boost::bind(&LLPathfindingManager::linksetTerrainCoro, this, terrainLinksetsURL, linksetsResponderPtr, terrainPostData));
- }
- }
- }
-}
-
-void LLPathfindingManager::requestGetCharacters(request_id_t pRequestId, object_request_callback_t pCharactersCallback) const
-{
- LLPathfindingObjectListPtr emptyCharacterListPtr;
-
- LLViewerRegion *currentRegion = getCurrentRegion();
-
- if (currentRegion == NULL)
- {
- pCharactersCallback(pRequestId, kRequestNotEnabled, emptyCharacterListPtr);
- }
- else if (!currentRegion->capabilitiesReceived())
- {
- pCharactersCallback(pRequestId, kRequestStarted, emptyCharacterListPtr);
- currentRegion->setCapabilitiesReceivedCallback(boost::bind(&LLPathfindingManager::handleDeferredGetCharactersForRegion, this, _1, pRequestId, pCharactersCallback));
- }
- else
- {
- std::string charactersURL = getCharactersURLForCurrentRegion();
- if (charactersURL.empty())
- {
- pCharactersCallback(pRequestId, kRequestNotEnabled, emptyCharacterListPtr);
- }
- else
- {
- pCharactersCallback(pRequestId, kRequestStarted, emptyCharacterListPtr);
-
- std::string coroname = LLCoros::instance().launch("LLPathfindingManager::charactersCoro",
- boost::bind(&LLPathfindingManager::charactersCoro, this, charactersURL, pRequestId, pCharactersCallback));
- }
- }
-}
-
-LLPathfindingManager::agent_state_slot_t LLPathfindingManager::registerAgentStateListener(agent_state_callback_t pAgentStateCallback)
-{
- return mAgentStateSignal.connect(pAgentStateCallback);
-}
-
-void LLPathfindingManager::requestGetAgentState()
-{
- LLViewerRegion *currentRegion = getCurrentRegion();
-
- if (currentRegion == NULL)
- {
- mAgentStateSignal(false);
- }
- else
- {
- if (!currentRegion->capabilitiesReceived())
- {
- currentRegion->setCapabilitiesReceivedCallback(boost::bind(&LLPathfindingManager::handleDeferredGetAgentStateForRegion, this, _1));
- }
- else if (!isPathfindingEnabledForRegion(currentRegion))
- {
- mAgentStateSignal(false);
- }
- else
- {
- std::string agentStateURL = getAgentStateURLForRegion(currentRegion);
- llassert(!agentStateURL.empty());
-
- std::string coroname = LLCoros::instance().launch("LLPathfindingManager::navAgentStateRequestCoro",
- boost::bind(&LLPathfindingManager::navAgentStateRequestCoro, this, agentStateURL));
- }
- }
-}
-
-void LLPathfindingManager::requestRebakeNavMesh(rebake_navmesh_callback_t pRebakeNavMeshCallback)
-{
- LLViewerRegion *currentRegion = getCurrentRegion();
-
- if (currentRegion == NULL)
- {
- pRebakeNavMeshCallback(false);
- }
- else if (!isPathfindingEnabledForRegion(currentRegion))
- {
- pRebakeNavMeshCallback(false);
- }
- else
- {
- std::string navMeshStatusURL = getNavMeshStatusURLForCurrentRegion();
- llassert(!navMeshStatusURL.empty());
-
- std::string coroname = LLCoros::instance().launch("LLPathfindingManager::navMeshRebakeCoro",
- boost::bind(&LLPathfindingManager::navMeshRebakeCoro, this, navMeshStatusURL, pRebakeNavMeshCallback));
- }
-}
-
-void LLPathfindingManager::handleDeferredGetAgentStateForRegion(const LLUUID &pRegionUUID)
-{
- LLViewerRegion *currentRegion = getCurrentRegion();
-
- if ((currentRegion != NULL) && (currentRegion->getRegionID() == pRegionUUID))
- {
- requestGetAgentState();
- }
-}
-
-void LLPathfindingManager::handleDeferredGetNavMeshForRegion(const LLUUID &pRegionUUID, bool pIsGetStatusOnly)
-{
- LLViewerRegion *currentRegion = getCurrentRegion();
-
- if ((currentRegion != NULL) && (currentRegion->getRegionID() == pRegionUUID))
- {
- requestGetNavMeshForRegion(currentRegion, pIsGetStatusOnly);
- }
-}
-
-void LLPathfindingManager::handleDeferredGetLinksetsForRegion(const LLUUID &pRegionUUID, request_id_t pRequestId, object_request_callback_t pLinksetsCallback) const
-{
- LLViewerRegion *currentRegion = getCurrentRegion();
-
- if ((currentRegion != NULL) && (currentRegion->getRegionID() == pRegionUUID))
- {
- requestGetLinksets(pRequestId, pLinksetsCallback);
- }
-}
-
-void LLPathfindingManager::handleDeferredGetCharactersForRegion(const LLUUID &pRegionUUID, request_id_t pRequestId, object_request_callback_t pCharactersCallback) const
-{
- LLViewerRegion *currentRegion = getCurrentRegion();
-
- if ((currentRegion != NULL) && (currentRegion->getRegionID() == pRegionUUID))
- {
- requestGetCharacters(pRequestId, pCharactersCallback);
- }
-}
-
-void LLPathfindingManager::navMeshStatusRequestCoro(std::string url, U64 regionHandle, bool isGetStatusOnly)
-{
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("NavMeshStatusRequest", httpPolicy));
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
-
- LLViewerRegion *region = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
- if (!region)
- {
- LL_WARNS("PathfindingManager") << "Attempting to retrieve navmesh status for region that has gone away." << LL_ENDL;
- return;
- }
- LLUUID regionUUID = region->getRegionID();
-
- region = NULL;
- LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
-
- region = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
-
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- LLPathfindingNavMeshStatus navMeshStatus(regionUUID);
- if (!status)
- {
- LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
- ". Building using empty status." << LL_ENDL;
- }
- else
- {
- result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
- navMeshStatus = LLPathfindingNavMeshStatus(regionUUID, result);
- }
-
- LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(regionUUID);
-
- if (!navMeshStatus.isValid())
- {
- navMeshPtr->handleNavMeshError();
- return;
- }
- else if (navMeshPtr->hasNavMeshVersion(navMeshStatus))
- {
- navMeshPtr->handleRefresh(navMeshStatus);
- return;
- }
- else if (isGetStatusOnly)
- {
- navMeshPtr->handleNavMeshNewVersion(navMeshStatus);
- return;
- }
-
- if ((!region) || !region->isAlive())
- {
- LL_WARNS("PathfindingManager") << "About to update navmesh status for region that has gone away." << LL_ENDL;
- navMeshPtr->handleNavMeshNotEnabled();
- return;
- }
-
- std::string navMeshURL = getRetrieveNavMeshURLForRegion(region);
-
- if (navMeshURL.empty())
- {
- navMeshPtr->handleNavMeshNotEnabled();
- return;
- }
-
- navMeshPtr->handleNavMeshStart(navMeshStatus);
-
- LLSD postData;
- result = httpAdapter->postAndSuspend(httpRequest, navMeshURL, postData);
-
- U32 navMeshVersion = navMeshStatus.getVersion();
-
- if (!status)
- {
- LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
- ". reporting error." << LL_ENDL;
- navMeshPtr->handleNavMeshError(navMeshVersion);
- }
- else
- {
- result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
- navMeshPtr->handleNavMeshResult(result, navMeshVersion);
-
- }
-
-}
-
-void LLPathfindingManager::navAgentStateRequestCoro(std::string url)
-{
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("NavAgentStateRequest", httpPolicy));
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
-
- LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
-
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- bool canRebake = false;
- if (!status)
- {
- LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
- ". Building using empty status." << LL_ENDL;
- }
- else
- {
- llassert(result.has(AGENT_STATE_CAN_REBAKE_REGION_FIELD));
- llassert(result.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).isBoolean());
- canRebake = result.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).asBoolean();
- }
-
- handleAgentState(canRebake);
-}
-
-void LLPathfindingManager::navMeshRebakeCoro(std::string url, rebake_navmesh_callback_t rebakeNavMeshCallback)
-{
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("NavMeshRebake", httpPolicy));
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
-
-
- LLSD postData = LLSD::emptyMap();
- postData["command"] = "rebuild";
-
- LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
-
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- bool success = true;
- if (!status)
- {
- LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
- ". Rebake failed." << LL_ENDL;
- success = false;
- }
-
- rebakeNavMeshCallback(success);
-}
-
-// If called with putData undefined this coroutine will issue a get. If there
-// is data in putData it will be PUT to the URL.
-void LLPathfindingManager::linksetObjectsCoro(std::string url, LinksetsResponder::ptr_t linksetsResponsderPtr, LLSD putData) const
-{
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("LinksetObjects", httpPolicy));
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
-
- LLSD result;
-
- if (putData.isUndefined())
- {
- result = httpAdapter->getAndSuspend(httpRequest, url);
- }
- else
- {
- result = httpAdapter->putAndSuspend(httpRequest, url, putData);
- }
-
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- if (!status)
- {
- LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
- ". linksetObjects failed." << LL_ENDL;
- linksetsResponsderPtr->handleObjectLinksetsError();
- }
- else
- {
- result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
- linksetsResponsderPtr->handleObjectLinksetsResult(result);
- }
-}
-
-// If called with putData undefined this coroutine will issue a GET. If there
-// is data in putData it will be PUT to the URL.
-void LLPathfindingManager::linksetTerrainCoro(std::string url, LinksetsResponder::ptr_t linksetsResponsderPtr, LLSD putData) const
-{
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("LinksetTerrain", httpPolicy));
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
-
- LLSD result;
-
- if (putData.isUndefined())
- {
- result = httpAdapter->getAndSuspend(httpRequest, url);
- }
- else
- {
- result = httpAdapter->putAndSuspend(httpRequest, url, putData);
- }
-
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- if (!status)
- {
- LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
- ". linksetTerrain failed." << LL_ENDL;
- linksetsResponsderPtr->handleTerrainLinksetsError();
- }
- else
- {
- result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
- linksetsResponsderPtr->handleTerrainLinksetsResult(result);
- }
-
-}
-
-void LLPathfindingManager::charactersCoro(std::string url, request_id_t requestId, object_request_callback_t callback) const
-{
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("LinksetTerrain", httpPolicy));
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
-
- LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
-
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- if (!status)
- {
- LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
- ". characters failed." << LL_ENDL;
-
- LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList());
- callback(requestId, LLPathfindingManager::kRequestError, characterListPtr);
- }
- else
- {
- result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
- LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(result));
- callback(requestId, LLPathfindingManager::kRequestCompleted, characterListPtr);
- }
-}
-
-void LLPathfindingManager::handleNavMeshStatusUpdate(const LLPathfindingNavMeshStatus &pNavMeshStatus)
-{
- LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(pNavMeshStatus.getRegionUUID());
-
- if (!pNavMeshStatus.isValid())
- {
- navMeshPtr->handleNavMeshError();
- }
- else
- {
- navMeshPtr->handleNavMeshNewVersion(pNavMeshStatus);
- }
-}
-
-void LLPathfindingManager::handleAgentState(bool pCanRebakeRegion)
-{
- mAgentStateSignal(pCanRebakeRegion);
-}
-
-LLPathfindingNavMeshPtr LLPathfindingManager::getNavMeshForRegion(const LLUUID &pRegionUUID)
-{
- LLPathfindingNavMeshPtr navMeshPtr;
- NavMeshMap::iterator navMeshIter = mNavMeshMap.find(pRegionUUID);
- if (navMeshIter == mNavMeshMap.end())
- {
- navMeshPtr = LLPathfindingNavMeshPtr(new LLPathfindingNavMesh(pRegionUUID));
- mNavMeshMap.insert(std::pair<LLUUID, LLPathfindingNavMeshPtr>(pRegionUUID, navMeshPtr));
- }
- else
- {
- navMeshPtr = navMeshIter->second;
- }
-
- return navMeshPtr;
-}
-
-LLPathfindingNavMeshPtr LLPathfindingManager::getNavMeshForRegion(LLViewerRegion *pRegion)
-{
- LLUUID regionUUID;
- if (pRegion != NULL)
- {
- regionUUID = pRegion->getRegionID();
- }
-
- return getNavMeshForRegion(regionUUID);
-}
-
-std::string LLPathfindingManager::getNavMeshStatusURLForCurrentRegion() const
-{
- return getNavMeshStatusURLForRegion(getCurrentRegion());
-}
-
-std::string LLPathfindingManager::getNavMeshStatusURLForRegion(LLViewerRegion *pRegion) const
-{
- return getCapabilityURLForRegion(pRegion, CAP_SERVICE_NAVMESH_STATUS);
-}
-
-std::string LLPathfindingManager::getRetrieveNavMeshURLForRegion(LLViewerRegion *pRegion) const
-{
- return getCapabilityURLForRegion(pRegion, CAP_SERVICE_RETRIEVE_NAVMESH);
-}
-
-std::string LLPathfindingManager::getRetrieveObjectLinksetsURLForCurrentRegion() const
-{
- return getCapabilityURLForCurrentRegion(CAP_SERVICE_GET_OBJECT_LINKSETS);
-}
-
-std::string LLPathfindingManager::getChangeObjectLinksetsURLForCurrentRegion() const
-{
- return getCapabilityURLForCurrentRegion(CAP_SERVICE_SET_OBJECT_LINKSETS);
-}
-
-std::string LLPathfindingManager::getTerrainLinksetsURLForCurrentRegion() const
-{
- return getCapabilityURLForCurrentRegion(CAP_SERVICE_TERRAIN_LINKSETS);
-}
-
-std::string LLPathfindingManager::getCharactersURLForCurrentRegion() const
-{
- return getCapabilityURLForCurrentRegion(CAP_SERVICE_CHARACTERS);
-}
-
-std::string LLPathfindingManager::getAgentStateURLForRegion(LLViewerRegion *pRegion) const
-{
- return getCapabilityURLForRegion(pRegion, CAP_SERVICE_AGENT_STATE);
-}
-
-std::string LLPathfindingManager::getCapabilityURLForCurrentRegion(const std::string &pCapabilityName) const
-{
- return getCapabilityURLForRegion(getCurrentRegion(), pCapabilityName);
-}
-
-std::string LLPathfindingManager::getCapabilityURLForRegion(LLViewerRegion *pRegion, const std::string &pCapabilityName) const
-{
- std::string capabilityURL("");
-
- if (pRegion != NULL)
- {
- capabilityURL = pRegion->getCapability(pCapabilityName);
- }
-
- if (capabilityURL.empty())
- {
- LL_WARNS() << "cannot find capability '" << pCapabilityName << "' for current region '"
- << ((pRegion != NULL) ? pRegion->getName() : "<null>") << "'" << LL_ENDL;
- }
-
- return capabilityURL;
-}
-
-LLViewerRegion *LLPathfindingManager::getCurrentRegion() const
-{
- return gAgent.getRegion();
-}
-
-//---------------------------------------------------------------------------
-// LLNavMeshSimStateChangeNode
-//---------------------------------------------------------------------------
-
-void LLNavMeshSimStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const
-{
- llassert(pInput.has(SIM_MESSAGE_BODY_FIELD));
- llassert(pInput.get(SIM_MESSAGE_BODY_FIELD).isMap());
- LLPathfindingNavMeshStatus navMeshStatus(pInput.get(SIM_MESSAGE_BODY_FIELD));
- LLPathfindingManager::getInstance()->handleNavMeshStatusUpdate(navMeshStatus);
-}
-
-//---------------------------------------------------------------------------
-// LLAgentStateChangeNode
-//---------------------------------------------------------------------------
-
-void LLAgentStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const
-{
- llassert(pInput.has(SIM_MESSAGE_BODY_FIELD));
- llassert(pInput.get(SIM_MESSAGE_BODY_FIELD).isMap());
- llassert(pInput.get(SIM_MESSAGE_BODY_FIELD).has(AGENT_STATE_CAN_REBAKE_REGION_FIELD));
- llassert(pInput.get(SIM_MESSAGE_BODY_FIELD).get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).isBoolean());
- bool canRebakeRegion = pInput.get(SIM_MESSAGE_BODY_FIELD).get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).asBoolean();
-
- LLPathfindingManager::getInstance()->handleAgentState(canRebakeRegion);
-}
-
-//---------------------------------------------------------------------------
-// LinksetsResponder
-//---------------------------------------------------------------------------
-LinksetsResponder::LinksetsResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pLinksetsCallback, bool pIsObjectRequested, bool pIsTerrainRequested)
- : mRequestId(pRequestId),
- mLinksetsCallback(pLinksetsCallback),
- mObjectMessagingState(pIsObjectRequested ? kWaiting : kNotRequested),
- mTerrainMessagingState(pIsTerrainRequested ? kWaiting : kNotRequested),
- mObjectLinksetListPtr(),
- mTerrainLinksetPtr()
-{
-}
-
-LinksetsResponder::~LinksetsResponder()
-{
-}
-
-void LinksetsResponder::handleObjectLinksetsResult(const LLSD &pContent)
-{
- mObjectLinksetListPtr = LLPathfindingObjectListPtr(new LLPathfindingLinksetList(pContent));
-
- mObjectMessagingState = kReceivedGood;
- if (mTerrainMessagingState != kWaiting)
- {
- sendCallback();
- }
-}
-
-void LinksetsResponder::handleObjectLinksetsError()
-{
- LL_WARNS() << "LinksetsResponder object linksets error" << LL_ENDL;
- mObjectMessagingState = kReceivedError;
- if (mTerrainMessagingState != kWaiting)
- {
- sendCallback();
- }
-}
-
-void LinksetsResponder::handleTerrainLinksetsResult(const LLSD &pContent)
-{
- mTerrainLinksetPtr = LLPathfindingObjectPtr(new LLPathfindingLinkset(pContent));
-
- mTerrainMessagingState = kReceivedGood;
- if (mObjectMessagingState != kWaiting)
- {
- sendCallback();
- }
-}
-
-void LinksetsResponder::handleTerrainLinksetsError()
-{
- LL_WARNS() << "LinksetsResponder terrain linksets error" << LL_ENDL;
- mTerrainMessagingState = kReceivedError;
- if (mObjectMessagingState != kWaiting)
- {
- sendCallback();
- }
-}
-
-void LinksetsResponder::sendCallback()
-{
- llassert(mObjectMessagingState != kWaiting);
- llassert(mTerrainMessagingState != kWaiting);
- LLPathfindingManager::ERequestStatus requestStatus =
- ((((mObjectMessagingState == kReceivedGood) || (mObjectMessagingState == kNotRequested)) &&
- ((mTerrainMessagingState == kReceivedGood) || (mTerrainMessagingState == kNotRequested))) ?
- LLPathfindingManager::kRequestCompleted : LLPathfindingManager::kRequestError);
-
- if (mObjectMessagingState != kReceivedGood)
- {
- mObjectLinksetListPtr = LLPathfindingObjectListPtr(new LLPathfindingLinksetList());
- }
-
- if (mTerrainMessagingState == kReceivedGood)
- {
- mObjectLinksetListPtr->update(mTerrainLinksetPtr);
- }
-
- mLinksetsCallback(mRequestId, requestStatus, mObjectLinksetListPtr);
-}
+/** +* @file llpathfindingmanager.cpp +* @brief Implementation of llpathfindingmanager +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + + +#include "llviewerprecompiledheaders.h" + +#include "llpathfindingmanager.h" + +#include <string> +#include <map> + +#include <boost/bind.hpp> +#include <boost/function.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/signals2.hpp> + +#include "llagent.h" +#include "llhttpnode.h" +#include "llnotificationsutil.h" +#include "llpathfindingcharacterlist.h" +#include "llpathfindinglinkset.h" +#include "llpathfindinglinksetlist.h" +#include "llpathfindingnavmesh.h" +#include "llpathfindingnavmeshstatus.h" +#include "llpathfindingobject.h" +#include "llpathinglib.h" +#include "llsingleton.h" +#include "llsd.h" +#include "lltrans.h" +#include "lluuid.h" +#include "llviewerregion.h" +#include "llweb.h" +#include "llcorehttputil.h" +#include "llworld.h" + +#define CAP_SERVICE_RETRIEVE_NAVMESH "RetrieveNavMeshSrc" + +#define CAP_SERVICE_NAVMESH_STATUS "NavMeshGenerationStatus" + +#define CAP_SERVICE_GET_OBJECT_LINKSETS "RegionObjects" +#define CAP_SERVICE_SET_OBJECT_LINKSETS "ObjectNavMeshProperties" +#define CAP_SERVICE_TERRAIN_LINKSETS "TerrainNavMeshProperties" + +#define CAP_SERVICE_CHARACTERS "CharacterProperties" + +#define SIM_MESSAGE_NAVMESH_STATUS_UPDATE "/message/NavMeshStatusUpdate" +#define SIM_MESSAGE_AGENT_STATE_UPDATE "/message/AgentStateUpdate" +#define SIM_MESSAGE_BODY_FIELD "body" + +#define CAP_SERVICE_AGENT_STATE "AgentState" + +#define AGENT_STATE_CAN_REBAKE_REGION_FIELD "can_modify_navmesh" + +//--------------------------------------------------------------------------- +// LLNavMeshSimStateChangeNode +//--------------------------------------------------------------------------- + +class LLNavMeshSimStateChangeNode : public LLHTTPNode +{ +public: + virtual void post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const; +}; + +LLHTTPRegistration<LLNavMeshSimStateChangeNode> gHTTPRegistrationNavMeshSimStateChangeNode(SIM_MESSAGE_NAVMESH_STATUS_UPDATE); + + +//--------------------------------------------------------------------------- +// LLAgentStateChangeNode +//--------------------------------------------------------------------------- +class LLAgentStateChangeNode : public LLHTTPNode +{ +public: + virtual void post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const; +}; + +LLHTTPRegistration<LLAgentStateChangeNode> gHTTPRegistrationAgentStateChangeNode(SIM_MESSAGE_AGENT_STATE_UPDATE); + +//--------------------------------------------------------------------------- +// LinksetsResponder +//--------------------------------------------------------------------------- + +class LinksetsResponder +{ +public: + LinksetsResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pLinksetsCallback, bool pIsObjectRequested, bool pIsTerrainRequested); + virtual ~LinksetsResponder(); + + void handleObjectLinksetsResult(const LLSD &pContent); + void handleObjectLinksetsError(); + void handleTerrainLinksetsResult(const LLSD &pContent); + void handleTerrainLinksetsError(); + + typedef std::shared_ptr<LinksetsResponder> ptr_t; + +protected: + +private: + void sendCallback(); + + typedef enum + { + kNotRequested, + kWaiting, + kReceivedGood, + kReceivedError + } EMessagingState; + + LLPathfindingManager::request_id_t mRequestId; + LLPathfindingManager::object_request_callback_t mLinksetsCallback; + + EMessagingState mObjectMessagingState; + EMessagingState mTerrainMessagingState; + + LLPathfindingObjectListPtr mObjectLinksetListPtr; + LLPathfindingObjectPtr mTerrainLinksetPtr; +}; + +typedef std::shared_ptr<LinksetsResponder> LinksetsResponderPtr; + +//--------------------------------------------------------------------------- +// LLPathfindingManager +//--------------------------------------------------------------------------- + +LLPathfindingManager::LLPathfindingManager(): + mNavMeshMap(), + mAgentStateSignal() +{ +} + +LLPathfindingManager::~LLPathfindingManager() +{ + quitSystem(); +} + +void LLPathfindingManager::initSystem() +{ + if (LLPathingLib::getInstance() == NULL) + { + LLPathingLib::initSystem(); + } +} + +void LLPathfindingManager::quitSystem() +{ + if (LLPathingLib::getInstance() != NULL) + { + LLPathingLib::quitSystem(); + } +} + +bool LLPathfindingManager::isPathfindingViewEnabled() const +{ + return (LLPathingLib::getInstance() != NULL); +} + +bool LLPathfindingManager::isPathfindingEnabledForCurrentRegion() const +{ + return isPathfindingEnabledForRegion(getCurrentRegion()); +} + +bool LLPathfindingManager::isPathfindingEnabledForRegion(LLViewerRegion *pRegion) const +{ + std::string retrieveNavMeshURL = getRetrieveNavMeshURLForRegion(pRegion); + return !retrieveNavMeshURL.empty(); +} + +bool LLPathfindingManager::isAllowViewTerrainProperties() const +{ + LLViewerRegion* region = getCurrentRegion(); + return (gAgent.isGodlike() || ((region != NULL) && region->canManageEstate())); +} + +LLPathfindingNavMesh::navmesh_slot_t LLPathfindingManager::registerNavMeshListenerForRegion(LLViewerRegion *pRegion, LLPathfindingNavMesh::navmesh_callback_t pNavMeshCallback) +{ + LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(pRegion); + return navMeshPtr->registerNavMeshListener(pNavMeshCallback); +} + +void LLPathfindingManager::requestGetNavMeshForRegion(LLViewerRegion *pRegion, bool pIsGetStatusOnly) +{ + LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(pRegion); + + if (pRegion == NULL) + { + navMeshPtr->handleNavMeshNotEnabled(); + } + else if (!pRegion->capabilitiesReceived()) + { + navMeshPtr->handleNavMeshWaitForRegionLoad(); + pRegion->setCapabilitiesReceivedCallback(boost::bind(&LLPathfindingManager::handleDeferredGetNavMeshForRegion, this, _1, pIsGetStatusOnly)); + } + else if (!isPathfindingEnabledForRegion(pRegion)) + { + navMeshPtr->handleNavMeshNotEnabled(); + } + else + { + std::string navMeshStatusURL = getNavMeshStatusURLForRegion(pRegion); + llassert(!navMeshStatusURL.empty()); + navMeshPtr->handleNavMeshCheckVersion(); + + U64 regionHandle = pRegion->getHandle(); + std::string coroname = LLCoros::instance().launch("LLPathfindingManager::navMeshStatusRequestCoro", + boost::bind(&LLPathfindingManager::navMeshStatusRequestCoro, this, navMeshStatusURL, regionHandle, pIsGetStatusOnly)); + } +} + +void LLPathfindingManager::requestGetLinksets(request_id_t pRequestId, object_request_callback_t pLinksetsCallback) const +{ + LLPathfindingObjectListPtr emptyLinksetListPtr; + LLViewerRegion *currentRegion = getCurrentRegion(); + + if (currentRegion == NULL) + { + pLinksetsCallback(pRequestId, kRequestNotEnabled, emptyLinksetListPtr); + } + else if (!currentRegion->capabilitiesReceived()) + { + pLinksetsCallback(pRequestId, kRequestStarted, emptyLinksetListPtr); + currentRegion->setCapabilitiesReceivedCallback(boost::bind(&LLPathfindingManager::handleDeferredGetLinksetsForRegion, this, _1, pRequestId, pLinksetsCallback)); + } + else + { + std::string objectLinksetsURL = getRetrieveObjectLinksetsURLForCurrentRegion(); + std::string terrainLinksetsURL = getTerrainLinksetsURLForCurrentRegion(); + if (objectLinksetsURL.empty() || terrainLinksetsURL.empty()) + { + pLinksetsCallback(pRequestId, kRequestNotEnabled, emptyLinksetListPtr); + } + else + { + pLinksetsCallback(pRequestId, kRequestStarted, emptyLinksetListPtr); + + bool doRequestTerrain = isAllowViewTerrainProperties(); + LinksetsResponder::ptr_t linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, true, doRequestTerrain)); + + std::string coroname = LLCoros::instance().launch("LLPathfindingManager::linksetObjectsCoro", + boost::bind(&LLPathfindingManager::linksetObjectsCoro, this, objectLinksetsURL, linksetsResponderPtr, LLSD())); + + if (doRequestTerrain) + { + std::string coroname = LLCoros::instance().launch("LLPathfindingManager::linksetTerrainCoro", + boost::bind(&LLPathfindingManager::linksetTerrainCoro, this, terrainLinksetsURL, linksetsResponderPtr, LLSD())); + } + } + } +} + +void LLPathfindingManager::requestSetLinksets(request_id_t pRequestId, const LLPathfindingObjectListPtr &pLinksetListPtr, LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD, object_request_callback_t pLinksetsCallback) const +{ + LLPathfindingObjectListPtr emptyLinksetListPtr; + + std::string objectLinksetsURL = getChangeObjectLinksetsURLForCurrentRegion(); + std::string terrainLinksetsURL = getTerrainLinksetsURLForCurrentRegion(); + if (objectLinksetsURL.empty() || terrainLinksetsURL.empty()) + { + pLinksetsCallback(pRequestId, kRequestNotEnabled, emptyLinksetListPtr); + } + else if ((pLinksetListPtr == NULL) || pLinksetListPtr->isEmpty()) + { + pLinksetsCallback(pRequestId, kRequestCompleted, emptyLinksetListPtr); + } + else + { + const LLPathfindingLinksetList *linksetList = dynamic_cast<const LLPathfindingLinksetList *>(pLinksetListPtr.get()); + + LLSD objectPostData = linksetList->encodeObjectFields(pLinksetUse, pA, pB, pC, pD); + LLSD terrainPostData; + if (isAllowViewTerrainProperties()) + { + terrainPostData = linksetList->encodeTerrainFields(pLinksetUse, pA, pB, pC, pD); + } + + if (objectPostData.isUndefined() && terrainPostData.isUndefined()) + { + pLinksetsCallback(pRequestId, kRequestCompleted, emptyLinksetListPtr); + } + else + { + pLinksetsCallback(pRequestId, kRequestStarted, emptyLinksetListPtr); + + LinksetsResponder::ptr_t linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, !objectPostData.isUndefined(), !terrainPostData.isUndefined())); + + if (!objectPostData.isUndefined()) + { + std::string coroname = LLCoros::instance().launch("LLPathfindingManager::linksetObjectsCoro", + boost::bind(&LLPathfindingManager::linksetObjectsCoro, this, objectLinksetsURL, linksetsResponderPtr, objectPostData)); + } + + if (!terrainPostData.isUndefined()) + { + std::string coroname = LLCoros::instance().launch("LLPathfindingManager::linksetTerrainCoro", + boost::bind(&LLPathfindingManager::linksetTerrainCoro, this, terrainLinksetsURL, linksetsResponderPtr, terrainPostData)); + } + } + } +} + +void LLPathfindingManager::requestGetCharacters(request_id_t pRequestId, object_request_callback_t pCharactersCallback) const +{ + LLPathfindingObjectListPtr emptyCharacterListPtr; + + LLViewerRegion *currentRegion = getCurrentRegion(); + + if (currentRegion == NULL) + { + pCharactersCallback(pRequestId, kRequestNotEnabled, emptyCharacterListPtr); + } + else if (!currentRegion->capabilitiesReceived()) + { + pCharactersCallback(pRequestId, kRequestStarted, emptyCharacterListPtr); + currentRegion->setCapabilitiesReceivedCallback(boost::bind(&LLPathfindingManager::handleDeferredGetCharactersForRegion, this, _1, pRequestId, pCharactersCallback)); + } + else + { + std::string charactersURL = getCharactersURLForCurrentRegion(); + if (charactersURL.empty()) + { + pCharactersCallback(pRequestId, kRequestNotEnabled, emptyCharacterListPtr); + } + else + { + pCharactersCallback(pRequestId, kRequestStarted, emptyCharacterListPtr); + + std::string coroname = LLCoros::instance().launch("LLPathfindingManager::charactersCoro", + boost::bind(&LLPathfindingManager::charactersCoro, this, charactersURL, pRequestId, pCharactersCallback)); + } + } +} + +LLPathfindingManager::agent_state_slot_t LLPathfindingManager::registerAgentStateListener(agent_state_callback_t pAgentStateCallback) +{ + return mAgentStateSignal.connect(pAgentStateCallback); +} + +void LLPathfindingManager::requestGetAgentState() +{ + LLViewerRegion *currentRegion = getCurrentRegion(); + + if (currentRegion == NULL) + { + mAgentStateSignal(false); + } + else + { + if (!currentRegion->capabilitiesReceived()) + { + currentRegion->setCapabilitiesReceivedCallback(boost::bind(&LLPathfindingManager::handleDeferredGetAgentStateForRegion, this, _1)); + } + else if (!isPathfindingEnabledForRegion(currentRegion)) + { + mAgentStateSignal(false); + } + else + { + std::string agentStateURL = getAgentStateURLForRegion(currentRegion); + llassert(!agentStateURL.empty()); + + std::string coroname = LLCoros::instance().launch("LLPathfindingManager::navAgentStateRequestCoro", + boost::bind(&LLPathfindingManager::navAgentStateRequestCoro, this, agentStateURL)); + } + } +} + +void LLPathfindingManager::requestRebakeNavMesh(rebake_navmesh_callback_t pRebakeNavMeshCallback) +{ + LLViewerRegion *currentRegion = getCurrentRegion(); + + if (currentRegion == NULL) + { + pRebakeNavMeshCallback(false); + } + else if (!isPathfindingEnabledForRegion(currentRegion)) + { + pRebakeNavMeshCallback(false); + } + else + { + std::string navMeshStatusURL = getNavMeshStatusURLForCurrentRegion(); + llassert(!navMeshStatusURL.empty()); + + std::string coroname = LLCoros::instance().launch("LLPathfindingManager::navMeshRebakeCoro", + boost::bind(&LLPathfindingManager::navMeshRebakeCoro, this, navMeshStatusURL, pRebakeNavMeshCallback)); + } +} + +void LLPathfindingManager::handleDeferredGetAgentStateForRegion(const LLUUID &pRegionUUID) +{ + LLViewerRegion *currentRegion = getCurrentRegion(); + + if ((currentRegion != NULL) && (currentRegion->getRegionID() == pRegionUUID)) + { + requestGetAgentState(); + } +} + +void LLPathfindingManager::handleDeferredGetNavMeshForRegion(const LLUUID &pRegionUUID, bool pIsGetStatusOnly) +{ + LLViewerRegion *currentRegion = getCurrentRegion(); + + if ((currentRegion != NULL) && (currentRegion->getRegionID() == pRegionUUID)) + { + requestGetNavMeshForRegion(currentRegion, pIsGetStatusOnly); + } +} + +void LLPathfindingManager::handleDeferredGetLinksetsForRegion(const LLUUID &pRegionUUID, request_id_t pRequestId, object_request_callback_t pLinksetsCallback) const +{ + LLViewerRegion *currentRegion = getCurrentRegion(); + + if ((currentRegion != NULL) && (currentRegion->getRegionID() == pRegionUUID)) + { + requestGetLinksets(pRequestId, pLinksetsCallback); + } +} + +void LLPathfindingManager::handleDeferredGetCharactersForRegion(const LLUUID &pRegionUUID, request_id_t pRequestId, object_request_callback_t pCharactersCallback) const +{ + LLViewerRegion *currentRegion = getCurrentRegion(); + + if ((currentRegion != NULL) && (currentRegion->getRegionID() == pRegionUUID)) + { + requestGetCharacters(pRequestId, pCharactersCallback); + } +} + +void LLPathfindingManager::navMeshStatusRequestCoro(std::string url, U64 regionHandle, bool isGetStatusOnly) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("NavMeshStatusRequest", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLViewerRegion *region = LLWorld::getInstance()->getRegionFromHandle(regionHandle); + if (!region) + { + LL_WARNS("PathfindingManager") << "Attempting to retrieve navmesh status for region that has gone away." << LL_ENDL; + return; + } + LLUUID regionUUID = region->getRegionID(); + + region = NULL; + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + region = LLWorld::getInstance()->getRegionFromHandle(regionHandle); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + LLPathfindingNavMeshStatus navMeshStatus(regionUUID); + if (!status) + { + LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() << + ". Building using empty status." << LL_ENDL; + } + else + { + result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS); + navMeshStatus = LLPathfindingNavMeshStatus(regionUUID, result); + } + + LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(regionUUID); + + if (!navMeshStatus.isValid()) + { + navMeshPtr->handleNavMeshError(); + return; + } + else if (navMeshPtr->hasNavMeshVersion(navMeshStatus)) + { + navMeshPtr->handleRefresh(navMeshStatus); + return; + } + else if (isGetStatusOnly) + { + navMeshPtr->handleNavMeshNewVersion(navMeshStatus); + return; + } + + if ((!region) || !region->isAlive()) + { + LL_WARNS("PathfindingManager") << "About to update navmesh status for region that has gone away." << LL_ENDL; + navMeshPtr->handleNavMeshNotEnabled(); + return; + } + + std::string navMeshURL = getRetrieveNavMeshURLForRegion(region); + + if (navMeshURL.empty()) + { + navMeshPtr->handleNavMeshNotEnabled(); + return; + } + + navMeshPtr->handleNavMeshStart(navMeshStatus); + + LLSD postData; + result = httpAdapter->postAndSuspend(httpRequest, navMeshURL, postData); + + U32 navMeshVersion = navMeshStatus.getVersion(); + + if (!status) + { + LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() << + ". reporting error." << LL_ENDL; + navMeshPtr->handleNavMeshError(navMeshVersion); + } + else + { + result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS); + navMeshPtr->handleNavMeshResult(result, navMeshVersion); + + } + +} + +void LLPathfindingManager::navAgentStateRequestCoro(std::string url) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("NavAgentStateRequest", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + bool canRebake = false; + if (!status) + { + LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() << + ". Building using empty status." << LL_ENDL; + } + else + { + llassert(result.has(AGENT_STATE_CAN_REBAKE_REGION_FIELD)); + llassert(result.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).isBoolean()); + canRebake = result.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).asBoolean(); + } + + handleAgentState(canRebake); +} + +void LLPathfindingManager::navMeshRebakeCoro(std::string url, rebake_navmesh_callback_t rebakeNavMeshCallback) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("NavMeshRebake", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + + LLSD postData = LLSD::emptyMap(); + postData["command"] = "rebuild"; + + LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + bool success = true; + if (!status) + { + LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() << + ". Rebake failed." << LL_ENDL; + success = false; + } + + rebakeNavMeshCallback(success); +} + +// If called with putData undefined this coroutine will issue a get. If there +// is data in putData it will be PUT to the URL. +void LLPathfindingManager::linksetObjectsCoro(std::string url, LinksetsResponder::ptr_t linksetsResponsderPtr, LLSD putData) const +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("LinksetObjects", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD result; + + if (putData.isUndefined()) + { + result = httpAdapter->getAndSuspend(httpRequest, url); + } + else + { + result = httpAdapter->putAndSuspend(httpRequest, url, putData); + } + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() << + ". linksetObjects failed." << LL_ENDL; + linksetsResponsderPtr->handleObjectLinksetsError(); + } + else + { + result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS); + linksetsResponsderPtr->handleObjectLinksetsResult(result); + } +} + +// If called with putData undefined this coroutine will issue a GET. If there +// is data in putData it will be PUT to the URL. +void LLPathfindingManager::linksetTerrainCoro(std::string url, LinksetsResponder::ptr_t linksetsResponsderPtr, LLSD putData) const +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("LinksetTerrain", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD result; + + if (putData.isUndefined()) + { + result = httpAdapter->getAndSuspend(httpRequest, url); + } + else + { + result = httpAdapter->putAndSuspend(httpRequest, url, putData); + } + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() << + ". linksetTerrain failed." << LL_ENDL; + linksetsResponsderPtr->handleTerrainLinksetsError(); + } + else + { + result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS); + linksetsResponsderPtr->handleTerrainLinksetsResult(result); + } + +} + +void LLPathfindingManager::charactersCoro(std::string url, request_id_t requestId, object_request_callback_t callback) const +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("LinksetTerrain", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() << + ". characters failed." << LL_ENDL; + + LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList()); + callback(requestId, LLPathfindingManager::kRequestError, characterListPtr); + } + else + { + result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS); + LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(result)); + callback(requestId, LLPathfindingManager::kRequestCompleted, characterListPtr); + } +} + +void LLPathfindingManager::handleNavMeshStatusUpdate(const LLPathfindingNavMeshStatus &pNavMeshStatus) +{ + LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(pNavMeshStatus.getRegionUUID()); + + if (!pNavMeshStatus.isValid()) + { + navMeshPtr->handleNavMeshError(); + } + else + { + navMeshPtr->handleNavMeshNewVersion(pNavMeshStatus); + } +} + +void LLPathfindingManager::handleAgentState(bool pCanRebakeRegion) +{ + mAgentStateSignal(pCanRebakeRegion); +} + +LLPathfindingNavMeshPtr LLPathfindingManager::getNavMeshForRegion(const LLUUID &pRegionUUID) +{ + LLPathfindingNavMeshPtr navMeshPtr; + NavMeshMap::iterator navMeshIter = mNavMeshMap.find(pRegionUUID); + if (navMeshIter == mNavMeshMap.end()) + { + navMeshPtr = LLPathfindingNavMeshPtr(new LLPathfindingNavMesh(pRegionUUID)); + mNavMeshMap.insert(std::pair<LLUUID, LLPathfindingNavMeshPtr>(pRegionUUID, navMeshPtr)); + } + else + { + navMeshPtr = navMeshIter->second; + } + + return navMeshPtr; +} + +LLPathfindingNavMeshPtr LLPathfindingManager::getNavMeshForRegion(LLViewerRegion *pRegion) +{ + LLUUID regionUUID; + if (pRegion != NULL) + { + regionUUID = pRegion->getRegionID(); + } + + return getNavMeshForRegion(regionUUID); +} + +std::string LLPathfindingManager::getNavMeshStatusURLForCurrentRegion() const +{ + return getNavMeshStatusURLForRegion(getCurrentRegion()); +} + +std::string LLPathfindingManager::getNavMeshStatusURLForRegion(LLViewerRegion *pRegion) const +{ + return getCapabilityURLForRegion(pRegion, CAP_SERVICE_NAVMESH_STATUS); +} + +std::string LLPathfindingManager::getRetrieveNavMeshURLForRegion(LLViewerRegion *pRegion) const +{ + return getCapabilityURLForRegion(pRegion, CAP_SERVICE_RETRIEVE_NAVMESH); +} + +std::string LLPathfindingManager::getRetrieveObjectLinksetsURLForCurrentRegion() const +{ + return getCapabilityURLForCurrentRegion(CAP_SERVICE_GET_OBJECT_LINKSETS); +} + +std::string LLPathfindingManager::getChangeObjectLinksetsURLForCurrentRegion() const +{ + return getCapabilityURLForCurrentRegion(CAP_SERVICE_SET_OBJECT_LINKSETS); +} + +std::string LLPathfindingManager::getTerrainLinksetsURLForCurrentRegion() const +{ + return getCapabilityURLForCurrentRegion(CAP_SERVICE_TERRAIN_LINKSETS); +} + +std::string LLPathfindingManager::getCharactersURLForCurrentRegion() const +{ + return getCapabilityURLForCurrentRegion(CAP_SERVICE_CHARACTERS); +} + +std::string LLPathfindingManager::getAgentStateURLForRegion(LLViewerRegion *pRegion) const +{ + return getCapabilityURLForRegion(pRegion, CAP_SERVICE_AGENT_STATE); +} + +std::string LLPathfindingManager::getCapabilityURLForCurrentRegion(const std::string &pCapabilityName) const +{ + return getCapabilityURLForRegion(getCurrentRegion(), pCapabilityName); +} + +std::string LLPathfindingManager::getCapabilityURLForRegion(LLViewerRegion *pRegion, const std::string &pCapabilityName) const +{ + std::string capabilityURL(""); + + if (pRegion != NULL) + { + capabilityURL = pRegion->getCapability(pCapabilityName); + } + + if (capabilityURL.empty()) + { + LL_WARNS() << "cannot find capability '" << pCapabilityName << "' for current region '" + << ((pRegion != NULL) ? pRegion->getName() : "<null>") << "'" << LL_ENDL; + } + + return capabilityURL; +} + +LLViewerRegion *LLPathfindingManager::getCurrentRegion() const +{ + return gAgent.getRegion(); +} + +//--------------------------------------------------------------------------- +// LLNavMeshSimStateChangeNode +//--------------------------------------------------------------------------- + +void LLNavMeshSimStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const +{ + llassert(pInput.has(SIM_MESSAGE_BODY_FIELD)); + llassert(pInput.get(SIM_MESSAGE_BODY_FIELD).isMap()); + LLPathfindingNavMeshStatus navMeshStatus(pInput.get(SIM_MESSAGE_BODY_FIELD)); + LLPathfindingManager::getInstance()->handleNavMeshStatusUpdate(navMeshStatus); +} + +//--------------------------------------------------------------------------- +// LLAgentStateChangeNode +//--------------------------------------------------------------------------- + +void LLAgentStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const +{ + llassert(pInput.has(SIM_MESSAGE_BODY_FIELD)); + llassert(pInput.get(SIM_MESSAGE_BODY_FIELD).isMap()); + llassert(pInput.get(SIM_MESSAGE_BODY_FIELD).has(AGENT_STATE_CAN_REBAKE_REGION_FIELD)); + llassert(pInput.get(SIM_MESSAGE_BODY_FIELD).get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).isBoolean()); + bool canRebakeRegion = pInput.get(SIM_MESSAGE_BODY_FIELD).get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).asBoolean(); + + LLPathfindingManager::getInstance()->handleAgentState(canRebakeRegion); +} + +//--------------------------------------------------------------------------- +// LinksetsResponder +//--------------------------------------------------------------------------- +LinksetsResponder::LinksetsResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pLinksetsCallback, bool pIsObjectRequested, bool pIsTerrainRequested) + : mRequestId(pRequestId), + mLinksetsCallback(pLinksetsCallback), + mObjectMessagingState(pIsObjectRequested ? kWaiting : kNotRequested), + mTerrainMessagingState(pIsTerrainRequested ? kWaiting : kNotRequested), + mObjectLinksetListPtr(), + mTerrainLinksetPtr() +{ +} + +LinksetsResponder::~LinksetsResponder() +{ +} + +void LinksetsResponder::handleObjectLinksetsResult(const LLSD &pContent) +{ + mObjectLinksetListPtr = LLPathfindingObjectListPtr(new LLPathfindingLinksetList(pContent)); + + mObjectMessagingState = kReceivedGood; + if (mTerrainMessagingState != kWaiting) + { + sendCallback(); + } +} + +void LinksetsResponder::handleObjectLinksetsError() +{ + LL_WARNS() << "LinksetsResponder object linksets error" << LL_ENDL; + mObjectMessagingState = kReceivedError; + if (mTerrainMessagingState != kWaiting) + { + sendCallback(); + } +} + +void LinksetsResponder::handleTerrainLinksetsResult(const LLSD &pContent) +{ + mTerrainLinksetPtr = LLPathfindingObjectPtr(new LLPathfindingLinkset(pContent)); + + mTerrainMessagingState = kReceivedGood; + if (mObjectMessagingState != kWaiting) + { + sendCallback(); + } +} + +void LinksetsResponder::handleTerrainLinksetsError() +{ + LL_WARNS() << "LinksetsResponder terrain linksets error" << LL_ENDL; + mTerrainMessagingState = kReceivedError; + if (mObjectMessagingState != kWaiting) + { + sendCallback(); + } +} + +void LinksetsResponder::sendCallback() +{ + llassert(mObjectMessagingState != kWaiting); + llassert(mTerrainMessagingState != kWaiting); + LLPathfindingManager::ERequestStatus requestStatus = + ((((mObjectMessagingState == kReceivedGood) || (mObjectMessagingState == kNotRequested)) && + ((mTerrainMessagingState == kReceivedGood) || (mTerrainMessagingState == kNotRequested))) ? + LLPathfindingManager::kRequestCompleted : LLPathfindingManager::kRequestError); + + if (mObjectMessagingState != kReceivedGood) + { + mObjectLinksetListPtr = LLPathfindingObjectListPtr(new LLPathfindingLinksetList()); + } + + if (mTerrainMessagingState == kReceivedGood) + { + mObjectLinksetListPtr->update(mTerrainLinksetPtr); + } + + mLinksetsCallback(mRequestId, requestStatus, mObjectLinksetListPtr); +} |
