lllandmark.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:7k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lllandmark.cpp
  3.  * @brief Landmark asset class
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "lllandmark.h"
  34. #include <errno.h>
  35. #include "message.h"
  36. #include "llregionhandle.h"
  37. std::pair<LLUUID, U64> LLLandmark::mLocalRegion;
  38. LLLandmark::region_map_t LLLandmark::mRegions;
  39. LLLandmark::region_callback_map_t LLLandmark::sRegionCallbackMap;
  40. LLLandmark::LLLandmark() :
  41. mGlobalPositionKnown(false)
  42. {
  43. }
  44. LLLandmark::LLLandmark(const LLVector3d& pos) :
  45. mGlobalPositionKnown(true),
  46. mGlobalPos( pos )
  47. {
  48. }
  49. bool LLLandmark::getGlobalPos(LLVector3d& pos)
  50. {
  51. if(mGlobalPositionKnown)
  52. {
  53. pos = mGlobalPos;
  54. }
  55. else if(mRegionID.notNull())
  56. {
  57. F32 g_x = -1.0;
  58. F32 g_y = -1.0;
  59. if(mRegionID == mLocalRegion.first)
  60. {
  61. from_region_handle(mLocalRegion.second, &g_x, &g_y);
  62. }
  63. else
  64. {
  65. region_map_t::iterator it = mRegions.find(mRegionID);
  66. if(it != mRegions.end())
  67. {
  68. from_region_handle((*it).second.mRegionHandle, &g_x, &g_y);
  69. }
  70. }
  71. if((g_x > 0.f) && (g_y > 0.f))
  72. {
  73. pos.mdV[0] = g_x + mRegionPos.mV[0];
  74. pos.mdV[1] = g_y + mRegionPos.mV[1];
  75. pos.mdV[2] = mRegionPos.mV[2];
  76. setGlobalPos(pos);
  77. }
  78. }
  79. return mGlobalPositionKnown;
  80. }
  81. void LLLandmark::setGlobalPos(const LLVector3d& pos)
  82. {
  83. mGlobalPos = pos;
  84. mGlobalPositionKnown = true;
  85. }
  86. bool LLLandmark::getRegionID(LLUUID& region_id)
  87. {
  88. if(mRegionID.notNull())
  89. {
  90. region_id = mRegionID;
  91. return true;
  92. }
  93. return false;
  94. }
  95. LLVector3 LLLandmark::getRegionPos() const
  96. {
  97. return mRegionPos;
  98. }
  99. // static
  100. LLLandmark* LLLandmark::constructFromString(const char *buffer)
  101. {
  102. const char* cur = buffer;
  103. S32 chars_read = 0;
  104. S32 count = 0;
  105. U32 version = 0;
  106. // read version 
  107. count = sscanf( cur, "Landmark version %un%n", &version, &chars_read );
  108. if(count != 1)
  109. {
  110. goto error;
  111. }
  112. if(version == 1)
  113. {
  114. LLVector3d pos;
  115. cur += chars_read;
  116. // read position
  117. count = sscanf( cur, "position %lf %lf %lfn%n", pos.mdV+VX, pos.mdV+VY, pos.mdV+VZ, &chars_read );
  118. if( count != 3 )
  119. {
  120. goto error;
  121. }
  122. cur += chars_read;
  123. // llinfos << "Landmark read: " << pos << llendl;
  124. return new LLLandmark(pos);
  125. }
  126. else if(version == 2)
  127. {
  128. // *NOTE: Changing the buffer size will require changing the
  129. // scanf call below.
  130. char region_id_str[MAX_STRING]; /* Flawfinder: ignore */
  131. LLVector3 pos;
  132. cur += chars_read;
  133. count = sscanf( /* Flawfinder: ignore */
  134. cur,
  135. "region_id %254sn%n",
  136. region_id_str, &chars_read);
  137. if(count != 1) goto error;
  138. cur += chars_read;
  139. count = sscanf(cur, "local_pos %f %f %fn%n", pos.mV+VX, pos.mV+VY, pos.mV+VZ, &chars_read);
  140. if(count != 3) goto error;
  141. cur += chars_read;
  142. LLLandmark* lm = new LLLandmark;
  143. lm->mRegionID.set(region_id_str);
  144. lm->mRegionPos = pos;
  145. return lm;
  146. }
  147.  error:
  148. llinfos << "Bad Landmark Asset: bad _DATA_ block." << llendl;
  149. return NULL;
  150. }
  151. // static
  152. void LLLandmark::registerCallbacks(LLMessageSystem* msg)
  153. {
  154. msg->setHandlerFunc("RegionIDAndHandleReply", &processRegionIDAndHandle);
  155. }
  156. // static
  157. void LLLandmark::requestRegionHandle(
  158. LLMessageSystem* msg,
  159. const LLHost& upstream_host,
  160. const LLUUID& region_id,
  161. region_handle_callback_t callback)
  162. {
  163. if(region_id.isNull())
  164. {
  165. // don't bother with checking - it's 0.
  166. lldebugs << "requestRegionHandle: null" << llendl;
  167. if(callback)
  168. {
  169. const U64 U64_ZERO = 0;
  170. callback(region_id, U64_ZERO);
  171. }
  172. }
  173. else
  174. {
  175. if(region_id == mLocalRegion.first)
  176. {
  177. lldebugs << "requestRegionHandle: local" << llendl;
  178. if(callback)
  179. {
  180. callback(region_id, mLocalRegion.second);
  181. }
  182. }
  183. else
  184. {
  185. region_map_t::iterator it = mRegions.find(region_id);
  186. if(it == mRegions.end())
  187. {
  188. lldebugs << "requestRegionHandle: upstream" << llendl;
  189. if(callback)
  190. {
  191. region_callback_map_t::value_type vt(region_id, callback);
  192. sRegionCallbackMap.insert(vt);
  193. }
  194. lldebugs << "Landmark requesting information about: "
  195.  << region_id << llendl;
  196. msg->newMessage("RegionHandleRequest");
  197. msg->nextBlock("RequestBlock");
  198. msg->addUUID("RegionID", region_id);
  199. msg->sendReliable(upstream_host);
  200. }
  201. else if(callback)
  202. {
  203. // we have the answer locally - just call the callack.
  204. lldebugs << "requestRegionHandle: ready" << llendl;
  205. callback(region_id, (*it).second.mRegionHandle);
  206. }
  207. }
  208. }
  209. // As good a place as any to expire old entries.
  210. expireOldEntries();
  211. }
  212. // static
  213. void LLLandmark::setRegionHandle(const LLUUID& region_id, U64 region_handle)
  214. {
  215. mLocalRegion.first = region_id;
  216. mLocalRegion.second = region_handle;
  217. }
  218. // static
  219. void LLLandmark::processRegionIDAndHandle(LLMessageSystem* msg, void**)
  220. {
  221. LLUUID region_id;
  222. msg->getUUID("ReplyBlock", "RegionID", region_id);
  223. mRegions.erase(region_id);
  224. CacheInfo info;
  225. const F32 CACHE_EXPIRY_SECONDS = 60.0f * 10.0f; // ten minutes
  226. info.mTimer.setTimerExpirySec(CACHE_EXPIRY_SECONDS);
  227. msg->getU64("ReplyBlock", "RegionHandle", info.mRegionHandle);
  228. region_map_t::value_type vt(region_id, info);
  229. mRegions.insert(vt);
  230. #if LL_DEBUG
  231. U32 grid_x, grid_y;
  232. grid_from_region_handle(info.mRegionHandle, &grid_x, &grid_y);
  233. lldebugs << "Landmark got reply for region: " << region_id << " "
  234.  << grid_x << "," << grid_y << llendl;
  235. #endif
  236. // make all the callbacks here.
  237. region_callback_map_t::iterator it;
  238. while((it = sRegionCallbackMap.find(region_id)) != sRegionCallbackMap.end())
  239. {
  240. (*it).second(region_id, info.mRegionHandle);
  241. sRegionCallbackMap.erase(it);
  242. }
  243. }
  244. // static
  245. void LLLandmark::expireOldEntries()
  246. {
  247. for(region_map_t::iterator it = mRegions.begin(); it != mRegions.end(); )
  248. {
  249. if((*it).second.mTimer.hasExpired())
  250. {
  251. mRegions.erase(it++);
  252. }
  253. else
  254. {
  255. ++it;
  256. }
  257. }
  258. }