llpathfindingmanager.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. /**
  2. * @file llpathfindingmanager.cpp
  3. * @brief Implementation of llpathfindingmanager
  4. *
  5. * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2012, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llpathfindingmanager.h"
  28. #include "llapp.h"
  29. #include "llcorehttputil.h"
  30. #include "llhttpnode.h"
  31. #if HAVE_PATHINGLIB
  32. #include "llpathinglib.h"
  33. #endif
  34. #include "llsd.h"
  35. #include "lltrans.h"
  36. #include "llagent.h"
  37. #include "llpathfindingcharacterlist.h"
  38. #include "llpathfindinglinkset.h"
  39. #include "llpathfindinglinksetlist.h"
  40. #include "llpathfindingnavmesh.h"
  41. #include "llpathfindingnavmeshstatus.h"
  42. #include "llstartup.h" // For getStartupState()
  43. #include "llviewerregion.h"
  44. #include "llweb.h"
  45. #include "llworld.h"
  46. //---------------------------------------------------------------------------
  47. // LLNavMeshSimStateChangeNode
  48. //---------------------------------------------------------------------------
  49. class LLNavMeshSimStateChangeNode final : public LLHTTPNode
  50. {
  51. protected:
  52. LOG_CLASS(LLNavMeshSimStateChangeNode);
  53. public:
  54. void post(ResponsePtr response, const LLSD& context,
  55. const LLSD& input) const override;
  56. };
  57. LLHTTPRegistration<LLNavMeshSimStateChangeNode>
  58. gHTTPRegistrationNavMeshSimStateChangeNode("/message/NavMeshStatusUpdate");
  59. //---------------------------------------------------------------------------
  60. // LLAgentStateChangeNode
  61. //---------------------------------------------------------------------------
  62. class LLAgentStateChangeNode final : public LLHTTPNode
  63. {
  64. protected:
  65. LOG_CLASS(LLAgentStateChangeNode);
  66. public:
  67. void post(ResponsePtr response, const LLSD& context,
  68. const LLSD& input) const override;
  69. };
  70. LLHTTPRegistration<LLAgentStateChangeNode>
  71. gHTTPRegistrationAgentStateChangeNode("/message/AgentStateUpdate");
  72. //---------------------------------------------------------------------------
  73. // LinksetsResponder
  74. //---------------------------------------------------------------------------
  75. class LinksetsResponder
  76. {
  77. public:
  78. LinksetsResponder(LLPathfindingManager::request_id_t req_id,
  79. LLPathfindingManager::object_request_cb_t cb,
  80. bool object_requested, bool terrain_requested);
  81. void handleObjectLinksetsResult(const LLSD& content);
  82. void handleObjectLinksetsError();
  83. void handleTerrainLinksetsResult(const LLSD& content);
  84. void handleTerrainLinksetsError();
  85. typedef std::shared_ptr<LinksetsResponder> ptr_t;
  86. private:
  87. void sendCallback();
  88. private:
  89. LLPathfindingManager::request_id_t mRequestId;
  90. LLPathfindingManager::object_request_cb_t mLinksetsCallback;
  91. LLPathfindingObjectList::ptr_t mObjectLinksetListPtr;
  92. LLPathfindingObject::ptr_t mTerrainLinksetPtr;
  93. typedef enum
  94. {
  95. kNotRequested,
  96. kWaiting,
  97. kReceivedGood,
  98. kReceivedError
  99. } EMessagingState;
  100. EMessagingState mObjectMessagingState;
  101. EMessagingState mTerrainMessagingState;
  102. };
  103. //---------------------------------------------------------------------------
  104. // LLPathfindingManager
  105. //---------------------------------------------------------------------------
  106. LLPathfindingManager::LLPathfindingManager()
  107. : LLSingleton<LLPathfindingManager>(),
  108. mAgentStateSignal(),
  109. // NOTE: by using these instead of omitting the corresponding
  110. // xxxAndSuspend() parameters, we avoid seeing such classes constructed
  111. // and destroyed each time...
  112. mHttpOptions(DEFAULT_HTTP_OPTIONS),
  113. mHttpHeaders(DEFAULT_HTTP_HEADERS)
  114. {
  115. #if HAVE_PATHINGLIB
  116. if (!LLPathingLib::getInstance())
  117. {
  118. LLPathingLib::initSystem();
  119. }
  120. #endif
  121. }
  122. LLPathfindingManager::~LLPathfindingManager()
  123. {
  124. mHttpOptions.reset();
  125. mHttpHeaders.reset();
  126. #if HAVE_PATHINGLIB
  127. if (LLPathingLib::getInstance())
  128. {
  129. LLPathingLib::quitSystem();
  130. }
  131. #endif
  132. }
  133. #if HAVE_PATHINGLIB
  134. bool LLPathfindingManager::isPathfindingViewEnabled() const
  135. {
  136. return LLPathingLib::getInstance() != NULL;
  137. }
  138. #endif
  139. bool LLPathfindingManager::isPathfindingEnabledForCurrentRegion() const
  140. {
  141. return isPathfindingEnabledForRegion(gAgent.getRegion());
  142. }
  143. bool LLPathfindingManager::isPathfindingEnabledForRegion(LLViewerRegion* region) const
  144. {
  145. return region && !region->getCapability("RetrieveNavMeshSrc").empty();
  146. }
  147. bool LLPathfindingManager::isAllowViewTerrainProperties() const
  148. {
  149. LLViewerRegion* region = gAgent.getRegion();
  150. return gAgent.isGodlike() || (region && region->canManageEstate());
  151. }
  152. LLPathfindingNavMesh::navmesh_slot_t
  153. LLPathfindingManager::registerNavMeshListenerForRegion(LLViewerRegion* region,
  154. LLPathfindingNavMesh::navmesh_cb_t cb)
  155. {
  156. LLPathfindingNavMesh::ptr_t navmeshp = getNavMeshForRegion(region);
  157. return navmeshp->registerNavMeshListener(cb);
  158. }
  159. void LLPathfindingManager::requestGetNavMeshForRegion(LLViewerRegion* region,
  160. bool get_status_only)
  161. {
  162. LLPathfindingNavMesh::ptr_t navmeshp = getNavMeshForRegion(region);
  163. if (!region)
  164. {
  165. navmeshp->handleNavMeshNotEnabled();
  166. return;
  167. }
  168. if (!region->capabilitiesReceived())
  169. {
  170. navmeshp->handleNavMeshWaitForRegionLoad();
  171. region->setCapsReceivedCB(boost::bind(&LLPathfindingManager::handleDeferredGetNavMeshForRegion,
  172. this, _1, get_status_only));
  173. return;
  174. }
  175. if (!isPathfindingEnabledForRegion(region))
  176. {
  177. navmeshp->handleNavMeshNotEnabled();
  178. return;
  179. }
  180. std::string status_url = getNavMeshStatusURLForRegion(region);
  181. if (status_url.empty())
  182. {
  183. llassert(false);
  184. return;
  185. }
  186. navmeshp->handleNavMeshCheckVersion();
  187. gCoros.launch("LLPathfindingManager::navMeshStatusRequestCoro",
  188. boost::bind(&LLPathfindingManager::navMeshStatusRequestCoro,
  189. this, status_url, region->getHandle(),
  190. get_status_only));
  191. }
  192. void LLPathfindingManager::requestGetLinksets(request_id_t req_id,
  193. object_request_cb_t cb) const
  194. {
  195. LLPathfindingObjectList::ptr_t empty_linkset_list;
  196. LLViewerRegion* region = gAgent.getRegion();
  197. if (!region)
  198. {
  199. cb(req_id, kRequestNotEnabled, empty_linkset_list);
  200. return;
  201. }
  202. if (!region->capabilitiesReceived())
  203. {
  204. cb(req_id, kRequestStarted, empty_linkset_list);
  205. region->setCapsReceivedCB(boost::bind(&LLPathfindingManager::handleDeferredGetLinksetsForRegion,
  206. this, _1, req_id, cb));
  207. return;
  208. }
  209. std::string object_url = getRetrieveObjectLinksetsURLForCurrentRegion();
  210. std::string terrain_url = getTerrainLinksetsURLForCurrentRegion();
  211. if (object_url.empty() || terrain_url.empty())
  212. {
  213. cb(req_id, kRequestNotEnabled, empty_linkset_list);
  214. return;
  215. }
  216. cb(req_id, kRequestStarted, empty_linkset_list);
  217. bool with_terrain = isAllowViewTerrainProperties();
  218. LinksetsResponder::ptr_t responder(new LinksetsResponder(req_id, cb, true,
  219. with_terrain));
  220. gCoros.launch("LLPathfindingManager::linksetObjectsCoro",
  221. boost::bind(&LLPathfindingManager::linksetObjectsCoro, this,
  222. object_url, responder, LLSD()));
  223. if (with_terrain)
  224. {
  225. gCoros.launch("LLPathfindingManager::linksetTerrainCoro",
  226. boost::bind(&LLPathfindingManager::linksetTerrainCoro,
  227. this, terrain_url, responder, LLSD()));
  228. }
  229. }
  230. void LLPathfindingManager::requestSetLinksets(request_id_t req_id,
  231. const LLPathfindingObjectList::ptr_t& pobjects,
  232. LLPathfindingLinkset::ELinksetUse use,
  233. S32 a, S32 b, S32 c, S32 d,
  234. object_request_cb_t cb) const
  235. {
  236. LLPathfindingObjectList::ptr_t empty_linkset_list;
  237. std::string object_url = getChangeObjectLinksetsURLForCurrentRegion();
  238. std::string terrain_url = getTerrainLinksetsURLForCurrentRegion();
  239. if (object_url.empty() || terrain_url.empty())
  240. {
  241. cb(req_id, kRequestNotEnabled, empty_linkset_list);
  242. return;
  243. }
  244. if (!pobjects || pobjects->isEmpty())
  245. {
  246. cb(req_id, kRequestCompleted, empty_linkset_list);
  247. return;
  248. }
  249. const LLPathfindingLinksetList* list = pobjects.get()->asLinksetList();
  250. if (!list)
  251. {
  252. llassert(false);
  253. return;
  254. }
  255. LLSD object_data = list->encodeObjectFields(use, a, b, c, d);
  256. LLSD terrain_data;
  257. if (isAllowViewTerrainProperties())
  258. {
  259. terrain_data = list->encodeTerrainFields(use, a, b, c, d);
  260. }
  261. bool got_object = !object_data.isUndefined();
  262. bool got_terrain = !terrain_data.isUndefined();
  263. if (!got_object && !got_terrain)
  264. {
  265. cb(req_id, kRequestCompleted, empty_linkset_list);
  266. return;
  267. }
  268. cb(req_id, kRequestStarted, empty_linkset_list);
  269. LinksetsResponder::ptr_t responder(new LinksetsResponder(req_id, cb,
  270. got_object,
  271. got_terrain));
  272. if (got_object)
  273. {
  274. gCoros.launch("LLPathfindingManager::linksetObjectsCoro",
  275. boost::bind(&LLPathfindingManager::linksetObjectsCoro,
  276. this, object_url, responder, object_data));
  277. }
  278. if (got_terrain)
  279. {
  280. gCoros.launch("LLPathfindingManager::linksetTerrainCoro",
  281. boost::bind(&LLPathfindingManager::linksetTerrainCoro,
  282. this, terrain_url, responder, terrain_data));
  283. }
  284. }
  285. void LLPathfindingManager::requestGetCharacters(request_id_t req_id,
  286. object_request_cb_t cb) const
  287. {
  288. LLPathfindingObjectList::ptr_t empty_char_list;
  289. LLViewerRegion* region = gAgent.getRegion();
  290. if (!region)
  291. {
  292. cb(req_id, kRequestNotEnabled, empty_char_list);
  293. return;
  294. }
  295. if (!region->capabilitiesReceived())
  296. {
  297. cb(req_id, kRequestStarted, empty_char_list);
  298. region->setCapsReceivedCB(boost::bind(&LLPathfindingManager::handleDeferredGetCharactersForRegion,
  299. this, _1, req_id, cb));
  300. return;
  301. }
  302. std::string char_url = getCharactersURLForCurrentRegion();
  303. if (char_url.empty())
  304. {
  305. cb(req_id, kRequestNotEnabled, empty_char_list);
  306. return;
  307. }
  308. cb(req_id, kRequestStarted, empty_char_list);
  309. gCoros.launch("LLPathfindingManager::charactersCoro",
  310. boost::bind(&LLPathfindingManager::charactersCoro,
  311. this, char_url, req_id, cb));
  312. }
  313. LLPathfindingManager::agent_state_slot_t LLPathfindingManager::registerAgentStateListener(agent_state_cb_t cb)
  314. {
  315. return mAgentStateSignal.connect(cb);
  316. }
  317. void LLPathfindingManager::requestGetAgentState()
  318. {
  319. LLViewerRegion* region = gAgent.getRegion();
  320. if (!region)
  321. {
  322. mAgentStateSignal(false);
  323. return;
  324. }
  325. if (!region->capabilitiesReceived())
  326. {
  327. region->setCapsReceivedCB(boost::bind(&LLPathfindingManager::handleDeferredGetAgentStateForRegion,
  328. this, _1));
  329. return;
  330. }
  331. if (!isPathfindingEnabledForRegion(region))
  332. {
  333. mAgentStateSignal(false);
  334. return;
  335. }
  336. std::string agent_url = getAgentStateURLForRegion(region);
  337. if (agent_url.empty())
  338. {
  339. llassert(false);
  340. llwarns << "Missing agent state capability !" << llendl;
  341. return;
  342. }
  343. gCoros.launch("LLPathfindingManager::navAgentStateRequestCoro",
  344. boost::bind(&LLPathfindingManager::navAgentStateRequestCoro,
  345. this, agent_url));
  346. }
  347. void LLPathfindingManager::requestRebakeNavMesh(rebake_navmesh_cb_t cb)
  348. {
  349. LLViewerRegion* region = gAgent.getRegion();
  350. if (!region || !isPathfindingEnabledForRegion(region))
  351. {
  352. cb(false);
  353. return;
  354. }
  355. std::string status_url = getNavMeshStatusURLForCurrentRegion();
  356. if (status_url.empty())
  357. {
  358. return;
  359. }
  360. gCoros.launch("LLPathfindingManager::navMeshRebakeCoro",
  361. boost::bind(&LLPathfindingManager::navMeshRebakeCoro,
  362. this, status_url, cb));
  363. }
  364. void LLPathfindingManager::handleDeferredGetAgentStateForRegion(const LLUUID& region_id)
  365. {
  366. LLViewerRegion* region = gAgent.getRegion();
  367. if (region && region->getRegionID() == region_id)
  368. {
  369. requestGetAgentState();
  370. }
  371. }
  372. void LLPathfindingManager::handleDeferredGetNavMeshForRegion(const LLUUID& region_id,
  373. bool get_status_only)
  374. {
  375. LLViewerRegion* region = gAgent.getRegion();
  376. if (region && region->getRegionID() == region_id)
  377. {
  378. requestGetNavMeshForRegion(region, get_status_only);
  379. }
  380. }
  381. void LLPathfindingManager::handleDeferredGetLinksetsForRegion(const LLUUID& region_id,
  382. request_id_t req_id,
  383. object_request_cb_t cb) const
  384. {
  385. LLViewerRegion* region = gAgent.getRegion();
  386. if (region && region->getRegionID() == region_id)
  387. {
  388. requestGetLinksets(req_id, cb);
  389. }
  390. }
  391. void LLPathfindingManager::handleDeferredGetCharactersForRegion(const LLUUID& region_id,
  392. request_id_t req_id,
  393. object_request_cb_t cb) const
  394. {
  395. LLViewerRegion* region = gAgent.getRegion();
  396. if (region && region->getRegionID() == region_id)
  397. {
  398. requestGetCharacters(req_id, cb);
  399. }
  400. }
  401. void LLPathfindingManager::navMeshStatusRequestCoro(const std::string& url,
  402. U64 region_handle,
  403. bool get_status_only)
  404. {
  405. LLViewerRegion* region = gWorld.getRegionFromHandle(region_handle);
  406. if (!region || !region->isAlive())
  407. {
  408. // No agent region is set before the STATE_WORLD_INIT step has been
  409. // completed, and login region goes "live" only at SATE_STARTED, so
  410. // only emit a warning when fully logged in.
  411. if (LLStartUp::isLoggedIn())
  412. {
  413. llwarns << "Region is gone. Navmesh status request aborted."
  414. << llendl;
  415. }
  416. return;
  417. }
  418. LLCoreHttpUtil::HttpCoroutineAdapter adapter("NavMeshStatusRequest");
  419. LLSD result = adapter.getAndSuspend(url, mHttpOptions, mHttpHeaders);
  420. if (!instanceExists() || LLApp::isExiting())
  421. {
  422. return; // Viewer is being closed down !
  423. }
  424. region = gWorld.getRegionFromHandle(region_handle);
  425. if (!region || !region->isAlive())
  426. {
  427. llwarns << "Region is gone. Ignoring response." << llendl;
  428. return;
  429. }
  430. LLCore::HttpStatus status =
  431. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  432. if (!status)
  433. {
  434. llwarns << "Navmesh status request failed (1): " << status.toString()
  435. << llendl;
  436. return;
  437. }
  438. LLUUID region_id = region->getRegionID();
  439. LLPathfindingNavMeshStatus nmstatus(region_id);
  440. result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
  441. LL_DEBUGS("NavMesh") << "Results (1): " << result << LL_ENDL;
  442. nmstatus = LLPathfindingNavMeshStatus(region_id, result);
  443. LLPathfindingNavMesh::ptr_t navmeshp = getNavMeshForRegion(region_id);
  444. if (!nmstatus.isValid())
  445. {
  446. navmeshp->handleNavMeshError();
  447. return;
  448. }
  449. if (navmeshp->hasNavMeshVersion(nmstatus))
  450. {
  451. navmeshp->handleRefresh(nmstatus);
  452. return;
  453. }
  454. if (get_status_only)
  455. {
  456. navmeshp->handleNavMeshNewVersion(nmstatus);
  457. return;
  458. }
  459. std::string nav_mesh_url = getRetrieveNavMeshURLForRegion(region);
  460. if (nav_mesh_url.empty())
  461. {
  462. navmeshp->handleNavMeshNotEnabled();
  463. return;
  464. }
  465. navmeshp->handleNavMeshStart(nmstatus);
  466. LLSD post_data;
  467. result = adapter.postAndSuspend(nav_mesh_url, post_data, mHttpOptions,
  468. mHttpHeaders);
  469. if (!instanceExists() || LLApp::isExiting())
  470. {
  471. return; // Viewer is being closed down !
  472. }
  473. status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  474. region = gWorld.getRegionFromHandle(region_handle);
  475. if (!region || !region->isAlive())
  476. {
  477. llwarns << "Region is gone (2). Flaging navmesh as disabled."
  478. << llendl;
  479. navmeshp->handleNavMeshNotEnabled();
  480. return;
  481. }
  482. U32 version = nmstatus.getVersion();
  483. if (status)
  484. {
  485. result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
  486. LL_DEBUGS("NavMesh") << "Results (2): " << result << LL_ENDL;
  487. navmeshp->handleNavMeshResult(result, version);
  488. }
  489. else
  490. {
  491. llwarns << "Navmesh status request failed (2): " << status.toString()
  492. << llendl;
  493. navmeshp->handleNavMeshError(version);
  494. }
  495. }
  496. void LLPathfindingManager::navAgentStateRequestCoro(const std::string& url)
  497. {
  498. LLCoreHttpUtil::HttpCoroutineAdapter adapter("NavAgentStateRequest");
  499. LLSD result = adapter.getAndSuspend(url, mHttpOptions, mHttpHeaders);
  500. if (!instanceExists() || LLApp::isExiting())
  501. {
  502. return; // Viewer is being closed down !
  503. }
  504. bool can_rebake = false;
  505. LLCore::HttpStatus status =
  506. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  507. if (status)
  508. {
  509. if (result.has("can_modify_navmesh") &&
  510. result.get("can_modify_navmesh").isBoolean())
  511. {
  512. can_rebake = result["can_modify_navmesh"].asBoolean();
  513. }
  514. else
  515. {
  516. llwarns << "Malformed agent state response: " << result << llendl;
  517. }
  518. }
  519. else
  520. {
  521. llwarns << "Agent state request failed: " << status.toString()
  522. << llendl;
  523. }
  524. handleAgentState(can_rebake);
  525. }
  526. void LLPathfindingManager::navMeshRebakeCoro(const std::string& url,
  527. rebake_navmesh_cb_t cd)
  528. {
  529. LLSD post_data = LLSD::emptyMap();
  530. post_data["command"] = "rebuild";
  531. LLCoreHttpUtil::HttpCoroutineAdapter adapter("NavMeshRebake");
  532. LLSD result = adapter.postAndSuspend(url, post_data, mHttpOptions,
  533. mHttpHeaders);
  534. if (!instanceExists() || LLApp::isExiting())
  535. {
  536. return; // Viewer is being closed down !
  537. }
  538. bool success = true;
  539. LLCore::HttpStatus status =
  540. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  541. if (!status)
  542. {
  543. llwarns << "Navmesh rebake request failed: " << status.toString()
  544. << llendl;
  545. success = false;
  546. }
  547. cd(success);
  548. }
  549. // If called with put_data undefined this coroutine will issue a get. If there
  550. // is data in put_data it will be PUT to the URL.
  551. void LLPathfindingManager::linksetObjectsCoro(const std::string& url,
  552. LinksetsResponder::ptr_t responder,
  553. LLSD put_data) const
  554. {
  555. LLCoreHttpUtil::HttpCoroutineAdapter adapter("LinksetObjects");
  556. LLSD result;
  557. if (put_data.isUndefined())
  558. {
  559. result = adapter.getAndSuspend(url, mHttpOptions, mHttpHeaders);
  560. }
  561. else
  562. {
  563. result = adapter.putAndSuspend(url, put_data, mHttpOptions,
  564. mHttpHeaders);
  565. }
  566. if (!instanceExists() || LLApp::isExiting())
  567. {
  568. return; // Viewer is being closed down !
  569. }
  570. LLCore::HttpStatus status =
  571. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  572. if (status)
  573. {
  574. result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
  575. LL_DEBUGS("NavMesh") << "Results: " << result << LL_ENDL;
  576. responder->handleObjectLinksetsResult(result);
  577. }
  578. else
  579. {
  580. llwarns << "Linkset objects request failed: " << status.toString()
  581. << llendl;
  582. responder->handleObjectLinksetsError();
  583. }
  584. }
  585. // If called with put_data undefined this coroutine will issue a GET. If there
  586. // is data in put_data it will be PUT to the URL.
  587. void LLPathfindingManager::linksetTerrainCoro(const std::string& url,
  588. LinksetsResponder::ptr_t responder,
  589. LLSD put_data) const
  590. {
  591. LLCoreHttpUtil::HttpCoroutineAdapter adapter("LinksetTerrain");
  592. LLSD result;
  593. if (put_data.isUndefined())
  594. {
  595. result = adapter.getAndSuspend(url, mHttpOptions, mHttpHeaders);
  596. }
  597. else
  598. {
  599. result = adapter.putAndSuspend(url, put_data, mHttpOptions,
  600. mHttpHeaders);
  601. }
  602. if (!instanceExists() || LLApp::isExiting())
  603. {
  604. return; // Viewer is being closed down !
  605. }
  606. LLCore::HttpStatus status =
  607. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  608. if (status)
  609. {
  610. result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
  611. LL_DEBUGS("NavMesh") << "Results: " << result << LL_ENDL;
  612. responder->handleTerrainLinksetsResult(result);
  613. }
  614. else
  615. {
  616. llwarns << "Linkset terrain request failed: " << status.toString()
  617. << llendl;
  618. responder->handleTerrainLinksetsError();
  619. }
  620. }
  621. void LLPathfindingManager::charactersCoro(const std::string& url,
  622. request_id_t req_id,
  623. object_request_cb_t cb) const
  624. {
  625. LLCoreHttpUtil::HttpCoroutineAdapter adapter("Characters");
  626. LLSD result = adapter.getAndSuspend(url, mHttpOptions, mHttpHeaders);
  627. if (!instanceExists() || LLApp::isExiting())
  628. {
  629. return; // Viewer is being closed down !
  630. }
  631. LLCore::HttpStatus status =
  632. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  633. if (status)
  634. {
  635. result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
  636. LL_DEBUGS("NavMesh") << "Results: " << result << LL_ENDL;
  637. LLPathfindingObjectList::ptr_t char_list =
  638. LLPathfindingObjectList::ptr_t(new LLPathfindingCharacterList(result));
  639. cb(req_id, LLPathfindingManager::kRequestCompleted, char_list);
  640. }
  641. else
  642. {
  643. llwarns << "Characters request failed: " << status.toString()
  644. << llendl;
  645. LLPathfindingObjectList::ptr_t char_list =
  646. LLPathfindingObjectList::ptr_t(new LLPathfindingCharacterList());
  647. cb(req_id, LLPathfindingManager::kRequestError, char_list);
  648. }
  649. }
  650. void LLPathfindingManager::handleNavMeshStatusUpdate(const LLPathfindingNavMeshStatus& status)
  651. {
  652. LLPathfindingNavMesh::ptr_t navmeshp =
  653. getNavMeshForRegion(status.getRegionUUID());
  654. if (!status.isValid())
  655. {
  656. navmeshp->handleNavMeshError();
  657. }
  658. else
  659. {
  660. navmeshp->handleNavMeshNewVersion(status);
  661. }
  662. }
  663. void LLPathfindingManager::handleAgentState(bool can_rebake_region)
  664. {
  665. mAgentStateSignal(can_rebake_region);
  666. }
  667. LLPathfindingNavMesh::ptr_t LLPathfindingManager::getNavMeshForRegion(const LLUUID& region_id)
  668. {
  669. LLPathfindingNavMesh::ptr_t navmeshp;
  670. map_t::iterator iter = mNavMeshMap.find(region_id);
  671. if (iter == mNavMeshMap.end())
  672. {
  673. navmeshp =
  674. LLPathfindingNavMesh::ptr_t(new LLPathfindingNavMesh(region_id));
  675. mNavMeshMap[region_id] = navmeshp;
  676. }
  677. else
  678. {
  679. navmeshp = iter->second;
  680. }
  681. return navmeshp;
  682. }
  683. LLPathfindingNavMesh::ptr_t LLPathfindingManager::getNavMeshForRegion(LLViewerRegion* region)
  684. {
  685. LLUUID region_id;
  686. if (region)
  687. {
  688. region_id = region->getRegionID();
  689. }
  690. return getNavMeshForRegion(region_id);
  691. }
  692. const std::string LLPathfindingManager::getNavMeshStatusURLForCurrentRegion() const
  693. {
  694. return getRegionCapability(gAgent.getRegion(), "NavMeshGenerationStatus");
  695. }
  696. const std::string LLPathfindingManager::getNavMeshStatusURLForRegion(LLViewerRegion* region) const
  697. {
  698. return getRegionCapability(region, "NavMeshGenerationStatus");
  699. }
  700. const std::string LLPathfindingManager::getRetrieveNavMeshURLForRegion(LLViewerRegion* region) const
  701. {
  702. return getRegionCapability(region, "RetrieveNavMeshSrc");
  703. }
  704. const std::string LLPathfindingManager::getRetrieveObjectLinksetsURLForCurrentRegion() const
  705. {
  706. return gAgent.getRegionCapability("RegionObjects");
  707. }
  708. const std::string LLPathfindingManager::getChangeObjectLinksetsURLForCurrentRegion() const
  709. {
  710. return gAgent.getRegionCapability("ObjectNavMeshProperties");
  711. }
  712. const std::string LLPathfindingManager::getTerrainLinksetsURLForCurrentRegion() const
  713. {
  714. return getRegionCapability(gAgent.getRegion(), "TerrainNavMeshProperties");
  715. }
  716. const std::string LLPathfindingManager::getCharactersURLForCurrentRegion() const
  717. {
  718. return getRegionCapability(gAgent.getRegion(), "CharacterProperties");
  719. }
  720. const std::string LLPathfindingManager::getAgentStateURLForRegion(LLViewerRegion* region) const
  721. {
  722. return getRegionCapability(region, "AgentState");
  723. }
  724. const std::string LLPathfindingManager::getRegionCapability(LLViewerRegion* region,
  725. const char* cap_name) const
  726. {
  727. const std::string& url = region ? region->getCapability(cap_name)
  728. : LLStringUtil::null;
  729. if (url.empty())
  730. {
  731. llwarns << "Cannot find capability '" << cap_name
  732. << "' for current region '"
  733. << (region ? region->getIdentity() : "<null>") << "'"
  734. << llendl;
  735. }
  736. return url;
  737. }
  738. //---------------------------------------------------------------------------
  739. // LLNavMeshSimStateChangeNode
  740. //---------------------------------------------------------------------------
  741. void LLNavMeshSimStateChangeNode::post(ResponsePtr response,
  742. const LLSD& context,
  743. const LLSD& input) const
  744. {
  745. if (!input.has("body") || !input.get("body").isMap())
  746. {
  747. llwarns << "Invalid response !" << llendl;
  748. return;
  749. }
  750. LLPathfindingNavMeshStatus nmstatus(input.get("body"));
  751. LLPathfindingManager::getInstance()->handleNavMeshStatusUpdate(nmstatus);
  752. }
  753. //---------------------------------------------------------------------------
  754. // LLAgentStateChangeNode
  755. //---------------------------------------------------------------------------
  756. void LLAgentStateChangeNode::post(ResponsePtr response, const LLSD& context,
  757. const LLSD& input) const
  758. {
  759. if (input.has("body") && input.get("body").isMap() &&
  760. input.get("body").has("can_modify_navmesh") &&
  761. input.get("body").get("can_modify_navmesh").isBoolean())
  762. {
  763. bool rebake_ok =
  764. input.get("body").get("can_modify_navmesh").asBoolean();
  765. LLPathfindingManager::getInstance()->handleAgentState(rebake_ok);
  766. }
  767. else
  768. {
  769. llwarns << "Invalid response !" << llendl;
  770. }
  771. }
  772. //---------------------------------------------------------------------------
  773. // LinksetsResponder
  774. //---------------------------------------------------------------------------
  775. LinksetsResponder::LinksetsResponder(LLPathfindingManager::request_id_t req_id,
  776. LLPathfindingManager::object_request_cb_t cb,
  777. bool object_requested,
  778. bool terrain_requested)
  779. : mRequestId(req_id),
  780. mLinksetsCallback(cb),
  781. mObjectMessagingState(object_requested ? kWaiting : kNotRequested),
  782. mTerrainMessagingState(terrain_requested ? kWaiting : kNotRequested),
  783. mObjectLinksetListPtr(),
  784. mTerrainLinksetPtr()
  785. {
  786. }
  787. void LinksetsResponder::handleObjectLinksetsResult(const LLSD& content)
  788. {
  789. mObjectLinksetListPtr =
  790. LLPathfindingObjectList::ptr_t(new LLPathfindingLinksetList(content));
  791. mObjectMessagingState = kReceivedGood;
  792. if (mTerrainMessagingState != kWaiting)
  793. {
  794. sendCallback();
  795. }
  796. }
  797. void LinksetsResponder::handleObjectLinksetsError()
  798. {
  799. mObjectMessagingState = kReceivedError;
  800. if (mTerrainMessagingState != kWaiting)
  801. {
  802. sendCallback();
  803. }
  804. }
  805. void LinksetsResponder::handleTerrainLinksetsResult(const LLSD& content)
  806. {
  807. mTerrainLinksetPtr =
  808. LLPathfindingObject::ptr_t(new LLPathfindingLinkset(content));
  809. mTerrainMessagingState = kReceivedGood;
  810. if (mObjectMessagingState != kWaiting)
  811. {
  812. sendCallback();
  813. }
  814. }
  815. void LinksetsResponder::handleTerrainLinksetsError()
  816. {
  817. mTerrainMessagingState = kReceivedError;
  818. if (mObjectMessagingState != kWaiting)
  819. {
  820. sendCallback();
  821. }
  822. }
  823. void LinksetsResponder::sendCallback()
  824. {
  825. llassert(mObjectMessagingState != kWaiting &&
  826. mTerrainMessagingState != kWaiting);
  827. LLPathfindingManager::ERequestStatus req_status;
  828. if ((mObjectMessagingState == kReceivedGood ||
  829. mObjectMessagingState == kNotRequested) &&
  830. (mTerrainMessagingState == kReceivedGood ||
  831. mTerrainMessagingState == kNotRequested))
  832. {
  833. req_status = LLPathfindingManager::kRequestCompleted;
  834. }
  835. else
  836. {
  837. req_status = LLPathfindingManager::kRequestError;
  838. }
  839. if (mObjectMessagingState != kReceivedGood)
  840. {
  841. mObjectLinksetListPtr =
  842. LLPathfindingObjectList::ptr_t(new LLPathfindingLinksetList());
  843. }
  844. if (mTerrainMessagingState == kReceivedGood)
  845. {
  846. mObjectLinksetListPtr->update(mTerrainLinksetPtr);
  847. }
  848. mLinksetsCallback(mRequestId, req_status, mObjectLinksetListPtr);
  849. }