LLClientView.cs 567 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Collections.Frozen;
  30. using System.Net;
  31. using System.Reflection;
  32. using System.Runtime;
  33. using System.Runtime.CompilerServices;
  34. using System.Runtime.InteropServices;
  35. using System.Threading;
  36. using log4net;
  37. using OpenMetaverse;
  38. using OpenMetaverse.Packets;
  39. using OpenMetaverse.StructuredData;
  40. using OpenSim.Framework;
  41. using OpenSim.Framework.Client;
  42. using OpenSim.Framework.Monitoring;
  43. using OpenSim.Region.Framework.Interfaces;
  44. using OpenSim.Region.Framework.Scenes;
  45. using OpenSim.Services.Interfaces;
  46. using AssetLandmark = OpenSim.Framework.AssetLandmark;
  47. using Caps = OpenSim.Framework.Capabilities.Caps;
  48. using PermissionMask = OpenSim.Framework.PermissionMask;
  49. using RegionFlags = OpenMetaverse.RegionFlags;
  50. namespace OpenSim.Region.ClientStack.LindenUDP
  51. {
  52. public delegate void PacketMethod(Packet packet);
  53. /// <summary>
  54. /// Handles new client connections
  55. /// Constructor takes a single Packet and authenticates everything
  56. /// </summary>
  57. public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IStatsCollector, IClientIPEndpoint
  58. {
  59. /// <value>
  60. /// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details.
  61. /// </value>
  62. public int DebugPacketLevel { get; set; }
  63. private delegate void StaticPacketMethod(LLClientView cli, Packet packet);
  64. #region Events
  65. public event BinaryGenericMessage OnBinaryGenericMessage;
  66. public event Action<IClientAPI> OnLogout;
  67. public event ObjectPermissions OnObjectPermissions;
  68. public event Action<IClientAPI> OnConnectionClosed;
  69. public event ViewerEffectEventHandler OnViewerEffect;
  70. public event ImprovedInstantMessage OnInstantMessage;
  71. public event ChatMessage OnChatFromClient;
  72. public event RezObject OnRezObject;
  73. public event DeRezObject OnDeRezObject;
  74. public event RezRestoreToWorld OnRezRestoreToWorld;
  75. public event ModifyTerrain OnModifyTerrain;
  76. public event Action<IClientAPI> OnRegionHandShakeReply;
  77. public event GenericCall1 OnRequestWearables;
  78. public event SetAppearance OnSetAppearance;
  79. public event AvatarNowWearing OnAvatarNowWearing;
  80. public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
  81. public event RezMultipleAttachmentsFromInv OnRezMultipleAttachmentsFromInv;
  82. public event UUIDNameRequest OnDetachAttachmentIntoInv;
  83. public event ObjectAttach OnObjectAttach;
  84. public event ObjectDeselect OnObjectDetach;
  85. public event ObjectDrop OnObjectDrop;
  86. public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
  87. public event UpdateAgent OnPreAgentUpdate;
  88. public event UpdateAgent OnAgentUpdate;
  89. public event UpdateAgent OnAgentCameraUpdate;
  90. public event AgentRequestSit OnAgentRequestSit;
  91. public event AgentSit OnAgentSit;
  92. public event AvatarPickerRequest OnAvatarPickerRequest;
  93. public event ChangeAnim OnChangeAnim;
  94. public event Action<IClientAPI> OnRequestAvatarsData;
  95. public event LinkObjects OnLinkObjects;
  96. public event DelinkObjects OnDelinkObjects;
  97. public event GrabObject OnGrabObject;
  98. public event DeGrabObject OnDeGrabObject;
  99. public event SpinStart OnSpinStart;
  100. public event SpinStop OnSpinStop;
  101. public event ObjectDuplicate OnObjectDuplicate;
  102. public event ObjectDuplicateOnRay OnObjectDuplicateOnRay;
  103. public event MoveObject OnGrabUpdate;
  104. public event SpinObject OnSpinUpdate;
  105. public event AddNewPrim OnAddPrim;
  106. public event RequestGodlikePowers OnRequestGodlikePowers;
  107. public event GodKickUser OnGodKickUser;
  108. public event ObjectExtraParams OnUpdateExtraParams;
  109. public event UpdateShape OnUpdatePrimShape;
  110. public event ObjectRequest OnObjectRequest;
  111. public event ObjectSelect OnObjectSelect;
  112. public event ObjectDeselect OnObjectDeselect;
  113. public event GenericCall7 OnObjectDescription;
  114. public event GenericCall7 OnObjectName;
  115. public event GenericCall7 OnObjectClickAction;
  116. public event GenericCall7 OnObjectMaterial;
  117. public event ObjectIncludeInSearch OnObjectIncludeInSearch;
  118. public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
  119. public event UpdatePrimFlags OnUpdatePrimFlags;
  120. public event UpdatePrimTexture OnUpdatePrimTexture;
  121. public event ClientChangeObject onClientChangeObject;
  122. public event UpdateVector OnUpdatePrimGroupPosition;
  123. public event UpdatePrimRotation OnUpdatePrimGroupRotation;
  124. public event UpdateVector OnUpdatePrimGroupScale;
  125. public event RequestMapBlocks OnRequestMapBlocks;
  126. public event RequestMapName OnMapNameRequest;
  127. public event TeleportLocationRequest OnTeleportLocationRequest;
  128. public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
  129. public event TeleportCancel OnTeleportCancel;
  130. public event RequestAvatarProperties OnRequestAvatarProperties;
  131. public event SetAlwaysRun OnSetAlwaysRun;
  132. public event AgentDataUpdate OnAgentDataUpdateRequest;
  133. public event TeleportLocationRequest OnSetStartLocationRequest;
  134. public event UpdateAvatarProperties OnUpdateAvatarProperties;
  135. public event CreateNewInventoryItem OnCreateNewInventoryItem;
  136. public event LinkInventoryItem OnLinkInventoryItem;
  137. public event CreateInventoryFolder OnCreateNewInventoryFolder;
  138. public event UpdateInventoryFolder OnUpdateInventoryFolder;
  139. public event MoveInventoryFolder OnMoveInventoryFolder;
  140. public event FetchInventoryDescendents OnFetchInventoryDescendents;
  141. public event PurgeInventoryDescendents OnPurgeInventoryDescendents;
  142. public event FetchInventory OnFetchInventory;
  143. public event RequestTaskInventory OnRequestTaskInventory;
  144. public event UpdateInventoryItem OnUpdateInventoryItem;
  145. public event CopyInventoryItem OnCopyInventoryItem;
  146. public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
  147. public event MoveInventoryItem OnMoveInventoryItem;
  148. public event RemoveInventoryItem OnRemoveInventoryItem;
  149. public event RemoveInventoryFolder OnRemoveInventoryFolder;
  150. public event UDPAssetUploadRequest OnAssetUploadRequest;
  151. public event XferReceive OnXferReceive;
  152. public event RequestXfer OnRequestXfer;
  153. public event ConfirmXfer OnConfirmXfer;
  154. public event AbortXfer OnAbortXfer;
  155. public event RequestTerrain OnRequestTerrain;
  156. public event RezScript OnRezScript;
  157. public event UpdateTaskInventory OnUpdateTaskInventory;
  158. public event MoveTaskInventory OnMoveTaskItem;
  159. public event RemoveTaskInventory OnRemoveTaskItem;
  160. public event UUIDNameRequest OnNameFromUUIDRequest;
  161. public event ParcelAccessListRequest OnParcelAccessListRequest;
  162. public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest;
  163. public event ParcelPropertiesRequest OnParcelPropertiesRequest;
  164. public event ParcelDivideRequest OnParcelDivideRequest;
  165. public event ParcelJoinRequest OnParcelJoinRequest;
  166. public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
  167. public event ParcelSelectObjects OnParcelSelectObjects;
  168. public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest;
  169. public event ParcelAbandonRequest OnParcelAbandonRequest;
  170. public event ParcelGodForceOwner OnParcelGodForceOwner;
  171. public event ParcelReclaim OnParcelReclaim;
  172. public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest;
  173. public event ParcelDeedToGroup OnParcelDeedToGroup;
  174. public event RegionInfoRequest OnRegionInfoRequest;
  175. public event EstateCovenantRequest OnEstateCovenantRequest;
  176. public event FriendActionDelegate OnApproveFriendRequest;
  177. public event FriendActionDelegate OnDenyFriendRequest;
  178. public event FriendshipTermination OnTerminateFriendship;
  179. public event GrantUserFriendRights OnGrantUserRights;
  180. public event MoneyTransferRequest OnMoneyTransferRequest;
  181. public event EconomyDataRequest OnEconomyDataRequest;
  182. public event MoneyBalanceRequest OnMoneyBalanceRequest;
  183. public event ParcelBuy OnParcelBuy;
  184. public event UUIDNameRequest OnTeleportHomeRequest;
  185. public event UUIDNameRequest OnUUIDGroupNameRequest;
  186. public event ScriptAnswer OnScriptAnswer;
  187. public event RequestPayPrice OnRequestPayPrice;
  188. public event ObjectSaleInfo OnObjectSaleInfo;
  189. public event ObjectBuy OnObjectBuy;
  190. public event AgentSit OnUndo;
  191. public event AgentSit OnRedo;
  192. public event LandUndo OnLandUndo;
  193. public event ForceReleaseControls OnForceReleaseControls;
  194. public event GodLandStatRequest OnLandStatRequest;
  195. public event RequestObjectPropertiesFamily OnObjectGroupRequest;
  196. public event DetailedEstateDataRequest OnDetailedEstateDataRequest;
  197. public event SetEstateFlagsRequest OnSetEstateFlagsRequest;
  198. public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture;
  199. public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights;
  200. public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest;
  201. public event SetRegionTerrainSettings OnSetRegionTerrainSettings;
  202. public event BakeTerrain OnBakeTerrain;
  203. public event RequestTerrain OnUploadTerrain;
  204. public event EstateChangeInfo OnEstateChangeInfo;
  205. public event EstateManageTelehub OnEstateManageTelehub;
  206. public event EstateRestartSimRequest OnEstateRestartSimRequest;
  207. public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest;
  208. public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest;
  209. public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest;
  210. public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest;
  211. public event EstateDebugRegionRequest OnEstateDebugRegionRequest;
  212. public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest;
  213. public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
  214. public event RegionHandleRequest OnRegionHandleRequest;
  215. public event ParcelInfoRequest OnParcelInfoRequest;
  216. public event ScriptReset OnScriptReset;
  217. public event GetScriptRunning OnGetScriptRunning;
  218. public event SetScriptRunning OnSetScriptRunning;
  219. public event Action<Vector3, bool, bool> OnAutoPilotGo;
  220. public event ActivateGesture OnActivateGesture;
  221. public event DeactivateGesture OnDeactivateGesture;
  222. public event ObjectOwner OnObjectOwner;
  223. public event DirPlacesQuery OnDirPlacesQuery;
  224. public event DirFindQuery OnDirFindQuery;
  225. public event DirLandQuery OnDirLandQuery;
  226. public event DirPopularQuery OnDirPopularQuery;
  227. public event DirClassifiedQuery OnDirClassifiedQuery;
  228. public event EventInfoRequest OnEventInfoRequest;
  229. public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime;
  230. public event MapItemRequest OnMapItemRequest;
  231. public event OfferCallingCard OnOfferCallingCard;
  232. public event AcceptCallingCard OnAcceptCallingCard;
  233. public event DeclineCallingCard OnDeclineCallingCard;
  234. public event SoundTrigger OnSoundTrigger;
  235. public event StartLure OnStartLure;
  236. public event TeleportLureRequest OnTeleportLureRequest;
  237. public event NetworkStats OnNetworkStatsUpdate;
  238. public event ClassifiedInfoRequest OnClassifiedInfoRequest;
  239. public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
  240. public event ClassifiedDelete OnClassifiedDelete;
  241. public event ClassifiedGodDelete OnClassifiedGodDelete;
  242. public event EventNotificationAddRequest OnEventNotificationAddRequest;
  243. public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
  244. public event EventGodDelete OnEventGodDelete;
  245. public event ParcelDwellRequest OnParcelDwellRequest;
  246. public event UserInfoRequest OnUserInfoRequest;
  247. public event UpdateUserInfo OnUpdateUserInfo;
  248. public event RetrieveInstantMessages OnRetrieveInstantMessages;
  249. public event PickDelete OnPickDelete;
  250. public event PickGodDelete OnPickGodDelete;
  251. public event PickInfoUpdate OnPickInfoUpdate;
  252. public event AvatarNotesUpdate OnAvatarNotesUpdate;
  253. public event MuteListRequest OnMuteListRequest;
  254. public event AvatarInterestUpdate OnAvatarInterestUpdate;
  255. public event PlacesQuery OnPlacesQuery;
  256. public event AgentFOV OnAgentFOV;
  257. public event FindAgentUpdate OnFindAgent;
  258. public event TrackAgentUpdate OnTrackAgent;
  259. public event NewUserReport OnUserReport;
  260. public event SaveStateHandler OnSaveState;
  261. public event GroupAccountSummaryRequest OnGroupAccountSummaryRequest;
  262. public event GroupAccountDetailsRequest OnGroupAccountDetailsRequest;
  263. public event GroupAccountTransactionsRequest OnGroupAccountTransactionsRequest;
  264. public event FreezeUserUpdate OnParcelFreezeUser;
  265. public event EjectUserUpdate OnParcelEjectUser;
  266. public event ParcelBuyPass OnParcelBuyPass;
  267. public event ParcelGodMark OnParcelGodMark;
  268. public event GroupActiveProposalsRequest OnGroupActiveProposalsRequest;
  269. public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
  270. public event SimWideDeletesDelegate OnSimWideDeletes;
  271. public event SendPostcard OnSendPostcard;
  272. public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
  273. public event MuteListEntryUpdate OnUpdateMuteListEntry;
  274. public event MuteListEntryRemove OnRemoveMuteListEntry;
  275. public event GodlikeMessage onGodlikeMessage;
  276. public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
  277. public event GenericCall2 OnUpdateThrottles;
  278. #pragma warning disable 0067
  279. // still unused
  280. public event GenericMessage OnGenericMessage;
  281. public event TextureRequest OnRequestTexture;
  282. public event StatusChange OnChildAgentStatus;
  283. public event GenericCall2 OnStopMovement;
  284. public event Action<UUID> OnRemoveAvatar;
  285. public event DisconnectUser OnDisconnectUser;
  286. public event RequestAsset OnRequestAsset;
  287. public event BuyObjectInventory OnBuyObjectInventory;
  288. public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture;
  289. public event TerrainUnacked OnUnackedTerrain;
  290. public event CachedTextureRequest OnCachedTextureRequest;
  291. public event UpdateVector OnUpdatePrimSinglePosition;
  292. public event StartAnim OnStartAnim;
  293. public event StopAnim OnStopAnim;
  294. public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation;
  295. public event UpdatePrimSingleRotationPosition OnUpdatePrimSingleRotationPosition;
  296. public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation;
  297. public event UpdateVector OnUpdatePrimScale;
  298. #pragma warning restore 0067
  299. #endregion Events
  300. #region Class Members
  301. // LLClientView Only
  302. public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args);
  303. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  304. private static readonly string LogHeader = "[LLCLIENTVIEW]";
  305. /// <summary>
  306. /// Handles UDP texture download.
  307. /// </summary>
  308. public LLImageManager ImageManager { get; private set; }
  309. public JobEngine m_asyncPacketProcess;
  310. private readonly LLUDPServer m_udpServer;
  311. private readonly LLUDPClient m_udpClient;
  312. internal readonly UUID m_sessionId;
  313. private readonly UUID m_secureSessionId;
  314. internal readonly UUID m_agentId;
  315. protected readonly UUID m_scopeId;
  316. private readonly uint m_circuitCode;
  317. private readonly byte[] m_regionChannelVersion = Utils.EmptyBytes;
  318. private readonly IGroupsModule m_GroupsModule;
  319. //private int m_cachedTextureSerial;
  320. private readonly PriorityQueue m_entityUpdates;
  321. private readonly PriorityQueue m_entityProps;
  322. private readonly Prioritizer m_prioritizer;
  323. private bool m_disableFacelights;
  324. private HashSet<SceneObjectGroup> GroupsInView = [];
  325. #pragma warning disable 0414
  326. private bool m_VelocityInterpolate;
  327. #pragma warning restore 0414
  328. private const uint MaxTransferBytesPerPacket = 600;
  329. private bool m_SupportObjectAnimations;
  330. private bool m_SupportPBR;
  331. public bool SupportTerrainPBR { get; private set; }
  332. public ViewerFlags ViewerFlags { get; private set; }
  333. /// <value>
  334. /// Maintain a record of all the objects killed. This allows us to stop an update being sent from the
  335. /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
  336. /// ownerless phantom.
  337. ///
  338. /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
  339. ///
  340. /// </value>
  341. protected List<uint> m_killRecord;
  342. //protected HashSet<uint> m_attachmentsSent;
  343. private bool m_SendLogoutPacketWhenClosing = true;
  344. /// <summary>
  345. /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for
  346. /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it
  347. /// is doing absolutely nothing.
  348. /// </summary>
  349. /// <remarks>
  350. /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods
  351. /// cannot retain a reference to it outside of that method.
  352. /// </remarks>
  353. private readonly AgentUpdateArgs m_thisAgentUpdateArgs = new();
  354. protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new();
  355. protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new(); //PauPaw:Local Generic Message handlers
  356. protected Scene m_scene;
  357. protected string m_firstName;
  358. protected string m_lastName;
  359. protected Vector3 m_startpos;
  360. protected UUID m_activeGroupID;
  361. protected string m_activeGroupName = String.Empty;
  362. protected ulong m_activeGroupPowers;
  363. protected Dictionary<UUID, ulong> m_groupPowers = new();
  364. protected int m_terrainCheckerCount;
  365. protected uint m_agentFOVCounter;
  366. protected IAssetService m_assetService;
  367. protected bool m_supportViewerCache = false;
  368. #endregion Class Members
  369. #region Properties
  370. public LLUDPClient UDPClient { get { return m_udpClient; } }
  371. public LLUDPServer UDPServer { get { return m_udpServer; } }
  372. public IPEndPoint RemoteEndPoint { get { return m_udpClient.RemoteEndPoint; } }
  373. public UUID SecureSessionId { get { return m_secureSessionId; } }
  374. public IScene Scene { get { return m_scene; } }
  375. public UUID SessionId { get { return m_sessionId; } }
  376. public Vector3 StartPos
  377. {
  378. get { return m_startpos; }
  379. set { m_startpos = value; }
  380. }
  381. public float StartFar { get; set; }
  382. public float FOV { get; set; } = 1.25f;
  383. public int viewHeight { get; set; } = 480;
  384. public int viewWidth { get; set; } = 640;
  385. public UUID AgentId { get { return m_agentId; } }
  386. public UUID ScopeId { get { return m_scopeId; } }
  387. public ISceneAgent SceneAgent { get; set; }
  388. public UUID ActiveGroupId { get { return m_activeGroupID; } set { m_activeGroupID = value; } }
  389. public string ActiveGroupName { get { return m_activeGroupName; } set { m_activeGroupName = value; } }
  390. public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } set { m_activeGroupPowers = value; } }
  391. public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
  392. public int PingTimeMS
  393. {
  394. get
  395. {
  396. if (UDPClient != null)
  397. return UDPClient.PingTimeMS;
  398. return 0;
  399. }
  400. }
  401. /// <summary>
  402. /// Entity update queues
  403. /// </summary>
  404. public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } }
  405. /// <summary>
  406. /// First name of the agent/avatar represented by the client
  407. /// </summary>
  408. public string FirstName { get { return m_firstName; } }
  409. /// <summary>
  410. /// Last name of the agent/avatar represented by the client
  411. /// </summary>
  412. public string LastName { get { return m_lastName; } }
  413. /// <summary>
  414. /// Full name of the client (first name and last name)
  415. /// </summary>
  416. public string Name { get { return FirstName + " " + LastName; } }
  417. public uint CircuitCode { get { return m_circuitCode; } }
  418. protected int m_animationSequenceNumber = (int)(Util.GetTimeStampTicks() & 0x5fffafL);
  419. public int NextAnimationSequenceNumber
  420. {
  421. get
  422. {
  423. int ret = Interlocked.Increment(ref m_animationSequenceNumber);
  424. if (ret <= 0)
  425. {
  426. m_animationSequenceNumber = (int)(Util.GetTimeStampTicks() & 0xafff5fL);
  427. ret = Interlocked.Increment(ref m_animationSequenceNumber);
  428. }
  429. return ret;
  430. }
  431. set
  432. {
  433. m_animationSequenceNumber = value;
  434. }
  435. }
  436. /// <summary>
  437. /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to
  438. /// prevent race conditions by different threads calling Close().
  439. /// </summary>
  440. public bool IsActive { get; set; }
  441. /// <summary>
  442. /// Used to synchronise threads when client is being closed.
  443. /// </summary>
  444. public readonly object CloseSyncLock = new object();
  445. public bool IsLoggingOut { get; set; }
  446. public bool DisableFacelights
  447. {
  448. get { return m_disableFacelights; }
  449. set { m_disableFacelights = value; }
  450. }
  451. public List<uint> SelectedObjects {get; private set;}
  452. public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
  453. #endregion Properties
  454. //~LLClientView()
  455. //{
  456. // m_log.DebugFormat("{0} Destructor called for {1}, circuit code {2}", LogHeader, Name, CircuitCode);
  457. //}
  458. /// <summary>
  459. /// Constructor
  460. /// </summary>
  461. public LLClientView(Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
  462. UUID agentId, UUID sessionId, uint circuitCode)
  463. {
  464. //DebugPacketLevel = 1;
  465. SelectedObjects = new List<uint>();
  466. RegisterInterface<IClientIM>(this);
  467. RegisterInterface<IClientInventory>(this);
  468. RegisterInterface<IClientChat>(this);
  469. m_scene = scene;
  470. int pcap = 512;
  471. if(pcap > m_scene.Entities.Count)
  472. pcap = m_scene.Entities.Count;
  473. m_entityUpdates = new PriorityQueue(pcap);
  474. m_entityProps = new PriorityQueue(pcap);
  475. m_killRecord = new List<uint>();
  476. //m_attachmentsSent = new HashSet<uint>();
  477. m_assetService = m_scene.RequestModuleInterface<IAssetService>();
  478. m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>();
  479. ImageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>());
  480. m_regionChannelVersion = Util.StringToBytes1024(scene.GetSimulatorVersion());
  481. m_agentId = agentId;
  482. m_sessionId = sessionId;
  483. m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
  484. m_circuitCode = circuitCode;
  485. m_firstName = sessionInfo.LoginInfo.First;
  486. m_lastName = sessionInfo.LoginInfo.Last;
  487. m_startpos = sessionInfo.LoginInfo.StartPos;
  488. StartFar = sessionInfo.LoginInfo.StartFar;
  489. m_udpServer = udpServer;
  490. m_udpClient = udpClient;
  491. m_udpClient.OnQueueEmpty += HandleQueueEmpty;
  492. m_udpClient.HasUpdates += HandleHasUpdates;
  493. m_udpClient.OnPacketStats += PopulateStats;
  494. m_prioritizer = new Prioritizer(m_scene);
  495. // Pick up agent scope which, for gods, can be different from the region scope
  496. IUserAccountService userAccountService = m_scene.RequestModuleInterface<IUserAccountService>();
  497. var myself = userAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_agentId);
  498. RegisterLocalPacketHandlers();
  499. string name = $"AsyncInUDP-{m_agentId}";
  500. m_asyncPacketProcess = new JobEngine(name, name, 5000);
  501. IsActive = true;
  502. m_supportViewerCache = m_udpServer.SupportViewerObjectsCache;
  503. }
  504. #region Client Methods
  505. /// <summary>
  506. /// Close down the client view
  507. /// </summary>
  508. public void Close()
  509. {
  510. Close(true, false);
  511. }
  512. public void Close(bool sendStop, bool force)
  513. {
  514. // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
  515. // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
  516. lock (CloseSyncLock)
  517. {
  518. // We still perform a force close inside the sync lock since this is intended to attempt close where
  519. // there is some unidentified connection problem, not where we have issues due to deadlock
  520. if (!IsActive && !force)
  521. {
  522. m_log.DebugFormat( "{0} Not attempting to close inactive client {1} in {2} since force flag is not set",
  523. LogHeader, Name, m_scene.Name);
  524. return;
  525. }
  526. IsActive = false;
  527. CloseWithoutChecks(sendStop);
  528. }
  529. }
  530. /// <summary>
  531. /// Closes down the client view without first checking whether it is active.
  532. /// </summary>
  533. /// <remarks>
  534. /// This exists because LLUDPServer has to set IsActive = false in earlier synchronous code before calling
  535. /// CloseWithoutIsActiveCheck asynchronously.
  536. ///
  537. /// Callers must lock ClosingSyncLock before calling.
  538. /// </remarks>
  539. public void CloseWithoutChecks(bool sendStop)
  540. {
  541. m_log.DebugFormat(
  542. "[CLIENT]: Close has been called for {0} attached to scene {1}",
  543. Name, m_scene.RegionInfo.RegionName);
  544. if (sendStop)
  545. {
  546. // Send the STOP packet
  547. DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
  548. OutPacket(disable, ThrottleOutPacketType.Unknown);
  549. }
  550. // Fire the callback for this connection closing
  551. OnConnectionClosed?.Invoke(this);
  552. m_asyncPacketProcess.Stop();
  553. // Flush all of the packets out of the UDP server for this client
  554. m_udpServer?.Flush(m_udpClient);
  555. // Remove ourselves from the scene
  556. m_scene.RemoveClient(m_agentId, true);
  557. SceneAgent = null;
  558. // We can't reach into other scenes and close the connection
  559. // We need to do this over grid communications
  560. //m_scene.CloseAllAgents(CircuitCode);
  561. // Disable UDP handling for this client
  562. m_udpClient.OnQueueEmpty -= HandleQueueEmpty;
  563. m_udpClient.HasUpdates -= HandleHasUpdates;
  564. m_udpClient.OnPacketStats -= PopulateStats;
  565. m_udpClient.Shutdown();
  566. // Shutdown the image manager
  567. ImageManager.Close();
  568. ImageManager = null;
  569. m_entityUpdates.Close();
  570. m_entityProps.Close();
  571. m_killRecord.Clear();
  572. GroupsInView.Clear();
  573. if(m_scene.GetNumberOfClients() == 0)
  574. {
  575. GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
  576. GC.Collect();
  577. GC.WaitForPendingFinalizers();
  578. GC.Collect();
  579. GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.Default;
  580. }
  581. }
  582. public void Kick(string message)
  583. {
  584. if (!SceneAgent.IsChildAgent)
  585. {
  586. KickUserPacket kupack = (KickUserPacket)PacketPool.Instance.GetPacket(PacketType.KickUser);
  587. kupack.UserInfo.AgentID = m_agentId;
  588. kupack.UserInfo.SessionID = SessionId;
  589. kupack.TargetBlock.TargetIP = 0;
  590. kupack.TargetBlock.TargetPort = 0;
  591. kupack.UserInfo.Reason = Util.StringToBytes256(message);
  592. OutPacket(kupack, ThrottleOutPacketType.Task);
  593. // You must sleep here or users get no message!
  594. Thread.Sleep(500);
  595. }
  596. }
  597. public void Stop()
  598. {
  599. }
  600. #endregion Client Methods
  601. #region Packet Handling
  602. public void PopulateStats(int inPackets, int outPackets, int unAckedBytes)
  603. {
  604. OnNetworkStatsUpdate?.Invoke(inPackets, outPackets, unAckedBytes);
  605. }
  606. /// <summary>
  607. /// Add a handler for the given packet type.
  608. /// </summary>
  609. /// <remarks>
  610. /// The packet is handled on its own thread. If packets must be handled in the order in which they
  611. /// are received then please use the synchronous version of this method.
  612. /// </remarks>
  613. /// <param name="packetType"></param>
  614. /// <param name="handler"></param>
  615. /// <returns>true if the handler was added. This is currently always the case.</returns>
  616. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  617. public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler)
  618. {
  619. return AddLocalPacketHandler(packetType, handler, true);
  620. }
  621. /// <summary>
  622. /// Add a handler for the given packet type.
  623. /// </summary>
  624. /// <param name="packetType"></param>
  625. /// <param name="handler"></param>
  626. /// <param name="doAsync">
  627. /// If true, when the packet is received it is handled on its own thread rather than on the main inward bound
  628. /// packet handler thread. This vastly increases respnosiveness but some packets need to be handled
  629. /// synchronously.
  630. /// </param>
  631. /// <returns>true if the handler was added. This is currently always the case.</returns>
  632. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  633. public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync)
  634. {
  635. lock (m_packetHandlers)
  636. return m_packetHandlers.TryAdd(packetType, new PacketProcessor(handler, doAsync));
  637. }
  638. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  639. public bool AddGenericPacketHandler(string MethodName, GenericMessage handler)
  640. {
  641. MethodName = MethodName.ToLower().Trim();
  642. lock (m_genericPacketHandlers)
  643. return m_genericPacketHandlers.TryAdd(MethodName, handler);
  644. }
  645. /// <summary>
  646. /// Try to process a packet using registered packet handlers
  647. /// </summary>
  648. /// <param name="packet"></param>
  649. /// <returns>True if a handler was found which successfully processed the packet.</returns>
  650. protected bool ProcessPacketMethod(Packet packet)
  651. {
  652. if (m_staticHandlers.TryGetValue(packet.Type, out StaticPacketProcessor spp))
  653. {
  654. if (spp.Async)
  655. {
  656. Packet lp = packet;
  657. StaticPacketMethod m = spp.method;
  658. LLClientView c = this;
  659. _ = m_asyncPacketProcess.QueueJob(packet.Type.ToString(), () => { m(c,lp); });
  660. }
  661. else
  662. {
  663. spp.method(this, packet);
  664. }
  665. return true;
  666. }
  667. if (m_packetHandlers.TryGetValue(packet.Type, out PacketProcessor pprocessor))
  668. {
  669. if (pprocessor.Async)
  670. {
  671. Packet lp = packet;
  672. PacketMethod m = pprocessor.method;
  673. _ = m_asyncPacketProcess.QueueJob(packet.Type.ToString(), () => { m(lp); });
  674. }
  675. else
  676. {
  677. pprocessor.method(packet);
  678. }
  679. return true;
  680. }
  681. return false;
  682. }
  683. #endregion Packet Handling
  684. # region Setup
  685. public virtual void Start()
  686. {
  687. m_asyncPacketProcess.Start();
  688. m_scene.AddNewAgent(this, PresenceType.User);
  689. //RefreshGroupMembership();
  690. }
  691. # endregion
  692. public void ActivateGesture(UUID assetId, UUID gestureId)
  693. {
  694. }
  695. public void DeactivateGesture(UUID assetId, UUID gestureId)
  696. {
  697. }
  698. // Sound
  699. public void SoundTrigger(UUID soundId, UUID owerid, UUID Objectid, UUID ParentId, float Gain, Vector3 Position, UInt64 Handle)
  700. {
  701. }
  702. #region Scene/Avatar to Client
  703. // temporary here ( from estatemanagermodule)
  704. private uint GetRegionFlags()
  705. {
  706. RegionFlags flags = RegionFlags.None;
  707. if (Scene.RegionInfo.RegionSettings.AllowDamage)
  708. flags |= RegionFlags.AllowDamage;
  709. if (Scene.RegionInfo.EstateSettings.AllowLandmark)
  710. flags |= RegionFlags.AllowLandmark;
  711. if (Scene.RegionInfo.EstateSettings.AllowSetHome)
  712. flags |= RegionFlags.AllowSetHome;
  713. if (Scene.RegionInfo.EstateSettings.ResetHomeOnTeleport)
  714. flags |= RegionFlags.ResetHomeOnTeleport;
  715. if (Scene.RegionInfo.RegionSettings.FixedSun)
  716. flags |= RegionFlags.SunFixed;
  717. // allow access override (was taxfree)
  718. if (!Scene.RegionInfo.EstateSettings.TaxFree) // this is now wrong means !ALLOW_ACCESS_OVERRIDE
  719. flags |= RegionFlags.AllowParcelAccessOverride;
  720. if (Scene.RegionInfo.RegionSettings.BlockTerraform)
  721. flags |= RegionFlags.BlockTerraform;
  722. if (!Scene.RegionInfo.RegionSettings.AllowLandResell)
  723. flags |= RegionFlags.BlockLandResell;
  724. if (Scene.RegionInfo.RegionSettings.Sandbox)
  725. flags |= RegionFlags.Sandbox;
  726. // nulllayer not used
  727. if (Scene.RegionInfo.RegionSettings.Casino)
  728. flags |= RegionFlags.SkipAgentAction; // redefined
  729. if (Scene.RegionInfo.RegionSettings.GodBlockSearch)
  730. flags |= RegionFlags.SkipUpdateInterestList; // redefined
  731. if (Scene.RegionInfo.RegionSettings.DisableCollisions)
  732. flags |= RegionFlags.SkipCollisions;
  733. if (Scene.RegionInfo.RegionSettings.DisableScripts)
  734. flags |= RegionFlags.SkipScripts;
  735. if (Scene.RegionInfo.RegionSettings.DisablePhysics)
  736. flags |= RegionFlags.SkipPhysics;
  737. if (Scene.RegionInfo.EstateSettings.PublicAccess)
  738. flags |= RegionFlags.ExternallyVisible; // ???? need revision
  739. //MainlandVisible -> allow return enc object
  740. //PublicAllowed -> allow return enc estate object
  741. if (Scene.RegionInfo.EstateSettings.BlockDwell)
  742. flags |= RegionFlags.BlockDwell;
  743. if (Scene.RegionInfo.RegionSettings.BlockFly)
  744. flags |= RegionFlags.NoFly;
  745. if (Scene.RegionInfo.EstateSettings.AllowDirectTeleport)
  746. flags |= RegionFlags.AllowDirectTeleport;
  747. if (Scene.RegionInfo.EstateSettings.EstateSkipScripts)
  748. flags |= RegionFlags.EstateSkipScripts;
  749. if (Scene.RegionInfo.RegionSettings.RestrictPushing)
  750. flags |= RegionFlags.RestrictPushObject;
  751. if (Scene.RegionInfo.EstateSettings.DenyAnonymous)
  752. flags |= RegionFlags.DenyAnonymous;
  753. //DenyIdentified unused
  754. //DenyTransacted unused
  755. if (Scene.RegionInfo.RegionSettings.AllowLandJoinDivide)
  756. flags |= RegionFlags.AllowParcelChanges;
  757. //AbuseEmailToEstateOwner -> block flyover
  758. if (Scene.RegionInfo.EstateSettings.AllowVoice)
  759. flags |= RegionFlags.AllowVoice;
  760. if (Scene.RegionInfo.RegionSettings.BlockShowInSearch)
  761. flags |= RegionFlags.BlockParcelSearch;
  762. if (Scene.RegionInfo.EstateSettings.DenyMinors)
  763. flags |= RegionFlags.DenyAgeUnverified;
  764. if(Scene.RegionInfo.EstateSettings.AllowEnvironmentOverride)
  765. flags |= RegionFlags.AllowEnvironmentOverride;
  766. return (uint)flags;
  767. }
  768. // Region handshake may need a more detailed look
  769. static private readonly byte[] RegionHandshakeHeader = new byte[] {
  770. Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED,
  771. 0, 0, 0, 0, // sequence number
  772. 0, // extra
  773. //0xff, 0xff, 0, 148 // ID 148 (low frequency bigendian)
  774. 0xff, 0xff, 0, 1, 148 // ID 148 (low frequency bigendian) zero encoded
  775. };
  776. public void SendRegionHandshake()
  777. {
  778. GetViewerCaps(); // make sure this is up to date
  779. RegionInfo regionInfo = m_scene.RegionInfo;
  780. RegionSettings regionSettings = regionInfo.RegionSettings;
  781. EstateSettings es = regionInfo.EstateSettings;
  782. bool isEstateManager = m_scene.Permissions.IsEstateManager(m_agentId); // go by oficial path
  783. uint regionFlags = GetRegionFlags();
  784. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  785. Buffer.BlockCopy(RegionHandshakeHeader, 0, buf.Data, 0, 11);
  786. // inline zeroencode
  787. LLUDPZeroEncoder zc = new(buf.Data);
  788. zc.Position = 11;
  789. //RegionInfo Block
  790. //RegionFlags U32
  791. zc.AddUInt(regionFlags);
  792. //SimAccess U8
  793. zc.AddByte(regionInfo.AccessLevel);
  794. //SimName
  795. zc.AddShortString(regionInfo.RegionName, 255);
  796. //SimOwner
  797. zc.AddUUID(es.EstateOwner);
  798. //IsEstateManager
  799. zc.AddByte((byte)(isEstateManager ? 1 : 0));
  800. //WaterHeight
  801. zc.AddFloat((float)regionSettings.WaterHeight); // why is this a double ??
  802. //BillableFactor
  803. zc.AddFloat(es.BillableFactor);
  804. //CacheID
  805. zc.AddUUID(regionSettings.CacheID);
  806. //TerrainBase0
  807. //TerrainBase1
  808. //TerrainBase2
  809. //TerrainBase3
  810. // this seem now obsolete, sending zero uuids
  811. // we should send the basic low resolution default ?
  812. zc.AddZeros(16 * 4);
  813. if(SupportTerrainPBR)
  814. {
  815. //TerrainDetail0
  816. zc.AddUUID(regionSettings.TerrainPBR1);
  817. //TerrainDetail1
  818. zc.AddUUID(regionSettings.TerrainPBR2);
  819. //TerrainDetail2
  820. zc.AddUUID(regionSettings.TerrainPBR3);
  821. //TerrainDetail3
  822. zc.AddUUID(regionSettings.TerrainPBR4);
  823. ViewerFlags |= ViewerFlags.SentTPBR;
  824. }
  825. else
  826. {
  827. //TerrainDetail0
  828. zc.AddUUID(regionSettings.TerrainTexture1);
  829. //TerrainDetail1
  830. zc.AddUUID(regionSettings.TerrainTexture2);
  831. //TerrainDetail2
  832. zc.AddUUID(regionSettings.TerrainTexture3);
  833. //TerrainDetail3
  834. zc.AddUUID(regionSettings.TerrainTexture4);
  835. }
  836. //TerrainStartHeight00
  837. zc.AddFloat((float)regionSettings.Elevation1SW);
  838. //TerrainStartHeight01
  839. zc.AddFloat((float)regionSettings.Elevation1NW);
  840. //TerrainStartHeight10
  841. zc.AddFloat((float)regionSettings.Elevation1SE);
  842. //TerrainStartHeight11
  843. zc.AddFloat((float)regionSettings.Elevation1NE);
  844. //TerrainHeightRange00
  845. zc.AddFloat((float)regionSettings.Elevation2SW);
  846. //TerrainHeightRange01
  847. zc.AddFloat((float)regionSettings.Elevation2NW);
  848. //TerrainHeightRange10
  849. zc.AddFloat((float)regionSettings.Elevation2SE);
  850. //TerrainHeightRange11
  851. zc.AddFloat((float)regionSettings.Elevation2NE);
  852. //RegionInfo2 block
  853. //region ID
  854. zc.AddUUID(regionInfo.RegionID);
  855. //RegionInfo3 block
  856. //CPUClassID
  857. zc.AddInt(9);
  858. //CPURatio
  859. zc.AddInt(1);
  860. // ColoName (string)
  861. // ProductSKU (string)
  862. // both empty strings
  863. zc.AddZeros(2);
  864. //ProductName
  865. zc.AddShortString(regionInfo.RegionType, 255);
  866. //RegionInfo4 block
  867. //RegionFlagsExtended
  868. //zc.AddZeros(1); // if we dont have this else
  869. zc.AddByte(1);
  870. zc.AddUInt64(regionFlags); // we have nothing other base flags
  871. //RegionProtocols
  872. // bit 0 signals server side texture baking
  873. // bit 63 signals more than 6 baked textures support"
  874. zc.AddUInt64(1UL << 63);
  875. buf.DataLength = zc.Finish();
  876. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown);
  877. }
  878. static private readonly byte[] AgentMovementCompleteHeader = new byte[] {
  879. Helpers.MSG_RELIABLE,
  880. 0, 0, 0, 0, // sequence number
  881. 0, // extra
  882. 0xff, 0xff, 0, 250 // ID 250 (low frequency bigendian)
  883. };
  884. public unsafe void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
  885. {
  886. // reset agent update args
  887. m_thisAgentUpdateArgs.CameraAtAxis.X = float.MinValue;
  888. m_thisAgentUpdateArgs.lastUpdateTS = 0;
  889. m_thisAgentUpdateArgs.lastMoveUpdateTS = 0;
  890. m_thisAgentUpdateArgs.ControlFlags = 0;
  891. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  892. byte[] bdata = buf.Data;
  893. //setup header
  894. Buffer.BlockCopy(AgentMovementCompleteHeader, 0, bdata, 0, 10);
  895. fixed(byte* data = bdata)
  896. {
  897. //AgentData block
  898. m_agentId.ToBytes(data + 10); // 26
  899. m_sessionId.ToBytes(data + 26); // 42
  900. //Data block
  901. if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0))
  902. m_startpos.ToBytes(data + 42); //54
  903. else
  904. pos.ToBytes(data + 42); //54
  905. look.ToBytes(data + 54); // 66
  906. //Utils.UInt64ToBytesSafepos(regInfo.RegionHandle, data + 66); // 74
  907. //Utils.UIntToBytesSafepos((uint)Util.UnixTimeSinceEpoch(), data + 74); //78
  908. Utils.UInt64ToBytes(regInfo.RegionHandle, data + 66); // 74
  909. Utils.IntToBytes((int)Util.UnixTimeSinceEpoch(), data + 74); //78
  910. //SimData
  911. int len = m_regionChannelVersion.Length;
  912. if(len == 0)
  913. {
  914. data[78] = 0;
  915. data[79] = 0;
  916. }
  917. else
  918. {
  919. data[78] = (byte)len;
  920. data[79] = (byte)(len >> 8);
  921. Buffer.BlockCopy(m_regionChannelVersion, 0, bdata, 80, len);
  922. }
  923. buf.DataLength = 80 + len;
  924. }
  925. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown);
  926. }
  927. static private readonly byte[] ChatFromSimulatorHeader = new byte[] {
  928. Helpers.MSG_RELIABLE,
  929. 0, 0, 0, 0, // sequence number
  930. 0, // extra
  931. 0xff, 0xff, 0, 139 // ID 139 (low frequency bigendian)
  932. };
  933. public void SendChatMessage(string message, byte chattype, Vector3 fromPos, string fromName,
  934. UUID sourceID, UUID ownerID, byte sourcetype, byte audible)
  935. {
  936. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  937. byte[] data = buf.Data;
  938. //setup header
  939. Buffer.BlockCopy(ChatFromSimulatorHeader, 0, data, 0, 10);
  940. int pos = 11;
  941. int len = Util.osUTF8Getbytes(fromName, data, 11, 255, true);
  942. data[10] = (byte)len;
  943. if (len > 0)
  944. pos += len;
  945. sourceID.ToBytes(data, pos); pos += 16;
  946. ownerID.ToBytes(data, pos); pos += 16;
  947. data[pos++] = sourcetype;
  948. data[pos++] = chattype;
  949. data[pos++] = audible;
  950. fromPos.ToBytes(data, pos); pos += 12;
  951. byte[] msg = Util.StringToBytes1024(message);
  952. len = msg.Length;
  953. if (len == 0)
  954. {
  955. data[pos++] = 0;
  956. data[pos++] = 0;
  957. }
  958. else
  959. {
  960. data[pos++] = (byte)len;
  961. data[pos++] = (byte)(len >> 8);
  962. Buffer.BlockCopy(msg, 0, data, pos, len); pos += len;
  963. }
  964. buf.DataLength = pos;
  965. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown);
  966. }
  967. /// <summary>
  968. /// Send an instant message to this client
  969. /// </summary>
  970. //
  971. static private readonly byte[] ImprovedInstantMessageHeader = new byte[] {
  972. Helpers.MSG_RELIABLE, //| Helpers.MSG_ZEROCODED, not doing spec zeroencode on this
  973. 0, 0, 0, 0, // sequence number
  974. 0, // extra
  975. 0xff, 0xff, 0, 254 // ID 139 (low frequency bigendian)
  976. };
  977. public void SendInstantMessage(GridInstantMessage im)
  978. {
  979. UUID fromAgentID = new(im.fromAgentID);
  980. UUID toAgentID = new(im.toAgentID);
  981. if (!m_scene.Permissions.CanInstantMessage(fromAgentID, toAgentID))
  982. return;
  983. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  984. byte[] data = buf.Data;
  985. //setup header
  986. Buffer.BlockCopy(ImprovedInstantMessageHeader, 0, data, 0, 10);
  987. //agentdata block
  988. fromAgentID.ToBytes(data, 10); // 26
  989. UUID.Zero.ToBytes(data, 26); // 42 sessionID zero?? TO check
  990. int pos = 42;
  991. //MessageBlock
  992. data[pos++] = (byte)((im.fromGroup) ? 1 : 0);
  993. toAgentID.ToBytes(data, pos); pos += 16;
  994. Utils.UIntToBytesSafepos(im.ParentEstateID, data, pos); pos += 4;
  995. (new UUID(im.RegionID)).ToBytes(data, pos); pos += 16;
  996. (im.Position).ToBytes(data, pos); pos += 12;
  997. data[pos++] = im.offline;
  998. data[pos++] = im.dialog;
  999. // this is odd
  1000. if (im.imSessionID == UUID.Zero.Guid)
  1001. (fromAgentID ^ toAgentID).ToBytes(data, pos);
  1002. else
  1003. (new UUID(im.imSessionID)).ToBytes(data, pos);
  1004. pos += 16;
  1005. Utils.UIntToBytesSafepos(im.timestamp, data, pos); pos += 4;
  1006. int len = Util.osUTF8Getbytes(im.fromAgentName, data, pos + 1, 255, true);
  1007. data[pos++] = (byte)len;
  1008. if (len > 0)
  1009. pos += len;
  1010. len = Util.osUTF8Getbytes(im.message, data, pos + 2, 1024, true);
  1011. if (len == 0)
  1012. {
  1013. data[pos++] = 0;
  1014. data[pos++] = 0;
  1015. }
  1016. else
  1017. {
  1018. data[pos++] = (byte)len;
  1019. data[pos++] = (byte)(len >> 8);
  1020. pos += len;
  1021. }
  1022. byte[] tmp = im.binaryBucket;
  1023. if(tmp is null)
  1024. {
  1025. data[pos++] = 0;
  1026. data[pos++] = 0;
  1027. }
  1028. else
  1029. {
  1030. len = tmp.Length;
  1031. if (len == 0)
  1032. {
  1033. data[pos++] = 0;
  1034. data[pos++] = 0;
  1035. }
  1036. else
  1037. {
  1038. data[pos++] = (byte)len;
  1039. data[pos++] = (byte)(len >> 8);
  1040. Buffer.BlockCopy(tmp, 0, data, pos, len); pos += len;
  1041. }
  1042. }
  1043. //EstateBlock does not seem in use TODO
  1044. //Utils.UIntToBytesSafepos(m_scene.RegionInfo.EstateSettings.EstateID, data, pos); pos += 4;
  1045. data[pos++] = 0;
  1046. data[pos++] = 0;
  1047. data[pos++] = 0;
  1048. data[pos++] = 0;
  1049. buf.DataLength = pos;
  1050. //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown, null, false, true);
  1051. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown);
  1052. }
  1053. static private readonly byte[] GenericMessageHeader = new byte[] {
  1054. Helpers.MSG_RELIABLE, //| Helpers.MSG_ZEROCODED, not doing spec zeroencode on this
  1055. 0, 0, 0, 0, // sequence number
  1056. 0, // extra
  1057. 0xff, 0xff, 1, 5 // ID 261 (low frequency bigendian)
  1058. };
  1059. public void SendGenericMessage(string method, UUID invoice, List<string> message)
  1060. {
  1061. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  1062. byte[] data = buf.Data;
  1063. //setup header
  1064. Buffer.BlockCopy(GenericMessageHeader, 0, data, 0, 10);
  1065. //agentdata block
  1066. m_agentId.ToBytes(data, 10); // 26
  1067. m_sessionId.ToBytes(data, 26); // 42 sessionID zero?? TO check
  1068. UUID.Zero.ToBytes(data, 42); // 58
  1069. int pos = 58;
  1070. //method block
  1071. int len = Util.osUTF8Getbytes(method, data, pos + 1, 255, true);
  1072. data[pos++] = (byte)len;
  1073. if (len > 0)
  1074. pos += len;
  1075. invoice.ToBytes(data, pos); pos += 16;
  1076. //ParamList block
  1077. if (message.Count == 0)
  1078. {
  1079. data[pos++] = 0;
  1080. buf.DataLength = pos;
  1081. //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true);
  1082. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  1083. return;
  1084. }
  1085. int countpos = pos;
  1086. ++pos;
  1087. int count = 0;
  1088. for(int indx = 0; indx < message.Count; ++indx)
  1089. {
  1090. len = Util.osUTF8Getbytes(message[indx], data, pos + 1, 255, true);
  1091. data[pos++] = (byte)len;
  1092. if (len > 0)
  1093. pos += len;
  1094. if (pos > LLUDPServer.MAXPAYLOAD - 100)
  1095. {
  1096. data[countpos] = (byte)count;
  1097. buf.DataLength = pos;
  1098. //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true);
  1099. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  1100. UDPPacketBuffer newbuf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  1101. Buffer.BlockCopy(data, 0, newbuf.Data, 0, countpos);
  1102. buf = newbuf;
  1103. data = buf.Data;
  1104. pos = countpos + 1;
  1105. count = 1;
  1106. }
  1107. else
  1108. ++count;
  1109. }
  1110. if (count > 0)
  1111. {
  1112. data[countpos] = (byte)count;
  1113. buf.DataLength = pos;
  1114. //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true);
  1115. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  1116. }
  1117. }
  1118. public void SendGenericMessage(string method, UUID invoice, List<byte[]> message)
  1119. {
  1120. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  1121. byte[] data = buf.Data;
  1122. //setup header
  1123. Buffer.BlockCopy(GenericMessageHeader, 0, data, 0, 10);
  1124. //agentdata block
  1125. m_agentId.ToBytes(data, 10); // 26
  1126. m_sessionId.ToBytes(data, 26); // 42 sessionID zero?? TO check
  1127. UUID.Zero.ToBytes(data, 42); // 58
  1128. int pos = 58;
  1129. //method block
  1130. int len = Util.osUTF8Getbytes(method, data, pos + 1, 255, true);
  1131. data[pos++] = (byte)len;
  1132. if (len > 0)
  1133. pos += len;
  1134. invoice.ToBytes(data, pos); pos += 16;
  1135. //ParamList block
  1136. if (message.Count == 0)
  1137. {
  1138. data[pos++] = 0;
  1139. buf.DataLength = pos;
  1140. //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true);
  1141. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  1142. return;
  1143. }
  1144. int countpos = pos;
  1145. ++pos;
  1146. byte[] val;
  1147. int count = 0;
  1148. for (int indx = 0; indx < message.Count; ++indx)
  1149. {
  1150. val = message[indx];
  1151. len = val.Length;
  1152. if(len > 255)
  1153. len = 255;
  1154. if (pos + len >= LLUDPServer.MAXPAYLOAD)
  1155. {
  1156. data[countpos] = (byte)count;
  1157. buf.DataLength = pos;
  1158. //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true);
  1159. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  1160. UDPPacketBuffer newbuf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  1161. Buffer.BlockCopy(data, 0, newbuf.Data, 0, countpos);
  1162. buf = newbuf;
  1163. data = buf.Data;
  1164. pos = countpos + 1;
  1165. count = 1;
  1166. }
  1167. else
  1168. ++count;
  1169. data[pos++] = (byte)len;
  1170. if (len > 0)
  1171. Buffer.BlockCopy(val, 0, data, pos, len); pos += len;
  1172. }
  1173. if (count > 0)
  1174. {
  1175. data[countpos] = (byte)count;
  1176. buf.DataLength = pos;
  1177. //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true);
  1178. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  1179. }
  1180. }
  1181. public void SendGroupActiveProposals(UUID groupID, UUID transactionID, GroupActiveProposals[] Proposals)
  1182. {
  1183. /* not in use and broken
  1184. GroupActiveProposalItemReplyPacket GAPIRP = new();
  1185. GAPIRP.AgentData.AgentID = m_agentId;
  1186. GAPIRP.AgentData.GroupID = groupID;
  1187. GAPIRP.TransactionData.TransactionID = transactionID;
  1188. if (Proposals.Length == 0)
  1189. {
  1190. GAPIRP.TransactionData.TotalNumItems = 1;
  1191. GAPIRP.ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock[]
  1192. {
  1193. new GroupActiveProposalItemReplyPacket.ProposalDataBlock()
  1194. {
  1195. VoteCast = Utils.StringToBytes("false"),
  1196. VoteID = UUID.Zero,
  1197. VoteInitiator = UUID.Zero,
  1198. Majority = 0,
  1199. Quorum = 0,
  1200. TerseDateID = Array.Empty<byte>(),
  1201. StartDateTime = Array.Empty<byte>(),
  1202. EndDateTime = Array.Empty<byte>(),
  1203. ProposalText = Array.Empty<byte>(),
  1204. AlreadyVoted = false
  1205. }
  1206. };
  1207. }
  1208. else
  1209. {
  1210. GAPIRP.TransactionData.TotalNumItems = (uint)Proposals.Length;
  1211. GAPIRP.ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock[Proposals.Length];
  1212. int i = 0;
  1213. foreach (GroupActiveProposals Proposal in Proposals)
  1214. {
  1215. GAPIRP.ProposalData[i++] = new GroupActiveProposalItemReplyPacket.ProposalDataBlock()
  1216. {
  1217. VoteCast = Utils.StringToBytes("false"),
  1218. VoteID = new UUID(Proposal.VoteID),
  1219. VoteInitiator = new UUID(Proposal.VoteInitiator),
  1220. Majority = Convert.ToSingle(Proposal.Majority),
  1221. Quorum = Convert.ToInt32(Proposal.Quorum),
  1222. TerseDateID = Utils.StringToBytes(Proposal.TerseDateID),
  1223. StartDateTime = Utils.StringToBytes(Proposal.StartDateTime),
  1224. EndDateTime = Utils.StringToBytes(Proposal.EndDateTime),
  1225. ProposalText = Utils.StringToBytes(Proposal.ProposalText),
  1226. AlreadyVoted = false
  1227. };
  1228. }
  1229. }
  1230. OutPacket(GAPIRP, ThrottleOutPacketType.Task);
  1231. */
  1232. }
  1233. public void SendGroupVoteHistory(UUID groupID, UUID transactionID, GroupVoteHistory[] Votes)
  1234. {
  1235. /* not in use and broken
  1236. GroupVoteHistoryItemReplyPacket GVHIRP = new GroupVoteHistoryItemReplyPacket();
  1237. GVHIRP.AgentData.AgentID = m_agentId;
  1238. GVHIRP.AgentData.GroupID = groupID;
  1239. GVHIRP.TransactionData.TransactionID = transactionID;
  1240. if (Votes.Length == 0)
  1241. {
  1242. GVHIRP.TransactionData.TotalNumItems = 0;
  1243. GVHIRP.HistoryItemData.VoteID = UUID.Zero;
  1244. GVHIRP.HistoryItemData.VoteInitiator = UUID.Zero;
  1245. GVHIRP.HistoryItemData.Majority = 0;
  1246. GVHIRP.HistoryItemData.Quorum = 0;
  1247. GVHIRP.HistoryItemData.TerseDateID = Array.Empty<byte>();
  1248. GVHIRP.HistoryItemData.StartDateTime = Array.Empty<byte>();
  1249. GVHIRP.HistoryItemData.EndDateTime = Array.Empty<byte>();
  1250. GVHIRP.HistoryItemData.VoteType = Array.Empty<byte>();
  1251. GVHIRP.HistoryItemData.VoteResult = Array.Empty<byte>();
  1252. GVHIRP.HistoryItemData.ProposalText = Array.Empty<byte>();
  1253. GVHIRP.VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock[]
  1254. {
  1255. new GroupVoteHistoryItemReplyPacket.VoteItemBlock()
  1256. {
  1257. CandidateID = UUID.Zero,
  1258. NumVotes = 0, //TODO: FIX THIS!!!
  1259. VoteCast = Utils.StringToBytes("No")
  1260. }
  1261. };
  1262. }
  1263. else
  1264. {
  1265. GVHIRP.TransactionData.TotalNumItems = (uint)Votes.Length;
  1266. int i = 0;
  1267. foreach (GroupVoteHistory Vote in Votes)
  1268. {
  1269. GVHIRP.HistoryItemData.VoteID = new UUID(Vote.VoteID);
  1270. GVHIRP.HistoryItemData.VoteInitiator = new UUID(Vote.VoteInitiator);
  1271. GVHIRP.HistoryItemData.Majority = (float)Convert.ToInt32(Vote.Majority);
  1272. GVHIRP.HistoryItemData.Quorum = Convert.ToInt32(Vote.Quorum);
  1273. GVHIRP.HistoryItemData.TerseDateID = Utils.StringToBytes(Vote.TerseDateID);
  1274. GVHIRP.HistoryItemData.StartDateTime = Utils.StringToBytes(Vote.StartDateTime);
  1275. GVHIRP.HistoryItemData.EndDateTime = Utils.StringToBytes(Vote.EndDateTime);
  1276. GVHIRP.HistoryItemData.VoteType = Utils.StringToBytes(Vote.VoteType);
  1277. GVHIRP.HistoryItemData.VoteResult = Utils.StringToBytes(Vote.VoteResult);
  1278. GVHIRP.HistoryItemData.ProposalText = Utils.StringToBytes(Vote.ProposalText);
  1279. GroupVoteHistoryItemReplyPacket.VoteItemBlock VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock();
  1280. GVHIRP.VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock[1];
  1281. VoteItem.CandidateID = UUID.Zero;
  1282. VoteItem.NumVotes = 0; //TODO: FIX THIS!!!
  1283. VoteItem.VoteCast = Utils.StringToBytes("Yes");
  1284. GVHIRP.VoteItem[i] = VoteItem;
  1285. i++;
  1286. }
  1287. }
  1288. OutPacket(GVHIRP, ThrottleOutPacketType.Task);
  1289. */
  1290. }
  1291. public void SendGroupAccountingDetails(IClientAPI sender,UUID groupID, UUID transactionID, UUID sessionID, int amt)
  1292. {
  1293. GroupAccountDetailsReplyPacket GADRP = new();
  1294. GADRP.AgentData.AgentID = sender.AgentId;
  1295. GADRP.AgentData.GroupID = groupID;
  1296. GADRP.MoneyData.CurrentInterval = 0;
  1297. GADRP.MoneyData.IntervalDays = 7;
  1298. GADRP.MoneyData.RequestID = transactionID;
  1299. GADRP.MoneyData.StartDate = Utils.StringToBytes(DateTime.Today.ToString());
  1300. GADRP.HistoryData = new GroupAccountDetailsReplyPacket.HistoryDataBlock[]
  1301. {
  1302. new GroupAccountDetailsReplyPacket.HistoryDataBlock()
  1303. {
  1304. Amount = amt,
  1305. Description = Array.Empty<byte>()
  1306. }
  1307. };
  1308. OutPacket(GADRP, ThrottleOutPacketType.Task);
  1309. }
  1310. public void SendGroupAccountingSummary(IClientAPI sender,UUID groupID, uint moneyAmt, int totalTier, int usedTier)
  1311. {
  1312. GroupAccountSummaryReplyPacket GASRP =
  1313. (GroupAccountSummaryReplyPacket)PacketPool.Instance.GetPacket(
  1314. PacketType.GroupAccountSummaryReply);
  1315. GASRP.AgentData.AgentID = sender.AgentId;
  1316. GASRP.AgentData.GroupID = groupID;
  1317. GASRP.MoneyData.Balance = (int)moneyAmt;
  1318. GASRP.MoneyData.TotalCredits = totalTier;
  1319. GASRP.MoneyData.TotalDebits = usedTier;
  1320. GASRP.MoneyData.StartDate = new byte[1];
  1321. GASRP.MoneyData.CurrentInterval = 1;
  1322. GASRP.MoneyData.GroupTaxCurrent = 0;
  1323. GASRP.MoneyData.GroupTaxEstimate = 0;
  1324. GASRP.MoneyData.IntervalDays = 0;
  1325. GASRP.MoneyData.LandTaxCurrent = 0;
  1326. GASRP.MoneyData.LandTaxEstimate = 0;
  1327. GASRP.MoneyData.LastTaxDate = new byte[1];
  1328. GASRP.MoneyData.LightTaxCurrent = 0;
  1329. GASRP.MoneyData.TaxDate = new byte[1];
  1330. GASRP.MoneyData.RequestID = sender.AgentId;
  1331. GASRP.MoneyData.ParcelDirFeeEstimate = 0;
  1332. GASRP.MoneyData.ParcelDirFeeCurrent = 0;
  1333. GASRP.MoneyData.ObjectTaxEstimate = 0;
  1334. GASRP.MoneyData.NonExemptMembers = 0;
  1335. GASRP.MoneyData.ObjectTaxCurrent = 0;
  1336. GASRP.MoneyData.LightTaxEstimate = 0;
  1337. OutPacket(GASRP, ThrottleOutPacketType.Task);
  1338. }
  1339. public void SendGroupTransactionsSummaryDetails(IClientAPI sender,UUID groupID, UUID transactionID, UUID sessionID, int amt)
  1340. {
  1341. // bad !
  1342. GroupAccountTransactionsReplyPacket GATRP =
  1343. (GroupAccountTransactionsReplyPacket)PacketPool.Instance.GetPacket(
  1344. PacketType.GroupAccountTransactionsReply);
  1345. GATRP.AgentData.AgentID = sender.AgentId;
  1346. GATRP.AgentData.GroupID = groupID;
  1347. GATRP.MoneyData.CurrentInterval = 0;
  1348. GATRP.MoneyData.IntervalDays = 7;
  1349. GATRP.MoneyData.RequestID = transactionID;
  1350. GATRP.MoneyData.StartDate = Utils.StringToBytes(DateTime.Today.ToString());
  1351. GATRP.HistoryData = new GroupAccountTransactionsReplyPacket.HistoryDataBlock[]
  1352. {
  1353. new GroupAccountTransactionsReplyPacket.HistoryDataBlock()
  1354. {
  1355. Amount = amt,
  1356. Item = Array.Empty<byte>(),
  1357. Time = Array.Empty<byte>(),
  1358. Type = 0,
  1359. User = Array.Empty<byte>(),
  1360. }
  1361. };
  1362. OutPacket(GATRP, ThrottleOutPacketType.Task);
  1363. }
  1364. public virtual bool CanSendLayerData()
  1365. {
  1366. int n = m_udpClient.GetPacketsQueuedCount(ThrottleOutPacketType.Land);
  1367. return n <= 128;
  1368. }
  1369. /// <summary>
  1370. /// Send the region heightmap to the client
  1371. /// This method is only called when not doing intellegent terrain patch sending and
  1372. /// is only called when the scene presence is initially created and sends all of the
  1373. /// region's patches to the client.
  1374. /// </summary>
  1375. /// <param name="map">heightmap</param>
  1376. public virtual void SendLayerData()
  1377. {
  1378. Util.FireAndForget(DoSendLayerData, null, "LLClientView.DoSendLayerData");
  1379. }
  1380. /// <summary>
  1381. /// Send terrain layer information to the client.
  1382. /// </summary>
  1383. /// <param name="o"></param>
  1384. private void DoSendLayerData(object o)
  1385. {
  1386. TerrainData map = m_scene.Heightmap.GetTerrainData();
  1387. try
  1388. {
  1389. // Send LayerData in a spiral pattern. Fun!
  1390. SendLayerTopRight(0, 0, map.SizeX / Constants.TerrainPatchSize - 1, map.SizeY / Constants.TerrainPatchSize - 1);
  1391. }
  1392. catch (Exception e)
  1393. {
  1394. m_log.Error("[CLIENT]: SendLayerData() Failed with exception: " + e.Message, e);
  1395. }
  1396. }
  1397. private void SendLayerTopRight(int x1, int y1, int x2, int y2)
  1398. {
  1399. int[] p = new int[2];
  1400. // Row
  1401. p[1] = y1;
  1402. for (int i = x1; i <= x2; ++i)
  1403. {
  1404. p[0] = i;
  1405. SendLayerData(p);
  1406. }
  1407. // Column
  1408. p[0] = x2;
  1409. for (int j = y1 + 1; j <= y2; ++j)
  1410. {
  1411. p[1] = j;
  1412. SendLayerData(p);
  1413. }
  1414. if (x2 - x1 > 0 && y2 - y1 > 0)
  1415. SendLayerBottomLeft(x1, y1 + 1, x2 - 1, y2);
  1416. }
  1417. void SendLayerBottomLeft(int x1, int y1, int x2, int y2)
  1418. {
  1419. int[] p = new int[2];
  1420. // Row in reverse
  1421. p[1] = y2;
  1422. for (int i = x2; i >= x1; --i)
  1423. {
  1424. p[0] = i;
  1425. SendLayerData(p);
  1426. }
  1427. // Column in reverse
  1428. p[0] = x1;
  1429. for (int j = y2 - 1; j >= y1; --j)
  1430. {
  1431. p[1] = j;
  1432. SendLayerData(p);
  1433. }
  1434. if (x2 - x1 > 0 && y2 - y1 > 0)
  1435. SendLayerTopRight(x1 + 1, y1, x2, y2 - 1);
  1436. }
  1437. static private readonly byte[] TerrainPacketHeader = new byte[] {
  1438. Helpers.MSG_RELIABLE, // zero code is not as spec
  1439. 0, 0, 0, 0, // sequence number
  1440. 0, // extra
  1441. 11, // ID (high frequency)
  1442. };
  1443. private const int END_OF_PATCHES = 97;
  1444. private const int STRIDE = 264;
  1445. public void SendLayerData(int[] map)
  1446. {
  1447. if(map is null)
  1448. return;
  1449. try
  1450. {
  1451. TerrainData terrData = m_scene.Heightmap.GetTerrainData();
  1452. byte landPacketType = (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) ?
  1453. (byte)TerrainPatch.LayerType.LandExtended : (byte)TerrainPatch.LayerType.Land;
  1454. int numberPatchs = map.Length / 2;
  1455. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  1456. byte[] data = buf.Data;
  1457. Buffer.BlockCopy(TerrainPacketHeader, 0, data, 0, 7);
  1458. data[7] = landPacketType;
  1459. //data[8] and data[9] == datablock size to fill later
  1460. data[10] = 0; // BitPack needs this on reused packets
  1461. // start data
  1462. BitPack bitpack = new(data, 10);
  1463. bitpack.PackBits(STRIDE, 16);
  1464. bitpack.PackBitsFromByte(16);
  1465. bitpack.PackBitsFromByte(landPacketType);
  1466. int s;
  1467. int datasize = 0;
  1468. for (int i = 0; i < numberPatchs; i++)
  1469. {
  1470. s = 2 * i;
  1471. OpenSimTerrainCompressor.CreatePatchFromTerrainData(bitpack, terrData, map[s], map[s + 1]);
  1472. if (bitpack.BytePos > 900 && i != numberPatchs - 1)
  1473. {
  1474. //finish this packet
  1475. bitpack.PackBitsFromByte(END_OF_PATCHES);
  1476. // fix the datablock length
  1477. datasize = bitpack.BytePos - 9;
  1478. data[8] = (byte)datasize;
  1479. data[9] = (byte)(datasize >> 8);
  1480. buf.DataLength = bitpack.BytePos + 1;
  1481. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land);
  1482. // start another
  1483. buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  1484. data = buf.Data;
  1485. Buffer.BlockCopy(TerrainPacketHeader, 0, data, 0, 7);
  1486. data[7] = landPacketType;
  1487. //data[8] and data[9] == datablock size to fill later
  1488. data[10] = 0; // BitPack needs this
  1489. // start data
  1490. bitpack = new BitPack(data, 10);
  1491. bitpack.PackBits(STRIDE, 16);
  1492. bitpack.PackBitsFromByte(16);
  1493. bitpack.PackBitsFromByte(landPacketType);
  1494. }
  1495. }
  1496. bitpack.PackBitsFromByte(END_OF_PATCHES);
  1497. datasize = bitpack.BytePos - 9;
  1498. data[8] = (byte)datasize;
  1499. data[9] = (byte)(datasize >> 8);
  1500. buf.DataLength = bitpack.BytePos + 1;
  1501. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land);
  1502. }
  1503. catch (Exception e)
  1504. {
  1505. m_log.Error("[CLIENT]: SendLayerData() Failed with exception: " + e.Message, e);
  1506. }
  1507. }
  1508. private static void DebugSendingPatches(string pWho, int[] pX, int[] pY)
  1509. {
  1510. if (m_log.IsDebugEnabled)
  1511. {
  1512. int numPatches = pX.Length;
  1513. string Xs = "";
  1514. string Ys = "";
  1515. for (int pp = 0; pp < numPatches; pp++)
  1516. {
  1517. Xs += String.Format("{0}", (int)pX[pp]) + ",";
  1518. Ys += String.Format("{0}", (int)pY[pp]) + ",";
  1519. }
  1520. m_log.DebugFormat("{0} {1}: numPatches={2}, X={3}, Y={4}", LogHeader, pWho, numPatches, Xs, Ys);
  1521. }
  1522. }
  1523. // wind caching
  1524. private readonly static Dictionary<ulong,int> lastWindVersion = new();
  1525. private readonly static Dictionary<ulong,List<LayerDataPacket>> lastWindPackets = new();
  1526. /// <summary>
  1527. /// Send the wind matrix to the client
  1528. /// </summary>
  1529. /// <param name="windSpeeds">16x16 array of wind speeds</param>
  1530. public virtual void SendWindData(int version, Vector2[] windSpeeds)
  1531. {
  1532. //Vector2[] windSpeeds = (Vector2[])o;
  1533. ulong handle = this.Scene.RegionInfo.RegionHandle;
  1534. bool isNewData;
  1535. lock(lastWindPackets)
  1536. {
  1537. if(!lastWindVersion.ContainsKey(handle) ||
  1538. !lastWindPackets.ContainsKey(handle))
  1539. {
  1540. lastWindVersion[handle] = 0;
  1541. lastWindPackets[handle] = new List<LayerDataPacket>();
  1542. isNewData = true;
  1543. }
  1544. else
  1545. isNewData = lastWindVersion[handle] != version;
  1546. }
  1547. if(isNewData)
  1548. {
  1549. TerrainPatch[] patches = new TerrainPatch[2];
  1550. patches[0] = new TerrainPatch { Data = new float[16 * 16] };
  1551. patches[1] = new TerrainPatch { Data = new float[16 * 16] };
  1552. for (int x = 0; x < 16 * 16; x++)
  1553. {
  1554. patches[0].Data[x] = windSpeeds[x].X;
  1555. patches[1].Data[x] = windSpeeds[x].Y;
  1556. }
  1557. // neither we or viewers have extended wind
  1558. byte layerType = (byte)TerrainPatch.LayerType.Wind;
  1559. LayerDataPacket layerpack =
  1560. OpenSimTerrainCompressor.CreateLayerDataPacketStandardSize(
  1561. patches, layerType);
  1562. layerpack.Header.Zerocoded = true;
  1563. lock(lastWindPackets)
  1564. {
  1565. lastWindPackets[handle].Clear();
  1566. lastWindPackets[handle].Add(layerpack);
  1567. lastWindVersion[handle] = version;
  1568. }
  1569. }
  1570. lock(lastWindPackets)
  1571. foreach(LayerDataPacket pkt in lastWindPackets[handle])
  1572. OutPacket(pkt, ThrottleOutPacketType.Wind);
  1573. }
  1574. /// <summary>
  1575. /// Tell the client that the given neighbour region is ready to receive a child agent.
  1576. /// </summary>
  1577. public virtual void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourEndPoint)
  1578. {
  1579. byte[] byteIP = neighbourEndPoint.Address.GetAddressBytes();
  1580. uint neighbourIP = (uint)byteIP[3] << 24 |
  1581. (uint)byteIP[2] << 16 |
  1582. (uint)byteIP[1] << 8 |
  1583. (uint)byteIP[0];
  1584. ushort neighbourPort = (ushort)neighbourEndPoint.Port;
  1585. EnableSimulatorPacket enablesimpacket = new();
  1586. enablesimpacket.SimulatorInfo.Handle = neighbourHandle;
  1587. enablesimpacket.SimulatorInfo.IP = neighbourIP;
  1588. enablesimpacket.SimulatorInfo.Port = neighbourPort;
  1589. enablesimpacket.Header.Reliable = true; // ESP's should be reliable.
  1590. OutPacket(enablesimpacket, ThrottleOutPacketType.Task);
  1591. }
  1592. public AgentCircuitData RequestClientInfo()
  1593. {
  1594. AgentCircuitData agentData = new()
  1595. {
  1596. AgentID = m_agentId,
  1597. SessionID = m_sessionId,
  1598. SecureSessionID = SecureSessionId,
  1599. circuitcode = m_circuitCode,
  1600. child = false,
  1601. firstname = m_firstName,
  1602. lastname = m_lastName
  1603. };
  1604. ICapabilitiesModule capsModule = m_scene.RequestModuleInterface<ICapabilitiesModule>();
  1605. if (capsModule is not null) // can happen when shutting down.
  1606. {
  1607. agentData.CapsPath = capsModule.GetCapsPath(m_agentId);
  1608. agentData.ChildrenCapSeeds = new Dictionary<ulong, string>(capsModule.GetChildrenSeeds(m_agentId));
  1609. }
  1610. return agentData;
  1611. }
  1612. public virtual void CrossRegion(ulong newRegionHandle, Vector3 pos, Vector3 lookAt, IPEndPoint externalIPEndPoint,
  1613. string capsURL)
  1614. {
  1615. Vector3 look = new(lookAt.X * 10, lookAt.Y * 10, lookAt.Z * 10);
  1616. byte[] byteIP = externalIPEndPoint.Address.GetAddressBytes();
  1617. uint externalIP = (uint)byteIP[3] << 24 |
  1618. (uint)byteIP[2] << 16 |
  1619. (uint)byteIP[1] << 8 |
  1620. (uint)byteIP[0];
  1621. CrossedRegionPacket newSimPack = new();
  1622. newSimPack.AgentData.AgentID = m_agentId;
  1623. newSimPack.AgentData.SessionID = m_sessionId;
  1624. newSimPack.Info.Position = pos;
  1625. newSimPack.Info.LookAt = look;
  1626. newSimPack.RegionData.RegionHandle = newRegionHandle;
  1627. newSimPack.RegionData.SimIP = externalIP;
  1628. newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port;
  1629. newSimPack.RegionData.SeedCapability = Util.StringToBytes256(capsURL);
  1630. // Hack to get this out immediately and skip throttles
  1631. OutPacket(newSimPack, ThrottleOutPacketType.Unknown);
  1632. }
  1633. static private readonly byte[] MapBlockItemHeader = new byte[] {
  1634. Helpers.MSG_RELIABLE,
  1635. 0, 0, 0, 0, // sequence number
  1636. 0, // extra
  1637. 0xff, 0xff, 1, 155 // ID 411 (low frequency bigendian)
  1638. };
  1639. public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags)
  1640. {
  1641. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  1642. byte[] data = buf.Data;
  1643. //setup header and agentinfo block
  1644. Buffer.BlockCopy(MapBlockItemHeader, 0, data, 0, 10);
  1645. m_agentId.ToBytes(data, 10); // 26
  1646. Utils.UIntToBytesSafepos(flags, data, 26); // 30
  1647. //RequestData block
  1648. Utils.UIntToBytesSafepos(mapitemtype, data, 30); // 34
  1649. int countpos = 34;
  1650. int pos = 35;
  1651. int lastpos;
  1652. int capacity = LLUDPServer.MAXPAYLOAD - pos;
  1653. int count = 0;
  1654. mapItemReply mr;
  1655. for (int k = 0; k < replies.Length; ++k)
  1656. {
  1657. lastpos = pos;
  1658. mr = replies[k];
  1659. Utils.UIntToBytesSafepos(mr.x, data, pos); pos += 4;
  1660. Utils.UIntToBytesSafepos(mr.y, data, pos); pos += 4;
  1661. mr.id.ToBytes(data, pos); pos += 16;
  1662. Utils.IntToBytesSafepos(mr.Extra, data, pos); pos += 4;
  1663. Utils.IntToBytesSafepos(mr.Extra2, data, pos); pos += 4;
  1664. int len = Util.osUTF8Getbytes(mr.name, data, pos + 1, 255, true);
  1665. data[pos++] = (byte)len;
  1666. if (len > 0)
  1667. pos += len;
  1668. if (pos < capacity)
  1669. ++count;
  1670. else
  1671. {
  1672. // prepare next packet
  1673. UDPPacketBuffer newbuf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  1674. Buffer.BlockCopy(data, 0, newbuf.Data, 0, 34);
  1675. // copy the block we already did
  1676. int alreadyDone = pos - lastpos;
  1677. Buffer.BlockCopy(data, lastpos, newbuf.Data, 35, alreadyDone); // 34 is datablock size
  1678. // finish current
  1679. data[countpos] = (byte)count;
  1680. buf.DataLength = lastpos;
  1681. // send it
  1682. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land);
  1683. buf = newbuf;
  1684. data = buf.Data;
  1685. pos = alreadyDone + 35;
  1686. capacity = LLUDPServer.MAXPAYLOAD - pos;
  1687. count = 1;
  1688. }
  1689. }
  1690. if (count > 0)
  1691. {
  1692. data[countpos] = (byte)count;
  1693. buf.DataLength = pos;
  1694. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land);
  1695. }
  1696. }
  1697. static private readonly byte[] MapBlockReplyHeader = new byte[] {
  1698. Helpers.MSG_RELIABLE,
  1699. 0, 0, 0, 0, // sequence number
  1700. 0, // extra
  1701. 0xff, 0xff, 1, 153 // ID 409 (low frequency bigendian)
  1702. };
  1703. public void SendMapBlock(List<MapBlockData> mapBlocks, uint flags)
  1704. {
  1705. ushort[] sizes = new ushort[2 * mapBlocks.Count];
  1706. bool needSizes = false;
  1707. int sizesptr = 0;
  1708. // check if we will need sizes block and get them aside
  1709. int count = 0;
  1710. ushort ut;
  1711. MapBlockData md;
  1712. for (int indx = 0; indx < mapBlocks.Count; ++indx)
  1713. {
  1714. md = mapBlocks[indx];
  1715. ut = md.SizeX;
  1716. sizes[count++] = ut;
  1717. if (ut > 256)
  1718. needSizes = true;
  1719. ut = md.SizeY;
  1720. sizes[count++] = ut;
  1721. if (ut > 256)
  1722. needSizes = true;
  1723. }
  1724. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  1725. byte[] data = buf.Data;
  1726. //setup header and agentinfo block
  1727. Buffer.BlockCopy(MapBlockReplyHeader, 0, data, 0, 10);
  1728. m_agentId.ToBytes(data, 10); // 26
  1729. Utils.UIntToBytesSafepos(flags, data, 26); // 30
  1730. int countpos = 30;
  1731. int pos = 31;
  1732. int lastpos;
  1733. int capacity = LLUDPServer.MAXPAYLOAD - pos;
  1734. count = 0;
  1735. for (int indx = 0; indx < mapBlocks.Count; ++indx)
  1736. {
  1737. md = mapBlocks[indx];
  1738. lastpos = pos;
  1739. Utils.UInt16ToBytes(md.X, data, pos); pos += 2;
  1740. Utils.UInt16ToBytes(md.Y, data, pos); pos += 2;
  1741. int len = Util.osUTF8Getbytes(md.Name, data, pos + 1, 255, true);
  1742. data[pos++] = (byte)len;
  1743. if (len > 0)
  1744. pos += len;
  1745. data[pos++] = md.Access;
  1746. Utils.UIntToBytesSafepos(md.RegionFlags, data, pos); pos += 4;
  1747. data[pos++] = md.WaterHeight;
  1748. data[pos++] = md.Agents;
  1749. md.MapImageId.ToBytes(data, pos); pos += 16;
  1750. if(needSizes)
  1751. capacity -= 4; // 2 shorts per entry
  1752. if(pos < capacity)
  1753. ++count;
  1754. else
  1755. {
  1756. // prepare next packet
  1757. UDPPacketBuffer newbuf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  1758. Buffer.BlockCopy(data, 0, newbuf.Data, 0, 30);
  1759. // copy the block we already did
  1760. int alreadyDone = pos - lastpos;
  1761. Buffer.BlockCopy(data, lastpos, newbuf.Data, 31, alreadyDone); // 30 is datablock size
  1762. // finish current
  1763. data[countpos] = (byte)count;
  1764. if (needSizes)
  1765. {
  1766. data[lastpos++] = (byte)count;
  1767. while (--count >= 0)
  1768. {
  1769. Utils.UInt16ToBytes(sizes[sizesptr++], data, lastpos); lastpos += 2;
  1770. Utils.UInt16ToBytes(sizes[sizesptr++], data, lastpos); lastpos += 2;
  1771. }
  1772. }
  1773. else
  1774. data[lastpos++] = 0;
  1775. buf.DataLength = lastpos;
  1776. // send it
  1777. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land);
  1778. buf = newbuf;
  1779. data = buf.Data;
  1780. pos = alreadyDone + 31;
  1781. capacity = LLUDPServer.MAXPAYLOAD - pos;
  1782. if (needSizes)
  1783. capacity -= 4; // 2 shorts per entry
  1784. count = 1;
  1785. }
  1786. }
  1787. if (count > 0)
  1788. {
  1789. data[countpos] = (byte)count;
  1790. if (needSizes)
  1791. {
  1792. data[pos++] = (byte)count;
  1793. while (--count >= 0)
  1794. {
  1795. Utils.UInt16ToBytes(sizes[sizesptr++], data, pos); pos += 2;
  1796. Utils.UInt16ToBytes(sizes[sizesptr++], data, pos); pos += 2;
  1797. }
  1798. }
  1799. else
  1800. data[pos++] = 0;
  1801. buf.DataLength = pos;
  1802. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land);
  1803. }
  1804. }
  1805. public void SendLocalTeleport(Vector3 position, Vector3 lookAt, uint flags)
  1806. {
  1807. TeleportLocalPacket tpLocal = (TeleportLocalPacket)PacketPool.Instance.GetPacket(PacketType.TeleportLocal);
  1808. tpLocal.Info.AgentID = m_agentId;
  1809. tpLocal.Info.TeleportFlags = flags;
  1810. tpLocal.Info.LocationID = 2;
  1811. tpLocal.Info.LookAt = lookAt;
  1812. tpLocal.Info.Position = position;
  1813. // Hack to get this out immediately and skip throttles
  1814. OutPacket(tpLocal, ThrottleOutPacketType.Unknown);
  1815. }
  1816. public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint newRegionEndPoint, uint locationID,
  1817. uint flags, string capsURL)
  1818. {
  1819. TeleportFinishPacket teleport = new();
  1820. teleport.Info.AgentID = m_agentId;
  1821. teleport.Info.RegionHandle = regionHandle;
  1822. teleport.Info.SimAccess = simAccess;
  1823. teleport.Info.SeedCapability = Util.StringToBytes256(capsURL);
  1824. byte[] byteIP = newRegionEndPoint.Address.GetAddressBytes();
  1825. teleport.Info.SimIP = (uint)byteIP[3] << 24 |
  1826. (uint)byteIP[2] << 16 |
  1827. (uint)byteIP[1] << 8 |
  1828. (uint)byteIP[0];
  1829. teleport.Info.SimPort = (ushort)newRegionEndPoint.Port;
  1830. teleport.Info.LocationID = 4;
  1831. teleport.Info.TeleportFlags = 1 << 4;
  1832. // Hack to get this out immediately and skip throttles.
  1833. OutPacket(teleport, ThrottleOutPacketType.Unknown);
  1834. }
  1835. /// <summary>
  1836. /// Inform the client that a teleport attempt has failed
  1837. /// </summary>
  1838. public void SendTeleportFailed(string reason)
  1839. {
  1840. TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed);
  1841. tpFailed.Info.AgentID = m_agentId;
  1842. tpFailed.Info.Reason = Util.StringToBytes256(reason);
  1843. tpFailed.AlertInfo = Array.Empty<TeleportFailedPacket.AlertInfoBlock>();
  1844. // Hack to get this out immediately and skip throttles
  1845. OutPacket(tpFailed, ThrottleOutPacketType.Unknown);
  1846. }
  1847. /// <summary>
  1848. ///
  1849. /// </summary>
  1850. public void SendTeleportStart(uint flags)
  1851. {
  1852. TeleportStartPacket tpStart = (TeleportStartPacket)PacketPool.Instance.GetPacket(PacketType.TeleportStart);
  1853. //TeleportStartPacket tpStart = new TeleportStartPacket();
  1854. tpStart.Info.TeleportFlags = flags; //16; // Teleport via location
  1855. // Hack to get this out immediately and skip throttles
  1856. OutPacket(tpStart, ThrottleOutPacketType.Unknown);
  1857. }
  1858. public void SendTeleportProgress(uint flags, string message)
  1859. {
  1860. TeleportProgressPacket tpProgress = (TeleportProgressPacket)PacketPool.Instance.GetPacket(PacketType.TeleportProgress);
  1861. tpProgress.AgentData.AgentID = m_agentId;
  1862. tpProgress.Info.TeleportFlags = flags;
  1863. tpProgress.Info.Message = Util.StringToBytes256(message);
  1864. // Hack to get this out immediately and skip throttles
  1865. OutPacket(tpProgress, ThrottleOutPacketType.Unknown);
  1866. }
  1867. public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item)
  1868. {
  1869. MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply);
  1870. money.MoneyData.AgentID = m_agentId;
  1871. money.MoneyData.TransactionID = transaction;
  1872. money.MoneyData.TransactionSuccess = success;
  1873. money.MoneyData.Description = description;
  1874. money.MoneyData.MoneyBalance = balance;
  1875. money.TransactionInfo.TransactionType = transactionType;
  1876. money.TransactionInfo.SourceID = sourceID;
  1877. money.TransactionInfo.IsSourceGroup = sourceIsGroup;
  1878. money.TransactionInfo.DestID = destID;
  1879. money.TransactionInfo.IsDestGroup = destIsGroup;
  1880. money.TransactionInfo.Amount = amount;
  1881. money.TransactionInfo.ItemDescription = Util.StringToBytes256(item);
  1882. OutPacket(money, ThrottleOutPacketType.Task);
  1883. }
  1884. public void SendPayPrice(UUID objectID, int[] payPrice)
  1885. {
  1886. if (payPrice[0] == 0 &&
  1887. payPrice[1] == 0 &&
  1888. payPrice[2] == 0 &&
  1889. payPrice[3] == 0 &&
  1890. payPrice[4] == 0)
  1891. return;
  1892. PayPriceReplyPacket payPriceReply = new();
  1893. payPriceReply.ObjectData.ObjectID = objectID;
  1894. payPriceReply.ObjectData.DefaultPayPrice = payPrice[0];
  1895. payPriceReply.ButtonData = new PayPriceReplyPacket.ButtonDataBlock[]
  1896. {
  1897. new PayPriceReplyPacket.ButtonDataBlock
  1898. {
  1899. PayButton = payPrice[1]
  1900. },
  1901. new PayPriceReplyPacket.ButtonDataBlock
  1902. {
  1903. PayButton = payPrice[2]
  1904. },
  1905. new PayPriceReplyPacket.ButtonDataBlock
  1906. {
  1907. PayButton = payPrice[3]
  1908. },
  1909. new PayPriceReplyPacket.ButtonDataBlock
  1910. {
  1911. PayButton = payPrice[4]
  1912. }
  1913. };
  1914. OutPacket(payPriceReply, ThrottleOutPacketType.Task);
  1915. }
  1916. public void SendKillObject(List<uint> localIDs)
  1917. {
  1918. // foreach (uint id in localIDs)
  1919. // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
  1920. // remove pending entities to reduce looping chances.
  1921. m_entityProps.Remove(localIDs);
  1922. m_entityUpdates.Remove(localIDs);
  1923. KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
  1924. int perpacket = localIDs.Count;
  1925. if(perpacket > 200)
  1926. perpacket = 200;
  1927. int nsent = 0;
  1928. kill.ObjectData = new KillObjectPacket.ObjectDataBlock[perpacket];
  1929. for (int i = 0 ; i < localIDs.Count ; i++ )
  1930. {
  1931. kill.ObjectData[nsent] = new KillObjectPacket.ObjectDataBlock
  1932. {
  1933. ID = localIDs[i]
  1934. };
  1935. if (++nsent >= 200)
  1936. {
  1937. OutPacket(kill, ThrottleOutPacketType.Task);
  1938. perpacket = localIDs.Count - i - 1;
  1939. if(perpacket == 0)
  1940. break;
  1941. if(perpacket > 200)
  1942. perpacket = 200;
  1943. kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
  1944. kill.ObjectData = new KillObjectPacket.ObjectDataBlock[perpacket];
  1945. nsent = 0;
  1946. }
  1947. }
  1948. if(nsent != 0)
  1949. {
  1950. OutPacket(kill, ThrottleOutPacketType.Task);
  1951. }
  1952. }
  1953. /// <summary>
  1954. /// Send information about the items contained in a folder to the client.
  1955. /// </summary>
  1956. /// <remarks>
  1957. /// XXX This method needs some refactoring loving
  1958. /// </remarks>
  1959. /// <param name="ownerID">The owner of the folder</param>
  1960. /// <param name="folderID">The id of the folder</param>
  1961. /// <param name="items">The items contained in the folder identified by folderID</param>
  1962. /// <param name="folders"></param>
  1963. /// <param name="fetchFolders">Do we need to send folder information?</param>
  1964. /// <param name="fetchItems">Do we need to send item information?</param>
  1965. public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
  1966. List<InventoryFolderBase> folders, int version, int descendents,
  1967. bool fetchFolders, bool fetchItems)
  1968. {
  1969. // An inventory descendents packet consists of a single agent section and an inventory details
  1970. // section for each inventory item. The size of each inventory item is approximately 550 bytes.
  1971. // limit to what may fit on MTU
  1972. int MAX_ITEMS_PER_PACKET = 5;
  1973. int MAX_FOLDERS_PER_PACKET = 6;
  1974. int totalItems = fetchItems ? items.Count : 0;
  1975. int totalFolders = fetchFolders ? folders.Count : 0;
  1976. int itemsSent = 0;
  1977. int foldersSent = 0;
  1978. int foldersToSend = 0;
  1979. int itemsToSend = 0;
  1980. InventoryDescendentsPacket currentPacket = null;
  1981. // Handle empty folders
  1982. //
  1983. if (totalItems == 0 && totalFolders == 0)
  1984. currentPacket = CreateInventoryDescendentsPacket(ownerID, folderID, version, descendents, 0, 0);
  1985. // To preserve SL compatibility, we will NOT combine folders and items in one packet
  1986. //
  1987. while (itemsSent < totalItems || foldersSent < totalFolders)
  1988. {
  1989. if (currentPacket is null) // Start a new packet
  1990. {
  1991. foldersToSend = totalFolders - foldersSent;
  1992. if (foldersToSend > MAX_FOLDERS_PER_PACKET)
  1993. foldersToSend = MAX_FOLDERS_PER_PACKET;
  1994. if (foldersToSend == 0)
  1995. {
  1996. itemsToSend = totalItems - itemsSent;
  1997. if (itemsToSend > MAX_ITEMS_PER_PACKET)
  1998. itemsToSend = MAX_ITEMS_PER_PACKET;
  1999. }
  2000. currentPacket = CreateInventoryDescendentsPacket(ownerID, folderID, version, descendents, foldersToSend, itemsToSend);
  2001. }
  2002. if (foldersToSend-- > 0)
  2003. currentPacket.FolderData[foldersSent % MAX_FOLDERS_PER_PACKET] = CreateFolderDataBlock(folders[foldersSent++]);
  2004. else if (itemsToSend-- > 0)
  2005. currentPacket.ItemData[itemsSent % MAX_ITEMS_PER_PACKET] = CreateItemDataBlock(items[itemsSent++]);
  2006. else
  2007. {
  2008. //m_log.DebugFormat(
  2009. // "[LLCLIENTVIEW]: Sending inventory folder details packet to {0} for folder {1}", Name, folderID);
  2010. OutPacket(currentPacket, ThrottleOutPacketType.Asset, false);
  2011. currentPacket = null;
  2012. }
  2013. }
  2014. if (currentPacket != null)
  2015. {
  2016. //m_log.DebugFormat(
  2017. // "[LLCLIENTVIEW]: Sending inventory folder details packet to {0} for folder {1}", Name, folderID);
  2018. OutPacket(currentPacket, ThrottleOutPacketType.Asset, false);
  2019. }
  2020. }
  2021. private static InventoryDescendentsPacket.FolderDataBlock CreateFolderDataBlock(InventoryFolderBase folder)
  2022. {
  2023. InventoryDescendentsPacket.FolderDataBlock newBlock = new()
  2024. {
  2025. FolderID = folder.ID,
  2026. Name = Util.StringToBytes256(folder.Name),
  2027. ParentID = folder.ParentID,
  2028. Type = (sbyte)folder.Type
  2029. };
  2030. //if (newBlock.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE)
  2031. // newBlock.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE;
  2032. return newBlock;
  2033. }
  2034. private static InventoryDescendentsPacket.ItemDataBlock CreateItemDataBlock(InventoryItemBase item)
  2035. {
  2036. InventoryDescendentsPacket.ItemDataBlock newBlock = new()
  2037. {
  2038. ItemID = item.ID,
  2039. AssetID = item.AssetID,
  2040. CreatorID = item.CreatorIdAsUuid,
  2041. BaseMask = item.BasePermissions,
  2042. Description = Util.StringToBytes256(item.Description),
  2043. EveryoneMask = item.EveryOnePermissions,
  2044. OwnerMask = item.CurrentPermissions,
  2045. FolderID = item.Folder,
  2046. InvType = (sbyte)item.InvType,
  2047. Name = Util.StringToBytes256(item.Name),
  2048. NextOwnerMask = item.NextPermissions,
  2049. OwnerID = item.Owner,
  2050. Type = (sbyte)item.AssetType,
  2051. GroupID = item.GroupID,
  2052. GroupOwned = item.GroupOwned,
  2053. GroupMask = item.GroupPermissions,
  2054. CreationDate = item.CreationDate,
  2055. SalePrice = item.SalePrice,
  2056. SaleType = item.SaleType,
  2057. Flags = item.Flags & 0x2000ff
  2058. };
  2059. newBlock.CRC =
  2060. Helpers.InventoryCRC(newBlock.CreationDate, newBlock.SaleType,
  2061. newBlock.InvType, newBlock.Type,
  2062. newBlock.AssetID, newBlock.GroupID,
  2063. newBlock.SalePrice,
  2064. newBlock.OwnerID, newBlock.CreatorID,
  2065. newBlock.ItemID, newBlock.FolderID,
  2066. newBlock.EveryoneMask,
  2067. newBlock.Flags, newBlock.OwnerMask,
  2068. newBlock.GroupMask, newBlock.NextOwnerMask);
  2069. return newBlock;
  2070. }
  2071. private static void AddNullFolderBlockToDecendentsPacket(ref InventoryDescendentsPacket packet)
  2072. {
  2073. packet.FolderData = new InventoryDescendentsPacket.FolderDataBlock[]
  2074. {
  2075. new InventoryDescendentsPacket.FolderDataBlock
  2076. {
  2077. FolderID = UUID.Zero,
  2078. ParentID = UUID.Zero,
  2079. Type = -1,
  2080. Name = Array.Empty<byte>()
  2081. }
  2082. };
  2083. }
  2084. private static void AddNullItemBlockToDescendentsPacket(ref InventoryDescendentsPacket packet)
  2085. {
  2086. packet.ItemData = new InventoryDescendentsPacket.ItemDataBlock[]
  2087. {
  2088. new InventoryDescendentsPacket.ItemDataBlock
  2089. {
  2090. ItemID = UUID.Zero,
  2091. AssetID = UUID.Zero,
  2092. CreatorID = UUID.Zero,
  2093. BaseMask = 0,
  2094. Description = Array.Empty<byte>(),
  2095. EveryoneMask = 0,
  2096. OwnerMask = 0,
  2097. FolderID = UUID.Zero,
  2098. InvType = (sbyte)0,
  2099. Name = Array.Empty<byte>(),
  2100. NextOwnerMask = 0,
  2101. OwnerID = UUID.Zero,
  2102. Type = -1,
  2103. GroupID = UUID.Zero,
  2104. GroupOwned = false,
  2105. GroupMask = 0,
  2106. CreationDate = 0,
  2107. SalePrice = 0,
  2108. SaleType = 0,
  2109. Flags = 0
  2110. }
  2111. };
  2112. // No need to add CRC
  2113. }
  2114. private InventoryDescendentsPacket CreateInventoryDescendentsPacket(UUID ownerID, UUID folderID, int version, int descendents, int folders, int items)
  2115. {
  2116. InventoryDescendentsPacket descend = (InventoryDescendentsPacket)PacketPool.Instance.GetPacket(PacketType.InventoryDescendents);
  2117. descend.Header.Zerocoded = true;
  2118. descend.AgentData.AgentID = m_agentId;
  2119. descend.AgentData.OwnerID = ownerID;
  2120. descend.AgentData.FolderID = folderID;
  2121. descend.AgentData.Version = version;
  2122. descend.AgentData.Descendents = descendents;
  2123. if (folders > 0)
  2124. descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[folders];
  2125. else
  2126. AddNullFolderBlockToDecendentsPacket(ref descend);
  2127. if (items > 0)
  2128. descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items];
  2129. else
  2130. AddNullItemBlockToDescendentsPacket(ref descend);
  2131. return descend;
  2132. }
  2133. public void SendInventoryItemDetails(InventoryItemBase[] items)
  2134. {
  2135. // Fudge this value. It's only needed to make the CRC anyway
  2136. const uint FULL_MASK_PERMISSIONS = (uint)0x7fffffff;
  2137. FetchInventoryReplyPacket inventoryReply = (FetchInventoryReplyPacket)PacketPool.Instance.GetPacket(PacketType.FetchInventoryReply);
  2138. inventoryReply.AgentData.AgentID = m_agentId;
  2139. int total = items.Length;
  2140. int count = 0;
  2141. for(int i = 0; i < items.Length; ++i)
  2142. {
  2143. if(count == 0)
  2144. {
  2145. if(total < 10)
  2146. {
  2147. inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[total];
  2148. total = 0;
  2149. }
  2150. else
  2151. {
  2152. inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[10];
  2153. total -= 10;
  2154. }
  2155. }
  2156. inventoryReply.InventoryData[count] = new FetchInventoryReplyPacket.InventoryDataBlock();
  2157. FetchInventoryReplyPacket.InventoryDataBlock data = inventoryReply.InventoryData[count];
  2158. data.ItemID = items[i].ID;
  2159. data.AssetID = items[i].AssetID;
  2160. data.CreatorID = items[i].CreatorIdAsUuid;
  2161. data.BaseMask = items[i].BasePermissions;
  2162. data.CreationDate = items[i].CreationDate;
  2163. data.Description = Util.StringToBytes256(items[i].Description);
  2164. data.EveryoneMask = items[i].EveryOnePermissions;
  2165. data.FolderID = items[i].Folder;
  2166. data.InvType = (sbyte)items[i].InvType;
  2167. data.Name = Util.StringToBytes256(items[i].Name);
  2168. data.NextOwnerMask = items[i].NextPermissions;
  2169. data.OwnerID = items[i].Owner;
  2170. data.OwnerMask = items[i].CurrentPermissions;
  2171. data.Type = (sbyte)items[i].AssetType;
  2172. data.GroupID = items[i].GroupID;
  2173. data.GroupOwned = items[i].GroupOwned;
  2174. data.GroupMask = items[i].GroupPermissions;
  2175. data.Flags = items[i].Flags;
  2176. data.SalePrice = items[i].SalePrice;
  2177. data.SaleType = items[i].SaleType;
  2178. data.CRC = Helpers.InventoryCRC(
  2179. 1000, 0, data.InvType, data.Type, data.AssetID,
  2180. data.GroupID, 100, data.OwnerID, data.CreatorID,
  2181. data.ItemID, data.FolderID, FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
  2182. FULL_MASK_PERMISSIONS);
  2183. ++count;
  2184. if(count == 10 || total == 0)
  2185. {
  2186. inventoryReply.Header.Zerocoded = true;
  2187. OutPacket(inventoryReply, ThrottleOutPacketType.Asset);
  2188. if(total == 0)
  2189. break;
  2190. count = 0;
  2191. }
  2192. }
  2193. }
  2194. protected void SendBulkUpdateInventoryFolder(InventoryFolderBase folderBase, UUID? transationID)
  2195. {
  2196. // We will use the same transaction id for all the separate packets to be sent out in this update.
  2197. UUID transactionId = transationID ?? UUID.Random();
  2198. List<BulkUpdateInventoryPacket.FolderDataBlock> folderDataBlocks = new();
  2199. SendBulkUpdateInventoryFolderRecursive(folderBase, ref folderDataBlocks, transactionId);
  2200. if (folderDataBlocks.Count > 0)
  2201. {
  2202. // We'll end up with some unsent folder blocks if there were some empty folders at the end of the list
  2203. // Send these now
  2204. BulkUpdateInventoryPacket bulkUpdate
  2205. = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory);
  2206. bulkUpdate.Header.Zerocoded = true;
  2207. bulkUpdate.AgentData.AgentID = m_agentId;
  2208. bulkUpdate.AgentData.TransactionID = transactionId;
  2209. bulkUpdate.FolderData = folderDataBlocks.ToArray();
  2210. bulkUpdate.ItemData = Array.Empty<BulkUpdateInventoryPacket.ItemDataBlock>();
  2211. //m_log.Debug("SendBulkUpdateInventory :" + bulkUpdate);
  2212. OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
  2213. }
  2214. }
  2215. /// <summary>
  2216. /// Recursively construct bulk update packets to send folders and items
  2217. /// </summary>
  2218. /// <param name="folder"></param>
  2219. /// <param name="folderDataBlocks"></param>
  2220. /// <param name="transactionId"></param>
  2221. private void SendBulkUpdateInventoryFolderRecursive(
  2222. InventoryFolderBase folder, ref List<BulkUpdateInventoryPacket.FolderDataBlock> folderDataBlocks,
  2223. UUID transactionId)
  2224. {
  2225. folderDataBlocks.Add(GenerateBulkUpdateFolderDataBlock(folder));
  2226. const int MAX_ITEMS_PER_PACKET = 5;
  2227. IInventoryService invService = m_scene.RequestModuleInterface<IInventoryService>();
  2228. // If there are any items then we have to start sending them off in this packet - the next folder will have
  2229. // to be in its own bulk update packet. Also, we can only fit 5 items in a packet (at least this was the limit
  2230. // being used on the Linden grid at 20081203).
  2231. InventoryCollection contents = invService.GetFolderContent(m_agentId, folder.ID); // folder.RequestListOfItems();
  2232. List<InventoryItemBase> items = contents.Items;
  2233. while (items.Count > 0)
  2234. {
  2235. BulkUpdateInventoryPacket bulkUpdate
  2236. = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory);
  2237. bulkUpdate.Header.Zerocoded = true;
  2238. bulkUpdate.AgentData.AgentID = m_agentId;
  2239. bulkUpdate.AgentData.TransactionID = transactionId;
  2240. bulkUpdate.FolderData = folderDataBlocks.ToArray();
  2241. int itemsToSend = (items.Count > MAX_ITEMS_PER_PACKET ? MAX_ITEMS_PER_PACKET : items.Count);
  2242. bulkUpdate.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[itemsToSend];
  2243. for (int i = 0; i < itemsToSend; i++)
  2244. {
  2245. // Remove from the end of the list so that we don't incur a performance penalty
  2246. bulkUpdate.ItemData[i] = GenerateBulkUpdateItemDataBlock(items[^1]);
  2247. items.RemoveAt(items.Count - 1);
  2248. }
  2249. //m_log.Debug("SendBulkUpdateInventoryRecursive :" + bulkUpdate);
  2250. OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
  2251. folderDataBlocks = new List<BulkUpdateInventoryPacket.FolderDataBlock>();
  2252. // If we're going to be sending another items packet then it needs to contain just the folder to which those
  2253. // items belong.
  2254. if (items.Count > 0)
  2255. folderDataBlocks.Add(GenerateBulkUpdateFolderDataBlock(folder));
  2256. }
  2257. List<InventoryFolderBase> subFolders = contents.Folders;
  2258. for (int indx = 0; indx < subFolders.Count; ++indx)
  2259. {
  2260. SendBulkUpdateInventoryFolderRecursive(subFolders[indx], ref folderDataBlocks, transactionId);
  2261. }
  2262. }
  2263. /// <summary>
  2264. /// Generate a bulk update inventory data block for the given folder
  2265. /// </summary>
  2266. /// <param name="folder"></param>
  2267. /// <returns></returns>
  2268. private static BulkUpdateInventoryPacket.FolderDataBlock GenerateBulkUpdateFolderDataBlock(InventoryFolderBase folder)
  2269. {
  2270. BulkUpdateInventoryPacket.FolderDataBlock folderBlock = new()
  2271. {
  2272. FolderID = folder.ID,
  2273. ParentID = folder.ParentID,
  2274. Type = (sbyte)folder.Type,
  2275. // Leaving this here for now, just in case we need to do this for a while
  2276. //if (folderBlock.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE)
  2277. // folderBlock.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE;
  2278. Name = Util.StringToBytes256(folder.Name)
  2279. };
  2280. return folderBlock;
  2281. }
  2282. /// <summary>
  2283. /// Generate a bulk update inventory data block for the given item
  2284. /// </summary>
  2285. /// <param name="item"></param>
  2286. /// <returns></returns>
  2287. private static BulkUpdateInventoryPacket.ItemDataBlock GenerateBulkUpdateItemDataBlock(InventoryItemBase item)
  2288. {
  2289. BulkUpdateInventoryPacket.ItemDataBlock itemBlock = new()
  2290. {
  2291. ItemID = item.ID,
  2292. AssetID = item.AssetID,
  2293. CreatorID = item.CreatorIdAsUuid,
  2294. BaseMask = item.BasePermissions,
  2295. Description = Util.StringToBytes256(item.Description),
  2296. EveryoneMask = item.EveryOnePermissions,
  2297. FolderID = item.Folder,
  2298. InvType = (sbyte)item.InvType,
  2299. Name = Util.StringToBytes256(item.Name),
  2300. NextOwnerMask = item.NextPermissions,
  2301. OwnerID = item.Owner,
  2302. OwnerMask = item.CurrentPermissions,
  2303. Type = (sbyte)item.AssetType,
  2304. GroupID = item.GroupID,
  2305. GroupOwned = item.GroupOwned,
  2306. GroupMask = item.GroupPermissions,
  2307. Flags = item.Flags & 0x2000ff,
  2308. SalePrice = item.SalePrice,
  2309. SaleType = item.SaleType,
  2310. CreationDate = item.CreationDate
  2311. };
  2312. itemBlock.CRC =
  2313. Helpers.InventoryCRC(
  2314. 1000, 0, itemBlock.InvType,
  2315. itemBlock.Type, itemBlock.AssetID,
  2316. itemBlock.GroupID, 100,
  2317. itemBlock.OwnerID, itemBlock.CreatorID,
  2318. itemBlock.ItemID, itemBlock.FolderID,
  2319. (uint)PermissionMask.All, 1, (uint)PermissionMask.All, (uint)PermissionMask.All,
  2320. (uint)PermissionMask.All);
  2321. return itemBlock;
  2322. }
  2323. public void SendBulkUpdateInventory(InventoryNodeBase node, UUID? transationID = null)
  2324. {
  2325. if (node is InventoryItemBase itbase)
  2326. SendBulkUpdateInventoryItem(itbase, transationID);
  2327. else if (node is InventoryFolderBase ftbase)
  2328. SendBulkUpdateInventoryFolder(ftbase, transationID);
  2329. else if (node is not null)
  2330. m_log.Error($"[CLIENT]: {Name} sent unknown inventory node named {node.Name}");
  2331. else
  2332. m_log.Error($"[CLIENT]: {Name} sent null inventory node");
  2333. }
  2334. protected void SendBulkUpdateInventoryItem(InventoryItemBase item, UUID? transationID = null)
  2335. {
  2336. IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
  2337. eq?.SendBulkUpdateInventoryItem(item, m_agentId, transationID);
  2338. }
  2339. public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
  2340. {
  2341. SendInventoryItemCreateUpdate(Item, UUID.Zero, callbackId);
  2342. }
  2343. /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
  2344. public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
  2345. {
  2346. const uint FULL_MASK_PERMISSIONS = (uint)0x7fffffff;
  2347. UpdateCreateInventoryItemPacket InventoryReply
  2348. = (UpdateCreateInventoryItemPacket)PacketPool.Instance.GetPacket(
  2349. PacketType.UpdateCreateInventoryItem);
  2350. // TODO: don't create new blocks if recycling an old packet
  2351. InventoryReply.AgentData.AgentID = m_agentId;
  2352. InventoryReply.AgentData.SimApproved = true;
  2353. InventoryReply.AgentData.TransactionID = transactionID;
  2354. InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[]
  2355. {
  2356. new UpdateCreateInventoryItemPacket.InventoryDataBlock
  2357. {
  2358. ItemID = Item.ID,
  2359. AssetID = Item.AssetID,
  2360. CreatorID = Item.CreatorIdAsUuid,
  2361. BaseMask = Item.BasePermissions,
  2362. Description = Util.StringToBytes256(Item.Description),
  2363. EveryoneMask = Item.EveryOnePermissions,
  2364. FolderID = Item.Folder,
  2365. InvType = (sbyte)Item.InvType,
  2366. Name = Util.StringToBytes256(Item.Name),
  2367. NextOwnerMask = Item.NextPermissions,
  2368. OwnerID = Item.Owner,
  2369. OwnerMask = Item.CurrentPermissions,
  2370. Type = (sbyte)Item.AssetType,
  2371. CallbackID = callbackId,
  2372. GroupID = Item.GroupID,
  2373. GroupOwned = Item.GroupOwned,
  2374. GroupMask = Item.GroupPermissions,
  2375. Flags = Item.Flags & 0x2000ff,
  2376. SalePrice = Item.SalePrice,
  2377. SaleType = Item.SaleType,
  2378. CreationDate = Item.CreationDate
  2379. }
  2380. };
  2381. InventoryReply.InventoryData[0].CRC =
  2382. Helpers.InventoryCRC(1000, 0, InventoryReply.InventoryData[0].InvType,
  2383. InventoryReply.InventoryData[0].Type, InventoryReply.InventoryData[0].AssetID,
  2384. InventoryReply.InventoryData[0].GroupID, 100,
  2385. InventoryReply.InventoryData[0].OwnerID, InventoryReply.InventoryData[0].CreatorID,
  2386. InventoryReply.InventoryData[0].ItemID, InventoryReply.InventoryData[0].FolderID,
  2387. FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
  2388. FULL_MASK_PERMISSIONS);
  2389. InventoryReply.Header.Zerocoded = true;
  2390. OutPacket(InventoryReply, ThrottleOutPacketType.Asset);
  2391. }
  2392. public void SendRemoveInventoryItem(UUID itemID)
  2393. {
  2394. RemoveInventoryItemPacket remove = (RemoveInventoryItemPacket)PacketPool.Instance.GetPacket(PacketType.RemoveInventoryItem);
  2395. // TODO: don't create new blocks if recycling an old packet
  2396. remove.AgentData.AgentID = m_agentId;
  2397. remove.AgentData.SessionID = m_sessionId;
  2398. remove.InventoryData = new RemoveInventoryItemPacket.InventoryDataBlock[]
  2399. {
  2400. new RemoveInventoryItemPacket.InventoryDataBlock
  2401. {
  2402. ItemID = itemID
  2403. }
  2404. };
  2405. remove.Header.Zerocoded = true;
  2406. OutPacket(remove, ThrottleOutPacketType.Asset);
  2407. }
  2408. /*
  2409. private uint adjustControls(int input)
  2410. {
  2411. uint ret = (uint)input;
  2412. uint masked = ret & 0x0f;
  2413. masked <<= 19;
  2414. ret |= masked;
  2415. return ret;
  2416. }
  2417. */
  2418. public void SendTakeControls(int controls, bool passToAgent, bool TakeControls)
  2419. {
  2420. ScriptControlChangePacket scriptcontrol = (ScriptControlChangePacket)PacketPool.Instance.GetPacket(PacketType.ScriptControlChange);
  2421. scriptcontrol.Data = new ScriptControlChangePacket.DataBlock[]
  2422. {
  2423. new ScriptControlChangePacket.DataBlock
  2424. {
  2425. //ddata.Controls = adjustControls(controls);
  2426. Controls = (uint)controls,
  2427. PassToAgent = passToAgent,
  2428. TakeControls = TakeControls
  2429. }
  2430. };
  2431. OutPacket(scriptcontrol, ThrottleOutPacketType.Task);
  2432. }
  2433. static private readonly byte[] ReplyTaskInventoryHeader = new byte[] {
  2434. Helpers.MSG_RELIABLE, //| Helpers.MSG_ZEROCODED, not doing spec zeroencode on this
  2435. 0, 0, 0, 0, // sequence number
  2436. 0, // extra
  2437. 0xff, 0xff, 1, 34 // ID 90 (low frequency bigendian)
  2438. };
  2439. public void SendTaskInventory(UUID taskID, short serial, byte[] fileName)
  2440. {
  2441. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  2442. byte[] data = buf.Data;
  2443. //setup header
  2444. Buffer.BlockCopy(ReplyTaskInventoryHeader, 0, data, 0, 10);
  2445. taskID.ToBytes(data, 10); // 26
  2446. Utils.Int16ToBytes(serial, data, 26); // 28
  2447. data[28] = (byte)fileName.Length;
  2448. if(data[28] > 0)
  2449. Buffer.BlockCopy(fileName, 0, data, 29, data[28]);
  2450. buf.DataLength = 29 + data[28];
  2451. //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true);
  2452. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  2453. }
  2454. static private readonly byte[] SendXferPacketHeader = new byte[] {
  2455. 0, //Helpers.MSG_RELIABLE, Xfer control must provide reliabialty
  2456. 0, 0, 0, 0, // sequence number
  2457. 0, // extra
  2458. 18 // ID (high frequency bigendian)
  2459. };
  2460. public void SendXferPacket(ulong xferID, uint packet,
  2461. byte[] XferData, int XferDataOffset, int XferDatapktLen, bool isTaskInventory)
  2462. {
  2463. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  2464. byte[] data = buf.Data;
  2465. //setup header
  2466. Buffer.BlockCopy(SendXferPacketHeader, 0, data, 0, 7);
  2467. Utils.UInt64ToBytesSafepos(xferID, data, 7); // 15
  2468. Utils.UIntToBytesSafepos(packet, data, 15); // 19
  2469. int len = XferDatapktLen;
  2470. if (XferDataOffset == 0) // first packet needs to send the total xfer data len
  2471. len += 4;
  2472. if (len > LLUDPServer.MAXPAYLOAD) // should never happen
  2473. len = LLUDPServer.MAXPAYLOAD;
  2474. if (len == 0)
  2475. {
  2476. data[19] = 0;
  2477. data[20] = 0;
  2478. }
  2479. else
  2480. {
  2481. data[19] = (byte)len;
  2482. data[20] = (byte)(len >> 8);
  2483. if(XferDataOffset == 0)
  2484. {
  2485. // need to send total xfer data len
  2486. Utils.IntToBytesSafepos(XferData.Length, data, 21);
  2487. if (XferDatapktLen > 0)
  2488. Buffer.BlockCopy(XferData, XferDataOffset, data, 25, XferDatapktLen);
  2489. }
  2490. else
  2491. Buffer.BlockCopy(XferData, XferDataOffset, data, 21, XferDatapktLen);
  2492. }
  2493. buf.DataLength = 21 + len;
  2494. m_udpServer.SendUDPPacket(m_udpClient, buf, isTaskInventory ? ThrottleOutPacketType.Task : ThrottleOutPacketType.Asset);
  2495. }
  2496. static private readonly byte[] AbortXferHeader = new byte[] {
  2497. Helpers.MSG_RELIABLE,
  2498. 0, 0, 0, 0, // sequence number
  2499. 0, // extra
  2500. 0xff, 0xff, 0, 157 // ID 157 (low frequency bigendian)
  2501. };
  2502. public void SendAbortXferPacket(ulong xferID)
  2503. {
  2504. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  2505. byte[] data = buf.Data;
  2506. //setup header
  2507. Buffer.BlockCopy(AbortXferHeader, 0, data, 0, 10);
  2508. Utils.UInt64ToBytesSafepos(xferID, data, 10); // 18
  2509. Utils.IntToBytesSafepos(0, data, 18); // 22 reason TODO
  2510. buf.DataLength = 22;
  2511. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Asset);
  2512. }
  2513. public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit,
  2514. int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor,
  2515. int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay,
  2516. int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent)
  2517. {
  2518. EconomyDataPacket economyData = (EconomyDataPacket)PacketPool.Instance.GetPacket(PacketType.EconomyData);
  2519. economyData.Info.EnergyEfficiency = EnergyEfficiency;
  2520. economyData.Info.ObjectCapacity = ObjectCapacity;
  2521. economyData.Info.ObjectCount = ObjectCount;
  2522. economyData.Info.PriceEnergyUnit = PriceEnergyUnit;
  2523. economyData.Info.PriceGroupCreate = PriceGroupCreate;
  2524. economyData.Info.PriceObjectClaim = PriceObjectClaim;
  2525. economyData.Info.PriceObjectRent = PriceObjectRent;
  2526. economyData.Info.PriceObjectScaleFactor = PriceObjectScaleFactor;
  2527. economyData.Info.PriceParcelClaim = PriceParcelClaim;
  2528. economyData.Info.PriceParcelClaimFactor = PriceParcelClaimFactor;
  2529. economyData.Info.PriceParcelRent = PriceParcelRent;
  2530. economyData.Info.PricePublicObjectDecay = PricePublicObjectDecay;
  2531. economyData.Info.PricePublicObjectDelete = PricePublicObjectDelete;
  2532. economyData.Info.PriceRentLight = PriceRentLight;
  2533. economyData.Info.PriceUpload = PriceUpload;
  2534. economyData.Info.TeleportMinPrice = TeleportMinPrice;
  2535. economyData.Info.TeleportPriceExponent = TeleportPriceExponent;
  2536. economyData.Header.Reliable = true;
  2537. OutPacket(economyData, ThrottleOutPacketType.Task);
  2538. }
  2539. static private readonly byte[] AvatarPickerReplyHeader = new byte[] {
  2540. Helpers.MSG_RELIABLE,
  2541. 0, 0, 0, 0, // sequence number
  2542. 0, // extra
  2543. 0xff, 0xff, 0, 28 // ID 28 (low frequency bigendian)
  2544. };
  2545. public void SendAvatarPickerReply(UUID QueryID, List<UserData> users)
  2546. {
  2547. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  2548. byte[] data = buf.Data;
  2549. //setup header
  2550. Buffer.BlockCopy(AvatarPickerReplyHeader, 0, data, 0, 10);
  2551. m_agentId.ToBytes(data, 10); //26
  2552. QueryID.ToBytes(data, 26); //42
  2553. if (users.Count == 0)
  2554. {
  2555. data[42] = 0;
  2556. buf.DataLength = 43;
  2557. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  2558. return;
  2559. }
  2560. int pos = 43;
  2561. int count = 0;
  2562. for(int u = 0; u < users.Count; ++u)
  2563. {
  2564. UserData user = users[u];
  2565. user.Id.ToBytes(data,pos);
  2566. pos+= 16;
  2567. byte[] tmp = Utils.StringToBytes(user.FirstName);
  2568. data[pos++] = (byte)tmp.Length;
  2569. if(tmp.Length > 0)
  2570. {
  2571. Buffer.BlockCopy(tmp, 0, data, pos, tmp.Length);
  2572. pos += tmp.Length;
  2573. }
  2574. tmp = Utils.StringToBytes(user.LastName);
  2575. data[pos++] = (byte)tmp.Length;
  2576. if (tmp.Length > 0)
  2577. {
  2578. Buffer.BlockCopy(tmp, 0, data, pos, tmp.Length);
  2579. pos += tmp.Length;
  2580. }
  2581. ++count;
  2582. if (pos >= LLUDPServer.MAXPAYLOAD - 120)
  2583. {
  2584. data[42] = (byte)count;
  2585. buf.DataLength = pos;
  2586. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  2587. if (u < users.Count - 1)
  2588. {
  2589. UDPPacketBuffer newbuf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  2590. byte[] newdata = newbuf.Data;
  2591. Buffer.BlockCopy(data, 0, newdata, 0, 42);
  2592. buf = newbuf;
  2593. data = newdata;
  2594. pos = 43;
  2595. }
  2596. count = 0;
  2597. }
  2598. }
  2599. if(count > 0)
  2600. {
  2601. data[42] = (byte)count;
  2602. buf.DataLength = pos;
  2603. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  2604. }
  2605. }
  2606. public void SendAgentDataUpdate(UUID agentid, UUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle)
  2607. {
  2608. if (agentid.Equals(m_agentId))
  2609. {
  2610. ActiveGroupId = activegroupid;
  2611. ActiveGroupName = groupname;
  2612. ActiveGroupPowers = grouppowers;
  2613. }
  2614. AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate);
  2615. sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid;
  2616. sendAgentDataUpdate.AgentData.AgentID = agentid;
  2617. sendAgentDataUpdate.AgentData.FirstName = Util.StringToBytes256(firstname);
  2618. sendAgentDataUpdate.AgentData.GroupName = Util.StringToBytes256(groupname);
  2619. sendAgentDataUpdate.AgentData.GroupPowers = grouppowers;
  2620. sendAgentDataUpdate.AgentData.GroupTitle = Util.StringToBytes256(grouptitle);
  2621. sendAgentDataUpdate.AgentData.LastName = Util.StringToBytes256(lastname);
  2622. OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task);
  2623. }
  2624. /// <summary>
  2625. /// Send an alert message to the client. This pops up a brief duration information box at a corner
  2626. /// </summary>
  2627. /// <param name="message"></param>
  2628. public void SendAlertMessage(string message)
  2629. {
  2630. AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage);
  2631. alertPack.AlertData.Message = Util.StringToBytes256(message);
  2632. alertPack.AlertInfo = Array.Empty<AlertMessagePacket.AlertInfoBlock>();
  2633. OutPacket(alertPack, ThrottleOutPacketType.Task);
  2634. }
  2635. public void SendAlertMessage(string message, string info)
  2636. {
  2637. AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage);
  2638. alertPack.AlertData.Message = Util.StringToBytes256(message);
  2639. alertPack.AlertInfo = new AlertMessagePacket.AlertInfoBlock[]
  2640. {
  2641. new AlertMessagePacket.AlertInfoBlock
  2642. {
  2643. Message = Util.StringToBytes256(info),
  2644. ExtraParams = Array.Empty<byte>()
  2645. }
  2646. };
  2647. OutPacket(alertPack, ThrottleOutPacketType.Task);
  2648. }
  2649. /// <summary>
  2650. /// Send an agent alert message to the client.
  2651. /// </summary>
  2652. /// <param name="message"></param>
  2653. /// <param name="modal">On the linden client, if this true then it displays a one button text box placed in the
  2654. /// middle of the window. If false, the message is displayed in a brief duration blue information box (as for
  2655. /// the AlertMessage packet).</param>
  2656. public void SendAgentAlertMessage(string message, bool modal)
  2657. {
  2658. // Prepend a slash to make the message come up in the top right
  2659. // again.
  2660. // Allow special formats to be sent from aware modules.
  2661. if (!modal && !message.StartsWith("ALERT: ") && !message.StartsWith("NOTIFY: ") && message != "Home position set." && message != "You died and have been teleported to your home location")
  2662. message = "/" + message;
  2663. AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
  2664. alertPack.AgentData.AgentID = m_agentId;
  2665. alertPack.AlertData.Message = Util.StringToBytes256(message);
  2666. alertPack.AlertData.Modal = modal;
  2667. OutPacket(alertPack, ThrottleOutPacketType.Task);
  2668. }
  2669. public void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message,
  2670. string url)
  2671. {
  2672. LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL);
  2673. loadURL.Data.ObjectName = Util.StringToBytes256(objectname);
  2674. loadURL.Data.ObjectID = objectID;
  2675. loadURL.Data.OwnerID = ownerID;
  2676. loadURL.Data.OwnerIsGroup = groupOwned;
  2677. loadURL.Data.Message = Util.StringToBytes256(message);
  2678. loadURL.Data.URL = Util.StringToBytes256(url);
  2679. OutPacket(loadURL, ThrottleOutPacketType.Task);
  2680. }
  2681. public void SendDialog(
  2682. string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg,
  2683. UUID textureID, int ch, string[] buttonlabels)
  2684. {
  2685. ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
  2686. dialog.Data.ObjectID = objectID;
  2687. dialog.Data.ObjectName = Util.StringToBytes256(objectname);
  2688. // this is the username of the *owner*
  2689. dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
  2690. dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
  2691. dialog.Data.Message = Util.StringToBytes(msg,512);
  2692. dialog.Data.ImageID = textureID;
  2693. dialog.Data.ChatChannel = ch;
  2694. ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length];
  2695. for (int i = 0; i < buttonlabels.Length; i++)
  2696. {
  2697. buttons[i] = new ScriptDialogPacket.ButtonsBlock
  2698. {
  2699. ButtonLabel = Util.StringToBytes(buttonlabels[i], 24)
  2700. };
  2701. }
  2702. dialog.Buttons = buttons;
  2703. dialog.OwnerData = new ScriptDialogPacket.OwnerDataBlock[1];
  2704. dialog.OwnerData[0] = new ScriptDialogPacket.OwnerDataBlock
  2705. {
  2706. OwnerID = ownerID
  2707. };
  2708. OutPacket(dialog, ThrottleOutPacketType.Task);
  2709. }
  2710. public void SendPreLoadSound(UUID objectID, UUID ownerID, UUID soundID)
  2711. {
  2712. PreloadSoundPacket preSound = (PreloadSoundPacket)PacketPool.Instance.GetPacket(PacketType.PreloadSound);
  2713. // TODO: don't create new blocks if recycling an old packet
  2714. preSound.DataBlock = new PreloadSoundPacket.DataBlockBlock[1];
  2715. preSound.DataBlock[0] = new PreloadSoundPacket.DataBlockBlock
  2716. {
  2717. ObjectID = objectID,
  2718. OwnerID = ownerID,
  2719. SoundID = soundID
  2720. };
  2721. preSound.Header.Zerocoded = true;
  2722. OutPacket(preSound, ThrottleOutPacketType.Task);
  2723. }
  2724. public void SendPlayAttachedSound(UUID soundID, UUID objectID, UUID ownerID, float gain, byte flags)
  2725. {
  2726. AttachedSoundPacket sound = (AttachedSoundPacket)PacketPool.Instance.GetPacket(PacketType.AttachedSound);
  2727. sound.DataBlock.SoundID = soundID;
  2728. sound.DataBlock.ObjectID = objectID;
  2729. sound.DataBlock.OwnerID = ownerID;
  2730. sound.DataBlock.Gain = gain;
  2731. sound.DataBlock.Flags = flags;
  2732. OutPacket(sound, ThrottleOutPacketType.Task);
  2733. }
  2734. public void SendTransferAbort(TransferRequestPacket transferRequest)
  2735. {
  2736. TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
  2737. abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
  2738. abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
  2739. m_log.Debug("[Assets] Aborting transfer; asset request failed");
  2740. OutPacket(abort, ThrottleOutPacketType.Task);
  2741. }
  2742. public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
  2743. {
  2744. SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
  2745. sound.SoundData.SoundID = soundID;
  2746. sound.SoundData.OwnerID = ownerID;
  2747. sound.SoundData.ObjectID = objectID;
  2748. sound.SoundData.ParentID = parentID;
  2749. sound.SoundData.Handle = handle;
  2750. sound.SoundData.Position = position;
  2751. sound.SoundData.Gain = gain;
  2752. OutPacket(sound, ThrottleOutPacketType.Task);
  2753. }
  2754. public void SendAttachedSoundGainChange(UUID objectID, float gain)
  2755. {
  2756. AttachedSoundGainChangePacket sound = (AttachedSoundGainChangePacket)PacketPool.Instance.GetPacket(PacketType.AttachedSoundGainChange);
  2757. sound.DataBlock.ObjectID = objectID;
  2758. sound.DataBlock.Gain = gain;
  2759. OutPacket(sound, ThrottleOutPacketType.Task);
  2760. }
  2761. public void SendViewerTime(Vector3 sunDir, float sunphase)
  2762. {
  2763. SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage);
  2764. viewertime.TimeInfo.UsecSinceStart = Util.UnixTimeSinceEpoch_uS();
  2765. viewertime.TimeInfo.SunDirection = sunDir;
  2766. viewertime.TimeInfo.SunPhase = sunphase;
  2767. viewertime.TimeInfo.SunAngVelocity = Vector3.Zero; //legacy
  2768. viewertime.TimeInfo.SecPerDay = 14400; // legacy
  2769. viewertime.TimeInfo.SecPerYear = 158400; // legacy
  2770. viewertime.Header.Reliable = false;
  2771. viewertime.Header.Zerocoded = true;
  2772. OutPacket(viewertime, ThrottleOutPacketType.Task);
  2773. }
  2774. public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks)
  2775. {
  2776. ViewerEffectPacket packet = (ViewerEffectPacket)PacketPool.Instance.GetPacket(PacketType.ViewerEffect);
  2777. // packet.AgentData.AgentID = m_agentId;
  2778. // packet.AgentData.SessionID = SessionId;
  2779. packet.Effect = effectBlocks;
  2780. // OutPacket(packet, ThrottleOutPacketType.State);
  2781. OutPacket(packet, ThrottleOutPacketType.Task);
  2782. }
  2783. public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] membershipType,
  2784. string flAbout, uint flags, UUID flImageID, UUID imageID, string profileURL,
  2785. UUID partnerID)
  2786. {
  2787. AvatarPropertiesReplyPacket avatarReply = (AvatarPropertiesReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPropertiesReply);
  2788. avatarReply.AgentData.AgentID = m_agentId;
  2789. avatarReply.AgentData.AvatarID = avatarID;
  2790. if (aboutText != null)
  2791. avatarReply.PropertiesData.AboutText = Util.StringToBytes1024(aboutText);
  2792. else
  2793. avatarReply.PropertiesData.AboutText = Utils.EmptyBytes;
  2794. avatarReply.PropertiesData.BornOn = Util.StringToBytes256(bornOn);
  2795. avatarReply.PropertiesData.CharterMember = membershipType;
  2796. if (flAbout != null)
  2797. avatarReply.PropertiesData.FLAboutText = Util.StringToBytes256(flAbout);
  2798. else
  2799. avatarReply.PropertiesData.FLAboutText = Utils.EmptyBytes;
  2800. avatarReply.PropertiesData.Flags = flags;
  2801. avatarReply.PropertiesData.FLImageID = flImageID;
  2802. avatarReply.PropertiesData.ImageID = imageID;
  2803. avatarReply.PropertiesData.ProfileURL = Util.StringToBytes256(profileURL);
  2804. avatarReply.PropertiesData.PartnerID = partnerID;
  2805. OutPacket(avatarReply, ThrottleOutPacketType.Task);
  2806. }
  2807. /// <summary>
  2808. /// Send the client an Estate message blue box pop-down with a single OK button
  2809. /// </summary>
  2810. /// <param name="FromAvatarID"></param>
  2811. /// <param name="fromSessionID"></param>
  2812. /// <param name="FromAvatarName"></param>
  2813. /// <param name="Message"></param>
  2814. public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message)
  2815. {
  2816. if (!SceneAgent.IsChildAgent)
  2817. SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, m_agentId, 1, Message, false, new Vector3()));
  2818. //SendInstantMessage(FromAvatarID, fromSessionID, Message, m_agentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch());
  2819. }
  2820. public void SendLogoutPacket()
  2821. {
  2822. // I know this is a bit of a hack, however there are times when you don't
  2823. // want to send this, but still need to do the rest of the shutdown process
  2824. // this method gets called from the packet server.. which makes it practically
  2825. // impossible to do any other way.
  2826. if (m_SendLogoutPacketWhenClosing)
  2827. {
  2828. LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply);
  2829. // TODO: don't create new blocks if recycling an old packet
  2830. logReply.AgentData.AgentID = m_agentId;
  2831. logReply.AgentData.SessionID = m_sessionId;
  2832. logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
  2833. logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock
  2834. {
  2835. ItemID = UUID.Zero
  2836. };
  2837. OutPacket(logReply, ThrottleOutPacketType.Task);
  2838. }
  2839. }
  2840. public void SendHealth(float health)
  2841. {
  2842. HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage);
  2843. healthpacket.HealthData.Health = health;
  2844. OutPacket(healthpacket, ThrottleOutPacketType.Task);
  2845. }
  2846. public void SendAgentOnline(UUID[] agentIDs)
  2847. {
  2848. OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length];
  2849. for (int i = 0; i < agentIDs.Length; i++)
  2850. {
  2851. onpb[i] = new OnlineNotificationPacket.AgentBlockBlock
  2852. {
  2853. AgentID = agentIDs[i]
  2854. };
  2855. }
  2856. OnlineNotificationPacket onp = new()
  2857. {
  2858. AgentBlock = onpb
  2859. };
  2860. onp.Header.Reliable = true;
  2861. OutPacket(onp, ThrottleOutPacketType.Task);
  2862. }
  2863. public void SendAgentOffline(UUID[] agentIDs)
  2864. {
  2865. OfflineNotificationPacket offp = new();
  2866. OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length];
  2867. for (int i = 0; i < agentIDs.Length; i++)
  2868. {
  2869. offpb[i] = new OfflineNotificationPacket.AgentBlockBlock
  2870. {
  2871. AgentID = agentIDs[i]
  2872. };
  2873. }
  2874. offp.AgentBlock = offpb;
  2875. offp.Header.Reliable = true;
  2876. OutPacket(offp, ThrottleOutPacketType.Task);
  2877. }
  2878. public void SendFindAgent(UUID HunterID, UUID PreyID, double GlobalX, double GlobalY)
  2879. {
  2880. FindAgentPacket fap = new();
  2881. fap.AgentBlock.Hunter = HunterID;
  2882. fap.AgentBlock.Prey = PreyID;
  2883. fap.AgentBlock.SpaceIP = 0;
  2884. fap.LocationBlock = new FindAgentPacket.LocationBlockBlock[]
  2885. {
  2886. new FindAgentPacket.LocationBlockBlock
  2887. {
  2888. GlobalX = GlobalX,
  2889. GlobalY = GlobalY
  2890. }
  2891. };
  2892. OutPacket(fap, ThrottleOutPacketType.Task);
  2893. }
  2894. public void SendSitResponse(UUID TargetID, Vector3 OffsetPos,
  2895. Quaternion SitOrientation, bool autopilot,
  2896. Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
  2897. {
  2898. AvatarSitResponsePacket avatarSitResponse = new();
  2899. avatarSitResponse.SitObject.ID = TargetID;
  2900. avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
  2901. avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
  2902. avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook;
  2903. avatarSitResponse.SitTransform.AutoPilot = autopilot;
  2904. avatarSitResponse.SitTransform.SitPosition = OffsetPos;
  2905. avatarSitResponse.SitTransform.SitRotation = SitOrientation;
  2906. OutPacket(avatarSitResponse, ThrottleOutPacketType.Task);
  2907. }
  2908. public void SendAdminResponse(UUID Token, uint AdminLevel)
  2909. {
  2910. GrantGodlikePowersPacket respondPacket = new();
  2911. respondPacket.AgentData.AgentID = m_agentId;
  2912. respondPacket.AgentData.SessionID = m_sessionId;
  2913. respondPacket.GrantData.GodLevel = (byte)AdminLevel;
  2914. respondPacket.GrantData.Token = Token;
  2915. OutPacket(respondPacket, ThrottleOutPacketType.Task);
  2916. }
  2917. public void SendGroupMembership(GroupMembershipData[] GroupMembership)
  2918. {
  2919. UpdateGroupMembership(GroupMembership);
  2920. SendAgentGroupDataUpdate(m_agentId, GroupMembership);
  2921. }
  2922. public void SendSelectedPartsProprieties(List<ISceneEntity> parts)
  2923. {
  2924. /* not in use
  2925. // udp part
  2926. ObjectPropertiesPacket packet =
  2927. (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
  2928. ObjectPropertiesPacket.ObjectDataBlock[] ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[parts.Count];
  2929. int i = 0;
  2930. foreach(SceneObjectPart sop in parts)
  2931. ObjectData[i++] = CreateObjectPropertiesBlock(sop);
  2932. packet.ObjectData = ObjectData;
  2933. packet.Header.Zerocoded = true;
  2934. // udp send splits this mega packets correctly
  2935. // mb later will avoid that to reduce gc stress
  2936. OutPacket(packet, ThrottleOutPacketType.Task, true);
  2937. // caps physics part
  2938. IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
  2939. if(eq is null)
  2940. return;
  2941. OSDArray array = new OSDArray();
  2942. foreach(SceneObjectPart sop in parts)
  2943. {
  2944. OSDMap physinfo = new OSDMap(6);
  2945. physinfo["LocalID"] = sop.LocalId;
  2946. physinfo["Density"] = sop.Density;
  2947. physinfo["Friction"] = sop.Friction;
  2948. physinfo["GravityMultiplier"] = sop.GravityModifier;
  2949. physinfo["Restitution"] = sop.Restitution;
  2950. physinfo["PhysicsShapeType"] = (int)sop.PhysicsShapeType;
  2951. array.Add(physinfo);
  2952. }
  2953. OSDMap llsdBody = new OSDMap(1);
  2954. llsdBody.Add("ObjectData", array);
  2955. eq.Enqueue(BuildEvent("ObjectPhysicsProperties", llsdBody),m_agentId);
  2956. */
  2957. }
  2958. public void SendPartPhysicsProprieties(ISceneEntity entity)
  2959. {
  2960. IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
  2961. if (eq is null)
  2962. return;
  2963. if (entity is not SceneObjectPart part)
  2964. return;
  2965. uint localid = part.LocalId;
  2966. byte physshapetype = part.PhysicsShapeType;
  2967. float density = part.Density;
  2968. float friction = part.Friction;
  2969. float bounce = part.Restitution;
  2970. float gravmod = part.GravityModifier;
  2971. eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod, m_agentId);
  2972. }
  2973. public void SendGroupNameReply(UUID groupLLUID, string GroupName)
  2974. {
  2975. UUIDGroupNameReplyPacket pack = new()
  2976. {
  2977. UUIDNameBlock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[]
  2978. {
  2979. new UUIDGroupNameReplyPacket.UUIDNameBlockBlock()
  2980. {
  2981. ID = groupLLUID,
  2982. GroupName = Util.StringToBytes256(GroupName)
  2983. }
  2984. }
  2985. };
  2986. OutPacket(pack, ThrottleOutPacketType.Task);
  2987. }
  2988. public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia)
  2989. {
  2990. IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
  2991. if (eq is null)
  2992. {
  2993. LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length];
  2994. for (int i = 0; i < lsrpia.Length; i++)
  2995. {
  2996. lsrepdba[i] = new LandStatReplyPacket.ReportDataBlock
  2997. {
  2998. LocationX = lsrpia[i].LocationX,
  2999. LocationY = lsrpia[i].LocationY,
  3000. LocationZ = lsrpia[i].LocationZ,
  3001. Score = lsrpia[i].Score,
  3002. TaskID = lsrpia[i].TaskID,
  3003. TaskLocalID = lsrpia[i].TaskLocalID,
  3004. TaskName = Util.StringToBytes256(lsrpia[i].TaskName),
  3005. OwnerName = Util.StringToBytes256(lsrpia[i].OwnerName)
  3006. };
  3007. }
  3008. LandStatReplyPacket lsrp = new();
  3009. lsrp.RequestData.ReportType = reportType;
  3010. lsrp.RequestData.RequestFlags = requestFlags;
  3011. lsrp.RequestData.TotalObjectCount = resultCount;
  3012. lsrp.ReportData = lsrepdba;
  3013. OutPacket(lsrp, ThrottleOutPacketType.Task);
  3014. }
  3015. else
  3016. {
  3017. osUTF8 sb = eq.StartEvent("LandStatReply");
  3018. LLSDxmlEncode2.AddArrayAndMap("RequestData", sb);
  3019. LLSDxmlEncode2.AddElem("ReportType", reportType, sb);
  3020. LLSDxmlEncode2.AddElem("RequestFlags", requestFlags, sb);
  3021. LLSDxmlEncode2.AddElem("TotalObjectCount", (uint)lsrpia.Length, sb);
  3022. LLSDxmlEncode2.AddEndMapAndArray(sb);
  3023. if (lsrpia.Length > 0)
  3024. {
  3025. LLSDxmlEncode2.AddArray("ReportData", sb);
  3026. foreach (var item in lsrpia)
  3027. {
  3028. LLSDxmlEncode2.AddMap(sb);
  3029. LLSDxmlEncode2.AddElem("LocationX", item.LocationX, sb);
  3030. LLSDxmlEncode2.AddElem("LocationY", item.LocationY, sb);
  3031. LLSDxmlEncode2.AddElem("LocationZ", item.LocationZ, sb);
  3032. LLSDxmlEncode2.AddElem("OwnerName", item.OwnerName, sb);
  3033. LLSDxmlEncode2.AddElem("Score", item.Score, sb);
  3034. LLSDxmlEncode2.AddElem("TaskID", item.TaskID, sb);
  3035. LLSDxmlEncode2.AddElem("TaskLocalID", item.TaskLocalID, sb);
  3036. LLSDxmlEncode2.AddElem("TaskName", item.TaskName, sb);
  3037. LLSDxmlEncode2.AddEndMap(sb);
  3038. }
  3039. LLSDxmlEncode2.AddEndArray(sb);
  3040. LLSDxmlEncode2.AddArray("DataExtended", sb);
  3041. foreach (var item in lsrpia)
  3042. {
  3043. LLSDxmlEncode2.AddMap(sb);
  3044. LLSDxmlEncode2.AddElem("MonoScore", 0.0f, sb);
  3045. LLSDxmlEncode2.AddElem("OwnerID", item.OwnerID, sb);
  3046. LLSDxmlEncode2.AddElem("ParcelName", item.Parcel, sb);
  3047. LLSDxmlEncode2.AddElem("PublicURLs", item.Urls, sb);
  3048. LLSDxmlEncode2.AddElem("Size", (float)item.Bytes, sb);
  3049. LLSDxmlEncode2.AddElem("TimeStamp", item.Time, sb);
  3050. LLSDxmlEncode2.AddEndMap(sb);
  3051. }
  3052. LLSDxmlEncode2.AddEndArray(sb);
  3053. }
  3054. eq.Enqueue(eq.EndEventToBytes(sb), m_agentId);
  3055. }
  3056. }
  3057. public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running)
  3058. {
  3059. IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
  3060. if (eq is null)
  3061. {
  3062. ScriptRunningReplyPacket scriptRunningReply = new();
  3063. scriptRunningReply.Script.ObjectID = objectID;
  3064. scriptRunningReply.Script.ItemID = itemID;
  3065. scriptRunningReply.Script.Running = running;
  3066. OutPacket(scriptRunningReply, ThrottleOutPacketType.Task);
  3067. }
  3068. else
  3069. {
  3070. eq.ScriptRunningEvent(objectID, itemID, running, m_agentId);
  3071. }
  3072. }
  3073. public void SendAsset(AssetRequestToClient req)
  3074. {
  3075. if (req.AssetInf is null)
  3076. {
  3077. m_log.Error($"{LogHeader} Cannot send asset, because it is null");
  3078. return;
  3079. }
  3080. if (req.AssetInf.Data is null)
  3081. {
  3082. m_log.Error($"{LogHeader} Cannot send asset {req.AssetInf.ID} ({req.AssetInf.Metadata.ContentType}), asset data is null");
  3083. return;
  3084. }
  3085. TransferInfoPacket Transfer = new();
  3086. Transfer.TransferInfo.ChannelType = 2;
  3087. Transfer.TransferInfo.Status = 0;
  3088. Transfer.TransferInfo.TargetType = 0;
  3089. if (req.AssetRequestSource == 2)
  3090. {
  3091. Transfer.TransferInfo.Params = new byte[20];
  3092. Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
  3093. int assType = req.AssetInf.Type;
  3094. Array.Copy(Utils.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4);
  3095. }
  3096. else if (req.AssetRequestSource == 3)
  3097. {
  3098. Transfer.TransferInfo.Params = req.Params;
  3099. }
  3100. Transfer.TransferInfo.Size = req.AssetInf.Data.Length;
  3101. Transfer.TransferInfo.TransferID = req.TransferRequestID;
  3102. Transfer.Header.Zerocoded = true;
  3103. OutPacket(Transfer, ThrottleOutPacketType.Asset);
  3104. if (req.NumPackets == 1)
  3105. {
  3106. TransferPacketPacket TransferPacket = new();
  3107. TransferPacket.TransferData.Packet = 0;
  3108. TransferPacket.TransferData.ChannelType = 2;
  3109. TransferPacket.TransferData.TransferID = req.TransferRequestID;
  3110. TransferPacket.TransferData.Data = req.AssetInf.Data;
  3111. TransferPacket.TransferData.Status = 1;
  3112. TransferPacket.Header.Zerocoded = true;
  3113. OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
  3114. }
  3115. else
  3116. {
  3117. int processedLength = 0;
  3118. // int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
  3119. int maxChunkSize = (int) MaxTransferBytesPerPacket;
  3120. int packetNumber = 0;
  3121. while (processedLength < req.AssetInf.Data.Length)
  3122. {
  3123. TransferPacketPacket TransferPacket = new();
  3124. TransferPacket.TransferData.Packet = packetNumber;
  3125. TransferPacket.TransferData.ChannelType = 2;
  3126. TransferPacket.TransferData.TransferID = req.TransferRequestID;
  3127. int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize);
  3128. byte[] chunk = new byte[chunkSize];
  3129. Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length);
  3130. TransferPacket.TransferData.Data = chunk;
  3131. // 0 indicates more packets to come, 1 indicates last packet
  3132. if (req.AssetInf.Data.Length - processedLength > maxChunkSize)
  3133. {
  3134. TransferPacket.TransferData.Status = 0;
  3135. }
  3136. else
  3137. {
  3138. TransferPacket.TransferData.Status = 1;
  3139. }
  3140. TransferPacket.Header.Zerocoded = true;
  3141. OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
  3142. processedLength += chunkSize;
  3143. packetNumber++;
  3144. }
  3145. }
  3146. }
  3147. public void SendAssetNotFound(AssetRequestToClient req)
  3148. {
  3149. TransferInfoPacket Transfer = new();
  3150. Transfer.TransferInfo.ChannelType = 2;
  3151. Transfer.TransferInfo.Status = -2;
  3152. Transfer.TransferInfo.TargetType = 0;
  3153. Transfer.TransferInfo.Params = req.Params;
  3154. Transfer.TransferInfo.Size = 0;
  3155. Transfer.TransferInfo.TransferID = req.TransferRequestID;
  3156. Transfer.Header.Zerocoded = true;
  3157. OutPacket(Transfer, ThrottleOutPacketType.Asset);
  3158. }
  3159. public void SendTexture(AssetBase TextureAsset)
  3160. {
  3161. }
  3162. public void SendRegionHandle(UUID regionID, ulong handle)
  3163. {
  3164. RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)PacketPool.Instance.GetPacket(PacketType.RegionIDAndHandleReply);
  3165. reply.ReplyBlock.RegionID = regionID;
  3166. reply.ReplyBlock.RegionHandle = handle;
  3167. OutPacket(reply, ThrottleOutPacketType.Land);
  3168. }
  3169. public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y)
  3170. {
  3171. ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply);
  3172. reply.AgentData.AgentID = m_agentId;
  3173. reply.Data.ParcelID = parcelID;
  3174. reply.Data.OwnerID = land.OwnerID;
  3175. reply.Data.Name = Utils.StringToBytes(land.Name, 63);
  3176. reply.Data.Desc = Utils.StringToBytes(land.Description, 255);
  3177. reply.Data.ActualArea = land.Area;
  3178. reply.Data.BillableArea = land.Area; // TODO: what is this?
  3179. reply.Data.Flags = (byte)Util.ConvertAccessLevelToMaturity((byte)info.AccessLevel);
  3180. if((land.Flags & (uint)ParcelFlags.ForSale) != 0)
  3181. reply.Data.Flags |= (1 << 7);
  3182. if (land.IsGroupOwned)
  3183. reply.Data.Flags |= 0x04;
  3184. Vector3 pos = land.UserLocation;
  3185. if (pos.IsZero())
  3186. {
  3187. pos = (land.AABBMax + land.AABBMin) * 0.5f;
  3188. }
  3189. reply.Data.GlobalX = info.RegionLocX + x;
  3190. reply.Data.GlobalY = info.RegionLocY + y;
  3191. reply.Data.GlobalZ = pos.Z;
  3192. reply.Data.SimName = Utils.StringToBytes(info.RegionName);
  3193. reply.Data.SnapshotID = land.SnapshotID;
  3194. reply.Data.Dwell = land.Dwell;
  3195. reply.Data.SalePrice = land.SalePrice;
  3196. reply.Data.AuctionID = (int)land.AuctionID;
  3197. OutPacket(reply, ThrottleOutPacketType.Land);
  3198. }
  3199. public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt)
  3200. {
  3201. ScriptTeleportRequestPacket packet = (ScriptTeleportRequestPacket)PacketPool.Instance.GetPacket(PacketType.ScriptTeleportRequest);
  3202. packet.Data.ObjectName = Utils.StringToBytes(objName);
  3203. packet.Data.SimName = Utils.StringToBytes(simName);
  3204. packet.Data.SimPosition = pos;
  3205. packet.Data.LookAt = lookAt;
  3206. OutPacket(packet, ThrottleOutPacketType.Task);
  3207. }
  3208. public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data)
  3209. {
  3210. DirPlacesReplyPacket packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply);
  3211. packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock();
  3212. packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1];
  3213. packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock();
  3214. packet.AgentData.AgentID = m_agentId;
  3215. packet.QueryData[0].QueryID = queryID;
  3216. DirPlacesReplyPacket.QueryRepliesBlock[] replies = Array.Empty<DirPlacesReplyPacket.QueryRepliesBlock>();
  3217. DirPlacesReplyPacket.StatusDataBlock[] status = Array.Empty<DirPlacesReplyPacket.StatusDataBlock>();
  3218. packet.QueryReplies = replies;
  3219. packet.StatusData = status;
  3220. foreach (DirPlacesReplyData d in data)
  3221. {
  3222. int idx = replies.Length;
  3223. Array.Resize(ref replies, idx + 1);
  3224. Array.Resize(ref status, idx + 1);
  3225. replies[idx] = new DirPlacesReplyPacket.QueryRepliesBlock();
  3226. status[idx] = new DirPlacesReplyPacket.StatusDataBlock();
  3227. replies[idx].ParcelID = d.parcelID;
  3228. replies[idx].Name = Utils.StringToBytes(d.name);
  3229. replies[idx].ForSale = d.forSale;
  3230. replies[idx].Auction = d.auction;
  3231. replies[idx].Dwell = d.dwell;
  3232. status[idx].Status = d.Status;
  3233. packet.QueryReplies = replies;
  3234. packet.StatusData = status;
  3235. if (packet.Length >= 1000)
  3236. {
  3237. OutPacket(packet, ThrottleOutPacketType.Task);
  3238. packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply);
  3239. packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock();
  3240. packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1];
  3241. packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock();
  3242. packet.AgentData.AgentID = m_agentId;
  3243. packet.QueryData[0].QueryID = queryID;
  3244. replies = Array.Empty<DirPlacesReplyPacket.QueryRepliesBlock>();
  3245. status = Array.Empty<DirPlacesReplyPacket.StatusDataBlock>();
  3246. }
  3247. }
  3248. if (replies.Length > 0 || data.Length == 0)
  3249. OutPacket(packet, ThrottleOutPacketType.Task);
  3250. }
  3251. public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data)
  3252. {
  3253. DirPeopleReplyPacket packet = (DirPeopleReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPeopleReply);
  3254. packet.AgentData = new DirPeopleReplyPacket.AgentDataBlock
  3255. {
  3256. AgentID = m_agentId
  3257. };
  3258. packet.QueryData = new DirPeopleReplyPacket.QueryDataBlock
  3259. {
  3260. QueryID = queryID
  3261. };
  3262. packet.QueryReplies = new DirPeopleReplyPacket.QueryRepliesBlock[data.Length];
  3263. int i = 0;
  3264. foreach (DirPeopleReplyData d in data)
  3265. {
  3266. packet.QueryReplies[i] = new DirPeopleReplyPacket.QueryRepliesBlock
  3267. {
  3268. AgentID = d.agentID,
  3269. FirstName = Utils.StringToBytes(d.firstName),
  3270. LastName = Utils.StringToBytes(d.lastName),
  3271. Group = Utils.StringToBytes(d.group),
  3272. Online = d.online,
  3273. Reputation = d.reputation
  3274. };
  3275. i++;
  3276. }
  3277. OutPacket(packet, ThrottleOutPacketType.Task);
  3278. }
  3279. public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data)
  3280. {
  3281. DirEventsReplyPacket packet = (DirEventsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirEventsReply);
  3282. packet.AgentData = new DirEventsReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3283. packet.QueryData = new DirEventsReplyPacket.QueryDataBlock { QueryID = queryID };
  3284. packet.QueryReplies = new DirEventsReplyPacket.QueryRepliesBlock[data.Length];
  3285. packet.StatusData = new DirEventsReplyPacket.StatusDataBlock[data.Length];
  3286. int i = 0;
  3287. foreach (DirEventsReplyData d in data)
  3288. {
  3289. packet.QueryReplies[i] = new DirEventsReplyPacket.QueryRepliesBlock();
  3290. packet.StatusData[i] = new DirEventsReplyPacket.StatusDataBlock();
  3291. packet.QueryReplies[i].OwnerID = d.ownerID;
  3292. packet.QueryReplies[i].Name = Utils.StringToBytes(d.name);
  3293. packet.QueryReplies[i].EventID = d.eventID;
  3294. packet.QueryReplies[i].Date = Utils.StringToBytes(d.date);
  3295. packet.QueryReplies[i].UnixTime = d.unixTime;
  3296. packet.QueryReplies[i].EventFlags = d.eventFlags;
  3297. packet.StatusData[i].Status = d.Status;
  3298. i++;
  3299. }
  3300. OutPacket(packet, ThrottleOutPacketType.Task);
  3301. }
  3302. public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data)
  3303. {
  3304. DirGroupsReplyPacket packet = (DirGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirGroupsReply);
  3305. packet.AgentData = new DirGroupsReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3306. packet.QueryData = new DirGroupsReplyPacket.QueryDataBlock { QueryID = queryID };
  3307. packet.QueryReplies = new DirGroupsReplyPacket.QueryRepliesBlock[data.Length];
  3308. int i = 0;
  3309. foreach (DirGroupsReplyData d in data)
  3310. {
  3311. packet.QueryReplies[i++] = new DirGroupsReplyPacket.QueryRepliesBlock
  3312. {
  3313. GroupID = d.groupID,
  3314. GroupName = Util.StringToBytes(d.groupName, 35),
  3315. Members = d.members,
  3316. SearchOrder = d.searchOrder
  3317. };
  3318. }
  3319. OutPacket(packet, ThrottleOutPacketType.Task);
  3320. }
  3321. public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data)
  3322. {
  3323. DirClassifiedReplyPacket packet = (DirClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirClassifiedReply);
  3324. packet.AgentData = new DirClassifiedReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3325. packet.QueryData = new DirClassifiedReplyPacket.QueryDataBlock { QueryID = queryID };
  3326. packet.QueryReplies = new DirClassifiedReplyPacket.QueryRepliesBlock[data.Length];
  3327. packet.StatusData = new DirClassifiedReplyPacket.StatusDataBlock[data.Length];
  3328. int i = 0;
  3329. foreach (DirClassifiedReplyData d in data)
  3330. {
  3331. packet.QueryReplies[i] = new DirClassifiedReplyPacket.QueryRepliesBlock();
  3332. packet.StatusData[i] = new DirClassifiedReplyPacket.StatusDataBlock();
  3333. packet.QueryReplies[i].ClassifiedID = d.classifiedID;
  3334. packet.QueryReplies[i].Name = Utils.StringToBytes(d.name);
  3335. packet.QueryReplies[i].ClassifiedFlags = d.classifiedFlags;
  3336. packet.QueryReplies[i].CreationDate = d.creationDate;
  3337. packet.QueryReplies[i].ExpirationDate = d.expirationDate;
  3338. packet.QueryReplies[i].PriceForListing = d.price;
  3339. packet.StatusData[i].Status = d.Status;
  3340. i++;
  3341. }
  3342. OutPacket(packet, ThrottleOutPacketType.Task);
  3343. }
  3344. public void SendDirLandReply(UUID queryID, DirLandReplyData[] data)
  3345. {
  3346. DirLandReplyPacket packet = (DirLandReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirLandReply);
  3347. packet.AgentData = new DirLandReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3348. packet.QueryData = new DirLandReplyPacket.QueryDataBlock { QueryID = queryID };
  3349. packet.QueryReplies = new DirLandReplyPacket.QueryRepliesBlock[data.Length];
  3350. int i = 0;
  3351. foreach (DirLandReplyData d in data)
  3352. {
  3353. packet.QueryReplies[i++] = new DirLandReplyPacket.QueryRepliesBlock
  3354. {
  3355. ParcelID = d.parcelID,
  3356. Name = Utils.StringToBytes(d.name),
  3357. Auction = d.auction,
  3358. ForSale = d.forSale,
  3359. SalePrice = d.salePrice,
  3360. ActualArea = d.actualArea
  3361. };
  3362. }
  3363. OutPacket(packet, ThrottleOutPacketType.Task);
  3364. }
  3365. public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data)
  3366. {
  3367. DirPopularReplyPacket packet = (DirPopularReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPopularReply);
  3368. packet.AgentData = new DirPopularReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3369. packet.QueryData = new DirPopularReplyPacket.QueryDataBlock{ QueryID = queryID };
  3370. packet.QueryReplies = new DirPopularReplyPacket.QueryRepliesBlock[data.Length];
  3371. int i = 0;
  3372. foreach (DirPopularReplyData d in data)
  3373. {
  3374. packet.QueryReplies[i++] = new DirPopularReplyPacket.QueryRepliesBlock
  3375. {
  3376. ParcelID = d.parcelID,
  3377. Name = Utils.StringToBytes(d.name),
  3378. Dwell = d.dwell
  3379. };
  3380. }
  3381. OutPacket(packet, ThrottleOutPacketType.Task);
  3382. }
  3383. public void SendEventInfoReply(EventData data)
  3384. {
  3385. EventInfoReplyPacket packet = (EventInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.EventInfoReply);
  3386. packet.AgentData = new EventInfoReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3387. packet.EventData = new EventInfoReplyPacket.EventDataBlock
  3388. {
  3389. EventID = data.eventID,
  3390. Creator = Utils.StringToBytes(data.creator),
  3391. Name = Utils.StringToBytes(data.name),
  3392. Category = Utils.StringToBytes(data.category),
  3393. Desc = Utils.StringToBytes(data.description),
  3394. Date = Utils.StringToBytes(data.date),
  3395. DateUTC = data.dateUTC,
  3396. Duration = data.duration,
  3397. Cover = data.cover,
  3398. Amount = data.amount,
  3399. SimName = Utils.StringToBytes(data.simName),
  3400. GlobalPos = new Vector3d(data.globalPos),
  3401. EventFlags = data.eventFlags
  3402. };
  3403. OutPacket(packet, ThrottleOutPacketType.Task);
  3404. }
  3405. public void SendOfferCallingCard(UUID srcID, UUID transactionID)
  3406. {
  3407. // a bit special, as this uses AgentID to store the source instead
  3408. // of the destination. The destination (the receiver) goes into destID
  3409. OfferCallingCardPacket p = (OfferCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.OfferCallingCard);
  3410. p.AgentData.AgentID = srcID;
  3411. p.AgentData.SessionID = UUID.Zero;
  3412. p.AgentBlock.DestID = m_agentId;
  3413. p.AgentBlock.TransactionID = transactionID;
  3414. OutPacket(p, ThrottleOutPacketType.Task);
  3415. }
  3416. public void SendAcceptCallingCard(UUID transactionID)
  3417. {
  3418. AcceptCallingCardPacket p = (AcceptCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.AcceptCallingCard);
  3419. p.AgentData.AgentID = m_agentId;
  3420. p.AgentData.SessionID = UUID.Zero;
  3421. p.FolderData = new AcceptCallingCardPacket.FolderDataBlock[1];
  3422. p.FolderData[0] = new AcceptCallingCardPacket.FolderDataBlock
  3423. {
  3424. FolderID = UUID.Zero
  3425. };
  3426. OutPacket(p, ThrottleOutPacketType.Task);
  3427. }
  3428. public void SendDeclineCallingCard(UUID transactionID)
  3429. {
  3430. DeclineCallingCardPacket p = (DeclineCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.DeclineCallingCard);
  3431. p.AgentData.AgentID = m_agentId;
  3432. p.AgentData.SessionID = UUID.Zero;
  3433. p.TransactionBlock.TransactionID = transactionID;
  3434. OutPacket(p, ThrottleOutPacketType.Task);
  3435. }
  3436. public void SendTerminateFriend(UUID exFriendID)
  3437. {
  3438. TerminateFriendshipPacket p = (TerminateFriendshipPacket)PacketPool.Instance.GetPacket(PacketType.TerminateFriendship);
  3439. p.AgentData.AgentID = m_agentId;
  3440. p.AgentData.SessionID = SessionId;
  3441. p.ExBlock.OtherID = exFriendID;
  3442. OutPacket(p, ThrottleOutPacketType.Task);
  3443. }
  3444. public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data)
  3445. {
  3446. IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
  3447. if (eq is null)
  3448. return;
  3449. // message template has a GroupData field AcceptNotices ignored by viewers
  3450. // and a array NewGroupData also ignored
  3451. osUTF8 sb = eq.StartEvent("AvatarGroupsReply");
  3452. LLSDxmlEncode2.AddArrayAndMap("AgentData", sb);
  3453. LLSDxmlEncode2.AddElem("AgentID", m_agentId, sb);
  3454. LLSDxmlEncode2.AddElem("AvatarID", avatarID, sb);
  3455. LLSDxmlEncode2.AddEndMapAndArray(sb);
  3456. bool notSameAvatar = avatarID != m_agentId;
  3457. if(data.Length == 0)
  3458. LLSDxmlEncode2.AddEmptyArray("GroupData", sb);
  3459. else
  3460. {
  3461. LLSDxmlEncode2.AddArray("GroupData", sb);
  3462. GroupMembershipData m;
  3463. for (int indx = 0; indx < data.Length; ++indx)
  3464. {
  3465. m = data[indx];
  3466. if(notSameAvatar && !m.ListInProfile)
  3467. continue;
  3468. LLSDxmlEncode2.AddMap(sb);
  3469. LLSDxmlEncode2.AddElem("GroupPowers", m.GroupPowers, sb);
  3470. LLSDxmlEncode2.AddElem("GroupTitle", m.GroupTitle, sb);
  3471. LLSDxmlEncode2.AddElem("GroupID",m.GroupID, sb);
  3472. LLSDxmlEncode2.AddElem("GroupName", m.GroupName, sb);
  3473. LLSDxmlEncode2.AddElem("GroupInsigniaID", m.GroupPicture, sb);
  3474. LLSDxmlEncode2.AddEndMap(sb);
  3475. }
  3476. LLSDxmlEncode2.AddEndArray(sb);
  3477. }
  3478. eq.Enqueue(eq.EndEventToBytes(sb), m_agentId);
  3479. }
  3480. public void SendAgentGroupDataUpdate(UUID avatarID, GroupMembershipData[] data)
  3481. {
  3482. if(avatarID != m_agentId)
  3483. m_log.Debug("[CLIENT]: SendAgentGroupDataUpdate avatarID != AgentId");
  3484. IEventQueue eq = this.Scene.RequestModuleInterface<IEventQueue>();
  3485. if(eq != null)
  3486. {
  3487. eq.GroupMembershipData(avatarID,data);
  3488. }
  3489. else
  3490. {
  3491. // use UDP if no caps
  3492. AgentGroupDataUpdatePacket Groupupdate = new();
  3493. AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[data.Length];
  3494. for (int i = 0; i < data.Length; ++i)
  3495. {
  3496. AgentGroupDataUpdatePacket.GroupDataBlock Group = new()
  3497. {
  3498. AcceptNotices = data[i].AcceptNotices,
  3499. Contribution = data[i].Contribution,
  3500. GroupID = data[i].GroupID,
  3501. GroupInsigniaID = data[i].GroupPicture,
  3502. GroupName = Util.StringToBytes256(data[i].GroupName),
  3503. GroupPowers = data[i].GroupPowers
  3504. };
  3505. Groups[i] = Group;
  3506. }
  3507. Groupupdate.GroupData = Groups;
  3508. Groupupdate.AgentData = new AgentGroupDataUpdatePacket.AgentDataBlock { AgentID = avatarID };
  3509. OutPacket(Groupupdate, ThrottleOutPacketType.Task);
  3510. }
  3511. }
  3512. public void SendJoinGroupReply(UUID groupID, bool success)
  3513. {
  3514. JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply);
  3515. p.AgentData = new JoinGroupReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3516. p.GroupData = new JoinGroupReplyPacket.GroupDataBlock
  3517. {
  3518. GroupID = groupID,
  3519. Success = success
  3520. };
  3521. OutPacket(p, ThrottleOutPacketType.Task);
  3522. }
  3523. public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success)
  3524. {
  3525. EjectGroupMemberReplyPacket p = (EjectGroupMemberReplyPacket)PacketPool.Instance.GetPacket(PacketType.EjectGroupMemberReply);
  3526. p.AgentData = new EjectGroupMemberReplyPacket.AgentDataBlock { AgentID = agentID };
  3527. p.GroupData = new EjectGroupMemberReplyPacket.GroupDataBlock { GroupID = groupID };
  3528. p.EjectData = new EjectGroupMemberReplyPacket.EjectDataBlock { Success = success };
  3529. OutPacket(p, ThrottleOutPacketType.Task);
  3530. }
  3531. public void SendLeaveGroupReply(UUID groupID, bool success)
  3532. {
  3533. LeaveGroupReplyPacket p = (LeaveGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.LeaveGroupReply);
  3534. p.AgentData = new LeaveGroupReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3535. p.GroupData = new LeaveGroupReplyPacket.GroupDataBlock
  3536. {
  3537. GroupID = groupID,
  3538. Success = success
  3539. };
  3540. OutPacket(p, ThrottleOutPacketType.Task);
  3541. }
  3542. public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name)
  3543. {
  3544. if (classifiedID.Length != name.Length)
  3545. return;
  3546. AvatarClassifiedReplyPacket ac =
  3547. (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarClassifiedReply);
  3548. ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock
  3549. {
  3550. AgentID = m_agentId,
  3551. TargetID = targetID
  3552. };
  3553. ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifiedID.Length];
  3554. int i;
  3555. for (i = 0; i < classifiedID.Length; i++)
  3556. {
  3557. ac.Data[i].ClassifiedID = classifiedID[i];
  3558. ac.Data[i].Name = Utils.StringToBytes(name[i]);
  3559. }
  3560. OutPacket(ac, ThrottleOutPacketType.Task);
  3561. }
  3562. public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price)
  3563. {
  3564. // fix classifiedFlags maturity
  3565. if((classifiedFlags & 0x4e) == 0) // if none
  3566. classifiedFlags |= 0x4; // pg
  3567. ClassifiedInfoReplyPacket cr =
  3568. (ClassifiedInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ClassifiedInfoReply);
  3569. cr.AgentData = new ClassifiedInfoReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3570. cr.Data = new ClassifiedInfoReplyPacket.DataBlock
  3571. {
  3572. ClassifiedID = classifiedID,
  3573. CreatorID = creatorID,
  3574. CreationDate = creationDate,
  3575. ExpirationDate = expirationDate,
  3576. Category = category,
  3577. Name = Utils.StringToBytes(name),
  3578. Desc = Utils.StringToBytes(description),
  3579. ParcelID = parcelID,
  3580. ParentEstate = parentEstate,
  3581. SnapshotID = snapshotID,
  3582. SimName = Utils.StringToBytes(simName),
  3583. PosGlobal = new Vector3d(globalPos),
  3584. ParcelName = Utils.StringToBytes(parcelName),
  3585. ClassifiedFlags = classifiedFlags,
  3586. PriceForListing = price
  3587. };
  3588. OutPacket(cr, ThrottleOutPacketType.Task);
  3589. }
  3590. public void SendAgentDropGroup(UUID groupID)
  3591. {
  3592. AgentDropGroupPacket dg = (AgentDropGroupPacket)PacketPool.Instance.GetPacket(PacketType.AgentDropGroup);
  3593. dg.AgentData = new AgentDropGroupPacket.AgentDataBlock
  3594. {
  3595. AgentID = m_agentId,
  3596. GroupID = groupID
  3597. };
  3598. OutPacket(dg, ThrottleOutPacketType.Task);
  3599. }
  3600. public void SendAvatarNotesReply(UUID targetID, string text)
  3601. {
  3602. AvatarNotesReplyPacket an = (AvatarNotesReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarNotesReply);
  3603. an.AgentData = new AvatarNotesReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3604. an.Data = new AvatarNotesReplyPacket.DataBlock
  3605. {
  3606. TargetID = targetID,
  3607. Notes = Utils.StringToBytes(text)
  3608. };
  3609. OutPacket(an, ThrottleOutPacketType.Task);
  3610. }
  3611. public void SendAvatarPicksReply(UUID targetID, Dictionary<UUID, string> picks)
  3612. {
  3613. AvatarPicksReplyPacket ap = (AvatarPicksReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPicksReply);
  3614. ap.AgentData = new AvatarPicksReplyPacket.AgentDataBlock
  3615. {
  3616. AgentID = m_agentId,
  3617. TargetID = targetID
  3618. };
  3619. ap.Data = new AvatarPicksReplyPacket.DataBlock[picks.Count];
  3620. int i = 0;
  3621. foreach (KeyValuePair<UUID, string> pick in picks)
  3622. {
  3623. ap.Data[i++] = new AvatarPicksReplyPacket.DataBlock
  3624. {
  3625. PickID = pick.Key,
  3626. PickName = Utils.StringToBytes(pick.Value)
  3627. };
  3628. }
  3629. OutPacket(ap, ThrottleOutPacketType.Task);
  3630. }
  3631. public void SendAvatarClassifiedReply(UUID targetID, Dictionary<UUID, string> classifieds)
  3632. {
  3633. AvatarClassifiedReplyPacket ac =
  3634. (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarClassifiedReply);
  3635. ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock
  3636. {
  3637. AgentID = m_agentId,
  3638. TargetID = targetID
  3639. };
  3640. ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifieds.Count];
  3641. int i = 0;
  3642. foreach (KeyValuePair<UUID, string> classified in classifieds)
  3643. {
  3644. ac.Data[i++] = new AvatarClassifiedReplyPacket.DataBlock
  3645. {
  3646. ClassifiedID = classified.Key,
  3647. Name = Utils.StringToBytes(classified.Value)
  3648. };
  3649. }
  3650. OutPacket(ac, ThrottleOutPacketType.Task);
  3651. }
  3652. public void SendParcelDwellReply(int localID, UUID parcelID, float dwell)
  3653. {
  3654. ParcelDwellReplyPacket pd =
  3655. (ParcelDwellReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelDwellReply);
  3656. pd.AgentData = new ParcelDwellReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3657. pd.Data = new ParcelDwellReplyPacket.DataBlock
  3658. {
  3659. LocalID = localID,
  3660. ParcelID = parcelID,
  3661. Dwell = dwell
  3662. };
  3663. OutPacket(pd, ThrottleOutPacketType.Land);
  3664. }
  3665. public void SendUserInfoReply(bool imViaEmail, bool visible, string email)
  3666. {
  3667. UserInfoReplyPacket ur =
  3668. (UserInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.UserInfoReply);
  3669. ur.AgentData = new UserInfoReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3670. ur.UserData = new UserInfoReplyPacket.UserDataBlock
  3671. {
  3672. IMViaEMail = imViaEmail,
  3673. DirectoryVisibility = Utils.StringToBytes(visible ? "default" : "hidden"),
  3674. EMail = Utils.StringToBytes(email)
  3675. };
  3676. OutPacket(ur, ThrottleOutPacketType.Task);
  3677. }
  3678. public void SendCreateGroupReply(UUID groupID, bool success, string message)
  3679. {
  3680. CreateGroupReplyPacket createGroupReply = (CreateGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.CreateGroupReply);
  3681. createGroupReply.AgentData = new CreateGroupReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3682. createGroupReply.ReplyData = new CreateGroupReplyPacket.ReplyDataBlock
  3683. {
  3684. GroupID = groupID,
  3685. Success = success,
  3686. Message = Utils.StringToBytes(message)
  3687. };
  3688. OutPacket(createGroupReply, ThrottleOutPacketType.Task);
  3689. }
  3690. public void SendUseCachedMuteList()
  3691. {
  3692. UseCachedMuteListPacket useCachedMuteList = (UseCachedMuteListPacket)PacketPool.Instance.GetPacket(PacketType.UseCachedMuteList);
  3693. useCachedMuteList.AgentData = new UseCachedMuteListPacket.AgentDataBlock { AgentID = m_agentId };
  3694. OutPacket(useCachedMuteList, ThrottleOutPacketType.Task);
  3695. }
  3696. public void SendEmpytMuteList()
  3697. {
  3698. GenericMessagePacket gmp = new();
  3699. gmp.AgentData.AgentID = m_agentId;
  3700. gmp.AgentData.SessionID = m_sessionId;
  3701. gmp.AgentData.TransactionID = UUID.Zero;
  3702. gmp.MethodData.Method = Util.StringToBytes256("emptymutelist");
  3703. gmp.ParamList = new GenericMessagePacket.ParamListBlock[1];
  3704. gmp.ParamList[0] = new GenericMessagePacket.ParamListBlock { Parameter = Array.Empty<byte>() };
  3705. OutPacket(gmp, ThrottleOutPacketType.Task);
  3706. }
  3707. public void SendMuteListUpdate(string filename)
  3708. {
  3709. MuteListUpdatePacket muteListUpdate = (MuteListUpdatePacket)PacketPool.Instance.GetPacket(PacketType.MuteListUpdate);
  3710. muteListUpdate.MuteData = new MuteListUpdatePacket.MuteDataBlock
  3711. {
  3712. AgentID = m_agentId,
  3713. Filename = Utils.StringToBytes(filename)
  3714. };
  3715. OutPacket(muteListUpdate, ThrottleOutPacketType.Task);
  3716. }
  3717. public void SendPickInfoReply(UUID pickID, UUID creatorID, bool topPick, UUID parcelID, string name, string desc, UUID snapshotID, string user, string originalName, string simName, Vector3 posGlobal, int sortOrder, bool enabled)
  3718. {
  3719. PickInfoReplyPacket pickInfoReply = (PickInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.PickInfoReply);
  3720. pickInfoReply.AgentData = new PickInfoReplyPacket.AgentDataBlock { AgentID = m_agentId };
  3721. pickInfoReply.Data = new PickInfoReplyPacket.DataBlock
  3722. {
  3723. PickID = pickID,
  3724. CreatorID = creatorID,
  3725. TopPick = topPick,
  3726. ParcelID = parcelID,
  3727. Name = Utils.StringToBytes(name),
  3728. Desc = Utils.StringToBytes(desc),
  3729. SnapshotID = snapshotID,
  3730. User = Utils.StringToBytes(user),
  3731. OriginalName = Utils.StringToBytes(originalName),
  3732. SimName = Utils.StringToBytes(simName),
  3733. PosGlobal = new Vector3d(posGlobal),
  3734. SortOrder = sortOrder,
  3735. Enabled = enabled
  3736. };
  3737. OutPacket(pickInfoReply, ThrottleOutPacketType.Task);
  3738. }
  3739. #endregion Scene/Avatar to Client
  3740. // Gesture
  3741. #region Appearance/ Wearables Methods
  3742. public void SendWearables(AvatarWearable[] wearables, int serial)
  3743. {
  3744. AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate);
  3745. aw.AgentData.AgentID = m_agentId;
  3746. aw.AgentData.SerialNum = (uint)serial;
  3747. aw.AgentData.SessionID = m_sessionId;
  3748. int count = 0;
  3749. for (int i = 0; i < wearables.Length; i++)
  3750. count += wearables[i].Count;
  3751. // TODO: don't create new blocks if recycling an old packet
  3752. aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count];
  3753. AgentWearablesUpdatePacket.WearableDataBlock awb;
  3754. int idx = 0;
  3755. for (int i = 0; i < wearables.Length; i++)
  3756. {
  3757. for (int j = 0; j < wearables[i].Count; j++)
  3758. {
  3759. awb = new AgentWearablesUpdatePacket.WearableDataBlock
  3760. {
  3761. WearableType = (byte)i,
  3762. AssetID = wearables[i][j].AssetID,
  3763. ItemID = wearables[i][j].ItemID
  3764. };
  3765. aw.WearableData[idx++] = awb;
  3766. //m_log.DebugFormat(
  3767. // "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}",
  3768. // awb.ItemID, awb.AssetID, i, Name);
  3769. }
  3770. }
  3771. OutPacket(aw, ThrottleOutPacketType.Task);
  3772. }
  3773. static private readonly byte[] AvatarAppearanceHeader = new byte[] {
  3774. Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED,
  3775. 0, 0, 0, 0, // sequence number
  3776. 0, // extra
  3777. 0xff, 0xff, 0, 158 // ID 158 (low frequency bigendian) not zeroencoded
  3778. //0xff, 0xff, 0, 1, 158 // ID 158 (low frequency bigendian) zeroencoded
  3779. };
  3780. public void SendAppearance(UUID targetID, byte[] visualParams, byte[] textureEntry, float hover)
  3781. {
  3782. // doing post zero encode, because odds of beeing bad are not that low
  3783. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  3784. Buffer.BlockCopy(AvatarAppearanceHeader, 0, buf.Data, 0, 10);
  3785. byte[] data = buf.Data;
  3786. int pos = 10;
  3787. //sender block
  3788. targetID.ToBytes(data, pos); pos += 16;
  3789. data[pos++] = 0;// is trial = false
  3790. // objectdata block ie texture
  3791. int len = textureEntry.Length;
  3792. if (len == 0)
  3793. {
  3794. data[pos++] = 0;
  3795. data[pos++] = 0;
  3796. }
  3797. else
  3798. {
  3799. data[pos++] = (byte)len;
  3800. data[pos++] = (byte)(len >> 8);
  3801. Buffer.BlockCopy(textureEntry, 0, data, pos, len); pos += len;
  3802. }
  3803. // visual parameters
  3804. len = visualParams.Length;
  3805. data[pos++] = (byte)len;
  3806. if(len > 0)
  3807. Buffer.BlockCopy(visualParams, 0, data, pos, len); pos += len;
  3808. // no AppearanceData
  3809. data[pos++] = 0;
  3810. // AppearanceHover vector 3
  3811. data[pos++] = 1;
  3812. Utils.FloatToBytesSafepos(0, data, pos); pos += 4;
  3813. Utils.FloatToBytesSafepos(0, data, pos); pos += 4;
  3814. Utils.FloatToBytesSafepos(hover, data, pos); pos += 4;
  3815. buf.DataLength = pos;
  3816. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, true);
  3817. }
  3818. static private readonly byte[] AvatarAnimationHeader = new byte[] {
  3819. Helpers.MSG_RELIABLE,
  3820. 0, 0, 0, 0, // sequence number
  3821. 0, // extra
  3822. 20 // ID (high frequency)
  3823. };
  3824. public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
  3825. {
  3826. // m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name);
  3827. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  3828. byte[] data = buf.Data;
  3829. //setup header
  3830. Buffer.BlockCopy(AvatarAnimationHeader, 0, data, 0, 7);
  3831. //agent block
  3832. sourceAgentId.ToBytes(data, 7);
  3833. // animations count
  3834. data[23] = (byte)animations.Length;
  3835. int pos = 24;
  3836. //self animations
  3837. if (sourceAgentId.Equals(m_agentId))
  3838. {
  3839. List<int> withobjects = new(animations.Length);
  3840. List<int> noobjects = new(animations.Length);
  3841. for (int indx = 0; indx < animations.Length; ++indx)
  3842. {
  3843. if (objectIDs[indx].Equals(sourceAgentId) || objectIDs[indx].IsZero())
  3844. noobjects.Add(indx);
  3845. else
  3846. withobjects.Add(indx);
  3847. }
  3848. int i;
  3849. // first the ones with corresponding objects
  3850. for (int indx = 0; indx < withobjects.Count; ++indx)
  3851. {
  3852. i = withobjects[indx];
  3853. animations[i].ToBytes(data, pos); pos += 16;
  3854. Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
  3855. }
  3856. // then the rest
  3857. for (int indx = 0; indx < noobjects.Count; ++indx)
  3858. {
  3859. i = noobjects[indx];
  3860. animations[i].ToBytes(data, pos); pos += 16;
  3861. Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
  3862. }
  3863. // object ids block
  3864. data[pos++] = (byte)withobjects.Count;
  3865. for (int indx = 0; indx < withobjects.Count; ++indx)
  3866. {
  3867. i = withobjects[indx];
  3868. objectIDs[i].ToBytes(data, pos); pos += 16;
  3869. }
  3870. }
  3871. else
  3872. {
  3873. for(int i = 0; i < animations.Length; ++i)
  3874. {
  3875. animations[i].ToBytes(data, pos); pos += 16;
  3876. Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
  3877. }
  3878. data[pos++] = 0; // no object ids
  3879. }
  3880. data[pos++] = 0; // no physical avatar events
  3881. buf.DataLength = pos;
  3882. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  3883. }
  3884. public void SendObjectAnimations(UUID[] animations, int[] seqs, UUID senderId)
  3885. {
  3886. // m_log.DebugFormat("[LLCLIENTVIEW]: Sending Object animations for {0} to {1}", sourceAgentId, Name);
  3887. if(!m_SupportObjectAnimations)
  3888. return;
  3889. ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation);
  3890. // TODO: don't create new blocks if recycling an old packet
  3891. ani.Sender = new ObjectAnimationPacket.SenderBlock
  3892. {
  3893. ID = senderId
  3894. };
  3895. ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[animations.Length];
  3896. for (int i = 0; i < animations.Length; ++i)
  3897. {
  3898. ani.AnimationList[i] = new ObjectAnimationPacket.AnimationListBlock
  3899. {
  3900. AnimID = animations[i],
  3901. AnimSequenceID = seqs[i]
  3902. };
  3903. }
  3904. OutPacket(ani, ThrottleOutPacketType.Task);
  3905. }
  3906. #endregion
  3907. #region Avatar Packet/Data Sending Methods
  3908. /// <summary>
  3909. /// Send an ObjectUpdate packet with information about an avatar
  3910. /// </summary>
  3911. public void SendEntityFullUpdateImmediate(ISceneEntity ent)
  3912. {
  3913. if (ent is not ScenePresence && ent is not SceneObjectPart)
  3914. return;
  3915. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  3916. Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7);
  3917. LLUDPZeroEncoder zc = new(buf.Data);
  3918. zc.Position = 7;
  3919. zc.AddUInt64(m_scene.RegionInfo.RegionHandle);
  3920. zc.AddUInt16(Utils.FloatZeroOneToushort(m_scene.TimeDilation));
  3921. zc.AddByte(1); // block count
  3922. if (ent is ScenePresence sp)
  3923. CreateAvatarUpdateBlock(sp, zc);
  3924. else
  3925. CreatePrimUpdateBlock(ent as SceneObjectPart, (ScenePresence)SceneAgent, zc);
  3926. buf.DataLength = zc.Finish();
  3927. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  3928. }
  3929. public unsafe void SendEntityTerseUpdateImmediate(ISceneEntity ent)
  3930. {
  3931. if (ent is null)
  3932. return;
  3933. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  3934. //setup header and regioninfo block
  3935. Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7);
  3936. fixed(byte* bdata = &buf.Data[0])
  3937. {
  3938. Utils.UInt16ToBytes(Utils.FloatZeroOneToushort(m_scene.TimeDilation), bdata + 15);
  3939. bdata[17] = 1;
  3940. byte* data = bdata + 18;
  3941. if (ent is ScenePresence sp)
  3942. {
  3943. Utils.UInt64ToBytes(sp.RegionHandle, bdata + 7);
  3944. CreateAvatartImprovedTerseBlock(sp, ref data);
  3945. }
  3946. else
  3947. {
  3948. Utils.UInt64ToBytes(m_scene.RegionInfo.RegionHandle, bdata + 7);
  3949. CreatePartImprovedTerseBlock((SceneObjectPart)ent, ref data, false);
  3950. }
  3951. buf.DataLength = (int)(data - bdata);
  3952. }
  3953. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, true);
  3954. }
  3955. //UUID m_courseLocationPrey = UUID.Zero;
  3956. bool m_couseLocationLastEmpty = false;
  3957. static private readonly byte[] CoarseLocationUpdateHeader = new byte[] {
  3958. 0, // no acks plz
  3959. 0, 0, 0, 0, // sequence number
  3960. 0, // extra
  3961. 0xff, 6 // ID 6 (medium frequency)
  3962. };
  3963. public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
  3964. {
  3965. // We don't need to update inactive clients.
  3966. if (!IsActive)
  3967. return;
  3968. int totalLocations = Math.Min(CoarseLocations.Count, 60);
  3969. if(totalLocations == 0)
  3970. {
  3971. if(m_couseLocationLastEmpty)
  3972. return;
  3973. m_couseLocationLastEmpty = true;
  3974. }
  3975. else
  3976. m_couseLocationLastEmpty = false;
  3977. int totalAgents = Math.Min(users.Count, 60);
  3978. if(totalAgents > totalLocations)
  3979. totalAgents = totalLocations;
  3980. int selfindex = -1;
  3981. int preyindex = -1;
  3982. //bool doprey = m_courseLocationPrey != UUID.Zero;
  3983. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  3984. Buffer.BlockCopy(CoarseLocationUpdateHeader, 0, buf.Data, 0, 8);
  3985. byte[] data = buf.Data;
  3986. data[8] = (byte)totalLocations;
  3987. int pos = 9;
  3988. for (int i = 0; i < totalLocations; ++i)
  3989. {
  3990. data[pos++] = (byte)CoarseLocations[i].X;
  3991. data[pos++] = (byte)CoarseLocations[i].Y;
  3992. data[pos++] = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25f);
  3993. if (i < totalAgents)
  3994. {
  3995. if (users[i] == m_agentId)
  3996. selfindex = i;
  3997. //if (doprey && users[i] == m_courseLocationPrey)
  3998. // preyindex = i;
  3999. }
  4000. }
  4001. Utils.Int16ToBytes((short)selfindex, data, pos); pos += 2;
  4002. Utils.Int16ToBytes((short)preyindex, data, pos); pos += 2;
  4003. data[pos++] = (byte)totalAgents;
  4004. for (int i = 0; i < totalAgents; ++i)
  4005. {
  4006. users[i].ToBytes(data, pos);
  4007. pos += 16;
  4008. }
  4009. buf.DataLength = pos;
  4010. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  4011. }
  4012. #endregion Avatar Packet/Data Sending Methods
  4013. #region Primitive Packet/Data Sending Methods
  4014. /// <summary>
  4015. /// Generate one of the object update packets based on PrimUpdateFlags
  4016. /// and broadcast the packet to clients
  4017. /// </summary>
  4018. public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
  4019. {
  4020. if (entity is SceneObjectPart p)
  4021. {
  4022. SceneObjectGroup g = p.ParentGroup;
  4023. if (g.HasPrivateAttachmentPoint && g.OwnerID != m_agentId)
  4024. return; // Don't send updates for other people's HUDs
  4025. if((updateFlags ^ PrimUpdateFlags.SendInTransit) == 0)
  4026. {
  4027. List<uint> partIDs = (new List<uint> {p.LocalId});
  4028. m_entityProps.Remove(partIDs);
  4029. m_entityUpdates.Remove(partIDs);
  4030. return;
  4031. }
  4032. }
  4033. int priority = m_prioritizer.GetUpdatePriority(this, entity);
  4034. m_entityUpdates.Enqueue(priority, EntityUpdatesPool.Get(entity, updateFlags));
  4035. }
  4036. /// <summary>
  4037. /// Requeue an EntityUpdate when it was not acknowledged by the client.
  4038. /// We will update the priority and put it in the correct queue, merging update flags
  4039. /// with any other updates that may be queued for the same entity.
  4040. /// The original update time is used for the merged update.
  4041. /// </summary>
  4042. private void ResendPrimUpdate(EntityUpdate update)
  4043. {
  4044. // If the update exists in priority queue, it will be updated.
  4045. // If it does not exist then it will be added with the current (rather than its original) priority
  4046. int priority = m_prioritizer.GetUpdatePriority(this, update.Entity);
  4047. m_entityUpdates.Enqueue(priority, update);
  4048. }
  4049. /// <summary>
  4050. /// Requeue a list of EntityUpdates when they were not acknowledged by the client.
  4051. /// We will update the priority and put it in the correct queue, merging update flags
  4052. /// with any other updates that may be queued for the same entity.
  4053. /// The original update time is used for the merged update.
  4054. /// </summary>
  4055. private void ResendPrimUpdates(List<EntityUpdate> updates, OutgoingPacket oPacket)
  4056. {
  4057. // m_log.WarnFormat("[CLIENT] resending prim updates {0}, packet sequence number {1}", updates[0].UpdateTime, oPacket.SequenceNumber);
  4058. // Remove the update packet from the list of packets waiting for acknowledgement
  4059. // because we are requeuing the list of updates. They will be resent in new packets
  4060. // with the most recent state and priority.
  4061. m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
  4062. if (oPacket.Buffer is null)
  4063. return;
  4064. // Count this as a resent packet since we are going to requeue all of the updates contained in it
  4065. Interlocked.Increment(ref m_udpClient.PacketsResent);
  4066. m_udpServer.PacketsResentCount++;
  4067. foreach (EntityUpdate update in updates)
  4068. ResendPrimUpdate(update);
  4069. }
  4070. static private readonly byte[] objectUpdateHeader = new byte[] {
  4071. Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED,
  4072. 0, 0, 0, 0, // sequence number
  4073. 0, // extra
  4074. 12 // ID (high frequency)
  4075. };
  4076. static private readonly byte[] terseUpdateHeader = new byte[] {
  4077. Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, // zero code is not as spec
  4078. 0, 0, 0, 0, // sequence number
  4079. 0, // extra
  4080. 15 // ID (high frequency)
  4081. };
  4082. static private readonly byte[] ObjectAnimationHeader = new byte[] {
  4083. Helpers.MSG_RELIABLE,
  4084. 0, 0, 0, 0, // sequence number
  4085. 0, // extra
  4086. 30 // ID (high frequency)
  4087. };
  4088. static private readonly byte[] CompressedObjectHeader = new byte[] {
  4089. Helpers.MSG_RELIABLE,
  4090. 0, 0, 0, 0, // sequence number
  4091. 0, // extra
  4092. 13 // ID (high frequency)
  4093. };
  4094. static private readonly byte[] ObjectUpdateCachedHeader = new byte[] {
  4095. Helpers.MSG_RELIABLE,
  4096. 0, 0, 0, 0, // sequence number
  4097. 0, // extra
  4098. 14 // ID (high frequency)
  4099. };
  4100. private void ProcessEntityUpdates(int maxUpdatesBytes)
  4101. {
  4102. if (!IsActive)
  4103. return;
  4104. ScenePresence mysp = (ScenePresence)SceneAgent;
  4105. if (mysp is null)
  4106. return;
  4107. List<EntityUpdate> objectUpdates = null;
  4108. List<EntityUpdate> objectUpdateProbes = null;
  4109. List<EntityUpdate> compressedUpdates = null;
  4110. List<EntityUpdate> terseUpdates = null;
  4111. List<SceneObjectPart> ObjectAnimationUpdates = null;
  4112. List<SceneObjectPart> needMaterials = null;
  4113. // Check to see if this is a flush
  4114. if (maxUpdatesBytes <= 0)
  4115. {
  4116. maxUpdatesBytes = Int32.MaxValue;
  4117. }
  4118. EntityUpdate update;
  4119. bool viewerCache = m_supportViewerCache;// && mysp.IsChildAgent; // only on child agents
  4120. bool doCulling = m_scene.ObjectsCullingByDistance;
  4121. float cullingrange = 64.0f;
  4122. Vector3 mypos = Vector3.Zero;
  4123. //bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance;
  4124. bool orderedDequeue = false; // temporary off
  4125. HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new();
  4126. bool useCompressUpdate = false;
  4127. if (doCulling)
  4128. {
  4129. cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f;
  4130. mypos = mysp.AbsolutePosition;
  4131. }
  4132. while (maxUpdatesBytes > 0)
  4133. {
  4134. if (!IsActive)
  4135. return;
  4136. if(orderedDequeue)
  4137. {
  4138. if (!m_entityUpdates.TryOrderedDequeue(out update))
  4139. break;
  4140. }
  4141. else
  4142. {
  4143. if (!m_entityUpdates.TryDequeue(out update))
  4144. break;
  4145. }
  4146. PrimUpdateFlags updateFlags = update.Flags;
  4147. if ((updateFlags & PrimUpdateFlags.Kill) != 0)
  4148. {
  4149. m_killRecord.Add(update.Entity.LocalId);
  4150. maxUpdatesBytes -= 30;
  4151. update.Free();
  4152. continue;
  4153. }
  4154. useCompressUpdate = false;
  4155. bool istree = false;
  4156. bool hasMaterialOverride = false;
  4157. if (update.Entity is SceneObjectPart part)
  4158. {
  4159. SceneObjectGroup grp = part.ParentGroup;
  4160. if (grp.inTransit && ((update.Flags & PrimUpdateFlags.SendInTransit) == 0))
  4161. {
  4162. update.Free();
  4163. continue;
  4164. }
  4165. if (grp.IsDeleted)
  4166. {
  4167. // Don't send updates for objects that have been marked deleted.
  4168. // Instead send another kill object, because the first one may have gotten
  4169. // into a race condition
  4170. if (part == grp.RootPart && !m_killRecord.Contains(grp.LocalId))
  4171. {
  4172. m_killRecord.Add(grp.LocalId);
  4173. maxUpdatesBytes -= 30;
  4174. }
  4175. update.Free();
  4176. continue;
  4177. }
  4178. if (grp.IsAttachment)
  4179. {
  4180. // animated attachments are nasty if not supported by viewer
  4181. if(!m_SupportObjectAnimations && grp.RootPart.Shape.MeshFlagEntry)
  4182. {
  4183. update.Free();
  4184. continue;
  4185. }
  4186. // Someone else's HUD, why are we getting these?
  4187. if (grp.HasPrivateAttachmentPoint && grp.OwnerID != m_agentId)
  4188. {
  4189. update.Free();
  4190. continue;
  4191. }
  4192. // if owner gone don't update it to anyone
  4193. if (!m_scene.TryGetScenePresence(part.OwnerID, out ScenePresence sp))
  4194. {
  4195. update.Free();
  4196. continue;
  4197. }
  4198. // On vehicle crossing, the attachments are received
  4199. // while the avatar is still a child. Don't send
  4200. // updates here because the LocalId has not yet
  4201. // been updated and the viewer will derender the
  4202. // attachments until the avatar becomes root.
  4203. if (sp.IsChildAgent)
  4204. {
  4205. update.Free();
  4206. continue;
  4207. }
  4208. // It's an attachment of a valid avatar, but
  4209. // doesn't seem to be attached, skip
  4210. List<SceneObjectGroup> atts = sp.GetAttachments();
  4211. bool found = false;
  4212. for (int indx = 0; indx < atts.Count; ++indx)
  4213. {
  4214. if (atts[indx] == grp)
  4215. {
  4216. found = true;
  4217. break;
  4218. }
  4219. }
  4220. if (!found)
  4221. {
  4222. update.Free();
  4223. continue;
  4224. }
  4225. if (m_disableFacelights)
  4226. {
  4227. if (grp.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
  4228. grp.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
  4229. {
  4230. part.Shape.LightEntry = false;
  4231. }
  4232. }
  4233. }
  4234. else if (doCulling)
  4235. {
  4236. if(GroupsNeedFullUpdate.Contains(grp))
  4237. {
  4238. update.Free();
  4239. continue;
  4240. }
  4241. bool inViewGroups = false;
  4242. lock(GroupsInView)
  4243. inViewGroups = GroupsInView.Contains(grp);
  4244. if(!inViewGroups)
  4245. {
  4246. Vector3 partpos = grp.getCenterOffset();
  4247. float dpos = (partpos - mypos).LengthSquared();
  4248. float maxview = grp.GetBoundsRadius() + cullingrange;
  4249. if (dpos > maxview * maxview)
  4250. {
  4251. update.Free();
  4252. continue;
  4253. }
  4254. if (!viewerCache || ((updateFlags & PrimUpdateFlags.UpdateProbe) == 0))
  4255. {
  4256. GroupsNeedFullUpdate.Add(grp);
  4257. update.Free();
  4258. continue;
  4259. }
  4260. }
  4261. }
  4262. if ((updateFlags & PrimUpdateFlags.UpdateProbe) != 0)
  4263. {
  4264. if (objectUpdateProbes is null)
  4265. {
  4266. objectUpdateProbes = new List<EntityUpdate>(64);
  4267. maxUpdatesBytes -= 18;
  4268. }
  4269. objectUpdateProbes.Add(update);
  4270. maxUpdatesBytes -= 12;
  4271. continue;
  4272. }
  4273. if ((updateFlags & PrimUpdateFlags.Animations) != 0)
  4274. {
  4275. if (m_SupportObjectAnimations && part.Animations != null)
  4276. {
  4277. ObjectAnimationUpdates ??= new List<SceneObjectPart>(8);
  4278. ObjectAnimationUpdates.Add(part);
  4279. maxUpdatesBytes -= 20 * part.Animations.Count + 24;
  4280. }
  4281. }
  4282. if(viewerCache)
  4283. useCompressUpdate = grp.IsViewerCachable;
  4284. istree = (part.Shape.PCode == (byte)PCode.Grass || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Tree);
  4285. if((m_SupportPBR && (updateFlags & PrimUpdateFlags.MaterialOvr) != 0))
  4286. hasMaterialOverride = !istree && part.Shape.RenderMaterials is not null;
  4287. }
  4288. else if (update.Entity is ScenePresence presence)
  4289. {
  4290. if (presence.IsDeleted)
  4291. {
  4292. update.Free();
  4293. continue;
  4294. }
  4295. // If ParentUUID is not UUID.Zero and ParentID is 0, this
  4296. // avatar is in the process of crossing regions while
  4297. // sat on an object. In this state, we don't want any
  4298. // updates because they will visually orbit the avatar.
  4299. // Update will be forced once crossing is completed anyway.
  4300. if (!presence.ParentUUID.IsZero() && presence.ParentID == 0)
  4301. {
  4302. update.Free();
  4303. continue;
  4304. }
  4305. }
  4306. else // what is this update ?
  4307. {
  4308. update.Free();
  4309. continue;
  4310. }
  4311. #region UpdateFlags to packet type conversion
  4312. updateFlags &= PrimUpdateFlags.FullUpdate; // clear other control bits already handled
  4313. if(updateFlags == PrimUpdateFlags.None)
  4314. {
  4315. update.Free();
  4316. continue;
  4317. }
  4318. const PrimUpdateFlags canNotUseImprovedMask = ~(
  4319. PrimUpdateFlags.AttachmentPoint |
  4320. PrimUpdateFlags.Position |
  4321. PrimUpdateFlags.Rotation |
  4322. PrimUpdateFlags.Velocity |
  4323. PrimUpdateFlags.Acceleration |
  4324. PrimUpdateFlags.AngularVelocity |
  4325. PrimUpdateFlags.CollisionPlane |
  4326. PrimUpdateFlags.Textures
  4327. );
  4328. #endregion UpdateFlags to packet type conversion
  4329. #region Block Construction
  4330. if ((updateFlags & canNotUseImprovedMask) == 0)
  4331. {
  4332. if (terseUpdates is null)
  4333. {
  4334. terseUpdates = new List<EntityUpdate>(16);
  4335. maxUpdatesBytes -= 18;
  4336. }
  4337. terseUpdates.Add(update);
  4338. if (update.Entity is ScenePresence)
  4339. maxUpdatesBytes -= 63; // no texture entry
  4340. else
  4341. {
  4342. if ((updateFlags & PrimUpdateFlags.Textures) == 0)
  4343. maxUpdatesBytes -= 47;
  4344. else
  4345. maxUpdatesBytes -= 150; // aprox
  4346. }
  4347. }
  4348. else
  4349. {
  4350. if (update.Entity is ScenePresence)
  4351. {
  4352. maxUpdatesBytes -= 150; // crude estimation
  4353. if (objectUpdates is null)
  4354. {
  4355. objectUpdates = new List<EntityUpdate>(16);
  4356. maxUpdatesBytes -= 18;
  4357. }
  4358. objectUpdates.Add(update);
  4359. }
  4360. else
  4361. {
  4362. if (useCompressUpdate)
  4363. {
  4364. if (istree)
  4365. maxUpdatesBytes -= 64;
  4366. else
  4367. maxUpdatesBytes -= 120; // crude estimation
  4368. if (compressedUpdates is null)
  4369. {
  4370. compressedUpdates = new List<EntityUpdate>(16);
  4371. maxUpdatesBytes -= 18;
  4372. }
  4373. compressedUpdates.Add(update);
  4374. }
  4375. else
  4376. {
  4377. if (istree)
  4378. maxUpdatesBytes -= 70;
  4379. else
  4380. maxUpdatesBytes -= 150; // crude estimation
  4381. if (objectUpdates is null)
  4382. {
  4383. objectUpdates = new List<EntityUpdate>(16);
  4384. maxUpdatesBytes -= 18;
  4385. }
  4386. objectUpdates.Add(update);
  4387. }
  4388. if(hasMaterialOverride)
  4389. {
  4390. needMaterials ??= new List<SceneObjectPart>(16);
  4391. needMaterials.Add((SceneObjectPart)update.Entity);
  4392. }
  4393. }
  4394. }
  4395. #endregion Block Construction
  4396. }
  4397. #region Packet Sending
  4398. ushort timeDilation;
  4399. if (!IsActive)
  4400. return;
  4401. timeDilation = Utils.FloatZeroOneToushort(m_scene.TimeDilation);
  4402. if (objectUpdates is not null)
  4403. {
  4404. //List<EntityUpdate> tau = new List<EntityUpdate>(30);
  4405. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  4406. Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7);
  4407. LLUDPZeroEncoder zc = new(buf.Data);
  4408. zc.Position = 7;
  4409. zc.AddUInt64(m_scene.RegionInfo.RegionHandle);
  4410. zc.AddUInt16(timeDilation);
  4411. zc.AddByte(1); // tmp block count
  4412. int countposition = zc.Position - 1;
  4413. int lastpos = 0;
  4414. int lastzc = 0;
  4415. int count = 0;
  4416. bool shouldCreateSelected = false; //mantis 8639
  4417. EntityUpdate eu;
  4418. for(int indx = 0; indx < objectUpdates.Count; ++indx)
  4419. {
  4420. eu = objectUpdates[indx];
  4421. lastpos = zc.Position;
  4422. lastzc = zc.ZeroCount;
  4423. if (eu.Entity is ScenePresence sp)
  4424. CreateAvatarUpdateBlock(sp, zc);
  4425. else
  4426. {
  4427. SceneObjectPart part = (SceneObjectPart)eu.Entity;
  4428. shouldCreateSelected = part.CreateSelected;
  4429. CreatePrimUpdateBlock(part, mysp, zc);
  4430. }
  4431. if (zc.Position < LLUDPServer.MAXPAYLOAD - 300)
  4432. {
  4433. //tau.Add(eu);
  4434. ++count;
  4435. }
  4436. else
  4437. {
  4438. // we need more packets
  4439. UDPPacketBuffer newbuf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  4440. Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same
  4441. buf.Data[countposition] = (byte)count;
  4442. // get pending zeros at cut point
  4443. if(lastzc > 0)
  4444. {
  4445. buf.Data[lastpos++] = 0;
  4446. buf.Data[lastpos++] = (byte)lastzc;
  4447. }
  4448. buf.DataLength = lastpos;
  4449. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
  4450. //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
  4451. null, false);
  4452. buf = newbuf;
  4453. zc.Data = buf.Data;
  4454. zc.ZeroCount = 0;
  4455. zc.Position = countposition + 1;
  4456. // im lazy now, just do last again
  4457. if (eu.Entity is ScenePresence eusp)
  4458. CreateAvatarUpdateBlock(eusp, zc);
  4459. else
  4460. {
  4461. if(shouldCreateSelected) //mantis 8639 recover selected state
  4462. ((SceneObjectPart)eu.Entity).CreateSelected = true;
  4463. CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc);
  4464. }
  4465. //tau = new List<EntityUpdate>(30);
  4466. //tau.Add(eu);
  4467. count = 1;
  4468. }
  4469. eu.Free(); //remove if using resend
  4470. }
  4471. if (count > 0)
  4472. {
  4473. buf.Data[countposition] = (byte)count;
  4474. buf.DataLength = zc.Finish();
  4475. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
  4476. //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
  4477. null, false);
  4478. }
  4479. }
  4480. if (compressedUpdates is not null)
  4481. {
  4482. //List<EntityUpdate> tau = new List<EntityUpdate>(30);
  4483. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  4484. byte[] data = buf.Data;
  4485. Buffer.BlockCopy(CompressedObjectHeader, 0, data, 0, 7);
  4486. data[0] |= Helpers.MSG_ZEROCODED;
  4487. LLUDPZeroEncoder zc = new(buf.Data);
  4488. zc.Position = 7;
  4489. zc.AddUInt64(m_scene.RegionInfo.RegionHandle);
  4490. zc.AddUInt16(timeDilation);
  4491. zc.AddByte(1); // tmp block count
  4492. int countposition = zc.Position - 1;
  4493. int lastpos = 0;
  4494. int lastzc = 0;
  4495. int count = 0;
  4496. bool shouldCreateSelected = false; //mantis 8639
  4497. EntityUpdate eu;
  4498. for (int indx = 0; indx < compressedUpdates.Count; ++indx)
  4499. {
  4500. eu = compressedUpdates[indx];
  4501. SceneObjectPart sop = (SceneObjectPart)eu.Entity;
  4502. if (sop.ParentGroup is null || sop.ParentGroup.IsDeleted)
  4503. continue;
  4504. shouldCreateSelected = sop.CreateSelected;
  4505. lastpos = zc.Position;
  4506. lastzc = zc.ZeroCount;
  4507. CreateCompressedUpdateBlockZC(sop, mysp, zc);
  4508. if (zc.Position < LLUDPServer.MAXPAYLOAD - 200)
  4509. {
  4510. //tau.Add(eu);
  4511. ++count;
  4512. }
  4513. else
  4514. {
  4515. // we need more packets
  4516. UDPPacketBuffer newbuf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  4517. Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same
  4518. buf.Data[countposition] = (byte)count;
  4519. // get pending zeros at cut point
  4520. if (lastzc > 0)
  4521. {
  4522. buf.Data[lastpos++] = 0;
  4523. buf.Data[lastpos++] = (byte)lastzc;
  4524. }
  4525. buf.DataLength = lastpos;
  4526. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
  4527. //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
  4528. null, false);
  4529. buf = newbuf;
  4530. zc.Data = buf.Data;
  4531. data[0] |= Helpers.MSG_ZEROCODED;
  4532. zc.ZeroCount = 0;
  4533. zc.Position = countposition + 1;
  4534. if (shouldCreateSelected) //mantis 8639 recover selected state
  4535. sop.CreateSelected = true;
  4536. // im lazy now, just do last again
  4537. CreateCompressedUpdateBlockZC(sop, mysp, zc);
  4538. //tau = new List<EntityUpdate>(30);
  4539. //tau.Add(eu);
  4540. count = 1;
  4541. }
  4542. eu.Free(); //remove if using resend
  4543. }
  4544. if (count > 0)
  4545. {
  4546. buf.Data[countposition] = (byte)count;
  4547. buf.DataLength = zc.Finish();
  4548. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
  4549. //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
  4550. null, false);
  4551. }
  4552. }
  4553. if (objectUpdateProbes is not null)
  4554. {
  4555. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  4556. byte[] data = buf.Data;
  4557. Buffer.BlockCopy(ObjectUpdateCachedHeader, 0, data, 0, 7);
  4558. Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, data, 7); // 15
  4559. Utils.UInt16ToBytes(timeDilation, data, 15); // 17
  4560. const int countposition = 17; // blocks count index
  4561. int pos = countposition + 1;
  4562. int count = 0;
  4563. EntityUpdate eu;
  4564. int indx = 0;
  4565. while (indx < objectUpdateProbes.Count)
  4566. {
  4567. unsafe
  4568. {
  4569. fixed(byte* bdata = &data[countposition + 1])
  4570. {
  4571. byte* ptr = bdata;
  4572. while (indx < objectUpdateProbes.Count)
  4573. {
  4574. eu = objectUpdateProbes[indx++];
  4575. SceneObjectPart sop = (SceneObjectPart)eu.Entity;
  4576. if (sop.ParentGroup is null || sop.ParentGroup.IsDeleted)
  4577. continue;
  4578. uint primflags = m_scene.Permissions.GenerateClientFlags(sop, mysp);
  4579. if (mysp.UUID.NotEqual(sop.OwnerID))
  4580. primflags &= ~(uint)PrimFlags.CreateSelected;
  4581. else
  4582. {
  4583. if (sop.CreateSelected)
  4584. primflags |= (uint)PrimFlags.CreateSelected;
  4585. else
  4586. primflags &= ~(uint)PrimFlags.CreateSelected;
  4587. }
  4588. Utils.UIntToBytes(sop.LocalId, ptr); ptr += 4;
  4589. Utils.UIntToBytes((uint)sop.PseudoCRC, ptr); ptr += 4; //WRONG
  4590. Utils.UIntToBytes(primflags, ptr); ptr += 4;
  4591. eu.Free();
  4592. ++count;
  4593. pos += 12;
  4594. if (pos > (LLUDPServer.MAXPAYLOAD - 13))
  4595. {
  4596. // we need more packets
  4597. UDPPacketBuffer newbuf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  4598. Buffer.BlockCopy(data, 0, newbuf.Data, 0, countposition); // start is the same
  4599. data[countposition] = (byte)count;
  4600. buf.DataLength = pos;
  4601. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false);
  4602. buf = newbuf;
  4603. data = buf.Data;
  4604. count = 0;
  4605. pos = countposition + 1;
  4606. break;
  4607. }
  4608. }
  4609. }
  4610. }
  4611. }
  4612. if (count > 0)
  4613. {
  4614. data[countposition] = (byte)count;
  4615. buf.DataLength = pos;
  4616. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false);
  4617. }
  4618. }
  4619. if (terseUpdates is not null)
  4620. {
  4621. int blocks = terseUpdates.Count;
  4622. //List<EntityUpdate> tau = new List<EntityUpdate>(30);
  4623. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  4624. //setup header and regioninfo block
  4625. Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7);
  4626. Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7);
  4627. Utils.UInt16ToBytes(timeDilation, buf.Data, 15);
  4628. const int COUNTINDEX = 17;
  4629. int pos = COUNTINDEX + 1;
  4630. int lastpos = 0;
  4631. int count = 0;
  4632. EntityUpdate eu;
  4633. int indx = 0;
  4634. while (indx < terseUpdates.Count)
  4635. {
  4636. unsafe
  4637. {
  4638. fixed(byte* bdata = &buf.Data[0])
  4639. {
  4640. byte* data = bdata + pos;
  4641. while (indx < terseUpdates.Count)
  4642. {
  4643. eu = terseUpdates[indx++];
  4644. lastpos = pos;
  4645. if(eu.Entity is ScenePresence sp)
  4646. CreateAvatartImprovedTerseBlock(sp, ref data);
  4647. else
  4648. CreatePartImprovedTerseBlock((SceneObjectPart)eu.Entity, ref data, (eu.Flags & PrimUpdateFlags.Textures) != 0);
  4649. eu.Free();
  4650. pos = (int)(data - bdata);
  4651. --blocks;
  4652. if (pos < LLUDPServer.MAXPAYLOAD)
  4653. {
  4654. //tau.Add(eu);
  4655. ++count;
  4656. }
  4657. else if (blocks > 0)
  4658. {
  4659. // we need more packets
  4660. UDPPacketBuffer newbuf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  4661. Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, COUNTINDEX); // start is the same
  4662. // copy what we done in excess
  4663. int extralen = pos - lastpos;
  4664. if(extralen > 0)
  4665. Buffer.BlockCopy(buf.Data, lastpos, newbuf.Data, 18, extralen);
  4666. pos = COUNTINDEX + 1 + extralen;
  4667. buf.Data[COUNTINDEX] = (byte)count;
  4668. buf.DataLength = lastpos;
  4669. // zero encode is not as spec
  4670. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
  4671. //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, true);
  4672. null, true);
  4673. //tau = new List<EntityUpdate>(30);
  4674. //tau.Add(eu);
  4675. count = 1;
  4676. buf = newbuf;
  4677. break;
  4678. }
  4679. }
  4680. }
  4681. }
  4682. }
  4683. if (count > 0)
  4684. {
  4685. buf.Data[COUNTINDEX] = (byte)count;
  4686. buf.DataLength = pos;
  4687. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
  4688. //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, true);
  4689. null, true);
  4690. }
  4691. }
  4692. if (ObjectAnimationUpdates is not null)
  4693. {
  4694. SceneObjectPart sop;
  4695. for (int indx = 0; indx < ObjectAnimationUpdates.Count; ++indx)
  4696. {
  4697. sop = ObjectAnimationUpdates[indx];
  4698. if (sop.Animations is null)
  4699. continue;
  4700. SceneObjectGroup sog = sop.ParentGroup;
  4701. if (sog is null || sog.IsDeleted)
  4702. continue;
  4703. SceneObjectPart root = sog.RootPart;
  4704. if (root is null || root.Shape is null || !root.Shape.MeshFlagEntry)
  4705. continue;
  4706. int count = sop.GetAnimations(out UUID[] ids, out int[] seqs);
  4707. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  4708. byte[] data = buf.Data;
  4709. //setup header
  4710. Buffer.BlockCopy(ObjectAnimationHeader, 0, data , 0, 7);
  4711. // sender block
  4712. sop.UUID.ToBytes(data, 7); // 23
  4713. //animations block
  4714. if (count > 255)
  4715. count = 255;
  4716. data[23] = (byte)count;
  4717. int pos = 24;
  4718. for(int i = 0; i < count; i++)
  4719. {
  4720. ids[i].ToBytes(data, pos); pos += 16;
  4721. Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
  4722. }
  4723. buf.DataLength = pos;
  4724. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  4725. }
  4726. }
  4727. if (needMaterials is not null)
  4728. {
  4729. foreach (SceneObjectPart sop in needMaterials)
  4730. {
  4731. if(sop.Shape.RenderMaterials is null)
  4732. continue;
  4733. string inner;
  4734. if (sop.Shape.RenderMaterials.overrides is not null &&
  4735. sop.Shape.RenderMaterials.overrides.Length > 0)
  4736. {
  4737. OSDMap data = new(3)
  4738. {
  4739. ["id"] = (int)sop.LocalId
  4740. };
  4741. OSDArray sides = new();
  4742. OSDArray sidesdata = new();
  4743. foreach (Primitive.RenderMaterials.RenderMaterialOverrideEntry ovr in sop.Shape.RenderMaterials.overrides)
  4744. {
  4745. sides.Add(ovr.te_index);
  4746. sidesdata.Add(string.IsNullOrEmpty(ovr.data) ? new OSD() : new OSDllsdxml(ovr.data));
  4747. }
  4748. data["te"] = sides;
  4749. data["od"] = sidesdata;
  4750. inner = OSDParser.SerializeLLSDNotation(data);
  4751. if (inner.Length < 4)
  4752. continue;
  4753. }
  4754. else
  4755. inner = $"{{'id':i{sop.LocalId},'od':[],'te':[]}}";
  4756. byte[] innerB = Util.UTF8NBGetbytes(inner);
  4757. if (innerB.Length > UDPPacketBuffer.BUFFER_SIZE - 16)
  4758. {
  4759. m_log.Debug($"[LLCLIENTVIEW]: GenericStreamingMessage packet too large ({innerB.Length})");
  4760. continue;
  4761. }
  4762. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  4763. byte[] dataptr = buf.Data;
  4764. //setup header
  4765. Buffer.BlockCopy(GenericStreamingMessageHeader, 0, dataptr, 0, 7);
  4766. Utils.UInt16ToBytes(16757, dataptr, 7);
  4767. dataptr[9] = (byte)(innerB.Length);
  4768. dataptr[10] = (byte)(innerB.Length >> 8);
  4769. Buffer.BlockCopy(innerB, 0, dataptr, 11, innerB.Length);
  4770. buf.DataLength = innerB.Length + 11;
  4771. // send it
  4772. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  4773. }
  4774. }
  4775. #endregion Packet Sending
  4776. #region Handle deleted objects
  4777. if (m_killRecord.Count > 0)
  4778. {
  4779. SendKillObject(m_killRecord);
  4780. m_killRecord.Clear();
  4781. }
  4782. if(GroupsNeedFullUpdate.Count > 0)
  4783. {
  4784. foreach(SceneObjectGroup grp in GroupsNeedFullUpdate)
  4785. {
  4786. lock (GroupsInView)
  4787. GroupsInView.Add(grp);
  4788. PrimUpdateFlags flags = PrimUpdateFlags.CancelKill;
  4789. if(viewerCache && grp.IsViewerCachable)
  4790. flags |= PrimUpdateFlags.UpdateProbe;
  4791. foreach (SceneObjectPart p in grp.Parts)
  4792. SendEntityUpdate(p, flags);
  4793. }
  4794. }
  4795. #endregion
  4796. }
  4797. static private readonly byte[] GenericStreamingMessageHeader = new byte[] {
  4798. Helpers.MSG_RELIABLE,
  4799. 0, 0, 0, 0, // sequence number
  4800. 0, // extra
  4801. 31 // ID 31 (high frequency)
  4802. };
  4803. // hack.. dont use
  4804. /*
  4805. public void SendPartFullUpdate(ISceneEntity ent, uint? parentID)
  4806. {
  4807. if (ent is SceneObjectPart)
  4808. {
  4809. SceneObjectPart part = (SceneObjectPart)ent;
  4810. ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
  4811. packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
  4812. packet.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
  4813. packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
  4814. ObjectUpdatePacket.ObjectDataBlock blk = CreatePrimUpdateBlock(part, mysp);
  4815. if (parentID.HasValue)
  4816. {
  4817. blk.ParentID = parentID.Value;
  4818. }
  4819. packet.ObjectData[0] = blk;
  4820. OutPacket(packet, ThrottleOutPacketType.Task, true);
  4821. }
  4822. // m_log.DebugFormat(
  4823. // "[LLCLIENTVIEW]: Sent {0} updates in ProcessEntityUpdates() for {1} {2} in {3}",
  4824. // updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name);
  4825. //
  4826. }
  4827. */
  4828. public void ReprioritizeUpdates()
  4829. {
  4830. m_entityUpdates.Reprioritize(UpdatePriorityHandler);
  4831. CheckGroupsInView();
  4832. }
  4833. private bool CheckGroupsInViewBusy = false;
  4834. public void CheckGroupsInView()
  4835. {
  4836. if(!m_scene.ObjectsCullingByDistance)
  4837. return;
  4838. if (!IsActive)
  4839. return;
  4840. if (CheckGroupsInViewBusy)
  4841. return;
  4842. if(SceneAgent is not ScenePresence mysp || mysp.IsDeleted)
  4843. return;
  4844. CheckGroupsInViewBusy = true;
  4845. float cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f;
  4846. Vector3 mypos = mysp.AbsolutePosition;
  4847. HashSet<SceneObjectGroup> NewGroupsInView = new();
  4848. HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new();
  4849. List<SceneObjectGroup> kills = new();
  4850. EntityBase[] entities = m_scene.Entities.GetEntities();
  4851. foreach (EntityBase e in entities.AsSpan())
  4852. {
  4853. if (!IsActive)
  4854. return;
  4855. if (e is SceneObjectGroup grp)
  4856. {
  4857. if(grp.IsDeleted || grp.IsAttachment )
  4858. continue;
  4859. bool inviewgroups;
  4860. lock (GroupsInView)
  4861. inviewgroups = GroupsInView.Contains(grp);
  4862. //temp handling of sits
  4863. if(grp.GetSittingAvatarsCount() > 0)
  4864. {
  4865. if (!inviewgroups)
  4866. GroupsNeedFullUpdate.Add(grp);
  4867. NewGroupsInView.Add(grp);
  4868. }
  4869. else
  4870. {
  4871. Vector3 grppos = grp.getCenterOffset();
  4872. float dpos = (grppos - mypos).LengthSquared();
  4873. float maxview = grp.GetBoundsRadius() + cullingrange;
  4874. if (dpos > maxview * maxview)
  4875. {
  4876. if(inviewgroups)
  4877. kills.Add(grp);
  4878. }
  4879. else
  4880. {
  4881. if (!inviewgroups)
  4882. GroupsNeedFullUpdate.Add(grp);
  4883. NewGroupsInView.Add(grp);
  4884. }
  4885. }
  4886. }
  4887. }
  4888. lock(GroupsInView)
  4889. GroupsInView = NewGroupsInView;
  4890. if (kills.Count > 0)
  4891. {
  4892. List<uint> partIDs = new();
  4893. foreach(SceneObjectGroup grp in CollectionsMarshal.AsSpan(kills))
  4894. {
  4895. SendEntityUpdate(grp.RootPart, PrimUpdateFlags.Kill);
  4896. foreach(SceneObjectPart p in grp.Parts)
  4897. {
  4898. if(p != grp.RootPart)
  4899. partIDs.Add(p.LocalId);
  4900. }
  4901. }
  4902. kills.Clear();
  4903. if(partIDs.Count > 0)
  4904. {
  4905. m_entityProps.Remove(partIDs);
  4906. m_entityUpdates.Remove(partIDs);
  4907. }
  4908. }
  4909. if(GroupsNeedFullUpdate.Count > 0)
  4910. {
  4911. bool sendProbes = m_supportViewerCache && (m_viewerHandShakeFlags & 2) == 0;
  4912. if(sendProbes)
  4913. {
  4914. foreach (SceneObjectGroup grp in GroupsNeedFullUpdate)
  4915. {
  4916. PrimUpdateFlags flags = PrimUpdateFlags.CancelKill;
  4917. if (grp.IsViewerCachable)
  4918. flags |= PrimUpdateFlags.UpdateProbe;
  4919. foreach (SceneObjectPart p in grp.Parts)
  4920. SendEntityUpdate(p, flags);
  4921. }
  4922. }
  4923. else
  4924. {
  4925. m_viewerHandShakeFlags &= ~2U; // nexttime send probes
  4926. PrimUpdateFlags flags = PrimUpdateFlags.CancelKill;
  4927. foreach (SceneObjectGroup grp in GroupsNeedFullUpdate)
  4928. {
  4929. foreach (SceneObjectPart p in grp.Parts)
  4930. SendEntityUpdate(p, flags);
  4931. }
  4932. }
  4933. }
  4934. CheckGroupsInViewBusy = false;
  4935. }
  4936. private bool UpdatePriorityHandler(ref int priority, ISceneEntity entity)
  4937. {
  4938. if (!IsActive)
  4939. return false;
  4940. priority = m_prioritizer.GetUpdatePriority(this, entity);
  4941. return true;
  4942. }
  4943. public void FlushPrimUpdates()
  4944. {
  4945. m_log.WarnFormat("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
  4946. while (m_entityUpdates.Count > 0)
  4947. ProcessEntityUpdates(-1);
  4948. }
  4949. #endregion Primitive Packet/Data Sending Methods
  4950. // These are used to implement an adaptive backoff in the number
  4951. // of updates converted to packets. Since we don't want packets
  4952. // to sit in the queue with old data, only convert enough updates
  4953. // to packets that can be sent in 30ms.
  4954. void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
  4955. {
  4956. if(m_scene is null)
  4957. return;
  4958. if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
  4959. {
  4960. int maxUpdateBytes = m_udpClient.GetCatBytesCanSend(ThrottleOutPacketType.Task, 30);
  4961. if (m_entityUpdates.Count > 0)
  4962. ProcessEntityUpdates(maxUpdateBytes);
  4963. if (m_entityProps.Count > 0)
  4964. ProcessEntityPropertyRequests(maxUpdateBytes);
  4965. }
  4966. if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
  4967. ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
  4968. }
  4969. internal bool HandleHasUpdates(ThrottleOutPacketTypeFlags categories)
  4970. {
  4971. if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
  4972. {
  4973. if (m_entityUpdates.Count > 0)
  4974. return true;
  4975. if (m_entityProps.Count > 0)
  4976. return true;
  4977. }
  4978. if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
  4979. {
  4980. if (ImageManager.HasUpdates())
  4981. return true;
  4982. }
  4983. return false;
  4984. }
  4985. public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
  4986. {
  4987. AssetUploadCompletePacket newPack = new();
  4988. newPack.AssetBlock.Type = AssetType;
  4989. newPack.AssetBlock.Success = Success;
  4990. newPack.AssetBlock.UUID = AssetFullID;
  4991. newPack.Header.Zerocoded = true;
  4992. OutPacket(newPack, ThrottleOutPacketType.Asset);
  4993. }
  4994. public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName)
  4995. {
  4996. RequestXferPacket newPack = new();
  4997. newPack.XferID.ID = XferID;
  4998. newPack.XferID.VFileType = AssetType;
  4999. newPack.XferID.VFileID = vFileID;
  5000. newPack.XferID.FilePath = FilePath;
  5001. newPack.XferID.Filename = FileName;
  5002. newPack.Header.Zerocoded = true;
  5003. OutPacket(newPack, ThrottleOutPacketType.Asset);
  5004. }
  5005. public void SendConfirmXfer(ulong xferID, uint PacketID)
  5006. {
  5007. ConfirmXferPacketPacket newPack = new();
  5008. newPack.XferID.ID = xferID;
  5009. newPack.XferID.Packet = PacketID;
  5010. newPack.Header.Zerocoded = true;
  5011. OutPacket(newPack, ThrottleOutPacketType.Asset);
  5012. }
  5013. public void SendInitiateDownload(string simFileName, string clientFileName)
  5014. {
  5015. InitiateDownloadPacket newPack = new();
  5016. newPack.AgentData.AgentID = m_agentId;
  5017. newPack.FileData.SimFilename = Utils.StringToBytes(simFileName);
  5018. newPack.FileData.ViewerFilename = Utils.StringToBytes(clientFileName);
  5019. OutPacket(newPack, ThrottleOutPacketType.Asset);
  5020. }
  5021. public void SendImageFirstPart(
  5022. ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec)
  5023. {
  5024. ImageDataPacket im = new();
  5025. im.ImageID.Packets = numParts;
  5026. im.ImageID.ID = ImageUUID;
  5027. if (ImageSize > 0)
  5028. im.ImageID.Size = ImageSize;
  5029. im.ImageData.Data = ImageData;
  5030. im.ImageID.Codec = imageCodec;
  5031. im.Header.Zerocoded = true;
  5032. OutPacket(im, ThrottleOutPacketType.Texture);
  5033. }
  5034. public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData)
  5035. {
  5036. ImagePacketPacket im = new();
  5037. im.ImageID.Packet = partNumber;
  5038. im.ImageID.ID = imageUuid;
  5039. im.ImageData.Data = imageData;
  5040. OutPacket(im, ThrottleOutPacketType.Texture);
  5041. }
  5042. public void SendImageNotFound(UUID imageid)
  5043. {
  5044. ImageNotInDatabasePacket notFoundPacket
  5045. = (ImageNotInDatabasePacket)PacketPool.Instance.GetPacket(PacketType.ImageNotInDatabase);
  5046. notFoundPacket.ImageID.ID = imageid;
  5047. OutPacket(notFoundPacket, ThrottleOutPacketType.Texture);
  5048. }
  5049. public void SendShutdownConnectionNotice()
  5050. {
  5051. OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown);
  5052. }
  5053. static private readonly byte[] SimStatsHeader = new byte[] {
  5054. 0,
  5055. 0, 0, 0, 0, // sequence number
  5056. 0, // extra
  5057. 0xff, 0xff, 0, 140 // ID 140 (low frequency bigendian)
  5058. };
  5059. public void SendSimStats(SimStats stats)
  5060. {
  5061. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  5062. byte[] data = buf.Data;
  5063. //setup header
  5064. Buffer.BlockCopy(SimStatsHeader, 0, data, 0, 10);
  5065. // Region Block
  5066. Utils.UIntToBytesSafepos(stats.RegionX, data, 10);
  5067. Utils.UIntToBytesSafepos(stats.RegionY, data, 14);
  5068. Utils.UIntToBytesSafepos(stats.RegionFlags, data, 18);
  5069. Utils.UIntToBytesSafepos(stats.ObjectCapacity, data, 22); // 26
  5070. // stats
  5071. data[26] = (byte)StatsIndex.ViewerArraySize;
  5072. int pos = 27;
  5073. int i = 0;
  5074. for (; i < (int)StatsIndex.UnAckedBytes; ++i)
  5075. {
  5076. Utils.UIntToBytesSafepos(SimStats.StatsIndexID[i], data, pos); pos += 4;
  5077. Utils.FloatToBytesSafepos(stats.StatsValues[i], data, pos); pos += 4;
  5078. }
  5079. // unack Bytes is in KB
  5080. Utils.UIntToBytesSafepos(SimStats.StatsIndexID[i], data, pos); pos += 4;
  5081. Utils.FloatToBytesSafepos(stats.StatsValues[i] / 1024, data, pos); pos += 4;
  5082. ++i;
  5083. for (; i < (int)StatsIndex.ViewerArraySize; ++i)
  5084. {
  5085. Utils.UIntToBytesSafepos(SimStats.StatsIndexID[i], data, pos); pos += 4;
  5086. Utils.FloatToBytesSafepos(stats.StatsValues[i], data, pos); pos += 4;
  5087. }
  5088. //no PID
  5089. Utils.IntToBytesSafepos(0, data, pos); pos += 4;
  5090. // no regioninfo (extended flags)
  5091. data[pos++] = 0; // = 1;
  5092. //Utils.UInt64ToBytesSafepos(RegionFlagsExtended, data, pos); pos += 8;
  5093. buf.DataLength = pos;
  5094. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  5095. }
  5096. public void SendObjectPropertiesFamilyData(ISceneEntity entity, uint requestFlags)
  5097. {
  5098. m_entityProps.Enqueue(0, EntityUpdatesPool.Get(entity, (PrimUpdateFlags)requestFlags, true, false));
  5099. }
  5100. private void ResendPropertyUpdate(EntityUpdate update)
  5101. {
  5102. m_entityProps.Enqueue(0, update);
  5103. }
  5104. private void ResendPropertyUpdates(List<EntityUpdate> updates, OutgoingPacket oPacket)
  5105. {
  5106. // m_log.WarnFormat("[CLIENT] resending object property {0}",updates[0].UpdateTime);
  5107. // Remove the update packet from the list of packets waiting for acknowledgement
  5108. // because we are requeuing the list of updates. They will be resent in new packets
  5109. // with the most recent state.
  5110. m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
  5111. // Count this as a resent packet since we are going to requeue all of the updates contained in it
  5112. Interlocked.Increment(ref m_udpClient.PacketsResent);
  5113. // We're not going to worry about interlock yet since its not currently critical that this total count
  5114. // is 100% correct
  5115. m_udpServer.PacketsResentCount++;
  5116. foreach (EntityUpdate update in updates)
  5117. ResendPropertyUpdate(update);
  5118. }
  5119. public void SendObjectPropertiesReply(ISceneEntity entity)
  5120. {
  5121. m_entityProps.Enqueue(0, EntityUpdatesPool.Get(entity,0,false,true));
  5122. }
  5123. static private readonly byte[] ObjectPropertyUpdateHeader = new byte[] {
  5124. Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED,
  5125. 0, 0, 0, 0, // sequence number
  5126. 0, // extra
  5127. 0xff, 9 // ID (medium frequency)
  5128. };
  5129. static private readonly byte[] ObjectFamilyUpdateHeader = new byte[] {
  5130. Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED,
  5131. 0, 0, 0, 0, // sequence number
  5132. 0, // extra
  5133. 0xff, 10 // ID (medium frequency)
  5134. };
  5135. private void ProcessEntityPropertyRequests(int maxUpdateBytes)
  5136. {
  5137. List<EntityUpdate> objectPropertiesUpdates = null;
  5138. List<EntityUpdate> objectPropertiesFamilyUpdates = null;
  5139. List<EntityUpdate> used = new(64);
  5140. List<SceneObjectPart> needPhysics = null;
  5141. // bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance;
  5142. bool orderedDequeue = false; // for now
  5143. EntityUpdate update;
  5144. while (maxUpdateBytes > 0)
  5145. {
  5146. if(orderedDequeue)
  5147. {
  5148. if (!m_entityProps.TryOrderedDequeue(out update))
  5149. break;
  5150. }
  5151. else
  5152. {
  5153. if (!m_entityProps.TryDequeue(out update))
  5154. break;
  5155. }
  5156. if (update.PropsFlags == 0)
  5157. {
  5158. update.Free();
  5159. continue;
  5160. }
  5161. if(update.Entity is not SceneObjectPart sop)
  5162. {
  5163. update.Free();
  5164. continue;
  5165. }
  5166. used.Add(update);
  5167. if ((update.PropsFlags & ObjectPropertyUpdateFlags.Family) != 0)
  5168. {
  5169. objectPropertiesFamilyUpdates ??= new List<EntityUpdate>();
  5170. objectPropertiesFamilyUpdates.Add(update);
  5171. maxUpdateBytes -= 100;
  5172. }
  5173. if ((update.PropsFlags & ObjectPropertyUpdateFlags.Object) != 0)
  5174. {
  5175. needPhysics ??= new List<SceneObjectPart>();
  5176. needPhysics.Add(sop);
  5177. objectPropertiesUpdates ??= new List<EntityUpdate>();
  5178. objectPropertiesUpdates.Add(update);
  5179. maxUpdateBytes -= 200; // aprox
  5180. }
  5181. }
  5182. if (objectPropertiesUpdates != null)
  5183. {
  5184. int blocks = objectPropertiesUpdates.Count;
  5185. //List<EntityUpdate> tau = new List<EntityUpdate>(30);
  5186. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  5187. Buffer.BlockCopy(ObjectPropertyUpdateHeader, 0, buf.Data, 0, 8);
  5188. LLUDPZeroEncoder zc = new(buf.Data);
  5189. zc.Position = 8;
  5190. zc.AddByte(1); // tmp block count
  5191. int countposition = zc.Position - 1;
  5192. int lastpos;
  5193. int lastzc;
  5194. int count = 0;
  5195. foreach (EntityUpdate eu in objectPropertiesUpdates)
  5196. {
  5197. lastpos = zc.Position;
  5198. lastzc = zc.ZeroCount;
  5199. CreateObjectPropertiesBlock((SceneObjectPart)eu.Entity, zc);
  5200. if (zc.Position < LLUDPServer.MAXPAYLOAD)
  5201. {
  5202. //tau.Add(eu);
  5203. ++count;
  5204. --blocks;
  5205. }
  5206. else if (blocks > 0)
  5207. {
  5208. // we need more packets
  5209. UDPPacketBuffer newbuf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  5210. Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same
  5211. buf.Data[countposition] = (byte)count;
  5212. // get pending zeros at cut point
  5213. if (lastzc > 0)
  5214. {
  5215. buf.Data[lastpos++] = 0;
  5216. buf.Data[lastpos++] = (byte)lastzc;
  5217. }
  5218. buf.DataLength = lastpos;
  5219. //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
  5220. // delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
  5221. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  5222. buf = newbuf;
  5223. zc.Data = buf.Data;
  5224. zc.ZeroCount = 0;
  5225. zc.Position = countposition + 1;
  5226. // im lazy now, just do last again
  5227. CreateObjectPropertiesBlock((SceneObjectPart)eu.Entity, zc);
  5228. //tau = new List<EntityUpdate>(30);
  5229. //tau.Add(eu);
  5230. count = 1;
  5231. --blocks;
  5232. }
  5233. }
  5234. if (count > 0)
  5235. {
  5236. buf.Data[countposition] = (byte)count;
  5237. buf.DataLength = zc.Finish();
  5238. //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
  5239. // delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
  5240. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  5241. }
  5242. }
  5243. if (objectPropertiesFamilyUpdates != null)
  5244. {
  5245. foreach (EntityUpdate eu in objectPropertiesFamilyUpdates)
  5246. {
  5247. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  5248. Buffer.BlockCopy(ObjectFamilyUpdateHeader, 0, buf.Data, 0, 8);
  5249. LLUDPZeroEncoder zc = new(buf.Data);
  5250. zc.Position = 8;
  5251. CreateObjectPropertiesFamilyBlock((SceneObjectPart)eu.Entity, eu.Flags, zc);
  5252. buf.DataLength = zc.Finish();
  5253. //List<EntityUpdate> tau = new List<EntityUpdate>(1);
  5254. //tau.Add(new ObjectPropertyUpdate((ISceneEntity) eu, (uint)eu.Flags, true, false));
  5255. //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
  5256. // delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
  5257. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task);
  5258. }
  5259. }
  5260. if (needPhysics != null)
  5261. {
  5262. IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
  5263. if(eq != null)
  5264. {
  5265. osUTF8 sb = eq.StartEvent("ObjectPhysicsProperties");
  5266. LLSDxmlEncode2.AddArray("ObjectData", sb);
  5267. foreach (SceneObjectPart sop in needPhysics)
  5268. {
  5269. LLSDxmlEncode2.AddMap(sb);
  5270. LLSDxmlEncode2.AddElem("LocalID",(int)sop.LocalId, sb);
  5271. LLSDxmlEncode2.AddElem("Density", sop.Density, sb);
  5272. LLSDxmlEncode2.AddElem("Friction", sop.Friction, sb);
  5273. LLSDxmlEncode2.AddElem("GravityMultiplier", sop.GravityModifier, sb);
  5274. LLSDxmlEncode2.AddElem("Restitution", sop.Restitution, sb);
  5275. LLSDxmlEncode2.AddElem("PhysicsShapeType", (int)sop.PhysicsShapeType, sb);
  5276. LLSDxmlEncode2.AddEndMap(sb);
  5277. }
  5278. LLSDxmlEncode2.AddEndArray(sb);
  5279. eq.Enqueue(eq.EndEventToBytes(sb), m_agentId);
  5280. }
  5281. }
  5282. foreach(EntityUpdate eu in used)
  5283. eu.Free();
  5284. }
  5285. private static void CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, PrimUpdateFlags requestFlags, LLUDPZeroEncoder zc)
  5286. {
  5287. SceneObjectPart root = sop.ParentGroup.RootPart;
  5288. zc.AddUInt((uint)requestFlags);
  5289. zc.AddUUID(sop.UUID);
  5290. if (sop.OwnerID == sop.GroupID)
  5291. zc.AddZeros(16);
  5292. else
  5293. zc.AddUUID(sop.OwnerID);
  5294. zc.AddUUID(sop.GroupID);
  5295. zc.AddUInt(root.BaseMask);
  5296. zc.AddUInt(root.OwnerMask);
  5297. zc.AddUInt(root.GroupMask);
  5298. zc.AddUInt(root.EveryoneMask);
  5299. zc.AddUInt(root.NextOwnerMask);
  5300. zc.AddZeros(4); // int ownership cost
  5301. //sale info block
  5302. zc.AddByte(root.ObjectSaleType);
  5303. zc.AddInt(root.SalePrice);
  5304. zc.AddUInt(sop.Category); //Category
  5305. zc.AddUUID(sop.LastOwnerID);
  5306. //name
  5307. zc.AddShortLimitedUTF8(sop.osUTF8Name);
  5308. //Description
  5309. zc.AddShortLimitedUTF8(sop.osUTF8Description);
  5310. }
  5311. private static void CreateObjectPropertiesBlock(SceneObjectPart sop, LLUDPZeroEncoder zc)
  5312. {
  5313. SceneObjectPart root = sop.ParentGroup.RootPart;
  5314. zc.AddUUID(sop.UUID);
  5315. zc.AddUUID(sop.CreatorID);
  5316. if (sop.OwnerID == sop.GroupID)
  5317. zc.AddZeros(16);
  5318. else
  5319. zc.AddUUID(sop.OwnerID);
  5320. zc.AddUUID(sop.GroupID);
  5321. zc.AddUInt64((ulong)sop.CreationDate * 1000000UL);
  5322. zc.AddUInt(root.BaseMask);
  5323. zc.AddUInt(root.OwnerMask);
  5324. zc.AddUInt(root.GroupMask);
  5325. zc.AddUInt(root.EveryoneMask);
  5326. zc.AddUInt(root.NextOwnerMask);
  5327. zc.AddZeros(4); // int ownership cost
  5328. //sale info block
  5329. zc.AddByte(root.ObjectSaleType);
  5330. zc.AddInt(root.SalePrice);
  5331. //aggregated perms we may will need to fix this
  5332. zc.AddByte(0); //AggregatePerms
  5333. zc.AddByte(0); //AggregatePermTextures;
  5334. zc.AddByte(0); //AggregatePermTexturesOwner
  5335. //inventory info
  5336. zc.AddUInt(sop.Category); //Category
  5337. zc.AddInt16((short)sop.InventorySerial);
  5338. zc.AddUUID(sop.FromUserInventoryItemID);
  5339. zc.AddUUID(UUID.Zero); //FolderID
  5340. zc.AddUUID(UUID.Zero); //FromTaskID
  5341. zc.AddUUID(sop.LastOwnerID);
  5342. //name
  5343. zc.AddShortLimitedUTF8(sop.osUTF8Name);
  5344. //Description
  5345. zc.AddShortLimitedUTF8(sop.osUTF8Description);
  5346. // touch name
  5347. zc.AddShortLimitedUTF8(sop.osUTF8TouchName);
  5348. // sit name
  5349. zc.AddShortLimitedUTF8(sop.osUTF8SitName);
  5350. //texture ids block
  5351. // still not sending, not clear the impact on viewers, if any.
  5352. // does seem redundant
  5353. // to send we will need proper list of face texture ids without having to unpack texture entry all the time
  5354. zc.AddZeros(1);
  5355. }
  5356. #region Estate Data Sending Methods
  5357. private static bool convertParamStringToBool(byte[] field)
  5358. {
  5359. string s = Utils.BytesToString(field);
  5360. if (s == "1" || s.ToLower() == "y" || s.ToLower() == "yes" || s.ToLower() == "t" || s.ToLower() == "true")
  5361. {
  5362. return true;
  5363. }
  5364. return false;
  5365. }
  5366. public void SendEstateList(UUID invoice, int code, UUID[] Data, uint estateID)
  5367. {
  5368. int TotalnumberIDs = Data.Length;
  5369. int numberIDs;
  5370. int IDIndex = 0;
  5371. do
  5372. {
  5373. if(TotalnumberIDs > 63)
  5374. numberIDs = 63;
  5375. else
  5376. numberIDs = TotalnumberIDs;
  5377. TotalnumberIDs -= numberIDs;
  5378. EstateOwnerMessagePacket packet = new();
  5379. packet.AgentData.TransactionID = UUID.Random();
  5380. packet.AgentData.AgentID = m_agentId;
  5381. packet.AgentData.SessionID = SessionId;
  5382. packet.MethodData.Invoice = invoice;
  5383. packet.MethodData.Method = Utils.StringToBytes("setaccess");
  5384. EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + numberIDs];
  5385. for (int i = 0; i < (6 + numberIDs); i++)
  5386. {
  5387. returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
  5388. }
  5389. returnblock[0].Parameter = Utils.StringToBytes(estateID.ToString());
  5390. returnblock[1].Parameter = Utils.StringToBytes(code.ToString());
  5391. if((code & 1) != 0) // allowagents
  5392. returnblock[2].Parameter = Utils.StringToBytes(numberIDs.ToString());
  5393. else
  5394. returnblock[2].Parameter = Utils.StringToBytes("0");
  5395. if((code & 2) != 0) // groups
  5396. returnblock[3].Parameter = Utils.StringToBytes(numberIDs.ToString());
  5397. else
  5398. returnblock[3].Parameter = Utils.StringToBytes("0");
  5399. if((code & 4) != 0) // bans
  5400. returnblock[4].Parameter = Utils.StringToBytes(numberIDs.ToString());
  5401. else
  5402. returnblock[4].Parameter = Utils.StringToBytes("0");
  5403. if((code & 8) != 0) // managers
  5404. returnblock[5].Parameter = Utils.StringToBytes(numberIDs.ToString());
  5405. else
  5406. returnblock[5].Parameter = Utils.StringToBytes("0");
  5407. int j = 6;
  5408. for (int i = 0; i < numberIDs; i++)
  5409. {
  5410. returnblock[j].Parameter = Data[IDIndex].GetBytes();
  5411. j++;
  5412. IDIndex++;
  5413. }
  5414. packet.ParamList = returnblock;
  5415. packet.Header.Reliable = true;
  5416. OutPacket(packet, ThrottleOutPacketType.Task);
  5417. } while (TotalnumberIDs > 0);
  5418. }
  5419. public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID)
  5420. {
  5421. List<UUID> BannedUsers = new();
  5422. for (int i = 0; i < bl.Length; i++)
  5423. {
  5424. if (bl[i] is null)
  5425. continue;
  5426. if (bl[i].BannedUserID.IsZero())
  5427. continue;
  5428. BannedUsers.Add(bl[i].BannedUserID);
  5429. }
  5430. SendEstateList(invoice, 4, BannedUsers.ToArray(), estateID);
  5431. }
  5432. public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args)
  5433. {
  5434. RegionInfoPacket rinfopack = new();
  5435. RegionInfoPacket.RegionInfoBlock rinfoblk = new();
  5436. rinfopack.AgentData.AgentID = m_agentId;
  5437. rinfopack.AgentData.SessionID = SessionId;
  5438. rinfoblk.BillableFactor = args.billableFactor;
  5439. rinfoblk.EstateID = args.estateID;
  5440. rinfoblk.MaxAgents = (byte)args.maxAgents;
  5441. rinfoblk.ObjectBonusFactor = args.objectBonusFactor;
  5442. rinfoblk.ParentEstateID = args.parentEstateID;
  5443. rinfoblk.PricePerMeter = args.pricePerMeter;
  5444. rinfoblk.RedirectGridX = args.redirectGridX;
  5445. rinfoblk.RedirectGridY = args.redirectGridY;
  5446. rinfoblk.RegionFlags = args.regionFlags;
  5447. rinfoblk.SimAccess = args.simAccess;
  5448. rinfoblk.SunHour = args.sunHour;
  5449. rinfoblk.TerrainLowerLimit = args.terrainLowerLimit;
  5450. rinfoblk.TerrainRaiseLimit = args.terrainRaiseLimit;
  5451. rinfoblk.UseEstateSun = args.useEstateSun;
  5452. rinfoblk.WaterHeight = args.waterHeight;
  5453. rinfoblk.SimName = Utils.StringToBytes(args.simName);
  5454. rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block
  5455. {
  5456. HardMaxAgents = (uint)args.AgentCapacity,
  5457. HardMaxObjects = (uint)args.ObjectsCapacity,
  5458. MaxAgents32 = (uint)args.maxAgents,
  5459. ProductName = Util.StringToBytes256(args.regionType),
  5460. ProductSKU = Utils.EmptyBytes
  5461. };
  5462. rinfopack.HasVariableBlocks = true;
  5463. rinfopack.RegionInfo = rinfoblk;
  5464. rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock
  5465. {
  5466. AgentID = m_agentId,
  5467. SessionID = m_sessionId
  5468. };
  5469. rinfopack.RegionInfo3 = Array.Empty<RegionInfoPacket.RegionInfo3Block>();
  5470. OutPacket(rinfopack, ThrottleOutPacketType.Task);
  5471. }
  5472. public void SendEstateCovenantInformation(UUID covenant)
  5473. {
  5474. //m_log.DebugFormat("[LLCLIENTVIEW]: Sending estate covenant asset id of {0} to {1}", covenant, Name);
  5475. EstateCovenantReplyPacket einfopack = new();
  5476. einfopack.Data.CovenantID = covenant;
  5477. einfopack.Data.CovenantTimestamp = (uint)m_scene.RegionInfo.RegionSettings.CovenantChangedDateTime;
  5478. einfopack.Data.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  5479. einfopack.Data.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName);
  5480. OutPacket(einfopack, ThrottleOutPacketType.Task);
  5481. }
  5482. public void SendDetailedEstateData(
  5483. UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition,
  5484. UUID covenant, uint covenantChanged, string abuseEmail, UUID estateOwner)
  5485. {
  5486. //m_log.DebugFormat(
  5487. // "[LLCLIENTVIEW]: Sending detailed estate data to {0} with covenant asset id {1}", Name, covenant);
  5488. EstateOwnerMessagePacket packet = new();
  5489. packet.MethodData.Invoice = invoice;
  5490. packet.AgentData.TransactionID = UUID.Random();
  5491. packet.MethodData.Method = Utils.StringToBytes("estateupdateinfo");
  5492. EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[10];
  5493. for (int i = 0; i < 10; i++)
  5494. {
  5495. returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
  5496. }
  5497. //Sending Estate Settings
  5498. returnblock[0].Parameter = Utils.StringToBytes(estateName);
  5499. returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString());
  5500. returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString());
  5501. returnblock[3].Parameter = Utils.StringToBytes(estateFlags.ToString());
  5502. returnblock[4].Parameter = Utils.StringToBytes(sunPosition.ToString());
  5503. returnblock[5].Parameter = Utils.StringToBytes(parentEstate.ToString());
  5504. returnblock[6].Parameter = Utils.StringToBytes(covenant.ToString());
  5505. returnblock[7].Parameter = Utils.StringToBytes(covenantChanged.ToString());
  5506. returnblock[8].Parameter = Utils.StringToBytes("1"); // what is this?
  5507. returnblock[9].Parameter = Utils.StringToBytes(abuseEmail);
  5508. packet.ParamList = returnblock;
  5509. //m_log.Debug("[ESTATE]: SIM--->" + packet.ToString());
  5510. OutPacket(packet, ThrottleOutPacketType.Task);
  5511. }
  5512. public void SendTelehubInfo(UUID ObjectID, string ObjectName, Vector3 ObjectPos, Quaternion ObjectRot, List<Vector3> SpawnPoint)
  5513. {
  5514. TelehubInfoPacket packet = (TelehubInfoPacket)PacketPool.Instance.GetPacket(PacketType.TelehubInfo);
  5515. packet.TelehubBlock.ObjectID = ObjectID;
  5516. packet.TelehubBlock.ObjectName = Utils.StringToBytes(ObjectName);
  5517. packet.TelehubBlock.TelehubPos = ObjectPos;
  5518. packet.TelehubBlock.TelehubRot = ObjectRot;
  5519. packet.SpawnPointBlock = new TelehubInfoPacket.SpawnPointBlockBlock[SpawnPoint.Count];
  5520. for (int n = 0; n < SpawnPoint.Count; n++)
  5521. {
  5522. packet.SpawnPointBlock[n] = new TelehubInfoPacket.SpawnPointBlockBlock{SpawnPointPos = SpawnPoint[n]};
  5523. }
  5524. OutPacket(packet, ThrottleOutPacketType.Task);
  5525. }
  5526. #endregion
  5527. #region Land Data Sending Methods
  5528. public void SendLandParcelOverlay(byte[] data, int sequence_id)
  5529. {
  5530. ParcelOverlayPacket packet = (ParcelOverlayPacket)PacketPool.Instance.GetPacket(PacketType.ParcelOverlay);
  5531. packet.ParcelData.Data = data;
  5532. packet.ParcelData.SequenceID = sequence_id;
  5533. OutPacket(packet, ThrottleOutPacketType.Land);
  5534. }
  5535. public void SendLandProperties(
  5536. int sequence_id, bool snap_selection, int request_result, ILandObject lo,
  5537. float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags)
  5538. {
  5539. //m_log.DebugFormat("[LLCLIENTVIEW]: Sending land properties for {0} to {1}", lo.LandData.GlobalID, Name);
  5540. IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
  5541. if (eq is null)
  5542. {
  5543. m_log.Warn("[LLCLIENTVIEW]: No EQ Interface when sending parcel data.");
  5544. return;
  5545. }
  5546. LandData landData = lo.LandData;
  5547. IPrimCounts pc = lo.PrimCounts;
  5548. int cap = 4 * landData.Bitmap.Length / 3 + 2048;
  5549. osUTF8 sb = eq.StartEvent("ParcelProperties", cap);
  5550. LLSDxmlEncode2.AddArrayAndMap("ParcelData", sb);
  5551. LLSDxmlEncode2.AddElem("LocalID", landData.LocalID, sb);
  5552. LLSDxmlEncode2.AddElem("AABBMax", landData.AABBMax, sb);
  5553. LLSDxmlEncode2.AddElem("AABBMin", landData.AABBMin, sb);
  5554. LLSDxmlEncode2.AddElem("Area", landData.Area, sb);
  5555. LLSDxmlEncode2.AddElem("AuctionID", (int)landData.AuctionID, sb);
  5556. LLSDxmlEncode2.AddElem("AuthBuyerID", landData.AuthBuyerID, sb);
  5557. LLSDxmlEncode2.AddElem("Bitmap", landData.Bitmap, sb);
  5558. LLSDxmlEncode2.AddElem("Category", (int)landData.Category, sb);
  5559. LLSDxmlEncode2.AddElem("ClaimDate", Util.ToDateTime(landData.ClaimDate), sb);
  5560. LLSDxmlEncode2.AddElem("ClaimPrice", landData.ClaimPrice, sb);
  5561. LLSDxmlEncode2.AddElem("Desc", landData.Description, sb);
  5562. LLSDxmlEncode2.AddElem("ParcelFlags", landData.Flags, sb);
  5563. LLSDxmlEncode2.AddElem("GroupID", landData.GroupID, sb);
  5564. LLSDxmlEncode2.AddElem("GroupPrims", pc.Group, sb);
  5565. LLSDxmlEncode2.AddElem("IsGroupOwned", landData.IsGroupOwned, sb);
  5566. LLSDxmlEncode2.AddElem("LandingType", (int)landData.LandingType, sb);
  5567. if (landData.Area > 0)
  5568. LLSDxmlEncode2.AddElem("MaxPrims", parcelObjectCapacity, sb);
  5569. else
  5570. LLSDxmlEncode2.AddElem("MaxPrims", (int)0, sb);
  5571. LLSDxmlEncode2.AddElem("MediaID", landData.MediaID, sb);
  5572. LLSDxmlEncode2.AddElem("MediaURL", landData.MediaURL, sb);
  5573. LLSDxmlEncode2.AddElem("MediaAutoScale", landData.MediaAutoScale != 0, sb);
  5574. LLSDxmlEncode2.AddElem("MusicURL", landData.MusicURL, sb);
  5575. LLSDxmlEncode2.AddElem("Name", landData.Name, sb);
  5576. LLSDxmlEncode2.AddElem("OtherCleanTime", landData.OtherCleanTime, sb);
  5577. LLSDxmlEncode2.AddElem("OtherCount", (int)0 , sb); //TODO
  5578. LLSDxmlEncode2.AddElem("OtherPrims", pc.Others, sb);
  5579. LLSDxmlEncode2.AddElem("OwnerID", landData.OwnerID, sb);
  5580. LLSDxmlEncode2.AddElem("OwnerPrims", pc.Owner, sb);
  5581. LLSDxmlEncode2.AddElem("ParcelPrimBonus", simObjectBonusFactor, sb);
  5582. LLSDxmlEncode2.AddElem("PassHours", landData.PassHours, sb);
  5583. LLSDxmlEncode2.AddElem("PassPrice", landData.PassPrice, sb);
  5584. LLSDxmlEncode2.AddElem("PublicCount", (int)0, sb); //TODO
  5585. LLSDxmlEncode2.AddElem("RegionDenyAnonymous", (regionFlags & (uint)RegionFlags.DenyAnonymous) != 0, sb);
  5586. LLSDxmlEncode2.AddElem("RegionDenyIdentified", false, sb);
  5587. LLSDxmlEncode2.AddElem("RegionDenyTransacted", false, sb);
  5588. LLSDxmlEncode2.AddElem("RegionPushOverride", (regionFlags & (uint)RegionFlags.RestrictPushObject) != 0, sb);
  5589. LLSDxmlEncode2.AddElem("RentPrice", (int) 0, sb);
  5590. LLSDxmlEncode2.AddElem("RequestResult", request_result, sb);
  5591. LLSDxmlEncode2.AddElem("SalePrice", landData.SalePrice, sb);
  5592. LLSDxmlEncode2.AddElem("SelectedPrims", pc.Selected, sb);
  5593. LLSDxmlEncode2.AddElem("SelfCount", (int)0, sb); //TODO
  5594. LLSDxmlEncode2.AddElem("SequenceID", sequence_id, sb);
  5595. if (landData.SimwideArea > 0)
  5596. LLSDxmlEncode2.AddElem("SimWideMaxPrims", lo.GetSimulatorMaxPrimCount(), sb);
  5597. else
  5598. LLSDxmlEncode2.AddElem("SimWideMaxPrims", (int)0, sb);
  5599. LLSDxmlEncode2.AddElem("SimWideTotalPrims", pc.Simulator, sb);
  5600. LLSDxmlEncode2.AddElem("SnapSelection", snap_selection, sb);
  5601. LLSDxmlEncode2.AddElem("SnapshotID", landData.SnapshotID, sb);
  5602. LLSDxmlEncode2.AddElem("Status", (int)landData.Status, sb);
  5603. LLSDxmlEncode2.AddElem("TotalPrims", pc.Total, sb);
  5604. LLSDxmlEncode2.AddElem("UserLocation", landData.UserLocation, sb);
  5605. LLSDxmlEncode2.AddElem("UserLookAt", landData.UserLookAt, sb);
  5606. LLSDxmlEncode2.AddElem("SeeAVs", landData.SeeAVs, sb);
  5607. LLSDxmlEncode2.AddElem("AnyAVSounds", landData.AnyAVSounds, sb);
  5608. LLSDxmlEncode2.AddElem("GroupAVSounds", landData.GroupAVSounds, sb);
  5609. LLSDxmlEncode2.AddEndMapAndArray(sb);
  5610. LLSDxmlEncode2.AddArrayAndMap("MediaData", sb);
  5611. LLSDxmlEncode2.AddElem("MediaDesc", landData.MediaDescription, sb);
  5612. LLSDxmlEncode2.AddElem("MediaHeight", landData.MediaHeight, sb);
  5613. LLSDxmlEncode2.AddElem("MediaWidth", landData.MediaWidth, sb);
  5614. LLSDxmlEncode2.AddElem("MediaLoop", landData.MediaLoop, sb);
  5615. LLSDxmlEncode2.AddElem("MediaType", landData.MediaType, sb);
  5616. //LLSDxmlEncode2.AddElem("ObscureMedia", landData.ObscureMedia, sb);
  5617. LLSDxmlEncode2.AddElem("ObscureMedia", false, sb); //obsolete
  5618. //LLSDxmlEncode2.AddElem("ObscureMusic", landData.ObscureMusic, sb);
  5619. LLSDxmlEncode2.AddElem("ObscureMusic", false, sb); //obsolete
  5620. LLSDxmlEncode2.AddEndMapAndArray(sb);
  5621. LLSDxmlEncode2.AddArrayAndMap("ParcelExtendedFlags", sb); // obscure moap
  5622. LLSDxmlEncode2.AddElem("Flags", (uint)(landData.ObscureMedia ? 1 : (int)0), sb);
  5623. LLSDxmlEncode2.AddEndMapAndArray(sb);
  5624. LLSDxmlEncode2.AddArrayAndMap("AgeVerificationBlock", sb);
  5625. LLSDxmlEncode2.AddElem("RegionDenyAgeUnverified", (regionFlags & (uint)RegionFlags.DenyAgeUnverified) != 0, sb);
  5626. LLSDxmlEncode2.AddEndMapAndArray(sb);
  5627. bool allowenvovr = (regionFlags & (uint)RegionFlags.AllowEnvironmentOverride) != 0;
  5628. int envVersion;
  5629. if(allowenvovr)
  5630. {
  5631. if (SceneAgent is ScenePresence sp && sp.EnvironmentVersion > 0)
  5632. envVersion = -1;
  5633. else
  5634. envVersion = landData.EnvironmentVersion;
  5635. }
  5636. else
  5637. envVersion = -1;
  5638. LLSDxmlEncode2.AddArrayAndMap("ParcelEnvironmentBlock", sb);
  5639. LLSDxmlEncode2.AddElem("ParcelEnvironmentVersion", envVersion, sb);
  5640. LLSDxmlEncode2.AddElem("RegionAllowEnvironmentOverride", allowenvovr, sb);
  5641. LLSDxmlEncode2.AddEndMapAndArray(sb);
  5642. bool accessovr = !Scene.RegionInfo.EstateSettings.TaxFree;
  5643. LLSDxmlEncode2.AddArrayAndMap("RegionAllowAccessBlock", sb);
  5644. LLSDxmlEncode2.AddElem("RegionAllowAccessOverride", accessovr, sb);
  5645. LLSDxmlEncode2.AddEndMapAndArray(sb);
  5646. eq.Enqueue(eq.EndEventToBytes(sb), m_agentId);
  5647. }
  5648. public void SendLandAccessListData(List<LandAccessEntry> accessList, uint accessFlag, int localLandID)
  5649. {
  5650. ParcelAccessListReplyPacket replyPacket = (ParcelAccessListReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply);
  5651. replyPacket.Data.AgentID = m_agentId;
  5652. replyPacket.Data.Flags = accessFlag;
  5653. replyPacket.Data.LocalID = localLandID;
  5654. replyPacket.Data.SequenceID = 0;
  5655. List<ParcelAccessListReplyPacket.ListBlock> list = new();
  5656. foreach (LandAccessEntry entry in accessList)
  5657. {
  5658. ParcelAccessListReplyPacket.ListBlock block = new()
  5659. {
  5660. Flags = accessFlag,
  5661. ID = entry.AgentID,
  5662. Time = entry.Expires
  5663. };
  5664. list.Add(block);
  5665. }
  5666. replyPacket.List = list.ToArray();
  5667. replyPacket.Header.Zerocoded = true;
  5668. OutPacket(replyPacket, ThrottleOutPacketType.Task);
  5669. }
  5670. public void SendForceClientSelectObjects(List<uint> ObjectIDs)
  5671. {
  5672. // m_log.DebugFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count);
  5673. bool firstCall = true;
  5674. const int MAX_OBJECTS_PER_PACKET = 251;
  5675. ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect);
  5676. ForceObjectSelectPacket.DataBlock[] data;
  5677. while (ObjectIDs.Count > 0)
  5678. {
  5679. if (firstCall)
  5680. {
  5681. pack._Header.ResetList = true;
  5682. firstCall = false;
  5683. }
  5684. else
  5685. {
  5686. pack._Header.ResetList = false;
  5687. }
  5688. if (ObjectIDs.Count > MAX_OBJECTS_PER_PACKET)
  5689. {
  5690. data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET];
  5691. }
  5692. else
  5693. {
  5694. data = new ForceObjectSelectPacket.DataBlock[ObjectIDs.Count];
  5695. }
  5696. int i;
  5697. for (i = 0; i < MAX_OBJECTS_PER_PACKET && ObjectIDs.Count > 0; i++)
  5698. {
  5699. data[i] = new ForceObjectSelectPacket.DataBlock
  5700. {
  5701. LocalID = Convert.ToUInt32(ObjectIDs[0])
  5702. };
  5703. ObjectIDs.RemoveAt(0);
  5704. }
  5705. pack.Data = data;
  5706. pack.Header.Zerocoded = true;
  5707. OutPacket(pack, ThrottleOutPacketType.Task);
  5708. }
  5709. }
  5710. public void SendCameraConstraint(Vector4 ConstraintPlane)
  5711. {
  5712. CameraConstraintPacket cpack = (CameraConstraintPacket)PacketPool.Instance.GetPacket(PacketType.CameraConstraint);
  5713. cpack.CameraCollidePlane = new CameraConstraintPacket.CameraCollidePlaneBlock
  5714. {
  5715. Plane = ConstraintPlane
  5716. };
  5717. //m_log.DebugFormat("[CLIENTVIEW]: Constraint {0}", ConstraintPlane);
  5718. OutPacket(cpack, ThrottleOutPacketType.Task);
  5719. }
  5720. public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
  5721. {
  5722. int notifyCount = ownersAndCount.Count;
  5723. ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply);
  5724. if (notifyCount > 0)
  5725. {
  5726. ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
  5727. = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
  5728. int num = 0;
  5729. foreach (UUID owner in ownersAndCount.Keys)
  5730. {
  5731. dataBlock[num++] = new ParcelObjectOwnersReplyPacket.DataBlock
  5732. {
  5733. Count = ownersAndCount[owner],
  5734. OnlineStatus = true, //TODO: fix me later
  5735. OwnerID = owner,
  5736. IsGroupOwned = land.GroupID.Equals(owner) || groups.Contains(owner)
  5737. };
  5738. if (num >= notifyCount)
  5739. break;
  5740. }
  5741. pack.Data = dataBlock;
  5742. }
  5743. else
  5744. {
  5745. pack.Data = Array.Empty<ParcelObjectOwnersReplyPacket.DataBlock>();
  5746. }
  5747. pack.Header.Zerocoded = true;
  5748. OutPacket(pack, ThrottleOutPacketType.Task);
  5749. }
  5750. #endregion
  5751. #region Helper Methods
  5752. private static void ClampVectorForUint(ref Vector3 v, float max)
  5753. {
  5754. float a, b;
  5755. a = MathF.Abs(v.X);
  5756. b = MathF.Abs(v.Y);
  5757. if (b > a)
  5758. a = b;
  5759. b = MathF.Abs(v.Z);
  5760. if (b > a)
  5761. a = b;
  5762. if (a > max)
  5763. {
  5764. a = max / a;
  5765. v.X *= a;
  5766. v.Y *= a;
  5767. v.Z *= a;
  5768. }
  5769. }
  5770. protected static void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture)
  5771. {
  5772. #region ScenePresence/SOP Handling
  5773. bool avatar = (entity is ScenePresence);
  5774. uint attachPoint;
  5775. Vector4 collisionPlane;
  5776. Vector3 position, velocity, acceleration, angularVelocity;
  5777. Quaternion rotation;
  5778. byte datasize;
  5779. byte[] te = null;
  5780. if (avatar)
  5781. {
  5782. ScenePresence presence = (ScenePresence)entity;
  5783. position = presence.OffsetPosition;
  5784. velocity = presence.Velocity;
  5785. acceleration = Vector3.Zero;
  5786. rotation = presence.Rotation;
  5787. // tpvs can only see rotations around Z in some cases
  5788. if (!presence.Flying && !presence.IsSatOnObject)
  5789. {
  5790. rotation.X = 0f;
  5791. rotation.Y = 0f;
  5792. }
  5793. rotation.Normalize();
  5794. angularVelocity = presence.AngularVelocity;
  5795. //m_log.DebugFormat(
  5796. // "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
  5797. attachPoint = presence.State;
  5798. collisionPlane = presence.CollisionPlane;
  5799. datasize = 60;
  5800. }
  5801. else
  5802. {
  5803. SceneObjectPart part = (SceneObjectPart)entity;
  5804. attachPoint = part.ParentGroup.AttachmentPoint;
  5805. attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16));
  5806. //m_log.DebugFormat(
  5807. // "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}",
  5808. // attachPoint, part.Name, part.LocalId, Name);
  5809. collisionPlane = Vector4.Zero;
  5810. position = part.RelativePosition;
  5811. velocity = part.Velocity;
  5812. acceleration = part.Acceleration;
  5813. angularVelocity = part.AngularVelocity;
  5814. rotation = part.RotationOffset;
  5815. datasize = 44;
  5816. if (includeTexture)
  5817. te = part.Shape.TextureEntry;
  5818. }
  5819. #endregion ScenePresence/SOP Handling
  5820. //object block size
  5821. data[pos++] = datasize;
  5822. // LocalID
  5823. Utils.UIntToBytes(entity.LocalId, data, pos);
  5824. pos += 4;
  5825. data[pos++] = (byte)attachPoint;
  5826. // Avatar/CollisionPlane
  5827. if (avatar)
  5828. {
  5829. data[pos++] = 1;
  5830. //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane);
  5831. if (collisionPlane == Vector4.Zero)
  5832. Vector4.UnitW.ToBytes(data, pos);
  5833. else
  5834. collisionPlane.ToBytes(data, pos);
  5835. pos += 16;
  5836. }
  5837. else
  5838. {
  5839. data[pos++] = 0;
  5840. }
  5841. // Position
  5842. position.ToBytes(data, pos);
  5843. pos += 12;
  5844. // Velocity
  5845. ClampVectorForUint(ref velocity, 128f);
  5846. Utils.FloatToUInt16Bytes(velocity.X, 128.0f, data, pos); pos += 2;
  5847. Utils.FloatToUInt16Bytes(velocity.Y, 128.0f, data, pos); pos += 2;
  5848. Utils.FloatToUInt16Bytes(velocity.Z, 128.0f, data, pos); pos += 2;
  5849. // Acceleration
  5850. ClampVectorForUint(ref acceleration, 64f);
  5851. Utils.FloatToUInt16Bytes(acceleration.X, 64.0f, data, pos); pos += 2;
  5852. Utils.FloatToUInt16Bytes(acceleration.Y, 64.0f, data, pos); pos += 2;
  5853. Utils.FloatToUInt16Bytes(acceleration.Z, 64.0f, data, pos); pos += 2;
  5854. // Rotation
  5855. Utils.FloatToUInt16Bytes(rotation.X, 1.0f, data, pos); pos += 2;
  5856. Utils.FloatToUInt16Bytes(rotation.Y, 1.0f, data, pos); pos += 2;
  5857. Utils.FloatToUInt16Bytes(rotation.Z, 1.0f, data, pos); pos += 2;
  5858. Utils.FloatToUInt16Bytes(rotation.W, 1.0f, data, pos); pos += 2;
  5859. // Angular Velocity
  5860. ClampVectorForUint(ref angularVelocity, 64f);
  5861. Utils.FloatToUInt16Bytes(angularVelocity.X, 64.0f, data, pos); pos += 2;
  5862. Utils.FloatToUInt16Bytes(angularVelocity.Y, 64.0f, data, pos); pos += 2;
  5863. Utils.FloatToUInt16Bytes(angularVelocity.Z, 64.0f, data, pos); pos += 2;
  5864. // texture entry block size
  5865. if (te is null)
  5866. {
  5867. data[pos++] = 0;
  5868. data[pos++] = 0;
  5869. }
  5870. else
  5871. {
  5872. int len = te.Length & 0x7fff;
  5873. int totlen = len + 4;
  5874. data[pos++] = (byte)totlen;
  5875. data[pos++] = (byte)(totlen >> 8);
  5876. data[pos++] = (byte)len; // wtf ???
  5877. data[pos++] = (byte)(len >> 8);
  5878. data[pos++] = 0;
  5879. data[pos++] = 0;
  5880. Buffer.BlockCopy(te, 0, data, pos, len);
  5881. pos += len;
  5882. }
  5883. // total size 63 or 47 + (texture size + 4)
  5884. }
  5885. protected static void CreatePartImprovedTerseBlock(SceneObjectPart part, byte[] data, ref int pos, bool includeTexture)
  5886. {
  5887. //object block size
  5888. data[pos++] = 44;
  5889. // LocalID
  5890. Utils.UIntToBytesSafepos(part.LocalId, data, pos);
  5891. pos += 4;
  5892. if (part.ParentGroup.AttachmentPoint == 0)
  5893. data[pos++] = 0;
  5894. else
  5895. {
  5896. uint attachPoint = 0xff & part.ParentGroup.AttachmentPoint;
  5897. data[pos++] = (byte)(attachPoint << 4 | attachPoint >> 4);
  5898. }
  5899. // no Avatar/CollisionPlane
  5900. data[pos++] = 0;
  5901. // Position
  5902. part.RelativePosition.ToBytes(data, pos);
  5903. pos += 12;
  5904. // Velocity
  5905. part.Velocity.ClampedToShortsBytes(128f, data, pos); pos += 6;
  5906. // Acceleration
  5907. part.Acceleration.ClampedToShortsBytes(64f, data, pos); pos += 6;
  5908. // Rotation
  5909. part.RotationOffset.ToShortsBytes(data, pos); pos += 8;
  5910. // Angular Velocity
  5911. part.AngularVelocity.ClampedToShortsBytes(64f, data, pos); pos += 6;
  5912. // texture entry block size
  5913. if (includeTexture && part.Shape.TextureEntry != null)
  5914. {
  5915. byte[] te = part.Shape.TextureEntry;
  5916. int len = te.Length & 0x7fff;
  5917. int totlen = len + 4;
  5918. data[pos++] = (byte)totlen;
  5919. data[pos++] = (byte)(totlen >> 8);
  5920. data[pos++] = (byte)len; // wtf ???
  5921. data[pos++] = (byte)(len >> 8);
  5922. data[pos++] = 0;
  5923. data[pos++] = 0;
  5924. Buffer.BlockCopy(te, 0, data, pos, len);
  5925. pos += len;
  5926. }
  5927. else
  5928. {
  5929. data[pos++] = 0;
  5930. data[pos++] = 0;
  5931. }
  5932. // total size 47 + (texture size + 4)
  5933. }
  5934. protected unsafe void CreatePartImprovedTerseBlock(SceneObjectPart part, ref byte* data, bool includeTexture)
  5935. {
  5936. //object block size
  5937. *data++ = 44;
  5938. // LocalID
  5939. Utils.UIntToBytes(part.LocalId, data); data += 4;
  5940. if (part.ParentGroup.AttachmentPoint == 0)
  5941. *data++ = 0;
  5942. else
  5943. {
  5944. uint attachPoint = 0xff & part.ParentGroup.AttachmentPoint;
  5945. *data++ = (byte)(attachPoint << 4 | attachPoint >> 4);
  5946. }
  5947. // no Avatar/CollisionPlane
  5948. *data++ = 0;
  5949. // Position
  5950. part.RelativePosition.ToBytes(data); data += 12;
  5951. // Velocity
  5952. part.Velocity.ClampedToShortsBytes(128f, data); data += 6;
  5953. // Acceleration
  5954. part.Acceleration.ClampedToShortsBytes(64f, data); data += 6;
  5955. // Rotation
  5956. part.RotationOffset.ToShortsBytes(data); data += 8;
  5957. // Angular Velocity
  5958. part.AngularVelocity.ClampedToShortsBytes(64f, data); data += 6;
  5959. // texture entry block size
  5960. if (includeTexture && part.Shape.TextureEntry != null)
  5961. {
  5962. byte[] te = part.Shape.TextureEntry;
  5963. uint len = (uint)te.Length & 0x7fff;
  5964. ushort totlen = (ushort)(len + 4);
  5965. Utils.UInt16ToBytes(totlen, data); data += 2;
  5966. Utils.UIntToBytes(len, data); data += 4;
  5967. fixed(byte* t = &te[0])
  5968. Buffer.MemoryCopy(t, data, 4096, (long)len);
  5969. data += len;
  5970. }
  5971. else
  5972. {
  5973. *data++ = 0;
  5974. *data++ = 0;
  5975. }
  5976. // total size 47 + (texture size + 4)
  5977. }
  5978. protected static void CreateAvatartImprovedTerseBlock(ScenePresence presence, byte[] data, ref int pos)
  5979. {
  5980. //m_log.DebugFormat(
  5981. // "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
  5982. //object block size
  5983. data[pos++] = 60;
  5984. // LocalID
  5985. Utils.UIntToBytesSafepos(presence.LocalId, data, pos);
  5986. pos += 4;
  5987. data[pos++] = presence.State;
  5988. // Avatar/CollisionPlane
  5989. data[pos++] = 1;
  5990. //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane);
  5991. if (presence.CollisionPlane.IsZero())
  5992. Vector4.UnitW.ToBytes(data, pos);
  5993. else
  5994. presence.CollisionPlane.ToBytes(data, pos);
  5995. pos += 16;
  5996. // Position
  5997. presence.OffsetPosition.ToBytes(data, pos);
  5998. pos += 12;
  5999. // Velocity
  6000. presence.Velocity.ClampedToShortsBytes(128f, data, pos); pos += 6;
  6001. // Acceleration is zero
  6002. Utils.UIntToBytesSafepos(0x7fff7fff, data, pos); pos += 4;
  6003. Utils.UInt16ToBytes(0x7fff, data, pos); pos += 2;
  6004. // Rotation
  6005. // tpvs can only see rotations around Z in some cases
  6006. Quaternion rotation = presence.Rotation;
  6007. if (!presence.Flying && !presence.IsSatOnObject)
  6008. {
  6009. Utils.UIntToBytesSafepos(0x7fff7fff, data, pos); pos += 4;
  6010. float rz = rotation.Z;
  6011. float rw = rotation.W;
  6012. float a = rz * rz + rw * rw;
  6013. if (a > -1e-6f && a < 1e-6f)
  6014. {
  6015. Utils.UIntToBytesSafepos(0xffff7fff, data, pos); pos += 4;
  6016. }
  6017. else
  6018. {
  6019. a = 1.0f / MathF.Sqrt(a);
  6020. Utils.FloatToUInt16Bytes(rz * a, 1.0f, data, pos); pos += 2;
  6021. Utils.FloatToUInt16Bytes(rw * a, 1.0f, data, pos); pos += 2;
  6022. }
  6023. }
  6024. else
  6025. {
  6026. rotation.ToShortsBytes(data, pos); pos += 8;
  6027. }
  6028. // Angular Velocity
  6029. presence.AngularVelocity.ClampedToShortsBytes(64f, data, pos); pos += 6;
  6030. //texture
  6031. data[pos++] = 0;
  6032. data[pos++] = 0;
  6033. // total size 63
  6034. }
  6035. protected unsafe void CreateAvatartImprovedTerseBlock(ScenePresence presence, ref byte* data)
  6036. {
  6037. //m_log.DebugFormat(
  6038. // "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
  6039. //object block size
  6040. *data++ = 60;
  6041. // LocalID
  6042. Utils.UIntToBytes(presence.LocalId, data); data += 4;
  6043. *data++ = presence.State;
  6044. // Avatar/CollisionPlane
  6045. *data++ = 1;
  6046. //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane);
  6047. if (presence.CollisionPlane.IsZero())
  6048. Vector4.UnitW.ToBytes(data);
  6049. else
  6050. presence.CollisionPlane.ToBytes(data);
  6051. data += 16;
  6052. // Position
  6053. presence.OffsetPosition.ToBytes(data); data += 12;
  6054. // Velocity
  6055. presence.Velocity.ClampedToShortsBytes(128f, data); data += 6;
  6056. // Acceleration is zero
  6057. Utils.UIntToBytes(0x7fff7fff, data); data += 4;
  6058. Utils.UInt16ToBytes(0x7fff, data); data += 2;
  6059. // Rotation
  6060. // tpvs can only see rotations around Z in some cases
  6061. Quaternion rotation = presence.Rotation;
  6062. if (!presence.Flying && !presence.IsSatOnObject)
  6063. {
  6064. Utils.UIntToBytes(0x7fff7fff, data); data += 4;
  6065. float rz = rotation.Z;
  6066. float rw = rotation.W;
  6067. float a = rz * rz + rw * rw;
  6068. if (a > -1e-6f && a < 1e-6f)
  6069. {
  6070. Utils.UIntToBytes(0xffff7fff, data); data += 4;
  6071. }
  6072. else
  6073. {
  6074. a = 1.0f / MathF.Sqrt(a);
  6075. Utils.UInt16ToBytes(Utils.FloatToUnitUInt16(rz * a), data); data += 2;
  6076. Utils.UInt16ToBytes(Utils.FloatToUnitUInt16(rw * a), data); data += 2;
  6077. }
  6078. }
  6079. else
  6080. {
  6081. rotation.ToShortsBytes(data); data += 8;
  6082. }
  6083. // Angular Velocity
  6084. presence.AngularVelocity.ClampedToShortsBytes(64f, data); data += 6;
  6085. //texture
  6086. *data++ = 0;
  6087. *data++ = 0;
  6088. // total size 63
  6089. }
  6090. protected static void CreateAvatarUpdateBlock(ScenePresence data, byte[] dest, ref int pos)
  6091. {
  6092. Utils.UIntToBytesSafepos(data.LocalId, dest, pos); pos += 4;
  6093. dest[pos++] = 0; // state
  6094. data.UUID.ToBytes(dest, pos); pos += 16;
  6095. Utils.UIntToBytesSafepos(0 , dest, pos); pos += 4; // crc
  6096. dest[pos++] = (byte)PCode.Avatar;
  6097. dest[pos++] = (byte)Material.Flesh;
  6098. dest[pos++] = 0; // clickaction
  6099. data.Appearance.AvatarSize.ToBytes(dest, pos); pos += 12;
  6100. // objectdata block
  6101. dest[pos++] = 76;
  6102. data.CollisionPlane.ToBytes(dest, pos); pos += 16;
  6103. data.OffsetPosition.ToBytes(dest, pos); pos += 12;
  6104. data.Velocity.ToBytes(dest, pos); pos += 12;
  6105. //acceleration.ToBytes(dest, pos); pos += 12;
  6106. Array.Clear(dest, pos, 12); pos += 12;
  6107. Quaternion rotation = data.Rotation;
  6108. // tpvs can only see rotations around Z in some cases
  6109. if (!data.Flying && !data.IsSatOnObject)
  6110. {
  6111. rotation.X = 0f;
  6112. rotation.Y = 0f;
  6113. }
  6114. rotation.ToBytes(dest, pos); pos += 12;
  6115. //angularvelocity.ToBytes(dest, pos); pos += 12;
  6116. Array.Clear(dest, pos, 12); pos += 12;
  6117. SceneObjectPart parentPart = data.ParentPart;
  6118. if (parentPart != null)
  6119. {
  6120. Utils.UIntToBytesSafepos(parentPart.ParentGroup.LocalId, dest, pos);
  6121. pos += 4;
  6122. }
  6123. else
  6124. {
  6125. //Utils.UIntToBytesSafepos(0, dest, pos);
  6126. //pos += 4;
  6127. dest[pos++] = 0;
  6128. dest[pos++] = 0;
  6129. dest[pos++] = 0;
  6130. dest[pos++] = 0;
  6131. }
  6132. //Utils.UIntToBytesSafepos(0, dest, pos); pos += 4; //update flags
  6133. dest[pos++] = 0;
  6134. dest[pos++] = 0;
  6135. dest[pos++] = 0;
  6136. dest[pos++] = 0;
  6137. //pbs
  6138. dest[pos++] = 16;
  6139. dest[pos++] = 1;
  6140. //Utils.UInt16ToBytes(0, dest, pos); pos += 2;
  6141. //Utils.UInt16ToBytes(0, dest, pos); pos += 2;
  6142. dest[pos++] = 0;
  6143. dest[pos++] = 0;
  6144. dest[pos++] = 0;
  6145. dest[pos++] = 0;
  6146. dest[pos++] = 100;
  6147. dest[pos++] = 100;
  6148. // rest of pbs is 0 (15), texture entry (2) and texture anim (1)
  6149. const int pbszeros = 15 + 2 + 1;
  6150. Array.Clear(dest, pos, pbszeros); pos += pbszeros;
  6151. //NameValue
  6152. byte[] nv;
  6153. if (data.HideTitle)
  6154. nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
  6155. data.Lastname + "\nTitle STRING RW SV ");
  6156. else
  6157. nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
  6158. data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
  6159. int len = nv.Length;
  6160. dest[pos++] = (byte)len;
  6161. dest[pos++] = (byte)(len >> 8);
  6162. Buffer.BlockCopy(nv, 0, dest, pos, len); pos += len;
  6163. // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1),
  6164. // sound id(16), sound owner(16) gain (4), flags (1), radius (4)
  6165. // jointtype(1) joint pivot(12) joint offset(12)
  6166. const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12;
  6167. Array.Clear(dest, pos, lastzeros); pos += lastzeros;
  6168. }
  6169. protected static void CreateAvatarUpdateBlock(ScenePresence data, LLUDPZeroEncoder zc)
  6170. {
  6171. Quaternion rotation = data.Rotation;
  6172. // tpvs can only see rotations around Z in some cases
  6173. if (!data.Flying && !data.IsSatOnObject)
  6174. {
  6175. rotation.X = 0f;
  6176. rotation.Y = 0f;
  6177. }
  6178. zc.AddUInt(data.LocalId);
  6179. zc.AddByte(0);
  6180. zc.AddUUID(data.UUID);
  6181. zc.AddZeros(4); // crc unused
  6182. zc.AddByte((byte)PCode.Avatar);
  6183. zc.AddByte((byte)Material.Flesh);
  6184. zc.AddByte(0); // clickaction
  6185. zc.AddVector3(data.Appearance.AvatarSize);
  6186. // objectdata block
  6187. zc.AddByte(76); // fixed avatar block size
  6188. zc.AddVector4(data.CollisionPlane);
  6189. zc.AddVector3(data.OffsetPosition);
  6190. zc.AddVector3(data.Velocity);
  6191. //zc.AddVector3(acceleration);
  6192. zc.AddZeros(12);
  6193. zc.AddNormQuat(rotation);
  6194. //zc.AddVector3(angularvelocity);
  6195. zc.AddZeros(12);
  6196. SceneObjectPart parentPart = data.ParentPart;
  6197. if (parentPart != null)
  6198. zc.AddUInt(parentPart.ParentGroup.LocalId);
  6199. else
  6200. zc.AddZeros(4);
  6201. zc.AddZeros(4); //update flags
  6202. //pbs volume data 23
  6203. //texture entry 2
  6204. //texture anim (1)
  6205. const int pbszeros = 23 + 2 + 1;
  6206. zc.AddZeros(pbszeros);
  6207. //NameValue
  6208. byte[] nv;
  6209. if (data.HideTitle)
  6210. nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
  6211. data.Lastname + "\nTitle STRING RW SV ");
  6212. else
  6213. nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
  6214. data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
  6215. int len = nv.Length;
  6216. zc.AddByte((byte)len);
  6217. zc.AddByte((byte)(len >> 8));
  6218. zc.AddBytes(nv, len);
  6219. // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1),
  6220. // sound id(16), sound owner(16) gain (4), flags (1), radius (4)
  6221. // jointtype(1) joint pivot(12) joint offset(12)
  6222. const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12;
  6223. zc.AddZeros(lastzeros);
  6224. }
  6225. protected void CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp, LLUDPZeroEncoder zc)
  6226. {
  6227. // prepare data
  6228. #region PrimFlags
  6229. // prim/update flags
  6230. PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp);
  6231. // Don't send the CreateSelected flag to everyone
  6232. primflags &= ~PrimFlags.CreateSelected;
  6233. if (sp.UUID == part.OwnerID)
  6234. {
  6235. if (part.CreateSelected)
  6236. {
  6237. // Only send this flag once, then unset it
  6238. primflags |= PrimFlags.CreateSelected;
  6239. part.CreateSelected = false;
  6240. }
  6241. }
  6242. #endregion PrimFlags
  6243. // data block
  6244. byte[] data = null;
  6245. byte state = part.Shape.State;
  6246. PCode pcode = (PCode)part.Shape.PCode;
  6247. //vegetation is special so just do it inline
  6248. if(pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree)
  6249. {
  6250. zc.AddUInt(part.LocalId);
  6251. zc.AddByte(state); // state
  6252. zc.AddUUID(part.UUID);
  6253. zc.AddUInt((uint)part.PseudoCRC);
  6254. zc.AddByte((byte)pcode);
  6255. // material 1
  6256. // clickaction 1
  6257. zc.AddZeros(2);
  6258. zc.AddVector3(part.Shape.Scale);
  6259. // objectdata block
  6260. zc.AddByte(60); // fixed object block size
  6261. zc.AddVector3(part.RelativePosition);
  6262. if (pcode == PCode.Grass)
  6263. zc.AddZeros(48);
  6264. else
  6265. {
  6266. zc.AddZeros(24);
  6267. zc.AddNormQuat(part.RotationOffset);
  6268. zc.AddZeros(12);
  6269. }
  6270. zc.AddUInt(part.ParentID);
  6271. zc.AddUInt((uint)primflags); //update flags
  6272. /*
  6273. if (pcode == PCode.Grass)
  6274. {
  6275. //pbs volume data 23
  6276. //texture entry 2
  6277. //texture anim 1
  6278. //name value 2
  6279. // data 1
  6280. // text 5
  6281. // media url 1
  6282. // particle system 1
  6283. // Extraparams 1
  6284. // sound id 16
  6285. // ownwer 16
  6286. // sound gain 4
  6287. // sound flags 1
  6288. // sound radius 4
  6289. // jointtype 1
  6290. // joint pivot 12
  6291. // joint offset 12
  6292. zc.AddZeros(23 + 2 + 1 + 2 + 1 + 5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12);
  6293. return;
  6294. }
  6295. */
  6296. //pbs volume data 23
  6297. //texture entry 2
  6298. //texture anim 1
  6299. //name value 2
  6300. zc.AddZeros(23 + 2 + 1 + 2);
  6301. //data: the tree type
  6302. zc.AddByte(1);
  6303. zc.AddZeros(1);
  6304. zc.AddByte(state);
  6305. // text 5
  6306. // media url 1
  6307. // particle system 1
  6308. // Extraparams 1
  6309. // sound id 16
  6310. // ownwer 16
  6311. // sound gain 4
  6312. // sound flags 1
  6313. // sound radius 4
  6314. // jointtype 1
  6315. // joint pivot 12
  6316. // joint offset 12
  6317. zc.AddZeros(5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12);
  6318. return;
  6319. }
  6320. //NameValue and state
  6321. byte[] nv = null;
  6322. if (part.ParentGroup.IsAttachment)
  6323. {
  6324. if (part.IsRoot)
  6325. {
  6326. if (part.ParentGroup.FromItemID.IsZero())
  6327. nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.UUID.ToString());
  6328. else
  6329. nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID.ToString());
  6330. }
  6331. int st = 0xff & (int)part.ParentGroup.AttachmentPoint;
  6332. state = (byte)((st >> 4) | (st << 4));
  6333. }
  6334. // filter out mesh faces hack
  6335. ushort profileBegin = part.Shape.ProfileBegin;
  6336. ushort profileHollow = part.Shape.ProfileHollow;
  6337. byte profileCurve = part.Shape.ProfileCurve;
  6338. byte pathScaleY = part.Shape.PathScaleY;
  6339. if (part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack
  6340. {
  6341. profileCurve = (byte)(part.Shape.ProfileCurve & 0x0f);
  6342. // fix old values that confused viewers
  6343. if (profileBegin == 1)
  6344. profileBegin = 9375;
  6345. if (profileHollow == 1)
  6346. profileHollow = 27500;
  6347. // fix torus hole size Y that also confuse some viewers
  6348. if (profileCurve == (byte)ProfileShape.Circle && pathScaleY < 150)
  6349. pathScaleY = 150;
  6350. }
  6351. // do encode the things
  6352. zc.AddUInt(part.LocalId);
  6353. zc.AddByte(state); // state
  6354. zc.AddUUID(part.UUID);
  6355. zc.AddUInt((uint)part.PseudoCRC);
  6356. zc.AddByte((byte)pcode);
  6357. zc.AddByte(part.Material);
  6358. zc.AddByte(part.ClickAction); // clickaction
  6359. zc.AddVector3(part.Shape.Scale);
  6360. // objectdata block
  6361. zc.AddByte(60); // fixed object block size
  6362. zc.AddVector3(part.RelativePosition);
  6363. zc.AddVector3(part.Velocity);
  6364. zc.AddVector3(part.Acceleration);
  6365. zc.AddNormQuat(part.RotationOffset);
  6366. zc.AddVector3(part.AngularVelocity);
  6367. zc.AddUInt(part.ParentID);
  6368. zc.AddUInt((uint)primflags); //update flags
  6369. //pbs
  6370. zc.AddByte(part.Shape.PathCurve);
  6371. zc.AddByte(profileCurve);
  6372. zc.AddUInt16(part.Shape.PathBegin);
  6373. zc.AddUInt16(part.Shape.PathEnd);
  6374. zc.AddByte(part.Shape.PathScaleX);
  6375. zc.AddByte(pathScaleY);
  6376. zc.AddByte(part.Shape.PathShearX);
  6377. zc.AddByte(part.Shape.PathShearY);
  6378. zc.AddByte((byte)part.Shape.PathTwist);
  6379. zc.AddByte((byte)part.Shape.PathTwistBegin);
  6380. zc.AddByte((byte)part.Shape.PathRadiusOffset);
  6381. zc.AddByte((byte)part.Shape.PathTaperX);
  6382. zc.AddByte((byte)part.Shape.PathTaperY);
  6383. zc.AddByte(part.Shape.PathRevolutions);
  6384. zc.AddByte((byte)part.Shape.PathSkew);
  6385. zc.AddUInt16(profileBegin);
  6386. zc.AddUInt16(part.Shape.ProfileEnd);
  6387. zc.AddUInt16(profileHollow);
  6388. // texture
  6389. byte[] tentry = part.Shape.TextureEntry;
  6390. if (tentry is null)
  6391. zc.AddZeros(2);
  6392. else
  6393. {
  6394. int len = tentry.Length;
  6395. zc.AddByte((byte)len);
  6396. zc.AddByte((byte)(len >> 8));
  6397. zc.AddBytes(tentry, len);
  6398. }
  6399. // texture animation
  6400. byte[] tanim = part.TextureAnimation;
  6401. if (tanim is null)
  6402. zc.AddZeros(1);
  6403. else
  6404. {
  6405. int len = tanim.Length;
  6406. zc.AddByte((byte)len);
  6407. zc.AddBytes(tanim, len);
  6408. }
  6409. //NameValue
  6410. if(nv is null)
  6411. zc.AddZeros(2);
  6412. else
  6413. {
  6414. int len = nv.Length;
  6415. zc.AddByte((byte)len);
  6416. zc.AddByte((byte)(len >> 8));
  6417. zc.AddBytes(nv, len);
  6418. }
  6419. // data
  6420. if (data is null)
  6421. zc.AddZeros(2);
  6422. else
  6423. {
  6424. int len = data.Length;
  6425. zc.AddByte((byte)len);
  6426. zc.AddByte((byte)(len >> 8));
  6427. zc.AddBytes(data, len);
  6428. }
  6429. //text
  6430. osUTF8 osUTF8PartText = part.osUTF8Text;
  6431. if (osUTF8PartText is null || osUTF8PartText.Length == 0)
  6432. zc.AddZeros(5);
  6433. else
  6434. {
  6435. zc.AddShortLimitedUTF8(osUTF8PartText);
  6436. //textcolor
  6437. byte[] tc = part.GetTextColor().GetBytes(false);
  6438. zc.AddBytes(tc, 4);
  6439. }
  6440. //media url
  6441. zc.AddShortLimitedUTF8(part.osUTFMediaUrl);
  6442. bool hasps = false;
  6443. //particle system
  6444. byte[] ps = part.ParticleSystem;
  6445. if (ps is null || ps.Length < 1)
  6446. zc.AddZeros(1);
  6447. else
  6448. {
  6449. int len = ps.Length;
  6450. zc.AddByte((byte)len);
  6451. zc.AddBytes(ps, len);
  6452. hasps = true;
  6453. }
  6454. //Extraparams
  6455. byte[] ep = part.Shape.ExtraParams;
  6456. if (ep is null || ep.Length < 2)
  6457. zc.AddZeros(1);
  6458. else
  6459. {
  6460. int len = ep.Length;
  6461. zc.AddByte((byte)len);
  6462. zc.AddBytes(ep, len);
  6463. }
  6464. bool hassound = part.Sound.IsNotZero() || part.SoundFlags != 0;
  6465. if (hassound)
  6466. zc.AddUUID(part.Sound);
  6467. else
  6468. zc.AddZeros(16);
  6469. if (hassound || hasps)
  6470. zc.AddUUID(part.OwnerID);
  6471. else
  6472. zc.AddZeros(16);
  6473. if (hassound)
  6474. {
  6475. zc.AddFloat((float)part.SoundGain);
  6476. zc.AddByte(part.SoundFlags);
  6477. zc.AddFloat((float)part.SoundRadius);
  6478. }
  6479. else
  6480. zc.AddZeros(9);
  6481. // jointtype(1) joint pivot(12) joint offset(12)
  6482. const int lastzeros = 1 + 12 + 12;
  6483. zc.AddZeros(lastzeros);
  6484. }
  6485. [Flags]
  6486. private enum CompressedFlags : uint
  6487. {
  6488. None = 0x00,
  6489. /// <summary>Unknown</summary>
  6490. ScratchPad = 0x01,
  6491. /// <summary>Whether the object has a TreeSpecies</summary>
  6492. Tree = 0x02,
  6493. /// <summary>Whether the object has floating text ala llSetText</summary>
  6494. HasText = 0x04,
  6495. /// <summary>Whether the object has an active particle system</summary>
  6496. HasParticlesLegacy = 0x08,
  6497. /// <summary>Whether the object has sound attached to it</summary>
  6498. HasSound = 0x10,
  6499. /// <summary>Whether the object is attached to a root object or not</summary>
  6500. HasParent = 0x20,
  6501. /// <summary>Whether the object has texture animation settings</summary>
  6502. TextureAnimation = 0x40,
  6503. /// <summary>Whether the object has an angular velocity</summary>
  6504. HasAngularVelocity = 0x80,
  6505. /// <summary>Whether the object has a name value pairs string</summary>
  6506. HasNameValues = 0x100,
  6507. /// <summary>Whether the object has a Media URL set</summary>
  6508. MediaURL = 0x200,
  6509. HasParticlesNew = 0x400
  6510. }
  6511. /*
  6512. protected void CreateCompressedUpdateBlock(SceneObjectPart part, ScenePresence sp, byte[] dest, ref int pos)
  6513. {
  6514. // prepare data
  6515. CompressedFlags cflags = CompressedFlags.None;
  6516. // prim/update flags
  6517. PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp);
  6518. // Don't send the CreateSelected flag to everyone
  6519. primflags &= ~PrimFlags.CreateSelected;
  6520. if (sp.UUID == part.OwnerID)
  6521. {
  6522. if (part.CreateSelected)
  6523. {
  6524. // Only send this flag once, then unset it
  6525. primflags |= PrimFlags.CreateSelected;
  6526. part.CreateSelected = false;
  6527. }
  6528. }
  6529. byte state = part.Shape.State;
  6530. PCode pcode = (PCode)part.Shape.PCode;
  6531. bool hastree = false;
  6532. if (pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree)
  6533. {
  6534. cflags |= CompressedFlags.Tree;
  6535. hastree = true;
  6536. }
  6537. //NameValue and state
  6538. byte[] nv = null;
  6539. if (part.ParentGroup.IsAttachment)
  6540. {
  6541. if (part.IsRoot)
  6542. {
  6543. UUID fromID = part.ParentGroup.FromItemID;
  6544. if (fromID == UUID.Zero)
  6545. fromID = part.UUID;
  6546. nv = Util.StringToBytes256("AttachItemID STRING RW SV " + fromID.ToString());
  6547. }
  6548. int st = 0xff & (int)part.ParentGroup.AttachmentPoint;
  6549. state = (byte)((st & >> 4) | (st << 4));
  6550. }
  6551. bool hastext = part.Text != null && part.Text.Length > 0;
  6552. bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0;
  6553. bool hasps = part.ParticleSystem != null && part.ParticleSystem.Length > 1;
  6554. bool hastexanim = part.TextureAnimation != null && part.TextureAnimation.Length > 0;
  6555. bool hasangvel = part.AngularVelocity.LengthSquared() > 1e-8f;
  6556. bool hasmediaurl = part.MediaUrl != null && part.MediaUrl.Length > 1;
  6557. bool haspsnew = false;
  6558. if (hastext)
  6559. cflags |= CompressedFlags.HasText;
  6560. if (hasps)
  6561. {
  6562. if(part.ParticleSystem.Length > 86)
  6563. {
  6564. hasps= false;
  6565. cflags |= CompressedFlags.HasParticlesNew;
  6566. haspsnew = true;
  6567. }
  6568. else
  6569. cflags |= CompressedFlags.HasParticlesLegacy;
  6570. }
  6571. if (hassound)
  6572. cflags |= CompressedFlags.HasSound;
  6573. if (part.ParentID != 0)
  6574. cflags |= CompressedFlags.HasParent;
  6575. if (hastexanim)
  6576. cflags |= CompressedFlags.TextureAnimation;
  6577. if (hasangvel)
  6578. cflags |= CompressedFlags.HasAngularVelocity;
  6579. if (hasmediaurl)
  6580. cflags |= CompressedFlags.MediaURL;
  6581. if (nv != null)
  6582. cflags |= CompressedFlags.HasNameValues;
  6583. // filter out mesh faces hack
  6584. ushort profileBegin = part.Shape.ProfileBegin;
  6585. ushort profileHollow = part.Shape.ProfileHollow;
  6586. byte profileCurve = part.Shape.ProfileCurve;
  6587. byte pathScaleY = part.Shape.PathScaleY;
  6588. if (part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack
  6589. {
  6590. profileCurve = (byte)(part.Shape.ProfileCurve & 0x0f);
  6591. // fix old values that confused viewers
  6592. if (profileBegin == 1)
  6593. profileBegin = 9375;
  6594. if (profileHollow == 1)
  6595. profileHollow = 27500;
  6596. // fix torus hole size Y that also confuse some viewers
  6597. if (profileCurve == (byte)ProfileShape.Circle && pathScaleY < 150)
  6598. pathScaleY = 150;
  6599. }
  6600. // first is primFlags
  6601. Utils.UIntToBytesSafepos((uint)primflags, dest, pos); pos += 4;
  6602. // datablock len to fill later
  6603. int lenpos = pos;
  6604. pos += 2;
  6605. // data block
  6606. part.UUID.ToBytes(dest, pos); pos += 16;
  6607. Utils.UIntToBytesSafepos(part.LocalId, dest, pos); pos += 4;
  6608. dest[pos++] = (byte)pcode;
  6609. dest[pos++] = state;
  6610. Utils.UIntToBytesSafepos((uint)part.ParentGroup.PseudoCRC, dest, pos); pos += 4;
  6611. dest[pos++] = part.Material;
  6612. dest[pos++] = part.ClickAction;
  6613. part.Shape.Scale.ToBytes(dest, pos); pos += 12;
  6614. part.RelativePosition.ToBytes(dest, pos); pos += 12;
  6615. if(pcode == PCode.Grass)
  6616. Vector3.Zero.ToBytes(dest, pos);
  6617. else
  6618. {
  6619. Quaternion rotation = part.RotationOffset;
  6620. rotation.Normalize();
  6621. rotation.ToBytes(dest, pos);
  6622. }
  6623. pos += 12;
  6624. Utils.UIntToBytesSafepos((uint)cflags, dest, pos); pos += 4;
  6625. if (hasps || haspsnew || hassound)
  6626. part.OwnerID.ToBytes(dest, pos);
  6627. else
  6628. UUID.Zero.ToBytes(dest, pos);
  6629. pos += 16;
  6630. if (hasangvel)
  6631. {
  6632. part.AngularVelocity.ToBytes(dest, pos); pos += 12;
  6633. }
  6634. if (part.ParentID != 0)
  6635. {
  6636. Utils.UIntToBytesSafepos(part.ParentID, dest, pos); pos += 4;
  6637. }
  6638. if (hastree)
  6639. dest[pos++] = state;
  6640. if (hastext)
  6641. {
  6642. byte[] text = Util.StringToBytes256(part.Text); // must be null term
  6643. Buffer.BlockCopy(text, 0, dest, pos, text.Length); pos += text.Length;
  6644. byte[] tc = part.GetTextColor().GetBytes(false);
  6645. Buffer.BlockCopy(tc, 0, dest, pos, tc.Length); pos += tc.Length;
  6646. }
  6647. if (hasmediaurl)
  6648. {
  6649. byte[] mu = Util.StringToBytes256(part.MediaUrl); // must be null term
  6650. Buffer.BlockCopy(mu, 0, dest, pos, mu.Length); pos += mu.Length;
  6651. }
  6652. if (hasps)
  6653. {
  6654. byte[] ps = part.ParticleSystem;
  6655. Buffer.BlockCopy(ps, 0, dest, pos, ps.Length); pos += ps.Length;
  6656. }
  6657. byte[] ex = part.Shape.ExtraParams;
  6658. if (ex is null || ex.Length < 2)
  6659. dest[pos++] = 0;
  6660. else
  6661. {
  6662. Buffer.BlockCopy(ex, 0, dest, pos, ex.Length); pos += ex.Length;
  6663. }
  6664. if (hassound)
  6665. {
  6666. part.Sound.ToBytes(dest, pos); pos += 16;
  6667. Utils.FloatToBytesSafepos((float)part.SoundGain, dest, pos); pos += 4;
  6668. dest[pos++] = part.SoundFlags;
  6669. Utils.FloatToBytesSafepos((float)part.SoundRadius, dest, pos); pos += 4;
  6670. }
  6671. if (nv != null)
  6672. {
  6673. Buffer.BlockCopy(nv, 0, dest, pos, nv.Length); pos += nv.Length;
  6674. }
  6675. dest[pos++] = part.Shape.PathCurve;
  6676. Utils.UInt16ToBytes(part.Shape.PathBegin, dest, pos); pos += 2;
  6677. Utils.UInt16ToBytes(part.Shape.PathEnd, dest, pos); pos += 2;
  6678. dest[pos++] = part.Shape.PathScaleX;
  6679. dest[pos++] = pathScaleY;
  6680. dest[pos++] = part.Shape.PathShearX;
  6681. dest[pos++] = part.Shape.PathShearY;
  6682. dest[pos++] = (byte)part.Shape.PathTwist;
  6683. dest[pos++] = (byte)part.Shape.PathTwistBegin;
  6684. dest[pos++] = (byte)part.Shape.PathRadiusOffset;
  6685. dest[pos++] = (byte)part.Shape.PathTaperX;
  6686. dest[pos++] = (byte)part.Shape.PathTaperY;
  6687. dest[pos++] = part.Shape.PathRevolutions;
  6688. dest[pos++] = (byte)part.Shape.PathSkew;
  6689. dest[pos++] = profileCurve;
  6690. Utils.UInt16ToBytes(profileBegin, dest, pos); pos += 2;
  6691. Utils.UInt16ToBytes(part.Shape.ProfileEnd, dest, pos); pos += 2;
  6692. Utils.UInt16ToBytes(profileHollow, dest, pos); pos += 2;
  6693. byte[] te = part.Shape.TextureEntry;
  6694. if (te is null)
  6695. {
  6696. dest[pos++] = 0;
  6697. dest[pos++] = 0;
  6698. dest[pos++] = 0;
  6699. dest[pos++] = 0;
  6700. }
  6701. else
  6702. {
  6703. int len = te.Length & 0x7fff;
  6704. dest[pos++] = (byte)len;
  6705. dest[pos++] = (byte)(len >> 8);
  6706. dest[pos++] = 0;
  6707. dest[pos++] = 0;
  6708. Buffer.BlockCopy(te, 0, dest, pos, len);
  6709. pos += len;
  6710. }
  6711. if (hastexanim)
  6712. {
  6713. byte[] ta = part.TextureAnimation;
  6714. int len = ta.Length & 0x7fff;
  6715. dest[pos++] = (byte)len;
  6716. dest[pos++] = (byte)(len >> 8);
  6717. dest[pos++] = 0;
  6718. dest[pos++] = 0;
  6719. Buffer.BlockCopy(ta, 0, dest, pos, len);
  6720. pos += len;
  6721. }
  6722. if (haspsnew)
  6723. {
  6724. byte[] ps = part.ParticleSystem;
  6725. Buffer.BlockCopy(ps, 0, dest, pos, ps.Length); pos += ps.Length;
  6726. }
  6727. int totlen = pos - lenpos - 2;
  6728. dest[lenpos++] = (byte)totlen;
  6729. dest[lenpos++] = (byte)(totlen >> 8);
  6730. }
  6731. */
  6732. protected void CreateCompressedUpdateBlockZC(SceneObjectPart part, ScenePresence sp, LLUDPZeroEncoder zc)
  6733. {
  6734. // prepare data
  6735. CompressedFlags cflags = CompressedFlags.None;
  6736. // prim/update flags
  6737. PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp);
  6738. // Don't send the CreateSelected flag to everyone
  6739. primflags &= ~PrimFlags.CreateSelected;
  6740. if (sp.UUID.Equals(part.OwnerID))
  6741. {
  6742. if (part.CreateSelected)
  6743. {
  6744. // Only send this flag once, then unset it
  6745. primflags |= PrimFlags.CreateSelected;
  6746. part.CreateSelected = false;
  6747. }
  6748. }
  6749. byte state = part.Shape.State;
  6750. PCode pcode = (PCode)part.Shape.PCode;
  6751. // trees and grass are a lot more compact
  6752. if (pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree)
  6753. {
  6754. // first is primFlags
  6755. zc.AddUInt((uint)primflags);
  6756. // datablock len
  6757. zc.AddByte(113);
  6758. zc.AddZeros(1);
  6759. // data block
  6760. zc.AddUUID(part.UUID);
  6761. zc.AddUInt(part.LocalId);
  6762. zc.AddByte((byte)pcode);
  6763. zc.AddByte(state);
  6764. zc.AddUInt((uint)part.PseudoCRC);
  6765. zc.AddZeros(2); // material and click action
  6766. zc.AddVector3(part.Shape.Scale);
  6767. zc.AddVector3(part.RelativePosition);
  6768. if (pcode == PCode.Grass)
  6769. zc.AddZeros(12);
  6770. else
  6771. zc.AddNormQuat(part.RotationOffset);
  6772. zc.AddUInt((uint)CompressedFlags.Tree); // cflags
  6773. zc.AddZeros(16); // owner id
  6774. zc.AddByte(state); // tree parameter
  6775. zc.AddZeros(28); //extraparameters 1, pbs 23, texture 4
  6776. return;
  6777. }
  6778. //NameValue and state
  6779. byte[] nv = null;
  6780. if (part.ParentGroup.IsAttachment)
  6781. {
  6782. if (part.IsRoot)
  6783. {
  6784. if (part.ParentGroup.FromItemID.IsZero())
  6785. nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.UUID.ToString());
  6786. else
  6787. nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID.ToString());
  6788. }
  6789. int st = 0xff & (int)part.ParentGroup.AttachmentPoint;
  6790. state = (byte)((st >> 4) | (st << 4));
  6791. }
  6792. bool hastext = false;
  6793. bool hassound = false;
  6794. bool hasps = false;
  6795. bool hastexanim = false;
  6796. bool hasangvel = false;
  6797. bool hasmediaurl = false;
  6798. bool haspsnew = false;
  6799. int BlockLengh = 111;
  6800. byte[] extraParamBytes = part.Shape.ExtraParams;
  6801. if (extraParamBytes is null || extraParamBytes.Length < 2)
  6802. {
  6803. ++BlockLengh;
  6804. extraParamBytes = null;
  6805. }
  6806. else
  6807. BlockLengh += extraParamBytes.Length;
  6808. byte[] hoverTextColor = null;
  6809. osUTF8 osUTF8PartText = part.osUTF8Text;
  6810. if (osUTF8PartText != null && osUTF8PartText.Length > 0)
  6811. {
  6812. cflags |= CompressedFlags.HasText;
  6813. BlockLengh += osUTF8PartText.Length;
  6814. if (osUTF8PartText[^1] != 0)
  6815. ++BlockLengh;
  6816. hoverTextColor = part.GetTextColor().GetBytes(false);
  6817. BlockLengh += hoverTextColor.Length;
  6818. hastext = true;
  6819. }
  6820. if (part.ParticleSystem != null && part.ParticleSystem.Length > 1)
  6821. {
  6822. BlockLengh += part.ParticleSystem.Length;
  6823. if (part.ParticleSystem.Length > 86)
  6824. {
  6825. hasps = false;
  6826. cflags |= CompressedFlags.HasParticlesNew;
  6827. haspsnew = true;
  6828. }
  6829. else
  6830. {
  6831. cflags |= CompressedFlags.HasParticlesLegacy;
  6832. hasps = true;
  6833. }
  6834. }
  6835. if (part.Sound.IsNotZero() || part.SoundFlags != 0)
  6836. {
  6837. BlockLengh += 25;
  6838. cflags |= CompressedFlags.HasSound;
  6839. hassound = true;
  6840. }
  6841. if (part.ParentID != 0)
  6842. {
  6843. BlockLengh += 4;
  6844. cflags |= CompressedFlags.HasParent;
  6845. }
  6846. if (part.TextureAnimation != null && part.TextureAnimation.Length > 0)
  6847. {
  6848. BlockLengh += part.TextureAnimation.Length + 4;
  6849. cflags |= CompressedFlags.TextureAnimation;
  6850. hastexanim = true;
  6851. }
  6852. if (part.AngularVelocity.LengthSquared() > 1e-8f)
  6853. {
  6854. BlockLengh += 12;
  6855. cflags |= CompressedFlags.HasAngularVelocity;
  6856. hasangvel = true;
  6857. }
  6858. osUTF8 osUTFMediaUrl = part.osUTFMediaUrl;
  6859. if (osUTFMediaUrl != null && osUTFMediaUrl.Length > 0)
  6860. {
  6861. BlockLengh += osUTFMediaUrl.Length;
  6862. if (osUTFMediaUrl[^1] != 0)
  6863. ++BlockLengh;
  6864. cflags |= CompressedFlags.MediaURL;
  6865. hasmediaurl = true;
  6866. }
  6867. if (nv != null)
  6868. {
  6869. BlockLengh += nv.Length;
  6870. cflags |= CompressedFlags.HasNameValues;
  6871. }
  6872. byte[] textureEntry = part.Shape.TextureEntry;
  6873. if(textureEntry != null)
  6874. BlockLengh += textureEntry.Length;
  6875. // filter out mesh faces hack
  6876. ushort profileBegin = part.Shape.ProfileBegin;
  6877. ushort profileHollow = part.Shape.ProfileHollow;
  6878. byte profileCurve = part.Shape.ProfileCurve;
  6879. byte pathScaleY = part.Shape.PathScaleY;
  6880. if (part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack
  6881. {
  6882. profileCurve = (byte)(part.Shape.ProfileCurve & 0x0f);
  6883. // fix old values that confused viewers
  6884. if (profileBegin == 1)
  6885. profileBegin = 9375;
  6886. if (profileHollow == 1)
  6887. profileHollow = 27500;
  6888. // fix torus hole size Y that also confuse some viewers
  6889. if (profileCurve == (byte)ProfileShape.Circle && pathScaleY < 150)
  6890. pathScaleY = 150;
  6891. }
  6892. // first is primFlags
  6893. zc.AddUInt((uint)primflags);
  6894. // datablock len
  6895. zc.AddByte((byte)BlockLengh);
  6896. zc.AddByte((byte)(BlockLengh >> 8));
  6897. // data block
  6898. zc.AddUUID(part.UUID);
  6899. zc.AddUInt(part.LocalId);
  6900. zc.AddByte((byte)pcode);
  6901. zc.AddByte(state);
  6902. zc.AddUInt((uint)part.PseudoCRC);
  6903. zc.AddByte(part.Material);
  6904. zc.AddByte(part.ClickAction);
  6905. zc.AddVector3(part.Shape.Scale);
  6906. zc.AddVector3(part.RelativePosition);
  6907. zc.AddNormQuat(part.RotationOffset);
  6908. zc.AddUInt((uint)cflags);
  6909. if (hasps || haspsnew || hassound)
  6910. zc.AddUUID(part.OwnerID);
  6911. else
  6912. zc.AddZeros(16);
  6913. if (hasangvel)
  6914. {
  6915. zc.AddVector3(part.AngularVelocity);
  6916. }
  6917. if (part.ParentID != 0)
  6918. {
  6919. zc.AddUInt(part.ParentID);
  6920. }
  6921. if (hastext)
  6922. {
  6923. zc.AddBytes(osUTF8PartText.GetArray(), osUTF8PartText.Length);
  6924. if (osUTF8PartText[^1] != 0)
  6925. zc.AddZeros(1);
  6926. zc.AddBytes(hoverTextColor, hoverTextColor.Length);
  6927. }
  6928. if (hasmediaurl)
  6929. {
  6930. zc.AddBytes(osUTFMediaUrl.GetArray(), osUTFMediaUrl.Length);
  6931. if (osUTFMediaUrl[^1] != 0)
  6932. zc.AddZeros(1);
  6933. }
  6934. if (hasps)
  6935. {
  6936. byte[] ps = part.ParticleSystem;
  6937. zc.AddBytes(ps, ps.Length);
  6938. }
  6939. if (extraParamBytes is null)
  6940. zc.AddZeros(1);
  6941. else
  6942. {
  6943. zc.AddBytes(extraParamBytes, extraParamBytes.Length);
  6944. }
  6945. if (hassound)
  6946. {
  6947. zc.AddUUID(part.Sound);
  6948. zc.AddFloat((float)part.SoundGain);
  6949. zc.AddByte(part.SoundFlags);
  6950. zc.AddFloat((float)part.SoundRadius);
  6951. }
  6952. if (nv != null)
  6953. {
  6954. zc.AddBytes(nv, nv.Length);
  6955. }
  6956. zc.AddByte(part.Shape.PathCurve);
  6957. zc.AddUInt16(part.Shape.PathBegin);
  6958. zc.AddUInt16(part.Shape.PathEnd);
  6959. zc.AddByte(part.Shape.PathScaleX);
  6960. zc.AddByte(pathScaleY);
  6961. zc.AddByte(part.Shape.PathShearX);
  6962. zc.AddByte(part.Shape.PathShearY);
  6963. zc.AddByte((byte)part.Shape.PathTwist);
  6964. zc.AddByte((byte)part.Shape.PathTwistBegin);
  6965. zc.AddByte((byte)part.Shape.PathRadiusOffset);
  6966. zc.AddByte((byte)part.Shape.PathTaperX);
  6967. zc.AddByte((byte)part.Shape.PathTaperY);
  6968. zc.AddByte(part.Shape.PathRevolutions);
  6969. zc.AddByte((byte)part.Shape.PathSkew);
  6970. zc.AddByte(profileCurve);
  6971. zc.AddUInt16(profileBegin);
  6972. zc.AddUInt16(part.Shape.ProfileEnd);
  6973. zc.AddUInt16(profileHollow);
  6974. if (textureEntry is null)
  6975. {
  6976. zc.AddZeros(4);
  6977. }
  6978. else
  6979. {
  6980. int len = textureEntry.Length;
  6981. zc.AddByte((byte)len);
  6982. zc.AddByte((byte)(len >> 8));
  6983. zc.AddZeros(2);
  6984. zc.AddBytes(textureEntry, len);
  6985. }
  6986. if (hastexanim)
  6987. {
  6988. byte[] ta = part.TextureAnimation;
  6989. int len = ta.Length;
  6990. zc.AddByte((byte)len);
  6991. zc.AddByte((byte)(len >> 8));
  6992. zc.AddZeros(2);
  6993. zc.AddBytes(ta, len);
  6994. }
  6995. if (haspsnew)
  6996. {
  6997. byte[] ps = part.ParticleSystem;
  6998. zc.AddBytes(ps, ps.Length);
  6999. }
  7000. }
  7001. public void SendNameReply(UUID profileId, string firstname, string lastname)
  7002. {
  7003. UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply);
  7004. // TODO: don't create new blocks if recycling an old packet
  7005. packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1];
  7006. packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock
  7007. {
  7008. ID = profileId,
  7009. FirstName = Util.StringToBytes256(firstname),
  7010. LastName = Util.StringToBytes256(lastname)
  7011. };
  7012. OutPacket(packet, ThrottleOutPacketType.Task);
  7013. }
  7014. public Dictionary<UUID, ulong> GetGroupPowers()
  7015. {
  7016. lock(m_groupPowers)
  7017. {
  7018. return new Dictionary<UUID, ulong>(m_groupPowers);
  7019. }
  7020. }
  7021. public void SetGroupPowers(Dictionary<UUID, ulong> powers)
  7022. {
  7023. lock(m_groupPowers)
  7024. {
  7025. m_groupPowers.Clear();
  7026. m_groupPowers = powers;
  7027. }
  7028. }
  7029. public ulong GetGroupPowers(UUID groupID)
  7030. {
  7031. lock(m_groupPowers)
  7032. {
  7033. if (m_groupPowers.ContainsKey(groupID))
  7034. return m_groupPowers[groupID];
  7035. }
  7036. return 0;
  7037. }
  7038. #endregion
  7039. private static readonly FrozenDictionary<PacketType, StaticPacketProcessor> m_staticHandlers = new SortedDictionary<PacketType, StaticPacketProcessor>()
  7040. //private static readonly Dictionary<PacketType, StaticPacketProcessor> m_staticHandlers = new()
  7041. {
  7042. { PacketType.AgentUpdate, new(HandleAgentUpdate, false) },
  7043. { PacketType.ViewerEffect, new(HandleViewerEffect , false) },
  7044. { PacketType.VelocityInterpolateOn, new(HandleVelocityInterpolateOn, false) },
  7045. { PacketType.VelocityInterpolateOff, new(HandleVelocityInterpolateOff, false) },
  7046. { PacketType.AgentCachedTexture, new(HandleAgentTextureCached, false) },
  7047. { PacketType.MultipleObjectUpdate, new(HandleMultipleObjUpdate, false) },
  7048. { PacketType.MoneyTransferRequest, new(HandleMoneyTransferRequest, false) },
  7049. { PacketType.ParcelBuy, new(HandleParcelBuyRequest, false) },
  7050. { PacketType.RegionHandshakeReply, new(HandlerRegionHandshakeReply, false) },
  7051. { PacketType.SetAlwaysRun, new(HandleSetAlwaysRun, false) },
  7052. { PacketType.AgentAnimation, new(HandleAgentAnimation, false) },
  7053. { PacketType.AgentThrottle, new(HandleAgentThrottle, false) },
  7054. { PacketType.AgentPause, new(HandleAgentPause, false) },
  7055. { PacketType.AgentResume, new(HandleAgentResume, false) },
  7056. { PacketType.ObjectImage, new(HandleObjectImage, false) },
  7057. { PacketType.ObjectGrab, new(HandleObjectGrab, false) },
  7058. { PacketType.ObjectGrabUpdate, new(HandleObjectGrabUpdate, false) },
  7059. { PacketType.ObjectSpinStart, new(HandleObjectSpinStart, false) },
  7060. { PacketType.ObjectSpinUpdate, new(HandleObjectSpinUpdate, false) },
  7061. { PacketType.ObjectSpinStop, new(HandleObjectSpinStop, false) },
  7062. { PacketType.ObjectDescription, new(HandleObjectDescription, false) },
  7063. { PacketType.ObjectName, new(HandleObjectName, false) },
  7064. { PacketType.ObjectPermissions, new(HandleObjectPermissions, false) },
  7065. { PacketType.Undo, new(HandleUndo, false) },
  7066. { PacketType.UndoLand, new(HandleLandUndo, false) },
  7067. { PacketType.Redo, new(HandleRedo, false) },
  7068. { PacketType.RequestObjectPropertiesFamily, new(HandleRequestObjectPropertiesFamily, false) },
  7069. { PacketType.ScriptAnswerYes, new(HandleScriptAnswerYes, false) },
  7070. { PacketType.ObjectClickAction, new(HandleObjectClickAction, false) },
  7071. { PacketType.ObjectMaterial, new(HandleObjectMaterial, false) },
  7072. { PacketType.RequestImage, new(HandleRequestImage, false) },
  7073. { PacketType.TransferRequest, new(HandleTransferRequest, false) },
  7074. { PacketType.ConfirmXferPacket, new(HandleConfirmXferPacket, false) },
  7075. { PacketType.UUIDNameRequest, new(HandleUUIDNameRequest, false) },
  7076. { PacketType.RegionHandleRequest, new(HandleRegionHandleRequest, false) },
  7077. { PacketType.ParcelAccessListRequest, new(HandleParcelAccessListRequest, false) },
  7078. { PacketType.ParcelAccessListUpdate, new(HandleParcelAccessListUpdate, false) },
  7079. { PacketType.ParcelPropertiesRequest, new(HandleParcelPropertiesRequest, false) },
  7080. { PacketType.RequestRegionInfo, new(HandleRequestRegionInfo, false) },
  7081. { PacketType.AgentFOV, new(HandleAgentFOV, false) },
  7082. { PacketType.MapItemRequest, new(HandleMapItemRequest, false) },
  7083. { PacketType.TransferAbort, new(HandleTransferAbort, false) },
  7084. { PacketType.AgentHeightWidth, new(HandleAgentHeightWidth, false) },
  7085. { PacketType.LogoutRequest, new(HandleLogout, true) },
  7086. { PacketType.UUIDGroupNameRequest, new(HandleUUIDGroupNameRequest, true) },
  7087. { PacketType.ObjectGroup, new(HandleObjectGroupRequest, true) },
  7088. { PacketType.GenericMessage, new(HandleGenericMessage, true) },
  7089. { PacketType.MuteListRequest, new(HandleMuteListRequest, false) },
  7090. { PacketType.UpdateMuteListEntry, new(HandleUpdateMuteListEntry, true) },
  7091. { PacketType.RemoveMuteListEntry, new(HandleRemoveMuteListEntry, true) },
  7092. { PacketType.AvatarPropertiesRequest, new(HandleAvatarPropertiesRequest, true) },
  7093. { PacketType.ChatFromViewer, new(HandleChatFromViewer, true) },
  7094. { PacketType.AvatarPropertiesUpdate, new(HandlerAvatarPropertiesUpdate, true) },
  7095. { PacketType.ScriptDialogReply, new(HandlerScriptDialogReply, true) },
  7096. { PacketType.ImprovedInstantMessage, new(HandlerImprovedInstantMessage, true) },
  7097. { PacketType.AcceptFriendship, new(HandlerAcceptFriendship, true) },
  7098. { PacketType.DeclineFriendship, new(HandlerDeclineFriendship, true) },
  7099. { PacketType.TerminateFriendship, new(HandlerTerminateFriendship, true) },
  7100. { PacketType.RezObject, new(HandlerRezObject, true) },
  7101. { PacketType.DeRezObject, new(HandlerDeRezObject, true) },
  7102. { PacketType.RezRestoreToWorld, new(HandlerRezRestoreToWorld, true) },
  7103. { PacketType.ModifyLand, new(HandlerModifyLand, true) },
  7104. { PacketType.AgentWearablesRequest, new(HandlerAgentWearablesRequest, true) },
  7105. { PacketType.AgentSetAppearance, new(HandlerAgentSetAppearance, true) },
  7106. { PacketType.AgentIsNowWearing, new(HandlerAgentIsNowWearing, true) },
  7107. { PacketType.RezSingleAttachmentFromInv, new(HandlerRezSingleAttachmentFromInv, true) },
  7108. { PacketType.RezMultipleAttachmentsFromInv, new(HandleRezMultipleAttachmentsFromInv, true) },
  7109. { PacketType.DetachAttachmentIntoInv, new(HandleDetachAttachmentIntoInv, true) },
  7110. { PacketType.ObjectAttach, new(HandleObjectAttach, true) },
  7111. { PacketType.ObjectDetach, new(HandleObjectDetach, true) },
  7112. { PacketType.ObjectDrop, new(HandleObjectDrop, true) },
  7113. { PacketType.CompleteAgentMovement, new(HandleCompleteAgentMovement, true) },
  7114. { PacketType.AgentRequestSit, new(HandleAgentRequestSit, true) },
  7115. { PacketType.AgentSit, new(HandleAgentSit, true) },
  7116. { PacketType.SoundTrigger, new(HandleSoundTrigger, true) },
  7117. { PacketType.AvatarPickerRequest, new(HandleAvatarPickerRequest, true) },
  7118. { PacketType.AgentDataUpdateRequest, new(HandleAgentDataUpdateRequest, true) },
  7119. { PacketType.UserInfoRequest, new(HandleUserInfoRequest, true) },
  7120. { PacketType.UpdateUserInfo, new(HandleUpdateUserInfo, true) },
  7121. { PacketType.SetStartLocationRequest, new(HandleSetStartLocationRequest, true) },
  7122. { PacketType.ForceScriptControlRelease, new(HandleForceScriptControlRelease, true) },
  7123. { PacketType.ObjectLink, new(HandleObjectLink, true) },
  7124. { PacketType.ObjectDelink, new(HandleObjectDelink, true) },
  7125. { PacketType.ObjectAdd, new(HandleObjectAdd, true) },
  7126. { PacketType.ObjectShape, new(HandleObjectShape, true) },
  7127. { PacketType.ObjectExtraParams, new(HandleObjectExtraParams, true) },
  7128. { PacketType.ObjectDuplicate, new(HandleObjectDuplicate, true) },
  7129. { PacketType.RequestMultipleObjects, new(HandleRequestMultipleObjects, true) },
  7130. { PacketType.ObjectSelect, new(HandleObjectSelect, true) },
  7131. { PacketType.ObjectDeselect, new(HandleObjectDeselect, true) },
  7132. { PacketType.ObjectPosition, new(HandleObjectPosition, true) },
  7133. { PacketType.ObjectScale, new(HandleObjectScale, true) },
  7134. { PacketType.ObjectRotation, new(HandleObjectRotation, true) },
  7135. { PacketType.ObjectFlagUpdate, new(HandleObjectFlagUpdate, true) },
  7136. { PacketType.ObjectDeGrab, new(HandleObjectDeGrab, true) },
  7137. { PacketType.ObjectDuplicateOnRay, new(HandleObjectDuplicateOnRay, true) },
  7138. { PacketType.ObjectIncludeInSearch, new(HandleObjectIncludeInSearch, true) },
  7139. { PacketType.AssetUploadRequest, new(HandleAssetUploadRequest, true) },
  7140. { PacketType.RequestXfer, new(HandleRequestXfer, true) },
  7141. { PacketType.SendXferPacket, new(HandleSendXferPacket, true) },
  7142. { PacketType.AbortXfer, new(HandleAbortXfer, true) },
  7143. { PacketType.CreateInventoryFolder, new (HandleCreateInventoryFolder, true) },
  7144. { PacketType.UpdateInventoryFolder, new(HandleUpdateInventoryFolder, true) },
  7145. { PacketType.MoveInventoryFolder, new(HandleMoveInventoryFolder, true) },
  7146. { PacketType.CreateInventoryItem, new(HandleCreateInventoryItem, true) },
  7147. { PacketType.LinkInventoryItem, new(HandleLinkInventoryItem, true) },
  7148. { PacketType.FetchInventory, new(HandleFetchInventory, true) },
  7149. { PacketType.FetchInventoryDescendents, new(HandleFetchInventoryDescendents, true) },
  7150. { PacketType.InventoryDescendents, new (HandleInventoryDescendents, true) },
  7151. { PacketType.PurgeInventoryDescendents, new(HandlePurgeInventoryDescendents, true) },
  7152. { PacketType.UpdateInventoryItem, new(HandleUpdateInventoryItem, true) },
  7153. { PacketType.CopyInventoryItem, new(HandleCopyInventoryItem, true) },
  7154. { PacketType.MoveInventoryItem, new(HandleMoveInventoryItem, true) },
  7155. { PacketType.RemoveInventoryItem, new(HandleRemoveInventoryItem, true) },
  7156. { PacketType.RemoveInventoryFolder, new(HandleRemoveInventoryFolder, true) },
  7157. { PacketType.RemoveInventoryObjects, new(HandleRemoveInventoryObjects, true) },
  7158. { PacketType.RequestTaskInventory, new(HandleRequestTaskInventory, true) },
  7159. { PacketType.UpdateTaskInventory, new(HandleUpdateTaskInventory, true) },
  7160. { PacketType.RemoveTaskInventory, new(HandleRemoveTaskInventory, true) },
  7161. { PacketType.MoveTaskInventory, new(HandleMoveTaskInventory, true) },
  7162. { PacketType.RezScript, new(HandleRezScript, true) },
  7163. { PacketType.MapLayerRequest, new(HandleMapLayerRequest, true) },
  7164. { PacketType.MapBlockRequest, new(HandleMapBlockRequest, true) },
  7165. { PacketType.MapNameRequest, new(HandleMapNameRequest, true) },
  7166. { PacketType.TeleportLandmarkRequest, new(HandleTeleportLandmarkRequest, true) },
  7167. { PacketType.TeleportCancel, new(HandleTeleportCancel, true) },
  7168. { PacketType.TeleportLocationRequest, new(HandleTeleportLocationRequest, true) },
  7169. { PacketType.ParcelInfoRequest, new (HandleParcelInfoRequest, true) },
  7170. { PacketType.ParcelDivide, new(HandleParcelDivide, true) },
  7171. { PacketType.ParcelJoin, new(HandleParcelJoin, true) },
  7172. { PacketType.ParcelPropertiesUpdate, new(HandleParcelPropertiesUpdate, true) },
  7173. { PacketType.ParcelSelectObjects, new(HandleParcelSelectObjects, true) },
  7174. { PacketType.ParcelObjectOwnersRequest, new(HandleParcelObjectOwnersRequest, true) },
  7175. { PacketType.ParcelGodForceOwner, new(HandleParcelGodForceOwner, true) },
  7176. { PacketType.ParcelRelease, new(HandleParcelRelease, true) },
  7177. { PacketType.ParcelReclaim, new(HandleParcelReclaim, true) },
  7178. { PacketType.ParcelReturnObjects, new(HandleParcelReturnObjects, true) },
  7179. { PacketType.ParcelSetOtherCleanTime, new(HandleParcelSetOtherCleanTime, true) },
  7180. { PacketType.ParcelDeedToGroup, new (HandleParcelDeedToGroup, true) },
  7181. { PacketType.LandStatRequest, new(HandleLandStatRequest, true) },
  7182. { PacketType.ParcelDwellRequest, new(HandleParcelDwellRequest, true) },
  7183. { PacketType.EstateOwnerMessage, new(HandleEstateOwnerMessage, true) },
  7184. { PacketType.EstateCovenantRequest, new(HandleEstateCovenantRequest, true) },
  7185. { PacketType.RequestGodlikePowers, new(HandleRequestGodlikePowers, true) },
  7186. { PacketType.GodKickUser, new(HandleGodKickUser, true) },
  7187. { PacketType.MoneyBalanceRequest, new(HandleMoneyBalanceRequest, true) },
  7188. { PacketType.EconomyDataRequest, new(HandleEconomyDataRequest, true) },
  7189. { PacketType.RequestPayPrice, new(HandleRequestPayPrice, true) },
  7190. { PacketType.ObjectSaleInfo, new(HandleObjectSaleInfo, true) },
  7191. { PacketType.ObjectBuy, new(HandleObjectBuy, true) },
  7192. { PacketType.GetScriptRunning, new(HandleGetScriptRunning, true) },
  7193. { PacketType.SetScriptRunning, new(HandleSetScriptRunning, true) },
  7194. { PacketType.ScriptReset, new(HandleScriptReset, true) },
  7195. { PacketType.ActivateGestures, new(HandleActivateGestures, true) },
  7196. { PacketType.DeactivateGestures, new(HandleDeactivateGestures, true) },
  7197. { PacketType.ObjectOwner, new(HandleObjectOwner, true) },
  7198. { PacketType.ViewerStats, new(HandleViewerStats, true) },
  7199. { PacketType.UseCircuitCode, new(HandleUseCircuitCode, true) },
  7200. { PacketType.CreateNewOutfitAttachments, new(HandleCreateNewOutfitAttachments, true) },
  7201. { PacketType.DirFindQuery, new(HandleDirFindQuery, true) },
  7202. { PacketType.DirPlacesQuery, new(HandleDirPlacesQuery, true) },
  7203. { PacketType.DirClassifiedQuery, new(HandleDirClassifiedQuery, true) },
  7204. { PacketType.DirLandQuery, new(HandleDirLandQuery, true) },
  7205. { PacketType.DirPopularQuery, new(HandleDirPopularQuery, true) },
  7206. { PacketType.EventInfoRequest, new(HandleEventInfoRequest, true) },
  7207. { PacketType.OfferCallingCard, new(HandleOfferCallingCard, true) },
  7208. { PacketType.AcceptCallingCard, new(HandleAcceptCallingCard, true) },
  7209. { PacketType.DeclineCallingCard, new(HandleDeclineCallingCard, true) },
  7210. { PacketType.ActivateGroup, new(HandleActivateGroup, true) },
  7211. { PacketType.GroupTitlesRequest, new(HandleGroupTitlesRequest, true) },
  7212. { PacketType.GroupProfileRequest, new(HandleGroupProfileRequest, true) },
  7213. { PacketType.GroupMembersRequest, new(HandleGroupMembersRequest, true) },
  7214. { PacketType.GroupRoleDataRequest, new(HandleGroupRoleDataRequest, true) },
  7215. { PacketType.GroupRoleMembersRequest, new(HandleGroupRoleMembersRequest, true) },
  7216. { PacketType.CreateGroupRequest, new(HandleCreateGroupRequest, true) },
  7217. { PacketType.UpdateGroupInfo, new(HandleUpdateGroupInfo, true) },
  7218. { PacketType.SetGroupAcceptNotices, new(HandleSetGroupAcceptNotices, true) },
  7219. { PacketType.GroupTitleUpdate, new(HandleGroupTitleUpdate, true) },
  7220. { PacketType.GroupNoticesListRequest, new(HandleGroupNoticesListRequest, true) },
  7221. { PacketType.GroupNoticeRequest, new(HandleGroupNoticeRequest, true) },
  7222. { PacketType.GroupRoleUpdate, new(HandleGroupRoleUpdate, true) },
  7223. { PacketType.GroupRoleChanges, new(HandleGroupRoleChanges, true) },
  7224. { PacketType.JoinGroupRequest, new(HandleJoinGroupRequest, true) },
  7225. { PacketType.LeaveGroupRequest, new(HandleLeaveGroupRequest, true) },
  7226. { PacketType.EjectGroupMemberRequest, new(HandleEjectGroupMemberRequest, true) },
  7227. { PacketType.InviteGroupRequest, new(HandleInviteGroupRequest, true) },
  7228. { PacketType.GroupAccountDetailsRequest, new(HandleGroupAccountDetailsRequest, true) },
  7229. { PacketType.GroupAccountSummaryRequest, new(HandleGroupAccountSummaryRequest, true) },
  7230. { PacketType.GroupAccountTransactionsRequest, new(HandleGroupTransactionsDetailsRequest, true) },
  7231. { PacketType.GroupActiveProposalsRequest, new(HandleGroupActiveProposalsRequest, true) },
  7232. { PacketType.GroupVoteHistoryRequest, new(HandleGroupVoteHistoryRequest, true) },
  7233. { PacketType.StartLure, new(HandleStartLure, true) },
  7234. { PacketType.TeleportLureRequest, new(HandleTeleportLureRequest, true) },
  7235. { PacketType.ClassifiedInfoRequest, new(HandleClassifiedInfoRequest, true) },
  7236. { PacketType.ClassifiedInfoUpdate, new(HandleClassifiedInfoUpdate, true) },
  7237. { PacketType.ClassifiedDelete, new(HandleClassifiedDelete, true) },
  7238. { PacketType.ClassifiedGodDelete, new(HandleClassifiedGodDelete, true) },
  7239. { PacketType.EventGodDelete, new(HandleEventGodDelete, true) },
  7240. { PacketType.EventNotificationAddRequest, new(HandleEventNotificationAddRequest, true) },
  7241. { PacketType.EventNotificationRemoveRequest, new(HandleEventNotificationRemoveRequest, true) },
  7242. { PacketType.RetrieveInstantMessages, new(HandleRetrieveInstantMessages, true) },
  7243. { PacketType.PickDelete, new(HandlePickDelete, true) },
  7244. { PacketType.PickGodDelete, new(HandlePickGodDelete, true) },
  7245. { PacketType.PickInfoUpdate, new(HandlePickInfoUpdate, true) },
  7246. { PacketType.AvatarNotesUpdate, new(HandleAvatarNotesUpdate, true) },
  7247. { PacketType.AvatarInterestsUpdate, new(HandleAvatarInterestsUpdate, true) },
  7248. { PacketType.GrantUserRights, new(HandleGrantUserRights, true) },
  7249. { PacketType.PlacesQuery, new(HandlePlacesQuery, true) },
  7250. { PacketType.UserReport, new(HandleUserReport, true) },
  7251. { PacketType.FindAgent, new(HandleFindAgent, true) },
  7252. { PacketType.TrackAgent, new(HandleTrackAgent, true) },
  7253. { PacketType.GodUpdateRegionInfo, new(HandleGodUpdateRegionInfoUpdate, true) },
  7254. { PacketType.GodlikeMessage, new(HandleGodlikeMessage, true) },
  7255. { PacketType.StateSave, new(HandleSaveStatePacket, true) },
  7256. { PacketType.RevokePermissions, new(HandleRevokePermissions, true) },
  7257. { PacketType.FreezeUser, new(HandleFreezeUser, true) },
  7258. { PacketType.EjectUser, new(HandleEjectUser, true) },
  7259. { PacketType.ParcelBuyPass, new(HandleParcelBuyPass, true) },
  7260. { PacketType.ParcelGodMarkAsContent, new(HandleParcelGodMarkAsContent, true) },
  7261. { PacketType.SimWideDeletes, new(HandleSimWideDeletes, true) },
  7262. { PacketType.SendPostcard, new(HandleSendPostcard, true) },
  7263. { PacketType.ChangeInventoryItemFlags, new(HandleChangeInventoryItemFlags, true) },
  7264. }.ToFrozenDictionary();
  7265. //};
  7266. protected virtual void RegisterLocalPacketHandlers()
  7267. {
  7268. AddGenericPacketHandler("autopilot", HandleAutopilot);
  7269. }
  7270. #region Packet Handlers
  7271. public int TotalAgentUpdates { get; set; }
  7272. #region Scene/Avatar
  7273. // Threshold for body rotation to be a significant agent update
  7274. // use the abs of cos
  7275. private const float QDELTABody = 1.0f - 0.00001f;
  7276. private const float QDELTAHead = 1.0f - 0.00001f;
  7277. // Threshold for camera rotation to be a significant agent update
  7278. private const float VDELTA = 0.01f;
  7279. /// <summary>
  7280. /// This checks the movement/state update significance against the last update made.
  7281. /// </summary>
  7282. /// <remarks>Can only be called by one thread at a time</remarks>
  7283. /// <returns></returns>
  7284. /// <param name='x'></param>
  7285. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  7286. private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x, double now)
  7287. {
  7288. if((x.ControlFlags & ~(uint)AgentManager.ControlFlags.AGENT_CONTROL_FINISH_ANIM) != (uint)AgentManager.ControlFlags.NONE &&
  7289. now > m_thisAgentUpdateArgs.lastMoveUpdateTS + 20)
  7290. return true;
  7291. if (
  7292. (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed
  7293. || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed
  7294. || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed
  7295. || (MathF.Abs(x.Far - m_thisAgentUpdateArgs.Far) >= 32f) // significant if far distance changed
  7296. )
  7297. return true;
  7298. float qdelta = MathF.Abs(x.BodyRotation.Dot(m_thisAgentUpdateArgs.BodyRotation));
  7299. return qdelta < QDELTABody; // significant if body rotation above(below cos) threshold
  7300. }
  7301. /// <summary>
  7302. /// This checks the camera update significance against the last update made.
  7303. /// </summary>
  7304. /// <remarks>Can only be called by one thread at a time</remarks>
  7305. /// <returns></returns>
  7306. /// <param name='x'></param>
  7307. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  7308. private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
  7309. {
  7310. return (MathF.Abs(x.CameraCenter.X - m_thisAgentUpdateArgs.CameraCenter.X) > VDELTA ||
  7311. MathF.Abs(x.CameraCenter.Y - m_thisAgentUpdateArgs.CameraCenter.Y) > VDELTA ||
  7312. MathF.Abs(x.CameraCenter.Z - m_thisAgentUpdateArgs.CameraCenter.Z) > VDELTA ||
  7313. MathF.Abs(x.CameraAtAxis.X - m_thisAgentUpdateArgs.CameraAtAxis.X) > VDELTA ||
  7314. MathF.Abs(x.CameraAtAxis.Y - m_thisAgentUpdateArgs.CameraAtAxis.Y) > VDELTA ||
  7315. MathF.Abs(x.CameraUpAxis.X - m_thisAgentUpdateArgs.CameraUpAxis.X) > VDELTA ||
  7316. MathF.Abs(x.CameraUpAxis.Y - m_thisAgentUpdateArgs.CameraUpAxis.Y) > VDELTA
  7317. );
  7318. }
  7319. private static void HandleAgentUpdate(LLClientView c, Packet packet)
  7320. {
  7321. if(c.OnAgentUpdate is null)
  7322. return;
  7323. AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
  7324. AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
  7325. uint seq = packet.Header.Sequence;
  7326. c.TotalAgentUpdates++;
  7327. // dont let ignored updates pollute this throttles
  7328. if(c.SceneAgent is null || c.SceneAgent.IsChildAgent ||
  7329. c.SceneAgent.IsInTransit || seq <= c.m_thisAgentUpdateArgs.lastpacketSequence )
  7330. {
  7331. // throttle reset is done at MoveAgentIntoRegion()
  7332. // called by scenepresence on completemovement
  7333. //PacketPool.Instance.ReturnPacket(packet);
  7334. return;
  7335. }
  7336. c.m_thisAgentUpdateArgs.lastpacketSequence = seq;
  7337. bool movement;
  7338. bool camera;
  7339. double now = Util.GetTimeStampMS();
  7340. if (now - c.m_thisAgentUpdateArgs.lastUpdateTS > 500.0) // at least 2 per sec
  7341. {
  7342. movement = true;
  7343. camera = true;
  7344. }
  7345. else
  7346. {
  7347. movement = c.CheckAgentMovementUpdateSignificance(x, now);
  7348. camera = c.CheckAgentCameraUpdateSignificance(x);
  7349. }
  7350. c.OnPreAgentUpdate?.Invoke(c, c.m_thisAgentUpdateArgs);
  7351. // Was there a significant movement/state change?
  7352. if (movement)
  7353. {
  7354. c.m_thisAgentUpdateArgs.lastMoveUpdateTS = now;
  7355. c.m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation;
  7356. c.m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags;
  7357. c.m_thisAgentUpdateArgs.Far = x.Far;
  7358. c.m_thisAgentUpdateArgs.Flags = x.Flags;
  7359. c.m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation;
  7360. c.m_thisAgentUpdateArgs.State = x.State;
  7361. c.m_thisAgentUpdateArgs.NeedsCameraCollision = !camera;
  7362. c.OnAgentUpdate?.Invoke(c, c.m_thisAgentUpdateArgs);
  7363. }
  7364. // Was there a significant camera(s) change?
  7365. if (camera)
  7366. {
  7367. c.m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
  7368. c.m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter;
  7369. c.m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
  7370. c.m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
  7371. c.m_thisAgentUpdateArgs.NeedsCameraCollision = true;
  7372. c.OnAgentCameraUpdate?.Invoke(c, c.m_thisAgentUpdateArgs);
  7373. }
  7374. if(movement && camera)
  7375. c.m_thisAgentUpdateArgs.lastUpdateTS = now;
  7376. }
  7377. private static void HandleMoneyTransferRequest(LLClientView c, Packet Pack)
  7378. {
  7379. if(c.OnMoneyTransferRequest is null)
  7380. return;
  7381. MoneyTransferRequestPacket money = (MoneyTransferRequestPacket)Pack;
  7382. c.OnMoneyTransferRequest?.Invoke(money.MoneyData.SourceID, money.MoneyData.DestID,
  7383. money.MoneyData.Amount, money.MoneyData.TransactionType,
  7384. Util.FieldToString(money.MoneyData.Description));
  7385. }
  7386. private static void HandleParcelGodMarkAsContent(LLClientView c, Packet packet)
  7387. {
  7388. if(c.OnParcelGodMark is null)
  7389. return;
  7390. ParcelGodMarkAsContentPacket ParcelGodMarkAsContent = (ParcelGodMarkAsContentPacket)packet;
  7391. c.OnParcelGodMark?.Invoke(c,
  7392. c.m_agentId,
  7393. ParcelGodMarkAsContent.ParcelData.LocalID);
  7394. }
  7395. private static void HandleFreezeUser(LLClientView c, Packet packet)
  7396. {
  7397. if(c.OnParcelFreezeUser is null)
  7398. return;
  7399. FreezeUserPacket FreezeUser = (FreezeUserPacket)packet;
  7400. c.OnParcelFreezeUser?.Invoke(c,
  7401. c.m_agentId,
  7402. FreezeUser.Data.Flags,
  7403. FreezeUser.Data.TargetID);
  7404. }
  7405. private static void HandleEjectUser(LLClientView c, Packet packet)
  7406. {
  7407. if(c.OnParcelEjectUser is null)
  7408. return;
  7409. EjectUserPacket EjectUser = (EjectUserPacket)packet;
  7410. c.OnParcelEjectUser?.Invoke(c,
  7411. c.m_agentId,
  7412. EjectUser.Data.Flags,
  7413. EjectUser.Data.TargetID);
  7414. }
  7415. private static void HandleParcelBuyPass(LLClientView c, Packet packet)
  7416. {
  7417. if(c.OnParcelBuyPass is null)
  7418. return;
  7419. ParcelBuyPassPacket ParcelBuyPass = (ParcelBuyPassPacket)packet;
  7420. c.OnParcelBuyPass?.Invoke(c,
  7421. c.m_agentId,
  7422. ParcelBuyPass.ParcelData.LocalID);
  7423. }
  7424. private static void HandleParcelBuyRequest(LLClientView c, Packet Pack)
  7425. {
  7426. ParcelBuyPacket parcel = (ParcelBuyPacket)Pack;
  7427. c.OnParcelBuy?.Invoke(c.m_agentId, parcel.Data.GroupID, parcel.Data.Final,
  7428. parcel.Data.IsGroupOwned,
  7429. parcel.Data.RemoveContribution, parcel.Data.LocalID, parcel.ParcelData.Area,
  7430. parcel.ParcelData.Price,
  7431. false);
  7432. }
  7433. private static void HandleUUIDGroupNameRequest(LLClientView c, Packet Pack)
  7434. {
  7435. if(c.OnUUIDGroupNameRequest is null)
  7436. return;
  7437. ScenePresence sp = (ScenePresence)c.SceneAgent;
  7438. if(sp is null || sp.IsDeleted || (sp.IsInTransit && !sp.IsInLocalTransit))
  7439. return;
  7440. UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack;
  7441. for (int i = 0; i < upack.UUIDNameBlock.Length; i++)
  7442. {
  7443. c.OnUUIDGroupNameRequest?.Invoke(upack.UUIDNameBlock[i].ID, c);
  7444. }
  7445. }
  7446. public static void HandleGenericMessage(LLClientView c, Packet pack)
  7447. {
  7448. if (c.m_genericPacketHandlers.Count == 0)
  7449. return;
  7450. GenericMessagePacket gmpack = (GenericMessagePacket)pack;
  7451. string method = Util.FieldToString(gmpack.MethodData.Method).ToLower().Trim();
  7452. if (c.m_genericPacketHandlers.TryGetValue(method, out GenericMessage handlerGenericMessage))
  7453. {
  7454. List<string> msg = new();
  7455. List<byte[]> msgBytes = new();
  7456. foreach (GenericMessagePacket.ParamListBlock block in gmpack.ParamList)
  7457. {
  7458. msg.Add(Util.FieldToString(block.Parameter));
  7459. msgBytes.Add(block.Parameter);
  7460. }
  7461. try
  7462. {
  7463. c.OnBinaryGenericMessage?.Invoke(c, method, msgBytes.ToArray());
  7464. handlerGenericMessage?.Invoke(c, method, msg);
  7465. }
  7466. catch (Exception e)
  7467. {
  7468. m_log.ErrorFormat(
  7469. "[LLCLIENTVIEW]: Exception when handling generic message {0}{1}", e.Message, e.StackTrace);
  7470. }
  7471. }
  7472. }
  7473. public static void HandleObjectGroupRequest(LLClientView c, Packet Pack)
  7474. {
  7475. if(c.OnObjectGroupRequest is null)
  7476. return;
  7477. ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack;
  7478. for (int i = 0; i < ogpack.ObjectData.Length; i++)
  7479. c.OnObjectGroupRequest?.Invoke(c, ogpack.AgentData.GroupID, ogpack.ObjectData[i].ObjectLocalID, UUID.Zero);
  7480. }
  7481. private static void HandleViewerEffect(LLClientView c, Packet Pack)
  7482. {
  7483. if(c.OnViewerEffect is null)
  7484. return;
  7485. ViewerEffectPacket viewer = (ViewerEffectPacket)Pack;
  7486. List<ViewerEffectEventHandlerArg> args = new(viewer.Effect.Length);
  7487. for (int i = 0; i < viewer.Effect.Length; i++)
  7488. {
  7489. //copy the effects block arguments into the event handler arg.
  7490. ViewerEffectEventHandlerArg argument = new()
  7491. {
  7492. AgentID = viewer.Effect[i].AgentID,
  7493. Color = viewer.Effect[i].Color,
  7494. Duration = viewer.Effect[i].Duration,
  7495. ID = viewer.Effect[i].ID,
  7496. Type = viewer.Effect[i].Type,
  7497. TypeData = viewer.Effect[i].TypeData
  7498. };
  7499. args.Add(argument);
  7500. }
  7501. c.OnViewerEffect?.Invoke(c, args);
  7502. }
  7503. private static void HandleVelocityInterpolateOff(LLClientView c, Packet Pack)
  7504. {
  7505. c.m_VelocityInterpolate = false;
  7506. }
  7507. private static void HandleVelocityInterpolateOn(LLClientView c, Packet Pack)
  7508. {
  7509. c.m_VelocityInterpolate = true;
  7510. }
  7511. private static void HandleAvatarPropertiesRequest(LLClientView c, Packet Pack)
  7512. {
  7513. AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack;
  7514. c.OnRequestAvatarProperties?.Invoke(c, avatarProperties.AgentData.AvatarID);
  7515. }
  7516. private static void HandleChatFromViewer(LLClientView c, Packet Pack)
  7517. {
  7518. if (c.OnChatFromClient is null)
  7519. return;
  7520. ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack;
  7521. ChatFromViewerPacket.ChatDataBlock packdata = inchatpack.ChatData;
  7522. OSChatMessage args = new()
  7523. {
  7524. Channel = packdata.Channel,
  7525. Message = Utils.BytesToString(packdata.Message),
  7526. Type = (ChatTypeEnum)packdata.Type,
  7527. Position = c.SceneAgent.AbsolutePosition,
  7528. Scene = c.Scene,
  7529. Sender = c
  7530. };
  7531. c.OnChatFromClient?.Invoke(c, args);
  7532. }
  7533. private static void HandlerAvatarPropertiesUpdate(LLClientView c, Packet Pack)
  7534. {
  7535. if (c.OnUpdateAvatarProperties is null)
  7536. return;
  7537. AvatarPropertiesUpdatePacket avatarProps = (AvatarPropertiesUpdatePacket)Pack;
  7538. AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = avatarProps.PropertiesData;
  7539. UserProfileProperties UserProfile = new()
  7540. {
  7541. UserId = c.AgentId,
  7542. WebUrl = Utils.BytesToString(Properties.ProfileURL),
  7543. ImageId = Properties.ImageID,
  7544. FirstLifeImageId = Properties.FLImageID,
  7545. AboutText = Utils.BytesToString(Properties.AboutText),
  7546. FirstLifeText = Utils.BytesToString(Properties.FLAboutText),
  7547. PublishProfile = Properties.AllowPublish,
  7548. PublishMature = Properties.MaturePublish
  7549. };
  7550. c.OnUpdateAvatarProperties?.Invoke(c, UserProfile);
  7551. }
  7552. private static void HandlerScriptDialogReply(LLClientView c, Packet Pack)
  7553. {
  7554. if (c.OnChatFromClient is null)
  7555. return;
  7556. ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack;
  7557. //m_log.DebugFormat("[CLIENT]: Received ScriptDialogReply from {0}", rdialog.Data.ObjectID);
  7558. ScriptDialogReplyPacket.DataBlock rdialogData = rdialog.Data;
  7559. OSChatMessage args = new()
  7560. {
  7561. Channel = rdialogData.ChatChannel,
  7562. Message = Utils.BytesToString(rdialogData.ButtonLabel),
  7563. Type = ChatTypeEnum.Region, //Behaviour in SL is that the response can be heard from any distance
  7564. Scene = c.Scene,
  7565. Sender = c
  7566. };
  7567. c.OnChatFromClient?.Invoke(c, args);
  7568. }
  7569. private static void HandlerImprovedInstantMessage(LLClientView c, Packet Pack)
  7570. {
  7571. if(c.OnInstantMessage is null)
  7572. return;
  7573. ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack;
  7574. string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName);
  7575. string IMmessage = Utils.BytesToString(msgpack.MessageBlock.Message);
  7576. GridInstantMessage im = new(c.Scene,
  7577. msgpack.AgentData.AgentID,
  7578. IMfromName,
  7579. msgpack.MessageBlock.ToAgentID,
  7580. msgpack.MessageBlock.Dialog,
  7581. msgpack.MessageBlock.FromGroup,
  7582. IMmessage,
  7583. msgpack.MessageBlock.ID,
  7584. msgpack.MessageBlock.Offline != 0,
  7585. msgpack.MessageBlock.Position,
  7586. msgpack.MessageBlock.BinaryBucket,
  7587. true);
  7588. c.OnInstantMessage?.Invoke(c, im);
  7589. }
  7590. private static void HandlerAcceptFriendship(LLClientView c, Packet Pack)
  7591. {
  7592. if(c.OnApproveFriendRequest is null)
  7593. return;
  7594. AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack;
  7595. // My guess is this is the folder to stick the calling card into
  7596. List<UUID> callingCardFolders = new();
  7597. UUID transactionID = afriendpack.TransactionBlock.TransactionID;
  7598. for (int fi = 0; fi < afriendpack.FolderData.Length; fi++)
  7599. {
  7600. callingCardFolders.Add(afriendpack.FolderData[fi].FolderID);
  7601. }
  7602. c.OnApproveFriendRequest?.Invoke(c, transactionID, callingCardFolders);
  7603. }
  7604. private static void HandlerDeclineFriendship(LLClientView c, Packet Pack)
  7605. {
  7606. DeclineFriendshipPacket dfriendpack = (DeclineFriendshipPacket)Pack;
  7607. c.OnDenyFriendRequest?.Invoke(c, dfriendpack.TransactionBlock.TransactionID, null);
  7608. }
  7609. private static void HandlerTerminateFriendship(LLClientView c, Packet Pack)
  7610. {
  7611. TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack;
  7612. UUID exFriendID = tfriendpack.ExBlock.OtherID;
  7613. FriendshipTermination TerminateFriendshipHandler = c.OnTerminateFriendship;
  7614. TerminateFriendshipHandler?.Invoke(c, exFriendID);
  7615. }
  7616. private static void HandleFindAgent(LLClientView c, Packet packet)
  7617. {
  7618. FindAgentPacket FindAgent = (FindAgentPacket)packet;
  7619. c.OnFindAgent?.Invoke(c, FindAgent.AgentBlock.Hunter,FindAgent.AgentBlock.Prey);
  7620. }
  7621. private static void HandleTrackAgent(LLClientView c, Packet packet)
  7622. {
  7623. TrackAgentPacket TrackAgent = (TrackAgentPacket)packet;
  7624. c.OnTrackAgent?.Invoke(c,
  7625. TrackAgent.AgentData.AgentID,
  7626. TrackAgent.TargetData.PreyID);
  7627. }
  7628. private static void HandlerRezObject(LLClientView c, Packet Pack)
  7629. {
  7630. RezObjectPacket rezPacket = (RezObjectPacket)Pack;
  7631. UUID rezGroupID = rezPacket.AgentData.GroupID;
  7632. if(!c.IsGroupMember(rezGroupID))
  7633. rezGroupID = UUID.Zero;
  7634. c.OnRezObject?.Invoke(c, rezPacket.InventoryData.ItemID, rezGroupID, rezPacket.RezData.RayEnd,
  7635. rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID,
  7636. rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection,
  7637. rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem,
  7638. rezPacket.RezData.FromTaskID);
  7639. }
  7640. private class DeRezObjectInfo
  7641. {
  7642. public List<uint> objectids;
  7643. public HashSet<int> rcvedpackets;
  7644. }
  7645. private Dictionary<UUID, DeRezObjectInfo> m_DeRezObjectDelayed;
  7646. private static void HandlerDeRezObject(LLClientView c, Packet Pack)
  7647. {
  7648. if (c.OnDeRezObject is null)
  7649. return;
  7650. DeRezObjectPacket DeRezPacket = (DeRezObjectPacket)Pack;
  7651. List<uint> deRezIDs;
  7652. DeRezObjectPacket.AgentBlockBlock DeRezPacketAgentBlock = DeRezPacket.AgentBlock;
  7653. DeRezAction action = (DeRezAction)DeRezPacketAgentBlock.Destination;
  7654. int numberPackets = DeRezPacketAgentBlock.PacketCount;
  7655. int curPacket = DeRezPacketAgentBlock.PacketNumber;
  7656. UUID id = DeRezPacketAgentBlock.TransactionID;
  7657. if (numberPackets > 1)
  7658. {
  7659. c.m_DeRezObjectDelayed ??= new Dictionary<UUID, DeRezObjectInfo>();
  7660. if (!c.m_DeRezObjectDelayed.TryGetValue(id, out DeRezObjectInfo info))
  7661. {
  7662. deRezIDs = new List<uint>(DeRezPacket.ObjectData.Length);
  7663. info = new DeRezObjectInfo
  7664. {
  7665. rcvedpackets = new HashSet<int>() { curPacket },
  7666. objectids = deRezIDs
  7667. };
  7668. c.m_DeRezObjectDelayed[id] = info;
  7669. }
  7670. else
  7671. {
  7672. if(info.rcvedpackets.Contains(curPacket))
  7673. return;
  7674. info.rcvedpackets.Add(curPacket);
  7675. deRezIDs = info.objectids;
  7676. }
  7677. foreach (DeRezObjectPacket.ObjectDataBlock data in DeRezPacket.ObjectData)
  7678. {
  7679. deRezIDs.Add(data.ObjectLocalID);
  7680. }
  7681. if (info.rcvedpackets.Count < numberPackets)
  7682. return;
  7683. c.m_DeRezObjectDelayed.Remove(id);
  7684. info.objectids = null;
  7685. info.rcvedpackets = null;
  7686. }
  7687. else
  7688. {
  7689. deRezIDs = new List<uint>(DeRezPacket.ObjectData.Length);
  7690. foreach (DeRezObjectPacket.ObjectDataBlock data in DeRezPacket.ObjectData)
  7691. {
  7692. deRezIDs.Add(data.ObjectLocalID);
  7693. }
  7694. }
  7695. c.OnDeRezObject?.Invoke(c, deRezIDs, DeRezPacketAgentBlock.GroupID,
  7696. action, DeRezPacketAgentBlock.DestinationID);
  7697. }
  7698. private static void HandlerRezRestoreToWorld(LLClientView c, Packet Pack)
  7699. {
  7700. RezRestoreToWorldPacket restore = (RezRestoreToWorldPacket)Pack;
  7701. c.OnRezRestoreToWorld?.Invoke(c, restore.InventoryData.ItemID);
  7702. }
  7703. private static void HandlerModifyLand(LLClientView c, Packet Pack)
  7704. {
  7705. if (c.OnModifyTerrain is null)
  7706. return;
  7707. ModifyLandPacket modify = (ModifyLandPacket)Pack;
  7708. if (modify.ParcelData.Length == 0)
  7709. return;
  7710. //m_log.Info("[LAND]: LAND:" + modify.ToString());
  7711. for (int i = 0; i < modify.ParcelData.Length; i++)
  7712. {
  7713. c.OnModifyTerrain?.Invoke(c.m_agentId, modify.ModifyBlock.Height, modify.ModifyBlock.Seconds,
  7714. modify.ModifyBlockExtended[i].BrushSize, modify.ModifyBlock.Action,
  7715. modify.ParcelData[i].North, modify.ParcelData[i].West,
  7716. modify.ParcelData[i].South, modify.ParcelData[i].East,
  7717. modify.ParcelData[i].LocalID);
  7718. }
  7719. }
  7720. public uint m_viewerHandShakeFlags = 0;
  7721. private static void HandlerRegionHandshakeReply(LLClientView c, Packet Pack)
  7722. {
  7723. if (c.OnRegionHandShakeReply is null)
  7724. return; // silence the warning
  7725. RegionHandshakeReplyPacket rsrpkt = (RegionHandshakeReplyPacket)Pack;
  7726. if(c.m_supportViewerCache)
  7727. c.m_viewerHandShakeFlags = rsrpkt.RegionInfo.Flags;
  7728. else
  7729. c.m_viewerHandShakeFlags = 0;
  7730. c.OnRegionHandShakeReply?.Invoke(c);
  7731. }
  7732. private static void HandlerAgentWearablesRequest(LLClientView c, Packet Pack)
  7733. {
  7734. c.OnRequestWearables?.Invoke(c);
  7735. c.OnRequestAvatarsData?.Invoke(c);
  7736. }
  7737. private static void HandlerAgentSetAppearance(LLClientView c, Packet Pack)
  7738. {
  7739. if(c.OnSetAppearance is null)
  7740. return;
  7741. AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack;
  7742. try
  7743. {
  7744. Vector3 avSize = appear.AgentData.Size;
  7745. byte[] visualparams = new byte[appear.VisualParam.Length];
  7746. for (int i = 0; i < appear.VisualParam.Length; i++)
  7747. visualparams[i] = appear.VisualParam[i].ParamValue;
  7748. //var b = appear.WearableData[0];
  7749. Primitive.TextureEntry te = null;
  7750. if (appear.ObjectData.TextureEntry.Length > 1)
  7751. te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length);
  7752. WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length];
  7753. for (int i=0; i<appear.WearableData.Length;i++)
  7754. cacheitems[i] = new WearableCacheItem(){
  7755. CacheId = appear.WearableData[i].CacheID,
  7756. TextureIndex=Convert.ToUInt32(appear.WearableData[i].TextureIndex)
  7757. };
  7758. c.OnSetAppearance?.Invoke(c, te, visualparams,avSize, cacheitems);
  7759. }
  7760. catch (Exception e)
  7761. {
  7762. m_log.Error($"[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {e.Message}");
  7763. }
  7764. }
  7765. private static void HandlerAgentIsNowWearing(LLClientView c, Packet Pack)
  7766. {
  7767. if (c.OnAvatarNowWearing is null)
  7768. return;
  7769. AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack;
  7770. AvatarWearingArgs wearingArgs = new();
  7771. for (int i = 0; i < nowWearing.WearableData.Length; i++)
  7772. {
  7773. //m_log.DebugFormat("[XXX]: Wearable type {0} item {1}", nowWearing.WearableData[i].WearableType, nowWearing.WearableData[i].ItemID);
  7774. AvatarWearingArgs.Wearable wearable = new(nowWearing.WearableData[i].ItemID,
  7775. nowWearing.WearableData[i].WearableType);
  7776. wearingArgs.NowWearing.Add(wearable);
  7777. }
  7778. c.OnAvatarNowWearing?.Invoke(c, wearingArgs);
  7779. }
  7780. private static void HandlerRezSingleAttachmentFromInv(LLClientView c, Packet Pack)
  7781. {
  7782. RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack;
  7783. c.OnRezSingleAttachmentFromInv?.Invoke(c, rez.ObjectData.ItemID,
  7784. rez.ObjectData.AttachmentPt);
  7785. }
  7786. private static void HandleRezMultipleAttachmentsFromInv(LLClientView c, Packet Pack)
  7787. {
  7788. if(c.OnRezMultipleAttachmentsFromInv is null)
  7789. return;
  7790. RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack;
  7791. List<KeyValuePair<UUID, uint>> rezlist = new();
  7792. foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in rez.ObjectData)
  7793. rezlist.Add(new KeyValuePair<UUID, uint>(obj.ItemID, obj.AttachmentPt));
  7794. c.OnRezMultipleAttachmentsFromInv?.Invoke(c, rezlist);
  7795. }
  7796. private static void HandleDetachAttachmentIntoInv(LLClientView c, Packet Pack)
  7797. {
  7798. if (c.OnDetachAttachmentIntoInv is null)
  7799. return;
  7800. DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack;
  7801. if(detachtoInv.ObjectData.AgentID.NotEqual(c.m_agentId))
  7802. return;
  7803. c.OnDetachAttachmentIntoInv?.Invoke(detachtoInv.ObjectData.ItemID, c);
  7804. }
  7805. private static void HandleObjectAttach(LLClientView c, Packet Pack)
  7806. {
  7807. if (c.OnObjectAttach is null)
  7808. return;
  7809. ObjectAttachPacket att = (ObjectAttachPacket)Pack;
  7810. if (att.ObjectData.Length > 0)
  7811. c.OnObjectAttach?.Invoke(c, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, false);
  7812. }
  7813. private static void HandleObjectDetach(LLClientView c, Packet Pack)
  7814. {
  7815. if(c.OnObjectDetach is null)
  7816. return;
  7817. ObjectDetachPacket dett = (ObjectDetachPacket)Pack;
  7818. for (int j = 0; j < dett.ObjectData.Length; j++)
  7819. {
  7820. uint obj = dett.ObjectData[j].ObjectLocalID;
  7821. c.OnObjectDetach?.Invoke(obj, c);
  7822. }
  7823. }
  7824. private static void HandleObjectDrop(LLClientView c, Packet Pack)
  7825. {
  7826. if(c.OnObjectDrop is null)
  7827. return;
  7828. ObjectDropPacket dropp = (ObjectDropPacket)Pack;
  7829. for (int j = 0; j < dropp.ObjectData.Length; j++)
  7830. {
  7831. uint obj = dropp.ObjectData[j].ObjectLocalID;
  7832. c.OnObjectDrop?.Invoke(obj, c);
  7833. }
  7834. }
  7835. private static void HandleSetAlwaysRun(LLClientView c, Packet Pack)
  7836. {
  7837. SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack;
  7838. c.OnSetAlwaysRun?.Invoke(c, run.AgentData.AlwaysRun);
  7839. }
  7840. private static void HandleCompleteAgentMovement(LLClientView c, Packet Pack)
  7841. {
  7842. //m_log.DebugFormat("[LLClientView] HandleCompleteAgentMovement");
  7843. CompleteAgentMovementPacket cmp = (CompleteAgentMovementPacket)Pack;
  7844. if(cmp.AgentData.CircuitCode == c.m_circuitCode)
  7845. c.OnCompleteMovementToRegion?.Invoke(c, true);
  7846. }
  7847. private static void HandleAgentAnimation(LLClientView c, Packet Pack)
  7848. {
  7849. if(c.OnChangeAnim is null)
  7850. return;
  7851. AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack;
  7852. for (int i = 0; i < AgentAni.AnimationList.Length; i++)
  7853. c.OnChangeAnim?.Invoke(AgentAni.AnimationList[i].AnimID, AgentAni.AnimationList[i].StartAnim, false);
  7854. c.OnChangeAnim?.Invoke(UUID.Zero, false, true);
  7855. }
  7856. private static void HandleAgentRequestSit(LLClientView c, Packet Pack)
  7857. {
  7858. if (c.OnAgentRequestSit is null)
  7859. return;
  7860. if (c.SceneAgent.IsChildAgent)
  7861. {
  7862. c.SendCantSitBecauseChildAgentResponse();
  7863. return;
  7864. }
  7865. AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack;
  7866. c.OnAgentRequestSit?.Invoke(c, agentRequestSit.AgentData.AgentID,
  7867. agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset);
  7868. }
  7869. private static void HandleAgentSit(LLClientView c, Packet Pack)
  7870. {
  7871. if (c.OnAgentSit is null)
  7872. return;
  7873. if (c.SceneAgent.IsChildAgent)
  7874. {
  7875. c.SendCantSitBecauseChildAgentResponse();
  7876. return;
  7877. }
  7878. AgentSitPacket agentSit = (AgentSitPacket)Pack;
  7879. c.OnAgentSit?.Invoke(c, agentSit.AgentData.AgentID);
  7880. }
  7881. /// <summary>
  7882. /// Used when a child agent gets a sit response which should not be fulfilled.
  7883. /// </summary>
  7884. private void SendCantSitBecauseChildAgentResponse()
  7885. {
  7886. SendAlertMessage("Can't sit on object because it is not in the same region as you.");
  7887. }
  7888. private static void HandleSoundTrigger(LLClientView c, Packet Pack)
  7889. {
  7890. SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack;
  7891. // UUIDS are sent as zeroes by the client, substitute agent's id
  7892. c.OnSoundTrigger?.Invoke(soundTriggerPacket.SoundData.SoundID, c.m_agentId,
  7893. c.m_agentId, c.m_agentId,
  7894. soundTriggerPacket.SoundData.Gain, soundTriggerPacket.SoundData.Position,
  7895. soundTriggerPacket.SoundData.Handle);
  7896. }
  7897. private static void HandleAvatarPickerRequest(LLClientView c, Packet Pack)
  7898. {
  7899. AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack;
  7900. AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData;
  7901. AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data;
  7902. //m_log.Debug("Agent Sends:" + Utils.BytesToString(querydata.Name));
  7903. c.OnAvatarPickerRequest?.Invoke(c, Requestdata.AgentID, Requestdata.QueryID,
  7904. Utils.BytesToString(querydata.Name));
  7905. }
  7906. private static void HandleAgentDataUpdateRequest(LLClientView c, Packet Pack)
  7907. {
  7908. AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack;
  7909. c.OnAgentDataUpdateRequest?.Invoke(c, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID);
  7910. }
  7911. private static void HandleUserInfoRequest(LLClientView c, Packet _)
  7912. {
  7913. if (c.OnUserInfoRequest != null)
  7914. {
  7915. c.OnUserInfoRequest(c);
  7916. }
  7917. else
  7918. {
  7919. c.SendUserInfoReply(false, true, "");
  7920. }
  7921. }
  7922. private static void HandleUpdateUserInfo(LLClientView c, Packet Pack)
  7923. {
  7924. if(c.OnUpdateUserInfo is null)
  7925. return;
  7926. UpdateUserInfoPacket updateUserInfo = (UpdateUserInfoPacket)Pack;
  7927. bool visible = true;
  7928. string DirectoryVisibility = Utils.BytesToString(updateUserInfo.UserData.DirectoryVisibility);
  7929. if (DirectoryVisibility == "hidden")
  7930. visible = false;
  7931. c.OnUpdateUserInfo?.Invoke( updateUserInfo.UserData.IMViaEMail, visible, c);
  7932. }
  7933. private static void HandleSetStartLocationRequest(LLClientView c, Packet Pack)
  7934. {
  7935. SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack;
  7936. float packX = avSetStartLocationRequestPacket.StartLocationData.LocationPos.X;
  7937. float packY = avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y;
  7938. // Linden Client limitation..
  7939. if (packX == 255.5f || packY == 255.5f)
  7940. {
  7941. if (c.m_scene.TryGetScenePresence(c.m_agentId, out ScenePresence avatar))
  7942. {
  7943. if (packX == 255.5f)
  7944. {
  7945. avSetStartLocationRequestPacket.StartLocationData.LocationPos.X = avatar.AbsolutePosition.X;
  7946. }
  7947. if (packY == 255.5f)
  7948. {
  7949. avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y = avatar.AbsolutePosition.Y;
  7950. }
  7951. }
  7952. }
  7953. c.OnSetStartLocationRequest?.Invoke(c, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos,
  7954. avSetStartLocationRequestPacket.StartLocationData.LocationLookAt,
  7955. avSetStartLocationRequestPacket.StartLocationData.LocationID);
  7956. }
  7957. private static void HandleAgentThrottle(LLClientView c, Packet Pack)
  7958. {
  7959. AgentThrottlePacket atpack = (AgentThrottlePacket)Pack;
  7960. c.m_udpClient.SetThrottles(atpack.Throttle.Throttles);
  7961. c.OnUpdateThrottles?.Invoke();
  7962. }
  7963. private static void HandleAgentPause(LLClientView c, Packet Pack)
  7964. {
  7965. c.m_udpClient.IsPaused = true;
  7966. }
  7967. private static void HandleAgentResume(LLClientView c, Packet Pack)
  7968. {
  7969. c.m_udpClient.IsPaused = false;
  7970. c.m_udpServer.SendPing(c.m_udpClient);
  7971. }
  7972. private static void HandleForceScriptControlRelease(LLClientView c, Packet _)
  7973. {
  7974. c.OnForceReleaseControls?.Invoke(c, c.m_agentId);
  7975. }
  7976. #endregion Scene/Avatar
  7977. #region Objects/m_sceneObjects
  7978. private static void HandleObjectLink(LLClientView c, Packet Pack)
  7979. {
  7980. ObjectLinkPacket link = (ObjectLinkPacket)Pack;
  7981. uint parentprimid = 0;
  7982. List<uint> childrenprims = new();
  7983. if (link.ObjectData.Length > 1)
  7984. {
  7985. parentprimid = link.ObjectData[0].ObjectLocalID;
  7986. for (int i = 1; i < link.ObjectData.Length; i++)
  7987. {
  7988. childrenprims.Add(link.ObjectData[i].ObjectLocalID);
  7989. }
  7990. }
  7991. c.OnLinkObjects?.Invoke(c, parentprimid, childrenprims);
  7992. }
  7993. private static void HandleObjectDelink(LLClientView c, Packet Pack)
  7994. {
  7995. ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack;
  7996. // It appears the prim at index 0 is not always the root prim (for
  7997. // instance, when one prim of a link set has been edited independently
  7998. // of the others). Therefore, we'll pass all the ids onto the delink
  7999. // method for it to decide which is the root.
  8000. List<uint> prims = new();
  8001. for (int i = 0; i < delink.ObjectData.Length; i++)
  8002. {
  8003. prims.Add(delink.ObjectData[i].ObjectLocalID);
  8004. }
  8005. c.OnDelinkObjects?.Invoke(prims, c);
  8006. }
  8007. private static void HandleObjectAdd(LLClientView c, Packet Pack)
  8008. {
  8009. ObjectAddPacket addPacket = (ObjectAddPacket)Pack;
  8010. if (addPacket.AgentData.SessionID.NotEqual(c.m_sessionId) || addPacket.AgentData.AgentID.NotEqual(c.m_agentId))
  8011. return;
  8012. ObjectAddPacket.ObjectDataBlock datablk = addPacket.ObjectData;
  8013. PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket);
  8014. c.OnAddPrim?.Invoke(c.m_agentId, addPacket.AgentData.GroupID, datablk.RayEnd,
  8015. datablk.Rotation, shape,
  8016. datablk.BypassRaycast, datablk.RayStart, datablk.RayTargetID, datablk.RayEndIsIntersection,
  8017. datablk.AddFlags);
  8018. }
  8019. private static void HandleObjectShape(LLClientView c, Packet Pack)
  8020. {
  8021. if(c.OnUpdatePrimShape is null)
  8022. return;
  8023. ObjectShapePacket shapePacket = (ObjectShapePacket)Pack;
  8024. for (int i = 0; i < shapePacket.ObjectData.Length; i++)
  8025. {
  8026. uint id = shapePacket.ObjectData[i].ObjectLocalID;
  8027. UpdateShapeArgs shapeData = new()
  8028. {
  8029. ObjectLocalID = id,
  8030. PathBegin = shapePacket.ObjectData[i].PathBegin,
  8031. PathCurve = shapePacket.ObjectData[i].PathCurve,
  8032. PathEnd = shapePacket.ObjectData[i].PathEnd,
  8033. PathRadiusOffset = shapePacket.ObjectData[i].PathRadiusOffset,
  8034. PathRevolutions = shapePacket.ObjectData[i].PathRevolutions,
  8035. PathScaleX = shapePacket.ObjectData[i].PathScaleX,
  8036. PathScaleY = shapePacket.ObjectData[i].PathScaleY,
  8037. PathShearX = shapePacket.ObjectData[i].PathShearX,
  8038. PathShearY = shapePacket.ObjectData[i].PathShearY,
  8039. PathSkew = shapePacket.ObjectData[i].PathSkew,
  8040. PathTaperX = shapePacket.ObjectData[i].PathTaperX,
  8041. PathTaperY = shapePacket.ObjectData[i].PathTaperY,
  8042. PathTwist = shapePacket.ObjectData[i].PathTwist,
  8043. PathTwistBegin = shapePacket.ObjectData[i].PathTwistBegin,
  8044. ProfileBegin = shapePacket.ObjectData[i].ProfileBegin,
  8045. ProfileCurve = shapePacket.ObjectData[i].ProfileCurve,
  8046. ProfileEnd = shapePacket.ObjectData[i].ProfileEnd,
  8047. ProfileHollow = shapePacket.ObjectData[i].ProfileHollow
  8048. };
  8049. c.OnUpdatePrimShape?.Invoke(c.m_agentId, id, shapeData);
  8050. }
  8051. }
  8052. private static void HandleObjectExtraParams(LLClientView c, Packet Pack)
  8053. {
  8054. ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack;
  8055. if (c.OnUpdateExtraParams != null)
  8056. {
  8057. for (int i = 0; i < extraPar.ObjectData.Length; i++)
  8058. {
  8059. c.OnUpdateExtraParams?.Invoke(c.m_agentId, extraPar.ObjectData[i].ObjectLocalID,
  8060. extraPar.ObjectData[i].ParamType,
  8061. extraPar.ObjectData[i].ParamInUse, extraPar.ObjectData[i].ParamData);
  8062. }
  8063. }
  8064. }
  8065. private static void HandleObjectDuplicate(LLClientView c, Packet Pack)
  8066. {
  8067. if(c.OnObjectDuplicate is null)
  8068. return;
  8069. ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack;
  8070. UUID rezGroupID = c.IsGroupMember(dupe.AgentData.GroupID) ? dupe.AgentData.GroupID : UUID.Zero;
  8071. //ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData;
  8072. for (int i = 0; i < dupe.ObjectData.Length; i++)
  8073. {
  8074. c.OnObjectDuplicate?.Invoke(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset,
  8075. dupe.SharedData.DuplicateFlags, c.m_agentId,
  8076. rezGroupID);
  8077. }
  8078. }
  8079. private static void HandleRequestMultipleObjects(LLClientView c, Packet Pack)
  8080. {
  8081. if (c.OnObjectRequest is null)
  8082. return;
  8083. RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack;
  8084. for (int i = 0; i < incomingRequest.ObjectData.Length; i++)
  8085. c.OnObjectRequest?.Invoke(incomingRequest.ObjectData[i].ID, c);
  8086. }
  8087. private static void HandleObjectSelect(LLClientView c, Packet Pack)
  8088. {
  8089. if(c.OnObjectSelect is null)
  8090. return;
  8091. ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack;
  8092. List<uint> thisSelection = new();
  8093. for (int i = 0; i < incomingselect.ObjectData.Length; i++)
  8094. thisSelection.Add(incomingselect.ObjectData[i].ObjectLocalID);
  8095. c.OnObjectSelect?.Invoke(thisSelection, c);
  8096. }
  8097. private static void HandleObjectDeselect(LLClientView c, Packet Pack)
  8098. {
  8099. if(c.OnObjectDeselect is null)
  8100. return;
  8101. ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack;
  8102. for (int i = 0; i < incomingdeselect.ObjectData.Length; i++)
  8103. {
  8104. c.OnObjectDeselect?.Invoke(incomingdeselect.ObjectData[i].ObjectLocalID, c);
  8105. }
  8106. }
  8107. private static void HandleObjectPosition(LLClientView c, Packet Pack)
  8108. {
  8109. if (c.OnUpdatePrimGroupPosition is null)
  8110. return;
  8111. // DEPRECATED: but till libsecondlife removes it, people will use it
  8112. ObjectPositionPacket position = (ObjectPositionPacket)Pack;
  8113. for (int i = 0; i < position.ObjectData.Length; i++)
  8114. c.OnUpdatePrimGroupPosition?.Invoke(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, c);
  8115. }
  8116. private static void HandleObjectScale(LLClientView c, Packet Pack)
  8117. {
  8118. if (c.OnUpdatePrimGroupScale is null)
  8119. return;
  8120. // DEPRECATED: but till libsecondlife removes it, people will use it
  8121. ObjectScalePacket scale = (ObjectScalePacket)Pack;
  8122. for (int i = 0; i < scale.ObjectData.Length; i++)
  8123. c.OnUpdatePrimGroupScale?.Invoke(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, c);
  8124. }
  8125. private static void HandleObjectRotation(LLClientView c, Packet Pack)
  8126. {
  8127. if (c.OnUpdatePrimGroupRotation is null)
  8128. return;
  8129. // DEPRECATED: but till libsecondlife removes it, people will use it
  8130. ObjectRotationPacket rotation = (ObjectRotationPacket)Pack;
  8131. for (int i = 0; i < rotation.ObjectData.Length; i++)
  8132. c.OnUpdatePrimGroupRotation?.Invoke(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, c);
  8133. }
  8134. private static void HandleObjectFlagUpdate(LLClientView c, Packet Pack)
  8135. {
  8136. if(c.OnUpdatePrimFlags is null)
  8137. return;
  8138. ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack;
  8139. // byte[] data = Pack.ToBytes();
  8140. // 46,47,48 are special positions within the packet
  8141. // This may change so perhaps we need a better way
  8142. // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?)
  8143. /*
  8144. bool UsePhysics = (data[46] != 0) ? true : false;
  8145. bool IsTemporary = (data[47] != 0) ? true : false;
  8146. bool IsPhantom = (data[48] != 0) ? true : false;
  8147. handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this);
  8148. */
  8149. bool UsePhysics = flags.AgentData.UsePhysics;
  8150. bool IsPhantom = flags.AgentData.IsPhantom;
  8151. bool IsTemporary = flags.AgentData.IsTemporary;
  8152. ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks = flags.ExtraPhysics;
  8153. ExtraPhysicsData physdata = new();
  8154. if (blocks is null || blocks.Length == 0)
  8155. {
  8156. physdata.PhysShapeType = PhysShapeType.invalid;
  8157. }
  8158. else
  8159. {
  8160. ObjectFlagUpdatePacket.ExtraPhysicsBlock phsblock = blocks[0];
  8161. physdata.PhysShapeType = (PhysShapeType)phsblock.PhysicsShapeType;
  8162. physdata.Bounce = phsblock.Restitution;
  8163. physdata.Density = phsblock.Density;
  8164. physdata.Friction = phsblock.Friction;
  8165. physdata.GravitationModifier = phsblock.GravityMultiplier;
  8166. }
  8167. c.OnUpdatePrimFlags?.Invoke(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, c);
  8168. }
  8169. Dictionary<uint, uint> objImageSeqs = null;
  8170. double lastobjImageSeqsMS = 0.0;
  8171. private static void HandleObjectImage(LLClientView c, Packet Pack)
  8172. {
  8173. if (c.OnUpdatePrimTexture is null)
  8174. return;
  8175. ObjectImagePacket imagePack = (ObjectImagePacket)Pack;
  8176. double now = Util.GetTimeStampMS();
  8177. if(c.objImageSeqs is null || ( now - c.lastobjImageSeqsMS > 30000.0))
  8178. c.objImageSeqs = new Dictionary<uint, uint>(16);
  8179. c.lastobjImageSeqsMS = now;
  8180. uint seq = Pack.Header.Sequence;
  8181. uint id;
  8182. ObjectImagePacket.ObjectDataBlock o;
  8183. for (int i = 0; i < imagePack.ObjectData.Length; i++)
  8184. {
  8185. o = imagePack.ObjectData[i];
  8186. id = o.ObjectLocalID;
  8187. if(c.objImageSeqs.TryGetValue(id, out uint lastseq))
  8188. {
  8189. if(seq <= lastseq)
  8190. continue;
  8191. }
  8192. c.objImageSeqs[id] = seq;
  8193. c.OnUpdatePrimTexture?.Invoke(id, o.TextureEntry, c);
  8194. }
  8195. }
  8196. private static void HandleObjectGrab(LLClientView c, Packet Pack)
  8197. {
  8198. if(c.OnGrabObject is null)
  8199. return;
  8200. ObjectGrabPacket grab = (ObjectGrabPacket)Pack;
  8201. List<SurfaceTouchEventArgs> touchArgs = new();
  8202. if ((grab.SurfaceInfo != null) && (grab.SurfaceInfo.Length > 0))
  8203. {
  8204. foreach (ObjectGrabPacket.SurfaceInfoBlock surfaceInfo in grab.SurfaceInfo)
  8205. {
  8206. SurfaceTouchEventArgs arg = new()
  8207. {
  8208. Binormal = surfaceInfo.Binormal,
  8209. FaceIndex = surfaceInfo.FaceIndex,
  8210. Normal = surfaceInfo.Normal,
  8211. Position = surfaceInfo.Position,
  8212. STCoord = surfaceInfo.STCoord,
  8213. UVCoord = surfaceInfo.UVCoord
  8214. };
  8215. touchArgs.Add(arg);
  8216. }
  8217. }
  8218. c.OnGrabObject?.Invoke(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, c, touchArgs);
  8219. }
  8220. private static void HandleObjectGrabUpdate(LLClientView c, Packet Pack)
  8221. {
  8222. if (c.OnGrabUpdate is null)
  8223. return;
  8224. ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack;
  8225. List<SurfaceTouchEventArgs> touchArgs = new();
  8226. if ((grabUpdate.SurfaceInfo != null) && (grabUpdate.SurfaceInfo.Length > 0))
  8227. {
  8228. foreach (ObjectGrabUpdatePacket.SurfaceInfoBlock surfaceInfo in grabUpdate.SurfaceInfo)
  8229. {
  8230. SurfaceTouchEventArgs arg = new()
  8231. {
  8232. Binormal = surfaceInfo.Binormal,
  8233. FaceIndex = surfaceInfo.FaceIndex,
  8234. Normal = surfaceInfo.Normal,
  8235. Position = surfaceInfo.Position,
  8236. STCoord = surfaceInfo.STCoord,
  8237. UVCoord = surfaceInfo.UVCoord
  8238. };
  8239. touchArgs.Add(arg);
  8240. }
  8241. }
  8242. c.OnGrabUpdate?.Invoke(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial,
  8243. grabUpdate.ObjectData.GrabPosition, c, touchArgs);
  8244. }
  8245. private static void HandleObjectDeGrab(LLClientView c, Packet Pack)
  8246. {
  8247. if (c.OnDeGrabObject is null)
  8248. return;
  8249. ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack;
  8250. List<SurfaceTouchEventArgs> touchArgs = new();
  8251. if ((deGrab.SurfaceInfo != null) && (deGrab.SurfaceInfo.Length > 0))
  8252. {
  8253. foreach (ObjectDeGrabPacket.SurfaceInfoBlock surfaceInfo in deGrab.SurfaceInfo)
  8254. {
  8255. SurfaceTouchEventArgs arg = new()
  8256. {
  8257. Binormal = surfaceInfo.Binormal,
  8258. FaceIndex = surfaceInfo.FaceIndex,
  8259. Normal = surfaceInfo.Normal,
  8260. Position = surfaceInfo.Position,
  8261. STCoord = surfaceInfo.STCoord,
  8262. UVCoord = surfaceInfo.UVCoord
  8263. };
  8264. touchArgs.Add(arg);
  8265. }
  8266. }
  8267. c.OnDeGrabObject?.Invoke(deGrab.ObjectData.LocalID, c, touchArgs);
  8268. }
  8269. private static void HandleObjectSpinStart(LLClientView c, Packet Pack)
  8270. {
  8271. //m_log.Warn("[CLIENT]: unhandled ObjectSpinStart packet");
  8272. ObjectSpinStartPacket spinStart = (ObjectSpinStartPacket)Pack;
  8273. if (spinStart.AgentData.SessionID.Equals(c.m_sessionId) && spinStart.AgentData.AgentID.Equals(c.m_agentId))
  8274. c.OnSpinStart?.Invoke(spinStart.ObjectData.ObjectID, c);
  8275. }
  8276. private static void HandleObjectSpinUpdate(LLClientView c, Packet Pack)
  8277. {
  8278. //m_log.Warn("[CLIENT]: unhandled ObjectSpinUpdate packet");
  8279. ObjectSpinUpdatePacket spinUpdate = (ObjectSpinUpdatePacket)Pack;
  8280. spinUpdate.ObjectData.Rotation.GetAxisAngle(out Vector3 axis, out float angle);
  8281. //m_log.Warn("[CLIENT]: ObjectSpinUpdate packet rot axis:" + axis + " angle:" + angle);
  8282. c.OnSpinUpdate?.Invoke(spinUpdate.ObjectData.ObjectID, spinUpdate.ObjectData.Rotation, c);
  8283. }
  8284. private static void HandleObjectSpinStop(LLClientView c, Packet Pack)
  8285. {
  8286. //m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet");
  8287. ObjectSpinStopPacket spinStop = (ObjectSpinStopPacket)Pack;
  8288. if (spinStop.AgentData.SessionID.Equals(c.m_sessionId) && spinStop.AgentData.AgentID.Equals(c.m_agentId))
  8289. c.OnSpinStop?.Invoke(spinStop.ObjectData.ObjectID, c);
  8290. }
  8291. private static void HandleObjectDescription(LLClientView c, Packet Pack)
  8292. {
  8293. if(c.OnObjectDescription is null)
  8294. return;
  8295. ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack;
  8296. for (int i = 0; i < objDes.ObjectData.Length; i++)
  8297. c.OnObjectDescription?.Invoke(c, objDes.ObjectData[i].LocalID,
  8298. Util.FieldToString(objDes.ObjectData[i].Description));
  8299. }
  8300. private static void HandleObjectName(LLClientView c, Packet Pack)
  8301. {
  8302. if(c.OnObjectName is null)
  8303. return;
  8304. ObjectNamePacket objName = (ObjectNamePacket)Pack;
  8305. for (int i = 0; i < objName.ObjectData.Length; i++)
  8306. c.OnObjectName?.Invoke(c, objName.ObjectData[i].LocalID,
  8307. Util.FieldToString(objName.ObjectData[i].Name));
  8308. }
  8309. private static void HandleObjectPermissions(LLClientView c, Packet Pack)
  8310. {
  8311. if (c.OnObjectPermissions is null)
  8312. return;
  8313. ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack;
  8314. for (int i = 0; i < newobjPerms.ObjectData.Length; i++)
  8315. {
  8316. ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i];
  8317. byte field = permChanges.Field;
  8318. uint localID = permChanges.ObjectLocalID;
  8319. uint mask = permChanges.Mask;
  8320. byte set = permChanges.Set;
  8321. c.OnObjectPermissions?.Invoke(c, newobjPerms.AgentData.AgentID, newobjPerms.AgentData.SessionID, field, localID, mask, set);
  8322. }
  8323. // Here's our data,
  8324. // PermField contains the field the info goes into
  8325. // PermField determines which mask we're changing
  8326. //
  8327. // chmask is the mask of the change
  8328. // setTF is whether we're adding it or taking it away
  8329. //
  8330. // objLocalID is the localID of the object.
  8331. // Unfortunately, we have to pass the event the packet because objData is an array
  8332. // That means multiple object perms may be updated in a single packet.
  8333. }
  8334. private static void HandleUndo(LLClientView c, Packet Pack)
  8335. {
  8336. if(c.OnUndo is null)
  8337. return;
  8338. UndoPacket undoitem = (UndoPacket)Pack;
  8339. for (int i = 0; i < undoitem.ObjectData.Length; i++)
  8340. c.OnUndo?.Invoke(c, undoitem.ObjectData[i].ObjectID);
  8341. }
  8342. private static void HandleLandUndo(LLClientView c, Packet Pack)
  8343. {
  8344. UndoLandPacket undolanditem = (UndoLandPacket)Pack;
  8345. c.OnLandUndo?.Invoke(c);
  8346. }
  8347. private static void HandleRedo(LLClientView c, Packet Pack)
  8348. {
  8349. if(c.OnRedo is null)
  8350. return;
  8351. RedoPacket redoitem = (RedoPacket)Pack;
  8352. for (int i = 0; i < redoitem.ObjectData.Length; i++)
  8353. c.OnRedo?.Invoke(c, redoitem.ObjectData[i].ObjectID);
  8354. }
  8355. private static void HandleObjectDuplicateOnRay(LLClientView c, Packet Pack)
  8356. {
  8357. if(c.OnObjectDuplicateOnRay is null)
  8358. return;
  8359. ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack;
  8360. UUID rezGroupID = dupeOnRay.AgentData.GroupID;
  8361. if (!c.IsGroupMember(rezGroupID))
  8362. rezGroupID = UUID.Zero;
  8363. for (int i = 0; i < dupeOnRay.ObjectData.Length; i++)
  8364. {
  8365. c.OnObjectDuplicateOnRay?.Invoke(dupeOnRay.ObjectData[i].ObjectLocalID,
  8366. dupeOnRay.AgentData.DuplicateFlags, c.m_agentId, rezGroupID,
  8367. dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd,
  8368. dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast,
  8369. dupeOnRay.AgentData.RayEndIsIntersection,
  8370. dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates);
  8371. }
  8372. }
  8373. private static void HandleRequestObjectPropertiesFamily(LLClientView c, Packet Pack)
  8374. {
  8375. //This powers the little tooltip that appears when you move your mouse over an object
  8376. RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack;
  8377. RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData;
  8378. c.OnRequestObjectPropertiesFamily?.Invoke(c, c.m_agentId, packObjBlock.RequestFlags,
  8379. packObjBlock.ObjectID);
  8380. }
  8381. private static void HandleObjectIncludeInSearch(LLClientView c, Packet Pack)
  8382. {
  8383. if(c.OnObjectIncludeInSearch is null)
  8384. return;
  8385. //This lets us set objects to appear in search (stuff like DataSnapshot, etc)
  8386. ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack;
  8387. foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData)
  8388. c.OnObjectIncludeInSearch?.Invoke(c, objData.IncludeInSearch, objData.ObjectLocalID);
  8389. }
  8390. private static void HandleScriptAnswerYes(LLClientView c, Packet Pack)
  8391. {
  8392. ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack;
  8393. c.OnScriptAnswer?.Invoke(c, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions);
  8394. }
  8395. private static void HandleObjectClickAction(LLClientView c, Packet Pack)
  8396. {
  8397. if(c.OnObjectClickAction is null)
  8398. return;
  8399. ObjectClickActionPacket ocpacket = (ObjectClickActionPacket)Pack;
  8400. foreach (ObjectClickActionPacket.ObjectDataBlock odata in ocpacket.ObjectData)
  8401. {
  8402. byte action = odata.ClickAction;
  8403. uint localID = odata.ObjectLocalID;
  8404. c.OnObjectClickAction?.Invoke(c, localID, action.ToString());
  8405. }
  8406. }
  8407. private static void HandleObjectMaterial(LLClientView c, Packet Pack)
  8408. {
  8409. if(c.OnObjectMaterial is null)
  8410. return;
  8411. ObjectMaterialPacket ompacket = (ObjectMaterialPacket)Pack;
  8412. foreach (ObjectMaterialPacket.ObjectDataBlock odata in ompacket.ObjectData)
  8413. {
  8414. byte material = odata.Material;
  8415. uint localID = odata.ObjectLocalID;
  8416. c.OnObjectMaterial?.Invoke(c, localID, material.ToString());
  8417. }
  8418. }
  8419. #endregion Objects/m_sceneObjects
  8420. #region Inventory/Asset/Other related packets
  8421. private static void HandleRequestImage(LLClientView c, Packet Pack)
  8422. {
  8423. RequestImagePacket imageRequest = (RequestImagePacket)Pack;
  8424. //handlerTextureRequest = null;
  8425. for (int i = 0; i < imageRequest.RequestImage.Length; i++)
  8426. {
  8427. TextureRequestArgs args = new();
  8428. RequestImagePacket.RequestImageBlock block = imageRequest.RequestImage[i];
  8429. args.RequestedAssetID = block.Image;
  8430. args.DiscardLevel = block.DiscardLevel;
  8431. args.PacketNumber = block.Packet;
  8432. args.Priority = block.DownloadPriority;
  8433. args.requestSequence = imageRequest.Header.Sequence;
  8434. // NOTE: This is not a built in part of the LLUDP protocol, but we double the
  8435. // priority of avatar textures to get avatars rezzing in faster than the
  8436. // surrounding scene
  8437. if ((ImageType)block.Type == ImageType.Baked)
  8438. args.Priority *= 2.0f;
  8439. c.ImageManager.EnqueueReq(args);
  8440. }
  8441. }
  8442. /// <summary>
  8443. /// This is the entry point for the UDP route by which the client can retrieve asset data. If the request
  8444. /// is successful then a TransferInfo packet will be sent back, followed by one or more TransferPackets
  8445. /// </summary>
  8446. /// <param name="sender"></param>
  8447. /// <param name="Pack"></param>
  8448. /// <returns>This parameter may be ignored since we appear to return true whatever happens</returns>
  8449. private static void HandleTransferRequest(LLClientView c, Packet Pack)
  8450. {
  8451. //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
  8452. TransferRequestPacket transfer = (TransferRequestPacket)Pack;
  8453. UUID taskID = UUID.Zero;
  8454. if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
  8455. {
  8456. if (!c.m_scene.Permissions.BypassPermissions())
  8457. {
  8458. // We're spawning a thread because the permissions check can block this thread
  8459. Util.FireAndForget(delegate
  8460. {
  8461. // This requests the asset if needed
  8462. c.HandleSimInventoryTransferRequestWithPermsCheck(c, transfer);
  8463. }, null, "LLClientView.HandleTransferRequest");
  8464. return;
  8465. }
  8466. }
  8467. else if (transfer.TransferInfo.SourceType == (int)SourceType.SimEstate)
  8468. {
  8469. //TransferRequestPacket does not include covenant uuid?
  8470. //get scene covenant uuid
  8471. taskID = c.m_scene.RegionInfo.RegionSettings.Covenant;
  8472. }
  8473. // This is non-blocking
  8474. c.MakeAssetRequest(transfer, taskID);
  8475. }
  8476. private void HandleSimInventoryTransferRequestWithPermsCheck(IClientAPI sender, TransferRequestPacket transfer)
  8477. {
  8478. UUID taskID = new(transfer.TransferInfo.Params, 48);
  8479. UUID itemID = new(transfer.TransferInfo.Params, 64);
  8480. UUID requestID = new(transfer.TransferInfo.Params, 80);
  8481. //m_log.DebugFormat(
  8482. // "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}",
  8483. // requestID, itemID, taskID, Name);
  8484. //m_log.Debug("Transfer Request: " + transfer.ToString());
  8485. // Validate inventory transfers
  8486. // Has to be done here, because AssetCache can't do it
  8487. //
  8488. if (!taskID.IsZero()) // Prim
  8489. {
  8490. SceneObjectPart part = m_scene.GetSceneObjectPart(taskID);
  8491. if (part is null)
  8492. {
  8493. m_log.WarnFormat(
  8494. "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist",
  8495. Name, requestID, itemID, taskID);
  8496. return;
  8497. }
  8498. TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID);
  8499. if (tii is null)
  8500. {
  8501. m_log.WarnFormat(
  8502. "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist",
  8503. Name, requestID, itemID, taskID);
  8504. return;
  8505. }
  8506. if (tii.Type == (int)AssetType.LSLText)
  8507. {
  8508. if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, m_agentId))
  8509. return;
  8510. }
  8511. else if (tii.Type == (int)AssetType.Notecard)
  8512. {
  8513. if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, m_agentId))
  8514. return;
  8515. }
  8516. else
  8517. {
  8518. // TODO: Change this code to allow items other than notecards and scripts to be successfully
  8519. // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule
  8520. if (part.OwnerID != m_agentId)
  8521. {
  8522. m_log.WarnFormat(
  8523. "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}",
  8524. Name, requestID, itemID, taskID, part.OwnerID);
  8525. return;
  8526. }
  8527. if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
  8528. {
  8529. m_log.WarnFormat(
  8530. "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set",
  8531. Name, requestID, itemID, taskID);
  8532. return;
  8533. }
  8534. if (tii.OwnerID != m_agentId)
  8535. {
  8536. m_log.WarnFormat(
  8537. "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}",
  8538. Name, requestID, itemID, taskID, tii.OwnerID);
  8539. return;
  8540. }
  8541. if ((
  8542. tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
  8543. != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
  8544. {
  8545. m_log.WarnFormat(
  8546. "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer",
  8547. Name, requestID, itemID, taskID);
  8548. return;
  8549. }
  8550. if (tii.AssetID != requestID)
  8551. {
  8552. m_log.WarnFormat(
  8553. "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}",
  8554. Name, requestID, itemID, taskID, tii.AssetID);
  8555. return;
  8556. }
  8557. }
  8558. }
  8559. else // Agent
  8560. {
  8561. IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
  8562. if (invAccess != null)
  8563. {
  8564. if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID))
  8565. return;
  8566. }
  8567. else
  8568. {
  8569. return;
  8570. }
  8571. }
  8572. // Permissions out of the way, let's request the asset
  8573. MakeAssetRequest(transfer, taskID);
  8574. }
  8575. private static void HandleAssetUploadRequest(LLClientView c, Packet Pack)
  8576. {
  8577. AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
  8578. // m_log.Debug("upload request " + request.ToString());
  8579. // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString());
  8580. UUID temp = UUID.Combine(request.AssetBlock.TransactionID, c.SecureSessionId);
  8581. c.OnAssetUploadRequest?.Invoke(c, temp,
  8582. request.AssetBlock.TransactionID, request.AssetBlock.Type,
  8583. request.AssetBlock.AssetData, request.AssetBlock.StoreLocal,
  8584. request.AssetBlock.Tempfile);
  8585. }
  8586. private static void HandleRequestXfer(LLClientView c, Packet Pack)
  8587. {
  8588. RequestXferPacket xferReq = (RequestXferPacket)Pack;
  8589. c.OnRequestXfer?.Invoke(c, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename));
  8590. }
  8591. private static void HandleSendXferPacket(LLClientView c, Packet Pack)
  8592. {
  8593. SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack;
  8594. c.OnXferReceive?.Invoke(c, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data);
  8595. }
  8596. private static void HandleConfirmXferPacket(LLClientView c, Packet Pack)
  8597. {
  8598. ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack;
  8599. c.OnConfirmXfer?.Invoke(c, confirmXfer.XferID.ID, confirmXfer.XferID.Packet);
  8600. }
  8601. private static void HandleAbortXfer(LLClientView c, Packet Pack)
  8602. {
  8603. AbortXferPacket abortXfer = (AbortXferPacket)Pack;
  8604. c.OnAbortXfer?.Invoke(c, abortXfer.XferID.ID);
  8605. }
  8606. private static void HandleCreateInventoryFolder(LLClientView c, Packet Pack)
  8607. {
  8608. CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack;
  8609. c.OnCreateNewInventoryFolder?.Invoke(c, invFolder.FolderData.FolderID,
  8610. (ushort)invFolder.FolderData.Type,
  8611. Util.FieldToString(invFolder.FolderData.Name),
  8612. invFolder.FolderData.ParentID);
  8613. }
  8614. private static void HandleUpdateInventoryFolder(LLClientView c, Packet Pack)
  8615. {
  8616. if (c.OnUpdateInventoryFolder is null)
  8617. return;
  8618. UpdateInventoryFolderPacket invFolderx = (UpdateInventoryFolderPacket)Pack;
  8619. if (invFolderx.AgentData.SessionID.NotEqual(c.m_sessionId) || invFolderx.AgentData.AgentID.NotEqual(c.m_agentId))
  8620. return;
  8621. for (int i = 0; i < invFolderx.FolderData.Length; i++)
  8622. {
  8623. c.OnUpdateInventoryFolder?.Invoke(c, invFolderx.FolderData[i].FolderID,
  8624. (ushort)invFolderx.FolderData[i].Type,
  8625. Util.FieldToString(invFolderx.FolderData[i].Name),
  8626. invFolderx.FolderData[i].ParentID);
  8627. }
  8628. }
  8629. private static void HandleMoveInventoryFolder(LLClientView c, Packet Pack)
  8630. {
  8631. if (c.OnMoveInventoryFolder is null)
  8632. return;
  8633. MoveInventoryFolderPacket invFoldery = (MoveInventoryFolderPacket)Pack;
  8634. for (int i = 0; i < invFoldery.InventoryData.Length; i++)
  8635. {
  8636. c.OnMoveInventoryFolder?.Invoke(c, invFoldery.InventoryData[i].FolderID,
  8637. invFoldery.InventoryData[i].ParentID);
  8638. }
  8639. }
  8640. private static void HandleCreateInventoryItem(LLClientView c, Packet Pack)
  8641. {
  8642. CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack;
  8643. if (createItem.AgentData.SessionID.NotEqual(c.m_sessionId) || createItem.AgentData.AgentID.NotEqual(c.m_agentId))
  8644. return;
  8645. c.OnCreateNewInventoryItem?.Invoke(c, createItem.InventoryBlock.TransactionID,
  8646. createItem.InventoryBlock.FolderID,
  8647. createItem.InventoryBlock.CallbackID,
  8648. Util.FieldToString(createItem.InventoryBlock.Description),
  8649. Util.FieldToString(createItem.InventoryBlock.Name),
  8650. createItem.InventoryBlock.InvType,
  8651. createItem.InventoryBlock.Type,
  8652. createItem.InventoryBlock.WearableType,
  8653. createItem.InventoryBlock.NextOwnerMask,
  8654. Util.UnixTimeSinceEpoch());
  8655. }
  8656. private static void HandleLinkInventoryItem(LLClientView c, Packet Pack)
  8657. {
  8658. LinkInventoryItemPacket createLink = (LinkInventoryItemPacket)Pack;
  8659. c.OnLinkInventoryItem?.Invoke(
  8660. c,
  8661. createLink.InventoryBlock.TransactionID,
  8662. createLink.InventoryBlock.FolderID,
  8663. createLink.InventoryBlock.CallbackID,
  8664. Util.FieldToString(createLink.InventoryBlock.Description),
  8665. Util.FieldToString(createLink.InventoryBlock.Name),
  8666. createLink.InventoryBlock.InvType,
  8667. createLink.InventoryBlock.Type,
  8668. createLink.InventoryBlock.OldItemID);
  8669. }
  8670. private static void HandleFetchInventory(LLClientView c, Packet Pack)
  8671. {
  8672. if (c.OnFetchInventory is null)
  8673. return;
  8674. FetchInventoryPacket FetchInventoryx = (FetchInventoryPacket)Pack;
  8675. FetchInventoryPacket.InventoryDataBlock[] data = FetchInventoryx.InventoryData;
  8676. UUID[] items = new UUID[data.Length];
  8677. UUID[] owners = new UUID[data.Length];
  8678. for (int i = 0; i < data.Length; ++i)
  8679. {
  8680. items[i] =data[i].ItemID;
  8681. owners[i] = data[i].OwnerID;
  8682. }
  8683. c.OnFetchInventory?.Invoke(c, items, owners);
  8684. }
  8685. private static void HandleFetchInventoryDescendents(LLClientView c, Packet Pack)
  8686. {
  8687. FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack;
  8688. FetchInventoryDescendentsPacket.InventoryDataBlock data = Fetch.InventoryData;
  8689. c.OnFetchInventoryDescendents?.Invoke(c, data.FolderID, data.OwnerID,
  8690. data.FetchFolders, data.FetchItems,
  8691. data.SortOrder);
  8692. }
  8693. private static void HandlePurgeInventoryDescendents(LLClientView c, Packet Pack)
  8694. {
  8695. PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack;
  8696. c.OnPurgeInventoryDescendents?.Invoke(c, Purge.InventoryData.FolderID);
  8697. }
  8698. private static void HandleUpdateInventoryItem(LLClientView c, Packet Pack)
  8699. {
  8700. if (c.OnUpdateInventoryItem is null)
  8701. return;
  8702. UpdateInventoryItemPacket inventoryItemUpdate = (UpdateInventoryItemPacket)Pack;
  8703. for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++)
  8704. {
  8705. InventoryItemBase itemUpd = new()
  8706. {
  8707. ID = inventoryItemUpdate.InventoryData[i].ItemID,
  8708. Name = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name),
  8709. Description = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description),
  8710. GroupID = inventoryItemUpdate.InventoryData[i].GroupID,
  8711. GroupOwned = inventoryItemUpdate.InventoryData[i].GroupOwned,
  8712. GroupPermissions = inventoryItemUpdate.InventoryData[i].GroupMask,
  8713. NextPermissions = inventoryItemUpdate.InventoryData[i].NextOwnerMask,
  8714. EveryOnePermissions = inventoryItemUpdate.InventoryData[i].EveryoneMask,
  8715. CreationDate = inventoryItemUpdate.InventoryData[i].CreationDate,
  8716. Folder = inventoryItemUpdate.InventoryData[i].FolderID,
  8717. InvType = inventoryItemUpdate.InventoryData[i].InvType,
  8718. SalePrice = inventoryItemUpdate.InventoryData[i].SalePrice,
  8719. SaleType = inventoryItemUpdate.InventoryData[i].SaleType,
  8720. Flags = inventoryItemUpdate.InventoryData[i].Flags
  8721. };
  8722. c.OnUpdateInventoryItem?.Invoke(c, inventoryItemUpdate.InventoryData[i].TransactionID,
  8723. inventoryItemUpdate.InventoryData[i].ItemID,
  8724. itemUpd);
  8725. }
  8726. }
  8727. private static void HandleCopyInventoryItem(LLClientView c, Packet Pack)
  8728. {
  8729. if(c.OnCopyInventoryItem is null)
  8730. return;
  8731. CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack;
  8732. foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData)
  8733. {
  8734. c.OnCopyInventoryItem?.Invoke(c, datablock.CallbackID, datablock.OldAgentID,
  8735. datablock.OldItemID, datablock.NewFolderID,
  8736. Util.FieldToString(datablock.NewName));
  8737. }
  8738. }
  8739. private static void HandleMoveInventoryItem(LLClientView c, Packet Pack)
  8740. {
  8741. if (c.OnMoveInventoryItem is null)
  8742. return;
  8743. MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack;
  8744. InventoryItemBase itm = null;
  8745. List<InventoryItemBase> items = new();
  8746. foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData)
  8747. {
  8748. itm = new InventoryItemBase(datablock.ItemID, c.m_agentId)
  8749. {
  8750. Folder = datablock.FolderID,
  8751. Name = Util.FieldToString(datablock.NewName)
  8752. };
  8753. // weird, comes out as empty string
  8754. //m_log.DebugFormat("[XXX] new name: {0}", itm.Name);
  8755. items.Add(itm);
  8756. }
  8757. c.OnMoveInventoryItem?.Invoke(c, items);
  8758. }
  8759. private static void HandleRemoveInventoryItem(LLClientView c, Packet Pack)
  8760. {
  8761. if(c.OnRemoveInventoryItem is null)
  8762. return;
  8763. RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack;
  8764. List<UUID> uuids = new(removeItem.InventoryData.Length);
  8765. foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData)
  8766. {
  8767. uuids.Add(datablock.ItemID);
  8768. }
  8769. c.OnRemoveInventoryItem?.Invoke(c, uuids);
  8770. }
  8771. private static void HandleRemoveInventoryFolder(LLClientView c, Packet Pack)
  8772. {
  8773. if (c.OnRemoveInventoryFolder is null)
  8774. return;
  8775. RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack;
  8776. List<UUID> uuids = new(removeFolder.FolderData.Length);
  8777. foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData)
  8778. {
  8779. uuids.Add(datablock.FolderID);
  8780. }
  8781. c.OnRemoveInventoryFolder?.Invoke(c, uuids);
  8782. }
  8783. private static void HandleRemoveInventoryObjects(LLClientView c, Packet Pack)
  8784. {
  8785. if (c.OnRemoveInventoryFolder is null || c.OnRemoveInventoryItem is null)
  8786. return;
  8787. RemoveInventoryObjectsPacket removeObject = (RemoveInventoryObjectsPacket)Pack;
  8788. List<UUID> uuids = new(removeObject.FolderData.Length);
  8789. foreach (RemoveInventoryObjectsPacket.FolderDataBlock datablock in removeObject.FolderData)
  8790. uuids.Add(datablock.FolderID);
  8791. c.OnRemoveInventoryFolder?.Invoke(c, uuids);
  8792. uuids.Clear();
  8793. foreach (RemoveInventoryObjectsPacket.ItemDataBlock datablock in removeObject.ItemData)
  8794. uuids.Add(datablock.ItemID);
  8795. c.OnRemoveInventoryItem?.Invoke(c, uuids);
  8796. }
  8797. private static void HandleRequestTaskInventory(LLClientView c, Packet Pack)
  8798. {
  8799. RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack;
  8800. c.OnRequestTaskInventory?.Invoke(c, requesttask.InventoryData.LocalID);
  8801. }
  8802. private static void HandleUpdateTaskInventory(LLClientView c, Packet Pack)
  8803. {
  8804. if (c.OnUpdateTaskInventory is null)
  8805. return;
  8806. UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack;
  8807. if (updatetask.UpdateData.Key != 0)
  8808. return; // only do inventory not assets
  8809. TaskInventoryItem newTaskItem = new()
  8810. {
  8811. ItemID = updatetask.InventoryData.ItemID,
  8812. ParentID = updatetask.InventoryData.FolderID,
  8813. CreatorID = updatetask.InventoryData.CreatorID,
  8814. OwnerID = updatetask.InventoryData.OwnerID,
  8815. GroupID = updatetask.InventoryData.GroupID,
  8816. BasePermissions = updatetask.InventoryData.BaseMask,
  8817. CurrentPermissions = updatetask.InventoryData.OwnerMask,
  8818. GroupPermissions = updatetask.InventoryData.GroupMask,
  8819. EveryonePermissions = updatetask.InventoryData.EveryoneMask,
  8820. NextPermissions = updatetask.InventoryData.NextOwnerMask,
  8821. // Unused? Clicking share with group sets GroupPermissions instead, so perhaps this is something
  8822. // different
  8823. //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned,
  8824. Type = updatetask.InventoryData.Type,
  8825. InvType = updatetask.InventoryData.InvType,
  8826. Flags = updatetask.InventoryData.Flags,
  8827. //newTaskItem.SaleType=updatetask.InventoryData.SaleType,
  8828. //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice,
  8829. Name = Util.FieldToString(updatetask.InventoryData.Name),
  8830. Description = Util.FieldToString(updatetask.InventoryData.Description),
  8831. CreationDate = (uint)updatetask.InventoryData.CreationDate
  8832. };
  8833. c.OnUpdateTaskInventory?.Invoke(c, updatetask.InventoryData.TransactionID,
  8834. newTaskItem, updatetask.UpdateData.LocalID);
  8835. }
  8836. private static void HandleRemoveTaskInventory(LLClientView c, Packet Pack)
  8837. {
  8838. RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack;
  8839. c.OnRemoveTaskItem?.Invoke(c, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID);
  8840. }
  8841. private static void HandleMoveTaskInventory(LLClientView c, Packet Pack)
  8842. {
  8843. MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack;
  8844. c.OnMoveTaskItem?.Invoke(
  8845. c, moveTaskInventoryPacket.AgentData.FolderID,
  8846. moveTaskInventoryPacket.InventoryData.LocalID,
  8847. moveTaskInventoryPacket.InventoryData.ItemID);
  8848. }
  8849. private static void HandleRezScript(LLClientView c, Packet Pack)
  8850. {
  8851. if(c.OnRezScript is null)
  8852. return;
  8853. //m_log.Debug(Pack.ToString());
  8854. RezScriptPacket rezScriptx = (RezScriptPacket)Pack;
  8855. if (rezScriptx.AgentData.SessionID.NotEqual(c.m_sessionId) || rezScriptx.AgentData.AgentID.NotEqual(c.m_agentId))
  8856. return;
  8857. InventoryItemBase item = new()
  8858. {
  8859. ID = rezScriptx.InventoryBlock.ItemID,
  8860. Folder = rezScriptx.InventoryBlock.FolderID,
  8861. CreatorId = rezScriptx.InventoryBlock.CreatorID.ToString(),
  8862. Owner = rezScriptx.InventoryBlock.OwnerID,
  8863. BasePermissions = rezScriptx.InventoryBlock.BaseMask,
  8864. CurrentPermissions = rezScriptx.InventoryBlock.OwnerMask,
  8865. EveryOnePermissions = rezScriptx.InventoryBlock.EveryoneMask,
  8866. NextPermissions = rezScriptx.InventoryBlock.NextOwnerMask,
  8867. GroupPermissions = rezScriptx.InventoryBlock.GroupMask,
  8868. GroupOwned = rezScriptx.InventoryBlock.GroupOwned,
  8869. GroupID = rezScriptx.InventoryBlock.GroupID,
  8870. AssetType = rezScriptx.InventoryBlock.Type,
  8871. InvType = rezScriptx.InventoryBlock.InvType,
  8872. Flags = rezScriptx.InventoryBlock.Flags,
  8873. SaleType = rezScriptx.InventoryBlock.SaleType,
  8874. SalePrice = rezScriptx.InventoryBlock.SalePrice,
  8875. Name = Util.FieldToString(rezScriptx.InventoryBlock.Name),
  8876. Description = Util.FieldToString(rezScriptx.InventoryBlock.Description),
  8877. CreationDate = rezScriptx.InventoryBlock.CreationDate
  8878. };
  8879. c.OnRezScript?.Invoke(c, item, rezScriptx.InventoryBlock.TransactionID, rezScriptx.UpdateBlock.ObjectLocalID);
  8880. }
  8881. private static void HandleMapLayerRequest(LLClientView c, Packet Pack)
  8882. {
  8883. c.RequestMapLayer();
  8884. }
  8885. private static void HandleMapBlockRequest(LLClientView c, Packet Pack)
  8886. {
  8887. MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack;
  8888. c.OnRequestMapBlocks?.Invoke(c, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY,
  8889. MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY, MapRequest.AgentData.Flags);
  8890. }
  8891. private static void HandleMapNameRequest(LLClientView c, Packet Pack)
  8892. {
  8893. MapNameRequestPacket map = (MapNameRequestPacket)Pack;
  8894. string mapName = map.NameData.Name.Length == 0 ? c.m_scene.RegionInfo.RegionName :
  8895. Util.UTF8.GetString(map.NameData.Name, 0, map.NameData.Name.Length - 1);
  8896. c.OnMapNameRequest?.Invoke(c, mapName, map.AgentData.Flags);
  8897. }
  8898. private static void HandleTeleportLandmarkRequest(LLClientView c, Packet Pack)
  8899. {
  8900. TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack;
  8901. UUID lmid = tpReq.Info.LandmarkID;
  8902. AssetLandmark lm;
  8903. if (!lmid.IsZero())
  8904. {
  8905. //AssetBase lma = m_assetCache.GetAsset(lmid, false);
  8906. AssetBase lma = c.m_assetService.Get(lmid.ToString());
  8907. if (lma is null)
  8908. {
  8909. // Failed to find landmark
  8910. // Let's try to search in the user's home asset server
  8911. lma = c.FindAssetInUserAssetServer(lmid.ToString());
  8912. if (lma is null)
  8913. {
  8914. // Really doesn't exist
  8915. m_log.WarnFormat("[llClient]: landmark asset {0} not found",lmid.ToString());
  8916. c.SendTeleportFailed("Could not find the landmark asset data");
  8917. return;
  8918. }
  8919. }
  8920. try
  8921. {
  8922. lm = new AssetLandmark(lma);
  8923. }
  8924. catch (NullReferenceException)
  8925. {
  8926. // asset not found generates null ref inside the assetlandmark constructor.
  8927. c.SendTeleportFailed("Could not find the landmark asset data");
  8928. return;
  8929. }
  8930. }
  8931. else
  8932. {
  8933. // Teleport home request
  8934. c.OnTeleportHomeRequest?.Invoke(c.m_agentId, c);
  8935. return;
  8936. }
  8937. c.OnTeleportLandmarkRequest?.Invoke(c, lm);
  8938. }
  8939. private static void HandleTeleportCancel(LLClientView c, Packet Pack)
  8940. {
  8941. TeleportCancelPacket pkt = (TeleportCancelPacket) Pack;
  8942. c.OnTeleportCancel?.Invoke(c);
  8943. }
  8944. private AssetBase FindAssetInUserAssetServer(string id)
  8945. {
  8946. AgentCircuitData aCircuit = ((Scene)Scene).AuthenticateHandler.GetAgentCircuitData(CircuitCode);
  8947. if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
  8948. {
  8949. string assetServer = aCircuit.ServiceURLs["AssetServerURI"].ToString();
  8950. if (!string.IsNullOrEmpty(assetServer))
  8951. return ((Scene)Scene).AssetService.Get(id, assetServer, false);
  8952. }
  8953. return null;
  8954. }
  8955. private static void HandleTeleportLocationRequest(LLClientView c, Packet Pack)
  8956. {
  8957. if(c.OnTeleportLocationRequest is null)
  8958. {
  8959. c.SendTeleportFailed("Could not process the teleport");
  8960. return;
  8961. }
  8962. TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack;
  8963. // Adjust teleport location to base of a larger region if requested to teleport to a sub-region
  8964. Util.RegionHandleToWorldLoc(tpLocReq.Info.RegionHandle, out uint locX, out uint locY);
  8965. RegionInfo ri = c.m_scene.RegionInfo;
  8966. if ((locX >= ri.WorldLocX)
  8967. && (locX < (ri.WorldLocX + ri.RegionSizeX))
  8968. && (locY >= ri.WorldLocY)
  8969. && (locY < (ri.WorldLocY + ri.RegionSizeY)))
  8970. {
  8971. tpLocReq.Info.RegionHandle = ri.RegionHandle;
  8972. tpLocReq.Info.Position.X += locX - ri.WorldLocX;
  8973. tpLocReq.Info.Position.Y += locY - ri.WorldLocY;
  8974. }
  8975. c.OnTeleportLocationRequest?.Invoke(c, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,
  8976. tpLocReq.Info.LookAt, 16);
  8977. }
  8978. #endregion Inventory/Asset/Other related packets
  8979. private static void HandleUUIDNameRequest(LLClientView c, Packet Pack)
  8980. {
  8981. if(c.OnNameFromUUIDRequest is null)
  8982. return;
  8983. ScenePresence sp = (ScenePresence)c.SceneAgent;
  8984. if(sp is null || sp.IsDeleted || (sp.IsInTransit && !sp.IsInLocalTransit))
  8985. return;
  8986. UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack;
  8987. foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock)
  8988. c.OnNameFromUUIDRequest?.Invoke(UUIDBlock.ID, c);
  8989. }
  8990. #region Parcel related packets
  8991. private static void HandleRegionHandleRequest(LLClientView c, Packet Pack)
  8992. {
  8993. RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
  8994. c.OnRegionHandleRequest?.Invoke(c, rhrPack.RequestBlock.RegionID);
  8995. }
  8996. private static void HandleParcelInfoRequest(LLClientView c, Packet Pack)
  8997. {
  8998. if(c.OnParcelInfoRequest is null)
  8999. return;
  9000. ParcelInfoRequestPacket pirPack = (ParcelInfoRequestPacket)Pack;
  9001. c.OnParcelInfoRequest?.Invoke(c, pirPack.Data.ParcelID);
  9002. }
  9003. private static void HandleParcelAccessListRequest(LLClientView c, Packet Pack)
  9004. {
  9005. ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack;
  9006. c.OnParcelAccessListRequest?.Invoke(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID,
  9007. requestPacket.Data.Flags, requestPacket.Data.SequenceID,
  9008. requestPacket.Data.LocalID, c);
  9009. }
  9010. private static void HandleParcelAccessListUpdate(LLClientView c, Packet Pack)
  9011. {
  9012. if(c.OnParcelAccessListUpdateRequest is null)
  9013. return;
  9014. ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack;
  9015. // viewers do send estimated number of packets and sequenceID, but don't seem reliable.
  9016. List<LandAccessEntry> entries = new(updatePacket.List.Length);
  9017. foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List)
  9018. {
  9019. LandAccessEntry entry = new()
  9020. {
  9021. AgentID = block.ID,
  9022. Flags = (AccessList)block.Flags,
  9023. Expires = block.Time
  9024. };
  9025. entries.Add(entry);
  9026. }
  9027. c.OnParcelAccessListUpdateRequest?.Invoke(updatePacket.AgentData.AgentID,
  9028. updatePacket.Data.Flags,
  9029. updatePacket.Data.TransactionID,
  9030. updatePacket.Data.LocalID,
  9031. entries, c);
  9032. }
  9033. private static void HandleParcelPropertiesRequest(LLClientView c, Packet Pack)
  9034. {
  9035. ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack;
  9036. ParcelPropertiesRequestPacket.ParcelDataBlock pdb = propertiesRequest.ParcelData;
  9037. c.OnParcelPropertiesRequest?.Invoke((int)MathF.Round(pdb.West), (int)MathF.Round(pdb.South),
  9038. (int)MathF.Round(pdb.East), (int)MathF.Round(pdb.North),
  9039. pdb.SequenceID, pdb.SnapSelection, c);
  9040. }
  9041. private static void HandleParcelDivide(LLClientView c, Packet Pack)
  9042. {
  9043. ParcelDividePacket landDivide = (ParcelDividePacket)Pack;
  9044. c.OnParcelDivideRequest?.Invoke((int)MathF.Round(landDivide.ParcelData.West),
  9045. (int)MathF.Round(landDivide.ParcelData.South),
  9046. (int)Math.Round(landDivide.ParcelData.East),
  9047. (int)MathF.Round(landDivide.ParcelData.North), c);
  9048. }
  9049. private static void HandleParcelJoin(LLClientView c, Packet Pack)
  9050. {
  9051. ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack;
  9052. c.OnParcelJoinRequest?.Invoke((int)MathF.Round(landJoin.ParcelData.West),
  9053. (int)MathF.Round(landJoin.ParcelData.South),
  9054. (int)MathF.Round(landJoin.ParcelData.East),
  9055. (int)MathF.Round(landJoin.ParcelData.North), c);
  9056. }
  9057. private static void HandleParcelPropertiesUpdate(LLClientView c, Packet Pack)
  9058. {
  9059. if (c.OnParcelPropertiesUpdateRequest is null)
  9060. return;
  9061. ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack;
  9062. if (parcelPropertiesPacket.AgentData.SessionID.NotEqual(c.m_sessionId) || parcelPropertiesPacket.AgentData.AgentID.NotEqual(c.m_agentId))
  9063. return;
  9064. LandUpdateArgs args = new()
  9065. {
  9066. AuthBuyerID = parcelPropertiesPacket.ParcelData.AuthBuyerID,
  9067. Category = (ParcelCategory)parcelPropertiesPacket.ParcelData.Category,
  9068. Desc = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc),
  9069. GroupID = parcelPropertiesPacket.ParcelData.GroupID,
  9070. LandingType = parcelPropertiesPacket.ParcelData.LandingType,
  9071. MediaAutoScale = parcelPropertiesPacket.ParcelData.MediaAutoScale,
  9072. MediaID = parcelPropertiesPacket.ParcelData.MediaID,
  9073. MediaURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL),
  9074. MusicURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL),
  9075. Name = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name),
  9076. ParcelFlags = parcelPropertiesPacket.ParcelData.ParcelFlags,
  9077. PassHours = parcelPropertiesPacket.ParcelData.PassHours,
  9078. PassPrice = parcelPropertiesPacket.ParcelData.PassPrice,
  9079. SalePrice = parcelPropertiesPacket.ParcelData.SalePrice,
  9080. SnapshotID = parcelPropertiesPacket.ParcelData.SnapshotID,
  9081. UserLocation = parcelPropertiesPacket.ParcelData.UserLocation,
  9082. UserLookAt = parcelPropertiesPacket.ParcelData.UserLookAt
  9083. };
  9084. c.OnParcelPropertiesUpdateRequest?.Invoke(args, parcelPropertiesPacket.ParcelData.LocalID, c);
  9085. }
  9086. private static void HandleParcelSelectObjects(LLClientView c, Packet Pack)
  9087. {
  9088. if(c.OnParcelSelectObjects is null)
  9089. return;
  9090. ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack;
  9091. List<UUID> returnIDs = new(selectPacket.ReturnIDs.Length);
  9092. foreach (ParcelSelectObjectsPacket.ReturnIDsBlock rb in selectPacket.ReturnIDs)
  9093. {
  9094. returnIDs.Add(rb.ReturnID);
  9095. }
  9096. c.OnParcelSelectObjects?.Invoke(selectPacket.ParcelData.LocalID,
  9097. Convert.ToInt32(selectPacket.ParcelData.ReturnType), returnIDs, c);
  9098. }
  9099. private static void HandleParcelObjectOwnersRequest(LLClientView c, Packet Pack)
  9100. {
  9101. ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack;
  9102. c.OnParcelObjectOwnerRequest?.Invoke(reqPacket.ParcelData.LocalID, c);
  9103. }
  9104. private static void HandleParcelGodForceOwner(LLClientView c, Packet Pack)
  9105. {
  9106. ParcelGodForceOwnerPacket godForceOwnerPacket = (ParcelGodForceOwnerPacket)Pack;
  9107. c.OnParcelGodForceOwner?.Invoke(godForceOwnerPacket.Data.LocalID, godForceOwnerPacket.Data.OwnerID, c);
  9108. }
  9109. private static void HandleParcelRelease(LLClientView c, Packet Pack)
  9110. {
  9111. ParcelReleasePacket releasePacket = (ParcelReleasePacket)Pack;
  9112. c.OnParcelAbandonRequest?.Invoke(releasePacket.Data.LocalID, c);
  9113. }
  9114. private static void HandleParcelReclaim(LLClientView c, Packet Pack)
  9115. {
  9116. ParcelReclaimPacket reclaimPacket = (ParcelReclaimPacket)Pack;
  9117. c.OnParcelReclaim?.Invoke(reclaimPacket.Data.LocalID, c);
  9118. }
  9119. private static void HandleParcelReturnObjects(LLClientView c, Packet Pack)
  9120. {
  9121. if(c.OnParcelReturnObjectsRequest is null)
  9122. return;
  9123. ParcelReturnObjectsPacket parcelReturnObjects = (ParcelReturnObjectsPacket)Pack;
  9124. UUID[] puserselectedOwnerIDs = new UUID[parcelReturnObjects.OwnerIDs.Length];
  9125. for (int parceliterator = 0; parceliterator < parcelReturnObjects.OwnerIDs.Length; parceliterator++)
  9126. puserselectedOwnerIDs[parceliterator] = parcelReturnObjects.OwnerIDs[parceliterator].OwnerID;
  9127. UUID[] puserselectedTaskIDs = new UUID[parcelReturnObjects.TaskIDs.Length];
  9128. for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++)
  9129. puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID;
  9130. c.OnParcelReturnObjectsRequest?.Invoke(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, c);
  9131. }
  9132. private static void HandleParcelSetOtherCleanTime(LLClientView c, Packet Pack)
  9133. {
  9134. ParcelSetOtherCleanTimePacket parcelSetOtherCleanTimePacket = (ParcelSetOtherCleanTimePacket)Pack;
  9135. c.OnParcelSetOtherCleanTime?.Invoke(c,
  9136. parcelSetOtherCleanTimePacket.ParcelData.LocalID,
  9137. parcelSetOtherCleanTimePacket.ParcelData.OtherCleanTime);
  9138. }
  9139. private static void HandleLandStatRequest(LLClientView c, Packet Pack)
  9140. {
  9141. LandStatRequestPacket lsrp = (LandStatRequestPacket)Pack;
  9142. c.OnLandStatRequest?.Invoke(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Utils.BytesToString(lsrp.RequestData.Filter), c);
  9143. }
  9144. private static void HandleParcelDwellRequest(LLClientView c, Packet Pack)
  9145. {
  9146. ParcelDwellRequestPacket dwellrq = (ParcelDwellRequestPacket)Pack;
  9147. c.OnParcelDwellRequest?.Invoke(dwellrq.Data.LocalID, c);
  9148. }
  9149. #endregion Parcel related packets
  9150. #region Estate Packets
  9151. private static double m_lastMapRegenTime = Double.MinValue;
  9152. private static void HandleEstateOwnerMessage(LLClientView c, Packet Pack)
  9153. {
  9154. EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack;
  9155. string method = Utils.BytesToString(messagePacket.MethodData.Method);
  9156. switch (method)
  9157. {
  9158. case "getinfo":
  9159. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9160. {
  9161. c.OnDetailedEstateDataRequest?.Invoke(c, messagePacket.MethodData.Invoice);
  9162. }
  9163. return;
  9164. case "setregioninfo":
  9165. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9166. {
  9167. c.OnSetEstateFlagsRequest?.Invoke(convertParamStringToBool(messagePacket.ParamList[0].Parameter), convertParamStringToBool(messagePacket.ParamList[1].Parameter),
  9168. convertParamStringToBool(messagePacket.ParamList[2].Parameter), !convertParamStringToBool(messagePacket.ParamList[3].Parameter),
  9169. Convert.ToInt16(Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[4].Parameter), Culture.NumberFormatInfo)),
  9170. (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter), Culture.NumberFormatInfo),
  9171. Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[6].Parameter)),
  9172. convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter));
  9173. }
  9174. return;
  9175. // case "texturebase":
  9176. // if (((Scene)m_scene).Permissions.CanIssueEstateCommand(m_agentId, false))
  9177. // {
  9178. // foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
  9179. // {
  9180. // string s = Utils.BytesToString(block.Parameter);
  9181. // string[] splitField = s.Split(' ');
  9182. // if (splitField.Length == 2)
  9183. // {
  9184. // UUID tempUUID = new UUID(splitField[1]);
  9185. // OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID);
  9186. // }
  9187. // }
  9188. // }
  9189. // break;
  9190. case "texturedetail":
  9191. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9192. {
  9193. foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
  9194. {
  9195. string s = Utils.BytesToString(block.Parameter);
  9196. string[] splitField = s.Split(' ');
  9197. if (splitField.Length == 2)
  9198. {
  9199. Int16 corner = Convert.ToInt16(splitField[0]);
  9200. UUID textureUUID = new(splitField[1]);
  9201. c.OnSetEstateTerrainDetailTexture?.Invoke(c, corner, textureUUID);
  9202. }
  9203. }
  9204. }
  9205. return;
  9206. case "textureheights":
  9207. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9208. {
  9209. foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
  9210. {
  9211. string s = Utils.BytesToString(block.Parameter);
  9212. string[] splitField = s.Split(' ');
  9213. if (splitField.Length == 3)
  9214. {
  9215. Int16 corner = Convert.ToInt16(splitField[0]);
  9216. float lowValue = Convert.ToSingle(splitField[1], Culture.NumberFormatInfo);
  9217. float highValue = Convert.ToSingle(splitField[2], Culture.NumberFormatInfo);
  9218. c.OnSetEstateTerrainTextureHeights?.Invoke(c, corner, lowValue, highValue);
  9219. }
  9220. }
  9221. }
  9222. return;
  9223. case "texturecommit":
  9224. c.OnCommitEstateTerrainTextureRequest?.Invoke(c);
  9225. return;
  9226. case "setregionterrain":
  9227. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9228. {
  9229. if (messagePacket.ParamList.Length != 9)
  9230. {
  9231. m_log.Error("EstateOwnerMessage: SetRegionTerrain method has a ParamList of invalid length");
  9232. }
  9233. else
  9234. {
  9235. try
  9236. {
  9237. float WaterHeight = Convert.ToSingle(Utils.BytesToString(messagePacket.ParamList[0].Parameter), Culture.NumberFormatInfo);
  9238. float TerrainRaiseLimit = Convert.ToSingle(Utils.BytesToString(messagePacket.ParamList[1].Parameter), Culture.NumberFormatInfo);
  9239. float TerrainLowerLimit = Convert.ToSingle(Utils.BytesToString(messagePacket.ParamList[2].Parameter), Culture.NumberFormatInfo);
  9240. bool UseEstateSun = convertParamStringToBool(messagePacket.ParamList[3].Parameter);
  9241. bool UseFixedSun = convertParamStringToBool(messagePacket.ParamList[4].Parameter);
  9242. float SunHour = Convert.ToSingle(Utils.BytesToString(messagePacket.ParamList[5].Parameter), Culture.NumberFormatInfo);
  9243. bool UseGlobal = convertParamStringToBool(messagePacket.ParamList[6].Parameter);
  9244. bool EstateFixedSun = convertParamStringToBool(messagePacket.ParamList[7].Parameter);
  9245. float EstateSunHour = Convert.ToSingle(Utils.BytesToString(messagePacket.ParamList[8].Parameter), Culture.NumberFormatInfo);
  9246. c.OnSetRegionTerrainSettings?.Invoke(WaterHeight, TerrainRaiseLimit, TerrainLowerLimit, UseEstateSun, UseFixedSun, SunHour, UseGlobal, EstateFixedSun, EstateSunHour);
  9247. }
  9248. catch (Exception ex)
  9249. {
  9250. m_log.Error("EstateOwnerMessage: Exception while setting terrain settings: \n" + messagePacket + "\n" + ex);
  9251. }
  9252. }
  9253. }
  9254. return;
  9255. case "restart":
  9256. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9257. {
  9258. // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart.
  9259. foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
  9260. {
  9261. if(Utils.TryParseSingle(Utils.BytesToString(block.Parameter), out float timeSeconds))
  9262. c.OnEstateRestartSimRequest?.Invoke(c, (int)timeSeconds);
  9263. }
  9264. }
  9265. return;
  9266. case "estatechangecovenantid":
  9267. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9268. {
  9269. foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
  9270. {
  9271. UUID newCovenantID = new(Utils.BytesToString(block.Parameter));
  9272. c.OnEstateChangeCovenantRequest?.Invoke(c, newCovenantID);
  9273. }
  9274. }
  9275. return;
  9276. case "estateaccessdelta": // Estate access delta manages the banlist and allow list too.
  9277. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9278. {
  9279. int estateAccessType = Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[1].Parameter));
  9280. c.OnUpdateEstateAccessDeltaRequest?.Invoke(c, messagePacket.MethodData.Invoice, estateAccessType, new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)));
  9281. }
  9282. return;
  9283. case "simulatormessage":
  9284. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9285. {
  9286. UUID SenderID = new(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
  9287. string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter);
  9288. string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter);
  9289. c.OnSimulatorBlueBoxMessageRequest?.Invoke(c, messagePacket.MethodData.Invoice,
  9290. SenderID, messagePacket.AgentData.SessionID, SenderName, Message);
  9291. }
  9292. return;
  9293. case "instantmessage":
  9294. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9295. {
  9296. if (messagePacket.ParamList.Length < 2)
  9297. return;
  9298. UUID SenderID;
  9299. string SenderName;
  9300. string Message;
  9301. if (messagePacket.ParamList.Length < 5)
  9302. {
  9303. SenderID = c.m_agentId;
  9304. SenderName = Utils.BytesToString(messagePacket.ParamList[0].Parameter);
  9305. Message = Utils.BytesToString(messagePacket.ParamList[1].Parameter);
  9306. }
  9307. else
  9308. {
  9309. SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
  9310. SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter);
  9311. Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter);
  9312. }
  9313. c.OnEstateBlueBoxMessageRequest?.Invoke(c, messagePacket.MethodData.Invoice,
  9314. SenderID, c.m_sessionId, SenderName, Message);
  9315. }
  9316. return;
  9317. case "setregiondebug":
  9318. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9319. {
  9320. if(c.OnEstateDebugRegionRequest is not null)
  9321. {
  9322. bool scripted = convertParamStringToBool(messagePacket.ParamList[0].Parameter);
  9323. bool collisionEvents = convertParamStringToBool(messagePacket.ParamList[1].Parameter);
  9324. bool physics = convertParamStringToBool(messagePacket.ParamList[2].Parameter);
  9325. c.OnEstateDebugRegionRequest?.Invoke(c, messagePacket.MethodData.Invoice,
  9326. c.m_agentId, scripted, collisionEvents, physics);
  9327. }
  9328. }
  9329. return;
  9330. case "teleporthomeuser":
  9331. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9332. {
  9333. if(UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out UUID Prey))
  9334. c.OnEstateTeleportOneUserHomeRequest?.Invoke(c, messagePacket.MethodData.Invoice, c.m_agentId, Prey, false);
  9335. }
  9336. return;
  9337. case "teleporthomeallusers":
  9338. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9339. {
  9340. c.OnEstateTeleportAllUsersHomeRequest?.Invoke(c, messagePacket.MethodData.Invoice, c.m_agentId);
  9341. }
  9342. return;
  9343. case "colliders":
  9344. c.OnLandStatRequest?.Invoke(0, 1, 0, "", c);
  9345. return;
  9346. case "scripts":
  9347. c.OnLandStatRequest?.Invoke(0, 0, 0, "", c);
  9348. return;
  9349. case "terrain":
  9350. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9351. {
  9352. if (messagePacket.ParamList.Length > 0)
  9353. {
  9354. string p0 = Utils.BytesToString(messagePacket.ParamList[0].Parameter);
  9355. switch(p0)
  9356. {
  9357. case "bake":
  9358. c.OnBakeTerrain?.Invoke(c);
  9359. break;
  9360. case "download filename":
  9361. if (messagePacket.ParamList.Length > 1)
  9362. c.OnRequestTerrain?.Invoke(c, Utils.BytesToString(messagePacket.ParamList[1].Parameter));
  9363. break;
  9364. case "upload filename":
  9365. if (messagePacket.ParamList.Length > 1)
  9366. c.OnUploadTerrain?.Invoke(c, Utils.BytesToString(messagePacket.ParamList[1].Parameter));
  9367. break;
  9368. default:
  9369. break;
  9370. }
  9371. }
  9372. }
  9373. return;
  9374. case "estatechangeinfo":
  9375. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9376. {
  9377. UInt32 param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter));
  9378. UInt32 param2 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
  9379. c.OnEstateChangeInfo?.Invoke(c, messagePacket.MethodData.Invoice, c.m_agentId, param1, param2);
  9380. }
  9381. return;
  9382. case "telehub":
  9383. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9384. {
  9385. UInt32 param1 = 0u;
  9386. string command = Utils.BytesToString(messagePacket.ParamList[0].Parameter);
  9387. if (command != "info ui")
  9388. {
  9389. try
  9390. {
  9391. param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter));
  9392. }
  9393. catch {}
  9394. }
  9395. c.OnEstateManageTelehub?.Invoke(c, messagePacket.MethodData.Invoice, messagePacket.AgentData.AgentID, command, param1);
  9396. }
  9397. return;
  9398. case "refreshmapvisibility":
  9399. if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9400. {
  9401. IWorldMapModule mapModule = c.m_scene.RequestModuleInterface<IWorldMapModule>();
  9402. if (mapModule is null)
  9403. {
  9404. c.SendAlertMessage("Terrain map generator not avaiable");
  9405. return;
  9406. }
  9407. if (m_lastMapRegenTime == Double.MaxValue)
  9408. {
  9409. c.SendAlertMessage("Terrain map generation still in progress");
  9410. return;
  9411. }
  9412. double now = Util.GetTimeStamp();
  9413. if (now - m_lastMapRegenTime < 120) // 2 minutes global cool down
  9414. {
  9415. c.SendAlertMessage("Please wait at least 2 minutes between map generation commands");
  9416. return;
  9417. }
  9418. m_lastMapRegenTime = Double.MaxValue;
  9419. c.m_scene.RegenerateMaptileAndReregister(c, null);
  9420. c.SendAlertMessage("Terrain map generated");
  9421. m_lastMapRegenTime = now;
  9422. }
  9423. return;
  9424. case "kickestate":
  9425. if(c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
  9426. {
  9427. if(UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[0].Parameter), out UUID Prey))
  9428. c.OnEstateTeleportOneUserHomeRequest?.Invoke(c, messagePacket.MethodData.Invoice,
  9429. c.m_agentId, Prey, true);
  9430. }
  9431. return;
  9432. default:
  9433. m_log.WarnFormat(
  9434. "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}",
  9435. method, c.Name, c.m_scene.Name);
  9436. for (int i = 0; i < messagePacket.ParamList.Length; i++)
  9437. {
  9438. EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i];
  9439. string data = (string)Utils.BytesToString(block.Parameter);
  9440. m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data);
  9441. }
  9442. return;
  9443. }
  9444. //int parcelID, uint reportType, uint requestflags, string filter
  9445. //lsrp.RequestData.ParcelLocalID;
  9446. //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts
  9447. //lsrp.RequestData.RequestFlags;
  9448. //lsrp.RequestData.Filter;
  9449. }
  9450. private static void HandleRequestRegionInfo(LLClientView c, Packet Pack)
  9451. {
  9452. RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData;
  9453. c.OnRegionInfoRequest?.Invoke(c);
  9454. }
  9455. private static void HandleEstateCovenantRequest(LLClientView c, Packet Pack)
  9456. {
  9457. EstateCovenantRequestPacket.AgentDataBlock epack = ((EstateCovenantRequestPacket)Pack).AgentData;
  9458. c.OnEstateCovenantRequest?.Invoke(c);
  9459. }
  9460. #endregion Estate Packets
  9461. #region GodPackets
  9462. private static void HandleRequestGodlikePowers(LLClientView c, Packet Pack)
  9463. {
  9464. RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack;
  9465. RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData;
  9466. if (ablock.SessionID.NotEqual(c.m_sessionId) || ablock.AgentID.NotEqual(c.m_agentId))
  9467. return;
  9468. RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock;
  9469. UUID token = rblock.Token;
  9470. c.OnRequestGodlikePowers?.Invoke(ablock.AgentID, ablock.SessionID, token, rblock.Godlike);
  9471. }
  9472. private static void HandleGodUpdateRegionInfoUpdate(LLClientView c, Packet packet)
  9473. {
  9474. GodUpdateRegionInfoPacket GodUpdateRegionInfo = (GodUpdateRegionInfoPacket)packet;
  9475. if (GodUpdateRegionInfo.AgentData.SessionID.NotEqual(c.m_sessionId) || GodUpdateRegionInfo.AgentData.AgentID.NotEqual(c.m_agentId))
  9476. return;
  9477. c.OnGodUpdateRegionInfoUpdate?.Invoke(c,
  9478. GodUpdateRegionInfo.RegionInfo.BillableFactor,
  9479. GodUpdateRegionInfo.RegionInfo.EstateID,
  9480. GodUpdateRegionInfo.RegionInfo.RegionFlags,
  9481. GodUpdateRegionInfo.RegionInfo.SimName,
  9482. GodUpdateRegionInfo.RegionInfo.RedirectGridX,
  9483. GodUpdateRegionInfo.RegionInfo.RedirectGridY);
  9484. }
  9485. private static void HandleSimWideDeletes(LLClientView c, Packet packet)
  9486. {
  9487. SimWideDeletesPacket SimWideDeletesRequest = (SimWideDeletesPacket)packet;
  9488. c.OnSimWideDeletes?.Invoke(c, SimWideDeletesRequest.AgentData.AgentID,(int)SimWideDeletesRequest.DataBlock.Flags,
  9489. SimWideDeletesRequest.DataBlock.TargetID);
  9490. }
  9491. private static void HandleGodlikeMessage(LLClientView c, Packet packet)
  9492. {
  9493. GodlikeMessagePacket GodlikeMessage = (GodlikeMessagePacket)packet;
  9494. c.onGodlikeMessage?.Invoke(c,
  9495. GodlikeMessage.MethodData.Invoice,
  9496. GodlikeMessage.MethodData.Method,
  9497. GodlikeMessage.ParamList[0].Parameter);
  9498. }
  9499. private static void HandleSaveStatePacket(LLClientView c, Packet packet)
  9500. {
  9501. StateSavePacket SaveStateMessage = (StateSavePacket)packet;
  9502. c.OnSaveState?.Invoke(c, SaveStateMessage.AgentData.AgentID);
  9503. }
  9504. private static void HandleGodKickUser(LLClientView c, Packet Pack)
  9505. {
  9506. GodKickUserPacket gkupack = (GodKickUserPacket)Pack;
  9507. c.OnGodKickUser?.Invoke(gkupack.UserInfo.GodID, gkupack.UserInfo.AgentID, gkupack.UserInfo.KickFlags, gkupack.UserInfo.Reason);
  9508. }
  9509. #endregion GodPackets
  9510. #region Economy/Transaction Packets
  9511. private static void HandleMoneyBalanceRequest(LLClientView c, Packet Pack)
  9512. {
  9513. MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack;
  9514. c.OnMoneyBalanceRequest?.Invoke(c, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID);
  9515. }
  9516. private static void HandleEconomyDataRequest(LLClientView c, Packet _)
  9517. {
  9518. c.OnEconomyDataRequest?.Invoke(c);
  9519. }
  9520. private static void HandleRequestPayPrice(LLClientView c, Packet Pack)
  9521. {
  9522. RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack;
  9523. c.OnRequestPayPrice?.Invoke(c, requestPayPricePacket.ObjectData.ObjectID);
  9524. }
  9525. private static void HandleObjectSaleInfo(LLClientView c, Packet Pack)
  9526. {
  9527. if(c.OnObjectSaleInfo is null)
  9528. return;
  9529. ObjectSaleInfoPacket objectSaleInfoPacket = (ObjectSaleInfoPacket)Pack;
  9530. foreach (ObjectSaleInfoPacket.ObjectDataBlock d in objectSaleInfoPacket.ObjectData)
  9531. {
  9532. c.OnObjectSaleInfo?.Invoke(c,
  9533. c.m_agentId,
  9534. c.SessionId,
  9535. d.LocalID,
  9536. d.SaleType,
  9537. d.SalePrice);
  9538. }
  9539. }
  9540. private static void HandleObjectBuy(LLClientView c, Packet Pack)
  9541. {
  9542. if(c.OnObjectBuy is null)
  9543. return;
  9544. ObjectBuyPacket objectBuyPacket = (ObjectBuyPacket)Pack;
  9545. foreach (ObjectBuyPacket.ObjectDataBlock d in objectBuyPacket.ObjectData)
  9546. {
  9547. c.OnObjectBuy?.Invoke(c,
  9548. objectBuyPacket.AgentData.AgentID,
  9549. objectBuyPacket.AgentData.SessionID,
  9550. objectBuyPacket.AgentData.GroupID,
  9551. objectBuyPacket.AgentData.CategoryID,
  9552. d.ObjectLocalID,
  9553. d.SaleType,
  9554. d.SalePrice);
  9555. }
  9556. }
  9557. #endregion Economy/Transaction Packets
  9558. #region Script Packets
  9559. private static void HandleGetScriptRunning(LLClientView c, Packet Pack)
  9560. {
  9561. GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack;
  9562. c.OnGetScriptRunning?.Invoke(c, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID);
  9563. }
  9564. private static void HandleSetScriptRunning(LLClientView c, Packet Pack)
  9565. {
  9566. SetScriptRunningPacket setScriptRunning = (SetScriptRunningPacket)Pack;
  9567. c.OnSetScriptRunning?.Invoke(c, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running);
  9568. }
  9569. private static void HandleScriptReset(LLClientView c, Packet Pack)
  9570. {
  9571. ScriptResetPacket scriptResetPacket = (ScriptResetPacket)Pack;
  9572. c.OnScriptReset?.Invoke(c, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID);
  9573. }
  9574. #endregion Script Packets
  9575. #region Gesture Managment
  9576. private static void HandleActivateGestures(LLClientView c, Packet Pack)
  9577. {
  9578. if(c.OnActivateGesture is null)
  9579. return;
  9580. ActivateGesturesPacket activateGesturePacket = (ActivateGesturesPacket)Pack;
  9581. ActivateGesturesPacket.DataBlock[] data = activateGesturePacket.Data;
  9582. for (int i= 0; i < data.Length; ++i)
  9583. {
  9584. c.OnActivateGesture?.Invoke(c,
  9585. data[i].AssetID,
  9586. data[i].ItemID);
  9587. }
  9588. }
  9589. private static void HandleDeactivateGestures(LLClientView c, Packet Pack)
  9590. {
  9591. if(c.OnDeactivateGesture is null)
  9592. return;
  9593. DeactivateGesturesPacket deactivateGesturePacket = (DeactivateGesturesPacket)Pack;
  9594. DeactivateGesturesPacket.DataBlock[] data = deactivateGesturePacket.Data;
  9595. for (int i = 0; i < data.Length; ++i)
  9596. {
  9597. c.OnDeactivateGesture?.Invoke(c, data[i].ItemID);
  9598. }
  9599. }
  9600. #endregion Gesture Managment
  9601. private static void HandleObjectOwner(LLClientView c, Packet Pack)
  9602. {
  9603. if (c.OnObjectOwner is null)
  9604. return;
  9605. ObjectOwnerPacket objectOwnerPacket = (ObjectOwnerPacket)Pack;
  9606. List<uint> localIDs = new();
  9607. foreach (ObjectOwnerPacket.ObjectDataBlock d in objectOwnerPacket.ObjectData)
  9608. localIDs.Add(d.ObjectLocalID);
  9609. c.OnObjectOwner?.Invoke(c, objectOwnerPacket.HeaderData.OwnerID, objectOwnerPacket.HeaderData.GroupID, localIDs);
  9610. }
  9611. private static void HandleAgentFOV(LLClientView c, Packet Pack)
  9612. {
  9613. AgentFOVPacket fovPacket = (AgentFOVPacket)Pack;
  9614. uint genCounter = fovPacket.FOVBlock.GenCounter;
  9615. if (genCounter == 0 || genCounter > c.m_agentFOVCounter)
  9616. {
  9617. c.m_agentFOVCounter = genCounter;
  9618. c.FOV = fovPacket.FOVBlock.VerticalAngle;
  9619. c.OnAgentFOV?.Invoke(c, c.FOV);
  9620. }
  9621. }
  9622. #region unimplemented handlers
  9623. private static void HandleViewerStats(LLClientView c, Packet Pack)
  9624. {
  9625. // TODO: handle this packet
  9626. //m_log.Warn("[CLIENT]: unhandled ViewerStats packet");
  9627. }
  9628. private static void HandleMapItemRequest(LLClientView c, Packet Pack)
  9629. {
  9630. MapItemRequestPacket mirpk = (MapItemRequestPacket)Pack;
  9631. //m_log.Debug(mirpk.ToString());
  9632. try
  9633. {
  9634. c.OnMapItemRequest?.Invoke(c, mirpk.AgentData.Flags, mirpk.AgentData.EstateID,
  9635. mirpk.AgentData.Godlike, mirpk.RequestData.ItemType,
  9636. mirpk.RequestData.RegionHandle);
  9637. }
  9638. catch( Exception e)
  9639. {
  9640. m_log.ErrorFormat("{0} HandleMapItemRequest exception: {1} : {2}", LogHeader, e.Message, e.StackTrace);
  9641. }
  9642. }
  9643. private static void HandleTransferAbort(LLClientView c, Packet Pack)
  9644. {
  9645. }
  9646. private static void HandleMuteListRequest(LLClientView c, Packet Pack)
  9647. {
  9648. MuteListRequestPacket muteListRequest = (MuteListRequestPacket)Pack;
  9649. if (c.OnMuteListRequest != null)
  9650. {
  9651. c.OnMuteListRequest?.Invoke(c, muteListRequest.MuteData.MuteCRC);
  9652. }
  9653. else
  9654. {
  9655. if(muteListRequest.MuteData.MuteCRC == 0)
  9656. c.SendEmpytMuteList();
  9657. else
  9658. c.SendUseCachedMuteList();
  9659. }
  9660. }
  9661. private static void HandleUpdateMuteListEntry(LLClientView c, Packet packet)
  9662. {
  9663. UpdateMuteListEntryPacket UpdateMuteListEntry = (UpdateMuteListEntryPacket)packet;
  9664. c.OnUpdateMuteListEntry?.Invoke(c, UpdateMuteListEntry.MuteData.MuteID,
  9665. Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
  9666. UpdateMuteListEntry.MuteData.MuteType,
  9667. UpdateMuteListEntry.MuteData.MuteFlags);
  9668. }
  9669. private static void HandleRemoveMuteListEntry(LLClientView c, Packet packet)
  9670. {
  9671. RemoveMuteListEntryPacket RemoveMuteListEntry = (RemoveMuteListEntryPacket)packet;
  9672. c.OnRemoveMuteListEntry?.Invoke(c,
  9673. RemoveMuteListEntry.MuteData.MuteID,
  9674. Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
  9675. }
  9676. private static void HandleUserReport(LLClientView c, Packet packet)
  9677. {
  9678. UserReportPacket UserReport = (UserReportPacket)packet;
  9679. c.OnUserReport?.Invoke(c,
  9680. Utils.BytesToString(UserReport.ReportData.AbuseRegionName),
  9681. UserReport.ReportData.AbuserID,
  9682. UserReport.ReportData.Category,
  9683. UserReport.ReportData.CheckFlags,
  9684. Utils.BytesToString(UserReport.ReportData.Details),
  9685. UserReport.ReportData.ObjectID,
  9686. UserReport.ReportData.Position,
  9687. UserReport.ReportData.ReportType,
  9688. UserReport.ReportData.ScreenshotID,
  9689. Utils.BytesToString(UserReport.ReportData.Summary),
  9690. UserReport.AgentData.AgentID);
  9691. }
  9692. private static void HandleSendPostcard(LLClientView c, Packet packet)
  9693. {
  9694. // SendPostcardPacket SendPostcard =
  9695. // (SendPostcardPacket)packet;
  9696. c.OnSendPostcard?.Invoke(c);
  9697. }
  9698. private static void HandleChangeInventoryItemFlags(LLClientView c, Packet packet)
  9699. {
  9700. if(c.OnChangeInventoryItemFlags is null)
  9701. return;
  9702. ChangeInventoryItemFlagsPacket ChangeInventoryItemFlags = (ChangeInventoryItemFlagsPacket)packet;
  9703. foreach(ChangeInventoryItemFlagsPacket.InventoryDataBlock b in ChangeInventoryItemFlags.InventoryData)
  9704. c.OnChangeInventoryItemFlags?.Invoke(c, b.ItemID, b.Flags);
  9705. }
  9706. private static void HandleUseCircuitCode(LLClientView c, Packet Pack)
  9707. {
  9708. /*
  9709. UseCircuitCodePacket uccp = (UseCircuitCodePacket)Pack;
  9710. if(uccp.CircuitCode.ID == m_agentId &&
  9711. uccp.CircuitCode.SessionID.Equals(m_sessionId) &&
  9712. uccp.CircuitCode.Code == m_circuitCode &&
  9713. SceneAgent != null &&
  9714. !((ScenePresence)SceneAgent).IsDeleted
  9715. )
  9716. SendRegionHandshake(); // possible someone returning
  9717. */
  9718. }
  9719. private static void HandleCreateNewOutfitAttachments(LLClientView c, Packet Pack)
  9720. {
  9721. if(c.OnMoveItemsAndLeaveCopy is null)
  9722. return;
  9723. CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
  9724. List<InventoryItemBase> items = new();
  9725. foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
  9726. {
  9727. InventoryItemBase b = new()
  9728. {
  9729. ID = n.OldItemID,
  9730. Folder = n.OldFolderID
  9731. };
  9732. items.Add(b);
  9733. }
  9734. c.OnMoveItemsAndLeaveCopy?.Invoke(c, items, packet.HeaderData.NewFolderID);
  9735. }
  9736. private static void HandleAgentHeightWidth(LLClientView c, Packet Pack)
  9737. {
  9738. AgentHeightWidthPacket hwPacket = (AgentHeightWidthPacket)Pack;
  9739. c.viewHeight = hwPacket.HeightWidthBlock.Height;
  9740. c.viewWidth = hwPacket.HeightWidthBlock.Width;
  9741. }
  9742. private static void HandleInventoryDescendents(LLClientView c, Packet Pack)
  9743. {
  9744. }
  9745. #endregion unimplemented handlers
  9746. #region Dir handlers
  9747. private static void HandleDirPlacesQuery(LLClientView c, Packet Pack)
  9748. {
  9749. DirPlacesQueryPacket dirPlacesQueryPacket = (DirPlacesQueryPacket)Pack;
  9750. c.OnDirPlacesQuery?.Invoke(c,
  9751. dirPlacesQueryPacket.QueryData.QueryID,
  9752. Utils.BytesToString(
  9753. dirPlacesQueryPacket.QueryData.QueryText),
  9754. (int)dirPlacesQueryPacket.QueryData.QueryFlags,
  9755. (int)dirPlacesQueryPacket.QueryData.Category,
  9756. Utils.BytesToString(
  9757. dirPlacesQueryPacket.QueryData.SimName),
  9758. dirPlacesQueryPacket.QueryData.QueryStart);
  9759. }
  9760. private static void HandleDirFindQuery(LLClientView c, Packet Pack)
  9761. {
  9762. DirFindQueryPacket dirFindQueryPacket = (DirFindQueryPacket)Pack;
  9763. c.OnDirFindQuery?.Invoke(c,
  9764. dirFindQueryPacket.QueryData.QueryID,
  9765. Utils.BytesToString(
  9766. dirFindQueryPacket.QueryData.QueryText).Trim(),
  9767. dirFindQueryPacket.QueryData.QueryFlags,
  9768. dirFindQueryPacket.QueryData.QueryStart);
  9769. }
  9770. private static void HandleDirLandQuery(LLClientView c, Packet Pack)
  9771. {
  9772. DirLandQueryPacket dirLandQueryPacket = (DirLandQueryPacket)Pack;
  9773. c.OnDirLandQuery?.Invoke(c,
  9774. dirLandQueryPacket.QueryData.QueryID,
  9775. dirLandQueryPacket.QueryData.QueryFlags,
  9776. dirLandQueryPacket.QueryData.SearchType,
  9777. dirLandQueryPacket.QueryData.Price,
  9778. dirLandQueryPacket.QueryData.Area,
  9779. dirLandQueryPacket.QueryData.QueryStart);
  9780. }
  9781. private static void HandleDirPopularQuery(LLClientView c, Packet Pack)
  9782. {
  9783. DirPopularQueryPacket dirPopularQueryPacket = (DirPopularQueryPacket)Pack;
  9784. c.OnDirPopularQuery?.Invoke(c,
  9785. dirPopularQueryPacket.QueryData.QueryID,
  9786. dirPopularQueryPacket.QueryData.QueryFlags);
  9787. }
  9788. private static void HandleDirClassifiedQuery(LLClientView c, Packet Pack)
  9789. {
  9790. DirClassifiedQueryPacket dirClassifiedQueryPacket = (DirClassifiedQueryPacket)Pack;
  9791. c.OnDirClassifiedQuery?.Invoke(c,
  9792. dirClassifiedQueryPacket.QueryData.QueryID,
  9793. Utils.BytesToString(
  9794. dirClassifiedQueryPacket.QueryData.QueryText),
  9795. dirClassifiedQueryPacket.QueryData.QueryFlags,
  9796. dirClassifiedQueryPacket.QueryData.Category,
  9797. dirClassifiedQueryPacket.QueryData.QueryStart);
  9798. }
  9799. private static void HandleEventInfoRequest(LLClientView c, Packet Pack)
  9800. {
  9801. EventInfoRequestPacket eventInfoRequestPacket = (EventInfoRequestPacket)Pack;
  9802. c.OnEventInfoRequest?.Invoke(c, eventInfoRequestPacket.EventData.EventID);
  9803. }
  9804. #endregion
  9805. #region Calling Card
  9806. private static void HandleOfferCallingCard(LLClientView c, Packet Pack)
  9807. {
  9808. OfferCallingCardPacket offerCallingCardPacket = (OfferCallingCardPacket)Pack;
  9809. c.OnOfferCallingCard?.Invoke(c,
  9810. offerCallingCardPacket.AgentBlock.DestID,
  9811. offerCallingCardPacket.AgentBlock.TransactionID);
  9812. }
  9813. private static void HandleAcceptCallingCard(LLClientView c, Packet Pack)
  9814. {
  9815. AcceptCallingCardPacket acceptCallingCardPacket = (AcceptCallingCardPacket)Pack;
  9816. // according to http://wiki.secondlife.com/wiki/AcceptCallingCard FolderData should
  9817. // contain exactly one entry
  9818. if (acceptCallingCardPacket.FolderData.Length > 0)
  9819. {
  9820. c.OnAcceptCallingCard?.Invoke(c,
  9821. acceptCallingCardPacket.TransactionBlock.TransactionID,
  9822. acceptCallingCardPacket.FolderData[0].FolderID);
  9823. }
  9824. }
  9825. private static void HandleDeclineCallingCard(LLClientView c, Packet Pack)
  9826. {
  9827. DeclineCallingCardPacket declineCallingCardPacket = (DeclineCallingCardPacket)Pack;
  9828. c.OnDeclineCallingCard?.Invoke(c,
  9829. declineCallingCardPacket.TransactionBlock.TransactionID);
  9830. }
  9831. #endregion Calling Card
  9832. #region Groups
  9833. private static void HandleActivateGroup(LLClientView c, Packet Pack)
  9834. {
  9835. if (c.m_GroupsModule is null)
  9836. return;
  9837. ActivateGroupPacket activateGroupPacket = (ActivateGroupPacket)Pack;
  9838. c.m_GroupsModule.ActivateGroup(c, activateGroupPacket.AgentData.GroupID);
  9839. }
  9840. private static void HandleGroupVoteHistoryRequest(LLClientView c, Packet packet)
  9841. {
  9842. GroupVoteHistoryRequestPacket GroupVoteHistoryRequest = (GroupVoteHistoryRequestPacket)packet;
  9843. c.OnGroupVoteHistoryRequest?.Invoke(c, c.m_agentId, c.SessionId, GroupVoteHistoryRequest.GroupData.GroupID, GroupVoteHistoryRequest.TransactionData.TransactionID);
  9844. }
  9845. private static void HandleGroupActiveProposalsRequest(LLClientView c, Packet packet)
  9846. {
  9847. GroupActiveProposalsRequestPacket GroupActiveProposalsRequest = (GroupActiveProposalsRequestPacket)packet;
  9848. c.OnGroupActiveProposalsRequest?.Invoke(c, c.m_agentId, c.SessionId, GroupActiveProposalsRequest.GroupData.GroupID, GroupActiveProposalsRequest.TransactionData.TransactionID);
  9849. }
  9850. private static void HandleGroupAccountDetailsRequest(LLClientView c, Packet packet)
  9851. {
  9852. GroupAccountDetailsRequestPacket GroupAccountDetailsRequest = (GroupAccountDetailsRequestPacket)packet;
  9853. c.OnGroupAccountDetailsRequest?.Invoke(c, c.m_agentId, GroupAccountDetailsRequest.AgentData.GroupID, GroupAccountDetailsRequest.MoneyData.RequestID, c.SessionId);
  9854. }
  9855. private static void HandleGroupAccountSummaryRequest(LLClientView c, Packet packet)
  9856. {
  9857. GroupAccountSummaryRequestPacket GroupAccountSummaryRequest = (GroupAccountSummaryRequestPacket)packet;
  9858. c.OnGroupAccountSummaryRequest?.Invoke(c, c.m_agentId, GroupAccountSummaryRequest.AgentData.GroupID);
  9859. }
  9860. private static void HandleGroupTransactionsDetailsRequest(LLClientView c, Packet packet)
  9861. {
  9862. GroupAccountTransactionsRequestPacket GroupAccountTransactionsRequest = (GroupAccountTransactionsRequestPacket)packet;
  9863. c.OnGroupAccountTransactionsRequest?.Invoke(c, c.m_agentId, GroupAccountTransactionsRequest.AgentData.GroupID,
  9864. GroupAccountTransactionsRequest.MoneyData.RequestID, c.SessionId);
  9865. }
  9866. private static void HandleGroupTitlesRequest(LLClientView c, Packet Pack)
  9867. {
  9868. if (c.m_GroupsModule is null)
  9869. return;
  9870. GroupTitlesRequestPacket groupTitlesRequest = (GroupTitlesRequestPacket)Pack;
  9871. GroupTitlesReplyPacket groupTitlesReply = (GroupTitlesReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupTitlesReply);
  9872. groupTitlesReply.AgentData = new GroupTitlesReplyPacket.AgentDataBlock
  9873. {
  9874. AgentID = c.m_agentId,
  9875. GroupID = groupTitlesRequest.AgentData.GroupID,
  9876. RequestID = groupTitlesRequest.AgentData.RequestID
  9877. };
  9878. List<GroupTitlesData> titles = c.m_GroupsModule.GroupTitlesRequest(c,
  9879. groupTitlesRequest.AgentData.GroupID);
  9880. groupTitlesReply.GroupData = new GroupTitlesReplyPacket.GroupDataBlock[titles.Count];
  9881. int i = 0;
  9882. foreach (GroupTitlesData d in titles)
  9883. {
  9884. groupTitlesReply.GroupData[i++] = new GroupTitlesReplyPacket.GroupDataBlock
  9885. {
  9886. Title = Util.StringToBytes256(d.Name),
  9887. RoleID = d.UUID,
  9888. Selected = d.Selected
  9889. };
  9890. }
  9891. c.OutPacket(groupTitlesReply, ThrottleOutPacketType.Task);
  9892. }
  9893. UUID lastGroupProfileRequestID = UUID.Zero;
  9894. double lastGroupProfileRequestTS = Util.GetTimeStampMS();
  9895. private static void HandleGroupProfileRequest(LLClientView c, Packet Pack)
  9896. {
  9897. if(c.m_GroupsModule is null)
  9898. return;
  9899. GroupProfileRequestPacket groupProfileRequest = (GroupProfileRequestPacket)Pack;
  9900. UUID grpID = groupProfileRequest.GroupData.GroupID;
  9901. double ts = Util.GetTimeStampMS();
  9902. if(grpID == c.lastGroupProfileRequestID && ts - c.lastGroupProfileRequestTS < 10000)
  9903. return;
  9904. c.lastGroupProfileRequestID = grpID;
  9905. c.lastGroupProfileRequestTS = ts;
  9906. GroupProfileReplyPacket groupProfileReply = (GroupProfileReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupProfileReply);
  9907. groupProfileReply.AgentData = new GroupProfileReplyPacket.AgentDataBlock();
  9908. groupProfileReply.GroupData = new GroupProfileReplyPacket.GroupDataBlock();
  9909. groupProfileReply.AgentData.AgentID = c.m_agentId;
  9910. GroupProfileData d = c.m_GroupsModule.GroupProfileRequest(c, groupProfileRequest.GroupData.GroupID);
  9911. if(d.GroupID.IsZero()) // don't send broken data
  9912. return;
  9913. groupProfileReply.GroupData.GroupID = d.GroupID;
  9914. groupProfileReply.GroupData.Name = Util.StringToBytes256(d.Name);
  9915. groupProfileReply.GroupData.Charter = Util.StringToBytes1024(d.Charter);
  9916. groupProfileReply.GroupData.ShowInList = d.ShowInList;
  9917. groupProfileReply.GroupData.MemberTitle = Util.StringToBytes256(d.MemberTitle);
  9918. groupProfileReply.GroupData.PowersMask = d.PowersMask;
  9919. groupProfileReply.GroupData.InsigniaID = d.InsigniaID;
  9920. groupProfileReply.GroupData.FounderID = d.FounderID;
  9921. groupProfileReply.GroupData.MembershipFee = d.MembershipFee;
  9922. groupProfileReply.GroupData.OpenEnrollment = d.OpenEnrollment;
  9923. groupProfileReply.GroupData.Money = d.Money;
  9924. groupProfileReply.GroupData.GroupMembershipCount = d.GroupMembershipCount;
  9925. groupProfileReply.GroupData.GroupRolesCount = d.GroupRolesCount;
  9926. groupProfileReply.GroupData.AllowPublish = d.AllowPublish;
  9927. groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
  9928. groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
  9929. if (c.m_scene.Permissions.IsGod(c.m_agentId) && (!c.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
  9930. {
  9931. if (c.m_scene.TryGetScenePresence(c.m_agentId, out ScenePresence p))
  9932. {
  9933. if (p.IsViewerUIGod)
  9934. {
  9935. groupProfileReply.GroupData.OpenEnrollment = true;
  9936. groupProfileReply.GroupData.MembershipFee = 0;
  9937. }
  9938. }
  9939. }
  9940. c.OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
  9941. if(grpID.Equals(c.lastGroupProfileRequestID))
  9942. c.lastGroupProfileRequestTS = Util.GetTimeStampMS() - 7000;
  9943. }
  9944. private static void HandleGroupMembersRequest(LLClientView c, Packet Pack)
  9945. {
  9946. if (c.m_GroupsModule is null)
  9947. return;
  9948. GroupMembersRequestPacket groupMembersRequestPacket = (GroupMembersRequestPacket)Pack;
  9949. List<GroupMembersData> members =
  9950. c.m_GroupsModule.GroupMembersRequest(c, groupMembersRequestPacket.GroupData.GroupID);
  9951. int memberCount = members.Count;
  9952. int indx = 0;
  9953. while (indx < memberCount)
  9954. {
  9955. int blockCount = memberCount - indx;
  9956. if (blockCount > 25)
  9957. blockCount = 25;
  9958. GroupMembersReplyPacket groupMembersReply = (GroupMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupMembersReply);
  9959. groupMembersReply.AgentData = new GroupMembersReplyPacket.AgentDataBlock();
  9960. groupMembersReply.GroupData = new GroupMembersReplyPacket.GroupDataBlock();
  9961. groupMembersReply.MemberData = new GroupMembersReplyPacket.MemberDataBlock[blockCount];
  9962. groupMembersReply.AgentData.AgentID = c.m_agentId;
  9963. groupMembersReply.GroupData.GroupID = groupMembersRequestPacket.GroupData.GroupID;
  9964. groupMembersReply.GroupData.RequestID = groupMembersRequestPacket.GroupData.RequestID;
  9965. groupMembersReply.GroupData.MemberCount = memberCount;
  9966. for (int i = 0; i < blockCount; i++)
  9967. {
  9968. GroupMembersData m = members[indx++];
  9969. groupMembersReply.MemberData[i] = new GroupMembersReplyPacket.MemberDataBlock
  9970. {
  9971. AgentID = m.AgentID,
  9972. Contribution = m.Contribution,
  9973. OnlineStatus = Util.StringToBytes256(m.OnlineStatus),
  9974. AgentPowers = m.AgentPowers,
  9975. Title = Util.StringToBytes256(m.Title),
  9976. IsOwner = m.IsOwner
  9977. };
  9978. }
  9979. c.OutPacket(groupMembersReply, ThrottleOutPacketType.Task);
  9980. }
  9981. }
  9982. private static void HandleGroupRoleDataRequest(LLClientView c, Packet Pack)
  9983. {
  9984. if (c.m_GroupsModule is null)
  9985. return;
  9986. GroupRoleDataRequestPacket groupRolesRequest = (GroupRoleDataRequestPacket)Pack;
  9987. GroupRoleDataReplyPacket groupRolesReply = (GroupRoleDataReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleDataReply);
  9988. groupRolesReply.AgentData = new GroupRoleDataReplyPacket.AgentDataBlock { AgentID = c.m_agentId };
  9989. groupRolesReply.GroupData = new GroupRoleDataReplyPacket.GroupDataBlock
  9990. {
  9991. GroupID = groupRolesRequest.GroupData.GroupID,
  9992. RequestID = groupRolesRequest.GroupData.RequestID
  9993. };
  9994. List<GroupRolesData> titles = c.m_GroupsModule.GroupRoleDataRequest(c,
  9995. groupRolesRequest.GroupData.GroupID);
  9996. groupRolesReply.GroupData.RoleCount = titles.Count;
  9997. groupRolesReply.RoleData = new GroupRoleDataReplyPacket.RoleDataBlock[titles.Count];
  9998. int i = 0;
  9999. foreach (GroupRolesData d in titles)
  10000. {
  10001. groupRolesReply.RoleData[i] = new GroupRoleDataReplyPacket.RoleDataBlock
  10002. {
  10003. RoleID = d.RoleID,
  10004. Name = Util.StringToBytes256(d.Name),
  10005. Title = Util.StringToBytes256(d.Title),
  10006. Description = Util.StringToBytes1024(d.Description),
  10007. Powers = d.Powers,
  10008. Members = (uint)d.Members
  10009. };
  10010. i++;
  10011. }
  10012. c.OutPacket(groupRolesReply, ThrottleOutPacketType.Task);
  10013. }
  10014. private static void HandleGroupRoleMembersRequest(LLClientView c, Packet Pack)
  10015. {
  10016. if (c.m_GroupsModule is null)
  10017. return;
  10018. GroupRoleMembersRequestPacket groupRoleMembersRequest = (GroupRoleMembersRequestPacket)Pack;
  10019. List<GroupRoleMembersData> mappings = c.m_GroupsModule.GroupRoleMembersRequest(c,
  10020. groupRoleMembersRequest.GroupData.GroupID);
  10021. int mappingsCount = mappings.Count;
  10022. while (mappings.Count > 0)
  10023. {
  10024. int pairs = mappings.Count;
  10025. if (pairs > 32)
  10026. pairs = 32;
  10027. GroupRoleMembersReplyPacket groupRoleMembersReply = (GroupRoleMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleMembersReply);
  10028. groupRoleMembersReply.AgentData = new GroupRoleMembersReplyPacket.AgentDataBlock
  10029. {
  10030. AgentID = c.m_agentId,
  10031. GroupID = groupRoleMembersRequest.GroupData.GroupID,
  10032. RequestID = groupRoleMembersRequest.GroupData.RequestID,
  10033. TotalPairs = (uint)mappingsCount
  10034. };
  10035. groupRoleMembersReply.MemberData = new GroupRoleMembersReplyPacket.MemberDataBlock[pairs];
  10036. for (int i = 0; i < pairs; i++)
  10037. {
  10038. GroupRoleMembersData d = mappings[0];
  10039. mappings.RemoveAt(0);
  10040. groupRoleMembersReply.MemberData[i] = new GroupRoleMembersReplyPacket.MemberDataBlock
  10041. {
  10042. RoleID = d.RoleID,
  10043. MemberID = d.MemberID
  10044. };
  10045. }
  10046. c.OutPacket(groupRoleMembersReply, ThrottleOutPacketType.Task);
  10047. }
  10048. }
  10049. private static void HandleCreateGroupRequest(LLClientView c, Packet Pack)
  10050. {
  10051. if (c.m_GroupsModule is null)
  10052. return;
  10053. CreateGroupRequestPacket createGroupRequest = (CreateGroupRequestPacket)Pack;
  10054. c.m_GroupsModule.CreateGroup(c,
  10055. Utils.BytesToString(createGroupRequest.GroupData.Name),
  10056. Utils.BytesToString(createGroupRequest.GroupData.Charter),
  10057. createGroupRequest.GroupData.ShowInList,
  10058. createGroupRequest.GroupData.InsigniaID,
  10059. createGroupRequest.GroupData.MembershipFee,
  10060. createGroupRequest.GroupData.OpenEnrollment,
  10061. createGroupRequest.GroupData.AllowPublish,
  10062. createGroupRequest.GroupData.MaturePublish);
  10063. }
  10064. private static void HandleUpdateGroupInfo(LLClientView c, Packet Pack)
  10065. {
  10066. if (c.m_GroupsModule is null)
  10067. return;
  10068. UpdateGroupInfoPacket updateGroupInfo = (UpdateGroupInfoPacket)Pack;
  10069. c.m_GroupsModule.UpdateGroupInfo(c,
  10070. updateGroupInfo.GroupData.GroupID,
  10071. Utils.BytesToString(updateGroupInfo.GroupData.Charter),
  10072. updateGroupInfo.GroupData.ShowInList,
  10073. updateGroupInfo.GroupData.InsigniaID,
  10074. updateGroupInfo.GroupData.MembershipFee,
  10075. updateGroupInfo.GroupData.OpenEnrollment,
  10076. updateGroupInfo.GroupData.AllowPublish,
  10077. updateGroupInfo.GroupData.MaturePublish);
  10078. }
  10079. private static void HandleSetGroupAcceptNotices(LLClientView c, Packet Pack)
  10080. {
  10081. if (c.m_GroupsModule is null)
  10082. return;
  10083. SetGroupAcceptNoticesPacket setGroupAcceptNotices = (SetGroupAcceptNoticesPacket)Pack;
  10084. c.m_GroupsModule.SetGroupAcceptNotices(c,
  10085. setGroupAcceptNotices.Data.GroupID,
  10086. setGroupAcceptNotices.Data.AcceptNotices,
  10087. setGroupAcceptNotices.NewData.ListInProfile);
  10088. }
  10089. private static void HandleGroupTitleUpdate(LLClientView c, Packet Pack)
  10090. {
  10091. GroupTitleUpdatePacket groupTitleUpdate = (GroupTitleUpdatePacket)Pack;
  10092. c.m_GroupsModule.GroupTitleUpdate(c,
  10093. groupTitleUpdate.AgentData.GroupID,
  10094. groupTitleUpdate.AgentData.TitleRoleID);
  10095. }
  10096. private static void HandleParcelDeedToGroup(LLClientView c, Packet Pack)
  10097. {
  10098. if (c.m_GroupsModule is null)
  10099. return;
  10100. ParcelDeedToGroupPacket parcelDeedToGroup = (ParcelDeedToGroupPacket)Pack;
  10101. c.OnParcelDeedToGroup?.Invoke(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID, c);
  10102. }
  10103. private static void HandleGroupNoticesListRequest(LLClientView c, Packet Pack)
  10104. {
  10105. if (c.m_GroupsModule is null)
  10106. return;
  10107. GroupNoticesListRequestPacket groupNoticesListRequest = (GroupNoticesListRequestPacket)Pack;
  10108. GroupNoticeData[] gn = c.m_GroupsModule.GroupNoticesListRequest(c, groupNoticesListRequest.Data.GroupID);
  10109. GroupNoticesListReplyPacket groupNoticesListReply = (GroupNoticesListReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupNoticesListReply);
  10110. groupNoticesListReply.AgentData = new GroupNoticesListReplyPacket.AgentDataBlock
  10111. {
  10112. AgentID = c.m_agentId,
  10113. GroupID = groupNoticesListRequest.Data.GroupID
  10114. };
  10115. groupNoticesListReply.Data = new GroupNoticesListReplyPacket.DataBlock[gn.Length];
  10116. int i = 0;
  10117. foreach (GroupNoticeData g in gn)
  10118. {
  10119. groupNoticesListReply.Data[i++] = new GroupNoticesListReplyPacket.DataBlock
  10120. {
  10121. NoticeID = g.NoticeID,
  10122. Timestamp = g.Timestamp,
  10123. FromName = Util.StringToBytes256(g.FromName),
  10124. Subject = Util.StringToBytes256(g.Subject),
  10125. HasAttachment = g.HasAttachment,
  10126. AssetType = g.AssetType
  10127. };
  10128. }
  10129. c.OutPacket(groupNoticesListReply, ThrottleOutPacketType.Task);
  10130. }
  10131. private static void HandleGroupNoticeRequest(LLClientView c, Packet Pack)
  10132. {
  10133. if (c.m_GroupsModule is null)
  10134. return;
  10135. GroupNoticeRequestPacket groupNoticeRequest = (GroupNoticeRequestPacket)Pack;
  10136. c.m_GroupsModule.GroupNoticeRequest(c, groupNoticeRequest.Data.GroupNoticeID);
  10137. }
  10138. private static void HandleGroupRoleUpdate(LLClientView c, Packet Pack)
  10139. {
  10140. if (c.m_GroupsModule is null)
  10141. return;
  10142. GroupRoleUpdatePacket groupRoleUpdate = (GroupRoleUpdatePacket)Pack;
  10143. foreach (GroupRoleUpdatePacket.RoleDataBlock d in groupRoleUpdate.RoleData)
  10144. {
  10145. c.m_GroupsModule.GroupRoleUpdate(c,
  10146. groupRoleUpdate.AgentData.GroupID,
  10147. d.RoleID,
  10148. Utils.BytesToString(d.Name),
  10149. Utils.BytesToString(d.Description),
  10150. Utils.BytesToString(d.Title),
  10151. d.Powers,
  10152. d.UpdateType);
  10153. }
  10154. c.m_GroupsModule.NotifyChange(groupRoleUpdate.AgentData.GroupID);
  10155. }
  10156. private static void HandleGroupRoleChanges(LLClientView c, Packet Pack)
  10157. {
  10158. if (c.m_GroupsModule is null)
  10159. return;
  10160. GroupRoleChangesPacket groupRoleChanges = (GroupRoleChangesPacket)Pack;
  10161. foreach (GroupRoleChangesPacket.RoleChangeBlock d in groupRoleChanges.RoleChange)
  10162. {
  10163. c.m_GroupsModule.GroupRoleChanges(c,
  10164. groupRoleChanges.AgentData.GroupID,
  10165. d.RoleID,
  10166. d.MemberID,
  10167. d.Change);
  10168. }
  10169. c.m_GroupsModule.NotifyChange(groupRoleChanges.AgentData.GroupID);
  10170. }
  10171. private static void HandleJoinGroupRequest(LLClientView c, Packet Pack)
  10172. {
  10173. if (c.m_GroupsModule is null)
  10174. return;
  10175. JoinGroupRequestPacket joinGroupRequest = (JoinGroupRequestPacket)Pack;
  10176. c.m_GroupsModule.JoinGroupRequest(c, joinGroupRequest.GroupData.GroupID);
  10177. }
  10178. private static void HandleLeaveGroupRequest(LLClientView c, Packet Pack)
  10179. {
  10180. if (c.m_GroupsModule is null)
  10181. return;
  10182. LeaveGroupRequestPacket leaveGroupRequest = (LeaveGroupRequestPacket)Pack;
  10183. c.m_GroupsModule.LeaveGroupRequest(c, leaveGroupRequest.GroupData.GroupID);
  10184. }
  10185. private static void HandleEjectGroupMemberRequest(LLClientView c, Packet Pack)
  10186. {
  10187. if (c.m_GroupsModule is null)
  10188. return;
  10189. EjectGroupMemberRequestPacket ejectGroupMemberRequest = (EjectGroupMemberRequestPacket)Pack;
  10190. foreach (EjectGroupMemberRequestPacket.EjectDataBlock e in ejectGroupMemberRequest.EjectData)
  10191. {
  10192. c.m_GroupsModule.EjectGroupMemberRequest(c,
  10193. ejectGroupMemberRequest.GroupData.GroupID,
  10194. e.EjecteeID);
  10195. }
  10196. }
  10197. private static void HandleInviteGroupRequest(LLClientView c, Packet Pack)
  10198. {
  10199. if (c.m_GroupsModule is null)
  10200. return;
  10201. InviteGroupRequestPacket inviteGroupRequest = (InviteGroupRequestPacket)Pack;
  10202. foreach (InviteGroupRequestPacket.InviteDataBlock b in inviteGroupRequest.InviteData)
  10203. {
  10204. c.m_GroupsModule.InviteGroupRequest(c,
  10205. inviteGroupRequest.GroupData.GroupID,
  10206. b.InviteeID,
  10207. b.RoleID);
  10208. }
  10209. }
  10210. #endregion Groups
  10211. private static void HandleStartLure(LLClientView c, Packet Pack)
  10212. {
  10213. if(c.OnStartLure is null)
  10214. return;
  10215. StartLurePacket startLureRequest = (StartLurePacket)Pack;
  10216. for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
  10217. {
  10218. c.OnStartLure?.Invoke(startLureRequest.Info.LureType,
  10219. Utils.BytesToString(
  10220. startLureRequest.Info.Message),
  10221. startLureRequest.TargetData[i].TargetID,
  10222. c);
  10223. }
  10224. }
  10225. private static void HandleTeleportLureRequest(LLClientView c, Packet Pack)
  10226. {
  10227. TeleportLureRequestPacket teleportLureRequest = (TeleportLureRequestPacket)Pack;
  10228. c.OnTeleportLureRequest?.Invoke(
  10229. teleportLureRequest.Info.LureID,
  10230. teleportLureRequest.Info.TeleportFlags,
  10231. c);
  10232. }
  10233. private static void HandleClassifiedInfoRequest(LLClientView c, Packet Pack)
  10234. {
  10235. ClassifiedInfoRequestPacket classifiedInfoRequest = (ClassifiedInfoRequestPacket)Pack;
  10236. c.OnClassifiedInfoRequest?.Invoke(
  10237. classifiedInfoRequest.Data.ClassifiedID,
  10238. c);
  10239. }
  10240. private static void HandleClassifiedInfoUpdate(LLClientView c, Packet Pack)
  10241. {
  10242. ClassifiedInfoUpdatePacket classifiedInfoUpdate = (ClassifiedInfoUpdatePacket)Pack;
  10243. // fix classifiedFlags maturity
  10244. byte classifiedFlags = classifiedInfoUpdate.Data.ClassifiedFlags;
  10245. if ((classifiedFlags & 0x4e) == 0) // if none
  10246. classifiedFlags |= 0x4; // pg
  10247. c.OnClassifiedInfoUpdate?.Invoke(
  10248. classifiedInfoUpdate.Data.ClassifiedID,
  10249. classifiedInfoUpdate.Data.Category,
  10250. Utils.BytesToString(
  10251. classifiedInfoUpdate.Data.Name),
  10252. Utils.BytesToString(
  10253. classifiedInfoUpdate.Data.Desc),
  10254. classifiedInfoUpdate.Data.ParcelID,
  10255. classifiedInfoUpdate.Data.ParentEstate,
  10256. classifiedInfoUpdate.Data.SnapshotID,
  10257. new Vector3(
  10258. classifiedInfoUpdate.Data.PosGlobal),
  10259. classifiedFlags,
  10260. classifiedInfoUpdate.Data.PriceForListing,
  10261. c);
  10262. }
  10263. private static void HandleClassifiedDelete(LLClientView c, Packet Pack)
  10264. {
  10265. ClassifiedDeletePacket classifiedDelete = (ClassifiedDeletePacket)Pack;
  10266. c.OnClassifiedDelete?.Invoke(
  10267. classifiedDelete.Data.ClassifiedID,
  10268. c);
  10269. }
  10270. private static void HandleClassifiedGodDelete(LLClientView c, Packet Pack)
  10271. {
  10272. ClassifiedGodDeletePacket classifiedGodDelete = (ClassifiedGodDeletePacket)Pack;
  10273. c.OnClassifiedGodDelete?.Invoke(
  10274. classifiedGodDelete.Data.ClassifiedID,
  10275. classifiedGodDelete.Data.QueryID,
  10276. c);
  10277. }
  10278. private static void HandleEventGodDelete(LLClientView c, Packet Pack)
  10279. {
  10280. EventGodDeletePacket eventGodDelete = (EventGodDeletePacket)Pack;
  10281. c.OnEventGodDelete?.Invoke(
  10282. eventGodDelete.EventData.EventID,
  10283. eventGodDelete.QueryData.QueryID,
  10284. Utils.BytesToString(
  10285. eventGodDelete.QueryData.QueryText),
  10286. eventGodDelete.QueryData.QueryFlags,
  10287. eventGodDelete.QueryData.QueryStart,
  10288. c);
  10289. }
  10290. private static void HandleEventNotificationAddRequest(LLClientView c, Packet Pack)
  10291. {
  10292. EventNotificationAddRequestPacket eventNotificationAdd = (EventNotificationAddRequestPacket)Pack;
  10293. c.OnEventNotificationAddRequest?.Invoke(eventNotificationAdd.EventData.EventID, c);
  10294. }
  10295. private static void HandleEventNotificationRemoveRequest(LLClientView c, Packet Pack)
  10296. {
  10297. EventNotificationRemoveRequestPacket eventNotificationRemove = (EventNotificationRemoveRequestPacket)Pack;
  10298. c.OnEventNotificationRemoveRequest?.Invoke(eventNotificationRemove.EventData.EventID, c);
  10299. }
  10300. private static void HandleRetrieveInstantMessages(LLClientView c, Packet Pack)
  10301. {
  10302. RetrieveInstantMessagesPacket rimpInstantMessagePack = (RetrieveInstantMessagesPacket)Pack;
  10303. c.OnRetrieveInstantMessages?.Invoke(c);
  10304. }
  10305. private static void HandlePickDelete(LLClientView c, Packet Pack)
  10306. {
  10307. PickDeletePacket pickDelete = (PickDeletePacket)Pack;
  10308. c.OnPickDelete?.Invoke(c, pickDelete.Data.PickID);
  10309. }
  10310. private static void HandlePickGodDelete(LLClientView c, Packet Pack)
  10311. {
  10312. PickGodDeletePacket pickGodDelete = (PickGodDeletePacket)Pack;
  10313. c.OnPickGodDelete?.Invoke(c,
  10314. pickGodDelete.AgentData.AgentID,
  10315. pickGodDelete.Data.PickID,
  10316. pickGodDelete.Data.QueryID);
  10317. }
  10318. private static void HandlePickInfoUpdate(LLClientView c, Packet Pack)
  10319. {
  10320. PickInfoUpdatePacket pickInfoUpdate = (PickInfoUpdatePacket)Pack;
  10321. c.OnPickInfoUpdate?.Invoke(c,
  10322. pickInfoUpdate.Data.PickID,
  10323. pickInfoUpdate.Data.CreatorID,
  10324. pickInfoUpdate.Data.TopPick,
  10325. Utils.BytesToString(pickInfoUpdate.Data.Name),
  10326. Utils.BytesToString(pickInfoUpdate.Data.Desc),
  10327. pickInfoUpdate.Data.SnapshotID,
  10328. pickInfoUpdate.Data.SortOrder,
  10329. pickInfoUpdate.Data.Enabled);
  10330. }
  10331. private static void HandleAvatarNotesUpdate(LLClientView c, Packet Pack)
  10332. {
  10333. AvatarNotesUpdatePacket avatarNotesUpdate = (AvatarNotesUpdatePacket)Pack;
  10334. c.OnAvatarNotesUpdate?.Invoke(c,
  10335. avatarNotesUpdate.Data.TargetID,
  10336. Utils.BytesToString(avatarNotesUpdate.Data.Notes));
  10337. }
  10338. private static void HandleAvatarInterestsUpdate(LLClientView c, Packet Pack)
  10339. {
  10340. AvatarInterestsUpdatePacket avatarInterestUpdate = (AvatarInterestsUpdatePacket)Pack;
  10341. c.OnAvatarInterestUpdate?.Invoke(c,
  10342. avatarInterestUpdate.PropertiesData.WantToMask,
  10343. Utils.BytesToString(avatarInterestUpdate.PropertiesData.WantToText),
  10344. avatarInterestUpdate.PropertiesData.SkillsMask,
  10345. Utils.BytesToString(avatarInterestUpdate.PropertiesData.SkillsText),
  10346. Utils.BytesToString(avatarInterestUpdate.PropertiesData.LanguagesText));
  10347. }
  10348. private static void HandleGrantUserRights(LLClientView c, Packet Pack)
  10349. {
  10350. GrantUserRightsPacket GrantUserRights = (GrantUserRightsPacket)Pack;
  10351. c.OnGrantUserRights?.Invoke(c,
  10352. GrantUserRights.Rights[0].AgentRelated,
  10353. GrantUserRights.Rights[0].RelatedRights);
  10354. }
  10355. private double m_nextRevokePermissionsTime = Double.MinValue;
  10356. private uint m_lastRevokePermissionsSeq = uint.MinValue;
  10357. private static void HandleRevokePermissions(LLClientView c, Packet Pack)
  10358. {
  10359. RevokePermissionsPacket pkt = (RevokePermissionsPacket)Pack;
  10360. uint thisSeq = pkt.Header.Sequence;
  10361. if (thisSeq == c.m_lastRevokePermissionsSeq)
  10362. return;
  10363. c.m_lastRevokePermissionsSeq = thisSeq;
  10364. ScenePresence sp = (ScenePresence)c.SceneAgent;
  10365. if(sp != null && !sp.IsDeleted && !sp.IsInTransit)
  10366. {
  10367. UUID objectID = pkt.Data.ObjectID;
  10368. double now = Util.GetTimeStampMS();
  10369. if (now < c.m_nextRevokePermissionsTime)
  10370. return;
  10371. if (objectID == c.m_scene.RegionInfo.RegionID)
  10372. c.m_nextRevokePermissionsTime = now + 2000;
  10373. else
  10374. c.m_nextRevokePermissionsTime = now + 50;
  10375. uint permissions = pkt.Data.ObjectPermissions;
  10376. sp.HandleRevokePermissions(objectID , permissions);
  10377. }
  10378. }
  10379. private static void HandlePlacesQuery(LLClientView c, Packet Pack)
  10380. {
  10381. PlacesQueryPacket placesQueryPacket = (PlacesQueryPacket)Pack;
  10382. c.OnPlacesQuery?.Invoke(placesQueryPacket.AgentData.QueryID,
  10383. placesQueryPacket.TransactionData.TransactionID,
  10384. Utils.BytesToString(
  10385. placesQueryPacket.QueryData.QueryText),
  10386. placesQueryPacket.QueryData.QueryFlags,
  10387. (byte)placesQueryPacket.QueryData.Category,
  10388. Utils.BytesToString(
  10389. placesQueryPacket.QueryData.SimName),
  10390. c);
  10391. }
  10392. #endregion Packet Handlers
  10393. public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question)
  10394. {
  10395. ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion);
  10396. scriptQuestion.Data.TaskID = taskID;
  10397. scriptQuestion.Data.ItemID = itemID;
  10398. scriptQuestion.Data.Questions = question;
  10399. scriptQuestion.Data.ObjectName = Util.StringToBytes256(taskName);
  10400. scriptQuestion.Data.ObjectOwner = Util.StringToBytes256(ownerName);
  10401. OutPacket(scriptQuestion, ThrottleOutPacketType.Task);
  10402. }
  10403. protected static void HandleLogout(LLClientView c, Packet packet)
  10404. {
  10405. var lrp = (LogoutRequestPacket)packet;
  10406. m_log.Info($"[CLIENT]: Got a logout request for {c.Name} in {c.Scene.Name}");
  10407. c.OnLogout?.Invoke(c);
  10408. }
  10409. /// <summary>
  10410. ///
  10411. /// </summary>
  10412. /// <param name="client"></param>
  10413. /// <returns></returns>
  10414. protected virtual void Logout(IClientAPI client)
  10415. {
  10416. m_log.Info($"[CLIENT]: Got a logout request for {Name} in {Scene.Name}");
  10417. OnLogout?.Invoke(client);
  10418. }
  10419. /// <summary>
  10420. /// </summary>
  10421. /// <remarks>
  10422. /// </remarks>
  10423. /// <param name="simclient"></param>
  10424. /// <param name="packet"></param>
  10425. /// <returns></returns>
  10426. protected static void HandleAgentTextureCached(LLClientView c, Packet packet)
  10427. {
  10428. //m_log.Debug("texture cached: " + packet.ToString());
  10429. AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
  10430. AgentCachedTextureResponsePacket cachedresp =
  10431. (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
  10432. ScenePresence p = c.m_scene.GetScenePresence(c.m_agentId);
  10433. if (p is null)
  10434. return;
  10435. WearableCacheItem[] cacheItems = p.Appearance?.WearableCacheItems;
  10436. cachedresp.AgentData.AgentID = c.m_agentId;
  10437. cachedresp.AgentData.SessionID = c.m_sessionId;
  10438. cachedresp.AgentData.SerialNum = cachedtex.AgentData.SerialNum;
  10439. cachedresp.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
  10440. if (cacheItems is null)
  10441. {
  10442. for (int i = 0; i < cachedtex.WearableData.Length; i++)
  10443. {
  10444. cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock()
  10445. {
  10446. TextureIndex = cachedtex.WearableData[i].TextureIndex,
  10447. TextureID = UUID.Zero,
  10448. HostName = Array.Empty<byte>()
  10449. };
  10450. }
  10451. }
  10452. else
  10453. {
  10454. for (int i = 0; i < cachedtex.WearableData.Length; i++)
  10455. {
  10456. var checkdWear = cachedtex.WearableData[i];
  10457. int idx = checkdWear.TextureIndex;
  10458. if (idx < cacheItems.Length)
  10459. {
  10460. var cachedIt = cacheItems[idx];
  10461. cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock()
  10462. {
  10463. TextureIndex = (byte)idx,
  10464. TextureID = checkdWear.ID.Equals(cachedIt.CacheId) ? cachedIt.TextureID : UUID.Zero,
  10465. HostName = Array.Empty<byte>()
  10466. };
  10467. }
  10468. else
  10469. {
  10470. cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock()
  10471. {
  10472. TextureIndex = (byte)idx,
  10473. TextureID = UUID.Zero,
  10474. HostName = Array.Empty<byte>()
  10475. };
  10476. }
  10477. }
  10478. }
  10479. cachedresp.Header.Zerocoded = true;
  10480. c.OutPacket(cachedresp, ThrottleOutPacketType.Task);
  10481. }
  10482. /// <summary>
  10483. /// Send a response back to a client when it asks the asset server (via the region server) if it has
  10484. /// its appearance texture cached.
  10485. /// </summary>
  10486. /// <param name="avatar"></param>
  10487. /// <param name="serial"></param>
  10488. /// <param name="cachedTextures"></param>
  10489. /// <returns></returns>
  10490. public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures)
  10491. {
  10492. if (avatar is not ScenePresence)
  10493. return;
  10494. AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
  10495. // TODO: don't create new blocks if recycling an old packet
  10496. cachedresp.AgentData.AgentID = m_agentId;
  10497. cachedresp.AgentData.SessionID = m_sessionId;
  10498. cachedresp.AgentData.SerialNum = serial;
  10499. cachedresp.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[cachedTextures.Count];
  10500. for (int i = 0; i < cachedTextures.Count; i++)
  10501. {
  10502. cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock()
  10503. {
  10504. TextureIndex = (byte)cachedTextures[i].BakedTextureIndex,
  10505. TextureID = cachedTextures[i].BakedTextureID,
  10506. HostName = Array.Empty<byte>()
  10507. };
  10508. }
  10509. cachedresp.Header.Zerocoded = true;
  10510. OutPacket(cachedresp, ThrottleOutPacketType.Task);
  10511. }
  10512. protected static void HandleMultipleObjUpdate(LLClientView c, Packet packet)
  10513. {
  10514. MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet;
  10515. // m_log.DebugFormat(
  10516. // "[CLIENT]: Incoming MultipleObjectUpdatePacket contained {0} blocks", multipleupdate.ObjectData.Length);
  10517. Scene tScene = c.m_scene;
  10518. for (int i = 0; i < multipleupdate.ObjectData.Length; i++)
  10519. {
  10520. MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i];
  10521. // Can't act on Null Data
  10522. if (block.Data != null)
  10523. {
  10524. uint localId = block.ObjectLocalID;
  10525. SceneObjectPart part = tScene.GetSceneObjectPart(localId);
  10526. if (part is null)
  10527. {
  10528. // It's a ghost! tell the client to delete it from view.
  10529. c.SendKillObject([localId]);
  10530. }
  10531. else
  10532. {
  10533. ClientChangeObject updatehandler = c.onClientChangeObject;
  10534. if (updatehandler != null)
  10535. {
  10536. ObjectChangeData udata = new();
  10537. /*ubit from ll JIRA:
  10538. * 0x01 position
  10539. * 0x02 rotation
  10540. * 0x04 scale
  10541. * 0x08 LINK_SET
  10542. * 0x10 UNIFORM for scale
  10543. */
  10544. // translate to internal changes
  10545. // not all cases .. just the ones older code did
  10546. switch (block.Type)
  10547. {
  10548. case 1: //change position sp
  10549. udata.position = new Vector3(block.Data, 0);
  10550. udata.change = ObjectChangeType.primP;
  10551. updatehandler(localId, udata, c);
  10552. break;
  10553. case 2: // rotation sp
  10554. udata.rotation = new Quaternion(block.Data, 0, true);
  10555. udata.change = ObjectChangeType.primR;
  10556. updatehandler(localId, udata, c);
  10557. break;
  10558. case 3: // position plus rotation
  10559. udata.position = new Vector3(block.Data, 0);
  10560. udata.rotation = new Quaternion(block.Data, 12, true);
  10561. udata.change = ObjectChangeType.primPR;
  10562. updatehandler(localId, udata, c);
  10563. break;
  10564. case 4: // scale sp
  10565. udata.scale = new Vector3(block.Data, 0);
  10566. udata.change = ObjectChangeType.primS;
  10567. updatehandler(localId, udata, c);
  10568. break;
  10569. case 0x14: // uniform scale sp
  10570. udata.scale = new Vector3(block.Data, 0);
  10571. udata.change = ObjectChangeType.primUS;
  10572. updatehandler(localId, udata, c);
  10573. break;
  10574. case 5: // scale and position sp
  10575. udata.position = new Vector3(block.Data, 0);
  10576. udata.scale = new Vector3(block.Data, 12);
  10577. udata.change = ObjectChangeType.primPS;
  10578. updatehandler(localId, udata, c);
  10579. break;
  10580. case 0x15: //uniform scale and position
  10581. udata.position = new Vector3(block.Data, 0);
  10582. udata.scale = new Vector3(block.Data, 12);
  10583. udata.change = ObjectChangeType.primPUS;
  10584. updatehandler(localId, udata, c);
  10585. break;
  10586. // now group related (bit 4)
  10587. case 9: //( 8 + 1 )group position
  10588. udata.position = new Vector3(block.Data, 0);
  10589. udata.change = ObjectChangeType.groupP;
  10590. updatehandler(localId, udata, c);
  10591. break;
  10592. case 0x0A: // (8 + 2) group rotation
  10593. udata.rotation = new Quaternion(block.Data, 0, true);
  10594. udata.change = ObjectChangeType.groupR;
  10595. updatehandler(localId, udata, c);
  10596. break;
  10597. case 0x0B: //( 8 + 2 + 1) group rotation and position
  10598. udata.position = new Vector3(block.Data, 0);
  10599. udata.rotation = new Quaternion(block.Data, 12, true);
  10600. udata.change = ObjectChangeType.groupPR;
  10601. updatehandler(localId, udata, c);
  10602. break;
  10603. case 0x0C: // (8 + 4) group scale
  10604. // only afects root prim and only sent by viewer editor object tab scaling
  10605. // mouse edition only allows uniform scaling
  10606. // SL MAY CHANGE THIS in viewers
  10607. udata.scale = new Vector3(block.Data, 0);
  10608. udata.change = ObjectChangeType.groupS;
  10609. updatehandler(localId, udata, c);
  10610. break;
  10611. case 0x0D: //(8 + 4 + 1) group scale and position
  10612. // exception as above
  10613. udata.position = new Vector3(block.Data, 0);
  10614. udata.scale = new Vector3(block.Data, 12);
  10615. udata.change = ObjectChangeType.groupPS;
  10616. updatehandler(localId, udata, c);
  10617. break;
  10618. case 0x1C: // (0x10 + 8 + 4 ) group scale UNIFORM
  10619. udata.scale = new Vector3(block.Data, 0);
  10620. udata.change = ObjectChangeType.groupUS;
  10621. updatehandler(localId, udata, c);
  10622. break;
  10623. case 0x1D: // (UNIFORM + GROUP + SCALE + POS)
  10624. udata.position = new Vector3(block.Data, 0);
  10625. udata.scale = new Vector3(block.Data, 12);
  10626. udata.change = ObjectChangeType.groupPUS;
  10627. updatehandler(localId, udata, c);
  10628. break;
  10629. default:
  10630. m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type));
  10631. break;
  10632. }
  10633. }
  10634. }
  10635. }
  10636. }
  10637. }
  10638. public void RequestMapLayer()
  10639. {
  10640. //should be getting the map layer from the grid server
  10641. //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area)
  10642. MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply);
  10643. // TODO: don't create new blocks if recycling an old packet
  10644. mapReply.AgentData.AgentID = m_agentId;
  10645. mapReply.AgentData.Flags = 0;
  10646. mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1];
  10647. mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock
  10648. {
  10649. Bottom = 0,
  10650. Left = 0,
  10651. Top = 30000,
  10652. Right = 30000,
  10653. ImageID = new UUID("00000000-0000-1111-9999-000000000006")
  10654. };
  10655. mapReply.Header.Zerocoded = true;
  10656. OutPacket(mapReply, ThrottleOutPacketType.Land);
  10657. }
  10658. public static void RequestMapBlocksX(int minX, int minY, int maxX, int maxY)
  10659. {
  10660. /*
  10661. IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY);
  10662. MapBlockReplyPacket mbReply = new MapBlockReplyPacket();
  10663. mbReply.AgentData.AgentId = m_agentId;
  10664. int len;
  10665. if (simMapProfiles is null)
  10666. len = 0;
  10667. else
  10668. len = simMapProfiles.Count;
  10669. mbReply.Data = new MapBlockReplyPacket.DataBlock[len];
  10670. int iii;
  10671. for (iii = 0; iii < len; iii++)
  10672. {
  10673. Hashtable mp = (Hashtable)simMapProfiles[iii];
  10674. mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock();
  10675. mbReply.Data[iii].Name = Util.UTF8.GetBytes((string)mp["name"]);
  10676. mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]);
  10677. mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]);
  10678. mbReply.Data[iii].MapImageID = new UUID((string)mp["map-image-id"]);
  10679. mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]);
  10680. mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]);
  10681. mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]);
  10682. mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]);
  10683. }
  10684. this.OutPacket(mbReply, ThrottleOutPacketType.Land);
  10685. */
  10686. }
  10687. /// <summary>
  10688. /// Sets the throttles from values supplied by the client
  10689. /// </summary>
  10690. /// <param name="throttles"></param>
  10691. public void SetChildAgentThrottle(byte[] throttles)
  10692. {
  10693. SetChildAgentThrottle(throttles, 1.0f);
  10694. }
  10695. public void SetChildAgentThrottle(byte[] throttles,float factor)
  10696. {
  10697. m_udpClient.SetThrottles(throttles, factor);
  10698. OnUpdateThrottles?.Invoke();
  10699. }
  10700. /// <summary>
  10701. /// Sets the throttles from values supplied caller
  10702. /// </summary>
  10703. /// <param name="throttles"></param>
  10704. public void SetAgentThrottleSilent(int throttle, int setting)
  10705. {
  10706. m_udpClient.ForceThrottleSetting(throttle,setting);
  10707. }
  10708. public int GetAgentThrottleSilent(int throttle)
  10709. {
  10710. return m_udpClient.GetThrottleSetting(throttle);
  10711. }
  10712. /// <summary>
  10713. /// Get the current throttles for this client as a packed byte array
  10714. /// </summary>
  10715. /// <param name="multiplier">Unused</param>
  10716. /// <returns></returns>
  10717. public byte[] GetThrottlesPacked(float multiplier)
  10718. {
  10719. return m_udpClient.GetThrottlesPacked(multiplier);
  10720. }
  10721. /// <summary>
  10722. /// Cruft?
  10723. /// </summary>
  10724. public virtual void InPacket(object NewPack)
  10725. {
  10726. throw new NotImplementedException();
  10727. }
  10728. /// <summary>
  10729. /// This is the starting point for sending a simulator packet out to the client
  10730. /// </summary>
  10731. /// <param name="packet">Packet to send</param>
  10732. /// <param name="throttlePacketType">Throttling category for the packet</param>
  10733. protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType)
  10734. {
  10735. #region BinaryStats
  10736. LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length);
  10737. #endregion BinaryStats
  10738. OutPacket(packet, throttlePacketType, true, null);
  10739. }
  10740. /// <summary>
  10741. /// This is the starting point for sending a simulator packet out to the client
  10742. /// </summary>
  10743. /// <param name="packet">Packet to send</param>
  10744. /// <param name="throttlePacketType">Throttling category for the packet</param>
  10745. /// <param name="doAutomaticSplitting">True to automatically split oversized
  10746. /// packets (the default), or false to disable splitting if the calling code
  10747. /// handles splitting manually</param>
  10748. protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting)
  10749. {
  10750. OutPacket(packet, throttlePacketType, doAutomaticSplitting, null);
  10751. }
  10752. /// <summary>
  10753. /// This is the starting point for sending a simulator packet out to the client
  10754. /// </summary>
  10755. /// <param name="packet">Packet to send</param>
  10756. /// <param name="throttlePacketType">Throttling category for the packet</param>
  10757. /// <param name="doAutomaticSplitting">True to automatically split oversized
  10758. /// packets (the default), or false to disable splitting if the calling code
  10759. /// handles splitting manually</param>
  10760. /// <param name="method">The method to be called in the event this packet is reliable
  10761. /// and unacknowledged. The server will provide normal resend capability if you do not
  10762. /// provide your own method.</param>
  10763. protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
  10764. {
  10765. if (m_outPacketsToDrop is not null)
  10766. {
  10767. if (m_outPacketsToDrop.Contains(packet.Type.ToString()))
  10768. {
  10769. PacketPool.Instance.ReturnPacket(packet);
  10770. return;
  10771. }
  10772. }
  10773. if (DebugPacketLevel > 0)
  10774. {
  10775. bool logPacket = true;
  10776. if (DebugPacketLevel <= 255
  10777. && (packet.Type == PacketType.SimStats || packet.Type == PacketType.SimulatorViewerTimeMessage))
  10778. logPacket = false;
  10779. if (DebugPacketLevel <= 200
  10780. && (packet.Type == PacketType.ImagePacket
  10781. || packet.Type == PacketType.ImageData
  10782. || packet.Type == PacketType.LayerData
  10783. || packet.Type == PacketType.CoarseLocationUpdate))
  10784. logPacket = false;
  10785. if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect))
  10786. logPacket = false;
  10787. if (DebugPacketLevel <= 50
  10788. && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
  10789. logPacket = false;
  10790. if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
  10791. logPacket = false;
  10792. if (logPacket)
  10793. m_log.DebugFormat(
  10794. "[CLIENT]: PACKET OUT to {0} ({1}) in {2} - {3}",
  10795. Name, SceneAgent.IsChildAgent ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type);
  10796. }
  10797. m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method);
  10798. }
  10799. protected void HandleAutopilot(Object sender, string method, List<String> args)
  10800. {
  10801. if(OnAutoPilotGo is null)
  10802. return;
  10803. Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out uint regionX, out uint regionY);
  10804. float locx = (float)(Convert.ToDouble(args[0]) - (double)regionX);
  10805. float locy = (float)(Convert.ToDouble(args[1]) - (double)regionY);
  10806. float locz = Convert.ToSingle(args[2]);
  10807. OnAutoPilotGo?.Invoke(new Vector3(locx, locy, locz), false, true);
  10808. }
  10809. /// <summary>
  10810. /// Entryway from the client to the simulator. All UDP packets from the client will end up here
  10811. /// </summary>
  10812. /// <param name="Pack">OpenMetaverse.packet</param>
  10813. public void ProcessInPacket(Packet packet)
  10814. {
  10815. if (m_inPacketsToDrop != null)
  10816. if (m_inPacketsToDrop.Contains(packet.Type.ToString()))
  10817. return;
  10818. if (DebugPacketLevel > 0)
  10819. {
  10820. bool logPacket = true;
  10821. if (DebugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
  10822. logPacket = false;
  10823. if (DebugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
  10824. logPacket = false;
  10825. if (DebugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
  10826. logPacket = false;
  10827. if (DebugPacketLevel <= 25 && packet.Type == PacketType.RequestObjectPropertiesFamily)
  10828. logPacket = false;
  10829. if (logPacket)
  10830. m_log.Debug(
  10831. $"[CLIENT]: PACKET IN from {Name} ({(SceneAgent.IsChildAgent ? "child" : "root")}) in {Scene.Name} - {packet.Type}");
  10832. }
  10833. if (!ProcessPacketMethod(packet))
  10834. m_log.Warn($"[CLIENT]: ignoring unhandled packet {packet.Type} from {Name} ({(SceneAgent.IsChildAgent ? "child" : "root")}) in {m_scene.Name}");
  10835. }
  10836. private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
  10837. {
  10838. PrimitiveBaseShape shape = new()
  10839. {
  10840. PCode = addPacket.ObjectData.PCode,
  10841. State = addPacket.ObjectData.State,
  10842. LastAttachPoint = addPacket.ObjectData.State,
  10843. PathBegin = addPacket.ObjectData.PathBegin,
  10844. PathEnd = addPacket.ObjectData.PathEnd,
  10845. PathScaleX = addPacket.ObjectData.PathScaleX,
  10846. PathScaleY = addPacket.ObjectData.PathScaleY,
  10847. PathShearX = addPacket.ObjectData.PathShearX,
  10848. PathShearY = addPacket.ObjectData.PathShearY,
  10849. PathSkew = addPacket.ObjectData.PathSkew,
  10850. ProfileBegin = addPacket.ObjectData.ProfileBegin,
  10851. ProfileEnd = addPacket.ObjectData.ProfileEnd,
  10852. Scale = addPacket.ObjectData.Scale,
  10853. PathCurve = addPacket.ObjectData.PathCurve,
  10854. ProfileCurve = addPacket.ObjectData.ProfileCurve,
  10855. ProfileHollow = addPacket.ObjectData.ProfileHollow,
  10856. PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset,
  10857. PathRevolutions = addPacket.ObjectData.PathRevolutions,
  10858. PathTaperX = addPacket.ObjectData.PathTaperX,
  10859. PathTaperY = addPacket.ObjectData.PathTaperY,
  10860. PathTwist = addPacket.ObjectData.PathTwist,
  10861. PathTwistBegin = addPacket.ObjectData.PathTwistBegin
  10862. };
  10863. Primitive.TextureEntry ntex = new(new UUID("89556747-24cb-43ed-920b-47caed15465f"));
  10864. shape.TextureEntry = ntex.GetBytes();
  10865. //shape.Textures = ntex;
  10866. return shape;
  10867. }
  10868. public ClientInfo GetClientInfo()
  10869. {
  10870. ClientInfo info = m_udpClient.GetClientInfo();
  10871. info.proxyEP = null;
  10872. info.agentcircuit ??= RequestClientInfo();
  10873. return info;
  10874. }
  10875. public void SetClientInfo(ClientInfo info)
  10876. {
  10877. m_udpClient.SetClientInfo(info);
  10878. }
  10879. #region Media Parcel Members
  10880. public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time)
  10881. {
  10882. ParcelMediaCommandMessagePacket commandMessagePacket = new();
  10883. commandMessagePacket.CommandBlock.Flags = flags;
  10884. commandMessagePacket.CommandBlock.Command = (uint)command;
  10885. commandMessagePacket.CommandBlock.Time = time;
  10886. OutPacket(commandMessagePacket, ThrottleOutPacketType.Task);
  10887. }
  10888. public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID,
  10889. byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight,
  10890. byte mediaLoop)
  10891. {
  10892. ParcelMediaUpdatePacket updatePacket = new();
  10893. updatePacket.DataBlock.MediaURL = Util.StringToBytes256(mediaUrl);
  10894. updatePacket.DataBlock.MediaID = mediaTextureID;
  10895. updatePacket.DataBlock.MediaAutoScale = autoScale;
  10896. updatePacket.DataBlockExtended.MediaType = Util.StringToBytes256(mediaType);
  10897. updatePacket.DataBlockExtended.MediaDesc = Util.StringToBytes256(mediaDesc);
  10898. updatePacket.DataBlockExtended.MediaWidth = mediaWidth;
  10899. updatePacket.DataBlockExtended.MediaHeight = mediaHeight;
  10900. updatePacket.DataBlockExtended.MediaLoop = mediaLoop;
  10901. OutPacket(updatePacket, ThrottleOutPacketType.Task);
  10902. }
  10903. #endregion
  10904. #region Camera
  10905. public void SendSetFollowCamProperties(UUID objectID, SortedDictionary<int, float> parameters)
  10906. {
  10907. SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties);
  10908. packet.ObjectData.ObjectID = objectID;
  10909. SetFollowCamPropertiesPacket.CameraPropertyBlock[] camPropBlock = new SetFollowCamPropertiesPacket.CameraPropertyBlock[parameters.Count];
  10910. uint idx = 0;
  10911. foreach (KeyValuePair<int, float> pair in parameters)
  10912. {
  10913. SetFollowCamPropertiesPacket.CameraPropertyBlock block = new()
  10914. {
  10915. Type = pair.Key,
  10916. Value = pair.Value
  10917. };
  10918. camPropBlock[idx++] = block;
  10919. }
  10920. packet.CameraProperty = camPropBlock;
  10921. OutPacket(packet, ThrottleOutPacketType.Task);
  10922. }
  10923. public void SendClearFollowCamProperties(UUID objectID)
  10924. {
  10925. ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties);
  10926. packet.ObjectData.ObjectID = objectID;
  10927. OutPacket(packet, ThrottleOutPacketType.Task);
  10928. }
  10929. #endregion
  10930. public void SetClientOption(string option, string value)
  10931. {
  10932. switch (option)
  10933. {
  10934. default:
  10935. break;
  10936. }
  10937. }
  10938. public string GetClientOption(string option)
  10939. {
  10940. switch (option)
  10941. {
  10942. default:
  10943. break;
  10944. }
  10945. return string.Empty;
  10946. }
  10947. #region IClientCore
  10948. private readonly Dictionary<Type, object> m_clientInterfaces = new();
  10949. /// <summary>
  10950. /// Register an interface on this client, should only be called in the constructor.
  10951. /// </summary>
  10952. /// <typeparam name="T"></typeparam>
  10953. /// <param name="iface"></param>
  10954. protected void RegisterInterface<T>(T iface)
  10955. {
  10956. lock (m_clientInterfaces)
  10957. {
  10958. m_clientInterfaces.TryAdd(typeof(T), iface);
  10959. }
  10960. }
  10961. public bool TryGet<T>(out T iface)
  10962. {
  10963. if(m_clientInterfaces.TryGetValue(typeof(T), out object o))
  10964. {
  10965. iface = (T)o;
  10966. return true;
  10967. }
  10968. iface = default;
  10969. return false;
  10970. }
  10971. public T Get<T>()
  10972. {
  10973. return (T)m_clientInterfaces[typeof(T)];
  10974. }
  10975. public void Disconnect(string reason)
  10976. {
  10977. Kick(reason);
  10978. Thread.Sleep(1000);
  10979. Disconnect();
  10980. }
  10981. public void Disconnect()
  10982. {
  10983. Close();
  10984. }
  10985. #endregion
  10986. public void RefreshGroupMembership()
  10987. {
  10988. lock(m_groupPowers)
  10989. {
  10990. GroupMembershipData activeMembership = null;
  10991. if (m_GroupsModule != null)
  10992. {
  10993. GroupMembershipData[] GroupMembership =
  10994. m_GroupsModule.GetMembershipData(m_agentId);
  10995. m_groupPowers.Clear();
  10996. if (GroupMembership != null)
  10997. {
  10998. for (int i = 0; i < GroupMembership.Length; i++)
  10999. {
  11000. m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers;
  11001. }
  11002. }
  11003. activeMembership = m_GroupsModule.GetActiveMembershipData(m_agentId);
  11004. if(activeMembership != null)
  11005. {
  11006. if(!m_groupPowers.ContainsKey(activeMembership.GroupID))
  11007. activeMembership = null;
  11008. else
  11009. {
  11010. m_activeGroupID = activeMembership.GroupID;
  11011. m_activeGroupName = activeMembership.GroupName;
  11012. m_activeGroupPowers = ActiveGroupPowers;
  11013. }
  11014. }
  11015. }
  11016. if(activeMembership is null)
  11017. {
  11018. m_activeGroupID = UUID.Zero;
  11019. m_activeGroupName = "";
  11020. m_activeGroupPowers = 0;
  11021. }
  11022. }
  11023. }
  11024. public void UpdateGroupMembership(GroupMembershipData[] data)
  11025. {
  11026. lock(m_groupPowers)
  11027. {
  11028. m_groupPowers.Clear();
  11029. if (data != null)
  11030. {
  11031. for (int i = 0; i < data.Length; i++)
  11032. m_groupPowers[data[i].GroupID] = data[i].GroupPowers;
  11033. }
  11034. }
  11035. }
  11036. public void GroupMembershipRemove(UUID GroupID)
  11037. {
  11038. lock(m_groupPowers)
  11039. {
  11040. if(m_groupPowers.ContainsKey(GroupID))
  11041. m_groupPowers.Remove(GroupID);
  11042. }
  11043. }
  11044. public void GroupMembershipAddReplace(UUID GroupID,ulong GroupPowers)
  11045. {
  11046. lock(m_groupPowers)
  11047. {
  11048. m_groupPowers[GroupID] = GroupPowers;
  11049. }
  11050. }
  11051. public string Report()
  11052. {
  11053. return m_udpClient.GetStats();
  11054. }
  11055. public string XReport(string uptime, string version)
  11056. {
  11057. return String.Empty;
  11058. }
  11059. public OSDMap OReport(string uptime, string version)
  11060. {
  11061. return new OSDMap();
  11062. }
  11063. /// <summary>
  11064. /// Make an asset request to the asset service in response to a client request.
  11065. /// </summary>
  11066. /// <param name="transferRequest"></param>
  11067. /// <param name="taskID"></param>
  11068. protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID)
  11069. {
  11070. int sourceType = transferRequest.TransferInfo.SourceType;
  11071. var requestID = sourceType switch
  11072. {
  11073. (int)SourceType.Asset => new UUID(transferRequest.TransferInfo.Params, 0),
  11074. (int)SourceType.SimInventoryItem => new UUID(transferRequest.TransferInfo.Params, 80),
  11075. (int)SourceType.SimEstate => taskID,
  11076. _ => UUID.Zero,
  11077. };
  11078. //m_log.DebugFormat(
  11079. // "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}",
  11080. // requestID, taskID, (SourceType)sourceType, Name);
  11081. //Note, the bool returned from the below function is useless since it is always false.
  11082. m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
  11083. }
  11084. /// <summary>
  11085. /// When we get a reply back from the asset service in response to a client request, send back the data.
  11086. /// </summary>
  11087. /// <param name="id"></param>
  11088. /// <param name="sender"></param>
  11089. /// <param name="asset"></param>
  11090. protected void AssetReceived(string id, Object sender, AssetBase asset)
  11091. {
  11092. TransferRequestPacket transferRequest = (TransferRequestPacket)sender;
  11093. UUID requestID = UUID.Zero;
  11094. byte source = (byte)SourceType.Asset;
  11095. if (asset is null)
  11096. {
  11097. // Try the user's asset server
  11098. IInventoryAccessModule inventoryAccessModule = Scene.RequestModuleInterface<IInventoryAccessModule>();
  11099. if (inventoryAccessModule.IsForeignUser(m_agentId, out string assetServerURL) && !string.IsNullOrEmpty(assetServerURL))
  11100. {
  11101. if (!assetServerURL.EndsWith('/') && !assetServerURL.EndsWith('='))
  11102. assetServerURL += "/";
  11103. //m_log.DebugFormat("[LLCLIENTVIEW]: asset {0} not found in local storage. Trying user's storage.", assetServerURL + id);
  11104. asset = m_scene.AssetService.Get(assetServerURL + id);
  11105. }
  11106. if (asset is null)
  11107. {
  11108. SendAssetNotFound( new AssetRequestToClient()
  11109. {
  11110. AssetInf = null,
  11111. AssetRequestSource = source,
  11112. IsTextureRequest = false,
  11113. NumPackets = 0,
  11114. Params = transferRequest.TransferInfo.Params,
  11115. RequestAssetID = requestID,
  11116. TransferRequestID = transferRequest.TransferInfo.TransferID
  11117. });
  11118. return;
  11119. }
  11120. }
  11121. if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
  11122. {
  11123. requestID = new UUID(transferRequest.TransferInfo.Params, 0);
  11124. }
  11125. else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
  11126. {
  11127. requestID = new UUID(transferRequest.TransferInfo.Params, 80);
  11128. source = (byte)SourceType.SimInventoryItem;
  11129. //m_log.Debug("asset request " + requestID);
  11130. }
  11131. // Scripts cannot be retrieved by direct request
  11132. if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset && asset.Type == (sbyte)AssetType.LSLText)
  11133. return;
  11134. // The asset is known to exist and is in our cache, so add it to the AssetRequests list
  11135. SendAsset(new AssetRequestToClient()
  11136. {
  11137. AssetInf = asset,
  11138. AssetRequestSource = source,
  11139. IsTextureRequest = false,
  11140. NumPackets = CalculateNumPackets(asset.Data),
  11141. Params = transferRequest.TransferInfo.Params,
  11142. RequestAssetID = requestID,
  11143. TransferRequestID = transferRequest.TransferInfo.TransferID
  11144. });
  11145. }
  11146. /// <summary>
  11147. /// Calculate the number of packets required to send the asset to the client.
  11148. /// </summary>
  11149. /// <param name="data"></param>
  11150. /// <returns></returns>
  11151. private static int CalculateNumPackets(byte[] data)
  11152. {
  11153. if (data is null || data.Length == 0)
  11154. return 0;
  11155. if (data.LongLength > MaxTransferBytesPerPacket)
  11156. {
  11157. // over max number of bytes so split up file
  11158. long restData = data.LongLength - MaxTransferBytesPerPacket;
  11159. int restPackets = (int)((restData + MaxTransferBytesPerPacket - 1) / MaxTransferBytesPerPacket);
  11160. return restPackets + 1;
  11161. }
  11162. else
  11163. return 1;
  11164. }
  11165. public void SendRebakeAvatarTextures(UUID textureID)
  11166. {
  11167. RebakeAvatarTexturesPacket pack =
  11168. (RebakeAvatarTexturesPacket)PacketPool.Instance.GetPacket(PacketType.RebakeAvatarTextures);
  11169. pack.TextureData = new RebakeAvatarTexturesPacket.TextureDataBlock { TextureID = textureID };
  11170. OutPacket(pack, ThrottleOutPacketType.Task);
  11171. }
  11172. public readonly struct PacketProcessor(PacketMethod m, bool doasync )
  11173. {
  11174. public readonly PacketMethod method = m;
  11175. public readonly bool Async = doasync;
  11176. }
  11177. private readonly struct StaticPacketProcessor(StaticPacketMethod m, bool doasync)
  11178. {
  11179. public readonly StaticPacketMethod method = m;
  11180. public readonly bool Async = doasync;
  11181. }
  11182. public void SendAvatarInterestsReply(UUID avatarID, uint wantMask, string wantText, uint skillsMask, string skillsText, string languages)
  11183. {
  11184. AvatarInterestsReplyPacket packet = (AvatarInterestsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarInterestsReply);
  11185. packet.AgentData.AgentID = m_agentId;
  11186. packet.AgentData.AvatarID = avatarID;
  11187. packet.PropertiesData.WantToMask = wantMask;
  11188. packet.PropertiesData.WantToText = Utils.StringToBytes(wantText);
  11189. packet.PropertiesData.SkillsMask = skillsMask;
  11190. packet.PropertiesData.SkillsText = Utils.StringToBytes(skillsText);
  11191. packet.PropertiesData.LanguagesText = Utils.StringToBytes(languages);
  11192. OutPacket(packet, ThrottleOutPacketType.Task);
  11193. }
  11194. public void SendChangeUserRights(UUID agentID, UUID friendID, int rights)
  11195. {
  11196. ChangeUserRightsPacket packet = (ChangeUserRightsPacket)PacketPool.Instance.GetPacket(PacketType.ChangeUserRights);
  11197. packet.AgentData.AgentID = agentID;
  11198. packet.Rights = new ChangeUserRightsPacket.RightsBlock[]
  11199. {
  11200. new ChangeUserRightsPacket.RightsBlock
  11201. {
  11202. AgentRelated = friendID,
  11203. RelatedRights = rights
  11204. }
  11205. };
  11206. OutPacket(packet, ThrottleOutPacketType.Task);
  11207. }
  11208. public void SendTextBoxRequest(string message, int chatChannel, string objectname, UUID ownerID, string ownerFirstName, string ownerLastName, UUID objectId)
  11209. {
  11210. ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
  11211. dialog.Data.ObjectID = objectId;
  11212. dialog.Data.ChatChannel = chatChannel;
  11213. dialog.Data.ImageID = UUID.Zero;
  11214. dialog.Data.ObjectName = Util.StringToBytes256(objectname);
  11215. // this is the username of the *owner*
  11216. dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
  11217. dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
  11218. dialog.Data.Message = Util.StringToBytes(message,512);
  11219. dialog.Buttons = new ScriptDialogPacket.ButtonsBlock[]
  11220. {
  11221. new ScriptDialogPacket.ButtonsBlock
  11222. {
  11223. ButtonLabel = Util.StringToBytes256("!!llTextBox!!")
  11224. }
  11225. };
  11226. dialog.OwnerData = new ScriptDialogPacket.OwnerDataBlock[]
  11227. {
  11228. new ScriptDialogPacket.OwnerDataBlock
  11229. {
  11230. OwnerID = ownerID
  11231. }
  11232. };
  11233. OutPacket(dialog, ThrottleOutPacketType.Task);
  11234. }
  11235. public void SendAgentTerseUpdate(ISceneEntity p)
  11236. {
  11237. if (p is ScenePresence sp)
  11238. {
  11239. UDPPacketBuffer buf = OpenSimUDPBase.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
  11240. //setup header and regioninfo block
  11241. Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7);
  11242. unsafe
  11243. {
  11244. fixed(byte* bdata = &buf.Data[0])
  11245. {
  11246. Utils.UInt64ToBytes(m_scene.RegionInfo.RegionHandle, bdata + 7);
  11247. Utils.UInt16ToBytes(Utils.FloatZeroOneToushort(m_scene.TimeDilation), bdata + 15);
  11248. bdata[17] = 1;
  11249. byte* data = bdata + 18;
  11250. CreateAvatartImprovedTerseBlock(sp, ref data);
  11251. buf.DataLength = (int)(data - bdata);
  11252. }
  11253. }
  11254. m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, true);
  11255. }
  11256. }
  11257. public void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data)
  11258. {
  11259. PlacesReplyPacket reply = null;
  11260. PlacesReplyPacket.QueryDataBlock[] dataBlocks = Array.Empty<PlacesReplyPacket.QueryDataBlock>();
  11261. for (int i = 0 ; i < data.Length ; i++)
  11262. {
  11263. PlacesReplyPacket.QueryDataBlock block = new()
  11264. {
  11265. OwnerID = data[i].OwnerID,
  11266. Name = Util.StringToBytes256(data[i].Name),
  11267. Desc = Util.StringToBytes1024(data[i].Desc),
  11268. ActualArea = data[i].ActualArea,
  11269. BillableArea = data[i].BillableArea,
  11270. Flags = data[i].Flags,
  11271. GlobalX = data[i].GlobalX,
  11272. GlobalY = data[i].GlobalY,
  11273. GlobalZ = data[i].GlobalZ,
  11274. SimName = Util.StringToBytes256(data[i].SimName),
  11275. SnapshotID = data[i].SnapshotID,
  11276. Dwell = data[i].Dwell,
  11277. Price = data[i].Price
  11278. };
  11279. if (reply is not null && reply.Length + block.Length > 1400)
  11280. {
  11281. OutPacket(reply, ThrottleOutPacketType.Task);
  11282. reply = null;
  11283. dataBlocks = Array.Empty<PlacesReplyPacket.QueryDataBlock>();
  11284. }
  11285. if (reply is null)
  11286. {
  11287. reply = (PlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.PlacesReply);
  11288. reply.AgentData.AgentID = m_agentId;
  11289. reply.AgentData.QueryID = queryID;
  11290. reply.TransactionData.TransactionID = transactionID;
  11291. reply.QueryData = dataBlocks;
  11292. }
  11293. Array.Resize(ref dataBlocks, dataBlocks.Length + 1);
  11294. dataBlocks[^1] = block;
  11295. reply.QueryData = dataBlocks;
  11296. }
  11297. if (reply != null)
  11298. OutPacket(reply, ThrottleOutPacketType.Task);
  11299. }
  11300. public void SendRemoveInventoryItems(UUID[] items)
  11301. {
  11302. IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
  11303. if (eq is null)
  11304. {
  11305. m_log.DebugFormat("[LLCLIENT]: Null event queue");
  11306. return;
  11307. }
  11308. osUTF8 sb = eq.StartEvent("RemoveInventoryItem");
  11309. LLSDxmlEncode2.AddArrayAndMap("AgentData", sb);
  11310. LLSDxmlEncode2.AddElem("AgentID", m_agentId, sb);
  11311. LLSDxmlEncode2.AddElem("SessionID", SessionId, sb);
  11312. LLSDxmlEncode2.AddEndMapAndArray(sb);
  11313. LLSDxmlEncode2.AddArray("InventoryData", sb);
  11314. foreach (UUID item in items)
  11315. {
  11316. LLSDxmlEncode2.AddMap(sb);
  11317. LLSDxmlEncode2.AddElem("ItemID",item, sb);
  11318. LLSDxmlEncode2.AddEndMap(sb);
  11319. }
  11320. LLSDxmlEncode2.AddEndArray(sb);
  11321. eq.Enqueue(eq.EndEventToBytes(sb), m_agentId);
  11322. }
  11323. public void SendRemoveInventoryFolders(UUID[] folders)
  11324. {
  11325. IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
  11326. if (eq is null)
  11327. {
  11328. m_log.DebugFormat("[LLCLIENT]: Null event queue");
  11329. return;
  11330. }
  11331. osUTF8 sb = eq.StartEvent("RemoveInventoryFolder");
  11332. LLSDxmlEncode2.AddArrayAndMap("AgentData", sb);
  11333. LLSDxmlEncode2.AddElem("AgentID", m_agentId, sb);
  11334. LLSDxmlEncode2.AddElem("SessionID", SessionId, sb);
  11335. LLSDxmlEncode2.AddEndMapAndArray(sb);
  11336. LLSDxmlEncode2.AddArray("FolderData", sb);
  11337. foreach (UUID folder in folders)
  11338. {
  11339. LLSDxmlEncode2.AddMap(sb);
  11340. LLSDxmlEncode2.AddElem("FolderID", folder, sb);
  11341. LLSDxmlEncode2.AddEndMap(sb);
  11342. }
  11343. LLSDxmlEncode2.AddEndArray(sb);
  11344. eq.Enqueue(eq.EndEventToBytes(sb), m_agentId);
  11345. }
  11346. public void SendBulkUpdateInventory(InventoryFolderBase[] folders, InventoryItemBase[] items)
  11347. {
  11348. IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
  11349. if (eq is null)
  11350. {
  11351. m_log.DebugFormat("[LLCLIENT]: Null event queue");
  11352. return;
  11353. }
  11354. osUTF8 sb = eq.StartEvent("BulkUpdateInventory");
  11355. LLSDxmlEncode2.AddArrayAndMap("AgentData", sb);
  11356. LLSDxmlEncode2.AddElem("AgentID", m_agentId, sb);
  11357. LLSDxmlEncode2.AddElem("TransactionID", UUID.Random(), sb);
  11358. LLSDxmlEncode2.AddEndMapAndArray(sb);
  11359. if(folders.Length == 0)
  11360. {
  11361. LLSDxmlEncode2.AddEmptyArray("FolderData", sb);
  11362. }
  11363. else
  11364. {
  11365. LLSDxmlEncode2.AddArray("FolderData", sb);
  11366. foreach (InventoryFolderBase folder in folders)
  11367. {
  11368. LLSDxmlEncode2.AddMap(sb);
  11369. LLSDxmlEncode2.AddElem("FolderID", folder.ID, sb);
  11370. LLSDxmlEncode2.AddElem("ParentID", folder.ParentID, sb);
  11371. LLSDxmlEncode2.AddElem("Type", (int)folder.Type, sb);
  11372. LLSDxmlEncode2.AddElem("Name", folder.Name, sb);
  11373. LLSDxmlEncode2.AddEndMap(sb);
  11374. }
  11375. LLSDxmlEncode2.AddEndArray(sb);
  11376. }
  11377. if(items.Length == 0)
  11378. {
  11379. LLSDxmlEncode2.AddEmptyArray("ItemData", sb);
  11380. }
  11381. else
  11382. {
  11383. LLSDxmlEncode2.AddArray("ItemData", sb);
  11384. foreach (InventoryItemBase item in items)
  11385. {
  11386. LLSDxmlEncode2.AddMap(sb);
  11387. LLSDxmlEncode2.AddElem("ItemID", item.ID, sb);
  11388. LLSDxmlEncode2.AddElem("CallbackID", (uint)0, sb);
  11389. LLSDxmlEncode2.AddElem("FolderID", item.Folder, sb);
  11390. LLSDxmlEncode2.AddElem("CreatorID", item.CreatorIdAsUuid, sb);
  11391. LLSDxmlEncode2.AddElem("OwnerID", item.Owner, sb);
  11392. LLSDxmlEncode2.AddElem("GroupID", item.GroupID, sb);
  11393. LLSDxmlEncode2.AddElem("BaseMask", item.BasePermissions, sb);
  11394. LLSDxmlEncode2.AddElem("OwnerMask", item.CurrentPermissions, sb);
  11395. LLSDxmlEncode2.AddElem("GroupMask", item.GroupPermissions, sb);
  11396. LLSDxmlEncode2.AddElem("EveryoneMask", item.EveryOnePermissions, sb);
  11397. LLSDxmlEncode2.AddElem("NextOwnerMask", item.NextPermissions, sb);
  11398. LLSDxmlEncode2.AddElem("GroupOwned", item.GroupOwned, sb);
  11399. LLSDxmlEncode2.AddElem("AssetID", item.AssetID, sb);
  11400. LLSDxmlEncode2.AddElem("Type", item.AssetType, sb);
  11401. LLSDxmlEncode2.AddElem("InvType", item.InvType, sb);
  11402. LLSDxmlEncode2.AddElem("Flags", item.Flags, sb);
  11403. LLSDxmlEncode2.AddElem("SaleType", item.SaleType, sb);
  11404. LLSDxmlEncode2.AddElem("SalePrice", item.SalePrice, sb);
  11405. LLSDxmlEncode2.AddElem("Name", item.Name, sb);
  11406. LLSDxmlEncode2.AddElem("Description", item.Description, sb);
  11407. LLSDxmlEncode2.AddElem("CreationDate", item.CreationDate, sb);
  11408. LLSDxmlEncode2.AddElem("CRC",
  11409. Helpers.InventoryCRC(1000, 0, (sbyte)item.InvType,
  11410. (sbyte)item.AssetType, item.AssetID,
  11411. item.GroupID, 100,
  11412. item.Owner, item.CreatorIdAsUuid,
  11413. item.ID, item.Folder,
  11414. (uint)PermissionMask.All, 1, (uint)PermissionMask.All, (uint)PermissionMask.All,
  11415. (uint)PermissionMask.All),
  11416. sb);
  11417. LLSDxmlEncode2.AddEndMap(sb);
  11418. }
  11419. LLSDxmlEncode2.AddEndArray(sb);
  11420. }
  11421. eq.Enqueue(eq.EndEventToBytes(sb), m_agentId);
  11422. }
  11423. private HashSet<string> m_outPacketsToDrop;
  11424. public bool AddOutPacketToDropSet(string packetName)
  11425. {
  11426. m_outPacketsToDrop ??= new HashSet<string>();
  11427. return m_outPacketsToDrop.Add(packetName);
  11428. }
  11429. public bool RemoveOutPacketFromDropSet(string packetName)
  11430. {
  11431. if (m_outPacketsToDrop is null)
  11432. return false;
  11433. return m_outPacketsToDrop.Remove(packetName);
  11434. }
  11435. public HashSet<string> GetOutPacketDropSet()
  11436. {
  11437. return new HashSet<string>(m_outPacketsToDrop);
  11438. }
  11439. private HashSet<string> m_inPacketsToDrop;
  11440. public bool AddInPacketToDropSet(string packetName)
  11441. {
  11442. m_inPacketsToDrop ??= new HashSet<string>();
  11443. return m_inPacketsToDrop.Add(packetName);
  11444. }
  11445. public bool RemoveInPacketFromDropSet(string packetName)
  11446. {
  11447. if (m_inPacketsToDrop is null)
  11448. return false;
  11449. return m_inPacketsToDrop.Remove(packetName);
  11450. }
  11451. public HashSet<string> GetInPacketDropSet()
  11452. {
  11453. return new HashSet<string>(m_inPacketsToDrop);
  11454. }
  11455. public uint GetViewerCaps()
  11456. {
  11457. m_SupportObjectAnimations = false;
  11458. uint ret;
  11459. if(m_supportViewerCache)
  11460. ret = m_viewerHandShakeFlags;
  11461. else
  11462. ret = (m_viewerHandShakeFlags & 4) | 2; // disable probes
  11463. if (m_scene.CapsModule != null)
  11464. {
  11465. Caps cap = m_scene.CapsModule.GetCapsForUser(CircuitCode);
  11466. if(cap != null)
  11467. {
  11468. if((cap.Flags & Caps.CapsFlags.SentSeeds) != 0)
  11469. ret |= (uint)ViewerFlags.SentSeeds;
  11470. if ((cap.Flags & Caps.CapsFlags.ObjectAnim) != 0)
  11471. {
  11472. m_SupportObjectAnimations = true;
  11473. ret |= (uint)ViewerFlags.ObjectAnim;
  11474. }
  11475. if ((cap.Flags & Caps.CapsFlags.WLEnv) != 0)
  11476. ret |= (uint)ViewerFlags.WLEnv;
  11477. if ((cap.Flags & Caps.CapsFlags.AdvEnv) != 0)
  11478. ret |= (uint)ViewerFlags.AdvEnv;
  11479. if ((cap.Flags & Caps.CapsFlags.PBR) != 0)
  11480. {
  11481. ret |= (uint)ViewerFlags.PBR;
  11482. m_SupportPBR = true;
  11483. }
  11484. if ((cap.Flags & Caps.CapsFlags.TPBR) != 0)
  11485. {
  11486. ret |= (uint)ViewerFlags.TPBR;
  11487. SupportTerrainPBR = true;
  11488. }
  11489. }
  11490. }
  11491. ret |= (uint)(ViewerFlags & (ViewerFlags.SentTPBR));
  11492. ViewerFlags = (ViewerFlags)ret;
  11493. return ret;
  11494. }
  11495. }
  11496. }