/** * @file llworldmap.cpp * @brief Underlying data representation for map of the world * * $LicenseInfo:firstyear=2003&license=viewergpl$ * * Copyright (c) 2003-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #include "llworldmap.h" #include "llregionhandle.h" #include "message.h" #include "llappviewer.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" #include "hippogridmanager.h" bool LLWorldMap::sGotMapURL = false; const F32 REQUEST_ITEMS_TIMER = 10.f * 60.f; // 10 minutes // For DEV-17507, do lazy image loading in llworldmapview.cpp instead, // limiting requests to currently visible regions and minimizing the // number of textures being requested simultaneously. // // Uncomment IMMEDIATE_IMAGE_LOAD to restore the old behavior // //#define IMMEDIATE_IMAGE_LOAD 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), mShowAgentLocations(FALSE), mAccess(0x0), mRegionFlags(0x0), mWaterHeight(0.f), mAlpha(-1.f) { } LLVector3d LLSimInfo::getGlobalOrigin() const { return from_region_handle(mHandle); } 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), mSLURLRegionName(), mSLURLRegionHandle(0), mSLURL(), mSLURLCallback(0), mSLURLTeleport(false) { for (S32 map=0; map REQUEST_ITEMS_TIMER) { mRequestTimer.reset(); mTelehubs.clear(); mInfohubs.clear(); mPGEvents.clear(); mMatureEvents.clear(); mAdultEvents.clear(); mLandForSale.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; mapmName)) ) { break; } sim_info = NULL; } } return sim_info; } bool LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global, std::string & outSimName ) { bool gotSimName = true; U64 handle = to_region_handle(pos_global); sim_info_map_t::iterator it = mSimInfoMap.find(handle); if (it != mSimInfoMap.end()) { LLSimInfo* info = (*it).second; outSimName = info->mName; } else { gotSimName = false; outSimName = "(unknown region)"; } return gotSimName; } void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer) { mCurrentMap = layer; if (!mMapLoaded[layer] || request_layer) { sendMapLayerRequest(); } 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 (mAdultEvents.size() == 0) { // Request for events (adult) sendItemRequest(MAP_ITEM_ADULT_EVENT); } if (mLandForSale.size() == 0) { // Request for Land For Sale sendItemRequest(MAP_ITEM_LAND_FOR_SALE); } if (mLandForSaleAdult.size() == 0) { // Request for Land For Sale sendItemRequest(MAP_ITEM_LAND_FOR_SALE_ADULT); } 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() { if (!gAgent.getRegion()) return; 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::sendNamedRegionRequest(std::string region_name, url_callback_t callback, const std::string& callback_url, bool teleport) // immediately teleport when result returned { mSLURLRegionName = region_name; mSLURLRegionHandle = 0; mSLURL = callback_url; mSLURLCallback = callback; mSLURLTeleport = teleport; sendNamedRegionRequest(region_name); } void LLWorldMap::sendHandleRegionRequest(U64 region_handle, url_callback_t callback, const std::string& callback_url, bool teleport) // immediately teleport when result returned { mSLURLRegionName.clear(); mSLURLRegionHandle = region_handle; mSLURL = callback_url; mSLURLCallback = callback; mSLURLTeleport = teleport; U32 global_x; U32 global_y; from_region_handle(region_handle, &global_x, &global_y); U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS); U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS); sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); } // 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)LLWorldMap::getInstance()->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); LLWorldMap::getInstance()->mMapLayers[agent_flags].clear(); // bool use_web_map_tiles = useWebMapTiles(); BOOL adjust = FALSE; for (S32 block=0; blockgetUUIDFast(_PREHASH_LayerData, _PREHASH_ImageID, new_layer.LayerImageID, block); 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); // if (use_web_map_tiles) // { // new_layer.LayerImage = loadObjectsTile(left, bottom); // no good... Maybe using of level 2 and higher web maps ? // } // else // { new_layer.LayerImage = gImageList.getImage(new_layer.LayerImageID, MIPMAP_TRUE, FALSE); // } gGL.getTexUnit(0)->bind(new_layer.LayerImage.get()); new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP); 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 = LLWorldMap::getInstance()->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; LLWorldMap::getInstance()->mMapLayers[agent_flags].push_back(new_layer); } LLWorldMap::getInstance()->mMapLoaded[agent_flags] = TRUE; if(adjust) gFloaterWorldMap->adjustZoomSliderBounds(); } // public static bool LLWorldMap::useWebMapTiles() { return gSavedSettings.getBOOL("UseWebMapTiles") && (( gHippoGridManager->getConnectedGrid()->isSecondLife() || sGotMapURL) && LLWorldMap::getInstance()->mCurrentMap == 0); } // public static LLPointer LLWorldMap::loadObjectsTile(U32 grid_x, U32 grid_y) { // Get the grid coordinates std::string imageurl = gSavedSettings.getString("MapServerURL") + llformat("map-%d-%d-%d-objects.jpg", 1, grid_x, grid_y); LLPointer img = gImageList.getImageFromUrl(imageurl); img->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP); // Return the smart pointer return img; } // public static void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**) { U32 agent_flags; msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); if ((S32)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; #ifdef IMMEDIATE_IMAGE_LOAD bool use_web_map_tiles = useWebMapTiles(); #endif BOOL adjust = FALSE; for (S32 block=0; blockgetU16Fast(_PREHASH_Data, _PREHASH_X, x_regions, block); msg->getU16Fast(_PREHASH_Data, _PREHASH_Y, y_regions, block); msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block); msg->getU8Fast(_PREHASH_Data, _PREHASH_Access, accesscode, 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; U64 handle = to_region_handle(x_meters, y_meters); if (accesscode == 255) { // This region doesn't exist if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation && LLWorldMap::getInstance()->mUnknownLocation.mdV[0] >= x_meters && LLWorldMap::getInstance()->mUnknownLocation.mdV[0] < x_meters + 256 && LLWorldMap::getInstance()->mUnknownLocation.mdV[1] >= y_meters && LLWorldMap::getInstance()->mUnknownLocation.mdV[1] < y_meters + 256) { // We were tracking this location, but it doesn't exist LLWorldMap::getInstance()->mInvalidLocation = TRUE; } found_null_sim = true; } else { adjust = LLWorldMap::getInstance()->extendAABB(x_meters, y_meters, x_meters+REGION_WIDTH_UNITS, y_meters+REGION_WIDTH_UNITS) || adjust; // llinfos << "Map sim " << name << " image layer " << agent_flags << " ID " << image_id.getString() << llendl; LLSimInfo* siminfo = new LLSimInfo(); sim_info_map_t::iterator iter = LLWorldMap::getInstance()->mSimInfoMap.find(handle); if (iter != LLWorldMap::getInstance()->mSimInfoMap.end()) { LLSimInfo* oldinfo = iter->second; for (S32 image=0; imagemMapImageID[image] = oldinfo->mMapImageID[image]; } delete oldinfo; } LLWorldMap::getInstance()->mSimInfoMap[handle] = siminfo; siminfo->mHandle = handle; siminfo->mName.assign( name ); siminfo->mAccess = accesscode; siminfo->mRegionFlags = region_flags; siminfo->mWaterHeight = (F32) water_height; siminfo->mMapImageID[agent_flags] = image_id; #ifdef IMMEDIATE_IMAGE_LOAD if (use_web_map_tiles) { siminfo->mCurrentImage = loadObjectsTile((U32)x_regions, (U32)y_regions); } else { siminfo->mCurrentImage = gImageList.getImage(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE); } gGL.getTexUnit(0)->bind(siminfo->mCurrentImage.get()); siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); #endif if (siminfo->mMapImageID[2].notNull()) { #ifdef IMMEDIATE_IMAGE_LOAD siminfo->mOverlayImage = gImageList.getImage(siminfo->mMapImageID[2], MIPMAP_TRUE, FALSE); #endif } else { siminfo->mOverlayImage = NULL; } if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation && LLWorldMap::getInstance()->mUnknownLocation.mdV[0] >= x_meters && LLWorldMap::getInstance()->mUnknownLocation.mdV[0] < x_meters + 256 && LLWorldMap::getInstance()->mUnknownLocation.mdV[1] >= y_meters && LLWorldMap::getInstance()->mUnknownLocation.mdV[1] < y_meters + 256) { if (siminfo->mAccess == SIM_ACCESS_DOWN) { // We were tracking this location, but it doesn't exist LLWorldMap::getInstance()->mInvalidLocation = true; } else { // We were tracking this location, and it does exist bool is_tracking_dbl = LLWorldMap::getInstance()->mIsTrackingDoubleClick == TRUE; gFloaterWorldMap->trackLocation(LLWorldMap::getInstance()->mUnknownLocation); if (is_tracking_dbl) { LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); gAgent.teleportViaLocation( pos_global ); } } } } if(LLWorldMap::getInstance()->mSLURLCallback != NULL) { // Server returns definitive capitalization, SLURL might not have that. if ((LLStringUtil::compareInsensitive(LLWorldMap::getInstance()->mSLURLRegionName, name)==0) || (LLWorldMap::getInstance()->mSLURLRegionHandle == handle)) { url_callback_t callback = LLWorldMap::getInstance()->mSLURLCallback; LLWorldMap::getInstance()->mSLURLCallback = NULL; LLWorldMap::getInstance()->mSLURLRegionName.clear(); LLWorldMap::getInstance()->mSLURLRegionHandle = 0; callback(handle, LLWorldMap::getInstance()->mSLURL, image_id, LLWorldMap::getInstance()->mSLURLTeleport); } } if(gAgent.mLureShow) { if((x_regions == gAgent.mLureGlobalX) && (y_regions == gAgent.mLureGlobalY)) { gAgent.onFoundLureDestination(); } } } 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; blockgetU32Fast(_PREHASH_Data, _PREHASH_X, X, block); msg->getU32Fast(_PREHASH_Data, _PREHASH_Y, Y, block); msg->getStringFast(_PREHASH_Data, _PREHASH_Name, 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 = LLWorldMap::getInstance()->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) { LLWorldMap::getInstance()->mInfohubs.push_back(new_item); } else { LLWorldMap::getInstance()->mTelehubs.push_back(new_item); } break; } case MAP_ITEM_PG_EVENT: // events case MAP_ITEM_MATURE_EVENT: case MAP_ITEM_ADULT_EVENT: { 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; new_item.mToolTip = llformat( "%d:%02d %s", display_hour, timep->tm_min, (timep->tm_hour < 12 ? "AM" : "PM") ); // HACK: store Z in extra2 new_item.mPosGlobal.mdV[VZ] = (F64)extra2; if (type == MAP_ITEM_PG_EVENT) { LLWorldMap::getInstance()->mPGEvents.push_back(new_item); } else if (type == MAP_ITEM_MATURE_EVENT) { LLWorldMap::getInstance()->mMatureEvents.push_back(new_item); } else if (type == MAP_ITEM_ADULT_EVENT) { LLWorldMap::getInstance()->mAdultEvents.push_back(new_item); } break; } case MAP_ITEM_LAND_FOR_SALE: // land for sale case MAP_ITEM_LAND_FOR_SALE_ADULT: // adult land for sale { new_item.mToolTip = llformat("%d sq. m. %s%d", new_item.mExtra, gHippoGridManager->getConnectedGrid()->getCurrencySymbol().c_str(), new_item.mExtra2); if (type == MAP_ITEM_LAND_FOR_SALE) { LLWorldMap::getInstance()->mLandForSale.push_back(new_item); } else if (type == MAP_ITEM_LAND_FOR_SALE_ADULT) { LLWorldMap::getInstance()->mLandForSaleAdult.push_back(new_item); } break; } case MAP_ITEM_CLASSIFIED: // classifieds { //DEPRECATED: no longer used 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 = LLWorldMap::getInstance()->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 << " " << (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::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]; }*/ }