summaryrefslogtreecommitdiff
path: root/indra/newview/llworldmap.cpp
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
committerJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
commit420b91db29485df39fd6e724e782c449158811cb (patch)
treeb471a94563af914d3ed3edd3e856d21cb1b69945 /indra/newview/llworldmap.cpp
Print done when done.
Diffstat (limited to 'indra/newview/llworldmap.cpp')
-rw-r--r--indra/newview/llworldmap.cpp915
1 files changed, 915 insertions, 0 deletions
diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp
new file mode 100644
index 0000000000..42d8b9fd20
--- /dev/null
+++ b/indra/newview/llworldmap.cpp
@@ -0,0 +1,915 @@
+/**
+ * @file llworldmap.cpp
+ * @brief Underlying data representation for map of the world
+ *
+ * Copyright (c) 2003-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llworldmap.h"
+
+#include "llregionhandle.h"
+#include "message.h"
+
+#include "viewer.h" // for gPacificDaylightTime
+#include "llagent.h"
+#include "llmapresponders.h"
+#include "llviewercontrol.h"
+#include "llfloaterworldmap.h"
+#include "lltracker.h"
+#include "llviewerimagelist.h"
+#include "llviewerregion.h"
+#include "llregionflags.h"
+
+LLWorldMap* gWorldMap = NULL;
+
+const F32 REQUEST_ITEMS_TIMER = 10.f * 60.f; // 10 minutes
+
+LLItemInfo::LLItemInfo(F32 global_x, F32 global_y,
+ const std::string& name,
+ LLUUID id,
+ S32 extra, S32 extra2)
+: mName(name),
+ mToolTip(""),
+ mPosGlobal(global_x, global_y, 40.0),
+ mID(id),
+ mSelected(FALSE),
+ mExtra(extra),
+ mExtra2(extra2)
+{
+ mRegionHandle = to_region_handle(mPosGlobal);
+}
+
+LLSimInfo::LLSimInfo()
+: mHandle(0),
+ mName(),
+ mAgentsUpdateTime(0),
+ mAccess(0x0),
+ mRegionFlags(0x0),
+ mWaterHeight(0.f),
+ mAlpha(-1.f)
+{
+}
+
+
+LLVector3d LLSimInfo::getGlobalPos(LLVector3 local_pos) const
+{
+ LLVector3d pos = from_region_handle(mHandle);
+ pos.mdV[VX] += local_pos.mV[VX];
+ pos.mdV[VY] += local_pos.mV[VY];
+ pos.mdV[VZ] += local_pos.mV[VZ];
+ return pos;
+}
+
+
+//---------------------------------------------------------------------------
+// World Map
+//---------------------------------------------------------------------------
+
+LLWorldMap::LLWorldMap() :
+ mIsTrackingUnknownLocation( FALSE ),
+ mInvalidLocation( FALSE ),
+ mIsTrackingDoubleClick( FALSE ),
+ mIsTrackingCommit( FALSE ),
+ mUnknownLocation( 0, 0, 0 ),
+ mRequestLandForSale(true),
+ mCurrentMap(0),
+ mMinX(U32_MAX),
+ mMaxX(U32_MIN),
+ mMinY(U32_MAX),
+ mMaxY(U32_MIN),
+ mNeighborMap(NULL),
+ mTelehubCoverageMap(NULL),
+ mNeighborMapWidth(0),
+ mNeighborMapHeight(0)
+{
+ for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map)
+ {
+ mMapLoaded[map] = FALSE;
+ mMapBlockLoaded[map] = new BOOL[MAP_BLOCK_RES*MAP_BLOCK_RES];
+ for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx)
+ {
+ mMapBlockLoaded[map][idx] = FALSE;
+ }
+ }
+}
+
+
+LLWorldMap::~LLWorldMap()
+{
+ reset();
+ for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map)
+ {
+ delete[] mMapBlockLoaded[map];
+ }
+}
+
+
+void LLWorldMap::reset()
+{
+ for_each(mSimInfoMap.begin(), mSimInfoMap.end(), DeletePairedPointer());
+ mSimInfoMap.clear();
+
+ for (S32 m=0; m<MAP_SIM_IMAGE_TYPES; ++m)
+ {
+ mMapLoaded[m] = FALSE;
+ }
+
+ clearSimFlags();
+
+ eraseItems();
+
+ mMinX = U32_MAX;
+ mMaxX = U32_MIN;
+
+ mMinY = U32_MAX;
+ mMaxY = U32_MIN;
+
+ delete [] mNeighborMap;
+ mNeighborMap = NULL;
+ delete [] mTelehubCoverageMap;
+ mTelehubCoverageMap = NULL;
+
+ mNeighborMapWidth = 0;
+ mNeighborMapHeight = 0;
+}
+
+void LLWorldMap::eraseItems()
+{
+ if (mRequestTimer.getElapsedTimeF32() > REQUEST_ITEMS_TIMER)
+ {
+ mRequestTimer.reset();
+
+ mTelehubs.clear();
+ mInfohubs.clear();
+ mPGEvents.clear();
+ mMatureEvents.clear();
+ mPopular.clear();
+ mLandForSale.clear();
+ mClassifieds.clear();
+ }
+// mAgentLocationsMap.clear(); // persists
+// mNumAgents.clear(); // persists
+}
+
+
+void LLWorldMap::clearImageRefs()
+{
+ for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
+ {
+ LLSimInfo* info = (*it).second;
+ if (info->mCurrentImage)
+ {
+ info->mCurrentImage->setBoostLevel(0);
+ info->mCurrentImage = NULL;
+ }
+ if (info->mOverlayImage)
+ {
+ info->mOverlayImage->setBoostLevel(0);
+ info->mOverlayImage = NULL;
+ }
+ }
+}
+
+// Doesn't clear the already-loaded sim infos, just re-requests them
+void LLWorldMap::clearSimFlags()
+{
+ for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map)
+ {
+ for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx)
+ {
+ mMapBlockLoaded[map][idx] = FALSE;
+ }
+ }
+}
+
+LLSimInfo* LLWorldMap::simInfoFromPosGlobal(const LLVector3d& pos_global)
+{
+ U64 handle = to_region_handle(pos_global);
+ return simInfoFromHandle(handle);
+}
+
+LLSimInfo* LLWorldMap::simInfoFromHandle(const U64 handle)
+{
+ sim_info_map_t::iterator it = mSimInfoMap.find(handle);
+ if (it != mSimInfoMap.end())
+ {
+ LLSimInfo* sim_info = (*it).second;
+ if (sim_info)
+ {
+ return sim_info;
+ }
+ }
+ return NULL;
+}
+
+
+LLSimInfo* LLWorldMap::simInfoFromName(const LLString& sim_name)
+{
+ LLSimInfo* sim_info = NULL;
+ if (!sim_name.empty())
+ {
+ for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
+ {
+ sim_info = (*it).second;
+ if (sim_info
+ && (0 == LLString::compareInsensitive(sim_name.c_str(), sim_info->mName.c_str())) )
+ {
+ break;
+ }
+ sim_info = NULL;
+ }
+ }
+ return sim_info;
+}
+
+LLString LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global)
+{
+ U64 handle = to_region_handle(pos_global);
+
+ sim_info_map_t::iterator it = mSimInfoMap.find(handle);
+ if (it != mSimInfoMap.end())
+ {
+ LLSimInfo* info = (*it).second;
+ return info->mName.c_str();
+ }
+ else
+ {
+ return "(unknown region)";
+ }
+}
+
+void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer)
+{
+ mCurrentMap = layer;
+ if (!mMapLoaded[layer] || request_layer)
+ {
+ sendMapLayerRequest();
+ sendItemRequest(MAP_ITEM_AGENT_COUNT);
+ }
+
+ if (mTelehubs.size() == 0 ||
+ mInfohubs.size() == 0)
+ {
+ // Request for telehubs
+ sendItemRequest(MAP_ITEM_TELEHUB);
+ }
+
+ if (mPGEvents.size() == 0)
+ {
+ // Request for events
+ sendItemRequest(MAP_ITEM_PG_EVENT);
+ }
+
+ if (mMatureEvents.size() == 0)
+ {
+ // Request for events (mature)
+ sendItemRequest(MAP_ITEM_MATURE_EVENT);
+ }
+
+ if (mPopular.size() == 0)
+ {
+ // Request for popular
+ sendItemRequest(MAP_ITEM_POPULAR);
+ }
+
+ if (mLandForSale.size() == 0)
+ {
+ // Request for Land For Sale
+ sendItemRequest(MAP_ITEM_LAND_FOR_SALE);
+ }
+
+ if (mClassifieds.size() == 0)
+ {
+ sendItemRequest(MAP_ITEM_CLASSIFIED);
+ }
+
+ clearImageRefs();
+ clearSimFlags();
+}
+
+void LLWorldMap::sendItemRequest(U32 type, U64 handle)
+{
+ LLMessageSystem* msg = gMessageSystem;
+ S32 layer = mCurrentMap;
+
+ msg->newMessageFast(_PREHASH_MapItemRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addU32Fast(_PREHASH_Flags, layer);
+ msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
+ msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
+
+ msg->nextBlockFast(_PREHASH_RequestData);
+ msg->addU32Fast(_PREHASH_ItemType, type);
+ msg->addU64Fast(_PREHASH_RegionHandle, handle); // If zero, filled in on sim
+
+ gAgent.sendReliableMessage();
+}
+
+// public
+void LLWorldMap::sendMapLayerRequest()
+{
+ LLSD body;
+ body["Flags"] = mCurrentMap;
+ std::string url = gAgent.getRegion()->getCapability(
+ gAgent.isGodlike() ? "MapLayerGod" : "MapLayer");
+
+ if (!url.empty())
+ {
+ llinfos << "LLWorldMap::sendMapLayerRequest via capability" << llendl;
+ LLHTTPClient::post(url, body, new LLMapLayerResponder());
+ }
+ else
+ {
+ llinfos << "LLWorldMap::sendMapLayerRequest via message system" << llendl;
+ LLMessageSystem* msg = gMessageSystem;
+ S32 layer = mCurrentMap;
+
+ // Request for layer
+ msg->newMessageFast(_PREHASH_MapLayerRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addU32Fast(_PREHASH_Flags, layer);
+ msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
+ msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
+ gAgent.sendReliableMessage();
+
+ if (mRequestLandForSale)
+ {
+ msg->newMessageFast(_PREHASH_MapLayerRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addU32Fast(_PREHASH_Flags, 2);
+ msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
+ msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
+ gAgent.sendReliableMessage();
+ }
+ }
+}
+
+// public
+void LLWorldMap::sendNamedRegionRequest(std::string region_name)
+{
+ LLMessageSystem* msg = gMessageSystem;
+ S32 layer = mCurrentMap;
+
+ // Request for layer
+ msg->newMessageFast(_PREHASH_MapNameRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addU32Fast(_PREHASH_Flags, layer);
+ msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
+ msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
+ msg->nextBlockFast(_PREHASH_NameData);
+ msg->addStringFast(_PREHASH_Name, region_name);
+ gAgent.sendReliableMessage();
+}
+
+// public
+void LLWorldMap::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent)
+{
+ S32 layer = mCurrentMap;
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_MapBlockRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ U32 flags = layer;
+ flags |= (return_nonexistent ? 0x10000 : 0);
+ msg->addU32Fast(_PREHASH_Flags, flags);
+ msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
+ msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
+ msg->nextBlockFast(_PREHASH_PositionData);
+ msg->addU16Fast(_PREHASH_MinX, min_x);
+ msg->addU16Fast(_PREHASH_MinY, min_y);
+ msg->addU16Fast(_PREHASH_MaxX, max_x);
+ msg->addU16Fast(_PREHASH_MaxY, max_y);
+ gAgent.sendReliableMessage();
+
+ if (mRequestLandForSale)
+ {
+ msg->newMessageFast(_PREHASH_MapBlockRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addU32Fast(_PREHASH_Flags, 2);
+ msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
+ msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
+ msg->nextBlockFast(_PREHASH_PositionData);
+ msg->addU16Fast(_PREHASH_MinX, min_x);
+ msg->addU16Fast(_PREHASH_MinY, min_y);
+ msg->addU16Fast(_PREHASH_MaxX, max_x);
+ msg->addU16Fast(_PREHASH_MaxY, max_y);
+ gAgent.sendReliableMessage();
+ }
+}
+
+// public static
+void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**)
+{
+ llinfos << "LLWorldMap::processMapLayerReply from message system" << llendl;
+
+ U32 agent_flags;
+ msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags);
+
+ if (agent_flags != (U32)gWorldMap->mCurrentMap)
+ {
+ llwarns << "Invalid or out of date map image type returned!" << llendl;
+ return;
+ }
+
+ LLUUID image_id;
+ //U32 left, right, top, bottom;
+
+ S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_LayerData);
+
+ gWorldMap->mMapLayers[agent_flags].clear();
+
+ BOOL adjust = FALSE;
+ for (S32 block=0; block<num_blocks; ++block)
+ {
+ LLWorldMapLayer new_layer;
+ new_layer.LayerDefined = TRUE;
+ msg->getUUIDFast(_PREHASH_LayerData, _PREHASH_ImageID, new_layer.LayerImageID, block);
+ new_layer.LayerImage = gImageList.getImage(new_layer.LayerImageID, MIPMAP_TRUE, FALSE);
+ new_layer.LayerImage->bindTexture(0);
+ new_layer.LayerImage->setClamp(TRUE, TRUE);
+
+ U32 left, right, top, bottom;
+ msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Left, left, block);
+ msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Right, right, block);
+ msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Top, top, block);
+ msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Bottom, bottom, block);
+
+ new_layer.LayerExtents.mLeft = left;
+ new_layer.LayerExtents.mRight = right;
+ new_layer.LayerExtents.mBottom = bottom;
+ new_layer.LayerExtents.mTop = top;
+
+ F32 x_meters = F32(left*REGION_WIDTH_UNITS);
+ F32 y_meters = F32(bottom*REGION_WIDTH_UNITS);
+ adjust = gWorldMap->extendAABB(U32(x_meters), U32(y_meters),
+ U32(x_meters+REGION_WIDTH_UNITS*new_layer.LayerExtents.getWidth()),
+ U32(y_meters+REGION_WIDTH_UNITS*new_layer.LayerExtents.getHeight())) || adjust;
+
+ gWorldMap->mMapLayers[agent_flags].push_back(new_layer);
+ }
+
+ gWorldMap->mMapLoaded[agent_flags] = TRUE;
+ if(adjust) gFloaterWorldMap->adjustZoomSliderBounds();
+}
+
+// public static
+void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**)
+{
+ U32 agent_flags;
+ msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags);
+
+ if (agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES)
+ {
+ llwarns << "Invalid map image type returned! " << agent_flags << llendl;
+ return;
+ }
+
+ S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data);
+
+ bool found_null_sim = false;
+
+ BOOL adjust = FALSE;
+ for (S32 block=0; block<num_blocks; ++block)
+ {
+ U16 x_regions;
+ U16 y_regions;
+ char name[MAX_STRING];
+ U8 access;
+ U32 region_flags;
+ U8 water_height;
+ U8 agents;
+ LLUUID image_id;
+ msg->getU16Fast(_PREHASH_Data, _PREHASH_X, x_regions, block);
+ msg->getU16Fast(_PREHASH_Data, _PREHASH_Y, y_regions, block);
+ msg->getStringFast(_PREHASH_Data, _PREHASH_Name, MAX_STRING, name, block);
+ msg->getU8Fast(_PREHASH_Data, _PREHASH_Access, access, block);
+ msg->getU32Fast(_PREHASH_Data, _PREHASH_RegionFlags, region_flags, block);
+ msg->getU8Fast(_PREHASH_Data, _PREHASH_WaterHeight, water_height, block);
+ msg->getU8Fast(_PREHASH_Data, _PREHASH_Agents, agents, block);
+ msg->getUUIDFast(_PREHASH_Data, _PREHASH_MapImageID, image_id, block);
+
+ U32 x_meters = x_regions * REGION_WIDTH_UNITS;
+ U32 y_meters = y_regions * REGION_WIDTH_UNITS;
+
+ if (access == 255)
+ {
+ // This region doesn't exist
+ if (gWorldMap->mIsTrackingUnknownLocation &&
+ gWorldMap->mUnknownLocation.mdV[0] >= x_meters &&
+ gWorldMap->mUnknownLocation.mdV[0] < x_meters + 256 &&
+ gWorldMap->mUnknownLocation.mdV[1] >= y_meters &&
+ gWorldMap->mUnknownLocation.mdV[1] < y_meters + 256)
+ {
+ // We were tracking this location, but it doesn't exist
+ gWorldMap->mInvalidLocation = TRUE;
+ }
+
+ found_null_sim = true;
+ }
+ else
+ {
+ adjust = gWorldMap->extendAABB(x_meters,
+ y_meters,
+ x_meters+REGION_WIDTH_UNITS,
+ y_meters+REGION_WIDTH_UNITS) || adjust;
+ U64 handle = to_region_handle(x_meters, y_meters);
+
+// llinfos << "Map sim " << name << " image layer " << agent_flags << " ID " << image_id.getString() << llendl;
+
+ LLSimInfo* siminfo = new LLSimInfo();
+ sim_info_map_t::iterator iter = gWorldMap->mSimInfoMap.find(handle);
+ if (iter != gWorldMap->mSimInfoMap.end())
+ {
+ LLSimInfo* oldinfo = iter->second;
+ for (S32 image=0; image<MAP_SIM_IMAGE_TYPES; ++image)
+ {
+ siminfo->mMapImageID[image] = oldinfo->mMapImageID[image];
+ }
+ delete oldinfo;
+ }
+ gWorldMap->mSimInfoMap[handle] = siminfo;
+
+ siminfo->mHandle = handle;
+ siminfo->mName.assign( name );
+ siminfo->mAccess = access;
+ siminfo->mRegionFlags = region_flags;
+ siminfo->mWaterHeight = (F32) water_height;
+ siminfo->mMapImageID[agent_flags] = image_id;
+ siminfo->mCurrentImage = gImageList.getImage(siminfo->mMapImageID[gWorldMap->mCurrentMap], MIPMAP_TRUE, FALSE);
+ siminfo->mCurrentImage->bindTexture(0);
+ siminfo->mCurrentImage->setClamp(TRUE, TRUE);
+
+ if (siminfo->mMapImageID[2].notNull())
+ {
+ siminfo->mOverlayImage = gImageList.getImage(siminfo->mMapImageID[2], MIPMAP_TRUE, FALSE);
+ }
+ else
+ {
+ siminfo->mOverlayImage = NULL;
+ }
+
+ if (gWorldMap->mIsTrackingUnknownLocation &&
+ gWorldMap->mUnknownLocation.mdV[0] >= x_meters &&
+ gWorldMap->mUnknownLocation.mdV[0] < x_meters + 256 &&
+ gWorldMap->mUnknownLocation.mdV[1] >= y_meters &&
+ gWorldMap->mUnknownLocation.mdV[1] < y_meters + 256)
+ {
+ if (siminfo->mAccess == SIM_ACCESS_DOWN)
+ {
+ // We were tracking this location, but it doesn't exist
+ gWorldMap->mInvalidLocation = true;
+ }
+ else
+ {
+ // We were tracking this location, and it does exist
+ bool is_tracking_dbl = gWorldMap->mIsTrackingDoubleClick == TRUE;
+ gFloaterWorldMap->trackLocation(gWorldMap->mUnknownLocation);
+ if (is_tracking_dbl)
+ {
+ LLVector3d pos_global = LLTracker::getTrackedPositionGlobal();
+ gAgent.teleportViaLocation( pos_global );
+ }
+ }
+ }
+ }
+ }
+ if(adjust) gFloaterWorldMap->adjustZoomSliderBounds();
+ gFloaterWorldMap->updateSims(found_null_sim);
+}
+
+// public static
+void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**)
+{
+ U32 type;
+ msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type);
+
+ S32 num_blocks = msg->getNumberOfBlocks("Data");
+
+ for (S32 block=0; block<num_blocks; ++block)
+ {
+ U32 X, Y;
+ char name[MAX_STRING];
+ S32 extra, extra2;
+ LLUUID uuid;
+ msg->getU32Fast(_PREHASH_Data, _PREHASH_X, X, block);
+ msg->getU32Fast(_PREHASH_Data, _PREHASH_Y, Y, block);
+ msg->getStringFast(_PREHASH_Data, _PREHASH_Name, MAX_STRING, name, block);
+ msg->getUUIDFast(_PREHASH_Data, _PREHASH_ID, uuid, block);
+ msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra, extra, block);
+ msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra2, extra2, block);
+
+ F32 world_x = (F32)X;
+ X /= REGION_WIDTH_UNITS;
+ F32 world_y = (F32)Y;
+ Y /= REGION_WIDTH_UNITS;
+
+ LLItemInfo new_item(world_x, world_y, name, uuid, extra, extra2);
+ LLSimInfo* siminfo = gWorldMap->simInfoFromHandle(new_item.mRegionHandle);
+
+ switch (type)
+ {
+ case MAP_ITEM_TELEHUB: // telehubs
+ {
+ // Telehub color, store in extra as 4 U8's
+ U8 *color = (U8 *)&new_item.mExtra;
+
+ F32 red = fmod((F32)X * 0.11f, 1.f) * 0.8f;
+ F32 green = fmod((F32)Y * 0.11f, 1.f) * 0.8f;
+ F32 blue = fmod(1.5f * (F32)(X + Y) * 0.11f, 1.f) * 0.8f;
+ F32 add_amt = (X % 2) ? 0.15f : -0.15f;
+ add_amt += (Y % 2) ? -0.15f : 0.15f;
+ color[0] = U8((red + add_amt) * 255);
+ color[1] = U8((green + add_amt) * 255);
+ color[2] = U8((blue + add_amt) * 255);
+ color[3] = 255;
+
+ // extra2 specifies whether this is an infohub or a telehub.
+ if (extra2)
+ {
+ gWorldMap->mInfohubs.push_back(new_item);
+ }
+ else
+ {
+ gWorldMap->mTelehubs.push_back(new_item);
+ }
+
+ break;
+ }
+ case MAP_ITEM_PG_EVENT: // events
+ case MAP_ITEM_MATURE_EVENT:
+ {
+ char buffer[32];
+ struct tm* timep;
+ // Convert to Pacific, based on server's opinion of whether
+ // it's daylight savings time there.
+ timep = utc_to_pacific_time(extra, gPacificDaylightTime);
+
+ S32 display_hour = timep->tm_hour % 12;
+ if (display_hour == 0) display_hour = 12;
+
+ sprintf(buffer, "%d:%02d %s",
+ display_hour,
+ timep->tm_min,
+ (timep->tm_hour < 12 ? "AM" : "PM") );
+ new_item.mToolTip.assign( buffer );
+
+ // HACK: store Z in extra2
+ new_item.mPosGlobal.mdV[VZ] = (F64)extra2;
+ if (type == MAP_ITEM_PG_EVENT)
+ {
+ gWorldMap->mPGEvents.push_back(new_item);
+ }
+ else
+ {
+ gWorldMap->mMatureEvents.push_back(new_item);
+ }
+ break;
+ }
+ case MAP_ITEM_POPULAR: // popular
+ {
+ new_item.mPosGlobal.mdV[VZ] = (F64)extra2;
+ gWorldMap->mPopular.push_back(new_item);
+ break;
+ }
+ case MAP_ITEM_LAND_FOR_SALE: // land for sale
+ {
+ new_item.mToolTip = llformat("%d sq. m. L$%d", new_item.mExtra, new_item.mExtra2);
+ gWorldMap->mLandForSale.push_back(new_item);
+ break;
+ }
+ case MAP_ITEM_CLASSIFIED: // classifieds
+ {
+ // HACK: Z-height is in Extra2 field.
+ new_item.mPosGlobal.mdV[VZ] = (F64)extra2;
+ gWorldMap->mClassifieds.push_back(new_item);
+ break;
+ }
+ case MAP_ITEM_AGENT_COUNT: // agent counts
+ {
+ // We only ever receive one per region, i.e. this update superceeds any others
+ gWorldMap->mNumAgents[new_item.mRegionHandle] = new_item.mExtra;
+ break;
+ }
+ case MAP_ITEM_AGENT_LOCATIONS: // agent locations
+ {
+ if (!siminfo)
+ {
+ llinfos << "siminfo missing for " << new_item.mPosGlobal.mdV[0] << ", " << new_item.mPosGlobal.mdV[1] << llendl;
+ break;
+ }
+// llinfos << "New Location " << new_item.mName << llendl;
+
+ item_info_list_t& agentcounts = gWorldMap->mAgentLocationsMap[new_item.mRegionHandle];
+
+ // Find the last item in the list with a different name and erase them
+ item_info_list_t::iterator lastiter;
+ for (lastiter = agentcounts.begin(); lastiter!=agentcounts.end(); ++lastiter)
+ {
+ const LLItemInfo& info = *lastiter;
+ if (info.mName == new_item.mName)
+ {
+ break;
+ }
+ }
+ if (lastiter != agentcounts.begin())
+ {
+ agentcounts.erase(agentcounts.begin(), lastiter);
+ }
+ // Now append the new location
+ if (new_item.mExtra > 0)
+ {
+ agentcounts.push_back(new_item);
+ }
+ break;
+ }
+ default:
+ break;
+ };
+ }
+}
+
+void LLWorldMap::dump()
+{
+ for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
+ {
+ U64 handle = (*it).first;
+ LLSimInfo* info = (*it).second;
+
+ U32 x_pos, y_pos;
+ from_region_handle(handle, &x_pos, &y_pos);
+
+ llinfos << x_pos << "," << y_pos
+ << " " << info->mName.c_str()
+ << " " << (S32)info->mAccess
+ << " " << std::hex << info->mRegionFlags << std::dec
+ << " " << info->mWaterHeight
+ //<< " " << info->mTelehubName
+ //<< " " << info->mTelehubPosition
+ << llendl;
+
+ if (info->mCurrentImage)
+ {
+ llinfos << "image discard " << (S32)info->mCurrentImage->getDiscardLevel()
+ << " fullwidth " << info->mCurrentImage->getWidth(0)
+ << " fullheight " << info->mCurrentImage->getHeight(0)
+ << " maxvirt " << info->mCurrentImage->mMaxVirtualSize
+ << " maxdisc " << (S32)info->mCurrentImage->getMaxDiscardLevel()
+ << llendl;
+ }
+ }
+}
+
+
+BOOL LLWorldMap::extendAABB(U32 min_x, U32 min_y, U32 max_x, U32 max_y)
+{
+ BOOL rv = FALSE;
+ if (min_x < mMinX)
+ {
+ rv = TRUE;
+ mMinX = min_x;
+ }
+ if (min_y < mMinY)
+ {
+ rv = TRUE;
+ mMinY = min_y;
+ }
+ if (max_x > mMaxX)
+ {
+ rv = TRUE;
+ mMaxX = max_x;
+ }
+ if (max_y > mMaxY)
+ {
+ rv = TRUE;
+ mMaxY = max_y;
+ }
+ lldebugs << "World map aabb: (" << mMinX << ", " << mMinY << "), ("
+ << mMaxX << ", " << mMaxY << ")" << llendl;
+ return rv;
+}
+
+
+U32 LLWorldMap::getWorldWidth() const
+{
+ return mMaxX - mMinX;
+}
+
+
+U32 LLWorldMap::getWorldHeight() const
+{
+ return mMaxY - mMinY;
+}
+
+BOOL LLWorldMap::coveredByTelehub(LLSimInfo* infop)
+{
+ /*if (!mTelehubCoverageMap)
+ {
+ return FALSE;
+ }
+ U32 x_pos, y_pos;
+ from_region_handle(infop->mHandle, &x_pos, &y_pos);
+ x_pos /= REGION_WIDTH_UNITS;
+ y_pos /= REGION_WIDTH_UNITS;
+
+ S32 index = x_pos - (mMinX / REGION_WIDTH_UNITS - 1) + (mNeighborMapWidth * (y_pos - (mMinY / REGION_WIDTH_UNITS - 1)));
+ return mTelehubCoverageMap[index] != 0; */
+ return FALSE;
+}
+
+void LLWorldMap::updateTelehubCoverage()
+{
+ /*S32 neighbor_width = getWorldWidth() / REGION_WIDTH_UNITS + 2;
+ S32 neighbor_height = getWorldHeight() / REGION_WIDTH_UNITS + 2;
+ if (neighbor_width > mNeighborMapWidth || neighbor_height > mNeighborMapHeight)
+ {
+ mNeighborMapWidth = neighbor_width;
+ mNeighborMapHeight = neighbor_height;
+ delete mNeighborMap;
+ delete mTelehubCoverageMap;
+
+ mNeighborMap = new U8[mNeighborMapWidth * mNeighborMapHeight];
+ mTelehubCoverageMap = new U8[mNeighborMapWidth * mNeighborMapHeight];
+ }
+
+ memset(mNeighborMap, 0, mNeighborMapWidth * mNeighborMapHeight * sizeof(U8));
+ memset(mTelehubCoverageMap, 0, mNeighborMapWidth * mNeighborMapHeight * sizeof(U8));
+
+ // leave 1 sim border
+ S32 min_x = (mMinX / REGION_WIDTH_UNITS) - 1;
+ S32 min_y = (mMinY / REGION_WIDTH_UNITS) - 1;
+
+ std::map<U64, LLSimInfo*>::const_iterator it;
+ for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
+ {
+ U64 handle = (*it).first;
+ //LLSimInfo* info = (*it).second;
+
+ U32 x_pos, y_pos;
+ from_region_handle(handle, &x_pos, &y_pos);
+ x_pos /= REGION_WIDTH_UNITS;
+ y_pos /= REGION_WIDTH_UNITS;
+ x_pos -= min_x;
+ y_pos -= min_y;
+
+ S32 index = x_pos + (mNeighborMapWidth * y_pos);
+ mNeighborMap[index - 1]++;
+ mNeighborMap[index + 1]++;
+ mNeighborMap[index - mNeighborMapWidth]++;
+ mNeighborMap[index + mNeighborMapWidth]++;
+ }
+
+ for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
+ {
+ U64 handle = (*it).first;
+ LLSimInfo* info = (*it).second;
+
+ U32 x_pos, y_pos;
+ from_region_handle(handle, &x_pos, &y_pos);
+ x_pos /= REGION_WIDTH_UNITS;
+ y_pos /= REGION_WIDTH_UNITS;
+ x_pos -= min_x;
+ y_pos -= min_y;
+
+ S32 index = x_pos + (mNeighborMapWidth * y_pos);
+
+ if (!info->mTelehubName.empty() && mNeighborMap[index])
+ {
+ S32 x_start = llmax(0, S32(x_pos - 5));
+ S32 x_span = llmin(mNeighborMapWidth - 1, (S32)(x_pos + 5)) - x_start + 1;
+ S32 y_start = llmax(0, (S32)y_pos - 5);
+ S32 y_end = llmin(mNeighborMapHeight - 1, (S32)(y_pos + 5));
+ for (S32 y_index = y_start; y_index <= y_end; y_index++)
+ {
+ memset(&mTelehubCoverageMap[x_start + y_index * mNeighborMapWidth], 0xff, sizeof(U8) * x_span);
+ }
+ }
+ }
+
+ for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
+ {
+ U64 handle = (*it).first;
+ //LLSimInfo* info = (*it).second;
+
+ U32 x_pos, y_pos;
+ from_region_handle(handle, &x_pos, &y_pos);
+ x_pos /= REGION_WIDTH_UNITS;
+ y_pos /= REGION_WIDTH_UNITS;
+
+ S32 index = x_pos - min_x + (mNeighborMapWidth * (y_pos - min_y));
+ mTelehubCoverageMap[index] *= mNeighborMap[index];
+ }*/
+}