aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llworldmap.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llworldmap.cpp934
1 files changed, 934 insertions, 0 deletions
diff --git a/linden/indra/newview/llworldmap.cpp b/linden/indra/newview/llworldmap.cpp
new file mode 100644
index 0000000..6e010f7
--- /dev/null
+++ b/linden/indra/newview/llworldmap.cpp
@@ -0,0 +1,934 @@
1/**
2 * @file llworldmap.cpp
3 * @brief Underlying data representation for map of the world
4 *
5 * Copyright (c) 2003-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "llworldmap.h"
31
32#include "llregionhandle.h"
33#include "message.h"
34
35#include "viewer.h" // for gPacificDaylightTime
36#include "llagent.h"
37#include "llmapresponders.h"
38#include "llviewercontrol.h"
39#include "llfloaterworldmap.h"
40#include "lltracker.h"
41#include "llviewerimagelist.h"
42#include "llviewerregion.h"
43#include "llregionflags.h"
44
45LLWorldMap* gWorldMap = NULL;
46
47const F32 REQUEST_ITEMS_TIMER = 10.f * 60.f; // 10 minutes
48
49LLItemInfo::LLItemInfo(F32 global_x, F32 global_y,
50 const std::string& name,
51 LLUUID id,
52 S32 extra, S32 extra2)
53: mName(name),
54 mToolTip(""),
55 mPosGlobal(global_x, global_y, 40.0),
56 mID(id),
57 mSelected(FALSE),
58 mExtra(extra),
59 mExtra2(extra2)
60{
61 mRegionHandle = to_region_handle(mPosGlobal);
62}
63
64LLSimInfo::LLSimInfo()
65: mHandle(0),
66 mName(),
67 mAgentsUpdateTime(0),
68 mAccess(0x0),
69 mRegionFlags(0x0),
70 mWaterHeight(0.f),
71 mAlpha(-1.f)
72{
73}
74
75
76LLVector3d LLSimInfo::getGlobalPos(LLVector3 local_pos) const
77{
78 LLVector3d pos = from_region_handle(mHandle);
79 pos.mdV[VX] += local_pos.mV[VX];
80 pos.mdV[VY] += local_pos.mV[VY];
81 pos.mdV[VZ] += local_pos.mV[VZ];
82 return pos;
83}
84
85
86//---------------------------------------------------------------------------
87// World Map
88//---------------------------------------------------------------------------
89
90LLWorldMap::LLWorldMap() :
91 mIsTrackingUnknownLocation( FALSE ),
92 mInvalidLocation( FALSE ),
93 mIsTrackingDoubleClick( FALSE ),
94 mIsTrackingCommit( FALSE ),
95 mUnknownLocation( 0, 0, 0 ),
96 mRequestLandForSale(true),
97 mCurrentMap(0),
98 mMinX(U32_MAX),
99 mMaxX(U32_MIN),
100 mMinY(U32_MAX),
101 mMaxY(U32_MIN),
102 mNeighborMap(NULL),
103 mTelehubCoverageMap(NULL),
104 mNeighborMapWidth(0),
105 mNeighborMapHeight(0)
106{
107 for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map)
108 {
109 mMapLoaded[map] = FALSE;
110 mMapBlockLoaded[map] = new BOOL[MAP_BLOCK_RES*MAP_BLOCK_RES];
111 for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx)
112 {
113 mMapBlockLoaded[map][idx] = FALSE;
114 }
115 }
116}
117
118
119LLWorldMap::~LLWorldMap()
120{
121 reset();
122 for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map)
123 {
124 delete[] mMapBlockLoaded[map];
125 }
126}
127
128
129void LLWorldMap::reset()
130{
131 for_each(mSimInfoMap.begin(), mSimInfoMap.end(), DeletePairedPointer());
132 mSimInfoMap.clear();
133
134 for (S32 m=0; m<MAP_SIM_IMAGE_TYPES; ++m)
135 {
136 mMapLoaded[m] = FALSE;
137 }
138
139 clearSimFlags();
140
141 eraseItems();
142
143 mMinX = U32_MAX;
144 mMaxX = U32_MIN;
145
146 mMinY = U32_MAX;
147 mMaxY = U32_MIN;
148
149 delete [] mNeighborMap;
150 mNeighborMap = NULL;
151 delete [] mTelehubCoverageMap;
152 mTelehubCoverageMap = NULL;
153
154 mNeighborMapWidth = 0;
155 mNeighborMapHeight = 0;
156}
157
158void LLWorldMap::eraseItems()
159{
160 if (mRequestTimer.getElapsedTimeF32() > REQUEST_ITEMS_TIMER)
161 {
162 mRequestTimer.reset();
163
164 mTelehubs.clear();
165 mInfohubs.clear();
166 mPGEvents.clear();
167 mMatureEvents.clear();
168 mPopular.clear();
169 mLandForSale.clear();
170 mClassifieds.clear();
171 }
172// mAgentLocationsMap.clear(); // persists
173// mNumAgents.clear(); // persists
174}
175
176
177void LLWorldMap::clearImageRefs()
178{
179 for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
180 {
181 LLSimInfo* info = (*it).second;
182 if (info->mCurrentImage)
183 {
184 info->mCurrentImage->setBoostLevel(0);
185 info->mCurrentImage = NULL;
186 }
187 if (info->mOverlayImage)
188 {
189 info->mOverlayImage->setBoostLevel(0);
190 info->mOverlayImage = NULL;
191 }
192 }
193}
194
195// Doesn't clear the already-loaded sim infos, just re-requests them
196void LLWorldMap::clearSimFlags()
197{
198 for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map)
199 {
200 for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx)
201 {
202 mMapBlockLoaded[map][idx] = FALSE;
203 }
204 }
205}
206
207LLSimInfo* LLWorldMap::simInfoFromPosGlobal(const LLVector3d& pos_global)
208{
209 U64 handle = to_region_handle(pos_global);
210 return simInfoFromHandle(handle);
211}
212
213LLSimInfo* LLWorldMap::simInfoFromHandle(const U64 handle)
214{
215 sim_info_map_t::iterator it = mSimInfoMap.find(handle);
216 if (it != mSimInfoMap.end())
217 {
218 LLSimInfo* sim_info = (*it).second;
219 if (sim_info)
220 {
221 return sim_info;
222 }
223 }
224 return NULL;
225}
226
227
228LLSimInfo* LLWorldMap::simInfoFromName(const LLString& sim_name)
229{
230 LLSimInfo* sim_info = NULL;
231 if (!sim_name.empty())
232 {
233 for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
234 {
235 sim_info = (*it).second;
236 if (sim_info
237 && (0 == LLString::compareInsensitive(sim_name.c_str(), sim_info->mName.c_str())) )
238 {
239 break;
240 }
241 sim_info = NULL;
242 }
243 }
244 return sim_info;
245}
246
247LLString LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global)
248{
249 U64 handle = to_region_handle(pos_global);
250
251 sim_info_map_t::iterator it = mSimInfoMap.find(handle);
252 if (it != mSimInfoMap.end())
253 {
254 LLSimInfo* info = (*it).second;
255 return info->mName.c_str();
256 }
257 else
258 {
259 return "(unknown region)";
260 }
261}
262
263void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer)
264{
265 mCurrentMap = layer;
266 if (!mMapLoaded[layer] || request_layer)
267 {
268 sendMapLayerRequest();
269 sendItemRequest(MAP_ITEM_AGENT_COUNT);
270 }
271
272 if (mTelehubs.size() == 0 ||
273 mInfohubs.size() == 0)
274 {
275 // Request for telehubs
276 sendItemRequest(MAP_ITEM_TELEHUB);
277 }
278
279 if (mPGEvents.size() == 0)
280 {
281 // Request for events
282 sendItemRequest(MAP_ITEM_PG_EVENT);
283 }
284
285 if (mMatureEvents.size() == 0)
286 {
287 // Request for events (mature)
288 sendItemRequest(MAP_ITEM_MATURE_EVENT);
289 }
290
291 if (mPopular.size() == 0)
292 {
293 // Request for popular
294 sendItemRequest(MAP_ITEM_POPULAR);
295 }
296
297 if (mLandForSale.size() == 0)
298 {
299 // Request for Land For Sale
300 sendItemRequest(MAP_ITEM_LAND_FOR_SALE);
301 }
302
303 if (mClassifieds.size() == 0)
304 {
305 sendItemRequest(MAP_ITEM_CLASSIFIED);
306 }
307
308 clearImageRefs();
309 clearSimFlags();
310}
311
312void LLWorldMap::sendItemRequest(U32 type, U64 handle)
313{
314 LLMessageSystem* msg = gMessageSystem;
315 S32 layer = mCurrentMap;
316
317 msg->newMessageFast(_PREHASH_MapItemRequest);
318 msg->nextBlockFast(_PREHASH_AgentData);
319 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
320 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
321 msg->addU32Fast(_PREHASH_Flags, layer);
322 msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
323 msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
324
325 msg->nextBlockFast(_PREHASH_RequestData);
326 msg->addU32Fast(_PREHASH_ItemType, type);
327 msg->addU64Fast(_PREHASH_RegionHandle, handle); // If zero, filled in on sim
328
329 gAgent.sendReliableMessage();
330}
331
332// public
333void LLWorldMap::sendMapLayerRequest()
334{
335 LLSD body;
336 body["Flags"] = mCurrentMap;
337 std::string url = gAgent.getRegion()->getCapability(
338 gAgent.isGodlike() ? "MapLayerGod" : "MapLayer");
339
340 if (!url.empty())
341 {
342 llinfos << "LLWorldMap::sendMapLayerRequest via capability" << llendl;
343 LLHTTPClient::post(url, body, new LLMapLayerResponder());
344 }
345 else
346 {
347 llinfos << "LLWorldMap::sendMapLayerRequest via message system" << llendl;
348 LLMessageSystem* msg = gMessageSystem;
349 S32 layer = mCurrentMap;
350
351 // Request for layer
352 msg->newMessageFast(_PREHASH_MapLayerRequest);
353 msg->nextBlockFast(_PREHASH_AgentData);
354 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
355 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
356 msg->addU32Fast(_PREHASH_Flags, layer);
357 msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
358 msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
359 gAgent.sendReliableMessage();
360
361 if (mRequestLandForSale)
362 {
363 msg->newMessageFast(_PREHASH_MapLayerRequest);
364 msg->nextBlockFast(_PREHASH_AgentData);
365 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
366 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
367 msg->addU32Fast(_PREHASH_Flags, 2);
368 msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
369 msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
370 gAgent.sendReliableMessage();
371 }
372 }
373}
374
375// public
376void LLWorldMap::sendNamedRegionRequest(std::string region_name)
377{
378 LLMessageSystem* msg = gMessageSystem;
379 S32 layer = mCurrentMap;
380
381 // Request for layer
382 msg->newMessageFast(_PREHASH_MapNameRequest);
383 msg->nextBlockFast(_PREHASH_AgentData);
384 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
385 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
386 msg->addU32Fast(_PREHASH_Flags, layer);
387 msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
388 msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
389 msg->nextBlockFast(_PREHASH_NameData);
390 msg->addStringFast(_PREHASH_Name, region_name);
391 gAgent.sendReliableMessage();
392}
393
394// public
395void LLWorldMap::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent)
396{
397 S32 layer = mCurrentMap;
398 LLMessageSystem* msg = gMessageSystem;
399 msg->newMessageFast(_PREHASH_MapBlockRequest);
400 msg->nextBlockFast(_PREHASH_AgentData);
401 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
402 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
403 U32 flags = layer;
404 flags |= (return_nonexistent ? 0x10000 : 0);
405 msg->addU32Fast(_PREHASH_Flags, flags);
406 msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
407 msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
408 msg->nextBlockFast(_PREHASH_PositionData);
409 msg->addU16Fast(_PREHASH_MinX, min_x);
410 msg->addU16Fast(_PREHASH_MinY, min_y);
411 msg->addU16Fast(_PREHASH_MaxX, max_x);
412 msg->addU16Fast(_PREHASH_MaxY, max_y);
413 gAgent.sendReliableMessage();
414
415 if (mRequestLandForSale)
416 {
417 msg->newMessageFast(_PREHASH_MapBlockRequest);
418 msg->nextBlockFast(_PREHASH_AgentData);
419 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
420 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
421 msg->addU32Fast(_PREHASH_Flags, 2);
422 msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
423 msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
424 msg->nextBlockFast(_PREHASH_PositionData);
425 msg->addU16Fast(_PREHASH_MinX, min_x);
426 msg->addU16Fast(_PREHASH_MinY, min_y);
427 msg->addU16Fast(_PREHASH_MaxX, max_x);
428 msg->addU16Fast(_PREHASH_MaxY, max_y);
429 gAgent.sendReliableMessage();
430 }
431}
432
433// public static
434void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**)
435{
436 llinfos << "LLWorldMap::processMapLayerReply from message system" << llendl;
437
438 U32 agent_flags;
439 msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags);
440
441 if (agent_flags != (U32)gWorldMap->mCurrentMap)
442 {
443 llwarns << "Invalid or out of date map image type returned!" << llendl;
444 return;
445 }
446
447 LLUUID image_id;
448 //U32 left, right, top, bottom;
449
450 S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_LayerData);
451
452 gWorldMap->mMapLayers[agent_flags].clear();
453
454 BOOL adjust = FALSE;
455 for (S32 block=0; block<num_blocks; ++block)
456 {
457 LLWorldMapLayer new_layer;
458 new_layer.LayerDefined = TRUE;
459 msg->getUUIDFast(_PREHASH_LayerData, _PREHASH_ImageID, new_layer.LayerImageID, block);
460 new_layer.LayerImage = gImageList.getImage(new_layer.LayerImageID, MIPMAP_TRUE, FALSE);
461 new_layer.LayerImage->bindTexture(0);
462 new_layer.LayerImage->setClamp(TRUE, TRUE);
463
464 U32 left, right, top, bottom;
465 msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Left, left, block);
466 msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Right, right, block);
467 msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Top, top, block);
468 msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Bottom, bottom, block);
469
470 new_layer.LayerExtents.mLeft = left;
471 new_layer.LayerExtents.mRight = right;
472 new_layer.LayerExtents.mBottom = bottom;
473 new_layer.LayerExtents.mTop = top;
474
475 F32 x_meters = F32(left*REGION_WIDTH_UNITS);
476 F32 y_meters = F32(bottom*REGION_WIDTH_UNITS);
477 adjust = gWorldMap->extendAABB(U32(x_meters), U32(y_meters),
478 U32(x_meters+REGION_WIDTH_UNITS*new_layer.LayerExtents.getWidth()),
479 U32(y_meters+REGION_WIDTH_UNITS*new_layer.LayerExtents.getHeight())) || adjust;
480
481 gWorldMap->mMapLayers[agent_flags].push_back(new_layer);
482 }
483
484 gWorldMap->mMapLoaded[agent_flags] = TRUE;
485 if(adjust) gFloaterWorldMap->adjustZoomSliderBounds();
486}
487
488// public static
489void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**)
490{
491 U32 agent_flags;
492 msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags);
493
494 if (agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES)
495 {
496 llwarns << "Invalid map image type returned! " << agent_flags << llendl;
497 return;
498 }
499
500 S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data);
501
502 bool found_null_sim = false;
503
504 BOOL adjust = FALSE;
505 for (S32 block=0; block<num_blocks; ++block)
506 {
507 U16 x_regions;
508 U16 y_regions;
509 char name[MAX_STRING];
510 U8 access;
511 U32 region_flags;
512 U8 water_height;
513 U8 agents;
514 LLUUID image_id;
515 msg->getU16Fast(_PREHASH_Data, _PREHASH_X, x_regions, block);
516 msg->getU16Fast(_PREHASH_Data, _PREHASH_Y, y_regions, block);
517 msg->getStringFast(_PREHASH_Data, _PREHASH_Name, MAX_STRING, name, block);
518 msg->getU8Fast(_PREHASH_Data, _PREHASH_Access, access, block);
519 msg->getU32Fast(_PREHASH_Data, _PREHASH_RegionFlags, region_flags, block);
520 msg->getU8Fast(_PREHASH_Data, _PREHASH_WaterHeight, water_height, block);
521 msg->getU8Fast(_PREHASH_Data, _PREHASH_Agents, agents, block);
522 msg->getUUIDFast(_PREHASH_Data, _PREHASH_MapImageID, image_id, block);
523
524 U32 x_meters = x_regions * REGION_WIDTH_UNITS;
525 U32 y_meters = y_regions * REGION_WIDTH_UNITS;
526
527 if (access == 255)
528 {
529 // This region doesn't exist
530 if (gWorldMap->mIsTrackingUnknownLocation &&
531 gWorldMap->mUnknownLocation.mdV[0] >= x_meters &&
532 gWorldMap->mUnknownLocation.mdV[0] < x_meters + 256 &&
533 gWorldMap->mUnknownLocation.mdV[1] >= y_meters &&
534 gWorldMap->mUnknownLocation.mdV[1] < y_meters + 256)
535 {
536 // We were tracking this location, but it doesn't exist
537 gWorldMap->mInvalidLocation = TRUE;
538 }
539
540 found_null_sim = true;
541 }
542 else
543 {
544 adjust = gWorldMap->extendAABB(x_meters,
545 y_meters,
546 x_meters+REGION_WIDTH_UNITS,
547 y_meters+REGION_WIDTH_UNITS) || adjust;
548 U64 handle = to_region_handle(x_meters, y_meters);
549
550// llinfos << "Map sim " << name << " image layer " << agent_flags << " ID " << image_id.getString() << llendl;
551
552 LLSimInfo* siminfo = new LLSimInfo();
553 sim_info_map_t::iterator iter = gWorldMap->mSimInfoMap.find(handle);
554 if (iter != gWorldMap->mSimInfoMap.end())
555 {
556 LLSimInfo* oldinfo = iter->second;
557 for (S32 image=0; image<MAP_SIM_IMAGE_TYPES; ++image)
558 {
559 siminfo->mMapImageID[image] = oldinfo->mMapImageID[image];
560 }
561 delete oldinfo;
562 }
563 gWorldMap->mSimInfoMap[handle] = siminfo;
564
565 siminfo->mHandle = handle;
566 siminfo->mName.assign( name );
567 siminfo->mAccess = access;
568 siminfo->mRegionFlags = region_flags;
569 siminfo->mWaterHeight = (F32) water_height;
570 siminfo->mMapImageID[agent_flags] = image_id;
571 siminfo->mCurrentImage = gImageList.getImage(siminfo->mMapImageID[gWorldMap->mCurrentMap], MIPMAP_TRUE, FALSE);
572 siminfo->mCurrentImage->bindTexture(0);
573 siminfo->mCurrentImage->setClamp(TRUE, TRUE);
574
575 if (siminfo->mMapImageID[2].notNull())
576 {
577 siminfo->mOverlayImage = gImageList.getImage(siminfo->mMapImageID[2], MIPMAP_TRUE, FALSE);
578 }
579 else
580 {
581 siminfo->mOverlayImage = NULL;
582 }
583
584 if (gWorldMap->mIsTrackingUnknownLocation &&
585 gWorldMap->mUnknownLocation.mdV[0] >= x_meters &&
586 gWorldMap->mUnknownLocation.mdV[0] < x_meters + 256 &&
587 gWorldMap->mUnknownLocation.mdV[1] >= y_meters &&
588 gWorldMap->mUnknownLocation.mdV[1] < y_meters + 256)
589 {
590 if (siminfo->mAccess == SIM_ACCESS_DOWN)
591 {
592 // We were tracking this location, but it doesn't exist
593 gWorldMap->mInvalidLocation = true;
594 }
595 else
596 {
597 // We were tracking this location, and it does exist
598 bool is_tracking_dbl = gWorldMap->mIsTrackingDoubleClick == TRUE;
599 gFloaterWorldMap->trackLocation(gWorldMap->mUnknownLocation);
600 if (is_tracking_dbl)
601 {
602 LLVector3d pos_global = LLTracker::getTrackedPositionGlobal();
603 gAgent.teleportViaLocation( pos_global );
604 }
605 }
606 }
607 }
608 }
609 if(adjust) gFloaterWorldMap->adjustZoomSliderBounds();
610 gFloaterWorldMap->updateSims(found_null_sim);
611}
612
613// public static
614void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**)
615{
616 U32 type;
617 msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type);
618
619 S32 num_blocks = msg->getNumberOfBlocks("Data");
620
621 for (S32 block=0; block<num_blocks; ++block)
622 {
623 U32 X, Y;
624 char name[MAX_STRING];
625 S32 extra, extra2;
626 LLUUID uuid;
627 msg->getU32Fast(_PREHASH_Data, _PREHASH_X, X, block);
628 msg->getU32Fast(_PREHASH_Data, _PREHASH_Y, Y, block);
629 msg->getStringFast(_PREHASH_Data, _PREHASH_Name, MAX_STRING, name, block);
630 msg->getUUIDFast(_PREHASH_Data, _PREHASH_ID, uuid, block);
631 msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra, extra, block);
632 msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra2, extra2, block);
633
634 F32 world_x = (F32)X;
635 X /= REGION_WIDTH_UNITS;
636 F32 world_y = (F32)Y;
637 Y /= REGION_WIDTH_UNITS;
638
639 LLItemInfo new_item(world_x, world_y, name, uuid, extra, extra2);
640 LLSimInfo* siminfo = gWorldMap->simInfoFromHandle(new_item.mRegionHandle);
641
642 switch (type)
643 {
644 case MAP_ITEM_TELEHUB: // telehubs
645 {
646 // Telehub color, store in extra as 4 U8's
647 U8 *color = (U8 *)&new_item.mExtra;
648
649 F32 red = fmod((F32)X * 0.11f, 1.f) * 0.8f;
650 F32 green = fmod((F32)Y * 0.11f, 1.f) * 0.8f;
651 F32 blue = fmod(1.5f * (F32)(X + Y) * 0.11f, 1.f) * 0.8f;
652 F32 add_amt = (X % 2) ? 0.15f : -0.15f;
653 add_amt += (Y % 2) ? -0.15f : 0.15f;
654 color[0] = U8((red + add_amt) * 255);
655 color[1] = U8((green + add_amt) * 255);
656 color[2] = U8((blue + add_amt) * 255);
657 color[3] = 255;
658
659 // extra2 specifies whether this is an infohub or a telehub.
660 if (extra2)
661 {
662 gWorldMap->mInfohubs.push_back(new_item);
663 }
664 else
665 {
666 gWorldMap->mTelehubs.push_back(new_item);
667 }
668
669 break;
670 }
671 case MAP_ITEM_PG_EVENT: // events
672 case MAP_ITEM_MATURE_EVENT:
673 {
674 char buffer[32];
675 struct tm* timep;
676 // Convert to Pacific, based on server's opinion of whether
677 // it's daylight savings time there.
678 timep = utc_to_pacific_time(extra, gPacificDaylightTime);
679
680 S32 display_hour = timep->tm_hour % 12;
681 if (display_hour == 0) display_hour = 12;
682
683 sprintf(buffer, "%d:%02d %s",
684 display_hour,
685 timep->tm_min,
686 (timep->tm_hour < 12 ? "AM" : "PM") );
687 new_item.mToolTip.assign( buffer );
688
689 // HACK: store Z in extra2
690 new_item.mPosGlobal.mdV[VZ] = (F64)extra2;
691 if (type == MAP_ITEM_PG_EVENT)
692 {
693 gWorldMap->mPGEvents.push_back(new_item);
694 }
695 else
696 {
697 gWorldMap->mMatureEvents.push_back(new_item);
698 }
699 break;
700 }
701 case MAP_ITEM_POPULAR: // popular
702 {
703 new_item.mPosGlobal.mdV[VZ] = (F64)extra2;
704 gWorldMap->mPopular.push_back(new_item);
705 break;
706 }
707 case MAP_ITEM_LAND_FOR_SALE: // land for sale
708 {
709 new_item.mToolTip = llformat("%d sq. m. L$%d", new_item.mExtra, new_item.mExtra2);
710 gWorldMap->mLandForSale.push_back(new_item);
711 break;
712 }
713 case MAP_ITEM_CLASSIFIED: // classifieds
714 {
715 // HACK: Z-height is in Extra2 field.
716 new_item.mPosGlobal.mdV[VZ] = (F64)extra2;
717 gWorldMap->mClassifieds.push_back(new_item);
718 break;
719 }
720 case MAP_ITEM_AGENT_COUNT: // agent counts
721 {
722 // We only ever receive one per region, i.e. this update superceeds any others
723 gWorldMap->mNumAgents[new_item.mRegionHandle] = new_item.mExtra;
724 break;
725 }
726 case MAP_ITEM_AGENT_LOCATIONS: // agent locations
727 {
728 if (!siminfo)
729 {
730 llinfos << "siminfo missing for " << new_item.mPosGlobal.mdV[0] << ", " << new_item.mPosGlobal.mdV[1] << llendl;
731 break;
732 }
733// llinfos << "New Location " << new_item.mName << llendl;
734
735 item_info_list_t& agentcounts = gWorldMap->mAgentLocationsMap[new_item.mRegionHandle];
736
737 // Find the last item in the list with a different name and erase them
738 item_info_list_t::iterator lastiter;
739 for (lastiter = agentcounts.begin(); lastiter!=agentcounts.end(); ++lastiter)
740 {
741 const LLItemInfo& info = *lastiter;
742 if (info.mName == new_item.mName)
743 {
744 break;
745 }
746 }
747 if (lastiter != agentcounts.begin())
748 {
749 agentcounts.erase(agentcounts.begin(), lastiter);
750 }
751 // Now append the new location
752 if (new_item.mExtra > 0)
753 {
754 agentcounts.push_back(new_item);
755 }
756 break;
757 }
758 default:
759 break;
760 };
761 }
762}
763
764void LLWorldMap::dump()
765{
766 for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
767 {
768 U64 handle = (*it).first;
769 LLSimInfo* info = (*it).second;
770
771 U32 x_pos, y_pos;
772 from_region_handle(handle, &x_pos, &y_pos);
773
774 llinfos << x_pos << "," << y_pos
775 << " " << info->mName.c_str()
776 << " " << (S32)info->mAccess
777 << " " << std::hex << info->mRegionFlags << std::dec
778 << " " << info->mWaterHeight
779 //<< " " << info->mTelehubName
780 //<< " " << info->mTelehubPosition
781 << llendl;
782
783 if (info->mCurrentImage)
784 {
785 llinfos << "image discard " << (S32)info->mCurrentImage->getDiscardLevel()
786 << " fullwidth " << info->mCurrentImage->getWidth(0)
787 << " fullheight " << info->mCurrentImage->getHeight(0)
788 << " maxvirt " << info->mCurrentImage->mMaxVirtualSize
789 << " maxdisc " << (S32)info->mCurrentImage->getMaxDiscardLevel()
790 << llendl;
791 }
792 }
793}
794
795
796BOOL LLWorldMap::extendAABB(U32 min_x, U32 min_y, U32 max_x, U32 max_y)
797{
798 BOOL rv = FALSE;
799 if (min_x < mMinX)
800 {
801 rv = TRUE;
802 mMinX = min_x;
803 }
804 if (min_y < mMinY)
805 {
806 rv = TRUE;
807 mMinY = min_y;
808 }
809 if (max_x > mMaxX)
810 {
811 rv = TRUE;
812 mMaxX = max_x;
813 }
814 if (max_y > mMaxY)
815 {
816 rv = TRUE;
817 mMaxY = max_y;
818 }
819 lldebugs << "World map aabb: (" << mMinX << ", " << mMinY << "), ("
820 << mMaxX << ", " << mMaxY << ")" << llendl;
821 return rv;
822}
823
824
825U32 LLWorldMap::getWorldWidth() const
826{
827 return mMaxX - mMinX;
828}
829
830
831U32 LLWorldMap::getWorldHeight() const
832{
833 return mMaxY - mMinY;
834}
835
836BOOL LLWorldMap::coveredByTelehub(LLSimInfo* infop)
837{
838 /*if (!mTelehubCoverageMap)
839 {
840 return FALSE;
841 }
842 U32 x_pos, y_pos;
843 from_region_handle(infop->mHandle, &x_pos, &y_pos);
844 x_pos /= REGION_WIDTH_UNITS;
845 y_pos /= REGION_WIDTH_UNITS;
846
847 S32 index = x_pos - (mMinX / REGION_WIDTH_UNITS - 1) + (mNeighborMapWidth * (y_pos - (mMinY / REGION_WIDTH_UNITS - 1)));
848 return mTelehubCoverageMap[index] != 0; */
849 return FALSE;
850}
851
852void LLWorldMap::updateTelehubCoverage()
853{
854 /*S32 neighbor_width = getWorldWidth() / REGION_WIDTH_UNITS + 2;
855 S32 neighbor_height = getWorldHeight() / REGION_WIDTH_UNITS + 2;
856 if (neighbor_width > mNeighborMapWidth || neighbor_height > mNeighborMapHeight)
857 {
858 mNeighborMapWidth = neighbor_width;
859 mNeighborMapHeight = neighbor_height;
860 delete mNeighborMap;
861 delete mTelehubCoverageMap;
862
863 mNeighborMap = new U8[mNeighborMapWidth * mNeighborMapHeight];
864 mTelehubCoverageMap = new U8[mNeighborMapWidth * mNeighborMapHeight];
865 }
866
867 memset(mNeighborMap, 0, mNeighborMapWidth * mNeighborMapHeight * sizeof(U8));
868 memset(mTelehubCoverageMap, 0, mNeighborMapWidth * mNeighborMapHeight * sizeof(U8));
869
870 // leave 1 sim border
871 S32 min_x = (mMinX / REGION_WIDTH_UNITS) - 1;
872 S32 min_y = (mMinY / REGION_WIDTH_UNITS) - 1;
873
874 std::map<U64, LLSimInfo*>::const_iterator it;
875 for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
876 {
877 U64 handle = (*it).first;
878 //LLSimInfo* info = (*it).second;
879
880 U32 x_pos, y_pos;
881 from_region_handle(handle, &x_pos, &y_pos);
882 x_pos /= REGION_WIDTH_UNITS;
883 y_pos /= REGION_WIDTH_UNITS;
884 x_pos -= min_x;
885 y_pos -= min_y;
886
887 S32 index = x_pos + (mNeighborMapWidth * y_pos);
888 mNeighborMap[index - 1]++;
889 mNeighborMap[index + 1]++;
890 mNeighborMap[index - mNeighborMapWidth]++;
891 mNeighborMap[index + mNeighborMapWidth]++;
892 }
893
894 for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
895 {
896 U64 handle = (*it).first;
897 LLSimInfo* info = (*it).second;
898
899 U32 x_pos, y_pos;
900 from_region_handle(handle, &x_pos, &y_pos);
901 x_pos /= REGION_WIDTH_UNITS;
902 y_pos /= REGION_WIDTH_UNITS;
903 x_pos -= min_x;
904 y_pos -= min_y;
905
906 S32 index = x_pos + (mNeighborMapWidth * y_pos);
907
908 if (!info->mTelehubName.empty() && mNeighborMap[index])
909 {
910 S32 x_start = llmax(0, S32(x_pos - 5));
911 S32 x_span = llmin(mNeighborMapWidth - 1, (S32)(x_pos + 5)) - x_start + 1;
912 S32 y_start = llmax(0, (S32)y_pos - 5);
913 S32 y_end = llmin(mNeighborMapHeight - 1, (S32)(y_pos + 5));
914 for (S32 y_index = y_start; y_index <= y_end; y_index++)
915 {
916 memset(&mTelehubCoverageMap[x_start + y_index * mNeighborMapWidth], 0xff, sizeof(U8) * x_span);
917 }
918 }
919 }
920
921 for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
922 {
923 U64 handle = (*it).first;
924 //LLSimInfo* info = (*it).second;
925
926 U32 x_pos, y_pos;
927 from_region_handle(handle, &x_pos, &y_pos);
928 x_pos /= REGION_WIDTH_UNITS;
929 y_pos /= REGION_WIDTH_UNITS;
930
931 S32 index = x_pos - min_x + (mNeighborMapWidth * (y_pos - min_y));
932 mTelehubCoverageMap[index] *= mNeighborMap[index];
933 }*/
934}