12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746 |
- /**
- * @file llviewerregion.cpp
- * @brief Implementation of the LLViewerRegion class.
- *
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- #include "llviewerregion.h"
- #include "llapp.h"
- #include "llbbox.h"
- #include "llcorehttputil.h"
- #include "lldir.h"
- #include "llfasttimer.h"
- #include "llhost.h"
- #include "llhttpnode.h"
- #include "llregionhandle.h"
- #include "llsdserialize.h"
- #include "llsdutil.h"
- #include "llsurface.h"
- #include "lltrans.h"
- #include "llmessage.h"
- #include "llagent.h"
- #include "llappviewer.h" // For gFrameTimeSeconds
- #include "llavatartracker.h"
- #include "llcommandhandler.h"
- #include "llenvironment.h"
- #include "lleventpoll.h"
- #include "llfloatergodtools.h"
- #include "llfloaterregioninfo.h"
- #include "hbfloatersearch.h"
- #include "llgltfmateriallist.h"
- #include "llgridmanager.h" // For gIsInSecondLife
- #include "llselectmgr.h" // For dialog_refresh_all()
- #include "llspatialpartition.h"
- #include "llstartup.h"
- #include "llurldispatcher.h"
- #include "llviewercontrol.h"
- #include "llviewerdisplay.h" // For gTeleportDisplay
- #include "llviewermenu.h" // For update_upload_costs_in_menus()
- #include "llviewerobjectlist.h"
- #include "llvieweroctree.h"
- #include "llviewerparcelmgr.h"
- #include "llviewerparceloverlay.h"
- #include "llviewerwindow.h" // For getProgressView()
- #include "llvlcomposition.h"
- #include "llvlmanager.h"
- #include "llvoavatarself.h"
- #include "llworld.h"
- #include "llworldmap.h"
- // The server only keeps our pending agent info for 60 seconds. We want to
- // allow for seed cap retry, but its not useful after that 60 seconds. Even
- // when we gave up on login, keep trying for caps after we are logged in.
- constexpr U32 MAX_CAP_REQUEST_ATTEMPTS = 30;
- constexpr U32 DEFAULT_MAX_REGION_WIDE_PRIM_COUNT = 15000;
- bool LLViewerRegion::sVOCacheCullingEnabled = false;
- S32 LLViewerRegion::sLastCameraUpdated = 0;
- S32 LLViewerRegion::sNewObjectCreationThrottle = -1;
- // NOTE: by using these instead of omitting the corresponding xxxAndSuspend()
- // parameters, we avoid seeing such classes constructed and destroyed each time
- LLCore::HttpHeaders::ptr_t LLViewerRegion::sHttpHeaders(new LLCore::HttpHeaders());
- LLCore::HttpOptions::ptr_t LLViewerRegion::sHttpOptions(new LLCore::HttpOptions());
- U64 LLRegionInfoModel::sRegionFlags = 0;
- U32 LLRegionInfoModel::sEstateID = 0;
- U32 LLRegionInfoModel::sParentEstateID = 0;
- S32 LLRegionInfoModel::sPricePerMeter = 0;
- S32 LLRegionInfoModel::sRedirectGridX = 0;
- S32 LLRegionInfoModel::sRedirectGridY = 0;
- F32 LLRegionInfoModel::sBillableFactor = 0.f;
- F32 LLRegionInfoModel::sObjectBonusFactor = 0.f;
- F32 LLRegionInfoModel::sWaterHeight = 0.f;
- F32 LLRegionInfoModel::sTerrainRaiseLimit = 0.f;
- F32 LLRegionInfoModel::sTerrainLowerLimit = 0.f;
- F32 LLRegionInfoModel::sSunHour = 0.f;
- S32 LLRegionInfoModel::sHardAgentLimit = 0;
- U8 LLRegionInfoModel::sSimAccess = 0;
- U8 LLRegionInfoModel::sAgentLimit = 0;
- bool LLRegionInfoModel::sUseEstateSun = false;
- std::string LLRegionInfoModel::sSimName;
- std::string LLRegionInfoModel::sSimType;
- // Support for secondlife:///app/region/{REGION} SLapps
- // N.B. this is defined to work exactly like the classic secondlife://{REGION}
- // However, the later syntax cannot support spaces in the region name because
- // spaces (and %20 chars) are illegal in the hostname of an http URL. Some
- // browsers let you get away with this, but some do not.
- // Hence we introduced the newer secondlife:///app/region alternative.
- class LLRegionHandler final : public LLCommandHandler
- {
- public:
- // requests will be throttled from a non-trusted browser
- LLRegionHandler()
- : LLCommandHandler("region", UNTRUSTED_THROTTLE)
- {
- }
- bool handle(const LLSD& params, const LLSD&, LLMediaCtrl* web) override
- {
- // Make sure that we at least have a region name
- S32 num_params = params.size();
- if (num_params < 1)
- {
- return false;
- }
- // Build a secondlife://{PLACE} SLurl from this SLapp
- std::string url = "secondlife://";
- for (S32 i = 0; i < num_params; ++i)
- {
- if (i > 0)
- {
- url += "/";
- }
- url += params[i].asString();
- }
- // Process the SLapp as if it was a secondlife://{PLACE} SLurl
- LLURLDispatcher::dispatch(url, "clicked", web, true);
- return true;
- }
- };
- LLRegionHandler gRegionHandler;
- LLViewerRegion::LLViewerRegion(const U64& handle, const LLHost& host,
- U32 grids_per_region_edge,
- U32 grids_per_patch_edge,
- F32 region_width_meters)
- : mHandle(handle),
- mHost(host),
- mTimeDilation(1.0f),
- mLastUpdate(0),
- mCreationTime(gFrameTimeSeconds),
- mIsEstateManager(false),
- mRegionFlags(REGION_FLAGS_DEFAULT),
- mRegionProtocols(0),
- mCentralBakeVersion(0),
- mSimAccess(SIM_ACCESS_MIN),
- mBillableFactor(1.0),
- mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT),
- mClassID(0),
- mCPURatio(0),
- mColoName("unknown"),
- mProductSKU("unknown"),
- mProductName("unknown"),
- mCacheLoading(false),
- mCacheLoaded(false),
- mCacheDirty(false),
- mPendingHandshakes(0),
- mLastCameraUpdate(0),
- mLastCameraOrigin(),
- mEventPoll(NULL),
- mSeedCapAttempts(0),
- mHttpResponderID(0),
- mCapabilitiesState(CAPABILITIES_STATE_INIT),
- mFeaturesReceived(false),
- mDead(false),
- mLastVisitedEntry(NULL),
- mInvisibilityCheckHistory(-1),
- mPaused(false),
- mMeshRezEnabled(false),
- mMeshUploadEnabled(false),
- mPhysicsShapeTypes(false),
- mDynamicPathfinding(false),
- mDynamicPathfindingEnabled(false),
- mBakesOnMeshEnabled(false),
- mOSExportPermSupported(false),
- mHoverHeigthFeature(false),
- mWhisperRange((U32)CHAT_WHISPER_RADIUS),
- mChatRange((U32)CHAT_NORMAL_RADIUS),
- mShoutRange((U32)CHAT_SHOUT_RADIUS),
- mMaxMaterialsPerTransaction(50), // Original hard coded default
- mRenderMaterialsCapability(1.f), // Original hard coded default
- mMaxTextureSize(1024),
- mHasPBRTerrain(false),
- mGLTFEnabled(false),
- mFirstWindLayerReceivedTime(0.f),
- mGotClouds(false),
- mWidth(region_width_meters) // Variable region size support
- {
- mOriginGlobal = from_region_handle(handle);
- updateRenderMatrix();
- mLandp = new LLSurface('l', NULL);
- // Create the composition layer for the surface
- mCompositionp = new LLVLComposition(mLandp, grids_per_region_edge,
- region_width_meters / grids_per_region_edge);
- mCompositionp->setSurface(mLandp);
- // Create the surfaces
- mLandp->setRegion(this);
- mLandp->create(grids_per_region_edge, grids_per_patch_edge, mOriginGlobal,
- mWidth);
- mParcelOverlay = new LLViewerParcelOverlay(this, region_width_meters);
- gViewerParcelMgr.setRegionWidth(region_width_meters);
- mWind.setRegionWidth(region_width_meters);
- mCloudLayer.create(this);
- mCloudLayer.setWindPointer(&mWind);
- setOriginGlobal(from_region_handle(handle));
- calculateCenterGlobal();
- // Create the object lists
- initStats();
- initPartitions();
- }
- void LLViewerRegion::initStats()
- {
- mLastNetUpdate.reset();
- mPacketsIn = 0;
- mBitsIn = 0;
- mLastBitsIn = 0;
- mLastPacketsIn = 0;
- mPacketsOut = 0;
- mLastPacketsOut = 0;
- mPacketsLost = 0;
- mLastPacketsLost = 0;
- mPingDelay = 0;
- mAlive = false; // can become false if circuit disconnects
- }
- // Creates object partitions. MUST MATCH declaration of eObjectPartitions
- void LLViewerRegion::initPartitions()
- {
- mObjectPartition.push_back(new LLHUDPartition(this)); //PARTITION_HUD
- mObjectPartition.push_back(new LLTerrainPartition(this)); //PARTITION_TERRAIN
- mObjectPartition.push_back(new LLVoidWaterPartition(this)); //PARTITION_VOIDWATER
- mObjectPartition.push_back(new LLWaterPartition(this)); //PARTITION_WATER
- mObjectPartition.push_back(new LLTreePartition(this)); //PARTITION_TREE
- mObjectPartition.push_back(new LLParticlePartition(this)); //PARTITION_PARTICLE
- mObjectPartition.push_back(new LLCloudPartition(this)); //PARTITION_CLOUD
- mObjectPartition.push_back(new LLGrassPartition(this)); //PARTITION_GRASS
- mObjectPartition.push_back(new LLVolumePartition(this)); //PARTITION_VOLUME
- mObjectPartition.push_back(new LLBridgePartition(this)); //PARTITION_BRIDGE
- mObjectPartition.push_back(new LLAvatarPartition(this)); //PARTITION_AVATAR
- mObjectPartition.push_back(new LLPuppetPartition(this)); //PARTITION_PUPPET
- mObjectPartition.push_back(new LLHUDParticlePartition(this)); //PARTITION_HUD_PARTICLE
- mObjectPartition.push_back(new LLVOCachePartition(this)); //PARTITION_VO_CACHE
- mObjectPartition.push_back(NULL); //PARTITION_NONE
- mVOCachePartition = getVOCachePartition();
- }
- void LLViewerRegion::deletePartitions()
- {
- std::for_each(mObjectPartition.begin(), mObjectPartition.end(),
- DeletePointer());
- mObjectPartition.clear();
- }
- LLViewerRegion::~LLViewerRegion()
- {
- mDead = true;
- mActiveSet.clear();
- mVisibleEntries.clear();
- mVisibleGroups.clear();
- mWaitingSet.clear();
- gVLManager.cleanupData(this);
- // Cannot do this on destruction, because the neighbor pointers might be
- // invalid. This should be reference counted...
- disconnectAllNeighbors();
- mCloudLayer.destroy();
- gViewerPartSim.cleanupRegion(this);
- gObjectList.killObjects(this);
- delete mCompositionp;
- delete mParcelOverlay;
- delete mLandp;
- delete mEventPoll;
- deletePartitions();
- saveObjectCache();
- }
- //static
- void LLViewerRegion::cacheLoadedCallback(U64 region_handle,
- LLVOCacheEntry::map_t* cachep,
- LLVOCacheEntry::emap_t* extrasp)
- {
- LLViewerRegion* self = gWorld.getRegionFromHandle(region_handle);
- if (self && !self->mDead && !LLApp::isExiting())
- {
- LL_DEBUGS("ObjectCache") << "Cache loaded callback for region: "
- << self->mName << " (handle " << region_handle
- << ")" << LL_ENDL;
- self->mCacheLoading = false;
- // Recover the cache data, if any.
- if (!cachep || cachep->empty())
- {
- self->mCacheDirty = true;
- }
- else
- {
- self->mCacheMap.swap(*cachep);
- }
- if (extrasp && !extrasp->empty())
- {
- self->mGLTFOverrides.swap(*extrasp);
- }
- // Reply to the pending handshake(s) now.
- while (self->mPendingHandshakes)
- {
- self->sendHandshakeReply();
- }
- }
- else if (!LLApp::isExiting())
- {
- llwarns << "Skipping for region handle " << region_handle
- << (self ? ": region not found." : " region is dead.")
- << llendl;
- }
- if (cachep)
- {
- delete cachep;
- }
- if (extrasp)
- {
- delete extrasp;
- }
- }
- void LLViewerRegion::loadObjectCache()
- {
- if (!mCacheLoaded)
- {
- // Pretend it is already loaded so that it does not get queued twice
- // or more (we do get several handshakes for the same region in SL). HB
- mCacheLoaded = true;
- if (LLVOCache::instanceExists())
- {
- llinfos << "Loading object cache for region: " << mName << llendl;
- mCacheLoading = true;
- LLVOCache::getInstance()->readFromCache(mHandle, mName, mCacheID);
- }
- }
- }
- void LLViewerRegion::saveObjectCache()
- {
- if (!mCacheLoaded)
- {
- LL_DEBUGS("ObjectCache") << "Cache map not loaded for region: "
- << mName << ". Skiping." << LL_ENDL;
- return;
- }
- if (mCacheMap.empty())
- {
- LL_DEBUGS("ObjectCache") << "Cache map empty for region: " << mName
- << ". Skiping." << LL_ENDL;
- return;
- }
- if (LLVOCache::instanceExists())
- {
- LL_DEBUGS("ObjectCache") << "Saving object cache for region: " << mName
- << LL_ENDL;
- constexpr F32 THRESHOLD = 600.f; // Seconds
- bool removal_enabled =
- sVOCacheCullingEnabled &&
- (LLApp::isExiting() ||
- mCreationTime - gFrameTimeSeconds > THRESHOLD);
- // Note: mCacheMap and/or mGLTFOverrides may be wiped out (for
- // speed, they are actually swapped with an empty map on successful
- // cache write) by this call. So they cannot be reused afterwards, but
- // this is OK, since we are going to destroy it: saveObjectCache() is
- // for now only called at the end of ~LLViewerRegion() (should this
- // change, the swap optimization would have to be removed and replaced
- // with a copy). HB
- LLVOCache::getInstance()->writeToCache(mHandle, mName, mCacheID,
- mCacheMap, mCacheDirty,
- mGLTFOverrides,
- removal_enabled);
- }
- mCacheDirty = false;
- }
- void LLViewerRegion::sendMessage()
- {
- gMessageSystemp->sendMessage(mHost);
- }
- void LLViewerRegion::sendReliableMessage()
- {
- gMessageSystemp->sendReliable(mHost);
- }
- void LLViewerRegion::sendEstateCovenantRequest()
- {
- LLMessageSystem* msg = gMessageSystemp;
- if (msg) // Paranoia
- {
- msg->newMessage(_PREHASH_EstateCovenantRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
- msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
- msg->sendReliable(mHost);
- }
- }
- void LLViewerRegion::setWaterHeight(F32 water_level)
- {
- mLandp->setWaterHeight(water_level);
- }
- F32 LLViewerRegion::getWaterHeight() const
- {
- return mLandp->getWaterHeight();
- }
- void LLViewerRegion::setOriginGlobal(const LLVector3d& origin_global)
- {
- mOriginGlobal = origin_global;
- updateRenderMatrix();
- mLandp->setOriginGlobal(origin_global);
- mWind.setOriginGlobal(origin_global);
- mCloudLayer.setOriginGlobal(origin_global);
- calculateCenterGlobal();
- }
- void LLViewerRegion::updateRenderMatrix()
- {
- mRenderMatrix.setTranslation(getOriginAgent());
- }
- LLVector3 LLViewerRegion::getOriginAgent() const
- {
- return gAgent.getPosAgentFromGlobal(mOriginGlobal);
- }
- LLVector3 LLViewerRegion::getCenterAgent() const
- {
- return gAgent.getPosAgentFromGlobal(mCenterGlobal);
- }
- void LLViewerRegion::setRegionNameAndZone(const std::string& name_zone)
- {
- std::string::size_type pipe_pos = name_zone.find('|');
- if (pipe_pos != std::string::npos)
- {
- size_t length = name_zone.size();
- mName = name_zone.substr(0, pipe_pos);
- mZoning = name_zone.substr(pipe_pos + 1, length - pipe_pos - 1);
- }
- else
- {
- mName = name_zone;
- mZoning.clear();
- }
- LLStringUtil::stripNonprintable(mName);
- LLStringUtil::stripNonprintable(mZoning);
- if (mEventPoll)
- {
- mEventPoll->setRegionName(mName);
- }
- }
- bool LLViewerRegion::canManageEstate() const
- {
- return gAgent.isGodlike() || isEstateManager() || gAgentID == getOwner();
- }
- //static
- std::string LLViewerRegion::accessToString(U8 sim_access)
- {
- static std::string access_pg = LLTrans::getString("SIM_ACCESS_PG");
- static std::string access_mature = LLTrans::getString("SIM_ACCESS_MATURE");
- static std::string access_adult = LLTrans::getString("SIM_ACCESS_ADULT");
- static std::string access_down = LLTrans::getString("SIM_ACCESS_DOWN");
- static std::string access_min = LLTrans::getString("unknown");
- switch (sim_access)
- {
- case SIM_ACCESS_PG:
- return access_pg;
- case SIM_ACCESS_MATURE:
- return access_mature;
- case SIM_ACCESS_ADULT:
- return access_adult;
- case SIM_ACCESS_DOWN:
- return access_down;
- case SIM_ACCESS_MIN:
- default:
- return access_min;
- }
- }
- //static
- std::string LLViewerRegion::accessToShortString(U8 sim_access)
- {
- switch (sim_access)
- {
- case SIM_ACCESS_PG:
- return "PG";
- case SIM_ACCESS_MATURE:
- return "M";
- case SIM_ACCESS_ADULT:
- return "A";
- case SIM_ACCESS_MIN:
- default:
- return "U";
- }
- }
- //static
- const std::string& LLViewerRegion::getMaturityIconName(U8 sim_access)
- {
- static const std::string pg = "access_pg.tga";
- static const std::string mature = "access_mature.tga";
- static const std::string adult = "access_adult.tga";
- if (sim_access <= SIM_ACCESS_PG)
- {
- return pg;
- }
- if (sim_access <= SIM_ACCESS_MATURE)
- {
- return mature;
- }
- return adult;
- }
- //static
- void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**)
- {
- if (!msg) return;
- std::string sim_name;
- msg->getString(_PREHASH_RegionInfo, _PREHASH_SimName, sim_name);
- F32 water_height;
- msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_WaterHeight, water_height);
- if (msg->getSender() != gAgent.getRegionHost())
- {
- // Update is for a different region than the one we are in.
- // Just check for a waterheight change.
- gWorld.waterHeightRegionInfo(sim_name, water_height);
- return;
- }
- LLRegionInfoModel::sSimName = sim_name;
- LLRegionInfoModel::sWaterHeight = water_height;
- msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_EstateID,
- LLRegionInfoModel::sEstateID);
- msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_ParentEstateID,
- LLRegionInfoModel::sParentEstateID);
- msg->getU8Fast(_PREHASH_RegionInfo, _PREHASH_SimAccess,
- LLRegionInfoModel::sSimAccess);
- msg->getU8Fast(_PREHASH_RegionInfo, _PREHASH_MaxAgents,
- LLRegionInfoModel::sAgentLimit);
- LLRegionInfoModel::sHardAgentLimit = 0;
- msg->getS32(_PREHASH_RegionInfo2, _PREHASH_HardMaxAgents,
- LLRegionInfoModel::sHardAgentLimit);
- if (!LLRegionInfoModel::sHardAgentLimit)
- {
- LLRegionInfoModel::sHardAgentLimit = 100;
- }
- msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_ObjectBonusFactor,
- LLRegionInfoModel::sObjectBonusFactor);
- msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_BillableFactor,
- LLRegionInfoModel::sBillableFactor);
- msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainRaiseLimit,
- LLRegionInfoModel::sTerrainRaiseLimit);
- msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainLowerLimit,
- LLRegionInfoModel::sTerrainLowerLimit);
- msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_PricePerMeter,
- LLRegionInfoModel::sPricePerMeter);
- msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_RedirectGridX,
- LLRegionInfoModel::sRedirectGridX);
- msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_RedirectGridY,
- LLRegionInfoModel::sRedirectGridY);
- msg->getBool(_PREHASH_RegionInfo, _PREHASH_UseEstateSun,
- LLRegionInfoModel::sUseEstateSun);
- // Actually the "last set" Sun hour, not the current Sun hour.
- msg->getF32(_PREHASH_RegionInfo, _PREHASH_SunHour,
- LLRegionInfoModel::sSunHour);
- // The only reasonable way to decide if we actually have any data is to
- // check to see if any of these fields have nonzero sizes
- std::string sim_type = LLTrans::getString("unknown");
- if (msg->getSize(_PREHASH_RegionInfo2, _PREHASH_ProductSKU) > 0 ||
- msg->getSize(_PREHASH_RegionInfo2, _PREHASH_ProductName) > 0)
- {
- msg->getString(_PREHASH_RegionInfo2, _PREHASH_ProductName,
- LLRegionInfoModel::sSimType);
- }
- else
- {
- LLRegionInfoModel::sSimType.clear();
- }
- if (msg->has(_PREHASH_RegionInfo3))
- {
- msg->getU64(_PREHASH_RegionInfo3, _PREHASH_RegionFlagsExtended,
- LLRegionInfoModel::sRegionFlags);
- }
- else
- {
- U32 flags = 0;
- msg->getU32(_PREHASH_RegionInfo, _PREHASH_RegionFlags, flags);
- LLRegionInfoModel::sRegionFlags = flags;
- }
- // Push values to the agent region
- LLViewerRegion* self = gAgent.getRegion();
- if (self)
- {
- self->setRegionNameAndZone(sim_name);
- self->setRegionFlags(LLRegionInfoModel::sRegionFlags);
- self->setSimAccess(LLRegionInfoModel::sSimAccess);
- self->setWaterHeight(LLRegionInfoModel::sWaterHeight);
- self->setBillableFactor(LLRegionInfoModel::sBillableFactor);
- }
- // Send the region info update notification to interested parties.
- LLFloaterRegionInfo::updateFromRegionInfo();
- LLFloaterGodTools::updateFromRegionInfo();
- // *TODO: this frequently results in one more request than we need. It is
- // not breaking, but should be nicer. We need to know new env version to
- // fix this, without it we can only do full re-request. They happens on
- // updates, on opening LLFloaterRegionInfo, on region crossing if info
- // floater is open.
- LLEnvironment::requestRegion();
- }
- void LLViewerRegion::renderPropertyLines() const
- {
- if (mParcelOverlay)
- {
- mParcelOverlay->renderPropertyLines();
- }
- }
- void LLViewerRegion::renderParcelBorders(F32 scale, const F32* color) const
- {
- if (mParcelOverlay)
- {
- mParcelOverlay->renderParcelBorders(scale, color);
- }
- }
- bool LLViewerRegion::renderBannedParcels(F32 scale, const F32* color) const
- {
- return mParcelOverlay && mParcelOverlay->renderBannedParcels(scale, color);
- }
- // This gets called when the height field changes.
- void LLViewerRegion::dirtyHeights()
- {
- // Property lines need to be reconstructed when the land changes.
- if (mParcelOverlay)
- {
- mParcelOverlay->setDirty();
- }
- }
- // Physically delete the cache entry
- void LLViewerRegion::killCacheEntry(LLVOCacheEntry* entryp, bool for_rendering)
- {
- if (!entryp|| !entryp->isValid())
- {
- return;
- }
- if (for_rendering && !entryp->isState(LLVOCacheEntry::ACTIVE))
- {
- addNewObject(entryp); // Force to add to rendering pipeline
- }
- // Remove from active list and waiting list
- if (entryp->isState(LLVOCacheEntry::ACTIVE))
- {
- mActiveSet.erase(entryp);
- }
- else
- {
- if (entryp->isState(LLVOCacheEntry::WAITING))
- {
- mWaitingSet.erase(entryp);
- }
- // Remove from mVOCachePartition
- removeFromVOCacheTree(entryp);
- }
- // Remove from the forced visible list
- mVisibleEntries.erase(entryp);
- // Disconnect from parent if it is a child
- if (entryp->getParentID() > 0)
- {
- LLVOCacheEntry* parentp = getCacheEntry(entryp->getParentID());
- if (parentp)
- {
- parentp->removeChild(entryp);
- }
- }
- else if (entryp->getNumOfChildren() > 0)
- {
- LLVOCacheEntry* childp = entryp->getChild();
- while (childp)
- {
- killCacheEntry(childp, for_rendering);
- childp = entryp->getChild();
- }
- }
- #if 0 // Nope: do not do this ! The object may re-rez later in the same
- // session (e.g. for neighbour region objects, depending on draw
- // distance, while moving or caming around) and its override may
- // not be re-sent by the simulator, causing a loss in the override
- // data ! HB
- // Kill the associated GLTF override.
- mGLTFOverrides.erase(entryp->getLocalID());
- #endif
- // Will remove it from the object cache, real deletion
- entryp->setState(LLVOCacheEntry::INACTIVE);
- entryp->removeOctreeEntry();
- entryp->setValid(false);
- }
- // Physically delete the cache entry
- void LLViewerRegion::killCacheEntry(U32 local_id)
- {
- killCacheEntry(getCacheEntry(local_id));
- }
- void LLViewerRegion::addActiveCacheEntry(LLVOCacheEntry* entry)
- {
- if (!entry || mDead ||
- // Ignore if already inserted
- entry->isState(LLVOCacheEntry::ACTIVE))
- {
- return;
- }
- if (entry->isState(LLVOCacheEntry::WAITING))
- {
- mWaitingSet.erase(entry);
- }
- entry->setState(LLVOCacheEntry::ACTIVE);
- entry->setVisible();
- llassert(entry->getEntry()->hasDrawable());
- mActiveSet.insert(entry);
- }
- void LLViewerRegion::removeActiveCacheEntry(LLVOCacheEntry* entry,
- LLDrawable* drawablep)
- {
- if (mDead || !entry || !entry->isValid() ||
- // Ignore if not an active entry
- !entry->isState(LLVOCacheEntry::ACTIVE))
- {
- return;
- }
- // Shift to the local regional space from agent space
- if (drawablep && drawablep->getVObj().notNull())
- {
- const LLVector3& pos = drawablep->getVObj()->getPositionRegion();
- LLVector4a shift;
- shift.load3(pos.mV);
- shift.sub(entry->getPositionGroup());
- entry->shift(shift);
- }
- if (entry->getParentID() > 0) // is a child
- {
- LLVOCacheEntry* parent = getCacheEntry(entry->getParentID());
- if (parent)
- {
- parent->addChild(entry);
- }
- else
- {
- // Parent not in cache (happens only when it is not cacheable)
- mOrphanMap[entry->getParentID()].push_back(entry->getLocalID());
- }
- }
- else
- {
- // Insert to vo cache tree.
- entry->updateParentBoundingInfo();
- entry->saveBoundingSphere();
- addToVOCacheTree(entry);
- }
- mVisibleEntries.erase(entry);
- mActiveSet.erase(entry);
- mWaitingSet.erase(entry);
- entry->setState(LLVOCacheEntry::INACTIVE);
- }
- bool LLViewerRegion::addVisibleGroup(LLViewerOctreeGroup* group)
- {
- if (mDead || group->isEmpty())
- {
- return false;
- }
- mVisibleGroups.push_back(group);
- return true;
- }
- void LLViewerRegion::updateReflectionProbes()
- {
- constexpr F32 HOVER_HEIGHT = 2.f;
- constexpr F32 PROBE_SPACING = 32.f;
- constexpr F32 HALF_PROBE_SPACING = PROBE_SPACING * 0.5f;
- constexpr F32 START = HALF_PROBE_SPACING;
- static const F32 PROBE_RADIUS = sqrtf(HALF_PROBE_SPACING *
- HALF_PROBE_SPACING * 3.f);
- // Using mWidth here instead of REGION_WIDTH_METERS for Variable region
- // size support. HB
- U32 grid_width = mWidth / PROBE_SPACING;
- mReflectionMaps.resize(grid_width * grid_width);
- F32 water_height = getWaterHeight();
- LLVector3 origin = getOriginAgent();
- for (U32 i = 0; i < grid_width; ++i)
- {
- F32 x = i * PROBE_SPACING + START;
- for (U32 j = 0; j < grid_width; ++j)
- {
- F32 y = j * PROBE_SPACING + START;
- U32 idx = i * grid_width + j;
- if (mReflectionMaps[idx].isNull())
- {
- mReflectionMaps[idx] =
- gPipeline.mReflectionMapManager.addProbe();
- }
- LLVector3 pos(x, y,
- HOVER_HEIGHT +
- llmax(water_height,
- mLandp->resolveHeightRegion(x, y)));
- pos += origin;
- mReflectionMaps[idx]->mOrigin.load3(pos.mV);
- mReflectionMaps[idx]->mRadius = PROBE_RADIUS;
- }
- }
- }
- void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry)
- {
- if (entry && sVOCacheCullingEnabled && !mDead &&
- entry->getEntry() && entry->isValid() &&
- entry->getParentID() == 0 && // Child in octree
- !entry->hasState(LLVOCacheEntry::IN_VO_TREE)) // Not in octree
- {
- llassert_always(!entry->getGroup()); // Not in octree.
- llassert(!entry->getEntry()->hasDrawable()); // No drawable
- if (mVOCachePartition->addEntry(entry->getEntry()))
- {
- entry->setState(LLVOCacheEntry::IN_VO_TREE);
- }
- }
- }
- void LLViewerRegion::removeFromVOCacheTree(LLVOCacheEntry* entry)
- {
- if (entry && !mDead && entry->getEntry() &&
- // Must be in tree
- entry->hasState(LLVOCacheEntry::IN_VO_TREE))
- {
- entry->clearState(LLVOCacheEntry::IN_VO_TREE);
- mVOCachePartition->removeEntry(entry->getEntry());
- }
- }
- // Add child objects as visible entries
- void LLViewerRegion::addVisibleChildCacheEntry(LLVOCacheEntry* parent,
- LLVOCacheEntry* child)
- {
- if (mDead)
- {
- return;
- }
- if (parent &&
- (!parent->isValid() || !parent->isState(LLVOCacheEntry::ACTIVE)))
- {
- // Parent must be valid and in rendering pipeline
- return;
- }
- if (child &&
- (!child->getEntry() || !child->isValid() ||
- !child->isState(LLVOCacheEntry::INACTIVE)))
- {
- // Child must be valid and not in the rendering pipeline
- return;
- }
- if (child)
- {
- child->setState(LLVOCacheEntry::IN_QUEUE);
- mVisibleEntries.insert(child);
- }
- else if (parent && parent->getNumOfChildren() > 0)
- {
- // Add all children
- while ((child = parent->getChild()))
- {
- addVisibleChildCacheEntry(NULL, child);
- }
- }
- }
- void LLViewerRegion::updateVisibleEntries()
- {
- if (mDead || !sNewObjectCreationThrottle ||
- (mVisibleGroups.empty() && mVisibleEntries.empty()))
- {
- return;
- }
- // A large number to force to load the object:
- constexpr F32 LARGE_SCENE_CONTRIBUTION = 1000.f;
- const LLVector3 camera_origin = gViewerCamera.getOrigin();
- const U32 cur_frame = LLViewerOctreeEntryData::getCurrentFrame();
- bool needs_update = cur_frame - mLastCameraUpdate > 5 &&
- (camera_origin -
- mLastCameraOrigin).lengthSquared() > 10.f;
- U32 last_update = mLastCameraUpdate;
- LLVector4a local_origin;
- local_origin.load3((camera_origin - getOriginAgent()).mV);
- // Process visible entries
- for (LLVOCacheEntry::set_t::iterator iter = mVisibleEntries.begin(),
- end = mVisibleEntries.end();
- iter != end; )
- {
- LLVOCacheEntry::set_t::iterator curiter = iter++;
- LLVOCacheEntry* entryp = *curiter;
- if (entryp && entryp->isValid() &&
- entryp->getState() < LLVOCacheEntry::WAITING)
- {
- // Set a large number to force to load this object.
- entryp->setSceneContribution(LARGE_SCENE_CONTRIBUTION);
- mWaitingList.insert(entryp);
- }
- else
- {
- mVisibleEntries.erase(curiter);
- }
- }
- // Process visible groups
- if (!mVOCachePartition)
- {
- return;
- }
- // Object projected area threshold
- F32 projection_threshold =
- LLVOCacheEntry::getSquaredPixelThreshold(mVOCachePartition->isFrontCull());
- F32 dist_threshold =
- mVOCachePartition->isFrontCull() ? gAgent.mDrawDistance
- : LLVOCacheEntry::sRearFarRadius;
- for (U32 i = 0, count = mVisibleGroups.size(); i < count; ++i)
- {
- LLPointer<LLViewerOctreeGroup> group = mVisibleGroups[i];
- if (group.isNull() || group->getNumRefs() < 3 || // Group to be deleted
- !group->getOctreeNode() || group->isEmpty()) // Group empty
- {
- continue;
- }
- for (LLViewerOctreeGroup::element_iter it = group->getDataBegin(),
- end2 = group->getDataEnd();
- it != end2; ++it)
- {
- if (*it && (*it)->hasVOCacheEntry())
- {
- LLVOCacheEntry* entryp =
- (LLVOCacheEntry*)(*it)->getVOCacheEntry();
- if (entryp->getParentID() == 0 && entryp->isValid())
- {
- entryp->calcSceneContribution(local_origin, needs_update,
- last_update, dist_threshold);
- if (entryp->getSceneContribution() > projection_threshold)
- {
- mWaitingList.insert(entryp);
- }
- }
- }
- }
- }
- if (needs_update)
- {
- mLastCameraOrigin = camera_origin;
- mLastCameraUpdate = cur_frame;
- }
- }
- void LLViewerRegion::createVisibleObjects(F32 max_time)
- {
- if (mDead)
- {
- return;
- }
- if (mWaitingList.empty())
- {
- mVOCachePartition->setCullHistory(false);
- return;
- }
- S32 throttle = sNewObjectCreationThrottle;
- bool do_throttle = throttle > 0;
- bool has_new_obj = false;
- LLTimer update_timer;
- for (LLVOCacheEntry::prio_list_t::iterator iter = mWaitingList.begin(),
- end = mWaitingList.end();
- iter != end; ++iter)
- {
- LLVOCacheEntry* entryp = *iter;
- if (entryp->getState() < LLVOCacheEntry::WAITING)
- {
- addNewObject(entryp);
- has_new_obj = true;
- if ((do_throttle && --throttle <= 0) ||
- update_timer.getElapsedTimeF32() > max_time)
- {
- break;
- }
- }
- }
- mVOCachePartition->setCullHistory(has_new_obj);
- }
- void LLViewerRegion::clearCachedVisibleObjects()
- {
- mWaitingList.clear();
- mVisibleGroups.clear();
- // Reset all occluders
- mVOCachePartition->resetOccluders();
- mPaused = true;
- // Clean visible entries
- for (LLVOCacheEntry::set_t::iterator iter = mVisibleEntries.begin();
- iter != mVisibleEntries.end(); )
- {
- LLVOCacheEntry::set_t::iterator curiter = iter++;
- LLVOCacheEntry* entry = *curiter;
- LLVOCacheEntry* parent = getCacheEntry(entry->getParentID());
- // If no child or parent is cache-able
- if (!entry->getParentID() || parent)
- {
- if (parent) // Has a cache-able parent
- {
- parent->addChild(entry);
- }
- mVisibleEntries.erase(curiter);
- }
- }
- // Remove all visible entries.
- mLastVisitedEntry = NULL;
- std::vector<LLDrawable*> delete_list;
- for (LLVOCacheEntry::set_t::iterator iter = mActiveSet.begin(),
- end = mActiveSet.end();
- iter != end; ++iter)
- {
- LLVOCacheEntry* entryp = *iter;
- if (!entryp)
- {
- continue;
- }
- LLViewerOctreeEntry* octreep = entryp->getEntry();
- if (!octreep)
- {
- continue;
- }
- LLDrawable* drawablep = (LLDrawable*)octreep->getDrawable();
- if (drawablep && !drawablep->getParent())
- {
- delete_list.push_back(drawablep);
- }
- }
- if (!delete_list.empty())
- {
- for (S32 i = 0, count = delete_list.size(); i < count; ++i)
- {
- gObjectList.killObject(delete_list[i]->getVObj());
- }
- delete_list.clear();
- }
- }
- // Perform some necessary but very light updates to replace the function
- // idleUpdate(...) in case there is not enough time.
- void LLViewerRegion::lightIdleUpdate()
- {
- if (sVOCacheCullingEnabled && !mCacheMap.empty())
- {
- LL_FAST_TIMER(FTM_UPD_CACHEDOBJECTS);
- // Reset all occluders
- mVOCachePartition->resetOccluders();
- }
- }
- void LLViewerRegion::idleUpdate(F32 max_update_time)
- {
- LLTimer update_timer;
- mLastUpdate = LLViewerOctreeEntryData::getCurrentFrame();
- {
- LL_FAST_TIMER(FTM_UPD_LANDPATCHES);
- mLandp->idleUpdate(max_update_time);
- }
- if (mParcelOverlay)
- {
- LL_FAST_TIMER(FTM_UPD_PARCELOVERLAY);
- // Hopefully not a significant time sink...
- mParcelOverlay->idleUpdate();
- }
- if (sVOCacheCullingEnabled && !mCacheMap.empty())
- {
- LL_FAST_TIMER(FTM_UPD_CACHEDOBJECTS);
- mPaused = false; // Un-pause
- S32 old_camera_id = LLViewerCamera::sCurCameraID;
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- // Reset all occluders
- mVOCachePartition->resetOccluders();
- F32 max_time = max_update_time - update_timer.getElapsedTimeF32();
- killInvisibleObjects(max_time * 0.4f);
- updateVisibleEntries();
- max_time = max_update_time - update_timer.getElapsedTimeF32();
- createVisibleObjects(max_time);
- mWaitingList.clear();
- mVisibleGroups.clear();
- LLViewerCamera::sCurCameraID = old_camera_id;
- }
- }
- // Update the throttling number for new object creation
- void LLViewerRegion::calcNewObjectCreationThrottle()
- {
- static LLCachedControl<S32> creation_throttle(gSavedSettings,
- "NewObjectCreationThrottle");
- static LLCachedControl<F32> throttle_delay(gSavedSettings,
- "NewObjectCreationThrottleDelay");
- static LLFrameTimer timer;
- // sNewObjectCreationThrottle =
- // -2 : throttle is disabled because either the screen is showing progress
- // view, or immediate after the screen is not black
- // -1 : throttle is disabled by the debug setting
- // 0 : no new object creation is allowed
- // > 0 : valid throttling number
- if (throttle_delay > 0.f &&
- (gTeleportDisplay ||
- (gViewerWindowp && gViewerWindowp->getProgressView()->getVisible())))
- {
- sNewObjectCreationThrottle = -2; // cancel the throttling
- timer.reset();
- }
- else if (sNewObjectCreationThrottle < -1)
- {
- // Just recovered from the login/teleport screen... Wait for
- // throttle_delay to reset the throttle
- if (timer.getElapsedTimeF32() > throttle_delay)
- {
- sNewObjectCreationThrottle = creation_throttle;
- if (sNewObjectCreationThrottle < -1)
- {
- sNewObjectCreationThrottle = -1;
- }
- }
- }
- }
- bool LLViewerRegion::isViewerCameraStatic()
- {
- return sLastCameraUpdated < LLViewerOctreeEntryData::getCurrentFrame();
- }
- void LLViewerRegion::killInvisibleObjects(F32 max_time)
- {
- if (!sVOCacheCullingEnabled || sNewObjectCreationThrottle < -1 ||
- mActiveSet.empty())
- {
- return;
- }
- LLTimer update_timer;
- LLVector4a camera_origin;
- camera_origin.load3(gViewerCamera.getOrigin().mV);
- LLVector4a local_origin;
- local_origin.load3((gViewerCamera.getOrigin() - getOriginAgent()).mV);
- F32 back_threshold = LLVOCacheEntry::sRearFarRadius;
- size_t max_update = 64;
- if (!mInvisibilityCheckHistory && isViewerCameraStatic())
- {
- // History is clean, reduce number of checking
- max_update /= 2;
- }
- std::vector<LLDrawable*> delete_list;
- S32 update_counter = llmin(max_update, mActiveSet.size());
- LLVOCacheEntry::set_t::iterator iter;
- for (iter = mActiveSet.upper_bound(mLastVisitedEntry);
- update_counter > 0; --update_counter, ++iter)
- {
- if (iter == mActiveSet.end())
- {
- iter = mActiveSet.begin();
- }
- if ((*iter)->getParentID() > 0)
- {
- // Skip child objects: they are removed with their parent.
- continue;
- }
- LLVOCacheEntry* entryp = *iter;
- if (!entryp->isAnyVisible(camera_origin, local_origin,
- back_threshold) &&
- entryp->mLastCameraUpdated < sLastCameraUpdated)
- {
- killObject(entryp, delete_list);
- }
- if (max_time < update_timer.getElapsedTimeF32())
- {
- break; // We timed out
- }
- }
- if (iter == mActiveSet.end())
- {
- mLastVisitedEntry = NULL;
- }
- else
- {
- mLastVisitedEntry = *iter;
- }
- mInvisibilityCheckHistory <<= 1;
- if (!delete_list.empty())
- {
- mInvisibilityCheckHistory |= 1;
- for (S32 i = 0, count = delete_list.size(); i < count; ++i)
- {
- gObjectList.killObject(delete_list[i]->getVObj());
- }
- delete_list.clear();
- }
- }
- void LLViewerRegion::killObject(LLVOCacheEntry* entry,
- std::vector<LLDrawable*>& delete_list)
- {
- // kill the object.
- LLDrawable* drawablep = (LLDrawable*)entry->getEntry()->getDrawable();
- llassert(drawablep && drawablep->getRegion() == this);
- if (drawablep && !drawablep->getParent())
- {
- LLViewerObject* vobj = drawablep->getVObj();
- if (vobj)
- {
- if (vobj->isSelected() ||
- (vobj->flagAnimSource() && isAgentAvatarValid() &&
- gAgentAvatarp->hasMotionFromSource(vobj->getID())))
- {
- // Do not remove objects user is interacting with
- ((LLViewerOctreeEntryData*)drawablep)->setVisible();
- return;
- }
- LLViewerObject::const_child_list_t& child_list = vobj->getChildren();
- for (LLViewerObject::child_list_t::const_iterator
- iter = child_list.begin(), end = child_list.end();
- iter != end; ++iter)
- {
- LLViewerObject* child = *iter;
- if (child && child->mDrawable)
- {
- if (!child->mDrawable->getEntry() ||
- !child->mDrawable->getEntry()->hasVOCacheEntry() ||
- child->isSelected() ||
- (child->flagAnimSource() &&
- isAgentAvatarValid() &&
- gAgentAvatarp->hasMotionFromSource(child->getID())))
- {
- // Do not remove parent if any of its children is non-
- // cacheable, animating or selected, especially for the
- // case when an avatar sits on a cacheable object.
- ((LLViewerOctreeEntryData*)drawablep)->setVisible();
- return;
- }
- LLOcclusionCullingGroup* group =
- (LLOcclusionCullingGroup*)child->mDrawable->getGroup();
- if (group && group->isAnyRecentlyVisible())
- {
- // Set the parent visible if any of its children visible.
- ((LLViewerOctreeEntryData*)drawablep)->setVisible();
- return;
- }
- }
- }
- }
- else
- {
- llwarns_once << "NULL viewer object for drawable: " << std::hex
- << drawablep << std::dec << llendl;
- llassert(false);
- }
- delete_list.push_back(drawablep);
- }
- }
- LLViewerObject* LLViewerRegion::addNewObject(LLVOCacheEntry* entry)
- {
- if (!entry || !entry->getEntry())
- {
- if (entry)
- {
- mVisibleEntries.erase(entry);
- entry->setState(LLVOCacheEntry::INACTIVE);
- }
- return NULL;
- }
- LLViewerObject* objp = NULL;
- if (!entry->getEntry()->hasDrawable())
- {
- // Not yet added to the rendering pipeline... Add the object now.
- objp = gObjectList.processObjectUpdateFromCache(entry, this);
- if (objp && !entry->isState(LLVOCacheEntry::ACTIVE))
- {
- mWaitingSet.insert(entry);
- entry->setState(LLVOCacheEntry::WAITING);
- }
- }
- else
- {
- LLViewerRegion* old_regionp =
- ((LLDrawable*)entry->getEntry()->getDrawable())->getRegion();
- if (old_regionp != this)
- {
- // This object exists in two regions at the same time; this case
- // can be safely ignored here because the server should soon send
- // update message to remove one region for this object.
- llwarns_once << "Entry: " << entry->getLocalID()
- << " exists in two regions at the same time."
- << llendl;
- return NULL;
- }
- llwarns_once << "Entry: " << entry->getLocalID()
- << " in rendering pipeline but not set to be active."
- << llendl;
- // Should not hit here any more, but does not hurt either, just put it
- // back to active list
- addActiveCacheEntry(entry);
- }
- if (objp)
- {
- loadCacheMiscExtras(objp);
- }
- return objp;
- }
- void LLViewerRegion::loadCacheMiscExtras(LLViewerObject* objp)
- {
- if (!objp)
- {
- return;
- }
- U32 local_id = objp->getLocalID();
- LLVOCacheEntry::emap_t::iterator iter = mGLTFOverrides.find(local_id);
- if (iter == mGLTFOverrides.end())
- {
- return;
- }
- LL_DEBUGS("ObjectCache") << "Applying cached data to object: "
- << objp->getID() << LL_ENDL;
- bool has_te[MAX_TES] = { false };
- const LLGLTFOverrideCacheEntry& entry = iter->second;
- for (auto it = entry.mGLTFMaterial.begin(),
- end = entry.mGLTFMaterial.end();
- it != end; ++it)
- {
- S32 te = it->first;
- objp->setTEGLTFMaterialOverride(te, it->second);
- if (objp->getTE(te) && objp->getTE(te)->isSelected())
- {
- LLGLTFMaterialList::doSelectionCallbacks(objp->getID(), te);
- }
- if (te < (S32)MAX_TES)
- {
- has_te[te] = true;
- }
- }
- // Null out overrides on TEs that should not have them
- for (U32 i = 0, count = llmin(objp->getNumTEs(), MAX_TES); i < count; ++i)
- {
- if (!has_te[i])
- {
- LLTextureEntry* tep = objp->getTE(i);
- if (tep && tep->getGLTFMaterialOverride())
- {
- objp->setTEGLTFMaterialOverride(i, NULL);
- LLGLTFMaterialList::doSelectionCallbacks(objp->getID(), i);
- }
- }
- }
- }
- void LLViewerRegion::applyCacheMiscExtras(LLViewerObject* objp)
- {
- if (!objp) return;
- U32 local_id = objp->getLocalID();
- LLVOCacheEntry::emap_t::iterator it = mGLTFOverrides.find(local_id);
- if (it == mGLTFOverrides.end())
- {
- return;
- }
- for (auto& side : it->second.mGLTFMaterial)
- {
- objp->setTEGLTFMaterialOverride(side.first, side.second);
- }
- }
- // Updates object cache if the object receives a full-update or a terse update
- LLViewerObject* LLViewerRegion::updateCacheEntry(U32 local_id,
- LLViewerObject* objectp)
- {
- LLVOCacheEntry* entry = getCacheEntry(local_id);
- if (!entry)
- {
- return objectp; // Not in the cache, do nothing.
- }
- if (!objectp) // Object not created
- {
- // Create a new object from cache.
- objectp = addNewObject(entry);
- }
- // Remove from cache
- killCacheEntry(entry, true);
- return objectp;
- }
- void LLViewerRegion::forceUpdate()
- {
- mLandp->idleUpdate(0.f);
- if (mParcelOverlay)
- {
- mParcelOverlay->idleUpdate(true);
- }
- }
- bool LLViewerRegion::isEventPollInFlight() const
- {
- return mEventPoll && mEventPoll->isPollInFlight();
- }
- F32 LLViewerRegion::getEventPollRequestAge() const
- {
- return mEventPoll ? mEventPoll->getPollAge() : -1.f;
- }
- void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction)
- {
- mLandp->connectNeighbor(neighborp->mLandp, direction);
- mCloudLayer.connectNeighbor(&(neighborp->mCloudLayer), direction);
- }
- void LLViewerRegion::disconnectAllNeighbors()
- {
- mLandp->disconnectAllNeighbors();
- mCloudLayer.disconnectAllNeighbors();
- }
- F32 LLViewerRegion::getCompositionXY(S32 x, S32 y) const
- {
- if (x >= mWidth)
- {
- if (y >= mWidth)
- {
- LLVector3d center = getCenterGlobal() +
- LLVector3d(mWidth, mWidth, 0.f);
- LLViewerRegion* regionp = gWorld.getRegionFromPosGlobal(center);
- if (regionp)
- {
- // OK, we need to do some hackery here - different simulators
- // no longer use the same composition values, necessarily.
- // If we're attempting to blend, then we want to make the
- // fractional part of this region match the fractional of the
- // adjacent. For now, just minimize the delta.
- F32 our_comp = mCompositionp->getValueScaled(mWidth - 1.f,
- mWidth - 1.f);
- F32 adj_comp =
- regionp->mCompositionp->getValueScaled(x - regionp->mWidth,
- y - regionp->mWidth);
- while (fabsf(our_comp - adj_comp) >= 1.f)
- {
- if (our_comp > adj_comp)
- {
- adj_comp += 1.f;
- }
- else
- {
- adj_comp -= 1.f;
- }
- }
- return adj_comp;
- }
- }
- else
- {
- LLVector3d center = getCenterGlobal() + LLVector3d(mWidth, 0, 0.f);
- LLViewerRegion* regionp = gWorld.getRegionFromPosGlobal(center);
- if (regionp)
- {
- // OK, we need to do some hackery here - different simulators
- // no longer use the same composition values, necessarily.
- // If we're attempting to blend, then we want to make the
- // fractional part of this region match the fractional of the
- // adjacent. For now, just minimize the delta.
- F32 our_comp = mCompositionp->getValueScaled(mWidth - 1.f,
- (F32)y);
- F32 adj_comp =
- regionp->mCompositionp->getValueScaled(x - regionp->mWidth,
- (F32)y);
- while (fabsf(our_comp - adj_comp) >= 1.f)
- {
- if (our_comp > adj_comp)
- {
- adj_comp += 1.f;
- }
- else
- {
- adj_comp -= 1.f;
- }
- }
- return adj_comp;
- }
- }
- }
- else if (y >= mWidth)
- {
- LLVector3d center = getCenterGlobal() + LLVector3d(0.f, mWidth, 0.f);
- LLViewerRegion* regionp = gWorld.getRegionFromPosGlobal(center);
- if (regionp)
- {
- // OK, we need to do some hackery here - different simulators no
- // longer use the same composition values, necessarily. If we're
- // attempting to blend, then we want to make the fractional part of
- // this region match the fractional of the adjacent. For now, just
- // minimize the delta.
- F32 our_comp = mCompositionp->getValueScaled((F32)x, mWidth - 1.f);
- F32 adj_comp =
- regionp->mCompositionp->getValueScaled((F32)x,
- y - regionp->mWidth);
- while (fabsf(our_comp - adj_comp) >= 1.f)
- {
- if (our_comp > adj_comp)
- {
- adj_comp += 1.f;
- }
- else
- {
- adj_comp -= 1.f;
- }
- }
- return adj_comp;
- }
- }
- return mCompositionp->getValueScaled((F32)x, (F32)y);
- }
- void LLViewerRegion::calculateCenterGlobal()
- {
- mCenterGlobal = mOriginGlobal;
- mCenterGlobal.mdV[VX] += 0.5 * mWidth;
- mCenterGlobal.mdV[VY] += 0.5 * mWidth;
- mCenterGlobal.mdV[VZ] = 0.5 * mLandp->getMinZ() + mLandp->getMaxZ();
- }
- void LLViewerRegion::calculateCameraDistance()
- {
- mCameraDistanceSquared = (F32)(gAgent.getCameraPositionGlobal() -
- getCenterGlobal()).lengthSquared();
- }
- std::ostream& operator<<(std::ostream& s, const LLViewerRegion& region)
- {
- s << "{ " << region.mHost
- << " mOriginGlobal = " << region.getOriginGlobal() << "\n";
- std::string name = region.getName();
- if (!name.empty())
- {
- s << " mName = " << name << '\n';
- }
- name = region.getZoning();
- if (!name.empty())
- {
- s << " mZoning = " << name << '\n';
- }
- s << "}";
- return s;
- }
- void LLViewerRegion::updateNetStats()
- {
- F32 dt = mLastNetUpdate.getElapsedTimeAndResetF32();
- LLCircuitData* cdp = gMessageSystemp->mCircuitInfo.findCircuit(mHost);
- if (!cdp)
- {
- mAlive = false;
- return;
- }
- mAlive = true;
- mDeltaTime = dt;
- mLastPacketsIn = mPacketsIn;
- mLastBitsIn = mBitsIn;
- mLastPacketsOut = mPacketsOut;
- mLastPacketsLost = mPacketsLost;
- mPacketsIn = cdp->getPacketsIn();
- mBitsIn = 8 * cdp->getBytesIn();
- mPacketsOut = cdp->getPacketsOut();
- mPacketsLost = cdp->getPacketsLost();
- mPingDelay = cdp->getPingDelay();
- mBitStat.addValue(mBitsIn - mLastBitsIn);
- mPacketsStat.addValue(mPacketsIn - mLastPacketsIn);
- mPacketsLostStat.addValue(mPacketsLost);
- }
- U32 LLViewerRegion::getPacketsLost() const
- {
- LLCircuitData* cdp = gMessageSystemp->mCircuitInfo.findCircuit(mHost);
- if (!cdp)
- {
- llinfos << "Could not find circuit for " << mHost << llendl;
- return 0;
- }
- return cdp->getPacketsLost();
- }
- bool LLViewerRegion::pointInRegionGlobal(const LLVector3d& point_global) const
- {
- LLVector3 pos_region = getPosRegionFromGlobal(point_global);
- return pos_region.mV[VX] >= 0 && pos_region.mV[VX] < mWidth &&
- pos_region.mV[VY] >= 0 && pos_region.mV[VY] <mWidth;
- }
- LLVector3 LLViewerRegion::getPosAgentFromRegion(const LLVector3& pos_region) const
- {
- return gAgent.getPosAgentFromGlobal(getPosGlobalFromRegion(pos_region));
- }
- F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos)
- {
- return mLandp->resolveHeightRegion(region_pos);
- }
- bool LLViewerRegion::isOwnedSelf(const LLVector3& pos)
- {
- return mParcelOverlay && mParcelOverlay->isOwnedSelf(pos);
- }
- // Owned by a group you belong to? (officer or member)
- bool LLViewerRegion::isOwnedGroup(const LLVector3& pos)
- {
- return mParcelOverlay && mParcelOverlay->isOwnedGroup(pos);
- }
- // Yhe new TCP coarse location handler node
- class CoarseLocationUpdate final : public LLHTTPNode
- {
- public:
- void post(ResponsePtr responder, const LLSD& context,
- const LLSD& input) const override
- {
- LLHost host(input["sender"].asString());
- LLViewerRegion* region = gWorld.getRegion(host);
- if (!region)
- {
- return;
- }
- S32 target_index = input["body"]["Index"][0]["Prey"].asInteger();
- S32 you_index = input["body"]["Index"][0]["You" ].asInteger();
- std::vector<U32>* avatar_locs = ®ion->mMapAvatars;
- uuid_vec_t* avatar_ids = ®ion->mMapAvatarIDs;
- avatar_locs->clear();
- avatar_ids->clear();
- LLSD locs = input["body"]["Location"];
- LLSD agents = input["body"]["AgentData"];
- LLSD::array_iterator locs_it = locs.beginArray();
- LLSD::array_iterator locs_end = locs.endArray();
- LLSD::array_iterator agents_it = agents.beginArray();
- bool has_agent_data = input["body"].has("AgentData");
- // Variable region size support
- F64 scale_factor = (F64)region->getWidth() / REGION_WIDTH_METERS;
- for (S32 i = 0; locs_it != locs_end; ++i, ++locs_it)
- {
- U8 x = locs_it->get("X").asInteger();
- U8 y = locs_it->get("Y").asInteger();
- U8 z = locs_it->get("Z").asInteger();
- // treat the target specially for the map, and don't add you or the
- // target
- if (i == target_index)
- {
- LLVector3d global_pos(region->getOriginGlobal());
- global_pos.mdV[VX] += (F64)x * scale_factor;
- global_pos.mdV[VY] += (F64)y * scale_factor;
- global_pos.mdV[VZ] += (F64)z * 4.0;
- gAvatarTracker.setTrackedCoarseLocation(global_pos);
- }
- else if (i != you_index)
- {
- U32 pos = 0x0;
- pos |= x;
- pos <<= 8;
- pos |= y;
- pos <<= 8;
- pos |= z;
- avatar_locs->push_back(pos);
- if (has_agent_data)
- {
- // For backwards compatibility with old message format
- avatar_ids->emplace_back(agents_it->get("AgentID").asUUID());
- }
- }
- if (has_agent_data)
- {
- ++agents_it;
- }
- }
- }
- };
- // build the coarse location HTTP node under the "/message" URL
- LLHTTPRegistration<CoarseLocationUpdate>
- gHTTPRegistrationCoarseLocationUpdate("/message/CoarseLocationUpdate");
- // the deprecated coarse location handler
- void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg)
- {
- mMapAvatars.clear();
- mMapAvatarIDs.clear();
- U8 x_pos = 0;
- U8 y_pos = 0;
- U8 z_pos = 0;
- U32 pos = 0x0;
- S16 agent_index;
- S16 target_index;
- msg->getS16Fast(_PREHASH_Index, _PREHASH_You, agent_index);
- msg->getS16Fast(_PREHASH_Index, _PREHASH_Prey, target_index);
- // Variable region size support
- F64 scale_factor = (F64)mWidth / REGION_WIDTH_METERS;
- bool has_agent_data = msg->has(_PREHASH_AgentData);
- S32 count = msg->getNumberOfBlocksFast(_PREHASH_Location);
- LLUUID agent_id;
- for (S32 i = 0; i < count; ++i)
- {
- msg->getU8Fast(_PREHASH_Location, _PREHASH_X, x_pos, i);
- msg->getU8Fast(_PREHASH_Location, _PREHASH_Y, y_pos, i);
- msg->getU8Fast(_PREHASH_Location, _PREHASH_Z, z_pos, i);
- agent_id.setNull();
- if (has_agent_data)
- {
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID,
- agent_id, i);
- }
- // Treat the target specially for the map
- if (i == target_index)
- {
- LLVector3d global_pos(mOriginGlobal);
- global_pos.mdV[VX] += (F64)x_pos * scale_factor;
- global_pos.mdV[VY] += (F64)y_pos * scale_factor;
- global_pos.mdV[VZ] += (F64)z_pos * 4.0;
- gAvatarTracker.setTrackedCoarseLocation(global_pos);
- }
- // Do not add self
- if (i != agent_index)
- {
- pos = 0x0;
- pos |= x_pos;
- pos <<= 8;
- pos |= y_pos;
- pos <<= 8;
- pos |= z_pos;
- mMapAvatars.push_back(pos);
- if (has_agent_data)
- {
- mMapAvatarIDs.emplace_back(agent_id);
- }
- else
- {
- // Maintain strict coherency in indices bewteen the mMapAvatars
- // and mMapAvatarIDs vectors, else things could get messy in
- // LLWorld::getAvatars()... HB
- mMapAvatarIDs.emplace_back(LLUUID::null);
- }
- }
- }
- }
- void LLViewerRegion::getInfo(LLSD& info)
- {
- info["Region"]["Host"] = mHost.getIPandPort();
- info["Region"]["Name"] = mName;
- U32 x, y;
- from_region_handle(getHandle(), &x, &y);
- info["Region"]["Handle"]["x"] = (LLSD::Integer)x;
- info["Region"]["Handle"]["y"] = (LLSD::Integer)y;
- }
- //static
- void LLViewerRegion::requestBaseCapabilitiesCoro(U64 region_handle)
- {
- LLViewerRegion* self = gWorld.getRegionFromHandle(region_handle);
- if (!self)
- {
- // Region was since disconnected. Ignore and abort.
- return;
- }
- LLCoreHttpUtil::HttpCoroutineAdapter adapter("BaseCapabilitiesRequest");
- LLSD result;
- // This loop is used for retrying a capabilities request.
- do
- {
- const std::string& url = self->getCapability("Seed");
- if (url.empty())
- {
- llwarns << "No Seed capability for region: "
- << self->getIdentity() << ". Aborted." << llendl;
- self->setCapabilitiesError();
- break;
- }
- EStartupState state = LLStartUp::getStartupState();
- if (state < STATE_WORLD_INIT)
- {
- llinfos << "Aborting capabilities request, reason: returned to login screen"
- << llendl;
- break;
- }
- if (++self->mSeedCapAttempts > MAX_CAP_REQUEST_ATTEMPTS)
- {
- // *TODO: Give a user pop-up about this error ?
- llwarns << "Failed to get seed capability from '" << url
- << "' after " << self->mSeedCapAttempts
- << " attempts, for region: " << self->getIdentity()
- << ". Giving up !" << llendl;
- self->setCapabilitiesError();
- break;
- }
- U32 id = ++self->mHttpResponderID;
- LLSD cap_names = LLSD::emptyArray();
- buildCapabilityNames(cap_names);
- llinfos << "Attempt #" << self->mSeedCapAttempts
- << " at requesting seed for region " << self->getIdentity()
- << " from: " << url << llendl;
- result = adapter.postAndSuspend(url, cap_names, sHttpOptions,
- sHttpHeaders);
- state = LLStartUp::getStartupState();
- if (state < STATE_WORLD_INIT)
- {
- llinfos << "Aborting capabilities request, reason: returned to login screen"
- << llendl;
- break;
- }
- // Abort now if we are quitting
- if (LLApp::isExiting() || gDisconnected)
- {
- break;
- }
- self = gWorld.getRegionFromHandle(region_handle);
- if (!self)
- {
- llwarns << "Received a capability response for a disconnected region. Ignored."
- << llendl;
- break;
- }
- if (id != self->mHttpResponderID)
- {
- llwarns << "Received a staled capability response. Ignored."
- << llendl;
- continue;
- }
- if (!result.isMap() || result.has("error"))
- {
- llwarns << "Malformed response. Ignored." << llendl;
- continue;
- }
- LLCore::HttpStatus status =
- LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
- if (!status)
- {
- llwarns << "HTTP error fetching capabilities for region: "
- << self->getIdentity() << ". Will retry..."
- << llendl;
- continue;
- }
- // Remove the http_result from the llsd
- result.erase("http_result");
- for (LLSD::map_const_iterator iter = result.beginMap(),
- end = result.endMap();
- iter != end; ++iter)
- {
- self->setCapability(iter->first, iter->second);
- LL_DEBUGS("Capabilities") << "Got capability '" << iter->first
- << "' for region: "
- << self->getIdentity() << LL_ENDL;
- }
- self->setCapabilitiesReceived(true);
- break;
- }
- while (true);
- }
- //static
- void LLViewerRegion::requestBaseCapabilitiesCompleteCoro(U64 region_handle)
- {
- LLViewerRegion* self = gWorld.getRegionFromHandle(region_handle);
- if (!self)
- {
- // Region was since disconnected. Ignore and abort.
- return;
- }
- const std::string& url = self->getCapability("Seed");
- if (url.empty())
- {
- llwarns << "No 'Seed' capability for region: " << self->getIdentity()
- << ". Aborted." << llendl;
- // Note: initial attempt failed to get this cap as well...
- self->setCapabilitiesError();
- return;
- }
- LLSD cap_names = LLSD::emptyArray();
- buildCapabilityNames(cap_names);
- llinfos << "Requesting second 'Seed' capability for region "
- << self->getIdentity() << " from: " << url << llendl;
- LLCoreHttpUtil::HttpCoroutineAdapter adapter("BaseCapabilitiesRequest");
- LLSD result = adapter.postAndSuspend(url, cap_names, sHttpOptions,
- sHttpHeaders);
- // Abort now if we are quitting
- if (LLApp::isExiting() || gDisconnected)
- {
- return;
- }
- self = gWorld.getRegionFromHandle(region_handle);
- if (!self)
- {
- llwarns << "Received a capability response for a disconnected region. Ignored."
- << llendl;
- return;
- }
- LLCore::HttpStatus status =
- LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
- if (!status)
- {
- llwarns << "HTTP error fetching second capabilities for region: "
- << self->getIdentity() << llendl;
- return;
- }
- // Remove the http_result from the LLSD
- result.erase("http_result");
- bool set_cap = gSavedSettings.getBool("RegisterChangedCaps");
- U32 old_count = (U32)self->getCapabilitiesCount();
- U32 count = 0;
- std::string new_caps_list;
- std::string changed_caps_list;
- for (LLSD::map_const_iterator iter = result.beginMap(),
- end = result.endMap();
- iter != end; ++iter)
- {
- const std::string name = iter->first;
- const std::string url = iter->second;
- if (self->isSpecialCapabilityName(name))
- {
- // Do not count special capabilities that are not kept in the map.
- LL_DEBUGS("Capabilities") << "Got special capability: " << name
- << " - " << url << LL_ENDL;
- continue;
- }
- const std::string& old_url = self->getCapability(name.c_str());
- if (old_url.empty())
- {
- if (!new_caps_list.empty())
- {
- new_caps_list += ", ";
- }
- new_caps_list += name;
- if (set_cap)
- {
- self->setCapability(name, url);
- }
- LL_DEBUGS("Capabilities") << "New capability '" << name
- << "' - URL: " << url << LL_ENDL;
- }
- else if (old_url != url)
- {
- if (!changed_caps_list.empty())
- {
- changed_caps_list += ", ";
- }
- changed_caps_list += name;
- if (set_cap)
- {
- self->setCapability(name, url);
- }
- LL_DEBUGS("Capabilities") << "Changed capability '" << name
- << "' - Old URL: " << old_url
- << " - New URL: " << url << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("Capabilities") << "Got duplicate capability (same url): "
- << name << LL_ENDL;
- }
- ++count;
- }
- self->onCapabilitiesReceived();
- if (!new_caps_list.empty())
- {
- if (set_cap)
- {
- llinfos << "Simulator " << self->getIdentity()
- << " sent the following new capabilities: "
- << new_caps_list << llendl;
- }
- else
- {
- llwarns_once << "Simulator " << self->getIdentity()
- << " sent the following new capabilities: "
- << new_caps_list << ". Ignoring." << llendl;
- }
- }
- if (!changed_caps_list.empty())
- {
- if (set_cap)
- {
- llinfos << "Simulator " << self->getIdentity()
- << " sent new URLs for capabilities: "
- << changed_caps_list << llendl;
- }
- else
- {
- llwarns_once << "Simulator " << self->getIdentity()
- << " sent new URLs for capabilities: "
- << changed_caps_list << ". Ignoring." << llendl;
- }
- }
- if (count != old_count + (U32)new_caps_list.size())
- {
- // There are some capabilities missing in the new set (which seems
- // to be a very common occurrence, thus the LL_DEBUGS instead of a
- // llwarns).
- LL_DEBUGS("Capabilities") << "Simulator " << self->getIdentity()
- << " sent a new, smaller set of capabilities."
- << LL_ENDL;
- }
- }
- //static
- void LLViewerRegion::requestSimulatorFeatureCoro(std::string url,
- U64 region_handle)
- {
- LLViewerRegion* self = gWorld.getRegionFromHandle(region_handle);
- if (!self)
- {
- // Region was since disconnected. Ignore and abort.
- return;
- }
- LLCoreHttpUtil::HttpCoroutineAdapter adapter("SimFeatureRequest");
- U32 attempt = 0;
- LLSD result;
- // This loop is used for retrying a capabilities request.
- do
- {
- if (++attempt > MAX_CAP_REQUEST_ATTEMPTS)
- {
- llwarns << "Retries count exceeded attempting to get simulator feature for region "
- << self->getIdentity() << " from: " << url << llendl;
- break;
- }
- result = adapter.getAndSuspend(url, sHttpOptions, sHttpHeaders);
- // Abort now if we are quitting
- if (LLApp::isExiting() || gDisconnected)
- {
- break;
- }
- self = gWorld.getRegionFromHandle(region_handle);
- if (!self)
- {
- // Region was since disconnected. Ignore and abort.
- llwarns << "Received a simulator feature for a disconnected region. Ignored."
- << llendl;
- break;
- }
- LLCore::HttpStatus status =
- LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
- if (!status)
- {
- llwarns << "HTTP error fetching simulator feature for region: "
- << self->getIdentity() << ". Will retry..." << llendl;
- continue;
- }
- // Remove the http_result from the LLSD
- result.erase("http_result");
- self->setSimulatorFeatures(result);
- break;
- }
- while (true);
- }
- void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
- {
- llinfos << "Received simulator features for region: " << getIdentity()
- << llendl;
- LL_DEBUGS("SimulatorFeatures") << "\n";
- std::stringstream str;
- LLSDSerialize::toPrettyXML(sim_features, str);
- LL_CONT << str.str() << LL_ENDL;
- mSimulatorFeatures = sim_features;
- mFeaturesReceived = true;
- if (mSimulatorFeatures.has("HostName"))
- {
- mHostName = mSimulatorFeatures["HostName"].asString();
- if (!gIsInSecondLife &&
- // AWS server reporting the alias for SL sim hostname. HB
- mHostName.find("secondlife.io") != std::string::npos)
- {
- llwarns << "Second Life sim detected while supposedly logged in OpenSim !"
- << llendl;
- gIsInSecondLife = true,
- gIsInSecondLifeBetaGrid =
- mHostName.find("aditi") != std::string::npos;
- gIsInProductionGrid = gIsInSecondLifeProductionGrid =
- !gIsInSecondLifeBetaGrid;
- if (gViewerWindowp)
- {
- gViewerWindowp->setMenuBackgroundColor();
- }
- llinfos << "Switched to Second Life mode/policy." << llendl;
- }
- }
- // Cache physics shape types availability flag. HB
- mPhysicsShapeTypes = mSimulatorFeatures.has("PhysicsShapeTypes");
- LL_DEBUGS("SimulatorFeatures") << "Physics shape types"
- << (mPhysicsShapeTypes ? " " : " not ")
- << "supported"
- << LL_ENDL;
- // Avatar Hover Height support. HB
- mHoverHeigthFeature = !getCapability("AgentPreferences").empty() &&
- mSimulatorFeatures.has("AvatarHoverHeightEnabled") &&
- mSimulatorFeatures["AvatarHoverHeightEnabled"].asBoolean();
- // Cache mesh support data. HB
- mMeshRezEnabled = mSimulatorFeatures.has("MeshRezEnabled") &&
- mSimulatorFeatures["MeshRezEnabled"].asBoolean();
- mMeshUploadEnabled = mSimulatorFeatures.has("MeshUploadEnabled") &&
- mSimulatorFeatures["MeshUploadEnabled"].asBoolean();
- LL_DEBUGS("SimulatorFeatures") << "Mesh rezzing "
- << (mMeshRezEnabled ? "enabled"
- : " disabled")
- << " - Mesh upload "
- << (mMeshUploadEnabled ? "enabled"
- : " disabled")
- << LL_ENDL;
- // Materials-related features. HB
- if (mSimulatorFeatures.has("MaxMaterialsPerTransaction") &&
- mSimulatorFeatures["MaxMaterialsPerTransaction"].isInteger())
- {
- mMaxMaterialsPerTransaction =
- mSimulatorFeatures["MaxMaterialsPerTransaction"].asInteger();
- }
- else
- {
- LL_DEBUGS("Materials") << "Region " << getIdentity()
- << " did not return MaxMaterialsPerTransaction, using default: 50"
- << LL_ENDL;
- }
- if (mSimulatorFeatures.has("RenderMaterialsCapability") &&
- mSimulatorFeatures["RenderMaterialsCapability"].isReal())
- {
- F32 value = mSimulatorFeatures["RenderMaterialsCapability"].asReal();
- if (value > 0.f)
- {
- mRenderMaterialsCapability = 1.f / value;
- LL_DEBUGS("Materials") << "Region " << getIdentity()
- << " RenderMaterialsCapability = " << value
- << " req/s." << LL_ENDL;
- }
- else
- {
- llwarns << "Region " << getIdentity()
- << " returned invalid RenderMaterialsCapability; using default (1 request/s)."
- << llendl;
- }
- }
- else
- {
- LL_DEBUGS("Materials") << "Region " << getIdentity()
- << " did not return RenderMaterialsCapability, using default (1 request/s)."
- << LL_ENDL;
- }
- // Mega-textures support.
- if (mSimulatorFeatures.has("MaxTextureResolution"))
- {
- mMaxTextureSize =
- llclamp(mSimulatorFeatures["MaxTextureResolution"].asInteger(),
- // Make sure we stay within our limits. HB
- 1024, MAX_IMAGE_SIZE / 2);
- if (mMaxTextureSize > gMaxImageSizeDefault)
- {
- llinfos << "Detected a larger image size limit for region "
- << getIdentity() << " (" << mMaxTextureSize << " vs "
- << gMaxImageSizeDefault
- << "): adopting it as the new limit." << llendl;
- gMaxImageSizeDefault = mMaxTextureSize;
- update_upload_costs_in_menus();
- }
- }
- // PBR terrain support
- if (mSimulatorFeatures.has("GLTFEnabled"))
- {
- mGLTFEnabled = true;
- }
- if (mGLTFEnabled || mSimulatorFeatures.has("PBRTerrainEnabled"))
- {
- mHasPBRTerrain = true;
- }
- // Cache path finding support data. HB
- mDynamicPathfinding = mSimulatorFeatures.has("DynamicPathfindingEnabled");
- mDynamicPathfindingEnabled = mDynamicPathfinding &&
- mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean();
- LL_DEBUGS("SimulatorFeatures") << "Dynamic pathfinding "
- << (mDynamicPathfinding ?
- (mDynamicPathfindingEnabled ? "enabled"
- : " disabled")
- : " not supported")
- << LL_ENDL;
- mBakesOnMeshEnabled = mSimulatorFeatures.has("BakesOnMeshEnabled") &&
- mSimulatorFeatures["BakesOnMeshEnabled"].asBoolean();
- if (gAgent.getRegion() == this)
- {
- gAgent.setUploadedBakesLimit();
- }
- LL_DEBUGS("SimulatorFeatures") << "Bake on mesh "
- << (mBakesOnMeshEnabled ? "enabled"
- : "disabled")
- << LL_ENDL;
- // We will not erase URLs passed on login (see below)...
- // This poses a problem for cross-grid TPs, when the arrival grid does not
- // provide the URLs for the corresponding services via the simulator
- // features and the departure grid did provide them via the login.cgi
- // script (and not via the simulator features either), but it is still
- // better than not erasing the sim-provided URLs when the arrival grid
- // does not provide the same services... HB
- // *TODO: detect cross-grid TPs and erase the URLs only when they occur...
- bool got_map_url = LLWorldMap::wasMapURLSetOnLogin();
- bool got_search_url = HBFloaterSearch::wasSearchURLSetOnLogin();
- // Cache OpenSim specific data. HB
- // See: http://opensimulator.org/wiki/SimulatorFeatures_Extras
- if (mSimulatorFeatures.has("OpenSimExtras"))
- {
- if (gIsInSecondLife)
- {
- llwarns << "OpenSim features detected while supposedly logged in Second Life !"
- << llendl;
- gIsInSecondLife = false,
- gIsInProductionGrid = true;
- gIsInSecondLifeBetaGrid = gIsInSecondLifeProductionGrid = false;
- if (gViewerWindowp)
- {
- gViewerWindowp->setMenuBackgroundColor();
- }
- llinfos << "Switched to OpenSim mode/policy." << llendl;
- }
- const LLSD& extras = mSimulatorFeatures["OpenSimExtras"];
- // Export permission support
- bool old_value = mOSExportPermSupported;
- mOSExportPermSupported = extras.has("ExportSupported") &&
- extras["ExportSupported"].asBoolean();
- if (mOSExportPermSupported != old_value)
- {
- dialog_refresh_all();
- }
- if (extras.has("map-server-url"))
- {
- LLWorldMap::gotMapServerURL(true);
- LLWorldMap::setMapServerURL(extras["map-server-url"].asString());
- LL_DEBUGS("SimulatorFeatures") << "Map server URL set to: "
- << extras["map-server-url"].asString()
- << LL_ENDL;
- got_map_url = true;
- }
- if (extras.has("search-server-url"))
- {
- std::string url = extras["search-server-url"].asString();
- HBFloaterSearch::setSearchURL(url);
- LL_DEBUGS("SimulatorFeatures") << "Search URL: " << url << LL_ENDL;
- got_search_url = true;
- }
- // Whisper/chat/shout ranges: seen in OS Grid...
- if (extras.has("whisper-range"))
- {
- mWhisperRange = (U32)extras["whisper-range"].asInteger();
- LL_DEBUGS("SimulatorFeatures") << "Whisper range: "
- << mWhisperRange << "m"
- << LL_ENDL;
- }
- if (extras.has("say-range"))
- {
- mChatRange = (U32)extras["say-range"].asInteger();
- gAgent.setNearChatRadius((F32)mChatRange * 0.5f);
- LL_DEBUGS("SimulatorFeatures") << "Chat range: " << mChatRange
- << "m" << LL_ENDL;
- }
- if (extras.has("shout-range"))
- {
- mShoutRange = (U32)extras["shout-range"].asInteger();
- LL_DEBUGS("SimulatorFeatures") << "Shout range: " << mShoutRange
- << "m" << LL_ENDL;
- }
- }
- if (mSimulatorFeatures.has("GridServices"))
- {
- const LLSD& services = mSimulatorFeatures["GridServices"];
- // Seen in Speculoos...
- if (services.has("search"))
- {
- std::string url = services["search"].asString();
- HBFloaterSearch::setSearchURL(url);
- LL_DEBUGS("SimulatorFeatures") << "Search URL: " << url << LL_ENDL;
- got_search_url = true;
- }
- }
- // When in OpenSim, erase the map and search URLs if not found in sim
- // features and not set at login time (see above). HB
- // *TODO: detect cross-grid TPs and erase the URLs only when they occur...
- if (!gIsInSecondLife)
- {
- if (!got_map_url)
- {
- LLWorldMap::gotMapServerURL(false);
- }
- if (!got_search_url)
- {
- HBFloaterSearch::setSearchURL("");
- }
- }
- mFeaturesReceivedSignal(getRegionID());
- // This is a single-shot signal. Forget callbacks to save resources.
- mFeaturesReceivedSignal.disconnect_all_slots();
- }
- boost::signals2::connection LLViewerRegion::setFeaturesReceivedCB(const caps_received_cb_t& cb)
- {
- return mFeaturesReceivedSignal.connect(cb);
- }
- // This is called when the parent is not cacheable. Moves all orphan children
- // out of the cache and inserts them into the rendering octree.
- void LLViewerRegion::findOrphans(U32 parent_id)
- {
- orphan_list_t::iterator iter = mOrphanMap.find(parent_id);
- if (iter != mOrphanMap.end())
- {
- std::vector<U32>* children = &mOrphanMap[parent_id];
- for (S32 i = 0, count = children->size(); i < count; ++i)
- {
- // Parent is visible, so is the child.
- addVisibleChildCacheEntry(NULL, getCacheEntry((*children)[i]));
- }
- children->clear();
- mOrphanMap.erase(parent_id);
- }
- }
- void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry)
- {
- if (!sVOCacheCullingEnabled)
- {
- gObjectList.processObjectUpdateFromCache(entry, this);
- return;
- }
- if (!entry || !entry->isValid())
- {
- return;
- }
- if (!entry->getEntry())
- {
- entry->setOctreeEntry(NULL);
- }
- if (!entry->getDP())
- {
- return;
- }
- if (entry->getEntry()->hasDrawable())
- {
- // Already in the rendering pipeline
- LLDrawable* drawablep = (LLDrawable*)entry->getEntry()->getDrawable();
- if (drawablep)
- {
- LLViewerRegion* old_regionp = drawablep->getRegion();
- if (old_regionp != this)
- {
- LLViewerObject* objp = drawablep->getVObj();
- if (objp)
- {
- // Remove from old region
- if (old_regionp)
- {
- old_regionp->killCacheEntry(objp->getLocalID());
- }
- // Change region
- objp->setRegion(this);
- }
- }
- }
- addActiveCacheEntry(entry);
- // Set parent id
- U32 parent_id = 0;
- LLViewerObject::unpackParentID(entry->getDP(), parent_id);
- if (parent_id != entry->getParentID())
- {
- entry->setParentID(parent_id);
- }
- // Update the object
- gObjectList.processObjectUpdateFromCache(entry, this);
- return; // done
- }
- // Must not be active.
- llassert_always(!entry->isState(LLVOCacheEntry::ACTIVE));
- removeFromVOCacheTree(entry); // remove from cache octree if it is in.
- LLVector3 pos, scale;
- LLQuaternion rot;
- // Decode spatial info and parent info
- U32 parent_id = LLViewerObject::extractSpatialExtents(entry->getDP(),
- pos, scale, rot);
- U32 old_parent_id = entry->getParentID();
- bool same_old_parent = parent_id == old_parent_id;
- if (!same_old_parent) // Parent changed.
- {
- if (old_parent_id > 0) // Has an old parent, disconnect it
- {
- LLVOCacheEntry* old_parent = getCacheEntry(old_parent_id);
- if (old_parent)
- {
- old_parent->removeChild(entry);
- if (!old_parent->isState(LLVOCacheEntry::INACTIVE))
- {
- mVisibleEntries.erase(entry);
- entry->setState(LLVOCacheEntry::INACTIVE);
- }
- }
- }
- entry->setParentID(parent_id);
- }
- if (parent_id > 0) // Got a new parent
- {
- // 1.- Find the parent in cache
- LLVOCacheEntry* parent = getCacheEntry(parent_id);
- // 2.- Parent is not in the cache, put into the orphan list.
- if (!parent)
- {
- if (!same_old_parent)
- {
- // Check if parent is non-cacheable and already created
- if (isNonCacheableObjectCreated(parent_id))
- {
- // Parent is visible, so is the child.
- addVisibleChildCacheEntry(NULL, entry);
- }
- else
- {
- entry->setBoundingInfo(pos, scale);
- mOrphanMap[parent_id].push_back(entry->getLocalID());
- }
- }
- else
- {
- entry->setBoundingInfo(pos, scale);
- }
- }
- // Not in cache.
- else if (!parent->isState(LLVOCacheEntry::INACTIVE))
- {
- // Parent is visible, so is the child.
- addVisibleChildCacheEntry(parent, entry);
- }
- else
- {
- entry->setBoundingInfo(pos, scale);
- parent->addChild(entry);
- if (parent->getGroup())
- {
- // Re-insert parent to vo-cache tree because its bounding info
- // changed.
- removeFromVOCacheTree(parent);
- addToVOCacheTree(parent);
- }
- }
- return;
- }
- //
- // No parent
- //
- entry->setBoundingInfo(pos, scale);
- if (!parent_id) // a potential parent
- {
- // Find all children and update their bounding info
- orphan_list_t::iterator iter = mOrphanMap.find(entry->getLocalID());
- if (iter != mOrphanMap.end())
- {
- std::vector<U32>* orphans = &mOrphanMap[entry->getLocalID()];
- for (S32 i = 0, count = orphans->size(); i < count; ++i)
- {
- LLVOCacheEntry* child = getCacheEntry((*orphans)[i]);
- if (child)
- {
- entry->addChild(child);
- }
- }
- orphans->clear();
- mOrphanMap.erase(entry->getLocalID());
- }
- }
- if (!entry->getGroup() && entry->isState(LLVOCacheEntry::INACTIVE))
- {
- addToVOCacheTree(entry);
- }
- }
- LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerBinaryBuffer& dp,
- U32 flags)
- {
- eCacheUpdateResult result;
- U32 crc, local_id;
- LLViewerObject::unpackU32(&dp, local_id, "LocalID");
- LLViewerObject::unpackU32(&dp, crc, "CRC");
- LLVOCacheEntry* entry = getCacheEntry(local_id, false);
- if (entry)
- {
- entry->setValid();
- // We have seen this object before
- if (entry->getCRC() == crc)
- {
- // Record a hit
- entry->recordDupe();
- result = CACHE_UPDATE_DUPE;
- }
- else // CRC changed
- {
- // Update the cache entry
- entry->updateEntry(crc, dp);
- decodeBoundingInfo(entry);
- result = CACHE_UPDATE_CHANGED;
- }
- }
- else
- {
- // We have not seen this object before; create new entry and add to map
- LLPointer<LLVOCacheEntry> new_entry = new LLVOCacheEntry(local_id, crc,
- dp);
- mCacheMap[local_id] = new_entry;
- decodeBoundingInfo(new_entry);
- entry = new_entry;
- result = CACHE_UPDATE_ADDED;
- }
- if (flags != 0xffffffff)
- {
- entry->setUpdateFlags(flags);
- LLUUID fullid;
- gObjectList.getUUIDFromLocal(fullid, local_id,
- gMessageSystemp->getSenderIP(),
- gMessageSystemp->getSenderPort());
- if (fullid.notNull())
- {
- LL_DEBUGS("ObjectCacheSpam") << "Set cache entry flags for object "
- << fullid << " to: " << flags
- << LL_ENDL;
- // We MUST also update the corresponding object when it exists ! HB
- LLViewerObject* objectp = gObjectList.findObject(fullid);
- if (objectp)
- {
- objectp->loadFlags(flags);
- }
- }
- }
- return result;
- }
- void LLViewerRegion::cacheFullUpdateGLTFOverride(const LLGLTFOverrideCacheEntry& data)
- {
- mGLTFOverrides[data.mLocalId] = data;
- }
- LLVOCacheEntry* LLViewerRegion::getCacheEntryForOctree(U32 local_id)
- {
- if (!sVOCacheCullingEnabled)
- {
- return NULL;
- }
- LLVOCacheEntry* entryp = getCacheEntry(local_id);
- removeFromVOCacheTree(entryp);
- return entryp;
- }
- LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id, bool valid)
- {
- LLVOCacheEntry::map_t::iterator iter = mCacheMap.find(local_id);
- if (iter != mCacheMap.end() && (!valid || iter->second->isValid()))
- {
- return iter->second;
- }
- return NULL;
- }
- void LLViewerRegion::addCacheMiss(U32 id,
- LLViewerRegion::eCacheMissType miss_type)
- {
- #if 0
- mCacheMissList[id] = miss_type;
- #else
- mCacheMissList.emplace_back(id, miss_type);
- #endif
- }
- // Checks if a non-cacheable object is already created.
- bool LLViewerRegion::isNonCacheableObjectCreated(U32 local_id)
- {
- return local_id > 0 && mNonCacheableCreatedList.count(local_id) != 0;
- }
- void LLViewerRegion::removeFromCreatedList(U32 local_id)
- {
- if (local_id > 0)
- {
- non_cacheable_list_t::iterator iter =
- mNonCacheableCreatedList.find(local_id);
- if (iter != mNonCacheableCreatedList.end())
- {
- mNonCacheableCreatedList.hset_erase(iter);
- }
- }
- }
- void LLViewerRegion::addToCreatedList(U32 local_id)
- {
- if (local_id > 0)
- {
- mNonCacheableCreatedList.insert(local_id);
- }
- }
- // Get data packer for this object, if we have cached data AND the CRC matches.
- bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags,
- U8& cache_miss_type)
- {
- LLVOCacheEntry* entryp = getCacheEntry(local_id, false);
- if (!entryp)
- {
- addCacheMiss(local_id, CACHE_MISS_TYPE_FULL);
- return false;
- }
- if (entryp->getCRC() != crc)
- {
- addCacheMiss(local_id, CACHE_MISS_TYPE_CRC);
- return false;
- }
- cache_miss_type = CACHE_MISS_TYPE_NONE;
- // We have seen this object before; record a hit.
- entryp->recordHit();
- if (flags != 0xffffffff)
- {
- LL_DEBUGS("ObjectCacheSpam") << "Setting cache entry flags for object ";
- LLUUID fullid;
- gObjectList.getUUIDFromLocal(fullid, local_id,
- gMessageSystemp->getSenderIP(),
- gMessageSystemp->getSenderPort());
- if (fullid.notNull())
- {
- LL_CONT << fullid;
- }
- else
- {
- LL_CONT << " with local Id/from server " << local_id << "/"
- << gMessageSystemp->getSender();
- }
- LL_CONT << " to: 0x" << std::hex << flags << std::dec << LL_ENDL;
- }
- entryp->setUpdateFlags(flags);
- if (entryp->isState(LLVOCacheEntry::ACTIVE))
- {
- LLDrawable* drawablep = (LLDrawable*)entryp->getEntry()->getDrawable();
- if (drawablep)
- {
- LLViewerObject* objp = drawablep->getVObj();
- if (objp)
- {
- objp->loadFlags(flags);
- }
- }
- }
- else if (!entryp->isValid()) // If not already probed
- {
- entryp->setValid();
- decodeBoundingInfo(entryp);
- }
- return true;
- }
- void LLViewerRegion::addCacheMissFull(U32 local_id)
- {
- addCacheMiss(local_id, CACHE_MISS_TYPE_FULL);
- }
- void LLViewerRegion::requestCacheMisses()
- {
- if (mCacheMissList.empty())
- {
- return;
- }
- LLMessageSystem* msg = gMessageSystemp;
- bool start_new_message = true;
- S32 blocks = 0;
- // Send requests for all cache-missed objects
- for (CacheMissItem::cache_miss_list_t::iterator
- iter = mCacheMissList.begin(), end = mCacheMissList.end();
- iter != end; ++iter)
- {
- if (start_new_message)
- {
- msg->newMessageFast(_PREHASH_RequestMultipleObjects);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
- msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
- start_new_message = false;
- }
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU8Fast(_PREHASH_CacheMissType, iter->mType);
- msg->addU32Fast(_PREHASH_ID, iter->mID);
- if (++blocks >= 255)
- {
- sendReliableMessage();
- start_new_message = true;
- blocks = 0;
- }
- }
- // Finish any pending message
- if (!start_new_message)
- {
- sendReliableMessage();
- }
- mCacheDirty = true;
- mCacheMissList.clear();
- }
- void LLViewerRegion::dumpCache()
- {
- constexpr S32 BINS = 4;
- S32 hit_bin[BINS];
- S32 change_bin[BINS];
- for (S32 i = 0; i < BINS; ++i)
- {
- hit_bin[i] = 0;
- change_bin[i] = 0;
- }
- for (LLVOCacheEntry::map_t::iterator iter = mCacheMap.begin(),
- end = mCacheMap.end();
- iter != end; ++iter)
- {
- LLVOCacheEntry* entry = iter->second;
- S32 hits = entry->getHitCount();
- S32 changes = entry->getCRCChangeCount();
- hits = llclamp(hits, 0, BINS - 1);
- changes = llclamp(changes, 0, BINS - 1);
- ++hit_bin[hits];
- ++change_bin[changes];
- }
- llinfos << "Count " << mCacheMap.size() << llendl;
- for (S32 i = 0; i < BINS; ++i)
- {
- llinfos << "Hits " << i << " " << hit_bin[i] << llendl;
- }
- for (S32 i = 0; i < BINS; ++i)
- {
- llinfos << "Changes " << i << " " << change_bin[i] << llendl;
- }
- }
- void LLViewerRegion::unpackRegionHandshake()
- {
- LLMessageSystem* msg = gMessageSystemp;
- U8 sim_access;
- msg->getU8(_PREHASH_RegionInfo, _PREHASH_SimAccess, sim_access);
- std::string sim_name;
- msg->getString(_PREHASH_RegionInfo, _PREHASH_SimName, sim_name);
- LLUUID sim_owner;
- msg->getUUID(_PREHASH_RegionInfo, _PREHASH_SimOwner, sim_owner);
- bool manager;
- msg->getBool(_PREHASH_RegionInfo, _PREHASH_IsEstateManager, manager);
- F32 water_height;
- msg->getF32(_PREHASH_RegionInfo, _PREHASH_WaterHeight, water_height);
- F32 billable_factor;
- msg->getF32(_PREHASH_RegionInfo, _PREHASH_BillableFactor, billable_factor);
- LLUUID cache_id;
- msg->getUUID(_PREHASH_RegionInfo, _PREHASH_CacheID, cache_id);
- U64 region_flags = 0;
- U64 region_protocols = 0;
- if (msg->has(_PREHASH_RegionInfo4))
- {
- msg->getU64Fast(_PREHASH_RegionInfo4, _PREHASH_RegionFlagsExtended,
- region_flags);
- msg->getU64Fast(_PREHASH_RegionInfo4, _PREHASH_RegionProtocols,
- region_protocols);
- }
- else
- {
- U32 flags = 0;
- msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_RegionFlags, flags);
- region_flags = flags;
- }
- setRegionProtocols(region_protocols);
- setRegionFlags(region_flags);
- setSimAccess(sim_access);
- setRegionNameAndZone(sim_name);
- setOwner(sim_owner);
- setIsEstateManager(manager);
- setWaterHeight(water_height);
- setBillableFactor(billable_factor);
- setCacheID(cache_id);
- LL_DEBUGS("ObjectCache") << "Got hanshake message for region: " << mName
- << " - Cache Id: " << mCacheID << LL_ENDL;
- LLUUID region_id;
- msg->getUUID(_PREHASH_RegionInfo2, _PREHASH_RegionID, region_id);
- setRegionID(region_id);
- // Retrieve the CR-53 (Homestead/Land SKU) information. The only reasonable
- // way to decide if we actually have any data is to check to see if any of
- // these fields have positive sizes.
- if (msg->getSize(_PREHASH_RegionInfo3, _PREHASH_ColoName) > 0 ||
- msg->getSize(_PREHASH_RegionInfo3, _PREHASH_ProductSKU) > 0 ||
- msg->getSize(_PREHASH_RegionInfo3, _PREHASH_ProductName) > 0)
- {
- msg->getS32(_PREHASH_RegionInfo3, _PREHASH_CPUClassID, mClassID);
- msg->getS32(_PREHASH_RegionInfo3, _PREHASH_CPURatio, mCPURatio);
- msg->getString(_PREHASH_RegionInfo3, _PREHASH_ColoName, mColoName);
- msg->getString(_PREHASH_RegionInfo3, _PREHASH_ProductSKU, mProductSKU);
- msg->getString(_PREHASH_RegionInfo3, _PREHASH_ProductName,
- mProductName);
- }
- mCentralBakeVersion = region_protocols & 1;
- if (!gIsInSecondLife && !mBakesOnMeshEnabled)
- {
- mBakesOnMeshEnabled = region_protocols & 0x8000000000000000ll;
- }
- // Get the 4 textures for land
- LLUUID tmp_id;
- msg->getUUID(_PREHASH_RegionInfo, _PREHASH_TerrainDetail0, tmp_id);
- bool changed = tmp_id != mCompositionp->getDetailAssetID(0);
- mCompositionp->setDetailAssetID(0, tmp_id);
- msg->getUUID(_PREHASH_RegionInfo, _PREHASH_TerrainDetail1, tmp_id);
- changed |= tmp_id != mCompositionp->getDetailAssetID(1);
- mCompositionp->setDetailAssetID(1, tmp_id);
- msg->getUUID(_PREHASH_RegionInfo, _PREHASH_TerrainDetail2, tmp_id);
- changed |= tmp_id != mCompositionp->getDetailAssetID(2);
- mCompositionp->setDetailAssetID(2, tmp_id);
- msg->getUUID(_PREHASH_RegionInfo, _PREHASH_TerrainDetail3, tmp_id);
- changed |= tmp_id != mCompositionp->getDetailAssetID(3);
- mCompositionp->setDetailAssetID(3, tmp_id);
- // Get the start altitude and range values for land textures
- F32 tmp_f32;
- msg->getF32(_PREHASH_RegionInfo, _PREHASH_TerrainStartHeight00, tmp_f32);
- changed |= tmp_f32 != mCompositionp->getStartHeight(0);
- mCompositionp->setStartHeight(0, tmp_f32);
- msg->getF32(_PREHASH_RegionInfo, _PREHASH_TerrainStartHeight01, tmp_f32);
- changed |= tmp_f32 != mCompositionp->getStartHeight(1);
- mCompositionp->setStartHeight(1, tmp_f32);
- msg->getF32(_PREHASH_RegionInfo, _PREHASH_TerrainStartHeight10, tmp_f32);
- changed |= tmp_f32 != mCompositionp->getStartHeight(2);
- mCompositionp->setStartHeight(2, tmp_f32);
- msg->getF32(_PREHASH_RegionInfo, _PREHASH_TerrainStartHeight11, tmp_f32);
- changed |= tmp_f32 != mCompositionp->getStartHeight(3);
- mCompositionp->setStartHeight(3, tmp_f32);
- msg->getF32(_PREHASH_RegionInfo, _PREHASH_TerrainHeightRange00, tmp_f32);
- changed |= tmp_f32 != mCompositionp->getHeightRange(0);
- mCompositionp->setHeightRange(0, tmp_f32);
- msg->getF32(_PREHASH_RegionInfo, _PREHASH_TerrainHeightRange01, tmp_f32);
- changed |= tmp_f32 != mCompositionp->getHeightRange(1);
- mCompositionp->setHeightRange(1, tmp_f32);
- msg->getF32(_PREHASH_RegionInfo, _PREHASH_TerrainHeightRange10, tmp_f32);
- changed |= tmp_f32 != mCompositionp->getHeightRange(2);
- mCompositionp->setHeightRange(2, tmp_f32);
- msg->getF32(_PREHASH_RegionInfo, _PREHASH_TerrainHeightRange11, tmp_f32);
- changed |= tmp_f32 != mCompositionp->getHeightRange(3);
- mCompositionp->setHeightRange(3, tmp_f32);
- bool was_ready = mCompositionp->getParamsReady();
- if (!was_ready)
- {
- mCompositionp->setParamsReady();
- }
- else if (changed)
- {
- mLandp->dirtyAllPatches();
- }
- // Update if the land changed
- LL_DEBUGS("RegionTexture") << "Region: " << sim_name
- << " - Composition did "
- << (changed ? "" : "not ")
- << "change and parameters were "
- << (was_ready ? "" : "not " ) << "ready."
- << LL_ENDL;
- // Now that we have the name, we can load the cache file off disk.
- loadObjectCache();
- // Reply to the handshake, but not while we already have a threaded cache
- // read in flight. In this latter case, just register a new pending
- // handshake reply until the cache got read. HB
- ++mPendingHandshakes;
- if (!mCacheLoading)
- {
- sendHandshakeReply();
- }
- }
- // *TODO: Send all upstream viewer->sim handshake info here.
- void LLViewerRegion::sendHandshakeReply()
- {
- if (!mPendingHandshakes)
- {
- return;
- }
- --mPendingHandshakes;
- LL_DEBUGS("ObjectCache") << "Sending handshake reply for region: "
- << mName << LL_ENDL;
- LLMessageSystem* msg = gMessageSystemp;
- msg->newMessage(_PREHASH_RegionHandshakeReply);
- msg->nextBlock(_PREHASH_AgentData);
- msg->addUUID(_PREHASH_AgentID, gAgentID);
- msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
- msg->nextBlock(_PREHASH_RegionInfo);
- U32 flags = REGION_HANDSHAKE_SUPPORTS_SELF_APPEARANCE;
- if (sVOCacheCullingEnabled)
- {
- // Set the bit 0 to be 1 to ask sim to send all cacheable objects.
- flags |= 0x00000001;
- }
- if (mCacheMap.empty())
- {
- // Set the bit 1 to be 1 to tell sim the cache file is empty, no need
- // to send cache probes.
- flags |= 0x00000002;
- }
- msg->addU32(_PREHASH_Flags, flags);
- msg->sendReliable(mHost);
- }
- //static
- void LLViewerRegion::buildCapabilityNames(LLSD& cap_names)
- {
- cap_names.append("AbuseCategories");
- cap_names.append("AcceptFriendship");
- cap_names.append("AcceptGroupInvite"); // For use with ReadOfflineMsgs
- cap_names.append("AgentExperiences");
- cap_names.append("AgentPreferences");
- cap_names.append("AgentProfile");
- cap_names.append("AgentState");
- #if 0 // *TODO: implement attachments scripts count ?
- cap_names.append("AttachmentResources");
- #endif
- cap_names.append("AvatarPickerSearch");
- cap_names.append("AvatarRenderInfo");
- cap_names.append("CharacterProperties");
- cap_names.append("ChatSessionRequest");
- cap_names.append("CopyInventoryFromNotecard");
- cap_names.append("CreateInventoryCategory");
- cap_names.append("DeclineFriendship"); // For use with ReadOfflineMsgs
- cap_names.append("DeclineGroupInvite");
- cap_names.append("DirectDelivery");
- cap_names.append("DispatchRegionInfo");
- #if 0 // Windlight region settings (deprecated, not used by this viewer)
- cap_names.append("EnvironmentSettings");
- #endif
- cap_names.append("EstateAccess");
- cap_names.append("EstateChangeInfo");
- cap_names.append("EventQueueGet");
- if (gIsInSecondLife || gSavedSettings.getBool("UseHTTPInventory"))
- {
- cap_names.append("FetchInventory2");
- cap_names.append("FetchInventoryDescendents2");
- cap_names.append("FetchLib2");
- cap_names.append("FetchLibDescendents2");
- cap_names.append("InventoryAPIv3");
- cap_names.append("LibraryAPIv3");
- }
- cap_names.append("ExperiencePreferences");
- cap_names.append("ExperienceQuery");
- cap_names.append("ExtEnvironment");
- cap_names.append("FindExperienceByName");
- cap_names.append("GetAdminExperiences");
- cap_names.append("GetCreatorExperiences");
- cap_names.append("GetExperiences");
- cap_names.append("GetExperienceInfo");
- cap_names.append("GetDisplayNames");
- cap_names.append("GetMesh");
- cap_names.append("GetMesh2");
- cap_names.append("GetMetadata");
- cap_names.append("GetObjectCost");
- cap_names.append("GetObjectPhysicsData");
- cap_names.append("GetTexture");
- cap_names.append("GroupAPIv1");
- cap_names.append("GroupExperiences");
- cap_names.append("GroupMemberData");
- cap_names.append("HomeLocation");
- // For 360° snapshots which are not implemented in this viewer, but we can
- // still request a 360° interest list if wanted, from the Advanced menu. HB
- cap_names.append("InterestList");
- cap_names.append("InventoryThumbnailUpload");
- cap_names.append("IsExperienceAdmin");
- cap_names.append("IsExperienceContributor");
- cap_names.append("MapLayer");
- cap_names.append("MapLayerGod");
- cap_names.append("MeshUploadFlag");
- cap_names.append("ModifyMaterialParams");
- cap_names.append("NavMeshGenerationStatus");
- cap_names.append("NewFileAgentInventory");
- // Requesting this cap triggers the sending of UDP messages for puppets:
- cap_names.append("ObjectAnimation");
- cap_names.append("ObjectMedia");
- cap_names.append("ObjectMediaNavigate");
- cap_names.append("ObjectNavMeshProperties");
- cap_names.append("ParcelNavigateMedia");
- cap_names.append("ParcelPropertiesUpdate");
- cap_names.append("ParcelVoiceInfoRequest");
- cap_names.append("ProductInfoRequest");
- cap_names.append("ProvisionVoiceAccountRequest");
- cap_names.append("Puppetry");
- // Needs AcceptGroupInvite & DeclineGroupInvite:
- cap_names.append("ReadOfflineMsgs");
- cap_names.append("RegionExperiences");
- cap_names.append("RegionObjects"); // Replaces "ObjectNavMeshProperties"
- cap_names.append("RemoteParcelRequest");
- cap_names.append("RenderMaterials");
- cap_names.append("RequestTextureDownload");
- #if 0 // *TODO: implement in llfloaterobjectweights.cpp ?
- cap_names.append("ResourceCostSelected");
- #endif
- cap_names.append("RetrieveNavMeshSrc");
- cap_names.append("SearchStatRequest");
- cap_names.append("SearchStatTracking");
- cap_names.append("SendPostcard");
- cap_names.append("SendUserReport");
- cap_names.append("SendUserReportWithScreenshot");
- cap_names.append("ServerReleaseNotes");
- cap_names.append("SetDisplayName");
- cap_names.append("SimConsole");
- cap_names.append("SimConsoleAsync");
- cap_names.append("SimulatorFeatures");
- cap_names.append("TerrainNavMeshProperties");
- cap_names.append("UntrustedSimulatorMessage");
- cap_names.append("UpdateAgentInformation");
- cap_names.append("UpdateAgentLanguage");
- cap_names.append("UpdateAvatarAppearance");
- cap_names.append("UpdateExperience");
- cap_names.append("UpdateGestureAgentInventory");
- cap_names.append("UpdateGestureTaskInventory");
- cap_names.append("UpdateMaterialAgentInventory");
- cap_names.append("UpdateMaterialTaskInventory");
- cap_names.append("UpdateNotecardAgentInventory");
- cap_names.append("UpdateNotecardTaskInventory");
- cap_names.append("UpdateScriptAgent");
- cap_names.append("UpdateScriptTask");
- cap_names.append("UpdateSettingsAgentInventory");
- cap_names.append("UpdateSettingsTaskInventory");
- cap_names.append("UploadBakedTexture");
- cap_names.append("UserInfo");
- static LLCachedControl<U32> advertize(gSavedSettings,
- "OSAdvertizePBRTerrain");
- if (!gIsInSecondLife && advertize)
- {
- // Capability telling OpenSim we do support PBR terrain. HB
- cap_names.append(advertize > 1 ? "VETPBR" : "VTPBR");
- }
- cap_names.append("ViewerAsset");
- cap_names.append("ViewerBenefits");
- cap_names.append("ViewerStartAuction");
- cap_names.append("ViewerStats");
- cap_names.append("VoiceSignalingRequest");
- }
- std::string LLViewerRegion::getIdentity() const
- {
- std::string name;
- if (mName.empty())
- {
- #if 0 // This can lead to long hiccups or "pauses" when the host is unknown
- // and the DNS resolves too slowly... HB
- name = mHost.getHostName();
- #else
- name = mHost.getIPString();
- #endif
- }
- else
- {
- name = mName;
- }
- if (mRegionID.isNull())
- {
- return name;
- }
- return name + " (" + mRegionID.asString() + ")";
- }
- void LLViewerRegion::setSeedCapability(const std::string& url)
- {
- if (getCapability("Seed") == url)
- {
- std::string coro =
- gCoros.launch("LLViewerRegion::requestBaseCapabilitiesCompleteCoro",
- boost::bind(&LLViewerRegion::requestBaseCapabilitiesCompleteCoro,
- mHandle));
- llinfos << "Coroutine " << coro
- << " launched for duplicate Seed for region " << getIdentity()
- << llendl;
- return;
- }
- delete mEventPoll;
- mEventPoll = NULL;
- mFeaturesReceived = mHoverHeigthFeature = false;
- mSimulatorFeatures.clear();
- mCapabilities.clear();
- static const std::string seed_cap("Seed");
- setCapability(seed_cap, url);
- std::string coro =
- gCoros.launch("LLViewerRegion::requestBaseCapabilitiesCoro",
- boost::bind(&LLViewerRegion::requestBaseCapabilitiesCoro,
- mHandle));
- llinfos << "Coroutine " << coro
- << " launched for capabilities request for region " << getIdentity()
- << " to seed: " << url << llendl;
- }
- std::string add_trailing_slash_to_cap(const std::string& url)
- {
- if (!url.empty() && *url.rbegin() != '/')
- {
- return url + "/";
- }
- return url;
- }
- void LLViewerRegion::setCapability(const std::string& name,
- const std::string& url)
- {
- // Guards against a crash seen when exiting the viewer shortly after a far
- // TP, during the shut down 'mainloop' pumping to exit coroutines: a
- // SimulatorFeatures reply may then arrive and trigger a call to gCoros
- // below, causing a crash due to the use of destroyed mutex. HB
- if (LLApp::isExiting() || gDisconnected)
- {
- return;
- }
- if (name == "EventQueueGet")
- {
- // *HACK: remember the event poll request URL to be able to relaunch it
- // for the TP race workaround. HB
- mCapabilities[name] = url;
- if (mEventPoll)
- {
- delete mEventPoll;
- }
- mEventPoll = new LLEventPoll(mHandle, mHost, url);
- // When restarting an event poll, we already have a sim name... HB
- if (!mName.empty())
- {
- mEventPoll->setRegionName(mName);
- }
- }
- else if (name == "UntrustedSimulatorMessage")
- {
- mHost.setUntrustedSimulatorCap(url);
- }
- else if (name == "SimulatorFeatures")
- {
- mCapabilities[name] = url;
- // Kick off a request for simulator features
- std::string coro_name =
- gCoros.launch("LLViewerRegion::requestSimulatorFeatureCoro",
- boost::bind(&LLViewerRegion::requestSimulatorFeatureCoro,
- url, mHandle));
- llinfos << "Coroutine " << coro_name
- << " launched to request simulator features for region "
- << getIdentity() << " from: " << url << llendl;
- // At this point, we should have a region name for this simulator. HB
- if (mEventPoll && !mName.empty())
- {
- mEventPoll->setRegionName(mName);
- }
- }
- else if (name == "Metadata")
- {
- LL_DEBUGS("Capabilities") << "Got special capability Metadata, content = "
- << url << LL_ENDL;
- }
- // Some cached capabilities need to have a trailing slash. HB
- else if (name == "GetTexture")
- {
- mGetTextureUrl = add_trailing_slash_to_cap(url);
- mCapabilities[name] = mGetTextureUrl;
- }
- else if (name == "GetMesh")
- {
- mGetMeshUrl = add_trailing_slash_to_cap(url);
- mCapabilities[name] = mGetMeshUrl;
- }
- else if (name == "GetMesh2")
- {
- mGetMesh2Url = add_trailing_slash_to_cap(url);
- mCapabilities[name] = mGetMesh2Url;
- }
- else if (name == "ViewerAsset")
- {
- mViewerAssetUrl = add_trailing_slash_to_cap(url);
- mCapabilities[name] = mViewerAssetUrl;
- }
- else if (name == "GetDisplayNames" || name == "GetExperienceInfo")
- {
- mCapabilities[name] = add_trailing_slash_to_cap(url);
- }
- else
- {
- mCapabilities[name] = url;
- }
- if (name == "InterestList")
- {
- setInterestListMode();
- }
- }
- bool LLViewerRegion::setInterestListMode(bool set_default) const
- {
- if (gAgent.getRegion() != this)
- {
- // Not our agent region: do not touch anything...
- return false;
- }
- const std::string& cap_url = getCapability("InterestList");
- if (cap_url.empty())
- {
- // No such capability, nothing to do.
- return false;
- }
- static LLCachedControl<bool> use_360(gSavedSettings, "Use360InterestList");
- LLSD body;
- body["mode"] = LLSD::String(!set_default && use_360 ? "360" : "default");
- return gAgent.requestPostCapability("InterestList", body);
- }
- // NOTE: do make sure to call this method only after the region capabilities
- // have been received !
- const std::string& LLViewerRegion::getTextureUrl() const
- {
- bool no_asset_cap = mViewerAssetUrl.empty();
- if (no_asset_cap && gIsInSecondLife)
- {
- if (mCapabilitiesState == CAPABILITIES_STATE_RECEIVED)
- {
- llwarns_once << "Region '" << getIdentity()
- << "' is missing ViewerAsset capability." << llendl;
- }
- else // This should not happen if the note above is respected
- {
- llwarns_once << "Region '" << getIdentity()
- << "' did not yet send the ViewerAsset capability."
- << llendl;
- llassert(false);
- }
- }
- static LLCachedControl<bool> use_viewerasset(gSavedSettings,
- "UseViewerAssetCap");
- if (use_viewerasset && !no_asset_cap)
- {
- LL_DEBUGS_ONCE("Capabilities") << "Using the ViewerAsset capability for region "
- << getIdentity() << LL_ENDL;
- return mViewerAssetUrl;
- }
- LL_DEBUGS_ONCE("Capabilities") << "Using the GetTexture capability for region "
- << getIdentity() << LL_ENDL;
- return mGetTextureUrl;
- }
- // NOTE: do make sure to call this method only after the region capabilities
- // have been received !
- const std::string& LLViewerRegion::getMeshUrl(bool* is_mesh2) const
- {
- bool no_asset_cap = mViewerAssetUrl.empty();
- if (no_asset_cap && gIsInSecondLife)
- {
- if (mCapabilitiesState == CAPABILITIES_STATE_RECEIVED)
- {
- llwarns_once << "Region '" << getIdentity()
- << "' is missing ViewerAsset capability." << llendl;
- }
- else // This should not happen if the note above is respected
- {
- llwarns_once << "Region '" << getIdentity()
- << "' did not yet send the ViewerAsset capability."
- << llendl;
- llassert(false);
- }
- }
- if (is_mesh2)
- {
- *is_mesh2 = true;
- }
- static LLCachedControl<bool> use_getmesh2(gSavedSettings,
- "UseGetMesh2Cap");
- static LLCachedControl<bool> use_viewerasset(gSavedSettings,
- "UseViewerAssetCap");
- if (use_viewerasset && !no_asset_cap)
- {
- LL_DEBUGS_ONCE("Capabilities") << "Using the ViewerAsset capability for region "
- << getIdentity() << LL_ENDL;
- return mViewerAssetUrl;
- }
- if ((gIsInSecondLife || use_getmesh2) && !mGetMesh2Url.empty())
- {
- LL_DEBUGS_ONCE("Capabilities") << "Using the GetMesh2Url capability for region "
- << getIdentity() << LL_ENDL;
- return mGetMesh2Url;
- }
- if (is_mesh2)
- {
- *is_mesh2 = false;
- }
- LL_DEBUGS_ONCE("Capabilities") << "Using the GetMeshUrl capability for region "
- << getIdentity() << LL_ENDL;
- return mGetMeshUrl;
- }
- bool LLViewerRegion::isSpecialCapabilityName(const std::string &name)
- {
- return name == "EventQueueGet" || name == "UntrustedSimulatorMessage" ||
- name == "Metadata" || name == "SimulatorFeatures";
- }
- const std::string& LLViewerRegion::getCapability(const char* name) const
- {
- capability_map_t::const_iterator iter = mCapabilities.find(name);
- if (iter == mCapabilities.end())
- {
- return LLStringUtil::null;
- }
- return iter->second;
- }
- void LLViewerRegion::onCapabilitiesReceived()
- {
- if (getCapability("SimulatorFeatures").empty())
- {
- llinfos << "No SimulatorFeatures capability for region: "
- << getIdentity() << llendl;
- mMeshRezEnabled = !getCapability("GetMesh").empty() ||
- !getCapability("GetMesh2").empty();
- mMeshUploadEnabled = !getCapability("MeshUploadFlag").empty();
- // There is no need holding back the sim features signal callbacks...
- // Just fire and disconnect them.
- mFeaturesReceived = true;
- mFeaturesReceivedSignal(getRegionID());
- mFeaturesReceivedSignal.disconnect_all_slots();
- }
- }
- void LLViewerRegion::setCapabilitiesReceived(bool received)
- {
- mCapabilitiesState = received ? CAPABILITIES_STATE_RECEIVED
- : CAPABILITIES_STATE_INIT;
- // Tell interested parties that we've received capabilities,
- // so that they can safely use getCapability().
- if (received)
- {
- onCapabilitiesReceived();
- mCapabilitiesReceivedSignal(getRegionID());
- // This is a single-shot signal. Forget callbacks to save resources.
- mCapabilitiesReceivedSignal.disconnect_all_slots();
- }
- }
- boost::signals2::connection LLViewerRegion::setCapsReceivedCB(const caps_received_cb_t& cb)
- {
- return mCapabilitiesReceivedSignal.connect(cb);
- }
- void LLViewerRegion::logActiveCapabilities() const
- {
- U32 count = 0;
- for (capability_map_t::const_iterator iter = mCapabilities.begin(),
- end = mCapabilities.end();
- iter != end; ++iter)
- {
- if (!iter->second.empty())
- {
- llinfos << iter->first << " URL is " << iter->second << llendl;
- ++count;
- }
- }
- llinfos << "Dumped " << count << " entries." << llendl;
- }
- std::string LLViewerRegion::getSimHostName()
- {
- return mHostName.empty() ? mHost.getHostName() : mHostName;
- }
- LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)
- {
- if (type < mObjectPartition.size() && type < PARTITION_VO_CACHE)
- {
- return (LLSpatialPartition*)mObjectPartition[type];
- }
- return NULL;
- }
- LLVOCachePartition* LLViewerRegion::getVOCachePartition()
- {
- // No need to check for mObjectPartition.size() against PARTITION_VO_CACHE
- // in release builds since mObjectPartition is always initialized in the
- // constructor of LLViewerRegion and not modified until the destructor is
- // called... HB
- llassert(mObjectPartition.size() > PARTITION_VO_CACHE);
- return (LLVOCachePartition*)mObjectPartition[PARTITION_VO_CACHE];
- }
- // The viewer can not yet distinquish between normal and estate-owned objects
- // so we collapse these two bits and enable the UI if either are set
- constexpr U64 ALLOW_RETURN_ENCROACHING_OBJECT =
- REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT |
- REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT;
- bool LLViewerRegion::objectIsReturnable(const LLVector3& pos,
- const std::vector<LLBBox>& boxes) const
- {
- return mParcelOverlay &&
- (mParcelOverlay->isOwnedSelf(pos) ||
- mParcelOverlay->isOwnedGroup(pos) ||
- (getRegionFlag(ALLOW_RETURN_ENCROACHING_OBJECT) &&
- mParcelOverlay->encroachesOwned(boxes)));
- }
- bool LLViewerRegion::childrenObjectReturnable(const std::vector<LLBBox>& boxes) const
- {
- return mParcelOverlay && mParcelOverlay->encroachesOnUnowned(boxes);
- }
- void LLViewerRegion::getNeighboringRegions(std::vector<LLViewerRegion*>& regions)
- {
- mLandp->getNeighboringRegions(regions);
- }
- void LLViewerRegion::getNeighboringRegionsStatus(std::vector<S32>& regions)
- {
- mLandp->getNeighboringRegionsStatus(regions);
- }
- void LLViewerRegion::dumpSettings()
- {
- llinfos << "Damage: " << (getAllowDamage() ? "on" : "off")
- << llendl;
- llinfos << "Landmark: " << (getAllowLandmark() ? "on" : "off")
- << llendl;
- llinfos << "SetHome: " << (getAllowSetHome() ? "on" : "off")
- << llendl;
- llinfos << "ResetHome: " << (getResetHomeOnTeleport() ? "on" : "off")
- << llendl;
- llinfos << "SunFixed: " << (getSunFixed() ? "on" : "off") << llendl;
- llinfos << "Clouds updates: " << (mGotClouds ? "yes" : "no") << llendl;
- llinfos << "BlockFly: " << (getBlockFly() ? "on" : "off") << llendl;
- llinfos << "AllowDirectTP: " << (getAllowDirectTeleport() ? "on" : "off")
- << llendl;
- llinfos << "Terraform: " << (getAllowTerraform() ? "on" : "off")
- << llendl;
- llinfos << "RestrictPush: " << (getRestrictPushObject() ? "on" : "off")
- << llendl;
- llinfos << "Voice: " << (isVoiceEnabled() ? "on" : "off")
- << llendl;
- llinfos << "Prelude: " << (isPrelude() ? "on" : "off") << llendl;
- llinfos << "Water: " << getWaterHeight() << "m" << llendl;
- llinfos << "Region size: " << mWidth << "m" << llendl;
- llinfos << "Max primitives: " << mMaxTasks << llendl;
- llinfos << "MeshRezEnabled: " << (mMeshRezEnabled ? "yes" : "no") << llendl;
- llinfos << "MeshRezUpload: " << (mMeshUploadEnabled ? "yes" : "no")
- << llendl;
- llinfos << "PathFinding: " << (mDynamicPathfinding ? "yes" : "no")
- << llendl;
- llinfos << "HoverHeight: " << (mHoverHeigthFeature ? "yes" : "no")
- << llendl;
- llinfos << "OS export perm: " << (isOSExportPermSupported() ? "yes" : "no")
- << llendl;
- llinfos << "WhisperRange: " << mWhisperRange << "m" << llendl;
- llinfos << "ChatRange: " << mChatRange << "m" << llendl;
- llinfos << "ShoutRange: " << mShoutRange << "m" << llendl;
- }
|