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 "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
00069
00070 const U32 INDRA_OBJECT_CACHE_VERSION = 14;
00071
00072
00073 extern BOOL gNoRender;
00074
00075 const F32 WATER_TEXTURE_SCALE = 8.f;
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
00113 mCompositionp = new LLVLComposition(mLandp, grids_per_region_edge, region_width_meters/grids_per_region_edge);
00114 mCompositionp->setSurface(mLandp);
00115
00116
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
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;
00157 }
00158
00159
00160
00161 LLViewerRegion::~LLViewerRegion()
00162 {
00163 gVLManager.cleanupData(this);
00164
00165
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
00190 mCacheLoaded = TRUE;
00191
00192 LLVOCacheEntry *entry;
00193
00194 char filename[256];
00195 snprintf(filename, sizeof(filename), "%s%sobjects_%d_%d.slc",
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");
00202 if (!fp)
00203 {
00204
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
00214
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
00225
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];
00284 snprintf(filename, sizeof(filename), "%s%sobjects_%d_%d.slc",
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");
00291 if (!fp)
00292 {
00293 llwarns << "Unable to write cache file " << filename << llendl;
00294 return;
00295 }
00296
00297
00298 U32 zero = 0;
00299 if (fwrite(&zero, sizeof(U32), 1, fp) != 1)
00300 {
00301 llwarns << "Short write" << llendl;
00302 }
00303
00304
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
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
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
00455 char* SIM_ACCESS_STR[] = { "Free Trial",
00456 "PG",
00457 "Mature",
00458 "Offline",
00459 "Unknown" };
00460
00461
00462 const char* LLViewerRegion::accessToString(U8 access)
00463 {
00464 switch(access)
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
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;
00501 }
00502
00503
00504 const char* LLViewerRegion::accessToShortString(U8 access)
00505 {
00506 switch(access)
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
00524 void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**)
00525 {
00526
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
00547 void LLViewerRegion::dirtyHeights()
00548 {
00549
00550 if (mParcelOverlay)
00551 {
00552 mParcelOverlay->setDirty();
00553 }
00554 }
00555
00556 BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
00557 {
00558
00559 BOOL did_update = mLandp->idleUpdate(max_update_time);
00560
00561 if (mParcelOverlay)
00562 {
00563
00564 mParcelOverlay->idleUpdate();
00565 }
00566
00567 return did_update;
00568 }
00569
00570
00571
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
00607
00608
00609
00610
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
00634
00635
00636
00637
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
00662
00663
00664
00665
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 ®ion)
00705 {
00706 s << "{ ";
00707 s << region.mHost;
00708 s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n";
00709 s << "}";
00710 return s;
00711 }
00712
00713
00714
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
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
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 = ®ion->mMapAvatars;
00856 LLDynamicArray<LLUUID>* avatar_ids = ®ion->mMapAvatarIDs;
00857 avatar_locs->reset();
00858 avatar_ids->reset();
00859
00860
00861
00862
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
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
00900 if(has_agent_data)
00901 {
00902 LLUUID agent_id(agents_it->get("AgentID").asUUID());
00903
00904 avatar_ids->put(agent_id);
00905 }
00906 }
00907 if (has_agent_data)
00908 {
00909 agents_it++;
00910 }
00911 }
00912 }
00913 };
00914
00915
00916 LLHTTPRegistration<CoarseLocationUpdate>
00917 gHTTPRegistrationCoarseLocationUpdate(
00918 "/message/CoarseLocationUpdate");
00919
00920
00921
00922 void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg)
00923 {
00924
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
00946
00947
00948
00949
00950
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];
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);
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
01004 if (entry->getCRC() == crc)
01005 {
01006
01007 entry->recordDupe();
01008 }
01009 else
01010 {
01011
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
01022
01023
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
01041
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
01051 if (entry->getCRC() == crc)
01052 {
01053
01054 entry->recordHit();
01055 return entry->getDP(crc);
01056 }
01057 else
01058 {
01059
01060 mCacheMissCRC.put(local_id);
01061 }
01062 }
01063 else
01064 {
01065
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
01091
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
01117
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
01143 if (!start_new_message)
01144 {
01145 sendReliableMessage();
01146 }
01147 mCacheMissFull.reset();
01148 mCacheMissCRC.reset();
01149
01150
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];
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
01261
01262 if (compp->getParamsReady())
01263 {
01264 getLand().dirtyAllPatches();
01265 }
01266 else
01267 {
01268 compp->setParamsReady();
01269 }
01270 }
01271
01272
01273
01274
01275 loadCache();
01276
01277
01278
01279
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
01380
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