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
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
00070
00071 const U32 INDRA_OBJECT_CACHE_VERSION = 14;
00072
00073
00074 extern BOOL gNoRender;
00075
00076 const F32 WATER_TEXTURE_SCALE = 8.f;
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
00114 mCompositionp = new LLVLComposition(mLandp, grids_per_region_edge, region_width_meters/grids_per_region_edge);
00115 mCompositionp->setSurface(mLandp);
00116
00117
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
00138 initStats();
00139
00140 mCacheStart.append(mCacheEnd);
00141
00142
00143
00144 mObjectPartition.push_back(new LLHUDPartition());
00145 mObjectPartition.push_back(new LLTerrainPartition());
00146 mObjectPartition.push_back(new LLWaterPartition());
00147 mObjectPartition.push_back(new LLTreePartition());
00148 mObjectPartition.push_back(new LLParticlePartition());
00149 mObjectPartition.push_back(new LLCloudPartition());
00150 mObjectPartition.push_back(new LLGrassPartition());
00151 mObjectPartition.push_back(new LLVolumePartition());
00152 mObjectPartition.push_back(new LLBridgePartition());
00153 mObjectPartition.push_back(NULL);
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;
00171 }
00172
00173
00174
00175 LLViewerRegion::~LLViewerRegion()
00176 {
00177 gVLManager.cleanupData(this);
00178
00179
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
00206 mCacheLoaded = TRUE;
00207
00208 LLVOCacheEntry *entry;
00209
00210 char filename[256];
00211 snprintf(filename, sizeof(filename), "%s%sobjects_%d_%d.slc",
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");
00218 if (!fp)
00219 {
00220
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
00230
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
00241
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];
00300 snprintf(filename, sizeof(filename), "%s%sobjects_%d_%d.slc",
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");
00307 if (!fp)
00308 {
00309 llwarns << "Unable to write cache file " << filename << llendl;
00310 return;
00311 }
00312
00313
00314 U32 zero = 0;
00315 if (fwrite(&zero, sizeof(U32), 1, fp) != 1)
00316 {
00317 llwarns << "Short write" << llendl;
00318 }
00319
00320
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
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
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
00481 char* SIM_ACCESS_STR[] = { "Free Trial",
00482 "PG",
00483 "Mature",
00484 "Offline",
00485 "Unknown" };
00486
00487
00488 const char* LLViewerRegion::accessToString(U8 access)
00489 {
00490 switch(access)
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
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;
00527 }
00528
00529
00530 const char* LLViewerRegion::accessToShortString(U8 access)
00531 {
00532 switch(access)
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
00550 void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**)
00551 {
00552
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
00573 void LLViewerRegion::dirtyHeights()
00574 {
00575
00576 if (mParcelOverlay)
00577 {
00578 mParcelOverlay->setDirty();
00579 }
00580 }
00581
00582 BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
00583 {
00584
00585 BOOL did_update = mLandp->idleUpdate(max_update_time);
00586
00587 if (mParcelOverlay)
00588 {
00589
00590 mParcelOverlay->idleUpdate();
00591 }
00592
00593 return did_update;
00594 }
00595
00596
00597
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
00633
00634
00635
00636
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
00660
00661
00662
00663
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
00688
00689
00690
00691
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 ®ion)
00731 {
00732 s << "{ ";
00733 s << region.mHost;
00734 s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n";
00735 s << "}";
00736 return s;
00737 }
00738
00739
00740
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
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
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 = ®ion->mMapAvatars;
00882 LLDynamicArray<LLUUID>* avatar_ids = ®ion->mMapAvatarIDs;
00883 avatar_locs->reset();
00884 avatar_ids->reset();
00885
00886
00887
00888
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
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
00926 if(has_agent_data)
00927 {
00928 LLUUID agent_id(agents_it->get("AgentID").asUUID());
00929
00930 avatar_ids->put(agent_id);
00931 }
00932 }
00933 if (has_agent_data)
00934 {
00935 agents_it++;
00936 }
00937 }
00938 }
00939 };
00940
00941
00942 LLHTTPRegistration<CoarseLocationUpdate>
00943 gHTTPRegistrationCoarseLocationUpdate(
00944 "/message/CoarseLocationUpdate");
00945
00946
00947
00948 void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg)
00949 {
00950
00951 mMapAvatars.reset();
00952 mMapAvatarIDs.reset();
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
00973
00974
00975
00976
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
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
01020 if (entry->getCRC() == crc)
01021 {
01022
01023 entry->recordDupe();
01024 }
01025 else
01026 {
01027
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
01038
01039
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
01057
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
01067 if (entry->getCRC() == crc)
01068 {
01069
01070 entry->recordHit();
01071 return entry->getDP(crc);
01072 }
01073 else
01074 {
01075
01076 mCacheMissCRC.put(local_id);
01077 }
01078 }
01079 else
01080 {
01081
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
01107
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
01133
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
01159 if (!start_new_message)
01160 {
01161 sendReliableMessage();
01162 }
01163 mCacheMissFull.reset();
01164 mCacheMissCRC.reset();
01165
01166
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];
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
01277
01278 if (compp->getParamsReady())
01279 {
01280 getLand().dirtyAllPatches();
01281 }
01282 else
01283 {
01284 compp->setParamsReady();
01285 }
01286 }
01287
01288
01289
01290
01291 loadCache();
01292
01293
01294
01295
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
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
01407
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