llviewerregion.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llviewerregion.h"
00035 
00036 #include "indra_constants.h"
00037 #include "llmath.h"
00038 #include "llhttpclient.h"
00039 #include "llregionflags.h"
00040 #include "llregionhandle.h"
00041 #include "llsurface.h"
00042 #include "message.h"
00043 //#include "vmath.h"
00044 #include "v3math.h"
00045 #include "v4math.h"
00046 
00047 #include "llagent.h"
00048 #include "llcallingcard.h"
00049 #include "llcaphttpsender.h"
00050 #include "lldir.h"
00051 #include "lleventpoll.h"
00052 #include "llfloatergodtools.h"
00053 #include "llfloaterreleasemsg.h"
00054 #include "llfloaterreporter.h"
00055 #include "llfloaterregioninfo.h"
00056 #include "llhttpnode.h"
00057 #include "llnetmap.h"
00058 #include "llsdutil.h"
00059 #include "llstartup.h"
00060 #include "llviewerobjectlist.h"
00061 #include "llviewerparceloverlay.h"
00062 #include "llvlmanager.h"
00063 #include "llvlcomposition.h"
00064 #include "llvocache.h"
00065 #include "llvoclouds.h"
00066 #include "llworld.h"
00067 #include "llspatialpartition.h"
00068 
00069 // Viewer object cache version, change if object update
00070 // format changes. JC
00071 const U32 INDRA_OBJECT_CACHE_VERSION = 14;
00072 
00073 
00074 extern BOOL gNoRender;
00075 
00076 const F32 WATER_TEXTURE_SCALE = 8.f;                    //  Number of times to repeat the water texture across a region
00077 const S16 MAX_MAP_DIST = 10;
00078 
00079 
00080 
00081 
00082 LLViewerRegion::LLViewerRegion(const U64 &handle,
00083                                                            const LLHost &host,
00084                                                            const U32 grids_per_region_edge, 
00085                                                            const U32 grids_per_patch_edge, 
00086                                                            const F32 region_width_meters)
00087 :       mCenterGlobal(),
00088         mHandle(handle),
00089         mHost( host ),
00090         mTimeDilation(1.0f),
00091         mName(""),
00092         mZoning(""),
00093         mOwnerID(),
00094         mIsEstateManager(FALSE),
00095         mCompositionp(NULL),
00096         mRegionFlags( REGION_FLAGS_DEFAULT ),
00097         mSimAccess( SIM_ACCESS_MIN ),
00098         mBillableFactor(1.0),
00099         mMaxTasks(MAX_TASKS_PER_REGION),
00100         mCacheLoaded(FALSE),
00101         mCacheEntriesCount(0),
00102         mCacheID(),
00103         mEventPoll(NULL)
00104 {
00105         mWidth = region_width_meters;
00106 
00107         mOriginGlobal = from_region_handle(handle); 
00108         updateRenderMatrix();
00109 
00110         mLandp = new LLSurface('l', NULL);
00111         if (!gNoRender)
00112         {
00113                 // Create the composition layer for the surface
00114                 mCompositionp = new LLVLComposition(mLandp, grids_per_region_edge, region_width_meters/grids_per_region_edge);
00115                 mCompositionp->setSurface(mLandp);
00116 
00117                 // Create the surfaces
00118                 mLandp->setRegion(this);
00119                 mLandp->create(grids_per_region_edge,
00120                                                 grids_per_patch_edge,
00121                                                 mOriginGlobal,
00122                                                 mWidth);
00123         }
00124 
00125         if (!gNoRender)
00126         {
00127                 mParcelOverlay = new LLViewerParcelOverlay(this, region_width_meters);
00128         }
00129         else
00130         {
00131                 mParcelOverlay = NULL;
00132         }
00133 
00134         setOriginGlobal(from_region_handle(handle));
00135         calculateCenterGlobal();
00136 
00137         // Create the object lists
00138         initStats();
00139 
00140         mCacheStart.append(mCacheEnd);
00141         
00142         //create object partitions
00143         //MUST MATCH declaration of eObjectPartitions
00144         mObjectPartition.push_back(new LLHUDPartition());               //PARTITION_HUD
00145         mObjectPartition.push_back(new LLTerrainPartition());   //PARTITION_TERRAIN
00146         mObjectPartition.push_back(new LLWaterPartition());             //PARTITION_WATER
00147         mObjectPartition.push_back(new LLTreePartition());              //PARTITION_TREE
00148         mObjectPartition.push_back(new LLParticlePartition());  //PARTITION_PARTICLE
00149         mObjectPartition.push_back(new LLCloudPartition());             //PARTITION_CLOUD
00150         mObjectPartition.push_back(new LLGrassPartition());             //PARTITION_GRASS
00151         mObjectPartition.push_back(new LLVolumePartition());    //PARTITION_VOLUME
00152         mObjectPartition.push_back(new LLBridgePartition());    //PARTITION_BRIDGE
00153         mObjectPartition.push_back(NULL);                                               //PARTITION_NONE
00154         
00155 }
00156 
00157 
00158 void LLViewerRegion::initStats()
00159 {
00160         mLastNetUpdate.reset();
00161         mPacketsIn = 0;
00162         mBitsIn = 0;
00163         mLastBitsIn = 0;
00164         mLastPacketsIn = 0;
00165         mPacketsOut = 0;
00166         mLastPacketsOut = 0;
00167         mPacketsLost = 0;
00168         mLastPacketsLost = 0;
00169         mPingDelay = 0;
00170         mAlive = FALSE;                                 // can become false if circuit disconnects
00171 }
00172 
00173 
00174 
00175 LLViewerRegion::~LLViewerRegion() 
00176 {
00177         gVLManager.cleanupData(this);
00178         // Can't do this on destruction, because the neighbor pointers might be invalid.
00179         // This should be reference counted...
00180         disconnectAllNeighbors();
00181         mCloudLayer.destroy();
00182         LLViewerPartSim::getInstance()->cleanupRegion(this);
00183 
00184         gObjectList.killObjects(this);
00185 
00186         delete mCompositionp;
00187         delete mParcelOverlay;
00188         delete mLandp;
00189         delete mEventPoll;
00190         LLHTTPSender::clearSender(mHost);
00191         
00192         saveCache();
00193 
00194         std::for_each(mObjectPartition.begin(), mObjectPartition.end(), DeletePointer());
00195 }
00196 
00197 
00198 void LLViewerRegion::loadCache()
00199 {
00200         if (mCacheLoaded)
00201         {
00202                 return;
00203         }
00204 
00205         // Presume success.  If it fails, we don't want to try again.
00206         mCacheLoaded = TRUE;
00207 
00208         LLVOCacheEntry *entry;
00209 
00210         char filename[256];             /* Flawfinder: ignore */
00211         snprintf(filename, sizeof(filename), "%s%sobjects_%d_%d.slc",           /* Flawfinder: ignore */
00212                 gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(), 
00213                 gDirUtilp->getDirDelimiter().c_str(),
00214                 U32(mHandle>>32)/REGION_WIDTH_UNITS, 
00215                 U32(mHandle)/REGION_WIDTH_UNITS );
00216 
00217         LLFILE* fp = LLFile::fopen(filename, "rb");             /* Flawfinder: ignore */
00218         if (!fp)
00219         {
00220                 // might not have a file, which is normal
00221                 return;
00222         }
00223 
00224         U32 zero;
00225         size_t nread;
00226         nread = fread(&zero, sizeof(U32), 1, fp);
00227         if (nread != 1 || zero)
00228         {
00229                 // a non-zero value here means bad things!
00230                 // skip reading the cached values
00231                 llinfos << "Cache file invalid" << llendl;
00232                 fclose(fp);
00233                 return;
00234         }
00235 
00236         U32 version;
00237         nread = fread(&version, sizeof(U32), 1, fp);
00238         if (nread != 1 || version != INDRA_OBJECT_CACHE_VERSION)
00239         {
00240                 // a version mismatch here means we've changed the binary format!
00241                 // skip reading the cached values
00242                 llinfos << "Cache version changed, discarding" << llendl;
00243                 fclose(fp);
00244                 return;
00245         }
00246 
00247         LLUUID cache_id;
00248         nread = fread(&cache_id.mData, 1, UUID_BYTES, fp);
00249         if (nread != UUID_BYTES || mCacheID != cache_id)
00250         {
00251                 llinfos << "Cache ID doesn't match for this region, discarding"
00252                         << llendl;
00253                 fclose(fp);
00254                 return;
00255         }
00256 
00257         S32 num_entries;
00258         nread = fread(&num_entries, sizeof(S32), 1, fp);
00259         if (nread != 1)
00260         {
00261                 llinfos << "Short read, discarding" << llendl;
00262                 fclose(fp);
00263                 return;
00264         }
00265         
00266         S32 i;
00267         for (i = 0; i < num_entries; i++)
00268         {
00269                 entry = new LLVOCacheEntry(fp);
00270                 if (!entry->getLocalID())
00271                 {
00272                         llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl;
00273                         delete entry;
00274                         entry = NULL;
00275                         break;
00276                 }
00277                 mCacheEnd.insert(*entry);
00278                 mCacheMap[entry->getLocalID()] = entry;
00279                 mCacheEntriesCount++;
00280         }
00281 
00282         fclose(fp);
00283 }
00284 
00285 
00286 void LLViewerRegion::saveCache()
00287 {
00288         if (!mCacheLoaded)
00289         {
00290                 return;
00291         }
00292 
00293         S32 num_entries = mCacheEntriesCount;
00294         if (0 == num_entries)
00295         {
00296                 return;
00297         }
00298 
00299         char filename[256];             /* Flawfinder: ignore */
00300         snprintf(filename, sizeof(filename), "%s%sobjects_%d_%d.slc",           /* Flawfinder: ignore */
00301                 gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(), 
00302                 gDirUtilp->getDirDelimiter().c_str(),
00303                 U32(mHandle>>32)/REGION_WIDTH_UNITS, 
00304                 U32(mHandle)/REGION_WIDTH_UNITS );
00305 
00306         LLFILE* fp = LLFile::fopen(filename, "wb");             /* Flawfinder: ignore */
00307         if (!fp)
00308         {
00309                 llwarns << "Unable to write cache file " << filename << llendl;
00310                 return;
00311         }
00312 
00313         // write out zero to indicate a version cache file
00314         U32 zero = 0;
00315         if (fwrite(&zero, sizeof(U32), 1, fp) != 1)
00316         {
00317                 llwarns << "Short write" << llendl;
00318         }
00319 
00320         // write out version number
00321         U32 version = INDRA_OBJECT_CACHE_VERSION;
00322         if (fwrite(&version, sizeof(U32), 1, fp) != 1)
00323         {
00324                 llwarns << "Short write" << llendl;
00325         }
00326 
00327         // write the cache id for this sim
00328         if (fwrite(&mCacheID.mData, 1, UUID_BYTES, fp) != UUID_BYTES)
00329         {
00330                 llwarns << "Short write" << llendl;
00331         }
00332 
00333         if (fwrite(&num_entries, sizeof(S32), 1, fp) != 1)
00334         {
00335                 llwarns << "Short write" << llendl;
00336         }
00337 
00338         LLVOCacheEntry *entry;
00339 
00340         for (entry = mCacheStart.getNext(); entry && (entry != &mCacheEnd); entry = entry->getNext())
00341         {
00342                 entry->writeToFile(fp);
00343         }
00344 
00345         mCacheMap.clear();
00346         mCacheEnd.unlink();
00347         mCacheEnd.init();
00348         mCacheStart.deleteAll();
00349         mCacheStart.init();
00350 
00351         fclose(fp);
00352 }
00353 
00354 void LLViewerRegion::sendMessage()
00355 {
00356         gMessageSystem->sendMessage(mHost);
00357 }
00358 
00359 void LLViewerRegion::sendReliableMessage()
00360 {
00361         gMessageSystem->sendReliable(mHost);
00362 }
00363 
00364 void LLViewerRegion::setFlags(BOOL b, U32 flags)
00365 {
00366         if (b)
00367         {
00368                 mRegionFlags |=  flags;
00369         }
00370         else
00371         {
00372                 mRegionFlags &= ~flags;
00373         }
00374 }
00375 
00376 void LLViewerRegion::setWaterHeight(F32 water_level)
00377 {
00378         mLandp->setWaterHeight(water_level);
00379 }
00380 
00381 F32 LLViewerRegion::getWaterHeight() const
00382 {
00383         return mLandp->getWaterHeight();
00384 }
00385 
00386 BOOL LLViewerRegion::isVoiceEnabled() const
00387 {
00388         return (getRegionFlags() & REGION_FLAGS_ALLOW_VOICE);
00389 }
00390 
00391 void LLViewerRegion::setRegionFlags(U32 flags)
00392 {
00393         mRegionFlags = flags;
00394 }
00395 
00396 
00397 void LLViewerRegion::setOriginGlobal(const LLVector3d &origin_global) 
00398 { 
00399         mOriginGlobal = origin_global; 
00400         updateRenderMatrix();
00401         mLandp->setOriginGlobal(origin_global);
00402         mWind.setOriginGlobal(origin_global);
00403         mCloudLayer.setOriginGlobal(origin_global);
00404         calculateCenterGlobal();
00405 }
00406 
00407 void LLViewerRegion::updateRenderMatrix()
00408 {
00409         mRenderMatrix.setTranslation(getOriginAgent());
00410 }
00411 
00412 void LLViewerRegion::setTimeDilation(F32 time_dilation)
00413 {
00414         mTimeDilation = time_dilation;
00415 }
00416 
00417 
00418 LLVector3 LLViewerRegion::getOriginAgent() const
00419 {
00420         return gAgent.getPosAgentFromGlobal(mOriginGlobal);
00421 }
00422 
00423 
00424 LLVector3 LLViewerRegion::getCenterAgent() const
00425 {
00426         return gAgent.getPosAgentFromGlobal(mCenterGlobal);
00427 }
00428 
00429 void LLViewerRegion::setRegionNameAndZone(const char* name_and_zone)
00430 {
00431         LLString name_zone(name_and_zone);
00432         std::string::size_type pipe_pos = name_zone.find('|');
00433         S32 length   = name_zone.size();
00434         if (pipe_pos != std::string::npos)
00435         {
00436                 mName   = name_zone.substr(0, pipe_pos);
00437                 mZoning = name_zone.substr(pipe_pos+1, length-(pipe_pos+1));
00438         }
00439         else
00440         {
00441                 mName   = name_zone;
00442                 mZoning = "";
00443         }
00444 
00445         LLString::stripNonprintable(mName);
00446         LLString::stripNonprintable(mZoning);
00447 }
00448 
00449 BOOL LLViewerRegion::canManageEstate() const
00450 {
00451         return gAgent.isGodlike()
00452                 || isEstateManager()
00453                 || gAgent.getID() == getOwner();
00454 }
00455 
00456 const char* LLViewerRegion::getSimAccessString() const
00457 {
00458         return accessToString(mSimAccess);
00459 }
00460 
00461 
00462 // static
00463 std::string LLViewerRegion::regionFlagsToString(U32 flags)
00464 {
00465         std::string result;
00466 
00467         if (flags & REGION_FLAGS_SANDBOX)
00468         {
00469                 result += "Sandbox";
00470         }
00471 
00472         if (flags & REGION_FLAGS_ALLOW_DAMAGE)
00473         {
00474                 result += " Not Safe";
00475         }
00476 
00477         return result;
00478 }
00479 
00480 // *TODO:Translate
00481 char* SIM_ACCESS_STR[] = { "Free Trial",
00482                                                    "PG",
00483                                                    "Mature",
00484                                                    "Offline",
00485                                                    "Unknown" };
00486                                                         
00487 // static
00488 const char* LLViewerRegion::accessToString(U8 access)           /* Flawfinder: ignore */
00489 {
00490         switch(access)          /* Flawfinder: ignore */
00491         {
00492         case SIM_ACCESS_TRIAL:
00493                 return SIM_ACCESS_STR[0];
00494 
00495         case SIM_ACCESS_PG:
00496                 return SIM_ACCESS_STR[1];
00497 
00498         case SIM_ACCESS_MATURE:
00499                 return SIM_ACCESS_STR[2];
00500 
00501         case SIM_ACCESS_DOWN:
00502                 return SIM_ACCESS_STR[3];
00503 
00504         case SIM_ACCESS_MIN:
00505         default:
00506                 return SIM_ACCESS_STR[4];
00507         }
00508 }
00509 
00510 // static
00511 U8 LLViewerRegion::stringToAccess(const char* access_str)
00512 {
00513         U8 access = SIM_ACCESS_MIN;
00514         if (0 == strcmp(access_str, SIM_ACCESS_STR[0]))
00515         {
00516                 access = SIM_ACCESS_TRIAL;
00517         }
00518         else if (0 == strcmp(access_str, SIM_ACCESS_STR[1]))
00519         {
00520                 access = SIM_ACCESS_PG;
00521         }
00522         else if (0 == strcmp(access_str, SIM_ACCESS_STR[2]))
00523         {
00524                 access = SIM_ACCESS_MATURE;
00525         }
00526         return access;          /* Flawfinder: ignore */
00527 }
00528 
00529 // static
00530 const char* LLViewerRegion::accessToShortString(U8 access)              /* Flawfinder: ignore */
00531 {
00532         switch(access)          /* Flawfinder: ignore */
00533         {
00534         case SIM_ACCESS_PG:
00535                 return "PG";
00536 
00537         case SIM_ACCESS_TRIAL:
00538                 return "TR";
00539 
00540         case SIM_ACCESS_MATURE:
00541                 return "M";
00542 
00543         case SIM_ACCESS_MIN:
00544         default:
00545                 return "U";
00546         }
00547 }
00548 
00549 // static
00550 void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**)
00551 {
00552         // send it to 'observers'
00553         LLFloaterGodTools::processRegionInfo(msg);
00554         LLFloaterRegionInfo::processRegionInfo(msg);
00555         LLFloaterReporter::processRegionInfo(msg);
00556 }
00557 
00558 
00559 
00560 S32 LLViewerRegion::renderPropertyLines()
00561 {
00562         if (mParcelOverlay)
00563         {
00564                 return mParcelOverlay->renderPropertyLines();
00565         }
00566         else
00567         {
00568                 return 0;
00569         }
00570 }
00571 
00572 // This gets called when the height field changes.
00573 void LLViewerRegion::dirtyHeights()
00574 {
00575         // Property lines need to be reconstructed when the land changes.
00576         if (mParcelOverlay)
00577         {
00578                 mParcelOverlay->setDirty();
00579         }
00580 }
00581 
00582 BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
00583 {
00584         // did_update returns TRUE if we did at least one significant update
00585         BOOL did_update = mLandp->idleUpdate(max_update_time);
00586         
00587         if (mParcelOverlay)
00588         {
00589                 // Hopefully not a significant time sink...
00590                 mParcelOverlay->idleUpdate();
00591         }
00592 
00593         return did_update;
00594 }
00595 
00596 
00597 // As above, but forcibly do the update.
00598 void LLViewerRegion::forceUpdate()
00599 {
00600         mLandp->idleUpdate(0.f);
00601 
00602         if (mParcelOverlay)
00603         {
00604                 mParcelOverlay->idleUpdate(true);
00605         }
00606 }
00607 
00608 void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction)
00609 {
00610         mLandp->connectNeighbor(neighborp->mLandp, direction);
00611         mCloudLayer.connectNeighbor(&(neighborp->mCloudLayer), direction);
00612 }
00613 
00614 
00615 void LLViewerRegion::disconnectAllNeighbors()
00616 {
00617         mLandp->disconnectAllNeighbors();
00618         mCloudLayer.disconnectAllNeighbors();
00619 }
00620 
00621 
00622 F32 LLViewerRegion::getCompositionXY(const S32 x, const S32 y) const
00623 {
00624         if (x >= 256)
00625         {
00626                 if (y >= 256)
00627                 {
00628                         LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 256.f, 0.f);
00629                         LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center);
00630                         if (regionp)
00631                         {
00632                                 // OK, we need to do some hackery here - different simulators no longer use
00633                                 // the same composition values, necessarily.
00634                                 // If we're attempting to blend, then we want to make the fractional part of
00635                                 // this region match the fractional of the adjacent.  For now, just minimize
00636                                 // the delta.
00637                                 F32 our_comp = getComposition()->getValueScaled(255, 255);
00638                                 F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, y - 256.f);
00639                                 while (llabs(our_comp - adj_comp) >= 1.f)
00640                                 {
00641                                         if (our_comp > adj_comp)
00642                                         {
00643                                                 adj_comp += 1.f;
00644                                         }
00645                                         else
00646                                         {
00647                                                 adj_comp -= 1.f;
00648                                         }
00649                                 }
00650                                 return adj_comp;
00651                         }
00652                 }
00653                 else
00654                 {
00655                         LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 0, 0.f);
00656                         LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center);
00657                         if (regionp)
00658                         {
00659                                 // OK, we need to do some hackery here - different simulators no longer use
00660                                 // the same composition values, necessarily.
00661                                 // If we're attempting to blend, then we want to make the fractional part of
00662                                 // this region match the fractional of the adjacent.  For now, just minimize
00663                                 // the delta.
00664                                 F32 our_comp = getComposition()->getValueScaled(255.f, (F32)y);
00665                                 F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, (F32)y);
00666                                 while (llabs(our_comp - adj_comp) >= 1.f)
00667                                 {
00668                                         if (our_comp > adj_comp)
00669                                         {
00670                                                 adj_comp += 1.f;
00671                                         }
00672                                         else
00673                                         {
00674                                                 adj_comp -= 1.f;
00675                                         }
00676                                 }
00677                                 return adj_comp;
00678                         }
00679                 }
00680         }
00681         else if (y >= 256)
00682         {
00683                 LLVector3d center = getCenterGlobal() + LLVector3d(0.f, 256.f, 0.f);
00684                 LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center);
00685                 if (regionp)
00686                 {
00687                         // OK, we need to do some hackery here - different simulators no longer use
00688                         // the same composition values, necessarily.
00689                         // If we're attempting to blend, then we want to make the fractional part of
00690                         // this region match the fractional of the adjacent.  For now, just minimize
00691                         // the delta.
00692                         F32 our_comp = getComposition()->getValueScaled((F32)x, 255.f);
00693                         F32 adj_comp = regionp->getComposition()->getValueScaled((F32)x, y - 256.f);
00694                         while (llabs(our_comp - adj_comp) >= 1.f)
00695                         {
00696                                 if (our_comp > adj_comp)
00697                                 {
00698                                         adj_comp += 1.f;
00699                                 }
00700                                 else
00701                                 {
00702                                         adj_comp -= 1.f;
00703                                 }
00704                         }
00705                         return adj_comp;
00706                 }
00707         }
00708 
00709         return getComposition()->getValueScaled((F32)x, (F32)y);
00710 }
00711 
00712 void LLViewerRegion::calculateCenterGlobal() 
00713 {
00714         mCenterGlobal = mOriginGlobal;
00715         mCenterGlobal.mdV[VX] += 0.5 * mWidth;
00716         mCenterGlobal.mdV[VY] += 0.5 * mWidth;
00717         mCenterGlobal.mdV[VZ] = 0.5*mLandp->getMinZ() + mLandp->getMaxZ();
00718 }
00719 
00720 void LLViewerRegion::calculateCameraDistance()
00721 {
00722         mCameraDistanceSquared = (F32)(gAgent.getCameraPositionGlobal() - getCenterGlobal()).magVecSquared();
00723 }
00724 
00725 U32 LLViewerRegion::getNetDetailsForLCD()
00726 {
00727         return mPingDelay;
00728 }
00729 
00730 std::ostream& operator<<(std::ostream &s, const LLViewerRegion &region)
00731 {
00732         s << "{ ";
00733         s << region.mHost;
00734         s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n";
00735         s << "}";
00736         return s;
00737 }
00738 
00739 
00740 // ---------------- Protected Member Functions ----------------
00741 
00742 void LLViewerRegion::updateNetStats()
00743 {
00744         F32 dt = mLastNetUpdate.getElapsedTimeAndResetF32();
00745 
00746         LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mHost);
00747         if (!cdp)
00748         {
00749                 mAlive = FALSE;
00750                 return;
00751         }
00752 
00753         mAlive = TRUE;
00754         mDeltaTime = dt;
00755 
00756         mLastPacketsIn =        mPacketsIn;
00757         mLastBitsIn =           mBitsIn;
00758         mLastPacketsOut =       mPacketsOut;
00759         mLastPacketsLost =      mPacketsLost;
00760 
00761         mPacketsIn =                            cdp->getPacketsIn();
00762         mBitsIn =                                       8 * cdp->getBytesIn();
00763         mPacketsOut =                           cdp->getPacketsOut();
00764         mPacketsLost =                          cdp->getPacketsLost();
00765         mPingDelay =                            cdp->getPingDelay();
00766 
00767         mBitStat.addValue(mBitsIn - mLastBitsIn);
00768         mPacketsStat.addValue(mPacketsIn - mLastPacketsIn);
00769         mPacketsLostStat.addValue(mPacketsLost);
00770 }
00771 
00772 
00773 U32 LLViewerRegion::getPacketsLost() const
00774 {
00775         LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mHost);
00776         if (!cdp)
00777         {
00778                 llinfos << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mHost << llendl;
00779                 return 0;
00780         }
00781         else
00782         {
00783                 return cdp->getPacketsLost();
00784         }
00785 }
00786 
00787 BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const
00788 {
00789         LLVector3 pos_region = getPosRegionFromGlobal(point_global);
00790 
00791         if (pos_region.mV[VX] < 0)
00792         {
00793                 return FALSE;
00794         }
00795         if (pos_region.mV[VX] >= mWidth)
00796         {
00797                 return FALSE;
00798         }
00799         if (pos_region.mV[VY] < 0)
00800         {
00801                 return FALSE;
00802         }
00803         if (pos_region.mV[VY] >= mWidth)
00804         {
00805                 return FALSE;
00806         }
00807         return TRUE;
00808 }
00809 
00810 LLVector3 LLViewerRegion::getPosRegionFromGlobal(const LLVector3d &point_global) const
00811 {
00812         LLVector3 pos_region;
00813         pos_region.setVec(point_global - mOriginGlobal);
00814         return pos_region;
00815 }
00816 
00817 LLVector3d LLViewerRegion::getPosGlobalFromRegion(const LLVector3 &pos_region) const
00818 {
00819         LLVector3d pos_region_d;
00820         pos_region_d.setVec(pos_region);
00821         return pos_region_d + mOriginGlobal;
00822 }
00823 
00824 LLVector3 LLViewerRegion::getPosAgentFromRegion(const LLVector3 &pos_region) const
00825 {
00826         LLVector3d pos_global = getPosGlobalFromRegion(pos_region);
00827 
00828         return gAgent.getPosAgentFromGlobal(pos_global);
00829 }
00830 
00831 LLVector3 LLViewerRegion::getPosRegionFromAgent(const LLVector3 &pos_agent) const
00832 {
00833         return pos_agent - getOriginAgent();
00834 }
00835 
00836 F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos)
00837 {
00838         return mLandp->resolveHeightRegion( region_pos );
00839 }
00840 
00841 BOOL LLViewerRegion::isOwnedSelf(const LLVector3& pos)
00842 {
00843         if (mParcelOverlay)
00844         {
00845                 return mParcelOverlay->isOwnedSelf(pos);
00846         } else {
00847                 return FALSE;
00848         }
00849 }
00850 
00851 // Owned by a group you belong to?  (officer or member)
00852 BOOL LLViewerRegion::isOwnedGroup(const LLVector3& pos)
00853 {
00854         if (mParcelOverlay)
00855         {
00856                 return mParcelOverlay->isOwnedGroup(pos);
00857         } else {
00858                 return FALSE;
00859         }
00860 }
00861 
00862 // the new TCP coarse location handler node
00863 class CoarseLocationUpdate : public LLHTTPNode
00864 {
00865 public:
00866         virtual void post(
00867                 ResponsePtr responder,
00868                 const LLSD& context,
00869                 const LLSD& input) const
00870         {
00871                 LLHost host(input["sender"].asString());
00872                 LLViewerRegion* region = LLWorld::getInstance()->getRegion(host);
00873                 if( !region )
00874                 {
00875                         return;
00876                 }
00877 
00878                 S32 target_index = input["body"]["Index"][0]["Prey"].asInteger();
00879                 S32 you_index    = input["body"]["Index"][0]["You" ].asInteger();
00880 
00881                 LLDynamicArray<U32>* avatar_locs = &region->mMapAvatars;
00882                 LLDynamicArray<LLUUID>* avatar_ids = &region->mMapAvatarIDs;
00883                 avatar_locs->reset();
00884                 avatar_ids->reset();
00885 
00886                 //llinfos << "coarse locations agent[0] " << input["body"]["AgentData"][0]["AgentID"].asUUID() << llendl;
00887                 //llinfos << "my agent id = " << gAgent.getID() << llendl;
00888                 //llinfos << ll_pretty_print_sd(input) << llendl;
00889 
00890                 LLSD 
00891                         locs   = input["body"]["Location"],
00892                         agents = input["body"]["AgentData"];
00893                 LLSD::array_iterator 
00894                         locs_it = locs.beginArray(), 
00895                         agents_it = agents.beginArray();
00896                 BOOL has_agent_data = input["body"].has("AgentData");
00897 
00898                 for(int i=0; 
00899                         locs_it != locs.endArray(); 
00900                         i++, locs_it++)
00901                 {
00902                         U8 
00903                                 x = locs_it->get("X").asInteger(),
00904                                 y = locs_it->get("Y").asInteger(),
00905                                 z = locs_it->get("Z").asInteger();
00906                         // treat the target specially for the map, and don't add you or the target
00907                         if(i == target_index)
00908                         {
00909                                 LLVector3d global_pos(region->getOriginGlobal());
00910                                 global_pos.mdV[VX] += (F64)x;
00911                                 global_pos.mdV[VY] += (F64)y;
00912                                 global_pos.mdV[VZ] += (F64)z * 4.0;
00913                                 LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos);
00914                         }
00915                         else if( i != you_index)
00916                         {
00917                                 U32 loc = x << 16 | y << 8 | z; loc = loc;
00918                                 U32 pos = 0x0;
00919                                 pos |= x;
00920                                 pos <<= 8;
00921                                 pos |= y;
00922                                 pos <<= 8;
00923                                 pos |= z;
00924                                 avatar_locs->put(pos);
00925                                 //llinfos << "next pos: " << x << "," << y << "," << z << ": " << pos << llendl;
00926                                 if(has_agent_data) // for backwards compatibility with old message format
00927                                 {
00928                                         LLUUID agent_id(agents_it->get("AgentID").asUUID());
00929                                         //llinfos << "next agent: " << agent_id.asString() << llendl;
00930                                         avatar_ids->put(agent_id);
00931                                 }
00932                         }
00933                         if (has_agent_data)
00934                         {
00935                                 agents_it++;
00936                         }
00937                 }
00938         }
00939 };
00940 
00941 // build the coarse location HTTP node under the "/message" URL
00942 LLHTTPRegistration<CoarseLocationUpdate>
00943    gHTTPRegistrationCoarseLocationUpdate(
00944            "/message/CoarseLocationUpdate");
00945 
00946 
00947 // the deprecated coarse location handler
00948 void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg)
00949 {
00950         //llinfos << "CoarseLocationUpdate" << llendl;
00951         mMapAvatars.reset();
00952         mMapAvatarIDs.reset(); // only matters in a rare case but it's good to be safe.
00953 
00954         U8 x_pos = 0;
00955         U8 y_pos = 0;
00956         U8 z_pos = 0;
00957 
00958         U32 pos = 0x0;
00959 
00960         S16 agent_index;
00961         S16 target_index;
00962         msg->getS16Fast(_PREHASH_Index, _PREHASH_You, agent_index);
00963         msg->getS16Fast(_PREHASH_Index, _PREHASH_Prey, target_index);
00964 
00965         S32 count = msg->getNumberOfBlocksFast(_PREHASH_Location);
00966         for(S32 i = 0; i < count; i++)
00967         {
00968                 msg->getU8Fast(_PREHASH_Location, _PREHASH_X, x_pos, i);
00969                 msg->getU8Fast(_PREHASH_Location, _PREHASH_Y, y_pos, i);
00970                 msg->getU8Fast(_PREHASH_Location, _PREHASH_Z, z_pos, i);
00971 
00972                 //llinfos << "  object X: " << (S32)x_pos << " Y: " << (S32)y_pos
00973                 //              << " Z: " << (S32)(z_pos * 4)
00974                 //              << llendl;
00975 
00976                 // treat the target specially for the map
00977                 if(i == target_index)
00978                 {
00979                         LLVector3d global_pos(mOriginGlobal);
00980                         global_pos.mdV[VX] += (F64)(x_pos);
00981                         global_pos.mdV[VY] += (F64)(y_pos);
00982                         global_pos.mdV[VZ] += (F64)(z_pos) * 4.0;
00983                         LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos);
00984                 }
00985                 
00986                 //don't add you
00987                 if( i != agent_index)
00988                 {
00989                         pos = 0x0;
00990                         pos |= x_pos;
00991                         pos <<= 8;
00992                         pos |= y_pos;
00993                         pos <<= 8;
00994                         pos |= z_pos;
00995                         mMapAvatars.put(pos);
00996                 }
00997         }
00998 }
00999 
01000 void LLViewerRegion::getInfo(LLSD& info)
01001 {
01002         info["Region"]["Host"] = getHost().getIPandPort();
01003         info["Region"]["Name"] = getName();
01004         U32 x, y;
01005         from_region_handle(getHandle(), &x, &y);
01006         info["Region"]["Handle"]["x"] = (LLSD::Integer)x;
01007         info["Region"]["Handle"]["y"] = (LLSD::Integer)y;
01008 }
01009 
01010 void LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)
01011 {
01012         U32 local_id = objectp->getLocalID();
01013         U32 crc = objectp->getCRC();
01014 
01015         LLVOCacheEntry* entry = get_if_there(mCacheMap, local_id, (LLVOCacheEntry*)NULL);
01016 
01017         if (entry)
01018         {
01019                 // we've seen this object before
01020                 if (entry->getCRC() == crc)
01021                 {
01022                         // Record a hit
01023                         entry->recordDupe();
01024                 }
01025                 else
01026                 {
01027                         // Update the cache entry
01028                         mCacheMap.erase(local_id);
01029                         delete entry;
01030                         entry = new LLVOCacheEntry(local_id, crc, dp);
01031                         mCacheEnd.insert(*entry);
01032                         mCacheMap[local_id] = entry;
01033                 }
01034         }
01035         else
01036         {
01037                 // we haven't seen this object before
01038 
01039                 // Create new entry and add to map
01040                 if (mCacheEntriesCount > MAX_OBJECT_CACHE_ENTRIES)
01041                 {
01042                         entry = mCacheStart.getNext();
01043                         mCacheMap.erase(entry->getLocalID());
01044                         delete entry;
01045                         mCacheEntriesCount--;
01046                 }
01047                 entry = new LLVOCacheEntry(local_id, crc, dp);
01048 
01049                 mCacheEnd.insert(*entry);
01050                 mCacheMap[local_id] = entry;
01051                 mCacheEntriesCount++;
01052         }
01053         return ;
01054 }
01055 
01056 // Get data packer for this object, if we have cached data
01057 // AND the CRC matches. JC
01058 LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc)
01059 {
01060         llassert(mCacheLoaded);
01061 
01062         LLVOCacheEntry* entry = get_if_there(mCacheMap, local_id, (LLVOCacheEntry*)NULL);
01063 
01064         if (entry)
01065         {
01066                 // we've seen this object before
01067                 if (entry->getCRC() == crc)
01068                 {
01069                         // Record a hit
01070                         entry->recordHit();
01071                         return entry->getDP(crc);
01072                 }
01073                 else
01074                 {
01075                         // llinfos << "CRC miss for " << local_id << llendl;
01076                         mCacheMissCRC.put(local_id);
01077                 }
01078         }
01079         else
01080         {
01081                 // llinfos << "Cache miss for " << local_id << llendl;
01082                 mCacheMissFull.put(local_id);
01083         }
01084         return NULL;
01085 }
01086 
01087 void LLViewerRegion::addCacheMissFull(const U32 local_id)
01088 {
01089         mCacheMissFull.put(local_id);
01090 }
01091 
01092 void LLViewerRegion::requestCacheMisses()
01093 {
01094         S32 full_count = mCacheMissFull.count();
01095         S32 crc_count = mCacheMissCRC.count();
01096         if (full_count == 0 && crc_count == 0) return;
01097 
01098         LLMessageSystem* msg = gMessageSystem;
01099         BOOL start_new_message = TRUE;
01100         S32 blocks = 0;
01101         S32 i;
01102 
01103         const U8 CACHE_MISS_TYPE_FULL = 0;
01104         const U8 CACHE_MISS_TYPE_CRC  = 1;
01105 
01106         // Send full cache miss updates.  For these, we KNOW we don't
01107         // have a viewer object.
01108         for (i = 0; i < full_count; i++)
01109         {
01110                 if (start_new_message)
01111                 {
01112                         msg->newMessageFast(_PREHASH_RequestMultipleObjects);
01113                         msg->nextBlockFast(_PREHASH_AgentData);
01114                         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
01115                         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01116                         start_new_message = FALSE;
01117                 }
01118 
01119                 msg->nextBlockFast(_PREHASH_ObjectData);
01120                 msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_FULL);
01121                 msg->addU32Fast(_PREHASH_ID, mCacheMissFull[i]);
01122                 blocks++;
01123 
01124                 if (blocks >= 255)
01125                 {
01126                         sendReliableMessage();
01127                         start_new_message = TRUE;
01128                         blocks = 0;
01129                 }
01130         }
01131 
01132         // Send CRC miss updates.  For these, we _might_ have a viewer object,
01133         // but probably not.
01134         for (i = 0; i < crc_count; i++)
01135         {
01136                 if (start_new_message)
01137                 {
01138                         msg->newMessageFast(_PREHASH_RequestMultipleObjects);
01139                         msg->nextBlockFast(_PREHASH_AgentData);
01140                         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
01141                         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01142                         start_new_message = FALSE;
01143                 }
01144 
01145                 msg->nextBlockFast(_PREHASH_ObjectData);
01146                 msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_CRC);
01147                 msg->addU32Fast(_PREHASH_ID, mCacheMissCRC[i]);
01148                 blocks++;
01149 
01150                 if (blocks >= 255)
01151                 {
01152                         sendReliableMessage();
01153                         start_new_message = TRUE;
01154                         blocks = 0;
01155                 }
01156         }
01157 
01158         // finish any pending message
01159         if (!start_new_message)
01160         {
01161                 sendReliableMessage();
01162         }
01163         mCacheMissFull.reset();
01164         mCacheMissCRC.reset();
01165 
01166         // llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl;
01167 }
01168 
01169 void LLViewerRegion::dumpCache()
01170 {
01171         const S32 BINS = 4;
01172         S32 hit_bin[BINS];
01173         S32 change_bin[BINS];
01174 
01175         S32 i;
01176         for (i = 0; i < BINS; ++i)
01177         {
01178                 hit_bin[i] = 0;
01179                 change_bin[i] = 0;
01180         }
01181 
01182         LLVOCacheEntry *entry;
01183 
01184         for (entry = mCacheStart.getNext(); entry && (entry != &mCacheEnd); entry = entry->getNext())
01185         {
01186                 S32 hits = entry->getHitCount();
01187                 S32 changes = entry->getCRCChangeCount();
01188 
01189                 hits = llclamp(hits, 0, BINS-1);
01190                 changes = llclamp(changes, 0, BINS-1);
01191 
01192                 hit_bin[hits]++;
01193                 change_bin[changes]++;
01194         }
01195 
01196         llinfos << "Count " << mCacheEntriesCount << llendl;
01197         for (i = 0; i < BINS; i++)
01198         {
01199                 llinfos << "Hits " << i << " " << hit_bin[i] << llendl;
01200         }
01201         for (i = 0; i < BINS; i++)
01202         {
01203                 llinfos << "Changes " << i << " " << change_bin[i] << llendl;
01204         }
01205 }
01206 
01207 void LLViewerRegion::unpackRegionHandshake()
01208 {
01209         LLMessageSystem *msg = gMessageSystem;
01210 
01211         const S32 SIM_NAME_BUF = 256;
01212         U32 region_flags;
01213         U8 sim_access;
01214         char sim_name[SIM_NAME_BUF];            /* Flawfinder: ignore */
01215         LLUUID sim_owner;
01216         BOOL is_estate_manager;
01217         F32 water_height;
01218         F32 billable_factor;
01219         LLUUID cache_id;
01220 
01221         msg->getU32             ("RegionInfo", "RegionFlags", region_flags);
01222         msg->getU8              ("RegionInfo", "SimAccess", sim_access);
01223         msg->getString  ("RegionInfo", "SimName", SIM_NAME_BUF, sim_name);
01224         msg->getUUID    ("RegionInfo", "SimOwner", sim_owner);
01225         msg->getBOOL    ("RegionInfo", "IsEstateManager", is_estate_manager);
01226         msg->getF32             ("RegionInfo", "WaterHeight", water_height);
01227         msg->getF32             ("RegionInfo", "BillableFactor", billable_factor);
01228         msg->getUUID    ("RegionInfo", "CacheID", cache_id );
01229 
01230         setRegionFlags(region_flags);
01231         setSimAccess(sim_access);
01232         setRegionNameAndZone(sim_name);
01233         setOwner(sim_owner);
01234         setIsEstateManager(is_estate_manager);
01235         setWaterHeight(water_height);
01236         setBillableFactor(billable_factor);
01237         setCacheID(cache_id);
01238 
01239         LLUUID region_id;
01240         msg->getUUID("RegionInfo2", "RegionID", region_id);
01241         setRegionID(region_id);
01242 
01243         LLVLComposition *compp = getComposition();
01244         if (compp)
01245         {
01246                 LLUUID tmp_id;
01247 
01248                 msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id);
01249                 compp->setDetailTextureID(0, tmp_id);
01250                 msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id);
01251                 compp->setDetailTextureID(1, tmp_id);
01252                 msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id);
01253                 compp->setDetailTextureID(2, tmp_id);
01254                 msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id);
01255                 compp->setDetailTextureID(3, tmp_id);
01256 
01257                 F32 tmp_f32;
01258                 msg->getF32("RegionInfo", "TerrainStartHeight00", tmp_f32);
01259                 compp->setStartHeight(0, tmp_f32);
01260                 msg->getF32("RegionInfo", "TerrainStartHeight01", tmp_f32);
01261                 compp->setStartHeight(1, tmp_f32);
01262                 msg->getF32("RegionInfo", "TerrainStartHeight10", tmp_f32);
01263                 compp->setStartHeight(2, tmp_f32);
01264                 msg->getF32("RegionInfo", "TerrainStartHeight11", tmp_f32);
01265                 compp->setStartHeight(3, tmp_f32);
01266 
01267                 msg->getF32("RegionInfo", "TerrainHeightRange00", tmp_f32);
01268                 compp->setHeightRange(0, tmp_f32);
01269                 msg->getF32("RegionInfo", "TerrainHeightRange01", tmp_f32);
01270                 compp->setHeightRange(1, tmp_f32);
01271                 msg->getF32("RegionInfo", "TerrainHeightRange10", tmp_f32);
01272                 compp->setHeightRange(2, tmp_f32);
01273                 msg->getF32("RegionInfo", "TerrainHeightRange11", tmp_f32);
01274                 compp->setHeightRange(3, tmp_f32);
01275 
01276                 // If this is an UPDATE (params already ready, we need to regenerate
01277                 // all of our terrain stuff, by
01278                 if (compp->getParamsReady())
01279                 {
01280                         getLand().dirtyAllPatches();
01281                 }
01282                 else
01283                 {
01284                         compp->setParamsReady();
01285                 }
01286         }
01287 
01288 
01289         // Now that we have the name, we can load the cache file
01290         // off disk.
01291         loadCache();
01292 
01293         // After loading cache, signal that simulator can start
01294         // sending data.
01295         // TODO: Send all upstream viewer->sim handshake info here.
01296         LLHost host = msg->getSender();
01297         msg->newMessage("RegionHandshakeReply");
01298         msg->nextBlock("AgentData");
01299         msg->addUUID("AgentID", gAgent.getID());
01300         msg->addUUID("SessionID", gAgent.getSessionID());
01301         msg->nextBlock("RegionInfo");
01302         msg->addU32("Flags", 0x0 );
01303         msg->sendReliable(host);
01304 }
01305 
01306 
01307 
01308 class BaseCapabilitiesComplete : public LLHTTPClient::Responder
01309 {
01310         LOG_CLASS(BaseCapabilitiesComplete);
01311 public:
01312     BaseCapabilitiesComplete(LLViewerRegion* region)
01313                 : mRegion(region)
01314     { }
01315 
01316     void error(U32 statusNum, const std::string& reason)
01317     {
01318                 LL_WARNS2("AppInit", "Capabilities") << statusNum << ": " << reason << LL_ENDL;
01319                 
01320                 if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
01321                 {
01322                         LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
01323                 }
01324     }
01325 
01326     void result(const LLSD& content)
01327     {
01328                 LLSD::map_const_iterator iter;
01329                 for(iter = content.beginMap(); iter != content.endMap(); ++iter)
01330                 {
01331                         mRegion->setCapability(iter->first, iter->second);
01332                         LL_DEBUGS2("AppInit", "Capabilities") << "got capability for " 
01333                                 << iter->first << LL_ENDL;
01334 
01335                         /* HACK we're waiting for the ServerReleaseNotes */
01336                         if ((iter->first == "ServerReleaseNotes") && (LLFloaterReleaseMsg::sDisplayMessage))
01337                         {
01338                                 LLFloaterReleaseMsg::show();
01339                                 LLFloaterReleaseMsg::sDisplayMessage = false;
01340                         }
01341                 }
01342                 
01343                 if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
01344                 {
01345                         LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
01346                 }
01347         }
01348 
01349     static boost::intrusive_ptr<BaseCapabilitiesComplete> build(
01350                                                                 LLViewerRegion* region)
01351     {
01352                 return boost::intrusive_ptr<BaseCapabilitiesComplete>(
01353                                                          new BaseCapabilitiesComplete(region));
01354     }
01355 
01356 private:
01357         LLViewerRegion* mRegion;
01358 };
01359 
01360 
01361 void LLViewerRegion::setSeedCapability(const std::string& url)
01362 {
01363   if (getCapability("Seed") == url)
01364     {
01365       llwarns << "Ignoring duplicate seed capability" << llendl;
01366       return;
01367     }
01368         delete mEventPoll;
01369         mEventPoll = NULL;
01370         
01371         mCapabilities.clear();
01372         setCapability("Seed", url);
01373 
01374         LLSD capabilityNames = LLSD::emptyArray();
01375         capabilityNames.append("ChatSessionRequest");
01376         capabilityNames.append("CopyInventoryFromNotecard");
01377         capabilityNames.append("DispatchRegionInfo");
01378         capabilityNames.append("EstateChangeInfo");
01379         capabilityNames.append("EventQueueGet");
01380         capabilityNames.append("FetchInventoryDescendents");
01381         capabilityNames.append("GroupProposalBallot");
01382         capabilityNames.append("MapLayer");
01383         capabilityNames.append("MapLayerGod");
01384         capabilityNames.append("NewFileAgentInventory");
01385         capabilityNames.append("ParcelPropertiesUpdate");
01386         capabilityNames.append("ParcelVoiceInfoRequest");
01387         capabilityNames.append("ProvisionVoiceAccountRequest");
01388         capabilityNames.append("RemoteParcelRequest");
01389         capabilityNames.append("RequestTextureDownload");
01390         capabilityNames.append("SearchStatRequest");
01391         capabilityNames.append("SearchStatTracking");
01392         capabilityNames.append("SendPostcard");
01393         capabilityNames.append("SendUserReport");
01394         capabilityNames.append("SendUserReportWithScreenshot");
01395         capabilityNames.append("ServerReleaseNotes");
01396         capabilityNames.append("StartGroupProposal");
01397         capabilityNames.append("UpdateGestureAgentInventory");
01398         capabilityNames.append("UpdateNotecardAgentInventory");
01399         capabilityNames.append("UpdateScriptAgentInventory");
01400         capabilityNames.append("UpdateGestureTaskInventory");
01401         capabilityNames.append("UpdateNotecardTaskInventory");
01402         capabilityNames.append("UpdateScriptTaskInventory");
01403         capabilityNames.append("ViewerStartAuction");
01404         capabilityNames.append("UntrustedSimulatorMessage");
01405         capabilityNames.append("ViewerStats");
01406         // Please add new capabilities alphabetically to reduce
01407         // merge conflicts.
01408 
01409         llinfos << "posting to seed " << url << llendl;
01410 
01411         LLHTTPClient::post(url, capabilityNames, BaseCapabilitiesComplete::build(this));
01412 }
01413 
01414 void LLViewerRegion::setCapability(const std::string& name, const std::string& url)
01415 {
01416         if(name == "EventQueueGet")
01417         {
01418                 delete mEventPoll;
01419                 mEventPoll = NULL;
01420                 mEventPoll = new LLEventPoll(url, getHost());
01421         }
01422         else if(name == "UntrustedSimulatorMessage")
01423         {
01424                 LLHTTPSender::setSender(mHost, new LLCapHTTPSender(url));
01425         }
01426         else
01427         {
01428                 mCapabilities[name] = url;
01429         }
01430 }
01431 
01432 std::string LLViewerRegion::getCapability(const std::string& name) const
01433 {
01434         CapabilityMap::const_iterator iter = mCapabilities.find(name);
01435         if(iter == mCapabilities.end())
01436         {
01437                 return "";
01438         }
01439         return iter->second;
01440 }
01441 
01442 void LLViewerRegion::logActiveCapabilities() const
01443 {
01444         int count = 0;
01445         CapabilityMap::const_iterator iter;
01446         for (iter = mCapabilities.begin(); iter != mCapabilities.end(); iter++, count++)
01447         {
01448                 if (!iter->second.empty())
01449                 {
01450                         llinfos << iter->first << " URL is " << iter->second << llendl;
01451                 }
01452         }
01453         llinfos << "Dumped " << count << " entries." << llendl;
01454 }
01455 
01456 LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)
01457 {
01458         if (type < mObjectPartition.size())
01459         {
01460                 return mObjectPartition[type];
01461         }
01462         return NULL;
01463 }
01464 

Generated on Fri May 16 08:34:16 2008 for SecondLife by  doxygen 1.5.5