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

Generated on Thu Jul 1 06:09:33 2010 for Second Life Viewer by  doxygen 1.4.7