LSL_Api.cs 349 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761
  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;
  29. using System.Collections.Generic;
  30. using System.Runtime.Remoting.Lifetime;
  31. using System.Text;
  32. using System.Threading;
  33. using System.Text.RegularExpressions;
  34. using Nini.Config;
  35. using log4net;
  36. using OpenMetaverse;
  37. using OpenMetaverse.Packets;
  38. using OpenSim;
  39. using OpenSim.Framework;
  40. using OpenSim.Framework.Communications.Cache;
  41. using OpenSim.Region.CoreModules;
  42. using OpenSim.Region.Framework.Interfaces;
  43. using OpenSim.Region.CoreModules.World.Land;
  44. using OpenSim.Region.CoreModules.World.Terrain;
  45. using OpenSim.Region.Framework.Scenes;
  46. using OpenSim.Region.Physics.Manager;
  47. using OpenSim.Region.ScriptEngine.Shared;
  48. using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
  49. using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
  50. using OpenSim.Region.ScriptEngine.Interfaces;
  51. using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
  52. using OpenSim.Services.Interfaces;
  53. using GridRegion = OpenSim.Services.Interfaces.GridRegion;
  54. using AssetLandmark = OpenSim.Framework.AssetLandmark;
  55. using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
  56. using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
  57. using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  58. using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
  59. using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
  60. using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  61. using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
  62. using System.Reflection;
  63. namespace OpenSim.Region.ScriptEngine.Shared.Api
  64. {
  65. /// <summary>
  66. /// Contains all LSL ll-functions. This class will be in Default AppDomain.
  67. /// </summary>
  68. public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
  69. {
  70. //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  71. protected IScriptEngine m_ScriptEngine;
  72. protected SceneObjectPart m_host;
  73. protected uint m_localID;
  74. protected UUID m_itemID;
  75. protected bool throwErrorOnNotImplemented = true;
  76. protected AsyncCommandManager AsyncCommands = null;
  77. protected float m_ScriptDelayFactor = 1.0f;
  78. protected float m_ScriptDistanceFactor = 1.0f;
  79. protected float m_MinTimerInterval = 0.5f;
  80. protected DateTime m_timer = DateTime.Now;
  81. protected bool m_waitingForScriptAnswer = false;
  82. protected bool m_automaticLinkPermission = false;
  83. protected IMessageTransferModule m_TransferModule = null;
  84. protected int m_notecardLineReadCharsMax = 255;
  85. protected int m_scriptConsoleChannel = 0;
  86. protected bool m_scriptConsoleChannelEnabled = false;
  87. protected IUrlModule m_UrlModule = null;
  88. public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
  89. {
  90. m_ScriptEngine = ScriptEngine;
  91. m_host = host;
  92. m_localID = localID;
  93. m_itemID = itemID;
  94. m_ScriptDelayFactor = m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
  95. m_ScriptDistanceFactor = m_ScriptEngine.Config.GetFloat("ScriptDistanceLimitFactor", 1.0f);
  96. m_MinTimerInterval = m_ScriptEngine.Config.GetFloat("MinTimerInterval", 0.5f);
  97. m_automaticLinkPermission = m_ScriptEngine.Config.GetBoolean("AutomaticLinkPermission", false);
  98. m_scriptConsoleChannel = m_ScriptEngine.Config.GetInt("ScriptConsoleChannel", 0);
  99. m_scriptConsoleChannelEnabled = (m_scriptConsoleChannel != 0);
  100. m_notecardLineReadCharsMax = m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255);
  101. if (m_notecardLineReadCharsMax > 65535)
  102. m_notecardLineReadCharsMax = 65535;
  103. m_TransferModule = m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
  104. m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
  105. if (m_UrlModule != null)
  106. {
  107. m_ScriptEngine.OnScriptRemoved += m_UrlModule.ScriptRemoved;
  108. m_ScriptEngine.OnObjectRemoved += m_UrlModule.ObjectRemoved;
  109. }
  110. AsyncCommands = new AsyncCommandManager(ScriptEngine);
  111. }
  112. public override Object InitializeLifetimeService()
  113. {
  114. ILease lease = (ILease)base.InitializeLifetimeService();
  115. if (lease.CurrentState == LeaseState.Initial)
  116. {
  117. lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
  118. // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
  119. // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
  120. }
  121. return lease;
  122. }
  123. protected virtual void ScriptSleep(int delay)
  124. {
  125. delay = (int)((float)delay * m_ScriptDelayFactor);
  126. if (delay == 0)
  127. return;
  128. System.Threading.Thread.Sleep(delay);
  129. }
  130. public Scene World
  131. {
  132. get { return m_ScriptEngine.World; }
  133. }
  134. public void state(string newState)
  135. {
  136. m_ScriptEngine.SetState(m_itemID, newState);
  137. }
  138. /// <summary>
  139. /// Reset the named script. The script must be present
  140. /// in the same prim.
  141. /// </summary>
  142. public void llResetScript()
  143. {
  144. m_host.AddScriptLPS(1);
  145. m_ScriptEngine.ApiResetScript(m_itemID);
  146. }
  147. public void llResetOtherScript(string name)
  148. {
  149. UUID item;
  150. m_host.AddScriptLPS(1);
  151. if ((item = ScriptByName(name)) != UUID.Zero)
  152. m_ScriptEngine.ResetScript(item);
  153. else
  154. ShoutError("llResetOtherScript: script "+name+" not found");
  155. }
  156. public LSL_Integer llGetScriptState(string name)
  157. {
  158. UUID item;
  159. m_host.AddScriptLPS(1);
  160. if ((item = ScriptByName(name)) != UUID.Zero)
  161. {
  162. return m_ScriptEngine.GetScriptState(item) ?1:0;
  163. }
  164. ShoutError("llGetScriptState: script "+name+" not found");
  165. // If we didn't find it, then it's safe to
  166. // assume it is not running.
  167. return 0;
  168. }
  169. public void llSetScriptState(string name, int run)
  170. {
  171. UUID item;
  172. m_host.AddScriptLPS(1);
  173. // These functions are supposed to be robust,
  174. // so get the state one step at a time.
  175. if ((item = ScriptByName(name)) != UUID.Zero)
  176. {
  177. m_ScriptEngine.SetScriptState(item, run == 0 ? false : true);
  178. }
  179. else
  180. {
  181. ShoutError("llSetScriptState: script "+name+" not found");
  182. }
  183. }
  184. public List<SceneObjectPart> GetLinkParts(int linkType)
  185. {
  186. List<SceneObjectPart> ret = new List<SceneObjectPart>();
  187. ret.Add(m_host);
  188. switch (linkType)
  189. {
  190. case ScriptBaseClass.LINK_SET:
  191. if (m_host.ParentGroup != null)
  192. return new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
  193. return ret;
  194. case ScriptBaseClass.LINK_ROOT:
  195. if (m_host.ParentGroup != null)
  196. {
  197. ret = new List<SceneObjectPart>();
  198. ret.Add(m_host.ParentGroup.RootPart);
  199. return ret;
  200. }
  201. return ret;
  202. case ScriptBaseClass.LINK_ALL_OTHERS:
  203. if (m_host.ParentGroup == null)
  204. return new List<SceneObjectPart>();
  205. ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
  206. if (ret.Contains(m_host))
  207. ret.Remove(m_host);
  208. return ret;
  209. case ScriptBaseClass.LINK_ALL_CHILDREN:
  210. if (m_host.ParentGroup == null)
  211. return new List<SceneObjectPart>();
  212. ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
  213. if (ret.Contains(m_host.ParentGroup.RootPart))
  214. ret.Remove(m_host.ParentGroup.RootPart);
  215. return ret;
  216. case ScriptBaseClass.LINK_THIS:
  217. return ret;
  218. default:
  219. if (linkType < 0 || m_host.ParentGroup == null)
  220. return new List<SceneObjectPart>();
  221. SceneObjectPart target = m_host.ParentGroup.GetLinkNumPart(linkType);
  222. if (target == null)
  223. return new List<SceneObjectPart>();
  224. ret = new List<SceneObjectPart>();
  225. ret.Add(target);
  226. return ret;
  227. }
  228. }
  229. protected UUID InventorySelf()
  230. {
  231. UUID invItemID = new UUID();
  232. lock (m_host.TaskInventory)
  233. {
  234. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  235. {
  236. if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
  237. {
  238. invItemID = inv.Key;
  239. break;
  240. }
  241. }
  242. }
  243. return invItemID;
  244. }
  245. protected UUID InventoryKey(string name, int type)
  246. {
  247. m_host.AddScriptLPS(1);
  248. lock (m_host.TaskInventory)
  249. {
  250. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  251. {
  252. if (inv.Value.Name == name)
  253. {
  254. if (inv.Value.Type != type)
  255. return UUID.Zero;
  256. return inv.Value.AssetID;
  257. }
  258. }
  259. }
  260. return UUID.Zero;
  261. }
  262. protected UUID InventoryKey(string name)
  263. {
  264. m_host.AddScriptLPS(1);
  265. lock (m_host.TaskInventory)
  266. {
  267. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  268. {
  269. if (inv.Value.Name == name)
  270. {
  271. return inv.Value.AssetID;
  272. }
  273. }
  274. }
  275. return UUID.Zero;
  276. }
  277. /// <summary>
  278. /// accepts a valid UUID, -or- a name of an inventory item.
  279. /// Returns a valid UUID or UUID.Zero if key invalid and item not found
  280. /// in prim inventory.
  281. /// </summary>
  282. /// <param name="k"></param>
  283. /// <returns></returns>
  284. protected UUID KeyOrName(string k)
  285. {
  286. UUID key = UUID.Zero;
  287. // if we can parse the string as a key, use it.
  288. if (UUID.TryParse(k, out key))
  289. {
  290. return key;
  291. }
  292. // else try to locate the name in inventory of object. found returns key,
  293. // not found returns UUID.Zero which will translate to the default particle texture
  294. else
  295. {
  296. return InventoryKey(k);
  297. }
  298. }
  299. // convert a LSL_Rotation to a Quaternion
  300. protected Quaternion Rot2Quaternion(LSL_Rotation r)
  301. {
  302. Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
  303. q.Normalize();
  304. return q;
  305. }
  306. //These are the implementations of the various ll-functions used by the LSL scripts.
  307. public LSL_Float llSin(double f)
  308. {
  309. m_host.AddScriptLPS(1);
  310. return (double)Math.Sin(f);
  311. }
  312. public LSL_Float llCos(double f)
  313. {
  314. m_host.AddScriptLPS(1);
  315. return (double)Math.Cos(f);
  316. }
  317. public LSL_Float llTan(double f)
  318. {
  319. m_host.AddScriptLPS(1);
  320. return (double)Math.Tan(f);
  321. }
  322. public LSL_Float llAtan2(double x, double y)
  323. {
  324. m_host.AddScriptLPS(1);
  325. return (double)Math.Atan2(x, y);
  326. }
  327. public LSL_Float llSqrt(double f)
  328. {
  329. m_host.AddScriptLPS(1);
  330. return (double)Math.Sqrt(f);
  331. }
  332. public LSL_Float llPow(double fbase, double fexponent)
  333. {
  334. m_host.AddScriptLPS(1);
  335. return (double)Math.Pow(fbase, fexponent);
  336. }
  337. public LSL_Integer llAbs(int i)
  338. {
  339. // changed to replicate LSL behaviour whereby minimum int value is returned untouched.
  340. m_host.AddScriptLPS(1);
  341. if (i == Int32.MinValue)
  342. return i;
  343. else
  344. return (int)Math.Abs(i);
  345. }
  346. public LSL_Float llFabs(double f)
  347. {
  348. m_host.AddScriptLPS(1);
  349. return (double)Math.Abs(f);
  350. }
  351. public LSL_Float llFrand(double mag)
  352. {
  353. m_host.AddScriptLPS(1);
  354. lock (Util.RandomClass)
  355. {
  356. return Util.RandomClass.NextDouble() * mag;
  357. }
  358. }
  359. public LSL_Integer llFloor(double f)
  360. {
  361. m_host.AddScriptLPS(1);
  362. return (int)Math.Floor(f);
  363. }
  364. public LSL_Integer llCeil(double f)
  365. {
  366. m_host.AddScriptLPS(1);
  367. return (int)Math.Ceiling(f);
  368. }
  369. // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
  370. public LSL_Integer llRound(double f)
  371. {
  372. m_host.AddScriptLPS(1);
  373. return (int)Math.Round(f, MidpointRounding.AwayFromZero);
  374. }
  375. //This next group are vector operations involving squaring and square root. ckrinke
  376. public LSL_Float llVecMag(LSL_Vector v)
  377. {
  378. m_host.AddScriptLPS(1);
  379. return LSL_Vector.Mag(v);
  380. }
  381. public LSL_Vector llVecNorm(LSL_Vector v)
  382. {
  383. m_host.AddScriptLPS(1);
  384. double mag = LSL_Vector.Mag(v);
  385. LSL_Vector nor = new LSL_Vector();
  386. nor.x = v.x / mag;
  387. nor.y = v.y / mag;
  388. nor.z = v.z / mag;
  389. return nor;
  390. }
  391. public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
  392. {
  393. m_host.AddScriptLPS(1);
  394. double dx = a.x - b.x;
  395. double dy = a.y - b.y;
  396. double dz = a.z - b.z;
  397. return Math.Sqrt(dx * dx + dy * dy + dz * dz);
  398. }
  399. //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
  400. // Utility function for llRot2Euler
  401. // normalize an angle between -PI and PI (-180 to +180 degrees)
  402. protected double NormalizeAngle(double angle)
  403. {
  404. if (angle > -Math.PI && angle < Math.PI)
  405. return angle;
  406. int numPis = (int)(Math.PI / angle);
  407. double remainder = angle - Math.PI * numPis;
  408. if (numPis % 2 == 1)
  409. return Math.PI - angle;
  410. return remainder;
  411. }
  412. // Old implementation of llRot2Euler, now normalized
  413. public LSL_Vector llRot2Euler(LSL_Rotation r)
  414. {
  415. m_host.AddScriptLPS(1);
  416. //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke
  417. LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s);
  418. double m = (t.x + t.y + t.z + t.s);
  419. if (m == 0) return new LSL_Vector();
  420. double n = 2 * (r.y * r.s + r.x * r.z);
  421. double p = m * m - n * n;
  422. if (p > 0)
  423. return new LSL_Vector(NormalizeAngle(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s))),
  424. NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))),
  425. NormalizeAngle(Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))));
  426. else if (n > 0)
  427. return new LSL_Vector(0.0, Math.PI * 0.5, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
  428. else
  429. return new LSL_Vector(0.0, -Math.PI * 0.5, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
  430. }
  431. /* From wiki:
  432. The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
  433. in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
  434. a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
  435. vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
  436. */
  437. /* How we arrived at this llEuler2Rot
  438. *
  439. * Experiment in SL to determine conventions:
  440. * llEuler2Rot(<PI,0,0>)=<1,0,0,0>
  441. * llEuler2Rot(<0,PI,0>)=<0,1,0,0>
  442. * llEuler2Rot(<0,0,PI>)=<0,0,1,0>
  443. *
  444. * Important facts about Quaternions
  445. * - multiplication is non-commutative (a*b != b*a)
  446. * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
  447. *
  448. * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
  449. * Qx = c1+i*s1
  450. * Qy = c2+j*s2;
  451. * Qz = c3+k*s3;
  452. *
  453. * Rotations applied in order (from above) Z, Y, X
  454. * Q = (Qz * Qy) * Qx
  455. * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
  456. * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
  457. * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
  458. * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3
  459. * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3 -s1*s2*s3
  460. * regroup: x=i*(s1*c2*c3+c1*s2*s3)
  461. * y=j*(c1*s2*c3-s1*c2*s3)
  462. * z=k*(s1*s2*c3+c1*c2*s3)
  463. * s= c1*c2*c3-s1*s2*s3
  464. *
  465. * This implementation agrees with the functions found here:
  466. * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
  467. * And with the results in SL.
  468. *
  469. * It's also possible to calculate llEuler2Rot by direct multiplication of
  470. * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
  471. * from the wiki).
  472. * Apparently in some cases this is better from a numerical precision perspective?
  473. */
  474. public LSL_Rotation llEuler2Rot(LSL_Vector v)
  475. {
  476. m_host.AddScriptLPS(1);
  477. double x,y,z,s;
  478. double c1 = Math.Cos(v.x * 0.5);
  479. double c2 = Math.Cos(v.y * 0.5);
  480. double c3 = Math.Cos(v.z * 0.5);
  481. double s1 = Math.Sin(v.x * 0.5);
  482. double s2 = Math.Sin(v.y * 0.5);
  483. double s3 = Math.Sin(v.z * 0.5);
  484. x = s1 * c2 * c3 + c1 * s2 * s3;
  485. y = c1 * s2 * c3 - s1 * c2 * s3;
  486. z = s1 * s2 * c3 + c1 * c2 * s3;
  487. s = c1 * c2 * c3 - s1 * s2 * s3;
  488. return new LSL_Rotation(x, y, z, s);
  489. }
  490. public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
  491. {
  492. m_host.AddScriptLPS(1);
  493. double s;
  494. double tr = fwd.x + left.y + up.z + 1.0;
  495. if (tr >= 1.0)
  496. {
  497. s = 0.5 / Math.Sqrt(tr);
  498. return new LSL_Rotation(
  499. (left.z - up.y) * s,
  500. (up.x - fwd.z) * s,
  501. (fwd.y - left.x) * s,
  502. 0.25 / s);
  503. }
  504. else
  505. {
  506. double max = (left.y > up.z) ? left.y : up.z;
  507. if (max < fwd.x)
  508. {
  509. s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0);
  510. double x = s * 0.5;
  511. s = 0.5 / s;
  512. return new LSL_Rotation(
  513. x,
  514. (fwd.y + left.x) * s,
  515. (up.x + fwd.z) * s,
  516. (left.z - up.y) * s);
  517. }
  518. else if (max == left.y)
  519. {
  520. s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0);
  521. double y = s * 0.5;
  522. s = 0.5 / s;
  523. return new LSL_Rotation(
  524. (fwd.y + left.x) * s,
  525. y,
  526. (left.z + up.y) * s,
  527. (up.x - fwd.z) * s);
  528. }
  529. else
  530. {
  531. s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0);
  532. double z = s * 0.5;
  533. s = 0.5 / s;
  534. return new LSL_Rotation(
  535. (up.x + fwd.z) * s,
  536. (left.z + up.y) * s,
  537. z,
  538. (fwd.y - left.x) * s);
  539. }
  540. }
  541. }
  542. public LSL_Vector llRot2Fwd(LSL_Rotation r)
  543. {
  544. m_host.AddScriptLPS(1);
  545. double x, y, z, m;
  546. m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
  547. // m is always greater than zero
  548. // if m is not equal to 1 then Rotation needs to be normalized
  549. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  550. {
  551. m = 1.0 / Math.Sqrt(m);
  552. r.x *= m;
  553. r.y *= m;
  554. r.z *= m;
  555. r.s *= m;
  556. }
  557. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  558. x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s;
  559. y = 2 * (r.x * r.y + r.z * r.s);
  560. z = 2 * (r.x * r.z - r.y * r.s);
  561. return (new LSL_Vector(x, y, z));
  562. }
  563. public LSL_Vector llRot2Left(LSL_Rotation r)
  564. {
  565. m_host.AddScriptLPS(1);
  566. double x, y, z, m;
  567. m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
  568. // m is always greater than zero
  569. // if m is not equal to 1 then Rotation needs to be normalized
  570. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  571. {
  572. m = 1.0 / Math.Sqrt(m);
  573. r.x *= m;
  574. r.y *= m;
  575. r.z *= m;
  576. r.s *= m;
  577. }
  578. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  579. x = 2 * (r.x * r.y - r.z * r.s);
  580. y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s;
  581. z = 2 * (r.x * r.s + r.y * r.z);
  582. return (new LSL_Vector(x, y, z));
  583. }
  584. public LSL_Vector llRot2Up(LSL_Rotation r)
  585. {
  586. m_host.AddScriptLPS(1);
  587. double x, y, z, m;
  588. m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
  589. // m is always greater than zero
  590. // if m is not equal to 1 then Rotation needs to be normalized
  591. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  592. {
  593. m = 1.0 / Math.Sqrt(m);
  594. r.x *= m;
  595. r.y *= m;
  596. r.z *= m;
  597. r.s *= m;
  598. }
  599. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  600. x = 2 * (r.x * r.z + r.y * r.s);
  601. y = 2 * (-r.x * r.s + r.y * r.z);
  602. z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s;
  603. return (new LSL_Vector(x, y, z));
  604. }
  605. public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
  606. {
  607. //A and B should both be normalized
  608. m_host.AddScriptLPS(1);
  609. double dotProduct = LSL_Vector.Dot(a, b);
  610. LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
  611. double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
  612. double angle = Math.Acos(dotProduct / magProduct);
  613. LSL_Vector axis = LSL_Vector.Norm(crossProduct);
  614. double s = Math.Sin(angle / 2);
  615. double x = axis.x * s;
  616. double y = axis.y * s;
  617. double z = axis.z * s;
  618. double w = Math.Cos(angle / 2);
  619. if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
  620. return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  621. return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
  622. }
  623. public void llWhisper(int channelID, string text)
  624. {
  625. m_host.AddScriptLPS(1);
  626. if (text.Length > 1023)
  627. text = text.Substring(0, 1023);
  628. World.SimChat(Utils.StringToBytes(text),
  629. ChatTypeEnum.Whisper, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
  630. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  631. wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
  632. }
  633. public void llSay(int channelID, string text)
  634. {
  635. m_host.AddScriptLPS(1);
  636. if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
  637. {
  638. Console.WriteLine(text);
  639. }
  640. else
  641. {
  642. if (text.Length > 1023)
  643. text = text.Substring(0, 1023);
  644. World.SimChat(Utils.StringToBytes(text),
  645. ChatTypeEnum.Say, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
  646. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  647. wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
  648. }
  649. }
  650. public void llShout(int channelID, string text)
  651. {
  652. m_host.AddScriptLPS(1);
  653. if (text.Length > 1023)
  654. text = text.Substring(0, 1023);
  655. World.SimChat(Utils.StringToBytes(text),
  656. ChatTypeEnum.Shout, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
  657. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  658. wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
  659. }
  660. public void llRegionSay(int channelID, string text)
  661. {
  662. if (channelID == 0)
  663. {
  664. LSLError("Cannot use llRegionSay() on channel 0");
  665. return;
  666. }
  667. if (text.Length > 1023)
  668. text = text.Substring(0, 1023);
  669. m_host.AddScriptLPS(1);
  670. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  671. wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
  672. }
  673. public LSL_Integer llListen(int channelID, string name, string ID, string msg)
  674. {
  675. m_host.AddScriptLPS(1);
  676. UUID keyID;
  677. UUID.TryParse(ID, out keyID);
  678. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  679. return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, keyID, msg);
  680. }
  681. public void llListenControl(int number, int active)
  682. {
  683. m_host.AddScriptLPS(1);
  684. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  685. wComm.ListenControl(m_itemID, number, active);
  686. }
  687. public void llListenRemove(int number)
  688. {
  689. m_host.AddScriptLPS(1);
  690. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  691. wComm.ListenRemove(m_itemID, number);
  692. }
  693. public void llSensor(string name, string id, int type, double range, double arc)
  694. {
  695. m_host.AddScriptLPS(1);
  696. UUID keyID = UUID.Zero;
  697. UUID.TryParse(id, out keyID);
  698. AsyncCommands.SensorRepeatPlugin.SenseOnce(m_localID, m_itemID, name, keyID, type, range, arc, m_host);
  699. }
  700. public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
  701. {
  702. m_host.AddScriptLPS(1);
  703. UUID keyID = UUID.Zero;
  704. UUID.TryParse(id, out keyID);
  705. AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_localID, m_itemID, name, keyID, type, range, arc, rate, m_host);
  706. }
  707. public void llSensorRemove()
  708. {
  709. m_host.AddScriptLPS(1);
  710. AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_localID, m_itemID);
  711. }
  712. public string resolveName(UUID objecUUID)
  713. {
  714. // try avatar username surname
  715. CachedUserInfo profile = World.CommsManager.UserProfileCacheService.GetUserDetails(objecUUID);
  716. if (profile != null && profile.UserProfile != null)
  717. {
  718. string avatarname = profile.UserProfile.FirstName + " " + profile.UserProfile.SurName;
  719. return avatarname;
  720. }
  721. // try an scene object
  722. SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID);
  723. if (SOP != null)
  724. {
  725. string objectname = SOP.Name;
  726. return objectname;
  727. }
  728. EntityBase SensedObject;
  729. World.Entities.TryGetValue(objecUUID, out SensedObject);
  730. if (SensedObject == null)
  731. {
  732. IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>();
  733. if (groups != null)
  734. {
  735. GroupRecord gr = groups.GetGroupRecord(objecUUID);
  736. if (gr != null)
  737. return gr.GroupName;
  738. }
  739. return String.Empty;
  740. }
  741. return SensedObject.Name;
  742. }
  743. public LSL_String llDetectedName(int number)
  744. {
  745. m_host.AddScriptLPS(1);
  746. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number);
  747. if (detectedParams == null)
  748. return String.Empty;
  749. return detectedParams.Name;
  750. }
  751. public LSL_String llDetectedKey(int number)
  752. {
  753. m_host.AddScriptLPS(1);
  754. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number);
  755. if (detectedParams == null)
  756. return String.Empty;
  757. return detectedParams.Key.ToString();
  758. }
  759. public LSL_String llDetectedOwner(int number)
  760. {
  761. m_host.AddScriptLPS(1);
  762. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number);
  763. if (detectedParams == null)
  764. return String.Empty;
  765. return detectedParams.Owner.ToString();
  766. }
  767. public LSL_Integer llDetectedType(int number)
  768. {
  769. m_host.AddScriptLPS(1);
  770. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number);
  771. if (detectedParams == null)
  772. return 0;
  773. return new LSL_Integer(detectedParams.Type);
  774. }
  775. public LSL_Vector llDetectedPos(int number)
  776. {
  777. m_host.AddScriptLPS(1);
  778. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number);
  779. if (detectedParams == null)
  780. return new LSL_Vector();
  781. return detectedParams.Position;
  782. }
  783. public LSL_Vector llDetectedVel(int number)
  784. {
  785. m_host.AddScriptLPS(1);
  786. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number);
  787. if (detectedParams == null)
  788. return new LSL_Vector();
  789. return detectedParams.Velocity;
  790. }
  791. public LSL_Vector llDetectedGrab(int number)
  792. {
  793. m_host.AddScriptLPS(1);
  794. DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number);
  795. if (parms == null)
  796. return new LSL_Vector(0, 0, 0);
  797. return parms.OffsetPos;
  798. }
  799. public LSL_Rotation llDetectedRot(int number)
  800. {
  801. m_host.AddScriptLPS(1);
  802. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number);
  803. if (detectedParams == null)
  804. return new LSL_Rotation();
  805. return detectedParams.Rotation;
  806. }
  807. public LSL_Integer llDetectedGroup(int number)
  808. {
  809. m_host.AddScriptLPS(1);
  810. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number);
  811. if (detectedParams == null)
  812. return new LSL_Integer(0);
  813. if (m_host.GroupID == detectedParams.Group)
  814. return new LSL_Integer(1);
  815. return new LSL_Integer(0);
  816. }
  817. public LSL_Integer llDetectedLinkNumber(int number)
  818. {
  819. m_host.AddScriptLPS(1);
  820. DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number);
  821. if (parms == null)
  822. return new LSL_Integer(0);
  823. return new LSL_Integer(parms.LinkNum);
  824. }
  825. /// <summary>
  826. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details
  827. /// </summary>
  828. public LSL_Vector llDetectedTouchBinormal(int index)
  829. {
  830. m_host.AddScriptLPS(1);
  831. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, index);
  832. if (detectedParams == null)
  833. return new LSL_Vector();
  834. return detectedParams.TouchBinormal;
  835. }
  836. /// <summary>
  837. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchFace for details
  838. /// </summary>
  839. public LSL_Integer llDetectedTouchFace(int index)
  840. {
  841. m_host.AddScriptLPS(1);
  842. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, index);
  843. if (detectedParams == null)
  844. return new LSL_Integer(-1);
  845. return new LSL_Integer(detectedParams.TouchFace);
  846. }
  847. /// <summary>
  848. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchNormal for details
  849. /// </summary>
  850. public LSL_Vector llDetectedTouchNormal(int index)
  851. {
  852. m_host.AddScriptLPS(1);
  853. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, index);
  854. if (detectedParams == null)
  855. return new LSL_Vector();
  856. return detectedParams.TouchNormal;
  857. }
  858. /// <summary>
  859. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchPos for details
  860. /// </summary>
  861. public LSL_Vector llDetectedTouchPos(int index)
  862. {
  863. m_host.AddScriptLPS(1);
  864. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, index);
  865. if (detectedParams == null)
  866. return new LSL_Vector();
  867. return detectedParams.TouchPos;
  868. }
  869. /// <summary>
  870. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchST for details
  871. /// </summary>
  872. public LSL_Vector llDetectedTouchST(int index)
  873. {
  874. m_host.AddScriptLPS(1);
  875. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, index);
  876. if (detectedParams == null)
  877. return new LSL_Vector(-1.0, -1.0, 0.0);
  878. return detectedParams.TouchST;
  879. }
  880. /// <summary>
  881. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchUV for details
  882. /// </summary>
  883. public LSL_Vector llDetectedTouchUV(int index)
  884. {
  885. m_host.AddScriptLPS(1);
  886. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, index);
  887. if (detectedParams == null)
  888. return new LSL_Vector(-1.0, -1.0, 0.0);
  889. return detectedParams.TouchUV;
  890. }
  891. public void llDie()
  892. {
  893. m_host.AddScriptLPS(1);
  894. throw new SelfDeleteException();
  895. }
  896. public LSL_Float llGround(LSL_Vector offset)
  897. {
  898. m_host.AddScriptLPS(1);
  899. Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x,
  900. (float)offset.y,
  901. (float)offset.z);
  902. //Get the slope normal. This gives us the equation of the plane tangent to the slope.
  903. LSL_Vector vsn = llGroundNormal(offset);
  904. // Clamp to valid position
  905. if (pos.X < 0)
  906. pos.X = 0;
  907. else if (pos.X >= World.Heightmap.Width)
  908. pos.X = World.Heightmap.Width - 1;
  909. if (pos.Y < 0)
  910. pos.Y = 0;
  911. else if (pos.Y >= World.Heightmap.Height)
  912. pos.Y = World.Heightmap.Height - 1;
  913. //Get the height for the integer coordinates from the Heightmap
  914. float baseheight = (float)World.Heightmap[(int)pos.X, (int)pos.Y];
  915. //Calculate the difference between the actual coordinates and the integer coordinates
  916. float xdiff = pos.X - (float)((int)pos.X);
  917. float ydiff = pos.Y - (float)((int)pos.Y);
  918. //Use the equation of the tangent plane to adjust the height to account for slope
  919. return (((vsn.x * xdiff) + (vsn.y * ydiff)) / (-1 * vsn.z)) + baseheight;
  920. }
  921. public LSL_Float llCloud(LSL_Vector offset)
  922. {
  923. m_host.AddScriptLPS(1);
  924. float cloudCover = 0f;
  925. ICloudModule module = World.RequestModuleInterface<ICloudModule>();
  926. if (module != null)
  927. {
  928. Vector3 pos = m_host.GetWorldPosition();
  929. int x = (int)(pos.X + offset.x);
  930. int y = (int)(pos.Y + offset.y);
  931. cloudCover = module.CloudCover(x, y, 0);
  932. }
  933. return cloudCover;
  934. }
  935. public LSL_Vector llWind(LSL_Vector offset)
  936. {
  937. m_host.AddScriptLPS(1);
  938. LSL_Vector wind = new LSL_Vector(0, 0, 0);
  939. IWindModule module = World.RequestModuleInterface<IWindModule>();
  940. if (module != null)
  941. {
  942. Vector3 pos = m_host.GetWorldPosition();
  943. int x = (int)(pos.X + offset.x);
  944. int y = (int)(pos.Y + offset.y);
  945. Vector3 windSpeed = module.WindSpeed(x, y, 0);
  946. wind.x = windSpeed.X;
  947. wind.y = windSpeed.Y;
  948. }
  949. return wind;
  950. }
  951. public void llSetStatus(int status, int value)
  952. {
  953. m_host.AddScriptLPS(1);
  954. int statusrotationaxis = 0;
  955. if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS)
  956. {
  957. if (value != 0)
  958. {
  959. SceneObjectGroup group = m_host.ParentGroup;
  960. if (group == null)
  961. return;
  962. bool allow = true;
  963. foreach (SceneObjectPart part in group.Children.Values)
  964. {
  965. if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
  966. {
  967. allow = false;
  968. break;
  969. }
  970. }
  971. if (!allow)
  972. return;
  973. m_host.ScriptSetPhysicsStatus(true);
  974. }
  975. else
  976. m_host.ScriptSetPhysicsStatus(false);
  977. }
  978. if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM)
  979. {
  980. if (value != 0)
  981. m_host.ScriptSetPhantomStatus(true);
  982. else
  983. m_host.ScriptSetPhantomStatus(false);
  984. }
  985. if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS)
  986. {
  987. m_host.AddFlag(PrimFlags.CastShadows);
  988. }
  989. if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X)
  990. {
  991. statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X;
  992. }
  993. if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y)
  994. {
  995. statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y;
  996. }
  997. if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z)
  998. {
  999. statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z;
  1000. }
  1001. if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB)
  1002. {
  1003. NotImplemented("llSetStatus - STATUS_BLOCK_GRAB");
  1004. }
  1005. if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE)
  1006. {
  1007. if (value != 0)
  1008. m_host.SetDieAtEdge(true);
  1009. else
  1010. m_host.SetDieAtEdge(false);
  1011. }
  1012. if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
  1013. {
  1014. NotImplemented("llSetStatus - STATUS_RETURN_AT_EDGE");
  1015. }
  1016. if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX)
  1017. {
  1018. NotImplemented("llSetStatus - STATUS_SANDBOX");
  1019. }
  1020. if (statusrotationaxis != 0)
  1021. {
  1022. m_host.SetAxisRotation(statusrotationaxis, value);
  1023. }
  1024. }
  1025. public LSL_Integer llGetStatus(int status)
  1026. {
  1027. m_host.AddScriptLPS(1);
  1028. // m_log.Debug(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString());
  1029. switch (status)
  1030. {
  1031. case ScriptBaseClass.STATUS_PHYSICS:
  1032. if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics)
  1033. {
  1034. return 1;
  1035. }
  1036. return 0;
  1037. case ScriptBaseClass.STATUS_PHANTOM:
  1038. if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom)
  1039. {
  1040. return 1;
  1041. }
  1042. return 0;
  1043. case ScriptBaseClass.STATUS_CAST_SHADOWS:
  1044. if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows)
  1045. {
  1046. return 1;
  1047. }
  1048. return 0;
  1049. case ScriptBaseClass.STATUS_BLOCK_GRAB:
  1050. NotImplemented("llGetStatus - STATUS_BLOCK_GRAB");
  1051. return 0;
  1052. case ScriptBaseClass.STATUS_DIE_AT_EDGE:
  1053. if (m_host.GetDieAtEdge())
  1054. return 1;
  1055. else
  1056. return 0;
  1057. case ScriptBaseClass.STATUS_RETURN_AT_EDGE:
  1058. NotImplemented("llGetStatus - STATUS_RETURN_AT_EDGE");
  1059. return 0;
  1060. case ScriptBaseClass.STATUS_ROTATE_X:
  1061. NotImplemented("llGetStatus - STATUS_ROTATE_X");
  1062. return 0;
  1063. case ScriptBaseClass.STATUS_ROTATE_Y:
  1064. NotImplemented("llGetStatus - STATUS_ROTATE_Y");
  1065. return 0;
  1066. case ScriptBaseClass.STATUS_ROTATE_Z:
  1067. NotImplemented("llGetStatus - STATUS_ROTATE_Z");
  1068. return 0;
  1069. case ScriptBaseClass.STATUS_SANDBOX:
  1070. NotImplemented("llGetStatus - STATUS_SANDBOX");
  1071. return 0;
  1072. }
  1073. return 0;
  1074. }
  1075. public void llSetScale(LSL_Vector scale)
  1076. {
  1077. m_host.AddScriptLPS(1);
  1078. SetScale(m_host, scale);
  1079. }
  1080. protected void SetScale(SceneObjectPart part, LSL_Vector scale)
  1081. {
  1082. // TODO: this needs to trigger a persistance save as well
  1083. if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
  1084. return;
  1085. if (scale.x < 0.01 || scale.y < 0.01 || scale.z < 0.01)
  1086. return;
  1087. if (part.ParentGroup.RootPart.PhysActor != null && part.ParentGroup.RootPart.PhysActor.IsPhysical)
  1088. {
  1089. if (scale.x > World.m_maxPhys)
  1090. scale.x = World.m_maxPhys;
  1091. if (scale.y > World.m_maxPhys)
  1092. scale.y = World.m_maxPhys;
  1093. if (scale.z > World.m_maxPhys)
  1094. scale.z = World.m_maxPhys;
  1095. }
  1096. if (scale.x > World.m_maxNonphys)
  1097. scale.x = World.m_maxNonphys;
  1098. if (scale.y > World.m_maxNonphys)
  1099. scale.y = World.m_maxNonphys;
  1100. if (scale.z > World.m_maxNonphys)
  1101. scale.z = World.m_maxNonphys;
  1102. Vector3 tmp = part.Scale;
  1103. tmp.X = (float)scale.x;
  1104. tmp.Y = (float)scale.y;
  1105. tmp.Z = (float)scale.z;
  1106. part.Scale = tmp;
  1107. part.SendFullUpdateToAllClients();
  1108. }
  1109. public LSL_Vector llGetScale()
  1110. {
  1111. m_host.AddScriptLPS(1);
  1112. return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z);
  1113. }
  1114. public void llSetClickAction(int action)
  1115. {
  1116. m_host.AddScriptLPS(1);
  1117. m_host.ClickAction = (byte)action;
  1118. if (m_host.ParentGroup != null) m_host.ParentGroup.HasGroupChanged = true;
  1119. m_host.ScheduleFullUpdate();
  1120. return;
  1121. }
  1122. public void llSetColor(LSL_Vector color, int face)
  1123. {
  1124. m_host.AddScriptLPS(1);
  1125. SetColor(m_host, color, face);
  1126. }
  1127. protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
  1128. {
  1129. Primitive.TextureEntry tex = part.Shape.Textures;
  1130. Color4 texcolor;
  1131. if (face >= 0 && face < GetNumberOfSides(part))
  1132. {
  1133. texcolor = tex.CreateFace((uint)face).RGBA;
  1134. texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
  1135. texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
  1136. texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
  1137. tex.FaceTextures[face].RGBA = texcolor;
  1138. part.UpdateTexture(tex);
  1139. return;
  1140. }
  1141. else if (face == ScriptBaseClass.ALL_SIDES)
  1142. {
  1143. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1144. {
  1145. if (tex.FaceTextures[i] != null)
  1146. {
  1147. texcolor = tex.FaceTextures[i].RGBA;
  1148. texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
  1149. texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
  1150. texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
  1151. tex.FaceTextures[i].RGBA = texcolor;
  1152. }
  1153. texcolor = tex.DefaultTexture.RGBA;
  1154. texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
  1155. texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
  1156. texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
  1157. tex.DefaultTexture.RGBA = texcolor;
  1158. }
  1159. part.UpdateTexture(tex);
  1160. return;
  1161. }
  1162. }
  1163. public void SetTexGen(SceneObjectPart part, int face,int style)
  1164. {
  1165. Primitive.TextureEntry tex = part.Shape.Textures;
  1166. MappingType textype;
  1167. textype = MappingType.Default;
  1168. if (style == (int)ScriptBaseClass.PRIM_TEXGEN_PLANAR)
  1169. textype = MappingType.Planar;
  1170. if (face >= 0 && face < GetNumberOfSides(part))
  1171. {
  1172. tex.CreateFace((uint) face);
  1173. tex.FaceTextures[face].TexMapType = textype;
  1174. part.UpdateTexture(tex);
  1175. return;
  1176. }
  1177. else if (face == ScriptBaseClass.ALL_SIDES)
  1178. {
  1179. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1180. {
  1181. if (tex.FaceTextures[i] != null)
  1182. {
  1183. tex.FaceTextures[i].TexMapType = textype;
  1184. }
  1185. tex.DefaultTexture.TexMapType = textype;
  1186. }
  1187. part.UpdateTexture(tex);
  1188. return;
  1189. }
  1190. }
  1191. public void SetGlow(SceneObjectPart part, int face, float glow)
  1192. {
  1193. Primitive.TextureEntry tex = part.Shape.Textures;
  1194. if (face >= 0 && face < GetNumberOfSides(part))
  1195. {
  1196. tex.CreateFace((uint) face);
  1197. tex.FaceTextures[face].Glow = glow;
  1198. part.UpdateTexture(tex);
  1199. return;
  1200. }
  1201. else if (face == ScriptBaseClass.ALL_SIDES)
  1202. {
  1203. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1204. {
  1205. if (tex.FaceTextures[i] != null)
  1206. {
  1207. tex.FaceTextures[i].Glow = glow;
  1208. }
  1209. tex.DefaultTexture.Glow = glow;
  1210. }
  1211. part.UpdateTexture(tex);
  1212. return;
  1213. }
  1214. }
  1215. public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
  1216. {
  1217. Shininess sval = new Shininess();
  1218. switch (shiny)
  1219. {
  1220. case 0:
  1221. sval = Shininess.None;
  1222. break;
  1223. case 1:
  1224. sval = Shininess.Low;
  1225. break;
  1226. case 2:
  1227. sval = Shininess.Medium;
  1228. break;
  1229. case 3:
  1230. sval = Shininess.High;
  1231. break;
  1232. default:
  1233. sval = Shininess.None;
  1234. break;
  1235. }
  1236. Primitive.TextureEntry tex = part.Shape.Textures;
  1237. if (face >= 0 && face < GetNumberOfSides(part))
  1238. {
  1239. tex.CreateFace((uint) face);
  1240. tex.FaceTextures[face].Shiny = sval;
  1241. tex.FaceTextures[face].Bump = bump;
  1242. part.UpdateTexture(tex);
  1243. return;
  1244. }
  1245. else if (face == ScriptBaseClass.ALL_SIDES)
  1246. {
  1247. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1248. {
  1249. if (tex.FaceTextures[i] != null)
  1250. {
  1251. tex.FaceTextures[i].Shiny = sval;
  1252. tex.FaceTextures[i].Bump = bump;;
  1253. }
  1254. tex.DefaultTexture.Shiny = sval;
  1255. tex.DefaultTexture.Bump = bump;
  1256. }
  1257. part.UpdateTexture(tex);
  1258. return;
  1259. }
  1260. }
  1261. public void SetFullBright(SceneObjectPart part, int face, bool bright)
  1262. {
  1263. Primitive.TextureEntry tex = part.Shape.Textures;
  1264. if (face >= 0 && face < GetNumberOfSides(part))
  1265. {
  1266. tex.CreateFace((uint) face);
  1267. tex.FaceTextures[face].Fullbright = bright;
  1268. part.UpdateTexture(tex);
  1269. return;
  1270. }
  1271. else if (face == ScriptBaseClass.ALL_SIDES)
  1272. {
  1273. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1274. {
  1275. if (tex.FaceTextures[i] != null)
  1276. {
  1277. tex.FaceTextures[i].Fullbright = bright;
  1278. }
  1279. }
  1280. tex.DefaultTexture.Fullbright = bright;
  1281. part.UpdateTexture(tex);
  1282. return;
  1283. }
  1284. }
  1285. public LSL_Float llGetAlpha(int face)
  1286. {
  1287. m_host.AddScriptLPS(1);
  1288. return GetAlpha(m_host, face);
  1289. }
  1290. protected LSL_Float GetAlpha(SceneObjectPart part, int face)
  1291. {
  1292. Primitive.TextureEntry tex = part.Shape.Textures;
  1293. if (face == ScriptBaseClass.ALL_SIDES)
  1294. {
  1295. int i;
  1296. double sum = 0.0;
  1297. for (i = 0 ; i < GetNumberOfSides(part) ; i++)
  1298. sum += (double)tex.GetFace((uint)i).RGBA.A;
  1299. return sum;
  1300. }
  1301. if (face >= 0 && face < GetNumberOfSides(part))
  1302. {
  1303. return (double)tex.GetFace((uint)face).RGBA.A;
  1304. }
  1305. return 0.0;
  1306. }
  1307. public void llSetAlpha(double alpha, int face)
  1308. {
  1309. m_host.AddScriptLPS(1);
  1310. SetAlpha(m_host, alpha, face);
  1311. }
  1312. public void llSetLinkAlpha(int linknumber, double alpha, int face)
  1313. {
  1314. m_host.AddScriptLPS(1);
  1315. List<SceneObjectPart> parts = GetLinkParts(linknumber);
  1316. foreach (SceneObjectPart part in parts)
  1317. SetAlpha(part, alpha, face);
  1318. }
  1319. protected void SetAlpha(SceneObjectPart part, double alpha, int face)
  1320. {
  1321. Primitive.TextureEntry tex = part.Shape.Textures;
  1322. Color4 texcolor;
  1323. if (face >= 0 && face < GetNumberOfSides(part))
  1324. {
  1325. texcolor = tex.CreateFace((uint)face).RGBA;
  1326. texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
  1327. tex.FaceTextures[face].RGBA = texcolor;
  1328. part.UpdateTexture(tex);
  1329. return;
  1330. }
  1331. else if (face == ScriptBaseClass.ALL_SIDES)
  1332. {
  1333. for (int i = 0; i < GetNumberOfSides(part); i++)
  1334. {
  1335. if (tex.FaceTextures[i] != null)
  1336. {
  1337. texcolor = tex.FaceTextures[i].RGBA;
  1338. texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
  1339. tex.FaceTextures[i].RGBA = texcolor;
  1340. }
  1341. }
  1342. texcolor = tex.DefaultTexture.RGBA;
  1343. texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
  1344. tex.DefaultTexture.RGBA = texcolor;
  1345. part.UpdateTexture(tex);
  1346. return;
  1347. }
  1348. }
  1349. /// <summary>
  1350. /// Set flexi parameters of a part.
  1351. ///
  1352. /// FIXME: Much of this code should probably be within the part itself.
  1353. /// </summary>
  1354. /// <param name="part"></param>
  1355. /// <param name="flexi"></param>
  1356. /// <param name="softness"></param>
  1357. /// <param name="gravity"></param>
  1358. /// <param name="friction"></param>
  1359. /// <param name="wind"></param>
  1360. /// <param name="tension"></param>
  1361. /// <param name="Force"></param>
  1362. protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
  1363. float wind, float tension, LSL_Vector Force)
  1364. {
  1365. if (part == null)
  1366. return;
  1367. if (flexi)
  1368. {
  1369. part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do
  1370. // work once the prim is already flexi
  1371. part.Shape.FlexiSoftness = softness;
  1372. part.Shape.FlexiGravity = gravity;
  1373. part.Shape.FlexiDrag = friction;
  1374. part.Shape.FlexiWind = wind;
  1375. part.Shape.FlexiTension = tension;
  1376. part.Shape.FlexiForceX = (float)Force.x;
  1377. part.Shape.FlexiForceY = (float)Force.y;
  1378. part.Shape.FlexiForceZ = (float)Force.z;
  1379. part.Shape.PathCurve = 0x80;
  1380. }
  1381. part.ParentGroup.HasGroupChanged = true;
  1382. part.ScheduleFullUpdate();
  1383. }
  1384. /// <summary>
  1385. /// Set a light point on a part
  1386. /// </summary>
  1387. /// FIXME: Much of this code should probably be in SceneObjectGroup
  1388. ///
  1389. /// <param name="part"></param>
  1390. /// <param name="light"></param>
  1391. /// <param name="color"></param>
  1392. /// <param name="intensity"></param>
  1393. /// <param name="radius"></param>
  1394. /// <param name="falloff"></param>
  1395. protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
  1396. {
  1397. if (part == null)
  1398. return;
  1399. if (light)
  1400. {
  1401. part.Shape.LightEntry = true;
  1402. part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f);
  1403. part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f);
  1404. part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f);
  1405. part.Shape.LightIntensity = intensity;
  1406. part.Shape.LightRadius = radius;
  1407. part.Shape.LightFalloff = falloff;
  1408. }
  1409. else
  1410. {
  1411. part.Shape.LightEntry = false;
  1412. }
  1413. part.ParentGroup.HasGroupChanged = true;
  1414. part.ScheduleFullUpdate();
  1415. }
  1416. public LSL_Vector llGetColor(int face)
  1417. {
  1418. m_host.AddScriptLPS(1);
  1419. return GetColor(m_host, face);
  1420. }
  1421. protected LSL_Vector GetColor(SceneObjectPart part, int face)
  1422. {
  1423. Primitive.TextureEntry tex = part.Shape.Textures;
  1424. Color4 texcolor;
  1425. LSL_Vector rgb = new LSL_Vector();
  1426. if (face == ScriptBaseClass.ALL_SIDES)
  1427. {
  1428. int i;
  1429. for (i = 0 ; i < GetNumberOfSides(part) ; i++)
  1430. {
  1431. texcolor = tex.GetFace((uint)i).RGBA;
  1432. rgb.x += texcolor.R;
  1433. rgb.y += texcolor.G;
  1434. rgb.z += texcolor.B;
  1435. }
  1436. rgb.x /= (float)GetNumberOfSides(part);
  1437. rgb.y /= (float)GetNumberOfSides(part);
  1438. rgb.z /= (float)GetNumberOfSides(part);
  1439. return rgb;
  1440. }
  1441. if (face >= 0 && face < GetNumberOfSides(part))
  1442. {
  1443. texcolor = tex.GetFace((uint)face).RGBA;
  1444. rgb.x = texcolor.R;
  1445. rgb.y = texcolor.G;
  1446. rgb.z = texcolor.B;
  1447. return rgb;
  1448. }
  1449. else
  1450. {
  1451. return new LSL_Vector();
  1452. }
  1453. }
  1454. public void llSetTexture(string texture, int face)
  1455. {
  1456. m_host.AddScriptLPS(1);
  1457. SetTexture(m_host, texture, face);
  1458. ScriptSleep(200);
  1459. }
  1460. public void llSetLinkTexture(int linknumber, string texture, int face)
  1461. {
  1462. m_host.AddScriptLPS(1);
  1463. List<SceneObjectPart> parts = GetLinkParts(linknumber);
  1464. foreach (SceneObjectPart part in parts)
  1465. SetTexture(part, texture, face);
  1466. ScriptSleep(200);
  1467. }
  1468. protected void SetTexture(SceneObjectPart part, string texture, int face)
  1469. {
  1470. UUID textureID=new UUID();
  1471. if (!UUID.TryParse(texture, out textureID))
  1472. {
  1473. textureID=InventoryKey(texture, (int)AssetType.Texture);
  1474. }
  1475. if (textureID == UUID.Zero)
  1476. return;
  1477. Primitive.TextureEntry tex = part.Shape.Textures;
  1478. if (face >= 0 && face < GetNumberOfSides(part))
  1479. {
  1480. Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
  1481. texface.TextureID = textureID;
  1482. tex.FaceTextures[face] = texface;
  1483. part.UpdateTexture(tex);
  1484. return;
  1485. }
  1486. else if (face == ScriptBaseClass.ALL_SIDES)
  1487. {
  1488. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1489. {
  1490. if (tex.FaceTextures[i] != null)
  1491. {
  1492. tex.FaceTextures[i].TextureID = textureID;
  1493. }
  1494. }
  1495. tex.DefaultTexture.TextureID = textureID;
  1496. part.UpdateTexture(tex);
  1497. return;
  1498. }
  1499. }
  1500. public void llScaleTexture(double u, double v, int face)
  1501. {
  1502. m_host.AddScriptLPS(1);
  1503. ScaleTexture(m_host, u, v, face);
  1504. ScriptSleep(200);
  1505. }
  1506. protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
  1507. {
  1508. Primitive.TextureEntry tex = part.Shape.Textures;
  1509. if (face >= 0 && face < GetNumberOfSides(part))
  1510. {
  1511. Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
  1512. texface.RepeatU = (float)u;
  1513. texface.RepeatV = (float)v;
  1514. tex.FaceTextures[face] = texface;
  1515. part.UpdateTexture(tex);
  1516. return;
  1517. }
  1518. if (face == ScriptBaseClass.ALL_SIDES)
  1519. {
  1520. for (int i = 0; i < GetNumberOfSides(part); i++)
  1521. {
  1522. if (tex.FaceTextures[i] != null)
  1523. {
  1524. tex.FaceTextures[i].RepeatU = (float)u;
  1525. tex.FaceTextures[i].RepeatV = (float)v;
  1526. }
  1527. }
  1528. tex.DefaultTexture.RepeatU = (float)u;
  1529. tex.DefaultTexture.RepeatV = (float)v;
  1530. part.UpdateTexture(tex);
  1531. return;
  1532. }
  1533. }
  1534. public void llOffsetTexture(double u, double v, int face)
  1535. {
  1536. m_host.AddScriptLPS(1);
  1537. OffsetTexture(m_host, u, v, face);
  1538. ScriptSleep(200);
  1539. }
  1540. protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
  1541. {
  1542. Primitive.TextureEntry tex = part.Shape.Textures;
  1543. if (face >= 0 && face < GetNumberOfSides(part))
  1544. {
  1545. Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
  1546. texface.OffsetU = (float)u;
  1547. texface.OffsetV = (float)v;
  1548. tex.FaceTextures[face] = texface;
  1549. part.UpdateTexture(tex);
  1550. return;
  1551. }
  1552. if (face == ScriptBaseClass.ALL_SIDES)
  1553. {
  1554. for (int i = 0; i < GetNumberOfSides(part); i++)
  1555. {
  1556. if (tex.FaceTextures[i] != null)
  1557. {
  1558. tex.FaceTextures[i].OffsetU = (float)u;
  1559. tex.FaceTextures[i].OffsetV = (float)v;
  1560. }
  1561. }
  1562. tex.DefaultTexture.OffsetU = (float)u;
  1563. tex.DefaultTexture.OffsetV = (float)v;
  1564. part.UpdateTexture(tex);
  1565. return;
  1566. }
  1567. }
  1568. public void llRotateTexture(double rotation, int face)
  1569. {
  1570. m_host.AddScriptLPS(1);
  1571. RotateTexture(m_host, rotation, face);
  1572. ScriptSleep(200);
  1573. }
  1574. protected void RotateTexture(SceneObjectPart part, double rotation, int face)
  1575. {
  1576. Primitive.TextureEntry tex = part.Shape.Textures;
  1577. if (face >= 0 && face < GetNumberOfSides(part))
  1578. {
  1579. Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
  1580. texface.Rotation = (float)rotation;
  1581. tex.FaceTextures[face] = texface;
  1582. part.UpdateTexture(tex);
  1583. return;
  1584. }
  1585. if (face == ScriptBaseClass.ALL_SIDES)
  1586. {
  1587. for (int i = 0; i < GetNumberOfSides(part); i++)
  1588. {
  1589. if (tex.FaceTextures[i] != null)
  1590. {
  1591. tex.FaceTextures[i].Rotation = (float)rotation;
  1592. }
  1593. }
  1594. tex.DefaultTexture.Rotation = (float)rotation;
  1595. part.UpdateTexture(tex);
  1596. return;
  1597. }
  1598. }
  1599. public LSL_String llGetTexture(int face)
  1600. {
  1601. m_host.AddScriptLPS(1);
  1602. return GetTexture(m_host, face);
  1603. }
  1604. protected LSL_String GetTexture(SceneObjectPart part, int face)
  1605. {
  1606. Primitive.TextureEntry tex = part.Shape.Textures;
  1607. if (face == ScriptBaseClass.ALL_SIDES)
  1608. {
  1609. face = 0;
  1610. }
  1611. if (face >= 0 && face < GetNumberOfSides(part))
  1612. {
  1613. Primitive.TextureEntryFace texface;
  1614. texface = tex.GetFace((uint)face);
  1615. return texface.TextureID.ToString();
  1616. }
  1617. else
  1618. {
  1619. return String.Empty;
  1620. }
  1621. }
  1622. public void llSetPos(LSL_Vector pos)
  1623. {
  1624. m_host.AddScriptLPS(1);
  1625. SetPos(m_host, pos);
  1626. ScriptSleep(200);
  1627. }
  1628. // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
  1629. // note linked setpos is capped "differently"
  1630. private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end)
  1631. {
  1632. if (llVecDist(start, end) > 10.0f * m_ScriptDistanceFactor)
  1633. return start + m_ScriptDistanceFactor * 10.0f * llVecNorm(end - start);
  1634. else
  1635. return end;
  1636. }
  1637. protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
  1638. {
  1639. // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
  1640. LSL_Vector currentPos = llGetLocalPos();
  1641. float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
  1642. bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
  1643. if (part.ParentGroup == null)
  1644. {
  1645. if ((targetPos.z < ground) && disable_underground_movement)
  1646. targetPos.z = ground;
  1647. LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos);
  1648. part.UpdateOffSet(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z));
  1649. }
  1650. else if (part.ParentGroup.RootPart == part)
  1651. {
  1652. if ((targetPos.z < ground) && disable_underground_movement)
  1653. targetPos.z = ground;
  1654. SceneObjectGroup parent = part.ParentGroup;
  1655. LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos);
  1656. parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z));
  1657. }
  1658. else
  1659. {
  1660. //it's late... i think this is right ?
  1661. if (llVecDist(new LSL_Vector(0,0,0), targetPos) <= 10.0f)
  1662. {
  1663. part.OffsetPosition = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z);
  1664. SceneObjectGroup parent = part.ParentGroup;
  1665. parent.HasGroupChanged = true;
  1666. parent.ScheduleGroupForTerseUpdate();
  1667. }
  1668. }
  1669. }
  1670. public LSL_Vector llGetPos()
  1671. {
  1672. m_host.AddScriptLPS(1);
  1673. Vector3 pos = m_host.GetWorldPosition();
  1674. return new LSL_Vector(pos.X, pos.Y, pos.Z);
  1675. }
  1676. public LSL_Vector llGetLocalPos()
  1677. {
  1678. m_host.AddScriptLPS(1);
  1679. if (m_host.ParentID != 0)
  1680. {
  1681. return new LSL_Vector(m_host.OffsetPosition.X,
  1682. m_host.OffsetPosition.Y,
  1683. m_host.OffsetPosition.Z);
  1684. }
  1685. else
  1686. {
  1687. return new LSL_Vector(m_host.AbsolutePosition.X,
  1688. m_host.AbsolutePosition.Y,
  1689. m_host.AbsolutePosition.Z);
  1690. }
  1691. }
  1692. public void llSetRot(LSL_Rotation rot)
  1693. {
  1694. m_host.AddScriptLPS(1);
  1695. // try to let this work as in SL...
  1696. if (m_host.ParentID == 0)
  1697. {
  1698. // special case: If we are root, rotate complete SOG to new rotation
  1699. SetRot(m_host, Rot2Quaternion(rot));
  1700. }
  1701. else
  1702. {
  1703. // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
  1704. SceneObjectGroup group = m_host.ParentGroup;
  1705. if (group != null) // a bit paranoid, maybe
  1706. {
  1707. SceneObjectPart rootPart = group.RootPart;
  1708. if (rootPart != null) // again, better safe than sorry
  1709. {
  1710. SetRot(m_host, rootPart.RotationOffset * Rot2Quaternion(rot));
  1711. }
  1712. }
  1713. }
  1714. ScriptSleep(200);
  1715. }
  1716. public void llSetLocalRot(LSL_Rotation rot)
  1717. {
  1718. m_host.AddScriptLPS(1);
  1719. SetRot(m_host, Rot2Quaternion(rot));
  1720. ScriptSleep(200);
  1721. }
  1722. protected void SetRot(SceneObjectPart part, Quaternion rot)
  1723. {
  1724. part.UpdateRotation(rot);
  1725. // Update rotation does not move the object in the physics scene if it's a linkset.
  1726. part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition;
  1727. }
  1728. /// <summary>
  1729. /// See http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
  1730. /// </summary>
  1731. public LSL_Rotation llGetRot()
  1732. {
  1733. // unlinked or root prim then use llRootRotation
  1734. // see llRootRotaion for references.
  1735. if (m_host.LinkNum == 0 || m_host.LinkNum == 1)
  1736. {
  1737. return llGetRootRotation();
  1738. }
  1739. m_host.AddScriptLPS(1);
  1740. Quaternion q = m_host.GetWorldRotation();
  1741. return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
  1742. }
  1743. private LSL_Rotation GetPartRot(SceneObjectPart part)
  1744. {
  1745. Quaternion q;
  1746. if (part.LinkNum == 0 || part.LinkNum == 1) // unlinked or root prim
  1747. {
  1748. if (part.ParentGroup.RootPart.AttachmentPoint != 0)
  1749. {
  1750. ScenePresence avatar = World.GetScenePresence(part.AttachedAvatar);
  1751. if (avatar != null)
  1752. {
  1753. if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
  1754. q = avatar.CameraRotation; // Mouselook
  1755. else
  1756. q = avatar.Rotation; // Currently infrequently updated so may be inaccurate
  1757. }
  1758. else
  1759. q = part.ParentGroup.GroupRotation; // Likely never get here but just in case
  1760. }
  1761. else
  1762. q = part.ParentGroup.GroupRotation; // just the group rotation
  1763. return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
  1764. }
  1765. q = part.GetWorldRotation();
  1766. return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
  1767. }
  1768. public LSL_Rotation llGetLocalRot()
  1769. {
  1770. m_host.AddScriptLPS(1);
  1771. return new LSL_Rotation(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W);
  1772. }
  1773. public void llSetForce(LSL_Vector force, int local)
  1774. {
  1775. m_host.AddScriptLPS(1);
  1776. if (m_host.ParentGroup != null)
  1777. {
  1778. if (!m_host.ParentGroup.IsDeleted)
  1779. {
  1780. if (local != 0)
  1781. force *= llGetRot();
  1782. m_host.ParentGroup.RootPart.SetForce(new PhysicsVector((float)force.x, (float)force.y, (float)force.z));
  1783. }
  1784. }
  1785. }
  1786. public LSL_Vector llGetForce()
  1787. {
  1788. LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0);
  1789. m_host.AddScriptLPS(1);
  1790. if (m_host.ParentGroup != null)
  1791. {
  1792. if (!m_host.ParentGroup.IsDeleted)
  1793. {
  1794. PhysicsVector tmpForce = m_host.ParentGroup.RootPart.GetForce();
  1795. force.x = tmpForce.X;
  1796. force.y = tmpForce.Y;
  1797. force.z = tmpForce.Z;
  1798. }
  1799. }
  1800. return force;
  1801. }
  1802. public LSL_Integer llTarget(LSL_Vector position, double range)
  1803. {
  1804. m_host.AddScriptLPS(1);
  1805. return m_host.registerTargetWaypoint(new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range);
  1806. }
  1807. public void llTargetRemove(int number)
  1808. {
  1809. m_host.AddScriptLPS(1);
  1810. m_host.unregisterTargetWaypoint(number);
  1811. }
  1812. public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
  1813. {
  1814. m_host.AddScriptLPS(1);
  1815. NotImplemented("llRotTarget");
  1816. return 0;
  1817. }
  1818. public void llRotTargetRemove(int number)
  1819. {
  1820. m_host.AddScriptLPS(1);
  1821. NotImplemented("llRotTargetRemove");
  1822. }
  1823. public void llMoveToTarget(LSL_Vector target, double tau)
  1824. {
  1825. m_host.AddScriptLPS(1);
  1826. m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau);
  1827. }
  1828. public void llStopMoveToTarget()
  1829. {
  1830. m_host.AddScriptLPS(1);
  1831. m_host.StopMoveToTarget();
  1832. }
  1833. public void llApplyImpulse(LSL_Vector force, int local)
  1834. {
  1835. m_host.AddScriptLPS(1);
  1836. //No energy force yet
  1837. Vector3 v = new Vector3((float)force.x, (float)force.y, (float)force.z);
  1838. if (v.Length() > 20000.0f)
  1839. {
  1840. v.Normalize();
  1841. v = v * 20000.0f;
  1842. }
  1843. m_host.ApplyImpulse(v, local != 0);
  1844. }
  1845. public void llApplyRotationalImpulse(LSL_Vector force, int local)
  1846. {
  1847. m_host.AddScriptLPS(1);
  1848. m_host.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
  1849. }
  1850. public void llSetTorque(LSL_Vector torque, int local)
  1851. {
  1852. m_host.AddScriptLPS(1);
  1853. m_host.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0);
  1854. }
  1855. public LSL_Vector llGetTorque()
  1856. {
  1857. m_host.AddScriptLPS(1);
  1858. Vector3 torque = m_host.GetTorque();
  1859. return new LSL_Vector(torque.X,torque.Y,torque.Z);
  1860. }
  1861. public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local)
  1862. {
  1863. m_host.AddScriptLPS(1);
  1864. llSetForce(force, local);
  1865. llSetTorque(torque, local);
  1866. }
  1867. public LSL_Vector llGetVel()
  1868. {
  1869. m_host.AddScriptLPS(1);
  1870. return new LSL_Vector(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z);
  1871. }
  1872. public LSL_Vector llGetAccel()
  1873. {
  1874. m_host.AddScriptLPS(1);
  1875. return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z);
  1876. }
  1877. public LSL_Vector llGetOmega()
  1878. {
  1879. m_host.AddScriptLPS(1);
  1880. return new LSL_Vector(m_host.RotationalVelocity.X, m_host.RotationalVelocity.Y, m_host.RotationalVelocity.Z);
  1881. }
  1882. public LSL_Float llGetTimeOfDay()
  1883. {
  1884. m_host.AddScriptLPS(1);
  1885. return (double)((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4));
  1886. }
  1887. public LSL_Float llGetWallclock()
  1888. {
  1889. m_host.AddScriptLPS(1);
  1890. return DateTime.Now.TimeOfDay.TotalSeconds;
  1891. }
  1892. public LSL_Float llGetTime()
  1893. {
  1894. m_host.AddScriptLPS(1);
  1895. TimeSpan ScriptTime = DateTime.Now - m_timer;
  1896. return (double)(ScriptTime.TotalMilliseconds / 1000);
  1897. }
  1898. public void llResetTime()
  1899. {
  1900. m_host.AddScriptLPS(1);
  1901. m_timer = DateTime.Now;
  1902. }
  1903. public LSL_Float llGetAndResetTime()
  1904. {
  1905. m_host.AddScriptLPS(1);
  1906. TimeSpan ScriptTime = DateTime.Now - m_timer;
  1907. m_timer = DateTime.Now;
  1908. return (double)(ScriptTime.TotalMilliseconds / 1000);
  1909. }
  1910. public void llSound(string sound, double volume, int queue, int loop)
  1911. {
  1912. m_host.AddScriptLPS(1);
  1913. // This function has been deprecated
  1914. // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound
  1915. Deprecated("llSound");
  1916. }
  1917. // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
  1918. // 20080530 Updated to remove code duplication
  1919. public void llPlaySound(string sound, double volume)
  1920. {
  1921. m_host.AddScriptLPS(1);
  1922. // send the sound, once, to all clients in range
  1923. m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0);
  1924. }
  1925. // Xantor 20080528 we should do this differently.
  1926. // 1) apply the sound to the object
  1927. // 2) schedule full update
  1928. // just sending the sound out once doesn't work so well when other avatars come in view later on
  1929. // or when the prim gets moved, changed, sat on, whatever
  1930. // see large number of mantises (mantes?)
  1931. // 20080530 Updated to remove code duplication
  1932. // 20080530 Stop sound if there is one, otherwise volume only changes don't work
  1933. public void llLoopSound(string sound, double volume)
  1934. {
  1935. m_host.AddScriptLPS(1);
  1936. if (m_host.Sound != UUID.Zero)
  1937. llStopSound();
  1938. m_host.Sound = KeyOrName(sound);
  1939. m_host.SoundGain = volume;
  1940. m_host.SoundFlags = 1; // looping
  1941. m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
  1942. m_host.ScheduleFullUpdate();
  1943. m_host.SendFullUpdateToAllClients();
  1944. }
  1945. public void llLoopSoundMaster(string sound, double volume)
  1946. {
  1947. m_host.AddScriptLPS(1);
  1948. NotImplemented("llLoopSoundMaster");
  1949. }
  1950. public void llLoopSoundSlave(string sound, double volume)
  1951. {
  1952. m_host.AddScriptLPS(1);
  1953. NotImplemented("llLoopSoundSlave");
  1954. }
  1955. public void llPlaySoundSlave(string sound, double volume)
  1956. {
  1957. m_host.AddScriptLPS(1);
  1958. NotImplemented("llPlaySoundSlave");
  1959. }
  1960. public void llTriggerSound(string sound, double volume)
  1961. {
  1962. m_host.AddScriptLPS(1);
  1963. // send the sound, once, to all clients in range
  1964. m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0);
  1965. }
  1966. // Xantor 20080528: Clear prim data of sound instead
  1967. public void llStopSound()
  1968. {
  1969. m_host.AddScriptLPS(1);
  1970. m_host.Sound = UUID.Zero;
  1971. m_host.SoundGain = 0;
  1972. m_host.SoundFlags = 0;
  1973. m_host.SoundRadius = 0;
  1974. m_host.ScheduleFullUpdate();
  1975. m_host.SendFullUpdateToAllClients();
  1976. // m_host.SendSound(UUID.Zero.ToString(), 1.0, false, 2);
  1977. }
  1978. public void llPreloadSound(string sound)
  1979. {
  1980. m_host.AddScriptLPS(1);
  1981. m_host.PreloadSound(sound);
  1982. ScriptSleep(1000);
  1983. }
  1984. /// <summary>
  1985. /// Return a portion of the designated string bounded by
  1986. /// inclusive indices (start and end). As usual, the negative
  1987. /// indices, and the tolerance for out-of-bound values, makes
  1988. /// this more complicated than it might otherwise seem.
  1989. /// </summary>
  1990. public LSL_String llGetSubString(string src, int start, int end)
  1991. {
  1992. m_host.AddScriptLPS(1);
  1993. // Normalize indices (if negative).
  1994. // After normlaization they may still be
  1995. // negative, but that is now relative to
  1996. // the start, rather than the end, of the
  1997. // sequence.
  1998. if (start < 0)
  1999. {
  2000. start = src.Length+start;
  2001. }
  2002. if (end < 0)
  2003. {
  2004. end = src.Length+end;
  2005. }
  2006. // Conventional substring
  2007. if (start <= end)
  2008. {
  2009. // Implies both bounds are out-of-range.
  2010. if (end < 0 || start >= src.Length)
  2011. {
  2012. return String.Empty;
  2013. }
  2014. // If end is positive, then it directly
  2015. // corresponds to the lengt of the substring
  2016. // needed (plus one of course). BUT, it
  2017. // must be within bounds.
  2018. if (end >= src.Length)
  2019. {
  2020. end = src.Length-1;
  2021. }
  2022. if (start < 0)
  2023. {
  2024. return src.Substring(0,end+1);
  2025. }
  2026. // Both indices are positive
  2027. return src.Substring(start, (end+1) - start);
  2028. }
  2029. // Inverted substring (end < start)
  2030. else
  2031. {
  2032. // Implies both indices are below the
  2033. // lower bound. In the inverted case, that
  2034. // means the entire string will be returned
  2035. // unchanged.
  2036. if (start < 0)
  2037. {
  2038. return src;
  2039. }
  2040. // If both indices are greater than the upper
  2041. // bound the result may seem initially counter
  2042. // intuitive.
  2043. if (end >= src.Length)
  2044. {
  2045. return src;
  2046. }
  2047. if (end < 0)
  2048. {
  2049. if (start < src.Length)
  2050. {
  2051. return src.Substring(start);
  2052. }
  2053. else
  2054. {
  2055. return String.Empty;
  2056. }
  2057. }
  2058. else
  2059. {
  2060. if (start < src.Length)
  2061. {
  2062. return src.Substring(0,end+1) + src.Substring(start);
  2063. }
  2064. else
  2065. {
  2066. return src.Substring(0,end+1);
  2067. }
  2068. }
  2069. }
  2070. }
  2071. /// <summary>
  2072. /// Delete substring removes the specified substring bounded
  2073. /// by the inclusive indices start and end. Indices may be
  2074. /// negative (indicating end-relative) and may be inverted,
  2075. /// i.e. end < start.
  2076. /// </summary>
  2077. public LSL_String llDeleteSubString(string src, int start, int end)
  2078. {
  2079. m_host.AddScriptLPS(1);
  2080. // Normalize indices (if negative).
  2081. // After normlaization they may still be
  2082. // negative, but that is now relative to
  2083. // the start, rather than the end, of the
  2084. // sequence.
  2085. if (start < 0)
  2086. {
  2087. start = src.Length+start;
  2088. }
  2089. if (end < 0)
  2090. {
  2091. end = src.Length+end;
  2092. }
  2093. // Conventionally delimited substring
  2094. if (start <= end)
  2095. {
  2096. // If both bounds are outside of the existing
  2097. // string, then return unchanges.
  2098. if (end < 0 || start >= src.Length)
  2099. {
  2100. return src;
  2101. }
  2102. // At least one bound is in-range, so we
  2103. // need to clip the out-of-bound argument.
  2104. if (start < 0)
  2105. {
  2106. start = 0;
  2107. }
  2108. if (end >= src.Length)
  2109. {
  2110. end = src.Length-1;
  2111. }
  2112. return src.Remove(start,end-start+1);
  2113. }
  2114. // Inverted substring
  2115. else
  2116. {
  2117. // In this case, out of bounds means that
  2118. // the existing string is part of the cut.
  2119. if (start < 0 || end >= src.Length)
  2120. {
  2121. return String.Empty;
  2122. }
  2123. if (end > 0)
  2124. {
  2125. if (start < src.Length)
  2126. {
  2127. return src.Remove(start).Remove(0,end+1);
  2128. }
  2129. else
  2130. {
  2131. return src.Remove(0,end+1);
  2132. }
  2133. }
  2134. else
  2135. {
  2136. if (start < src.Length)
  2137. {
  2138. return src.Remove(start);
  2139. }
  2140. else
  2141. {
  2142. return src;
  2143. }
  2144. }
  2145. }
  2146. }
  2147. /// <summary>
  2148. /// Insert string inserts the specified string identified by src
  2149. /// at the index indicated by index. Index may be negative, in
  2150. /// which case it is end-relative. The index may exceed either
  2151. /// string bound, with the result being a concatenation.
  2152. /// </summary>
  2153. public LSL_String llInsertString(string dest, int index, string src)
  2154. {
  2155. m_host.AddScriptLPS(1);
  2156. // Normalize indices (if negative).
  2157. // After normlaization they may still be
  2158. // negative, but that is now relative to
  2159. // the start, rather than the end, of the
  2160. // sequence.
  2161. if (index < 0)
  2162. {
  2163. index = dest.Length+index;
  2164. // Negative now means it is less than the lower
  2165. // bound of the string.
  2166. if (index < 0)
  2167. {
  2168. return src+dest;
  2169. }
  2170. }
  2171. if (index >= dest.Length)
  2172. {
  2173. return dest+src;
  2174. }
  2175. // The index is in bounds.
  2176. // In this case the index refers to the index that will
  2177. // be assigned to the first character of the inserted string.
  2178. // So unlike the other string operations, we do not add one
  2179. // to get the correct string length.
  2180. return dest.Substring(0,index)+src+dest.Substring(index);
  2181. }
  2182. public LSL_String llToUpper(string src)
  2183. {
  2184. m_host.AddScriptLPS(1);
  2185. return src.ToUpper();
  2186. }
  2187. public LSL_String llToLower(string src)
  2188. {
  2189. m_host.AddScriptLPS(1);
  2190. return src.ToLower();
  2191. }
  2192. public LSL_Integer llGiveMoney(string destination, int amount)
  2193. {
  2194. UUID invItemID=InventorySelf();
  2195. if (invItemID == UUID.Zero)
  2196. return 0;
  2197. m_host.AddScriptLPS(1);
  2198. TaskInventoryItem item = m_host.TaskInventory[invItemID];
  2199. lock (m_host.TaskInventory)
  2200. {
  2201. item = m_host.TaskInventory[invItemID];
  2202. }
  2203. if (item.PermsGranter == UUID.Zero)
  2204. return 0;
  2205. if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
  2206. {
  2207. LSLError("No permissions to give money");
  2208. return 0;
  2209. }
  2210. UUID toID = new UUID();
  2211. if (!UUID.TryParse(destination, out toID))
  2212. {
  2213. LSLError("Bad key in llGiveMoney");
  2214. return 0;
  2215. }
  2216. IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
  2217. if (money == null)
  2218. {
  2219. NotImplemented("llGiveMoney");
  2220. return 0;
  2221. }
  2222. bool result = money.ObjectGiveMoney(
  2223. m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
  2224. if (result)
  2225. return 1;
  2226. return 0;
  2227. }
  2228. public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
  2229. {
  2230. m_host.AddScriptLPS(1);
  2231. Deprecated("llMakeExplosion");
  2232. ScriptSleep(100);
  2233. }
  2234. public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset)
  2235. {
  2236. m_host.AddScriptLPS(1);
  2237. Deprecated("llMakeFountain");
  2238. ScriptSleep(100);
  2239. }
  2240. public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
  2241. {
  2242. m_host.AddScriptLPS(1);
  2243. Deprecated("llMakeSmoke");
  2244. ScriptSleep(100);
  2245. }
  2246. public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
  2247. {
  2248. m_host.AddScriptLPS(1);
  2249. Deprecated("llMakeFire");
  2250. ScriptSleep(100);
  2251. }
  2252. public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
  2253. {
  2254. m_host.AddScriptLPS(1);
  2255. if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
  2256. return;
  2257. float dist = (float)llVecDist(llGetPos(), pos);
  2258. if (dist > m_ScriptDistanceFactor * 10.0f)
  2259. return;
  2260. TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
  2261. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
  2262. {
  2263. if (inv.Value.Name == inventory)
  2264. {
  2265. // make sure we're an object.
  2266. if (inv.Value.InvType != (int)InventoryType.Object)
  2267. {
  2268. llSay(0, "Unable to create requested object. Object is missing from database.");
  2269. return;
  2270. }
  2271. Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
  2272. Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z);
  2273. // need the magnitude later
  2274. float velmag = (float)Util.GetMagnitude(llvel);
  2275. SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, Rot2Quaternion(rot), llvel, param);
  2276. // If either of these are null, then there was an unknown error.
  2277. if (new_group == null)
  2278. continue;
  2279. if (new_group.RootPart == null)
  2280. continue;
  2281. // objects rezzed with this method are die_at_edge by default.
  2282. new_group.RootPart.SetDieAtEdge(true);
  2283. m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
  2284. "object_rez", new Object[] {
  2285. new LSL_String(
  2286. new_group.RootPart.UUID.ToString()) },
  2287. new DetectParams[0]));
  2288. float groupmass = new_group.GetMass();
  2289. if (new_group.RootPart.PhysActor != null && new_group.RootPart.PhysActor.IsPhysical && llvel != Vector3.Zero)
  2290. {
  2291. //Recoil.
  2292. llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0);
  2293. }
  2294. // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
  2295. ScriptSleep((int)((groupmass * velmag) / 10));
  2296. ScriptSleep(100);
  2297. return;
  2298. }
  2299. }
  2300. llSay(0, "Could not find object " + inventory);
  2301. }
  2302. public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
  2303. {
  2304. llRezAtRoot(inventory, pos, vel, rot, param);
  2305. }
  2306. public void llLookAt(LSL_Vector target, double strength, double damping)
  2307. {
  2308. // partial implementation, rotates objects correctly but does not apply strength or damping attributes
  2309. m_host.AddScriptLPS(1);
  2310. // Determine where we are looking from
  2311. LSL_Vector from = llGetPos();
  2312. // Work out the normalised vector from the source to the target
  2313. LSL_Vector delta = llVecNorm(target - from);
  2314. LSL_Vector angle = new LSL_Vector(0,0,0);
  2315. // Calculate the yaw
  2316. // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system
  2317. angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO;
  2318. // Calculate pitch
  2319. angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z)));
  2320. // we need to convert from a vector describing
  2321. // the angles of rotation in radians into rotation value
  2322. LSL_Types.Quaternion rot = llEuler2Rot(angle);
  2323. // Orient the object to the angle calculated
  2324. llSetRot(rot);
  2325. }
  2326. public void llStopLookAt()
  2327. {
  2328. m_host.AddScriptLPS(1);
  2329. NotImplemented("llStopLookAt");
  2330. }
  2331. public void llSetTimerEvent(double sec)
  2332. {
  2333. if (sec != 0.0 && sec < m_MinTimerInterval)
  2334. sec = m_MinTimerInterval;
  2335. m_host.AddScriptLPS(1);
  2336. // Setting timer repeat
  2337. AsyncCommands.TimerPlugin.SetTimerEvent(m_localID, m_itemID, sec);
  2338. }
  2339. public virtual void llSleep(double sec)
  2340. {
  2341. m_host.AddScriptLPS(1);
  2342. Thread.Sleep((int)(sec * 1000));
  2343. }
  2344. public LSL_Float llGetMass()
  2345. {
  2346. m_host.AddScriptLPS(1);
  2347. return m_host.GetMass();
  2348. }
  2349. public void llCollisionFilter(string name, string id, int accept)
  2350. {
  2351. m_host.AddScriptLPS(1);
  2352. NotImplemented("llCollisionFilter");
  2353. }
  2354. public void llTakeControls(int controls, int accept, int pass_on)
  2355. {
  2356. TaskInventoryItem item;
  2357. lock (m_host.TaskInventory)
  2358. {
  2359. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  2360. return;
  2361. else
  2362. item = m_host.TaskInventory[InventorySelf()];
  2363. }
  2364. if (item.PermsGranter != UUID.Zero)
  2365. {
  2366. ScenePresence presence = World.GetScenePresence(item.PermsGranter);
  2367. if (presence != null)
  2368. {
  2369. if ((item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
  2370. {
  2371. presence.RegisterControlEventsToScript(controls, accept, pass_on, m_localID, m_itemID);
  2372. }
  2373. }
  2374. }
  2375. m_host.AddScriptLPS(1);
  2376. }
  2377. public void llReleaseControls()
  2378. {
  2379. TaskInventoryItem item;
  2380. lock (m_host.TaskInventory)
  2381. {
  2382. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  2383. return;
  2384. else
  2385. item = m_host.TaskInventory[InventorySelf()];
  2386. }
  2387. m_host.AddScriptLPS(1);
  2388. if (item.PermsGranter != UUID.Zero)
  2389. {
  2390. ScenePresence presence = World.GetScenePresence(item.PermsGranter);
  2391. if (presence != null)
  2392. {
  2393. if ((item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
  2394. {
  2395. // Unregister controls from Presence
  2396. presence.UnRegisterControlEventsToScript(m_localID, m_itemID);
  2397. // Remove Take Control permission.
  2398. item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
  2399. }
  2400. }
  2401. }
  2402. }
  2403. public void llReleaseURL(string url)
  2404. {
  2405. m_host.AddScriptLPS(1);
  2406. if (m_UrlModule != null)
  2407. m_UrlModule.ReleaseURL(url);
  2408. }
  2409. public void llAttachToAvatar(int attachment)
  2410. {
  2411. m_host.AddScriptLPS(1);
  2412. if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
  2413. return;
  2414. TaskInventoryItem item;
  2415. lock (m_host.TaskInventory)
  2416. {
  2417. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  2418. return;
  2419. else
  2420. item = m_host.TaskInventory[InventorySelf()];
  2421. }
  2422. if (item.PermsGranter != m_host.OwnerID)
  2423. return;
  2424. if ((item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
  2425. {
  2426. SceneObjectGroup grp = m_host.ParentGroup;
  2427. ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  2428. m_ScriptEngine.World.AttachObject(presence.ControllingClient,
  2429. grp.LocalId, (uint)attachment, Quaternion.Identity,
  2430. Vector3.Zero, false);
  2431. }
  2432. }
  2433. public void llDetachFromAvatar()
  2434. {
  2435. m_host.AddScriptLPS(1);
  2436. if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
  2437. return;
  2438. TaskInventoryItem item;
  2439. lock (m_host.TaskInventory)
  2440. {
  2441. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  2442. return;
  2443. else
  2444. item = m_host.TaskInventory[InventorySelf()];
  2445. }
  2446. if (item.PermsGranter != m_host.OwnerID)
  2447. return;
  2448. if ((item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
  2449. {
  2450. SceneObjectGroup grp = m_host.ParentGroup;
  2451. UUID itemID = grp.GetFromItemID();
  2452. ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  2453. m_ScriptEngine.World.DetachSingleAttachmentToInv(itemID,
  2454. presence.ControllingClient);
  2455. }
  2456. }
  2457. public void llTakeCamera(string avatar)
  2458. {
  2459. m_host.AddScriptLPS(1);
  2460. Deprecated("llTakeCamera");
  2461. }
  2462. public void llReleaseCamera(string avatar)
  2463. {
  2464. m_host.AddScriptLPS(1);
  2465. Deprecated("llReleaseCamera");
  2466. }
  2467. public LSL_String llGetOwner()
  2468. {
  2469. m_host.AddScriptLPS(1);
  2470. return m_host.OwnerID.ToString();
  2471. }
  2472. public void llInstantMessage(string user, string message)
  2473. {
  2474. m_host.AddScriptLPS(1);
  2475. // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
  2476. // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
  2477. // but I don't think we have a list of scenes available from here.
  2478. // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
  2479. // user is a UUID
  2480. // TODO: figure out values for client, fromSession, and imSessionID
  2481. // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
  2482. UUID friendTransactionID = UUID.Random();
  2483. //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
  2484. GridInstantMessage msg = new GridInstantMessage();
  2485. msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
  2486. msg.toAgentID = new Guid(user); // toAgentID.Guid;
  2487. msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
  2488. // m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
  2489. // m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
  2490. msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp;
  2491. //if (client != null)
  2492. //{
  2493. msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
  2494. //}
  2495. //else
  2496. //{
  2497. // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it
  2498. //}
  2499. // Cap the message length at 1024.
  2500. if (message != null && message.Length > 1024)
  2501. msg.message = message.Substring(0, 1024);
  2502. else
  2503. msg.message = message;
  2504. msg.dialog = (byte)19; // messgage from script ??? // dialog;
  2505. msg.fromGroup = false;// fromGroup;
  2506. msg.offline = (byte)0; //offline;
  2507. msg.ParentEstateID = 0; //ParentEstateID;
  2508. msg.Position = Vector3.Zero;// new Vector3(m_host.AbsolutePosition);
  2509. msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
  2510. msg.binaryBucket = new byte[0];// binaryBucket;
  2511. if (m_TransferModule != null)
  2512. {
  2513. m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
  2514. }
  2515. ScriptSleep(2000);
  2516. }
  2517. public void llEmail(string address, string subject, string message)
  2518. {
  2519. m_host.AddScriptLPS(1);
  2520. IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
  2521. if (emailModule == null)
  2522. {
  2523. ShoutError("llEmail: email module not configured");
  2524. return;
  2525. }
  2526. emailModule.SendEmail(m_host.UUID, address, subject, message);
  2527. ScriptSleep(20000);
  2528. }
  2529. public void llGetNextEmail(string address, string subject)
  2530. {
  2531. m_host.AddScriptLPS(1);
  2532. IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
  2533. if (emailModule == null)
  2534. {
  2535. ShoutError("llGetNextEmail: email module not configured");
  2536. return;
  2537. }
  2538. Email email;
  2539. email = emailModule.GetNextEmail(m_host.UUID, address, subject);
  2540. if (email == null)
  2541. return;
  2542. m_ScriptEngine.PostObjectEvent(m_host.LocalId,
  2543. new EventParams("email",
  2544. new Object[] {
  2545. new LSL_String(email.time),
  2546. new LSL_String(email.sender),
  2547. new LSL_String(email.subject),
  2548. new LSL_String(email.message),
  2549. new LSL_Integer(email.numLeft)},
  2550. new DetectParams[0]));
  2551. }
  2552. public LSL_String llGetKey()
  2553. {
  2554. m_host.AddScriptLPS(1);
  2555. return m_host.UUID.ToString();
  2556. }
  2557. public void llSetBuoyancy(double buoyancy)
  2558. {
  2559. m_host.AddScriptLPS(1);
  2560. if (m_host.ParentGroup != null)
  2561. {
  2562. if (!m_host.ParentGroup.IsDeleted)
  2563. {
  2564. m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy);
  2565. }
  2566. }
  2567. }
  2568. /// <summary>
  2569. /// Attempt to clamp the object on the Z axis at the given height over tau seconds.
  2570. /// </summary>
  2571. /// <param name="height">Height to hover. Height of zero disables hover.</param>
  2572. /// <param name="water">False if height is calculated just from ground, otherwise uses ground or water depending on whichever is higher</param>
  2573. /// <param name="tau">Number of seconds over which to reach target</param>
  2574. public void llSetHoverHeight(double height, int water, double tau)
  2575. {
  2576. m_host.AddScriptLPS(1);
  2577. if (m_host.PhysActor != null)
  2578. {
  2579. PIDHoverType hoverType = PIDHoverType.Ground;
  2580. if (water != 0)
  2581. {
  2582. hoverType = PIDHoverType.GroundAndWater;
  2583. }
  2584. m_host.SetHoverHeight((float)height, hoverType, (float)tau);
  2585. }
  2586. }
  2587. public void llStopHover()
  2588. {
  2589. m_host.AddScriptLPS(1);
  2590. if (m_host.PhysActor != null)
  2591. {
  2592. m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
  2593. }
  2594. }
  2595. public void llMinEventDelay(double delay)
  2596. {
  2597. m_host.AddScriptLPS(1);
  2598. try
  2599. {
  2600. m_ScriptEngine.SetMinEventDelay(m_itemID, delay);
  2601. }
  2602. catch (NotImplementedException)
  2603. {
  2604. // Currently not implemented in DotNetEngine only XEngine
  2605. NotImplemented("llMinEventDelay in DotNetEngine");
  2606. }
  2607. }
  2608. /// <summary>
  2609. /// llSoundPreload is deprecated. In SL this appears to do absolutely nothing
  2610. /// and is documented to have no delay.
  2611. /// </summary>
  2612. public void llSoundPreload(string sound)
  2613. {
  2614. m_host.AddScriptLPS(1);
  2615. }
  2616. public void llRotLookAt(LSL_Rotation target, double strength, double damping)
  2617. {
  2618. m_host.AddScriptLPS(1);
  2619. NotImplemented("llRotLookAt");
  2620. }
  2621. public LSL_Integer llStringLength(string str)
  2622. {
  2623. m_host.AddScriptLPS(1);
  2624. if (str.Length > 0)
  2625. {
  2626. return str.Length;
  2627. }
  2628. else
  2629. {
  2630. return 0;
  2631. }
  2632. }
  2633. public void llStartAnimation(string anim)
  2634. {
  2635. m_host.AddScriptLPS(1);
  2636. UUID invItemID = InventorySelf();
  2637. if (invItemID == UUID.Zero)
  2638. return;
  2639. TaskInventoryItem item;
  2640. lock (m_host.TaskInventory)
  2641. {
  2642. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  2643. return;
  2644. else
  2645. item = m_host.TaskInventory[InventorySelf()];
  2646. }
  2647. if (item.PermsGranter == UUID.Zero)
  2648. return;
  2649. if ((item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
  2650. {
  2651. ScenePresence presence = World.GetScenePresence(item.PermsGranter);
  2652. if (presence != null)
  2653. {
  2654. // Do NOT try to parse UUID, animations cannot be triggered by ID
  2655. UUID animID=InventoryKey(anim, (int)AssetType.Animation);
  2656. if (animID == UUID.Zero)
  2657. presence.AddAnimation(anim, m_host.UUID);
  2658. else
  2659. presence.AddAnimation(animID, m_host.UUID);
  2660. }
  2661. }
  2662. }
  2663. public void llStopAnimation(string anim)
  2664. {
  2665. m_host.AddScriptLPS(1);
  2666. UUID invItemID=InventorySelf();
  2667. if (invItemID == UUID.Zero)
  2668. return;
  2669. TaskInventoryItem item;
  2670. lock (m_host.TaskInventory)
  2671. {
  2672. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  2673. return;
  2674. else
  2675. item = m_host.TaskInventory[InventorySelf()];
  2676. }
  2677. if (item.PermsGranter == UUID.Zero)
  2678. return;
  2679. if ((item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
  2680. {
  2681. UUID animID = new UUID();
  2682. if (!UUID.TryParse(anim, out animID))
  2683. {
  2684. animID=InventoryKey(anim);
  2685. }
  2686. ScenePresence presence = World.GetScenePresence(item.PermsGranter);
  2687. if (presence != null)
  2688. {
  2689. if (animID == UUID.Zero)
  2690. presence.RemoveAnimation(anim);
  2691. else
  2692. presence.RemoveAnimation(animID);
  2693. }
  2694. }
  2695. }
  2696. public void llPointAt(LSL_Vector pos)
  2697. {
  2698. m_host.AddScriptLPS(1);
  2699. NotImplemented("llPointAt");
  2700. }
  2701. public void llStopPointAt()
  2702. {
  2703. m_host.AddScriptLPS(1);
  2704. NotImplemented("llStopPointAt");
  2705. }
  2706. public void llTargetOmega(LSL_Vector axis, double spinrate, double gain)
  2707. {
  2708. m_host.AddScriptLPS(1);
  2709. m_host.RotationalVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
  2710. m_host.AngularVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
  2711. m_host.ScheduleTerseUpdate();
  2712. m_host.SendTerseUpdateToAllClients();
  2713. m_host.ParentGroup.HasGroupChanged = true;
  2714. }
  2715. public LSL_Integer llGetStartParameter()
  2716. {
  2717. m_host.AddScriptLPS(1);
  2718. return m_ScriptEngine.GetStartParameter(m_itemID);
  2719. }
  2720. public void llGodLikeRezObject(string inventory, LSL_Vector pos)
  2721. {
  2722. m_host.AddScriptLPS(1);
  2723. NotImplemented("llGodLikeRezObject");
  2724. }
  2725. public void llRequestPermissions(string agent, int perm)
  2726. {
  2727. UUID agentID = new UUID();
  2728. if (!UUID.TryParse(agent, out agentID))
  2729. return;
  2730. UUID invItemID = InventorySelf();
  2731. if (invItemID == UUID.Zero)
  2732. return; // Not in a prim? How??
  2733. TaskInventoryItem item;
  2734. lock (m_host.TaskInventory)
  2735. {
  2736. item = m_host.TaskInventory[invItemID];
  2737. }
  2738. if (agentID == UUID.Zero || perm == 0) // Releasing permissions
  2739. {
  2740. llReleaseControls();
  2741. item.PermsGranter = UUID.Zero;
  2742. item.PermsMask = 0;
  2743. m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
  2744. "run_time_permissions", new Object[] {
  2745. new LSL_Integer(0) },
  2746. new DetectParams[0]));
  2747. return;
  2748. }
  2749. if (item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
  2750. llReleaseControls();
  2751. m_host.AddScriptLPS(1);
  2752. if (m_host.ParentGroup.IsAttachment && (UUID)agent == m_host.ParentGroup.RootPart.AttachedAvatar)
  2753. {
  2754. // When attached, certain permissions are implicit if requested from owner
  2755. int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
  2756. ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
  2757. ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
  2758. ScriptBaseClass.PERMISSION_ATTACH;
  2759. if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
  2760. {
  2761. lock (m_host.TaskInventory)
  2762. {
  2763. m_host.TaskInventory[invItemID].PermsGranter = agentID;
  2764. m_host.TaskInventory[invItemID].PermsMask = perm;
  2765. }
  2766. m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
  2767. "run_time_permissions", new Object[] {
  2768. new LSL_Integer(perm) },
  2769. new DetectParams[0]));
  2770. return;
  2771. }
  2772. }
  2773. else if (m_host.SitTargetAvatar == agentID) // Sitting avatar
  2774. {
  2775. // When agent is sitting, certain permissions are implicit if requested from sitting agent
  2776. int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
  2777. ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
  2778. ScriptBaseClass.PERMISSION_TRACK_CAMERA |
  2779. ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
  2780. if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
  2781. {
  2782. lock (m_host.TaskInventory)
  2783. {
  2784. m_host.TaskInventory[invItemID].PermsGranter = agentID;
  2785. m_host.TaskInventory[invItemID].PermsMask = perm;
  2786. }
  2787. m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
  2788. "run_time_permissions", new Object[] {
  2789. new LSL_Integer(perm) },
  2790. new DetectParams[0]));
  2791. return;
  2792. }
  2793. }
  2794. ScenePresence presence = World.GetScenePresence(agentID);
  2795. if (presence != null)
  2796. {
  2797. string ownerName = resolveName(m_host.ParentGroup.RootPart.OwnerID);
  2798. if (ownerName == String.Empty)
  2799. ownerName = "(hippos)";
  2800. if (!m_waitingForScriptAnswer)
  2801. {
  2802. lock (m_host.TaskInventory)
  2803. {
  2804. m_host.TaskInventory[invItemID].PermsGranter = agentID;
  2805. m_host.TaskInventory[invItemID].PermsMask = 0;
  2806. }
  2807. presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
  2808. m_waitingForScriptAnswer=true;
  2809. }
  2810. presence.ControllingClient.SendScriptQuestion(
  2811. m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, invItemID, perm);
  2812. return;
  2813. }
  2814. // Requested agent is not in range, refuse perms
  2815. m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
  2816. "run_time_permissions", new Object[] {
  2817. new LSL_Integer(0) },
  2818. new DetectParams[0]));
  2819. }
  2820. void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer)
  2821. {
  2822. if (taskID != m_host.UUID)
  2823. return;
  2824. UUID invItemID = InventorySelf();
  2825. if (invItemID == UUID.Zero)
  2826. return;
  2827. client.OnScriptAnswer-=handleScriptAnswer;
  2828. m_waitingForScriptAnswer=false;
  2829. if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
  2830. llReleaseControls();
  2831. lock (m_host.TaskInventory)
  2832. {
  2833. m_host.TaskInventory[invItemID].PermsMask = answer;
  2834. }
  2835. m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
  2836. "run_time_permissions", new Object[] {
  2837. new LSL_Integer(answer) },
  2838. new DetectParams[0]));
  2839. }
  2840. public LSL_String llGetPermissionsKey()
  2841. {
  2842. m_host.AddScriptLPS(1);
  2843. lock (m_host.TaskInventory)
  2844. {
  2845. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  2846. {
  2847. if (item.Type == 10 && item.ItemID == m_itemID)
  2848. {
  2849. return item.PermsGranter.ToString();
  2850. }
  2851. }
  2852. }
  2853. return UUID.Zero.ToString();
  2854. }
  2855. public LSL_Integer llGetPermissions()
  2856. {
  2857. m_host.AddScriptLPS(1);
  2858. lock (m_host.TaskInventory)
  2859. {
  2860. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  2861. {
  2862. if (item.Type == 10 && item.ItemID == m_itemID)
  2863. {
  2864. int perms = item.PermsMask;
  2865. if (m_automaticLinkPermission)
  2866. perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
  2867. return perms;
  2868. }
  2869. }
  2870. }
  2871. return 0;
  2872. }
  2873. public LSL_Integer llGetLinkNumber()
  2874. {
  2875. m_host.AddScriptLPS(1);
  2876. if (m_host.ParentGroup.Children.Count > 1)
  2877. {
  2878. return m_host.LinkNum;
  2879. }
  2880. else
  2881. {
  2882. return 0;
  2883. }
  2884. }
  2885. public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
  2886. {
  2887. List<SceneObjectPart> parts = GetLinkParts(linknumber);
  2888. foreach (SceneObjectPart part in parts)
  2889. SetColor(part, color, face);
  2890. }
  2891. public void llCreateLink(string target, int parent)
  2892. {
  2893. m_host.AddScriptLPS(1);
  2894. UUID invItemID = InventorySelf();
  2895. TaskInventoryItem item;
  2896. lock (m_host.TaskInventory)
  2897. {
  2898. item = m_host.TaskInventory[invItemID];
  2899. }
  2900. if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
  2901. && !m_automaticLinkPermission)
  2902. {
  2903. ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
  2904. return;
  2905. }
  2906. IClientAPI client = null;
  2907. ScenePresence sp = World.GetScenePresence(item.PermsGranter);
  2908. if (sp != null)
  2909. client = sp.ControllingClient;
  2910. SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)target);
  2911. if (targetPart.ParentGroup.RootPart.AttachmentPoint != 0)
  2912. return; // Fail silently if attached
  2913. SceneObjectGroup parentPrim = null, childPrim = null;
  2914. if (targetPart != null)
  2915. {
  2916. if (parent != 0) {
  2917. parentPrim = m_host.ParentGroup;
  2918. childPrim = targetPart.ParentGroup;
  2919. }
  2920. else
  2921. {
  2922. parentPrim = targetPart.ParentGroup;
  2923. childPrim = m_host.ParentGroup;
  2924. }
  2925. // byte uf = childPrim.RootPart.UpdateFlag;
  2926. childPrim.RootPart.UpdateFlag = 0;
  2927. parentPrim.LinkToGroup(childPrim);
  2928. // if (uf != (Byte)0)
  2929. // parent.RootPart.UpdateFlag = uf;
  2930. }
  2931. parentPrim.TriggerScriptChangedEvent(Changed.LINK);
  2932. parentPrim.RootPart.AddFlag(PrimFlags.CreateSelected);
  2933. parentPrim.HasGroupChanged = true;
  2934. parentPrim.ScheduleGroupForFullUpdate();
  2935. if (client != null)
  2936. parentPrim.GetProperties(client);
  2937. ScriptSleep(1000);
  2938. }
  2939. public void llBreakLink(int linknum)
  2940. {
  2941. m_host.AddScriptLPS(1);
  2942. UUID invItemID = InventorySelf();
  2943. lock (m_host.TaskInventory)
  2944. {
  2945. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
  2946. && !m_automaticLinkPermission)
  2947. {
  2948. ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
  2949. return;
  2950. }
  2951. }
  2952. if (linknum < ScriptBaseClass.LINK_THIS)
  2953. return;
  2954. SceneObjectGroup parentPrim = m_host.ParentGroup;
  2955. if (parentPrim.RootPart.AttachmentPoint != 0)
  2956. return; // Fail silently if attached
  2957. SceneObjectPart childPrim = null;
  2958. switch (linknum)
  2959. {
  2960. case ScriptBaseClass.LINK_ROOT:
  2961. break;
  2962. case ScriptBaseClass.LINK_SET:
  2963. case ScriptBaseClass.LINK_ALL_OTHERS:
  2964. case ScriptBaseClass.LINK_ALL_CHILDREN:
  2965. case ScriptBaseClass.LINK_THIS:
  2966. foreach (SceneObjectPart part in parentPrim.Children.Values)
  2967. {
  2968. if (part.UUID != m_host.UUID)
  2969. {
  2970. childPrim = part;
  2971. break;
  2972. }
  2973. }
  2974. break;
  2975. default:
  2976. childPrim = parentPrim.GetLinkNumPart(linknum);
  2977. if (childPrim.UUID == m_host.UUID)
  2978. childPrim = null;
  2979. break;
  2980. }
  2981. if (linknum == ScriptBaseClass.LINK_ROOT)
  2982. {
  2983. // Restructuring Multiple Prims.
  2984. List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
  2985. parts.Remove(parentPrim.RootPart);
  2986. foreach (SceneObjectPart part in parts)
  2987. {
  2988. parentPrim.DelinkFromGroup(part.LocalId, true);
  2989. }
  2990. parentPrim.TriggerScriptChangedEvent(Changed.LINK);
  2991. if (parts.Count > 0)
  2992. {
  2993. SceneObjectPart newRoot = parts[0];
  2994. parts.Remove(newRoot);
  2995. foreach (SceneObjectPart part in parts)
  2996. {
  2997. part.UpdateFlag = 0;
  2998. newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
  2999. }
  3000. }
  3001. }
  3002. else
  3003. {
  3004. if (childPrim == null)
  3005. return;
  3006. parentPrim.DelinkFromGroup(childPrim.LocalId, true);
  3007. parentPrim.TriggerScriptChangedEvent(Changed.LINK);
  3008. }
  3009. }
  3010. public void llBreakAllLinks()
  3011. {
  3012. m_host.AddScriptLPS(1);
  3013. SceneObjectGroup parentPrim = m_host.ParentGroup;
  3014. if (parentPrim.RootPart.AttachmentPoint != 0)
  3015. return; // Fail silently if attached
  3016. List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
  3017. parts.Remove(parentPrim.RootPart);
  3018. foreach (SceneObjectPart part in parts)
  3019. {
  3020. parentPrim.DelinkFromGroup(part.LocalId, true);
  3021. parentPrim.TriggerScriptChangedEvent(Changed.LINK);
  3022. }
  3023. }
  3024. public LSL_String llGetLinkKey(int linknum)
  3025. {
  3026. m_host.AddScriptLPS(1);
  3027. SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
  3028. if (part != null)
  3029. {
  3030. return part.UUID.ToString();
  3031. }
  3032. else
  3033. {
  3034. return UUID.Zero.ToString();
  3035. }
  3036. }
  3037. /// <summary>
  3038. /// The rules governing the returned name are not simple. The only
  3039. /// time a blank name is returned is if the target prim has a blank
  3040. /// name. If no prim with the given link number can be found then
  3041. /// usually NULL_KEY is returned but there are exceptions.
  3042. ///
  3043. /// In a single unlinked prim, A call with 0 returns the name, all
  3044. /// other values for link number return NULL_KEY
  3045. ///
  3046. /// In link sets it is more complicated.
  3047. ///
  3048. /// If the script is in the root prim:-
  3049. /// A zero link number returns NULL_KEY.
  3050. /// Positive link numbers return the name of the prim, or NULL_KEY
  3051. /// if a prim does not exist at that position.
  3052. /// Negative link numbers return the name of the first child prim.
  3053. ///
  3054. /// If the script is in a child prim:-
  3055. /// Link numbers 0 or 1 return the name of the root prim.
  3056. /// Positive link numbers return the name of the prim or NULL_KEY
  3057. /// if a prim does not exist at that position.
  3058. /// Negative numbers return the name of the root prim.
  3059. ///
  3060. /// References
  3061. /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetLinkName
  3062. /// Mentions NULL_KEY being returned
  3063. /// http://wiki.secondlife.com/wiki/LlGetLinkName
  3064. /// Mentions using the LINK_* constants, some of which are negative
  3065. /// </summary>
  3066. public LSL_String llGetLinkName(int linknum)
  3067. {
  3068. m_host.AddScriptLPS(1);
  3069. // simplest case, this prims link number
  3070. if (m_host.LinkNum == linknum)
  3071. return m_host.Name;
  3072. // Single prim
  3073. if (m_host.LinkNum == 0)
  3074. {
  3075. if (linknum == 0)
  3076. return m_host.Name;
  3077. else
  3078. return UUID.Zero.ToString();
  3079. }
  3080. // Link set
  3081. SceneObjectPart part = null;
  3082. if (m_host.LinkNum == 1) // this is the Root prim
  3083. {
  3084. if (linknum < 0)
  3085. part = m_host.ParentGroup.GetLinkNumPart(2);
  3086. else
  3087. part = m_host.ParentGroup.GetLinkNumPart(linknum);
  3088. }
  3089. else // this is a child prim
  3090. {
  3091. if (linknum < 2)
  3092. part = m_host.ParentGroup.GetLinkNumPart(1);
  3093. else
  3094. part = m_host.ParentGroup.GetLinkNumPart(linknum);
  3095. }
  3096. if (part != null)
  3097. return part.Name;
  3098. else
  3099. return UUID.Zero.ToString();
  3100. }
  3101. public LSL_Integer llGetInventoryNumber(int type)
  3102. {
  3103. m_host.AddScriptLPS(1);
  3104. int count = 0;
  3105. lock (m_host.TaskInventory)
  3106. {
  3107. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  3108. {
  3109. if (inv.Value.Type == type || type == -1)
  3110. {
  3111. count = count + 1;
  3112. }
  3113. }
  3114. }
  3115. return count;
  3116. }
  3117. public LSL_String llGetInventoryName(int type, int number)
  3118. {
  3119. m_host.AddScriptLPS(1);
  3120. ArrayList keys = new ArrayList();
  3121. lock (m_host.TaskInventory)
  3122. {
  3123. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  3124. {
  3125. if (inv.Value.Type == type || type == -1)
  3126. {
  3127. keys.Add(inv.Value.Name);
  3128. }
  3129. }
  3130. }
  3131. if (keys.Count == 0)
  3132. {
  3133. return String.Empty;
  3134. }
  3135. keys.Sort();
  3136. if (keys.Count > number)
  3137. {
  3138. return (string)keys[number];
  3139. }
  3140. return String.Empty;
  3141. }
  3142. public LSL_Float llGetEnergy()
  3143. {
  3144. m_host.AddScriptLPS(1);
  3145. // TODO: figure out real energy value
  3146. return 1.0f;
  3147. }
  3148. public void llGiveInventory(string destination, string inventory)
  3149. {
  3150. m_host.AddScriptLPS(1);
  3151. bool found = false;
  3152. UUID destId = UUID.Zero;
  3153. UUID objId = UUID.Zero;
  3154. int assetType = 0;
  3155. string objName = String.Empty;
  3156. if (!UUID.TryParse(destination, out destId))
  3157. {
  3158. llSay(0, "Could not parse key " + destination);
  3159. return;
  3160. }
  3161. // move the first object found with this inventory name
  3162. lock (m_host.TaskInventory)
  3163. {
  3164. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  3165. {
  3166. if (inv.Value.Name == inventory)
  3167. {
  3168. found = true;
  3169. objId = inv.Key;
  3170. assetType = inv.Value.Type;
  3171. objName = inv.Value.Name;
  3172. break;
  3173. }
  3174. }
  3175. }
  3176. if (!found)
  3177. {
  3178. llSay(0, String.Format("Could not find object '{0}'", inventory));
  3179. throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
  3180. }
  3181. // check if destination is an avatar
  3182. if (World.GetScenePresence(destId) != null)
  3183. {
  3184. // destination is an avatar
  3185. InventoryItemBase agentItem =
  3186. World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
  3187. if (agentItem == null)
  3188. return;
  3189. byte[] bucket = new byte[17];
  3190. bucket[0] = (byte)assetType;
  3191. byte[] objBytes = objId.GetBytes();
  3192. Array.Copy(objBytes, 0, bucket, 1, 16);
  3193. Console.WriteLine("Giving inventory");
  3194. GridInstantMessage msg = new GridInstantMessage(World,
  3195. m_host.UUID, m_host.Name+", an object owned by "+
  3196. resolveName(m_host.OwnerID)+",", destId,
  3197. (byte)InstantMessageDialog.InventoryOffered,
  3198. false, objName+"\n"+m_host.Name+" is located at "+
  3199. World.RegionInfo.RegionName+" "+
  3200. m_host.AbsolutePosition.ToString(),
  3201. agentItem.ID, true, m_host.AbsolutePosition,
  3202. bucket);
  3203. if (m_TransferModule != null)
  3204. m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
  3205. }
  3206. else
  3207. {
  3208. // destination is an object
  3209. World.MoveTaskInventoryItem(destId, m_host, objId);
  3210. }
  3211. ScriptSleep(3000);
  3212. }
  3213. public void llRemoveInventory(string name)
  3214. {
  3215. m_host.AddScriptLPS(1);
  3216. lock (m_host.TaskInventory)
  3217. {
  3218. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  3219. {
  3220. if (item.Name == name)
  3221. {
  3222. if (item.ItemID == m_itemID)
  3223. throw new ScriptDeleteException();
  3224. else
  3225. m_host.Inventory.RemoveInventoryItem(item.ItemID);
  3226. return;
  3227. }
  3228. }
  3229. }
  3230. }
  3231. public void llSetText(string text, LSL_Vector color, double alpha)
  3232. {
  3233. m_host.AddScriptLPS(1);
  3234. Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f),
  3235. Util.Clip((float)color.y, 0.0f, 1.0f),
  3236. Util.Clip((float)color.z, 0.0f, 1.0f));
  3237. m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
  3238. m_host.ParentGroup.HasGroupChanged = true;
  3239. }
  3240. public LSL_Float llWater(LSL_Vector offset)
  3241. {
  3242. m_host.AddScriptLPS(1);
  3243. return World.RegionInfo.RegionSettings.WaterHeight;
  3244. }
  3245. public void llPassTouches(int pass)
  3246. {
  3247. m_host.AddScriptLPS(1);
  3248. if (pass != 0)
  3249. m_host.PassTouches = true;
  3250. else
  3251. m_host.PassTouches = false;
  3252. }
  3253. public LSL_String llRequestAgentData(string id, int data)
  3254. {
  3255. m_host.AddScriptLPS(1);
  3256. UUID uuid = (UUID)id;
  3257. UserProfileData userProfile =
  3258. World.CommsManager.UserService.GetUserProfile(uuid);
  3259. UserAgentData userAgent =
  3260. World.CommsManager.UserService.GetAgentByUUID(uuid);
  3261. if (userProfile == null || userAgent == null)
  3262. return UUID.Zero.ToString();
  3263. string reply = String.Empty;
  3264. switch (data)
  3265. {
  3266. case 1: // DATA_ONLINE (0|1)
  3267. // TODO: implement fetching of this information
  3268. if (userProfile.CurrentAgent.AgentOnline)
  3269. reply = "1";
  3270. else
  3271. reply = "0";
  3272. break;
  3273. case 2: // DATA_NAME (First Last)
  3274. reply = userProfile.FirstName + " " + userProfile.SurName;
  3275. break;
  3276. case 3: // DATA_BORN (YYYY-MM-DD)
  3277. DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
  3278. born = born.AddSeconds(userProfile.Created);
  3279. reply = born.ToString("yyyy-MM-dd");
  3280. break;
  3281. case 4: // DATA_RATING (0,0,0,0,0,0)
  3282. reply = "0,0,0,0,0,0";
  3283. break;
  3284. case 8: // DATA_PAYINFO (0|1|2|3)
  3285. reply = "0";
  3286. break;
  3287. default:
  3288. return UUID.Zero.ToString(); // Raise no event
  3289. }
  3290. UUID rq = UUID.Random();
  3291. UUID tid = AsyncCommands.
  3292. DataserverPlugin.RegisterRequest(m_localID,
  3293. m_itemID, rq.ToString());
  3294. AsyncCommands.
  3295. DataserverPlugin.DataserverReply(rq.ToString(), reply);
  3296. ScriptSleep(100);
  3297. return tid.ToString();
  3298. }
  3299. public LSL_String llRequestInventoryData(string name)
  3300. {
  3301. m_host.AddScriptLPS(1);
  3302. TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
  3303. foreach (TaskInventoryItem item in itemDictionary.Values)
  3304. {
  3305. if (item.Type == 3 && item.Name == name)
  3306. {
  3307. UUID tid = AsyncCommands.
  3308. DataserverPlugin.RegisterRequest(m_localID,
  3309. m_itemID, item.AssetID.ToString());
  3310. Vector3 region = new Vector3(
  3311. World.RegionInfo.RegionLocX * Constants.RegionSize,
  3312. World.RegionInfo.RegionLocY * Constants.RegionSize,
  3313. 0);
  3314. World.AssetService.Get(item.AssetID.ToString(), this,
  3315. delegate(string i, object sender, AssetBase a)
  3316. {
  3317. AssetLandmark lm = new AssetLandmark(a);
  3318. float rx = (uint)(lm.RegionHandle >> 32);
  3319. float ry = (uint)lm.RegionHandle;
  3320. region = lm.Position + new Vector3(rx, ry, 0) - region;
  3321. string reply = region.ToString();
  3322. AsyncCommands.
  3323. DataserverPlugin.DataserverReply(i.ToString(),
  3324. reply);
  3325. });
  3326. ScriptSleep(1000);
  3327. return tid.ToString();
  3328. }
  3329. }
  3330. ScriptSleep(1000);
  3331. return String.Empty;
  3332. }
  3333. public void llSetDamage(double damage)
  3334. {
  3335. m_host.AddScriptLPS(1);
  3336. m_host.ParentGroup.Damage = (float)damage;
  3337. }
  3338. public void llTeleportAgentHome(string agent)
  3339. {
  3340. m_host.AddScriptLPS(1);
  3341. UUID agentId = new UUID();
  3342. if (UUID.TryParse(agent, out agentId))
  3343. {
  3344. ScenePresence presence = World.GetScenePresence(agentId);
  3345. if (presence != null)
  3346. {
  3347. // agent must be over the owners land
  3348. if (m_host.OwnerID == World.LandChannel.GetLandObject(
  3349. presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
  3350. {
  3351. presence.ControllingClient.SendTeleportLocationStart();
  3352. World.TeleportClientHome(agentId, presence.ControllingClient);
  3353. }
  3354. }
  3355. }
  3356. ScriptSleep(5000);
  3357. }
  3358. public void llTextBox(string avatar, string message, int chat_channel)
  3359. {
  3360. m_host.AddScriptLPS(1);
  3361. NotImplemented("llTextBox");
  3362. }
  3363. public void llModifyLand(int action, int brush)
  3364. {
  3365. m_host.AddScriptLPS(1);
  3366. ITerrainModule tm = m_ScriptEngine.World.RequestModuleInterface<ITerrainModule>();
  3367. if (tm != null)
  3368. {
  3369. tm.ModifyTerrain(m_host.OwnerID, m_host.AbsolutePosition, (byte) brush, (byte) action, m_host.OwnerID);
  3370. }
  3371. }
  3372. public void llCollisionSound(string impact_sound, double impact_volume)
  3373. {
  3374. m_host.AddScriptLPS(1);
  3375. //NotImplemented("llCollisionSound");
  3376. // TODO: Parameter check logic required.
  3377. UUID soundId = UUID.Zero;
  3378. if (!UUID.TryParse(impact_sound, out soundId))
  3379. {
  3380. lock (m_host.TaskInventory)
  3381. {
  3382. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  3383. {
  3384. if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
  3385. {
  3386. soundId = item.AssetID;
  3387. break;
  3388. }
  3389. }
  3390. }
  3391. }
  3392. m_host.CollisionSound = soundId;
  3393. m_host.CollisionSoundVolume = (float)impact_volume;
  3394. }
  3395. public void llCollisionSprite(string impact_sprite)
  3396. {
  3397. m_host.AddScriptLPS(1);
  3398. NotImplemented("llCollisionSprite");
  3399. }
  3400. public LSL_String llGetAnimation(string id)
  3401. {
  3402. // This should only return a value if the avatar is in the same region
  3403. m_host.AddScriptLPS(1);
  3404. UUID avatar = (UUID)id;
  3405. ScenePresence presence = World.GetScenePresence(avatar);
  3406. if (presence == null)
  3407. return "";
  3408. if (m_host.RegionHandle == presence.RegionHandle)
  3409. {
  3410. Dictionary<UUID, string> animationstateNames = AnimationSet.Animations.AnimStateNames;
  3411. if (presence != null)
  3412. {
  3413. AnimationSet currentAnims = presence.Animations;
  3414. string currentAnimationState = String.Empty;
  3415. if (animationstateNames.TryGetValue(currentAnims.DefaultAnimation.AnimID, out currentAnimationState))
  3416. return currentAnimationState;
  3417. }
  3418. }
  3419. return String.Empty;
  3420. }
  3421. public void llMessageLinked(int linknumber, int num, string msg, string id)
  3422. {
  3423. m_host.AddScriptLPS(1);
  3424. List<SceneObjectPart> parts = GetLinkParts(linknumber);
  3425. UUID partItemID;
  3426. foreach (SceneObjectPart part in parts)
  3427. {
  3428. TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
  3429. foreach (TaskInventoryItem item in itemsDictionary.Values)
  3430. {
  3431. if (item.Type == ScriptBaseClass.INVENTORY_SCRIPT)
  3432. {
  3433. partItemID = item.ItemID;
  3434. int linkNumber = m_host.LinkNum;
  3435. if (m_host.ParentGroup.Children.Count == 1)
  3436. linkNumber = 0;
  3437. object[] resobj = new object[]
  3438. {
  3439. new LSL_Integer(linkNumber), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
  3440. };
  3441. m_ScriptEngine.PostScriptEvent(partItemID,
  3442. new EventParams("link_message",
  3443. resobj, new DetectParams[0]));
  3444. }
  3445. }
  3446. }
  3447. }
  3448. public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local)
  3449. {
  3450. m_host.AddScriptLPS(1);
  3451. bool pushrestricted = World.RegionInfo.RegionSettings.RestrictPushing;
  3452. bool pushAllowed = false;
  3453. bool pusheeIsAvatar = false;
  3454. UUID targetID = UUID.Zero;
  3455. if (!UUID.TryParse(target,out targetID))
  3456. return;
  3457. ScenePresence pusheeav = null;
  3458. Vector3 PusheePos = Vector3.Zero;
  3459. SceneObjectPart pusheeob = null;
  3460. ScenePresence avatar = World.GetScenePresence(targetID);
  3461. if (avatar != null)
  3462. {
  3463. pusheeIsAvatar = true;
  3464. // Pushee doesn't have a physics actor
  3465. if (avatar.PhysicsActor == null)
  3466. return;
  3467. // Pushee is in GodMode this pushing object isn't owned by them
  3468. if (avatar.GodLevel > 0 && m_host.OwnerID != targetID)
  3469. return;
  3470. pusheeav = avatar;
  3471. // Find pushee position
  3472. // Pushee Linked?
  3473. if (pusheeav.ParentID != 0)
  3474. {
  3475. SceneObjectPart parentobj = World.GetSceneObjectPart(pusheeav.ParentID);
  3476. if (parentobj != null)
  3477. {
  3478. PusheePos = parentobj.AbsolutePosition;
  3479. }
  3480. else
  3481. {
  3482. PusheePos = pusheeav.AbsolutePosition;
  3483. }
  3484. }
  3485. else
  3486. {
  3487. PusheePos = pusheeav.AbsolutePosition;
  3488. }
  3489. }
  3490. if (!pusheeIsAvatar)
  3491. {
  3492. // not an avatar so push is not affected by parcel flags
  3493. pusheeob = World.GetSceneObjectPart((UUID)target);
  3494. // We can't find object
  3495. if (pusheeob == null)
  3496. return;
  3497. // Object not pushable. Not an attachment and has no physics component
  3498. if (!pusheeob.IsAttachment && pusheeob.PhysActor == null)
  3499. return;
  3500. PusheePos = pusheeob.AbsolutePosition;
  3501. pushAllowed = true;
  3502. }
  3503. else
  3504. {
  3505. if (pushrestricted)
  3506. {
  3507. ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos.X, PusheePos.Y);
  3508. // We didn't find the parcel but region is push restricted so assume it is NOT ok
  3509. if (targetlandObj == null)
  3510. return;
  3511. // Need provisions for Group Owned here
  3512. if (m_host.OwnerID == targetlandObj.LandData.OwnerID ||
  3513. targetlandObj.LandData.IsGroupOwned || m_host.OwnerID == targetID)
  3514. {
  3515. pushAllowed = true;
  3516. }
  3517. }
  3518. else
  3519. {
  3520. ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos.X, PusheePos.Y);
  3521. if (targetlandObj == null)
  3522. {
  3523. // We didn't find the parcel but region isn't push restricted so assume it's ok
  3524. pushAllowed = true;
  3525. }
  3526. else
  3527. {
  3528. // Parcel push restriction
  3529. if ((targetlandObj.LandData.Flags & (uint)ParcelFlags.RestrictPushObject) == (uint)ParcelFlags.RestrictPushObject)
  3530. {
  3531. // Need provisions for Group Owned here
  3532. if (m_host.OwnerID == targetlandObj.LandData.OwnerID ||
  3533. targetlandObj.LandData.IsGroupOwned ||
  3534. m_host.OwnerID == targetID)
  3535. {
  3536. pushAllowed = true;
  3537. }
  3538. //ParcelFlags.RestrictPushObject
  3539. //pushAllowed = true;
  3540. }
  3541. else
  3542. {
  3543. // Parcel isn't push restricted
  3544. pushAllowed = true;
  3545. }
  3546. }
  3547. }
  3548. }
  3549. if (pushAllowed)
  3550. {
  3551. float distance = (PusheePos - m_host.AbsolutePosition).Length();
  3552. float distance_term = distance * distance * distance; // Script Energy
  3553. float pusher_mass = m_host.GetMass();
  3554. float PUSH_ATTENUATION_DISTANCE = 17f;
  3555. float PUSH_ATTENUATION_SCALE = 5f;
  3556. float distance_attenuation = 1f;
  3557. if (distance > PUSH_ATTENUATION_DISTANCE)
  3558. {
  3559. float normalized_units = 1f + (distance - PUSH_ATTENUATION_DISTANCE) / PUSH_ATTENUATION_SCALE;
  3560. distance_attenuation = 1f / normalized_units;
  3561. }
  3562. Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z);
  3563. {
  3564. float impulse_length = applied_linear_impulse.Length();
  3565. float desired_energy = impulse_length * pusher_mass;
  3566. if (desired_energy > 0f)
  3567. desired_energy += distance_term;
  3568. float scaling_factor = 1f;
  3569. scaling_factor *= distance_attenuation;
  3570. applied_linear_impulse *= scaling_factor;
  3571. }
  3572. if (pusheeIsAvatar)
  3573. {
  3574. if (pusheeav != null)
  3575. {
  3576. if (pusheeav.PhysicsActor != null)
  3577. {
  3578. if (local != 0)
  3579. {
  3580. applied_linear_impulse *= m_host.GetWorldRotation();
  3581. }
  3582. pusheeav.PhysicsActor.AddForce(new PhysicsVector(applied_linear_impulse.X, applied_linear_impulse.Y, applied_linear_impulse.Z), true);
  3583. }
  3584. }
  3585. }
  3586. else
  3587. {
  3588. if (pusheeob != null)
  3589. {
  3590. if (pusheeob.PhysActor != null)
  3591. {
  3592. pusheeob.ApplyImpulse(applied_linear_impulse, local != 0);
  3593. }
  3594. }
  3595. }
  3596. }
  3597. }
  3598. public void llPassCollisions(int pass)
  3599. {
  3600. m_host.AddScriptLPS(1);
  3601. NotImplemented("llPassCollisions");
  3602. }
  3603. public LSL_String llGetScriptName()
  3604. {
  3605. string result = String.Empty;
  3606. m_host.AddScriptLPS(1);
  3607. lock (m_host.TaskInventory)
  3608. {
  3609. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  3610. {
  3611. if (item.Type == 10 && item.ItemID == m_itemID)
  3612. {
  3613. result = item.Name!=null?item.Name:String.Empty;
  3614. break;
  3615. }
  3616. }
  3617. }
  3618. return result;
  3619. }
  3620. // this function to understand which shape it is (taken from meshmerizer)
  3621. // quite useful can be used by meshmerizer to have a centralized point of understanding the shape
  3622. // except that it refers to scripting constants
  3623. public int getScriptPrimType(PrimitiveBaseShape primShape)
  3624. {
  3625. if (primShape.SculptEntry)
  3626. return ScriptBaseClass.PRIM_TYPE_SCULPT;
  3627. if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
  3628. {
  3629. if (primShape.PathCurve == (byte)Extrusion.Straight)
  3630. return ScriptBaseClass.PRIM_TYPE_BOX;
  3631. else if (primShape.PathCurve == (byte)Extrusion.Curve1)
  3632. return ScriptBaseClass.PRIM_TYPE_TUBE;
  3633. }
  3634. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
  3635. {
  3636. if (primShape.PathCurve == (byte)Extrusion.Straight)
  3637. return ScriptBaseClass.PRIM_TYPE_CYLINDER;
  3638. // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
  3639. else if (primShape.PathCurve == (byte)Extrusion.Curve1)
  3640. return ScriptBaseClass.PRIM_TYPE_TORUS;
  3641. }
  3642. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
  3643. {
  3644. if (primShape.PathCurve == (byte)Extrusion.Curve1 || primShape.PathCurve == (byte)Extrusion.Curve2)
  3645. return ScriptBaseClass.PRIM_TYPE_SPHERE;
  3646. }
  3647. else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
  3648. {
  3649. if (primShape.PathCurve == (byte)Extrusion.Straight)
  3650. return ScriptBaseClass.PRIM_TYPE_PRISM;
  3651. else if (primShape.PathCurve == (byte)Extrusion.Curve1)
  3652. return ScriptBaseClass.PRIM_TYPE_RING;
  3653. }
  3654. return ScriptBaseClass.PRIM_TYPE_BOX;
  3655. }
  3656. // Helper functions to understand if object has cut, hollow, dimple, and other affecting number of faces
  3657. protected void hasCutHollowDimpleProfileCut(int primType, PrimitiveBaseShape shape, out bool hasCut, out bool hasHollow,
  3658. out bool hasDimple, out bool hasProfileCut)
  3659. {
  3660. if (primType == ScriptBaseClass.PRIM_TYPE_BOX
  3661. ||
  3662. primType == ScriptBaseClass.PRIM_TYPE_CYLINDER
  3663. ||
  3664. primType == ScriptBaseClass.PRIM_TYPE_PRISM)
  3665. hasCut = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0);
  3666. else
  3667. hasCut = (shape.PathBegin > 0) || (shape.PathEnd > 0);
  3668. hasHollow = shape.ProfileHollow > 0;
  3669. hasDimple = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); // taken from llSetPrimitiveParms
  3670. hasProfileCut = hasDimple; // is it the same thing?
  3671. }
  3672. public LSL_Integer llGetNumberOfSides()
  3673. {
  3674. m_host.AddScriptLPS(1);
  3675. return GetNumberOfSides(m_host);
  3676. }
  3677. protected int GetNumberOfSides(SceneObjectPart part)
  3678. {
  3679. int ret = 0;
  3680. bool hasCut;
  3681. bool hasHollow;
  3682. bool hasDimple;
  3683. bool hasProfileCut;
  3684. int primType = getScriptPrimType(part.Shape);
  3685. hasCutHollowDimpleProfileCut(primType, part.Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut);
  3686. switch (primType)
  3687. {
  3688. case ScriptBaseClass.PRIM_TYPE_BOX:
  3689. ret = 6;
  3690. if (hasCut) ret += 2;
  3691. if (hasHollow) ret += 1;
  3692. break;
  3693. case ScriptBaseClass.PRIM_TYPE_CYLINDER:
  3694. ret = 3;
  3695. if (hasCut) ret += 2;
  3696. if (hasHollow) ret += 1;
  3697. break;
  3698. case ScriptBaseClass.PRIM_TYPE_PRISM:
  3699. ret = 5;
  3700. if (hasCut) ret += 2;
  3701. if (hasHollow) ret += 1;
  3702. break;
  3703. case ScriptBaseClass.PRIM_TYPE_SPHERE:
  3704. ret = 1;
  3705. if (hasCut) ret += 2;
  3706. if (hasDimple) ret += 2;
  3707. if (hasHollow) ret += 3; // Emulate lsl on secondlife (according to documentation it should have added only +1)
  3708. break;
  3709. case ScriptBaseClass.PRIM_TYPE_TORUS:
  3710. ret = 1;
  3711. if (hasCut) ret += 2;
  3712. if (hasProfileCut) ret += 2;
  3713. if (hasHollow) ret += 1;
  3714. break;
  3715. case ScriptBaseClass.PRIM_TYPE_TUBE:
  3716. ret = 4;
  3717. if (hasCut) ret += 2;
  3718. if (hasProfileCut) ret += 2;
  3719. if (hasHollow) ret += 1;
  3720. break;
  3721. case ScriptBaseClass.PRIM_TYPE_RING:
  3722. ret = 3;
  3723. if (hasCut) ret += 2;
  3724. if (hasProfileCut) ret += 2;
  3725. if (hasHollow) ret += 1;
  3726. break;
  3727. case ScriptBaseClass.PRIM_TYPE_SCULPT:
  3728. ret = 1;
  3729. break;
  3730. }
  3731. return ret;
  3732. }
  3733. /* The new / changed functions were tested with the following LSL script:
  3734. default
  3735. {
  3736. state_entry()
  3737. {
  3738. rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD);
  3739. llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot));
  3740. llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG));
  3741. // convert back and forth between quaternion <-> vector and angle
  3742. rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot));
  3743. llOwnerSay("Old rotation was: "+(string) rot);
  3744. llOwnerSay("re-converted rotation is: "+(string) newrot);
  3745. llSetRot(rot); // to check the parameters in the prim
  3746. }
  3747. }
  3748. */
  3749. // Xantor 29/apr/2008
  3750. // Returns rotation described by rotating angle radians about axis.
  3751. // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
  3752. public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle)
  3753. {
  3754. m_host.AddScriptLPS(1);
  3755. double x, y, z, s, t;
  3756. s = Math.Cos(angle / 2);
  3757. t = Math.Sin(angle / 2); // temp value to avoid 2 more sin() calcs
  3758. x = axis.x * t;
  3759. y = axis.y * t;
  3760. z = axis.z * t;
  3761. return new LSL_Rotation(x,y,z,s);
  3762. }
  3763. // Xantor 29/apr/2008
  3764. // converts a Quaternion to X,Y,Z axis rotations
  3765. public LSL_Vector llRot2Axis(LSL_Rotation rot)
  3766. {
  3767. m_host.AddScriptLPS(1);
  3768. double x,y,z;
  3769. if (rot.s > 1) // normalization needed
  3770. {
  3771. double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
  3772. rot.z * rot.z + rot.s * rot.s);
  3773. rot.x /= length;
  3774. rot.y /= length;
  3775. rot.z /= length;
  3776. rot.s /= length;
  3777. }
  3778. // double angle = 2 * Math.Acos(rot.s);
  3779. double s = Math.Sqrt(1 - rot.s * rot.s);
  3780. if (s < 0.001)
  3781. {
  3782. x = 1;
  3783. y = z = 0;
  3784. }
  3785. else
  3786. {
  3787. x = rot.x / s; // normalise axis
  3788. y = rot.y / s;
  3789. z = rot.z / s;
  3790. }
  3791. return new LSL_Vector(x,y,z);
  3792. }
  3793. // Returns the angle of a quaternion (see llRot2Axis for the axis)
  3794. public LSL_Float llRot2Angle(LSL_Rotation rot)
  3795. {
  3796. m_host.AddScriptLPS(1);
  3797. if (rot.s > 1) // normalization needed
  3798. {
  3799. double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
  3800. rot.z * rot.z + rot.s * rot.s);
  3801. rot.x /= length;
  3802. rot.y /= length;
  3803. rot.z /= length;
  3804. rot.s /= length;
  3805. }
  3806. double angle = 2 * Math.Acos(rot.s);
  3807. return angle;
  3808. }
  3809. public LSL_Float llAcos(double val)
  3810. {
  3811. m_host.AddScriptLPS(1);
  3812. return (double)Math.Acos(val);
  3813. }
  3814. public LSL_Float llAsin(double val)
  3815. {
  3816. m_host.AddScriptLPS(1);
  3817. return (double)Math.Asin(val);
  3818. }
  3819. // Xantor 30/apr/2008
  3820. public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b)
  3821. {
  3822. m_host.AddScriptLPS(1);
  3823. double angle = Math.Acos(a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s) * 2;
  3824. if (angle < 0) angle = -angle;
  3825. if (angle > Math.PI) return (Math.PI * 2 - angle);
  3826. return angle;
  3827. }
  3828. public LSL_String llGetInventoryKey(string name)
  3829. {
  3830. m_host.AddScriptLPS(1);
  3831. lock (m_host.TaskInventory)
  3832. {
  3833. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  3834. {
  3835. if (inv.Value.Name == name)
  3836. {
  3837. if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
  3838. {
  3839. return inv.Value.AssetID.ToString();
  3840. }
  3841. else
  3842. {
  3843. return UUID.Zero.ToString();
  3844. }
  3845. }
  3846. }
  3847. }
  3848. return UUID.Zero.ToString();
  3849. }
  3850. public void llAllowInventoryDrop(int add)
  3851. {
  3852. m_host.AddScriptLPS(1);
  3853. if (add != 0)
  3854. m_host.ParentGroup.RootPart.AllowedDrop = true;
  3855. else
  3856. m_host.ParentGroup.RootPart.AllowedDrop = false;
  3857. // Update the object flags
  3858. m_host.ParentGroup.RootPart.aggregateScriptEvents();
  3859. }
  3860. public LSL_Vector llGetSunDirection()
  3861. {
  3862. m_host.AddScriptLPS(1);
  3863. LSL_Vector SunDoubleVector3;
  3864. Vector3 SunFloatVector3;
  3865. // sunPosition estate setting is set in OpenSim.Region.CoreModules.SunModule
  3866. // have to convert from Vector3 (float) to LSL_Vector (double)
  3867. SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector;
  3868. SunDoubleVector3.x = (double)SunFloatVector3.X;
  3869. SunDoubleVector3.y = (double)SunFloatVector3.Y;
  3870. SunDoubleVector3.z = (double)SunFloatVector3.Z;
  3871. return SunDoubleVector3;
  3872. }
  3873. public LSL_Vector llGetTextureOffset(int face)
  3874. {
  3875. m_host.AddScriptLPS(1);
  3876. return GetTextureOffset(m_host, face);
  3877. }
  3878. protected LSL_Vector GetTextureOffset(SceneObjectPart part, int face)
  3879. {
  3880. Primitive.TextureEntry tex = part.Shape.Textures;
  3881. LSL_Vector offset = new LSL_Vector();
  3882. if (face == ScriptBaseClass.ALL_SIDES)
  3883. {
  3884. face = 0;
  3885. }
  3886. if (face >= 0 && face < GetNumberOfSides(part))
  3887. {
  3888. offset.x = tex.GetFace((uint)face).OffsetU;
  3889. offset.y = tex.GetFace((uint)face).OffsetV;
  3890. offset.z = 0.0;
  3891. return offset;
  3892. }
  3893. else
  3894. {
  3895. return offset;
  3896. }
  3897. }
  3898. public LSL_Vector llGetTextureScale(int side)
  3899. {
  3900. m_host.AddScriptLPS(1);
  3901. Primitive.TextureEntry tex = m_host.Shape.Textures;
  3902. LSL_Vector scale;
  3903. if (side == -1)
  3904. {
  3905. side = 0;
  3906. }
  3907. scale.x = tex.GetFace((uint)side).RepeatU;
  3908. scale.y = tex.GetFace((uint)side).RepeatV;
  3909. scale.z = 0.0;
  3910. return scale;
  3911. }
  3912. public LSL_Float llGetTextureRot(int face)
  3913. {
  3914. m_host.AddScriptLPS(1);
  3915. return GetTextureRot(m_host, face);
  3916. }
  3917. protected LSL_Float GetTextureRot(SceneObjectPart part, int face)
  3918. {
  3919. Primitive.TextureEntry tex = part.Shape.Textures;
  3920. if (face == -1)
  3921. {
  3922. face = 0;
  3923. }
  3924. if (face >= 0 && face < GetNumberOfSides(part))
  3925. {
  3926. return tex.GetFace((uint)face).Rotation;
  3927. }
  3928. else
  3929. {
  3930. return 0.0;
  3931. }
  3932. }
  3933. public LSL_Integer llSubStringIndex(string source, string pattern)
  3934. {
  3935. m_host.AddScriptLPS(1);
  3936. return source.IndexOf(pattern);
  3937. }
  3938. public LSL_String llGetOwnerKey(string id)
  3939. {
  3940. m_host.AddScriptLPS(1);
  3941. UUID key = new UUID();
  3942. if (UUID.TryParse(id, out key))
  3943. {
  3944. try
  3945. {
  3946. SceneObjectPart obj = World.GetSceneObjectPart(key);
  3947. if (obj == null)
  3948. return id; // the key is for an agent so just return the key
  3949. else
  3950. return obj.OwnerID.ToString();
  3951. }
  3952. catch (KeyNotFoundException)
  3953. {
  3954. return id; // The Object/Agent not in the region so just return the key
  3955. }
  3956. }
  3957. else
  3958. {
  3959. return UUID.Zero.ToString();
  3960. }
  3961. }
  3962. public LSL_Vector llGetCenterOfMass()
  3963. {
  3964. m_host.AddScriptLPS(1);
  3965. NotImplemented("llGetCenterOfMass");
  3966. return new LSL_Vector();
  3967. }
  3968. public LSL_List llListSort(LSL_List src, int stride, int ascending)
  3969. {
  3970. m_host.AddScriptLPS(1);
  3971. if (stride <= 0)
  3972. {
  3973. stride = 1;
  3974. }
  3975. return src.Sort(stride, ascending);
  3976. }
  3977. public LSL_Integer llGetListLength(LSL_List src)
  3978. {
  3979. m_host.AddScriptLPS(1);
  3980. if (src == null)
  3981. {
  3982. return 0;
  3983. }
  3984. else
  3985. {
  3986. return src.Length;
  3987. }
  3988. }
  3989. public LSL_Integer llList2Integer(LSL_List src, int index)
  3990. {
  3991. m_host.AddScriptLPS(1);
  3992. if (index < 0)
  3993. {
  3994. index = src.Length + index;
  3995. }
  3996. if (index >= src.Length || index < 0)
  3997. {
  3998. return 0;
  3999. }
  4000. try
  4001. {
  4002. if (src.Data[index] is LSL_Integer)
  4003. return (LSL_Integer) src.Data[index];
  4004. else if (src.Data[index] is LSL_Float)
  4005. return Convert.ToInt32(((LSL_Float) src.Data[index]).value);
  4006. return new LSL_Integer(src.Data[index].ToString());
  4007. }
  4008. catch (FormatException)
  4009. {
  4010. return 0;
  4011. }
  4012. }
  4013. public LSL_Float llList2Float(LSL_List src, int index)
  4014. {
  4015. m_host.AddScriptLPS(1);
  4016. if (index < 0)
  4017. {
  4018. index = src.Length + index;
  4019. }
  4020. if (index >= src.Length || index < 0)
  4021. {
  4022. return 0.0;
  4023. }
  4024. try
  4025. {
  4026. if (src.Data[index] is LSL_Integer)
  4027. return Convert.ToDouble(((LSL_Integer) src.Data[index]).value);
  4028. else if (src.Data[index] is LSL_Float)
  4029. return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
  4030. else if (src.Data[index] is LSL_String)
  4031. return Convert.ToDouble(((LSL_String) src.Data[index]).m_string);
  4032. return Convert.ToDouble(src.Data[index]);
  4033. }
  4034. catch (FormatException)
  4035. {
  4036. return 0.0;
  4037. }
  4038. }
  4039. public LSL_String llList2String(LSL_List src, int index)
  4040. {
  4041. m_host.AddScriptLPS(1);
  4042. if (index < 0)
  4043. {
  4044. index = src.Length + index;
  4045. }
  4046. if (index >= src.Length || index < 0)
  4047. {
  4048. return String.Empty;
  4049. }
  4050. return src.Data[index].ToString();
  4051. }
  4052. public LSL_String llList2Key(LSL_List src, int index)
  4053. {
  4054. m_host.AddScriptLPS(1);
  4055. if (index < 0)
  4056. {
  4057. index = src.Length + index;
  4058. }
  4059. if (index >= src.Length || index < 0)
  4060. {
  4061. return "";
  4062. }
  4063. return src.Data[index].ToString();
  4064. }
  4065. public LSL_Vector llList2Vector(LSL_List src, int index)
  4066. {
  4067. m_host.AddScriptLPS(1);
  4068. if (index < 0)
  4069. {
  4070. index = src.Length + index;
  4071. }
  4072. if (index >= src.Length || index < 0)
  4073. {
  4074. return new LSL_Vector(0, 0, 0);
  4075. }
  4076. if (src.Data[index].GetType() == typeof(LSL_Vector))
  4077. {
  4078. return (LSL_Vector)src.Data[index];
  4079. }
  4080. else
  4081. {
  4082. return new LSL_Vector(src.Data[index].ToString());
  4083. }
  4084. }
  4085. public LSL_Rotation llList2Rot(LSL_List src, int index)
  4086. {
  4087. m_host.AddScriptLPS(1);
  4088. if (index < 0)
  4089. {
  4090. index = src.Length + index;
  4091. }
  4092. if (index >= src.Length || index < 0)
  4093. {
  4094. return new LSL_Rotation(0, 0, 0, 1);
  4095. }
  4096. if (src.Data[index].GetType() == typeof(LSL_Rotation))
  4097. {
  4098. return (LSL_Rotation)src.Data[index];
  4099. }
  4100. else
  4101. {
  4102. return new LSL_Rotation(src.Data[index].ToString());
  4103. }
  4104. }
  4105. public LSL_List llList2List(LSL_List src, int start, int end)
  4106. {
  4107. m_host.AddScriptLPS(1);
  4108. return src.GetSublist(start, end);
  4109. }
  4110. public LSL_List llDeleteSubList(LSL_List src, int start, int end)
  4111. {
  4112. return src.DeleteSublist(start, end);
  4113. }
  4114. public LSL_Integer llGetListEntryType(LSL_List src, int index)
  4115. {
  4116. m_host.AddScriptLPS(1);
  4117. if (index < 0)
  4118. {
  4119. index = src.Length + index;
  4120. }
  4121. if (index >= src.Length)
  4122. {
  4123. return 0;
  4124. }
  4125. if (src.Data[index] is LSL_Integer || src.Data[index] is Int32)
  4126. return 1;
  4127. if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double)
  4128. return 2;
  4129. if (src.Data[index] is LSL_String || src.Data[index] is String)
  4130. {
  4131. UUID tuuid;
  4132. if (UUID.TryParse(src.Data[index].ToString(), out tuuid))
  4133. {
  4134. return 4;
  4135. }
  4136. else
  4137. {
  4138. return 3;
  4139. }
  4140. }
  4141. if (src.Data[index] is LSL_Vector)
  4142. return 5;
  4143. if (src.Data[index] is LSL_Rotation)
  4144. return 6;
  4145. if (src.Data[index] is LSL_List)
  4146. return 7;
  4147. return 0;
  4148. }
  4149. /// <summary>
  4150. /// Process the supplied list and return the
  4151. /// content of the list formatted as a comma
  4152. /// separated list. There is a space after
  4153. /// each comma.
  4154. /// </summary>
  4155. public LSL_String llList2CSV(LSL_List src)
  4156. {
  4157. string ret = String.Empty;
  4158. int x = 0;
  4159. m_host.AddScriptLPS(1);
  4160. if (src.Data.Length > 0)
  4161. {
  4162. ret = src.Data[x++].ToString();
  4163. for (; x < src.Data.Length; x++)
  4164. {
  4165. ret += ", "+src.Data[x].ToString();
  4166. }
  4167. }
  4168. return ret;
  4169. }
  4170. /// <summary>
  4171. /// The supplied string is scanned for commas
  4172. /// and converted into a list. Commas are only
  4173. /// effective if they are encountered outside
  4174. /// of '<' '>' delimiters. Any whitespace
  4175. /// before or after an element is trimmed.
  4176. /// </summary>
  4177. public LSL_List llCSV2List(string src)
  4178. {
  4179. LSL_List result = new LSL_List();
  4180. int parens = 0;
  4181. int start = 0;
  4182. int length = 0;
  4183. m_host.AddScriptLPS(1);
  4184. for (int i = 0; i < src.Length; i++)
  4185. {
  4186. switch (src[i])
  4187. {
  4188. case '<':
  4189. parens++;
  4190. length++;
  4191. break;
  4192. case '>':
  4193. if (parens > 0)
  4194. parens--;
  4195. length++;
  4196. break;
  4197. case ',':
  4198. if (parens == 0)
  4199. {
  4200. result.Add(src.Substring(start,length).Trim());
  4201. start += length+1;
  4202. length = 0;
  4203. }
  4204. else
  4205. {
  4206. length++;
  4207. }
  4208. break;
  4209. default:
  4210. length++;
  4211. break;
  4212. }
  4213. }
  4214. result.Add(src.Substring(start,length).Trim());
  4215. return result;
  4216. }
  4217. /// <summary>
  4218. /// Randomizes the list, be arbitrarily reordering
  4219. /// sublists of stride elements. As the stride approaches
  4220. /// the size of the list, the options become very
  4221. /// limited.
  4222. /// </summary>
  4223. /// <remarks>
  4224. /// This could take a while for very large list
  4225. /// sizes.
  4226. /// </remarks>
  4227. public LSL_List llListRandomize(LSL_List src, int stride)
  4228. {
  4229. LSL_List result;
  4230. Random rand = new Random();
  4231. int chunkk;
  4232. int[] chunks;
  4233. m_host.AddScriptLPS(1);
  4234. if (stride <= 0)
  4235. {
  4236. stride = 1;
  4237. }
  4238. // Stride MUST be a factor of the list length
  4239. // If not, then return the src list. This also
  4240. // traps those cases where stride > length.
  4241. if (src.Length != stride && src.Length%stride == 0)
  4242. {
  4243. chunkk = src.Length/stride;
  4244. chunks = new int[chunkk];
  4245. for (int i = 0; i < chunkk; i++)
  4246. chunks[i] = i;
  4247. // Knuth shuffle the chunkk index
  4248. for (int i = chunkk - 1; i >= 1; i--)
  4249. {
  4250. // Elect an unrandomized chunk to swap
  4251. int index = rand.Next(i + 1);
  4252. int tmp;
  4253. // and swap position with first unrandomized chunk
  4254. tmp = chunks[i];
  4255. chunks[i] = chunks[index];
  4256. chunks[index] = tmp;
  4257. }
  4258. // Construct the randomized list
  4259. result = new LSL_List();
  4260. for (int i = 0; i < chunkk; i++)
  4261. {
  4262. for (int j = 0; j < stride; j++)
  4263. {
  4264. result.Add(src.Data[chunks[i]*stride+j]);
  4265. }
  4266. }
  4267. }
  4268. else {
  4269. object[] array = new object[src.Length];
  4270. Array.Copy(src.Data, 0, array, 0, src.Length);
  4271. result = new LSL_List(array);
  4272. }
  4273. return result;
  4274. }
  4275. /// <summary>
  4276. /// Elements in the source list starting with 0 and then
  4277. /// every i+stride. If the stride is negative then the scan
  4278. /// is backwards producing an inverted result.
  4279. /// Only those elements that are also in the specified
  4280. /// range are included in the result.
  4281. /// </summary>
  4282. public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride)
  4283. {
  4284. LSL_List result = new LSL_List();
  4285. int[] si = new int[2];
  4286. int[] ei = new int[2];
  4287. bool twopass = false;
  4288. m_host.AddScriptLPS(1);
  4289. // First step is always to deal with negative indices
  4290. if (start < 0)
  4291. start = src.Length+start;
  4292. if (end < 0)
  4293. end = src.Length+end;
  4294. // Out of bounds indices are OK, just trim them
  4295. // accordingly
  4296. if (start > src.Length)
  4297. start = src.Length;
  4298. if (end > src.Length)
  4299. end = src.Length;
  4300. if (stride == 0)
  4301. stride = 1;
  4302. // There may be one or two ranges to be considered
  4303. if (start != end)
  4304. {
  4305. if (start <= end)
  4306. {
  4307. si[0] = start;
  4308. ei[0] = end;
  4309. }
  4310. else
  4311. {
  4312. si[1] = start;
  4313. ei[1] = src.Length;
  4314. si[0] = 0;
  4315. ei[0] = end;
  4316. twopass = true;
  4317. }
  4318. // The scan always starts from the beginning of the
  4319. // source list, but members are only selected if they
  4320. // fall within the specified sub-range. The specified
  4321. // range values are inclusive.
  4322. // A negative stride reverses the direction of the
  4323. // scan producing an inverted list as a result.
  4324. if (stride > 0)
  4325. {
  4326. for (int i = 0; i < src.Length; i += stride)
  4327. {
  4328. if (i<=ei[0] && i>=si[0])
  4329. result.Add(src.Data[i]);
  4330. if (twopass && i>=si[1] && i<=ei[1])
  4331. result.Add(src.Data[i]);
  4332. }
  4333. }
  4334. else if (stride < 0)
  4335. {
  4336. for (int i = src.Length - 1; i >= 0; i += stride)
  4337. {
  4338. if (i <= ei[0] && i >= si[0])
  4339. result.Add(src.Data[i]);
  4340. if (twopass && i >= si[1] && i <= ei[1])
  4341. result.Add(src.Data[i]);
  4342. }
  4343. }
  4344. }
  4345. else
  4346. {
  4347. if (start%stride == 0)
  4348. {
  4349. result.Add(src.Data[start]);
  4350. }
  4351. }
  4352. return result;
  4353. }
  4354. public LSL_Integer llGetRegionAgentCount()
  4355. {
  4356. m_host.AddScriptLPS(1);
  4357. return new LSL_Integer(World.GetAvatars().Count);
  4358. }
  4359. public LSL_Vector llGetRegionCorner()
  4360. {
  4361. m_host.AddScriptLPS(1);
  4362. return new LSL_Vector(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
  4363. }
  4364. /// <summary>
  4365. /// Insert the list identified by <src> into the
  4366. /// list designated by <dest> such that the first
  4367. /// new element has the index specified by <index>
  4368. /// </summary>
  4369. public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
  4370. {
  4371. LSL_List pref = null;
  4372. LSL_List suff = null;
  4373. m_host.AddScriptLPS(1);
  4374. if (index < 0)
  4375. {
  4376. index = index+dest.Length;
  4377. if (index < 0)
  4378. {
  4379. index = 0;
  4380. }
  4381. }
  4382. if (index != 0)
  4383. {
  4384. pref = dest.GetSublist(0,index-1);
  4385. if (index < dest.Length)
  4386. {
  4387. suff = dest.GetSublist(index,-1);
  4388. return pref + src + suff;
  4389. }
  4390. else
  4391. {
  4392. return pref + src;
  4393. }
  4394. }
  4395. else
  4396. {
  4397. if (index < dest.Length)
  4398. {
  4399. suff = dest.GetSublist(index,-1);
  4400. return src + suff;
  4401. }
  4402. else
  4403. {
  4404. return src;
  4405. }
  4406. }
  4407. }
  4408. /// <summary>
  4409. /// Returns the index of the first occurrence of test
  4410. /// in src.
  4411. /// </summary>
  4412. public LSL_Integer llListFindList(LSL_List src, LSL_List test)
  4413. {
  4414. int index = -1;
  4415. int length = src.Length - test.Length + 1;
  4416. m_host.AddScriptLPS(1);
  4417. // If either list is empty, do not match
  4418. if (src.Length != 0 && test.Length != 0)
  4419. {
  4420. for (int i = 0; i < length; i++)
  4421. {
  4422. if (src.Data[i].Equals(test.Data[0]))
  4423. {
  4424. int j;
  4425. for (j = 1; j < test.Length; j++)
  4426. if (!src.Data[i+j].Equals(test.Data[j]))
  4427. break;
  4428. if (j == test.Length)
  4429. {
  4430. index = i;
  4431. break;
  4432. }
  4433. }
  4434. }
  4435. }
  4436. return index;
  4437. }
  4438. public LSL_String llGetObjectName()
  4439. {
  4440. m_host.AddScriptLPS(1);
  4441. return m_host.Name!=null?m_host.Name:String.Empty;
  4442. }
  4443. public void llSetObjectName(string name)
  4444. {
  4445. m_host.AddScriptLPS(1);
  4446. m_host.Name = name!=null?name:String.Empty;
  4447. }
  4448. public LSL_String llGetDate()
  4449. {
  4450. m_host.AddScriptLPS(1);
  4451. DateTime date = DateTime.Now.ToUniversalTime();
  4452. string result = date.ToString("yyyy-MM-dd");
  4453. return result;
  4454. }
  4455. public LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir)
  4456. {
  4457. m_host.AddScriptLPS(1);
  4458. // edge will be used to pass the Region Coordinates offset
  4459. // we want to check for a neighboring sim
  4460. LSL_Vector edge = new LSL_Vector(0, 0, 0);
  4461. if (dir.x == 0)
  4462. {
  4463. if (dir.y == 0)
  4464. {
  4465. // Direction vector is 0,0 so return
  4466. // false since we're staying in the sim
  4467. return 0;
  4468. }
  4469. else
  4470. {
  4471. // Y is the only valid direction
  4472. edge.y = dir.y / Math.Abs(dir.y);
  4473. }
  4474. }
  4475. else
  4476. {
  4477. LSL_Float mag;
  4478. if (dir.x > 0)
  4479. {
  4480. mag = (Constants.RegionSize - pos.x) / dir.x;
  4481. }
  4482. else
  4483. {
  4484. mag = (pos.x/dir.x);
  4485. }
  4486. mag = Math.Abs(mag);
  4487. edge.y = pos.y + (dir.y * mag);
  4488. if (edge.y > Constants.RegionSize || edge.y < 0)
  4489. {
  4490. // Y goes out of bounds first
  4491. edge.y = dir.y / Math.Abs(dir.y);
  4492. }
  4493. else
  4494. {
  4495. // X goes out of bounds first or its a corner exit
  4496. edge.y = 0;
  4497. edge.x = dir.x / Math.Abs(dir.x);
  4498. }
  4499. }
  4500. List<GridRegion> neighbors = World.GridService.GetNeighbours(World.RegionInfo.ScopeID, World.RegionInfo.RegionID);
  4501. uint neighborX = World.RegionInfo.RegionLocX + (uint)dir.x;
  4502. uint neighborY = World.RegionInfo.RegionLocY + (uint)dir.y;
  4503. foreach (GridRegion sri in neighbors)
  4504. {
  4505. if (sri.RegionLocX == neighborX && sri.RegionLocY == neighborY)
  4506. return 0;
  4507. }
  4508. return 1;
  4509. }
  4510. /// <summary>
  4511. /// Not fully implemented yet. Still to do:-
  4512. /// AGENT_BUSY
  4513. /// Remove as they are done
  4514. /// </summary>
  4515. public LSL_Integer llGetAgentInfo(string id)
  4516. {
  4517. m_host.AddScriptLPS(1);
  4518. UUID key = new UUID();
  4519. if (!UUID.TryParse(id, out key))
  4520. {
  4521. return 0;
  4522. }
  4523. int flags = 0;
  4524. ScenePresence agent = World.GetScenePresence(key);
  4525. if (agent == null)
  4526. {
  4527. return 0;
  4528. }
  4529. if (agent.IsChildAgent)
  4530. return 0; // Fail if they are not in the same region
  4531. // note: in OpenSim, sitting seems to cancel AGENT_ALWAYS_RUN, unlike SL
  4532. if (agent.SetAlwaysRun)
  4533. {
  4534. flags |= ScriptBaseClass.AGENT_ALWAYS_RUN;
  4535. }
  4536. if (agent.HasAttachments())
  4537. {
  4538. flags |= ScriptBaseClass.AGENT_ATTACHMENTS;
  4539. if (agent.HasScriptedAttachments())
  4540. flags |= ScriptBaseClass.AGENT_SCRIPTED;
  4541. }
  4542. if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0)
  4543. {
  4544. flags |= ScriptBaseClass.AGENT_FLYING;
  4545. flags |= ScriptBaseClass.AGENT_IN_AIR; // flying always implies in-air, even if colliding with e.g. a wall
  4546. }
  4547. if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AWAY) != 0)
  4548. {
  4549. flags |= ScriptBaseClass.AGENT_AWAY;
  4550. }
  4551. // seems to get unset, even if in mouselook, when avatar is sitting on a prim???
  4552. if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
  4553. {
  4554. flags |= ScriptBaseClass.AGENT_MOUSELOOK;
  4555. }
  4556. if ((agent.State & (byte)AgentState.Typing) != (byte)0)
  4557. {
  4558. flags |= ScriptBaseClass.AGENT_TYPING;
  4559. }
  4560. string agentMovementAnimation = agent.GetMovementAnimation();
  4561. if (agentMovementAnimation == "CROUCH")
  4562. {
  4563. flags |= ScriptBaseClass.AGENT_CROUCHING;
  4564. }
  4565. if (agentMovementAnimation == "WALK" || agentMovementAnimation == "CROUCHWALK")
  4566. {
  4567. flags |= ScriptBaseClass.AGENT_WALKING;
  4568. }
  4569. // not colliding implies in air. Note: flying also implies in-air, even if colliding (see above)
  4570. // note: AGENT_IN_AIR and AGENT_WALKING seem to be mutually exclusive states in SL.
  4571. // note: this may need some tweaking when walking downhill. you "fall down" for a brief instant
  4572. // and don't collide when walking downhill, which instantly registers as in-air, briefly. should
  4573. // there be some minimum non-collision threshold time before claiming the avatar is in-air?
  4574. if ((flags & ScriptBaseClass.AGENT_WALKING) == 0 &&
  4575. agent.PhysicsActor != null &&
  4576. !agent.PhysicsActor.IsColliding)
  4577. {
  4578. flags |= ScriptBaseClass.AGENT_IN_AIR;
  4579. }
  4580. if (agent.ParentID != 0)
  4581. {
  4582. flags |= ScriptBaseClass.AGENT_ON_OBJECT;
  4583. flags |= ScriptBaseClass.AGENT_SITTING;
  4584. }
  4585. if (agent.Animations.DefaultAnimation.AnimID == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
  4586. {
  4587. flags |= ScriptBaseClass.AGENT_SITTING;
  4588. }
  4589. //NotImplemented("llGetAgentInfo");
  4590. return flags;
  4591. }
  4592. public LSL_String llGetAgentLanguage(string id)
  4593. {
  4594. // This should only return a value if the avatar is in the same region
  4595. //ckrinke 1-30-09 : This needs to parse the XMLRPC language field supplied
  4596. //by the client at login. Currently returning only en-us until our I18N
  4597. //effort gains momentum
  4598. m_host.AddScriptLPS(1);
  4599. return "en-us";
  4600. }
  4601. public void llAdjustSoundVolume(double volume)
  4602. {
  4603. m_host.AddScriptLPS(1);
  4604. m_host.AdjustSoundGain(volume);
  4605. ScriptSleep(100);
  4606. }
  4607. public void llSetSoundQueueing(int queue)
  4608. {
  4609. m_host.AddScriptLPS(1);
  4610. NotImplemented("llSetSoundQueueing");
  4611. }
  4612. public void llSetSoundRadius(double radius)
  4613. {
  4614. m_host.AddScriptLPS(1);
  4615. m_host.SoundRadius = radius;
  4616. }
  4617. public LSL_String llKey2Name(string id)
  4618. {
  4619. m_host.AddScriptLPS(1);
  4620. UUID key = new UUID();
  4621. if (UUID.TryParse(id,out key))
  4622. {
  4623. ScenePresence presence = World.GetScenePresence(key);
  4624. if (presence != null)
  4625. {
  4626. return presence.ControllingClient.Name;
  4627. //return presence.Name;
  4628. }
  4629. if (World.GetSceneObjectPart(key) != null)
  4630. {
  4631. return World.GetSceneObjectPart(key).Name;
  4632. }
  4633. }
  4634. return String.Empty;
  4635. }
  4636. public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate)
  4637. {
  4638. m_host.AddScriptLPS(1);
  4639. Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation();
  4640. pTexAnim.Flags = (Primitive.TextureAnimMode)mode;
  4641. //ALL_SIDES
  4642. if (face == ScriptBaseClass.ALL_SIDES)
  4643. face = 255;
  4644. pTexAnim.Face = (uint)face;
  4645. pTexAnim.Length = (float)length;
  4646. pTexAnim.Rate = (float)rate;
  4647. pTexAnim.SizeX = (uint)sizex;
  4648. pTexAnim.SizeY = (uint)sizey;
  4649. pTexAnim.Start = (float)start;
  4650. m_host.AddTextureAnimation(pTexAnim);
  4651. m_host.SendFullUpdateToAllClients();
  4652. m_host.ParentGroup.HasGroupChanged = true;
  4653. }
  4654. public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east,
  4655. LSL_Vector bottom_south_west)
  4656. {
  4657. m_host.AddScriptLPS(1);
  4658. NotImplemented("llTriggerSoundLimited");
  4659. }
  4660. public void llEjectFromLand(string pest)
  4661. {
  4662. m_host.AddScriptLPS(1);
  4663. UUID agentId = new UUID();
  4664. if (UUID.TryParse(pest, out agentId))
  4665. {
  4666. ScenePresence presence = World.GetScenePresence(agentId);
  4667. if (presence != null)
  4668. {
  4669. // agent must be over the owners land
  4670. if (m_host.OwnerID == World.LandChannel.GetLandObject(
  4671. presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
  4672. World.TeleportClientHome(agentId, presence.ControllingClient);
  4673. }
  4674. }
  4675. ScriptSleep(5000);
  4676. }
  4677. public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
  4678. {
  4679. m_host.AddScriptLPS(1);
  4680. LSL_List ret = new LSL_List();
  4681. LSL_List spacers = new LSL_List();
  4682. if (in_spacers.Length > 0 && separators.Length > 0)
  4683. {
  4684. for (int i = 0; i < in_spacers.Length; i++)
  4685. {
  4686. object s = in_spacers.Data[i];
  4687. for (int j = 0; j < separators.Length; j++)
  4688. {
  4689. if (separators.Data[j].ToString() == s.ToString())
  4690. {
  4691. s = null;
  4692. break;
  4693. }
  4694. }
  4695. if (s != null)
  4696. {
  4697. spacers.Add(s);
  4698. }
  4699. }
  4700. }
  4701. object[] delimiters = new object[separators.Length + spacers.Length];
  4702. separators.Data.CopyTo(delimiters, 0);
  4703. spacers.Data.CopyTo(delimiters, separators.Length);
  4704. bool dfound = false;
  4705. do
  4706. {
  4707. dfound = false;
  4708. int cindex = -1;
  4709. string cdeli = "";
  4710. for (int i = 0; i < delimiters.Length; i++)
  4711. {
  4712. int index = str.IndexOf(delimiters[i].ToString());
  4713. bool found = index != -1;
  4714. if (found && String.Empty != delimiters[i].ToString())
  4715. {
  4716. if ((cindex > index) || (cindex == -1))
  4717. {
  4718. cindex = index;
  4719. cdeli = delimiters[i].ToString();
  4720. }
  4721. dfound = dfound || found;
  4722. }
  4723. }
  4724. if (cindex != -1)
  4725. {
  4726. if (cindex > 0)
  4727. {
  4728. ret.Add(new LSL_String(str.Substring(0, cindex)));
  4729. }
  4730. // Cannot use spacers.Contains() because spacers may be either type String or LSLString
  4731. for (int j = 0; j < spacers.Length; j++)
  4732. {
  4733. if (spacers.Data[j].ToString() == cdeli)
  4734. {
  4735. ret.Add(new LSL_String(cdeli));
  4736. break;
  4737. }
  4738. }
  4739. str = str.Substring(cindex + cdeli.Length);
  4740. }
  4741. } while (dfound);
  4742. if (str != "")
  4743. {
  4744. ret.Add(new LSL_String(str));
  4745. }
  4746. return ret;
  4747. }
  4748. public LSL_Integer llOverMyLand(string id)
  4749. {
  4750. m_host.AddScriptLPS(1);
  4751. UUID key = new UUID();
  4752. if (UUID.TryParse(id, out key))
  4753. {
  4754. ScenePresence presence = World.GetScenePresence(key);
  4755. if (presence != null) // object is an avatar
  4756. {
  4757. if (m_host.OwnerID
  4758. == World.LandChannel.GetLandObject(
  4759. presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
  4760. return 1;
  4761. }
  4762. else // object is not an avatar
  4763. {
  4764. SceneObjectPart obj = World.GetSceneObjectPart(key);
  4765. if (obj != null)
  4766. if (m_host.OwnerID
  4767. == World.LandChannel.GetLandObject(
  4768. obj.AbsolutePosition.X, obj.AbsolutePosition.Y).LandData.OwnerID)
  4769. return 1;
  4770. }
  4771. }
  4772. return 0;
  4773. }
  4774. public LSL_String llGetLandOwnerAt(LSL_Vector pos)
  4775. {
  4776. m_host.AddScriptLPS(1);
  4777. return World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).LandData.OwnerID.ToString();
  4778. }
  4779. /// <summary>
  4780. /// According to http://lslwiki.net/lslwiki/wakka.php?wakka=llGetAgentSize
  4781. /// only the height of avatars vary and that says:
  4782. /// Width (x) and depth (y) are constant. (0.45m and 0.6m respectively).
  4783. /// </summary>
  4784. public LSL_Vector llGetAgentSize(string id)
  4785. {
  4786. m_host.AddScriptLPS(1);
  4787. ScenePresence avatar = World.GetScenePresence((UUID)id);
  4788. LSL_Vector agentSize;
  4789. if (avatar == null || avatar.IsChildAgent) // Fail if not in the same region
  4790. {
  4791. agentSize = ScriptBaseClass.ZERO_VECTOR;
  4792. }
  4793. else
  4794. {
  4795. agentSize = new LSL_Vector(0.45, 0.6, avatar.Appearance.AvatarHeight);
  4796. }
  4797. return agentSize;
  4798. }
  4799. public LSL_Integer llSameGroup(string agent)
  4800. {
  4801. m_host.AddScriptLPS(1);
  4802. UUID agentId = new UUID();
  4803. if (!UUID.TryParse(agent, out agentId))
  4804. return new LSL_Integer(0);
  4805. ScenePresence presence = World.GetScenePresence(agentId);
  4806. if (presence == null || presence.IsChildAgent) // Return flase for child agents
  4807. return new LSL_Integer(0);
  4808. IClientAPI client = presence.ControllingClient;
  4809. if (m_host.GroupID == client.ActiveGroupId)
  4810. return new LSL_Integer(1);
  4811. else
  4812. return new LSL_Integer(0);
  4813. }
  4814. public void llUnSit(string id)
  4815. {
  4816. m_host.AddScriptLPS(1);
  4817. UUID key = new UUID();
  4818. if (UUID.TryParse(id, out key))
  4819. {
  4820. ScenePresence av = World.GetScenePresence(key);
  4821. if (av != null)
  4822. {
  4823. if (llAvatarOnSitTarget() == id)
  4824. {
  4825. // if the avatar is sitting on this object, then
  4826. // we can unsit them. We don't want random scripts unsitting random people
  4827. // Lets avoid the popcorn avatar scenario.
  4828. av.StandUp();
  4829. }
  4830. else
  4831. {
  4832. // If the object owner also owns the parcel
  4833. // or
  4834. // if the land is group owned and the object is group owned by the same group
  4835. // or
  4836. // if the object is owned by a person with estate access.
  4837. ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y);
  4838. if (parcel != null)
  4839. {
  4840. if (m_host.OwnerID == parcel.LandData.OwnerID ||
  4841. (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.LandData.GroupID
  4842. && parcel.LandData.IsGroupOwned) || World.Permissions.IsGod(m_host.OwnerID))
  4843. {
  4844. av.StandUp();
  4845. }
  4846. }
  4847. }
  4848. }
  4849. }
  4850. }
  4851. public LSL_Vector llGroundSlope(LSL_Vector offset)
  4852. {
  4853. m_host.AddScriptLPS(1);
  4854. //Get the slope normal. This gives us the equation of the plane tangent to the slope.
  4855. LSL_Vector vsn = llGroundNormal(offset);
  4856. //Plug the x,y coordinates of the slope normal into the equation of the plane to get
  4857. //the height of that point on the plane. The resulting vector gives the slope.
  4858. Vector3 vsl = new Vector3();
  4859. vsl.X = (float)vsn.x;
  4860. vsl.Y = (float)vsn.y;
  4861. vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z));
  4862. vsl.Normalize();
  4863. //Normalization might be overkill here
  4864. return new LSL_Vector(vsl.X, vsl.Y, vsl.Z);
  4865. }
  4866. public LSL_Vector llGroundNormal(LSL_Vector offset)
  4867. {
  4868. m_host.AddScriptLPS(1);
  4869. Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x,
  4870. (float)offset.y,
  4871. (float)offset.z);
  4872. // Clamp to valid position
  4873. if (pos.X < 0)
  4874. pos.X = 0;
  4875. else if (pos.X >= World.Heightmap.Width)
  4876. pos.X = World.Heightmap.Width - 1;
  4877. if (pos.Y < 0)
  4878. pos.Y = 0;
  4879. else if (pos.Y >= World.Heightmap.Height)
  4880. pos.Y = World.Heightmap.Height - 1;
  4881. //Find two points in addition to the position to define a plane
  4882. Vector3 p0 = new Vector3(pos.X, pos.Y,
  4883. (float)World.Heightmap[(int)pos.X, (int)pos.Y]);
  4884. Vector3 p1 = new Vector3();
  4885. Vector3 p2 = new Vector3();
  4886. if ((pos.X + 1.0f) >= World.Heightmap.Width)
  4887. p1 = new Vector3(pos.X + 1.0f, pos.Y,
  4888. (float)World.Heightmap[(int)pos.X, (int)pos.Y]);
  4889. else
  4890. p1 = new Vector3(pos.X + 1.0f, pos.Y,
  4891. (float)World.Heightmap[(int)(pos.X + 1.0f), (int)pos.Y]);
  4892. if ((pos.Y + 1.0f) >= World.Heightmap.Height)
  4893. p2 = new Vector3(pos.X, pos.Y + 1.0f,
  4894. (float)World.Heightmap[(int)pos.X, (int)pos.Y]);
  4895. else
  4896. p2 = new Vector3(pos.X, pos.Y + 1.0f,
  4897. (float)World.Heightmap[(int)pos.X, (int)(pos.Y + 1.0f)]);
  4898. //Find normalized vectors from p0 to p1 and p0 to p2
  4899. Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
  4900. Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z);
  4901. v0.Normalize();
  4902. v1.Normalize();
  4903. //Find the cross product of the vectors (the slope normal).
  4904. Vector3 vsn = new Vector3();
  4905. vsn.X = (v0.Y * v1.Z) - (v0.Z * v1.Y);
  4906. vsn.Y = (v0.Z * v1.X) - (v0.X * v1.Z);
  4907. vsn.Z = (v0.X * v1.Y) - (v0.Y * v1.X);
  4908. vsn.Normalize();
  4909. //I believe the crossproduct of two normalized vectors is a normalized vector so
  4910. //this normalization may be overkill
  4911. return new LSL_Vector(vsn.X, vsn.Y, vsn.Z);
  4912. }
  4913. public LSL_Vector llGroundContour(LSL_Vector offset)
  4914. {
  4915. m_host.AddScriptLPS(1);
  4916. LSL_Vector x = llGroundSlope(offset);
  4917. return new LSL_Vector(-x.y, x.x, 0.0);
  4918. }
  4919. public LSL_Integer llGetAttached()
  4920. {
  4921. m_host.AddScriptLPS(1);
  4922. return m_host.ParentGroup.RootPart.AttachmentPoint;
  4923. }
  4924. public LSL_Integer llGetFreeMemory()
  4925. {
  4926. m_host.AddScriptLPS(1);
  4927. // Make scripts designed for LSO happy
  4928. return 16384;
  4929. }
  4930. public LSL_Integer llGetFreeURLs()
  4931. {
  4932. m_host.AddScriptLPS(1);
  4933. if (m_UrlModule != null)
  4934. return new LSL_Integer(m_UrlModule.GetFreeUrls());
  4935. return new LSL_Integer(0);
  4936. }
  4937. public LSL_String llGetRegionName()
  4938. {
  4939. m_host.AddScriptLPS(1);
  4940. return World.RegionInfo.RegionName;
  4941. }
  4942. public LSL_Float llGetRegionTimeDilation()
  4943. {
  4944. m_host.AddScriptLPS(1);
  4945. return (double)World.TimeDilation;
  4946. }
  4947. /// <summary>
  4948. /// Returns the value reported in the client Statistics window
  4949. /// </summary>
  4950. public LSL_Float llGetRegionFPS()
  4951. {
  4952. m_host.AddScriptLPS(1);
  4953. return World.SimulatorFPS;
  4954. }
  4955. /* particle system rules should be coming into this routine as doubles, that is
  4956. rule[0] should be an integer from this list and rule[1] should be the arg
  4957. for the same integer. wiki.secondlife.com has most of this mapping, but some
  4958. came from http://www.caligari-designs.com/p4u2
  4959. We iterate through the list for 'Count' elements, incrementing by two for each
  4960. iteration and set the members of Primitive.ParticleSystem, one at a time.
  4961. */
  4962. public enum PrimitiveRule : int
  4963. {
  4964. PSYS_PART_FLAGS = 0,
  4965. PSYS_PART_START_COLOR = 1,
  4966. PSYS_PART_START_ALPHA = 2,
  4967. PSYS_PART_END_COLOR = 3,
  4968. PSYS_PART_END_ALPHA = 4,
  4969. PSYS_PART_START_SCALE = 5,
  4970. PSYS_PART_END_SCALE = 6,
  4971. PSYS_PART_MAX_AGE = 7,
  4972. PSYS_SRC_ACCEL = 8,
  4973. PSYS_SRC_PATTERN = 9,
  4974. PSYS_SRC_TEXTURE = 12,
  4975. PSYS_SRC_BURST_RATE = 13,
  4976. PSYS_SRC_BURST_PART_COUNT = 15,
  4977. PSYS_SRC_BURST_RADIUS = 16,
  4978. PSYS_SRC_BURST_SPEED_MIN = 17,
  4979. PSYS_SRC_BURST_SPEED_MAX = 18,
  4980. PSYS_SRC_MAX_AGE = 19,
  4981. PSYS_SRC_TARGET_KEY = 20,
  4982. PSYS_SRC_OMEGA = 21,
  4983. PSYS_SRC_ANGLE_BEGIN = 22,
  4984. PSYS_SRC_ANGLE_END = 23
  4985. }
  4986. internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
  4987. {
  4988. Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None;
  4989. return returnval;
  4990. }
  4991. protected Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues()
  4992. {
  4993. Primitive.ParticleSystem ps = new Primitive.ParticleSystem();
  4994. // TODO find out about the other defaults and add them here
  4995. ps.PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
  4996. ps.PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
  4997. ps.PartStartScaleX = 1.0f;
  4998. ps.PartStartScaleY = 1.0f;
  4999. ps.PartEndScaleX = 1.0f;
  5000. ps.PartEndScaleY = 1.0f;
  5001. ps.BurstSpeedMin = 1.0f;
  5002. ps.BurstSpeedMax = 1.0f;
  5003. ps.BurstRate = 0.1f;
  5004. ps.PartMaxAge = 10.0f;
  5005. return ps;
  5006. }
  5007. public void llParticleSystem(LSL_List rules)
  5008. {
  5009. m_host.AddScriptLPS(1);
  5010. if (rules.Length == 0)
  5011. {
  5012. m_host.RemoveParticleSystem();
  5013. m_host.ParentGroup.HasGroupChanged = true;
  5014. }
  5015. else
  5016. {
  5017. Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues();
  5018. LSL_Vector tempv = new LSL_Vector();
  5019. float tempf = 0;
  5020. for (int i = 0; i < rules.Length; i += 2)
  5021. {
  5022. switch (Convert.ToInt32(rules.Data[i]))
  5023. {
  5024. case (int)ScriptBaseClass.PSYS_PART_FLAGS:
  5025. prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1);
  5026. break;
  5027. case (int)ScriptBaseClass.PSYS_PART_START_COLOR:
  5028. tempv = rules.GetVector3Item(i + 1);
  5029. prules.PartStartColor.R = (float)tempv.x;
  5030. prules.PartStartColor.G = (float)tempv.y;
  5031. prules.PartStartColor.B = (float)tempv.z;
  5032. break;
  5033. case (int)ScriptBaseClass.PSYS_PART_START_ALPHA:
  5034. tempf = (float)rules.GetLSLFloatItem(i + 1);
  5035. prules.PartStartColor.A = tempf;
  5036. break;
  5037. case (int)ScriptBaseClass.PSYS_PART_END_COLOR:
  5038. tempv = rules.GetVector3Item(i + 1);
  5039. prules.PartEndColor.R = (float)tempv.x;
  5040. prules.PartEndColor.G = (float)tempv.y;
  5041. prules.PartEndColor.B = (float)tempv.z;
  5042. break;
  5043. case (int)ScriptBaseClass.PSYS_PART_END_ALPHA:
  5044. tempf = (float)rules.GetLSLFloatItem(i + 1);
  5045. prules.PartEndColor.A = tempf;
  5046. break;
  5047. case (int)ScriptBaseClass.PSYS_PART_START_SCALE:
  5048. tempv = rules.GetVector3Item(i + 1);
  5049. prules.PartStartScaleX = (float)tempv.x;
  5050. prules.PartStartScaleY = (float)tempv.y;
  5051. break;
  5052. case (int)ScriptBaseClass.PSYS_PART_END_SCALE:
  5053. tempv = rules.GetVector3Item(i + 1);
  5054. prules.PartEndScaleX = (float)tempv.x;
  5055. prules.PartEndScaleY = (float)tempv.y;
  5056. break;
  5057. case (int)ScriptBaseClass.PSYS_PART_MAX_AGE:
  5058. tempf = (float)rules.GetLSLFloatItem(i + 1);
  5059. prules.PartMaxAge = tempf;
  5060. break;
  5061. case (int)ScriptBaseClass.PSYS_SRC_ACCEL:
  5062. tempv = rules.GetVector3Item(i + 1);
  5063. prules.PartAcceleration.X = (float)tempv.x;
  5064. prules.PartAcceleration.Y = (float)tempv.y;
  5065. prules.PartAcceleration.Z = (float)tempv.z;
  5066. break;
  5067. case (int)ScriptBaseClass.PSYS_SRC_PATTERN:
  5068. int tmpi = (int)rules.GetLSLIntegerItem(i + 1);
  5069. prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
  5070. break;
  5071. case (int)ScriptBaseClass.PSYS_SRC_TEXTURE:
  5072. prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1));
  5073. break;
  5074. case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE:
  5075. tempf = (float)rules.GetLSLFloatItem(i + 1);
  5076. prules.BurstRate = (float)tempf;
  5077. break;
  5078. case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT:
  5079. prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1);
  5080. break;
  5081. case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS:
  5082. tempf = (float)rules.GetLSLFloatItem(i + 1);
  5083. prules.BurstRadius = (float)tempf;
  5084. break;
  5085. case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN:
  5086. tempf = (float)rules.GetLSLFloatItem(i + 1);
  5087. prules.BurstSpeedMin = (float)tempf;
  5088. break;
  5089. case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX:
  5090. tempf = (float)rules.GetLSLFloatItem(i + 1);
  5091. prules.BurstSpeedMax = (float)tempf;
  5092. break;
  5093. case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE:
  5094. tempf = (float)rules.GetLSLFloatItem(i + 1);
  5095. prules.MaxAge = (float)tempf;
  5096. break;
  5097. case (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY:
  5098. UUID key = UUID.Zero;
  5099. if (UUID.TryParse(rules.Data[i + 1].ToString(), out key))
  5100. {
  5101. prules.Target = key;
  5102. }
  5103. else
  5104. {
  5105. prules.Target = m_host.UUID;
  5106. }
  5107. break;
  5108. case (int)ScriptBaseClass.PSYS_SRC_OMEGA:
  5109. // AL: This is an assumption, since it is the only thing that would match.
  5110. tempv = rules.GetVector3Item(i + 1);
  5111. prules.AngularVelocity.X = (float)tempv.x;
  5112. prules.AngularVelocity.Y = (float)tempv.y;
  5113. prules.AngularVelocity.Z = (float)tempv.z;
  5114. break;
  5115. case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN:
  5116. tempf = (float)rules.GetLSLFloatItem(i + 1);
  5117. prules.InnerAngle = (float)tempf;
  5118. break;
  5119. case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END:
  5120. tempf = (float)rules.GetLSLFloatItem(i + 1);
  5121. prules.OuterAngle = (float)tempf;
  5122. break;
  5123. }
  5124. }
  5125. prules.CRC = 1;
  5126. m_host.AddNewParticleSystem(prules);
  5127. m_host.ParentGroup.HasGroupChanged = true;
  5128. }
  5129. m_host.SendFullUpdateToAllClients();
  5130. }
  5131. public void llGroundRepel(double height, int water, double tau)
  5132. {
  5133. m_host.AddScriptLPS(1);
  5134. NotImplemented("llGroundRepel");
  5135. }
  5136. protected UUID GetTaskInventoryItem(string name)
  5137. {
  5138. lock (m_host.TaskInventory)
  5139. {
  5140. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  5141. {
  5142. if (inv.Value.Name == name)
  5143. return inv.Key;
  5144. }
  5145. }
  5146. return UUID.Zero;
  5147. }
  5148. public void llGiveInventoryList(string destination, string category, LSL_List inventory)
  5149. {
  5150. m_host.AddScriptLPS(1);
  5151. UUID destID;
  5152. if (!UUID.TryParse(destination, out destID))
  5153. return;
  5154. List<UUID> itemList = new List<UUID>();
  5155. foreach (Object item in inventory.Data)
  5156. {
  5157. UUID itemID;
  5158. if (UUID.TryParse(item.ToString(), out itemID))
  5159. {
  5160. itemList.Add(itemID);
  5161. }
  5162. else
  5163. {
  5164. itemID = GetTaskInventoryItem(item.ToString());
  5165. if (itemID != UUID.Zero)
  5166. itemList.Add(itemID);
  5167. }
  5168. }
  5169. if (itemList.Count == 0)
  5170. return;
  5171. UUID folderID = m_ScriptEngine.World.MoveTaskInventoryItems(destID, category, m_host, itemList);
  5172. if (folderID == UUID.Zero)
  5173. return;
  5174. byte[] bucket = new byte[17];
  5175. bucket[0] = (byte)AssetType.Folder;
  5176. byte[] objBytes = folderID.GetBytes();
  5177. Array.Copy(objBytes, 0, bucket, 1, 16);
  5178. GridInstantMessage msg = new GridInstantMessage(World,
  5179. m_host.UUID, m_host.Name+", an object owned by "+
  5180. resolveName(m_host.OwnerID)+",", destID,
  5181. (byte)InstantMessageDialog.InventoryOffered,
  5182. false, category+"\n"+m_host.Name+" is located at "+
  5183. World.RegionInfo.RegionName+" "+
  5184. m_host.AbsolutePosition.ToString(),
  5185. folderID, true, m_host.AbsolutePosition,
  5186. bucket);
  5187. if (m_TransferModule != null)
  5188. m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
  5189. }
  5190. public void llSetVehicleType(int type)
  5191. {
  5192. m_host.AddScriptLPS(1);
  5193. if (m_host.ParentGroup != null)
  5194. {
  5195. if (!m_host.ParentGroup.IsDeleted)
  5196. {
  5197. m_host.ParentGroup.RootPart.SetVehicleType(type);
  5198. }
  5199. }
  5200. }
  5201. //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
  5202. //CFK 9/28: so these are not complete yet.
  5203. public void llSetVehicleFloatParam(int param, LSL_Float value)
  5204. {
  5205. m_host.AddScriptLPS(1);
  5206. if (m_host.ParentGroup != null)
  5207. {
  5208. if (!m_host.ParentGroup.IsDeleted)
  5209. {
  5210. m_host.ParentGroup.RootPart.SetVehicleFloatParam(param, (float)value);
  5211. }
  5212. }
  5213. }
  5214. //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
  5215. //CFK 9/28: so these are not complete yet.
  5216. public void llSetVehicleVectorParam(int param, LSL_Vector vec)
  5217. {
  5218. m_host.AddScriptLPS(1);
  5219. if (m_host.ParentGroup != null)
  5220. {
  5221. if (!m_host.ParentGroup.IsDeleted)
  5222. {
  5223. m_host.ParentGroup.RootPart.SetVehicleVectorParam(param,
  5224. new PhysicsVector((float)vec.x, (float)vec.y, (float)vec.z));
  5225. }
  5226. }
  5227. }
  5228. //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
  5229. //CFK 9/28: so these are not complete yet.
  5230. public void llSetVehicleRotationParam(int param, LSL_Rotation rot)
  5231. {
  5232. m_host.AddScriptLPS(1);
  5233. if (m_host.ParentGroup != null)
  5234. {
  5235. if (!m_host.ParentGroup.IsDeleted)
  5236. {
  5237. m_host.ParentGroup.RootPart.SetVehicleRotationParam(param,
  5238. Rot2Quaternion(rot));
  5239. }
  5240. }
  5241. }
  5242. public void llSetVehicleFlags(int flags)
  5243. {
  5244. m_host.AddScriptLPS(1);
  5245. NotImplemented("llSetVehicleFlags");
  5246. }
  5247. public void llRemoveVehicleFlags(int flags)
  5248. {
  5249. m_host.AddScriptLPS(1);
  5250. NotImplemented("llRemoveVehicleFlags");
  5251. }
  5252. public void llSitTarget(LSL_Vector offset, LSL_Rotation rot)
  5253. {
  5254. m_host.AddScriptLPS(1);
  5255. // LSL quaternions can normalize to 0, normal Quaternions can't.
  5256. if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
  5257. rot.z = 1; // ZERO_ROTATION = 0,0,0,1
  5258. m_host.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z);
  5259. m_host.SitTargetOrientation = Rot2Quaternion(rot);
  5260. m_host.ParentGroup.HasGroupChanged = true;
  5261. }
  5262. public LSL_String llAvatarOnSitTarget()
  5263. {
  5264. m_host.AddScriptLPS(1);
  5265. return m_host.GetAvatarOnSitTarget().ToString();
  5266. }
  5267. public void llAddToLandPassList(string avatar, double hours)
  5268. {
  5269. m_host.AddScriptLPS(1);
  5270. UUID key;
  5271. LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  5272. if (land.OwnerID == m_host.OwnerID)
  5273. {
  5274. ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
  5275. if (UUID.TryParse(avatar, out key))
  5276. {
  5277. entry.AgentID = key;
  5278. entry.Flags = AccessList.Access;
  5279. entry.Time = DateTime.Now.AddHours(hours);
  5280. land.ParcelAccessList.Add(entry);
  5281. }
  5282. }
  5283. ScriptSleep(100);
  5284. }
  5285. public void llSetTouchText(string text)
  5286. {
  5287. m_host.AddScriptLPS(1);
  5288. m_host.TouchName = text;
  5289. }
  5290. public void llSetSitText(string text)
  5291. {
  5292. m_host.AddScriptLPS(1);
  5293. m_host.SitName = text;
  5294. }
  5295. public void llSetCameraEyeOffset(LSL_Vector offset)
  5296. {
  5297. m_host.AddScriptLPS(1);
  5298. m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z));
  5299. }
  5300. public void llSetCameraAtOffset(LSL_Vector offset)
  5301. {
  5302. m_host.AddScriptLPS(1);
  5303. m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z));
  5304. }
  5305. public LSL_String llDumpList2String(LSL_List src, string seperator)
  5306. {
  5307. m_host.AddScriptLPS(1);
  5308. if (src.Length == 0)
  5309. {
  5310. return String.Empty;
  5311. }
  5312. string ret = String.Empty;
  5313. foreach (object o in src.Data)
  5314. {
  5315. ret = ret + o.ToString() + seperator;
  5316. }
  5317. ret = ret.Substring(0, ret.Length - seperator.Length);
  5318. return ret;
  5319. }
  5320. public LSL_Integer llScriptDanger(LSL_Vector pos)
  5321. {
  5322. m_host.AddScriptLPS(1);
  5323. bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z));
  5324. if (result)
  5325. {
  5326. return 1;
  5327. }
  5328. else
  5329. {
  5330. return 0;
  5331. }
  5332. }
  5333. public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel)
  5334. {
  5335. IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
  5336. if (dm == null)
  5337. return;
  5338. m_host.AddScriptLPS(1);
  5339. UUID av = new UUID();
  5340. if (!UUID.TryParse(avatar,out av))
  5341. {
  5342. LSLError("First parameter to llDialog needs to be a key");
  5343. return;
  5344. }
  5345. if (buttons.Length > 12)
  5346. {
  5347. LSLError("No more than 12 buttons can be shown");
  5348. return;
  5349. }
  5350. string[] buts = new string[buttons.Length];
  5351. for (int i = 0; i < buttons.Length; i++)
  5352. {
  5353. if (buttons.Data[i].ToString() == String.Empty)
  5354. {
  5355. LSLError("button label cannot be blank");
  5356. return;
  5357. }
  5358. if (buttons.Data[i].ToString().Length > 24)
  5359. {
  5360. LSLError("button label cannot be longer than 24 characters");
  5361. return;
  5362. }
  5363. buts[i] = buttons.Data[i].ToString();
  5364. }
  5365. dm.SendDialogToUser(
  5366. av, m_host.Name, m_host.UUID, m_host.OwnerID,
  5367. message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
  5368. ScriptSleep(1000);
  5369. }
  5370. public void llVolumeDetect(int detect)
  5371. {
  5372. m_host.AddScriptLPS(1);
  5373. if (m_host.ParentGroup != null)
  5374. {
  5375. if (!m_host.ParentGroup.IsDeleted)
  5376. {
  5377. m_host.ParentGroup.RootPart.ScriptSetVolumeDetect(detect!=0);
  5378. }
  5379. }
  5380. }
  5381. /// <summary>
  5382. /// This is a depecated function so this just replicates the result of
  5383. /// invoking it in SL
  5384. /// </summary>
  5385. public void llRemoteLoadScript(string target, string name, int running, int start_param)
  5386. {
  5387. m_host.AddScriptLPS(1);
  5388. // Report an error as it does in SL
  5389. ShoutError("Deprecated. Please use llRemoteLoadScriptPin instead.");
  5390. ScriptSleep(3000);
  5391. }
  5392. public void llSetRemoteScriptAccessPin(int pin)
  5393. {
  5394. m_host.AddScriptLPS(1);
  5395. m_host.ScriptAccessPin = pin;
  5396. }
  5397. public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
  5398. {
  5399. m_host.AddScriptLPS(1);
  5400. bool found = false;
  5401. UUID destId = UUID.Zero;
  5402. UUID srcId = UUID.Zero;
  5403. if (!UUID.TryParse(target, out destId))
  5404. {
  5405. llSay(0, "Could not parse key " + target);
  5406. return;
  5407. }
  5408. // target must be a different prim than the one containing the script
  5409. if (m_host.UUID == destId)
  5410. {
  5411. return;
  5412. }
  5413. // copy the first script found with this inventory name
  5414. lock (m_host.TaskInventory)
  5415. {
  5416. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  5417. {
  5418. if (inv.Value.Name == name)
  5419. {
  5420. // make sure the object is a script
  5421. if (10 == inv.Value.Type)
  5422. {
  5423. found = true;
  5424. srcId = inv.Key;
  5425. break;
  5426. }
  5427. }
  5428. }
  5429. }
  5430. if (!found)
  5431. {
  5432. llSay(0, "Could not find script " + name);
  5433. return;
  5434. }
  5435. // the rest of the permission checks are done in RezScript, so check the pin there as well
  5436. World.RezScript(srcId, m_host, destId, pin, running, start_param);
  5437. // this will cause the delay even if the script pin or permissions were wrong - seems ok
  5438. ScriptSleep(3000);
  5439. }
  5440. public void llOpenRemoteDataChannel()
  5441. {
  5442. m_host.AddScriptLPS(1);
  5443. IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
  5444. if (xmlrpcMod.IsEnabled())
  5445. {
  5446. UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, UUID.Zero);
  5447. IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
  5448. if (xmlRpcRouter != null)
  5449. {
  5450. string ExternalHostName = m_ScriptEngine.World.RegionInfo.ExternalHostName;
  5451. xmlRpcRouter.RegisterNewReceiver(m_ScriptEngine.ScriptModule, channelID, m_host.UUID,
  5452. m_itemID, String.Format("http://{0}:{1}/", ExternalHostName,
  5453. xmlrpcMod.Port.ToString()));
  5454. }
  5455. object[] resobj = new object[]
  5456. {
  5457. new LSL_Integer(1),
  5458. new LSL_String(channelID.ToString()),
  5459. new LSL_String(UUID.Zero.ToString()),
  5460. new LSL_String(String.Empty),
  5461. new LSL_Integer(0),
  5462. new LSL_String(String.Empty)
  5463. };
  5464. m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams("remote_data", resobj,
  5465. new DetectParams[0]));
  5466. }
  5467. ScriptSleep(1000);
  5468. }
  5469. public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata)
  5470. {
  5471. m_host.AddScriptLPS(1);
  5472. IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
  5473. ScriptSleep(3000);
  5474. return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString();
  5475. }
  5476. public void llRemoteDataReply(string channel, string message_id, string sdata, int idata)
  5477. {
  5478. m_host.AddScriptLPS(1);
  5479. IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
  5480. xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
  5481. ScriptSleep(3000);
  5482. }
  5483. public void llCloseRemoteDataChannel(string channel)
  5484. {
  5485. m_host.AddScriptLPS(1);
  5486. IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
  5487. xmlrpcMod.CloseXMLRPCChannel((UUID)channel);
  5488. ScriptSleep(1000);
  5489. }
  5490. public LSL_String llMD5String(string src, int nonce)
  5491. {
  5492. m_host.AddScriptLPS(1);
  5493. return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()));
  5494. }
  5495. public LSL_String llSHA1String(string src)
  5496. {
  5497. m_host.AddScriptLPS(1);
  5498. return Util.SHA1Hash(src).ToLower();
  5499. }
  5500. protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist)
  5501. {
  5502. ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
  5503. if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
  5504. holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
  5505. holeshape != (int)ScriptBaseClass.PRIM_HOLE_SQUARE &&
  5506. holeshape != (int)ScriptBaseClass.PRIM_HOLE_TRIANGLE)
  5507. {
  5508. holeshape = (int)ScriptBaseClass.PRIM_HOLE_DEFAULT;
  5509. }
  5510. shapeBlock.ProfileCurve = (byte)holeshape;
  5511. if (cut.x < 0f)
  5512. {
  5513. cut.x = 0f;
  5514. }
  5515. if (cut.x > 1f)
  5516. {
  5517. cut.x = 1f;
  5518. }
  5519. if (cut.y < 0f)
  5520. {
  5521. cut.y = 0f;
  5522. }
  5523. if (cut.y > 1f)
  5524. {
  5525. cut.y = 1f;
  5526. }
  5527. if (cut.y - cut.x < 0.05f)
  5528. {
  5529. cut.x = cut.y - 0.05f;
  5530. }
  5531. shapeBlock.ProfileBegin = (ushort)(50000 * cut.x);
  5532. shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y));
  5533. if (hollow < 0f)
  5534. {
  5535. hollow = 0f;
  5536. }
  5537. if (hollow > 0.95)
  5538. {
  5539. hollow = 0.95f;
  5540. }
  5541. shapeBlock.ProfileHollow = (ushort)(50000 * hollow);
  5542. if (twist.x < -1.0f)
  5543. {
  5544. twist.x = -1.0f;
  5545. }
  5546. if (twist.x > 1.0f)
  5547. {
  5548. twist.x = 1.0f;
  5549. }
  5550. if (twist.y < -1.0f)
  5551. {
  5552. twist.y = -1.0f;
  5553. }
  5554. if (twist.y > 1.0f)
  5555. {
  5556. twist.y = 1.0f;
  5557. }
  5558. shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x);
  5559. shapeBlock.PathTwist = (sbyte)(100 * twist.y);
  5560. shapeBlock.ObjectLocalID = part.LocalId;
  5561. // retain pathcurve
  5562. shapeBlock.PathCurve = part.Shape.PathCurve;
  5563. return shapeBlock;
  5564. }
  5565. protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge)
  5566. {
  5567. ObjectShapePacket.ObjectDataBlock shapeBlock;
  5568. shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
  5569. shapeBlock.ProfileCurve += fudge;
  5570. if (taper_b.x < 0f)
  5571. {
  5572. taper_b.x = 0f;
  5573. }
  5574. if (taper_b.x > 2f)
  5575. {
  5576. taper_b.x = 2f;
  5577. }
  5578. if (taper_b.y < 0f)
  5579. {
  5580. taper_b.y = 0f;
  5581. }
  5582. if (taper_b.y > 2f)
  5583. {
  5584. taper_b.y = 2f;
  5585. }
  5586. shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x));
  5587. shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y));
  5588. if (topshear.x < -0.5f)
  5589. {
  5590. topshear.x = -0.5f;
  5591. }
  5592. if (topshear.x > 0.5f)
  5593. {
  5594. topshear.x = 0.5f;
  5595. }
  5596. if (topshear.y < -0.5f)
  5597. {
  5598. topshear.y = -0.5f;
  5599. }
  5600. if (topshear.y > 0.5f)
  5601. {
  5602. topshear.y = 0.5f;
  5603. }
  5604. shapeBlock.PathShearX = (byte)(100 * topshear.x);
  5605. shapeBlock.PathShearY = (byte)(100 * topshear.y);
  5606. part.UpdateShape(shapeBlock);
  5607. }
  5608. protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge)
  5609. {
  5610. ObjectShapePacket.ObjectDataBlock shapeBlock;
  5611. shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
  5612. // profile/path swapped for a sphere
  5613. shapeBlock.PathBegin = shapeBlock.ProfileBegin;
  5614. shapeBlock.PathEnd = shapeBlock.ProfileEnd;
  5615. shapeBlock.ProfileCurve += fudge;
  5616. shapeBlock.PathScaleX = 100;
  5617. shapeBlock.PathScaleY = 100;
  5618. if (dimple.x < 0f)
  5619. {
  5620. dimple.x = 0f;
  5621. }
  5622. if (dimple.x > 1f)
  5623. {
  5624. dimple.x = 1f;
  5625. }
  5626. if (dimple.y < 0f)
  5627. {
  5628. dimple.y = 0f;
  5629. }
  5630. if (dimple.y > 1f)
  5631. {
  5632. dimple.y = 1f;
  5633. }
  5634. if (dimple.y - cut.x < 0.05f)
  5635. {
  5636. dimple.x = cut.y - 0.05f;
  5637. }
  5638. shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x);
  5639. shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y));
  5640. part.UpdateShape(shapeBlock);
  5641. }
  5642. protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte fudge)
  5643. {
  5644. ObjectShapePacket.ObjectDataBlock shapeBlock;
  5645. shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
  5646. shapeBlock.ProfileCurve += fudge;
  5647. // profile/path swapped for a torrus, tube, ring
  5648. shapeBlock.PathBegin = shapeBlock.ProfileBegin;
  5649. shapeBlock.PathEnd = shapeBlock.ProfileEnd;
  5650. if (holesize.x < 0.05f)
  5651. {
  5652. holesize.x = 0.05f;
  5653. }
  5654. if (holesize.x > 1f)
  5655. {
  5656. holesize.x = 1f;
  5657. }
  5658. if (holesize.y < 0.05f)
  5659. {
  5660. holesize.y = 0.05f;
  5661. }
  5662. if (holesize.y > 0.5f)
  5663. {
  5664. holesize.y = 0.5f;
  5665. }
  5666. shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x));
  5667. shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y));
  5668. if (topshear.x < -0.5f)
  5669. {
  5670. topshear.x = -0.5f;
  5671. }
  5672. if (topshear.x > 0.5f)
  5673. {
  5674. topshear.x = 0.5f;
  5675. }
  5676. if (topshear.y < -0.5f)
  5677. {
  5678. topshear.y = -0.5f;
  5679. }
  5680. if (topshear.y > 0.5f)
  5681. {
  5682. topshear.y = 0.5f;
  5683. }
  5684. shapeBlock.PathShearX = (byte)(100 * topshear.x);
  5685. shapeBlock.PathShearY = (byte)(100 * topshear.y);
  5686. if (profilecut.x < 0f)
  5687. {
  5688. profilecut.x = 0f;
  5689. }
  5690. if (profilecut.x > 1f)
  5691. {
  5692. profilecut.x = 1f;
  5693. }
  5694. if (profilecut.y < 0f)
  5695. {
  5696. profilecut.y = 0f;
  5697. }
  5698. if (profilecut.y > 1f)
  5699. {
  5700. profilecut.y = 1f;
  5701. }
  5702. if (profilecut.y - cut.x < 0.05f)
  5703. {
  5704. profilecut.x = cut.y - 0.05f;
  5705. }
  5706. shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x);
  5707. shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y));
  5708. if (taper_a.x < -1f)
  5709. {
  5710. taper_a.x = -1f;
  5711. }
  5712. if (taper_a.x > 1f)
  5713. {
  5714. taper_a.x = 1f;
  5715. }
  5716. if (taper_a.y < -1f)
  5717. {
  5718. taper_a.y = -1f;
  5719. }
  5720. if (taper_a.y > 1f)
  5721. {
  5722. taper_a.y = 1f;
  5723. }
  5724. shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x);
  5725. shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y);
  5726. if (revolutions < 1f)
  5727. {
  5728. revolutions = 1f;
  5729. }
  5730. if (revolutions > 4f)
  5731. {
  5732. revolutions = 4f;
  5733. }
  5734. shapeBlock.PathRevolutions = (byte)(66.666667 * (revolutions - 1.0));
  5735. // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
  5736. if (radiusoffset < 0f)
  5737. {
  5738. radiusoffset = 0f;
  5739. }
  5740. if (radiusoffset > 1f)
  5741. {
  5742. radiusoffset = 1f;
  5743. }
  5744. shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset);
  5745. if (skew < -0.95f)
  5746. {
  5747. skew = -0.95f;
  5748. }
  5749. if (skew > 0.95f)
  5750. {
  5751. skew = 0.95f;
  5752. }
  5753. shapeBlock.PathSkew = (sbyte)(100 * skew);
  5754. part.UpdateShape(shapeBlock);
  5755. }
  5756. protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type)
  5757. {
  5758. ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
  5759. UUID sculptId;
  5760. if (!UUID.TryParse(map, out sculptId))
  5761. {
  5762. sculptId = InventoryKey(map, (int)AssetType.Texture);
  5763. }
  5764. if (sculptId == UUID.Zero)
  5765. return;
  5766. shapeBlock.ObjectLocalID = part.LocalId;
  5767. shapeBlock.PathScaleX = 100;
  5768. shapeBlock.PathScaleY = 150;
  5769. if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER &&
  5770. type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE &&
  5771. type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE &&
  5772. type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS)
  5773. {
  5774. // default
  5775. type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
  5776. }
  5777. // retain pathcurve
  5778. shapeBlock.PathCurve = part.Shape.PathCurve;
  5779. part.Shape.SetSculptData((byte)type, sculptId);
  5780. part.Shape.SculptEntry = true;
  5781. part.UpdateShape(shapeBlock);
  5782. }
  5783. public void llSetPrimitiveParams(LSL_List rules)
  5784. {
  5785. m_host.AddScriptLPS(1);
  5786. SetPrimParams(m_host, rules);
  5787. }
  5788. public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
  5789. {
  5790. m_host.AddScriptLPS(1);
  5791. List<SceneObjectPart> parts = GetLinkParts(linknumber);
  5792. foreach (SceneObjectPart part in parts)
  5793. SetPrimParams(part, rules);
  5794. }
  5795. protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
  5796. {
  5797. int idx = 0;
  5798. while (idx < rules.Length)
  5799. {
  5800. int code = rules.GetLSLIntegerItem(idx++);
  5801. int remain = rules.Length - idx;
  5802. int face;
  5803. LSL_Vector v;
  5804. switch (code)
  5805. {
  5806. case (int)ScriptBaseClass.PRIM_POSITION:
  5807. if (remain < 1)
  5808. return;
  5809. v=rules.GetVector3Item(idx++);
  5810. SetPos(part, v);
  5811. break;
  5812. case (int)ScriptBaseClass.PRIM_SIZE:
  5813. if (remain < 1)
  5814. return;
  5815. v=rules.GetVector3Item(idx++);
  5816. SetScale(part, v);
  5817. break;
  5818. case (int)ScriptBaseClass.PRIM_ROTATION:
  5819. if (remain < 1)
  5820. return;
  5821. LSL_Rotation q = rules.GetQuaternionItem(idx++);
  5822. // try to let this work as in SL...
  5823. if (part.ParentID == 0)
  5824. {
  5825. // special case: If we are root, rotate
  5826. // complete SOG to new rotation
  5827. SetRot(part, Rot2Quaternion(q));
  5828. }
  5829. else
  5830. {
  5831. // we are a child. The rotation values
  5832. // will be set to the one of root modified
  5833. // by rot, as in SL. Don't ask.
  5834. SceneObjectGroup group = part.ParentGroup;
  5835. if (group != null) // a bit paranoid, maybe
  5836. {
  5837. SceneObjectPart rootPart = group.RootPart;
  5838. if (rootPart != null) // again, better safe than sorry
  5839. {
  5840. SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q));
  5841. }
  5842. }
  5843. }
  5844. break;
  5845. case (int)ScriptBaseClass.PRIM_TYPE:
  5846. if (remain < 3)
  5847. return;
  5848. code = (int)rules.GetLSLIntegerItem(idx++);
  5849. remain = rules.Length - idx;
  5850. float hollow;
  5851. LSL_Vector twist;
  5852. LSL_Vector taper_b;
  5853. LSL_Vector topshear;
  5854. float revolutions;
  5855. float radiusoffset;
  5856. float skew;
  5857. LSL_Vector holesize;
  5858. LSL_Vector profilecut;
  5859. switch (code)
  5860. {
  5861. case (int)ScriptBaseClass.PRIM_TYPE_BOX:
  5862. if (remain < 6)
  5863. return;
  5864. face = (int)rules.GetLSLIntegerItem(idx++);
  5865. v = rules.GetVector3Item(idx++); // cut
  5866. hollow = (float)rules.GetLSLFloatItem(idx++);
  5867. twist = rules.GetVector3Item(idx++);
  5868. taper_b = rules.GetVector3Item(idx++);
  5869. topshear = rules.GetVector3Item(idx++);
  5870. part.Shape.PathCurve = (byte)Extrusion.Straight;
  5871. SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 1);
  5872. break;
  5873. case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
  5874. if (remain < 6)
  5875. return;
  5876. face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
  5877. v = rules.GetVector3Item(idx++); // cut
  5878. hollow = (float)rules.GetLSLFloatItem(idx++);
  5879. twist = rules.GetVector3Item(idx++);
  5880. taper_b = rules.GetVector3Item(idx++);
  5881. topshear = rules.GetVector3Item(idx++);
  5882. part.Shape.ProfileShape = ProfileShape.Circle;
  5883. part.Shape.PathCurve = (byte)Extrusion.Straight;
  5884. SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 0);
  5885. break;
  5886. case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
  5887. if (remain < 6)
  5888. return;
  5889. face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
  5890. v = rules.GetVector3Item(idx++); //cut
  5891. hollow = (float)rules.GetLSLFloatItem(idx++);
  5892. twist = rules.GetVector3Item(idx++);
  5893. taper_b = rules.GetVector3Item(idx++);
  5894. topshear = rules.GetVector3Item(idx++);
  5895. part.Shape.PathCurve = (byte)Extrusion.Straight;
  5896. SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 3);
  5897. break;
  5898. case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
  5899. if (remain < 5)
  5900. return;
  5901. face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
  5902. v = rules.GetVector3Item(idx++); // cut
  5903. hollow = (float)rules.GetLSLFloatItem(idx++);
  5904. twist = rules.GetVector3Item(idx++);
  5905. taper_b = rules.GetVector3Item(idx++); // dimple
  5906. part.Shape.PathCurve = (byte)Extrusion.Curve1;
  5907. SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, 5);
  5908. break;
  5909. case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
  5910. if (remain < 11)
  5911. return;
  5912. face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
  5913. v = rules.GetVector3Item(idx++); //cut
  5914. hollow = (float)rules.GetLSLFloatItem(idx++);
  5915. twist = rules.GetVector3Item(idx++);
  5916. holesize = rules.GetVector3Item(idx++);
  5917. topshear = rules.GetVector3Item(idx++);
  5918. profilecut = rules.GetVector3Item(idx++);
  5919. taper_b = rules.GetVector3Item(idx++); // taper_a
  5920. revolutions = (float)rules.GetLSLFloatItem(idx++);
  5921. radiusoffset = (float)rules.GetLSLFloatItem(idx++);
  5922. skew = (float)rules.GetLSLFloatItem(idx++);
  5923. part.Shape.PathCurve = (byte)Extrusion.Curve1;
  5924. SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
  5925. revolutions, radiusoffset, skew, 0);
  5926. break;
  5927. case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
  5928. if (remain < 11)
  5929. return;
  5930. face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
  5931. v = rules.GetVector3Item(idx++); //cut
  5932. hollow = (float)rules.GetLSLFloatItem(idx++);
  5933. twist = rules.GetVector3Item(idx++);
  5934. holesize = rules.GetVector3Item(idx++);
  5935. topshear = rules.GetVector3Item(idx++);
  5936. profilecut = rules.GetVector3Item(idx++);
  5937. taper_b = rules.GetVector3Item(idx++); // taper_a
  5938. revolutions = (float)rules.GetLSLFloatItem(idx++);
  5939. radiusoffset = (float)rules.GetLSLFloatItem(idx++);
  5940. skew = (float)rules.GetLSLFloatItem(idx++);
  5941. part.Shape.PathCurve = (byte)Extrusion.Curve1;
  5942. SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
  5943. revolutions, radiusoffset, skew, 1);
  5944. break;
  5945. case (int)ScriptBaseClass.PRIM_TYPE_RING:
  5946. if (remain < 11)
  5947. return;
  5948. face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
  5949. v = rules.GetVector3Item(idx++); //cut
  5950. hollow = (float)rules.GetLSLFloatItem(idx++);
  5951. twist = rules.GetVector3Item(idx++);
  5952. holesize = rules.GetVector3Item(idx++);
  5953. topshear = rules.GetVector3Item(idx++);
  5954. profilecut = rules.GetVector3Item(idx++);
  5955. taper_b = rules.GetVector3Item(idx++); // taper_a
  5956. revolutions = (float)rules.GetLSLFloatItem(idx++);
  5957. radiusoffset = (float)rules.GetLSLFloatItem(idx++);
  5958. skew = (float)rules.GetLSLFloatItem(idx++);
  5959. part.Shape.PathCurve = (byte)Extrusion.Curve1;
  5960. SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
  5961. revolutions, radiusoffset, skew, 3);
  5962. break;
  5963. case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
  5964. if (remain < 2)
  5965. return;
  5966. string map = rules.Data[idx++].ToString();
  5967. face = (int)rules.GetLSLIntegerItem(idx++); // type
  5968. part.Shape.PathCurve = (byte)Extrusion.Curve1;
  5969. SetPrimitiveShapeParams(part, map, face);
  5970. break;
  5971. }
  5972. break;
  5973. case (int)ScriptBaseClass.PRIM_TEXTURE:
  5974. if (remain < 5)
  5975. return;
  5976. face=(int)rules.GetLSLIntegerItem(idx++);
  5977. string tex=rules.Data[idx++].ToString();
  5978. LSL_Vector repeats=rules.GetVector3Item(idx++);
  5979. LSL_Vector offsets=rules.GetVector3Item(idx++);
  5980. double rotation=(double)rules.GetLSLFloatItem(idx++);
  5981. SetTexture(part, tex, face);
  5982. ScaleTexture(part, repeats.x, repeats.y, face);
  5983. OffsetTexture(part, offsets.x, offsets.y, face);
  5984. RotateTexture(part, rotation, face);
  5985. break;
  5986. case (int)ScriptBaseClass.PRIM_COLOR:
  5987. if (remain < 3)
  5988. return;
  5989. face=(int)rules.GetLSLIntegerItem(idx++);
  5990. LSL_Vector color=rules.GetVector3Item(idx++);
  5991. double alpha=(double)rules.GetLSLFloatItem(idx++);
  5992. SetColor(part, color, face);
  5993. SetAlpha(part, alpha, face);
  5994. break;
  5995. case (int)ScriptBaseClass.PRIM_FLEXIBLE:
  5996. if (remain < 7)
  5997. return;
  5998. bool flexi = rules.GetLSLIntegerItem(idx++);
  5999. int softness = rules.GetLSLIntegerItem(idx++);
  6000. float gravity = (float)rules.GetLSLFloatItem(idx++);
  6001. float friction = (float)rules.GetLSLFloatItem(idx++);
  6002. float wind = (float)rules.GetLSLFloatItem(idx++);
  6003. float tension = (float)rules.GetLSLFloatItem(idx++);
  6004. LSL_Vector force = rules.GetVector3Item(idx++);
  6005. SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force);
  6006. break;
  6007. case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
  6008. if (remain < 5)
  6009. return;
  6010. bool light = rules.GetLSLIntegerItem(idx++);
  6011. LSL_Vector lightcolor = rules.GetVector3Item(idx++);
  6012. float intensity = (float)rules.GetLSLFloatItem(idx++);
  6013. float radius = (float)rules.GetLSLFloatItem(idx++);
  6014. float falloff = (float)rules.GetLSLFloatItem(idx++);
  6015. SetPointLight(part, light, lightcolor, intensity, radius, falloff);
  6016. break;
  6017. case (int)ScriptBaseClass.PRIM_GLOW:
  6018. if (remain < 2)
  6019. return;
  6020. face = rules.GetLSLIntegerItem(idx++);
  6021. float glow = (float)rules.GetLSLFloatItem(idx++);
  6022. SetGlow(part, face, glow);
  6023. break;
  6024. case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
  6025. if (remain < 3)
  6026. return;
  6027. face = (int)rules.GetLSLIntegerItem(idx++);
  6028. int shiny = (int)rules.GetLSLIntegerItem(idx++);
  6029. Bumpiness bump = (Bumpiness)Convert.ToByte((int)rules.GetLSLIntegerItem(idx++));
  6030. SetShiny(part, face, shiny, bump);
  6031. break;
  6032. case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
  6033. if (remain < 2)
  6034. return;
  6035. face = rules.GetLSLIntegerItem(idx++);
  6036. bool st = rules.GetLSLIntegerItem(idx++);
  6037. SetFullBright(part, face , st);
  6038. break;
  6039. case (int)ScriptBaseClass.PRIM_MATERIAL:
  6040. if (remain < 1)
  6041. return;
  6042. int mat = rules.GetLSLIntegerItem(idx++);
  6043. if (mat < 0 || mat > 7)
  6044. return;
  6045. part.Material = Convert.ToByte(mat);
  6046. break;
  6047. case (int)ScriptBaseClass.PRIM_PHANTOM:
  6048. if (remain < 1)
  6049. return;
  6050. string ph = rules.Data[idx++].ToString();
  6051. bool phantom;
  6052. if (ph.Equals("1"))
  6053. phantom = true;
  6054. else
  6055. phantom = false;
  6056. part.ScriptSetPhantomStatus(phantom);
  6057. break;
  6058. case (int)ScriptBaseClass.PRIM_PHYSICS:
  6059. if (remain < 1)
  6060. return;
  6061. string phy = rules.Data[idx++].ToString();
  6062. bool physics;
  6063. if (phy.Equals("1"))
  6064. physics = true;
  6065. else
  6066. physics = false;
  6067. part.ScriptSetPhysicsStatus(physics);
  6068. break;
  6069. case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
  6070. if (remain < 1)
  6071. return;
  6072. string temp = rules.Data[idx++].ToString();
  6073. bool tempOnRez;
  6074. if (temp.Equals("1"))
  6075. tempOnRez = true;
  6076. else
  6077. tempOnRez = false;
  6078. part.ScriptSetTemporaryStatus(tempOnRez);
  6079. break;
  6080. case (int)ScriptBaseClass.PRIM_TEXGEN:
  6081. if (remain < 2)
  6082. return;
  6083. //face,type
  6084. face = rules.GetLSLIntegerItem(idx++);
  6085. int style = rules.GetLSLIntegerItem(idx++);
  6086. SetTexGen(part, face, style);
  6087. break;
  6088. }
  6089. }
  6090. }
  6091. public LSL_String llStringToBase64(string str)
  6092. {
  6093. m_host.AddScriptLPS(1);
  6094. try
  6095. {
  6096. byte[] encData_byte = new byte[str.Length];
  6097. encData_byte = Util.UTF8.GetBytes(str);
  6098. string encodedData = Convert.ToBase64String(encData_byte);
  6099. return encodedData;
  6100. }
  6101. catch (Exception e)
  6102. {
  6103. throw new Exception("Error in base64Encode" + e.Message);
  6104. }
  6105. }
  6106. public LSL_String llBase64ToString(string str)
  6107. {
  6108. m_host.AddScriptLPS(1);
  6109. try
  6110. {
  6111. return Util.Base64ToString(str);
  6112. }
  6113. catch (Exception e)
  6114. {
  6115. throw new Exception("Error in base64Decode" + e.Message);
  6116. }
  6117. }
  6118. public LSL_String llXorBase64Strings(string str1, string str2)
  6119. {
  6120. m_host.AddScriptLPS(1);
  6121. Deprecated("llXorBase64Strings");
  6122. ScriptSleep(300);
  6123. return String.Empty;
  6124. }
  6125. public void llRemoteDataSetRegion()
  6126. {
  6127. m_host.AddScriptLPS(1);
  6128. NotImplemented("llRemoteDataSetRegion");
  6129. }
  6130. public LSL_Float llLog10(double val)
  6131. {
  6132. m_host.AddScriptLPS(1);
  6133. return (double)Math.Log10(val);
  6134. }
  6135. public LSL_Float llLog(double val)
  6136. {
  6137. m_host.AddScriptLPS(1);
  6138. return (double)Math.Log(val);
  6139. }
  6140. public LSL_List llGetAnimationList(string id)
  6141. {
  6142. m_host.AddScriptLPS(1);
  6143. LSL_List l = new LSL_List();
  6144. ScenePresence av = World.GetScenePresence((UUID)id);
  6145. if (av == null || av.IsChildAgent) // only if in the region
  6146. return l;
  6147. UUID[] anims;
  6148. anims = av.GetAnimationArray();
  6149. foreach (UUID foo in anims)
  6150. l.Add(foo.ToString());
  6151. return l;
  6152. }
  6153. public void llSetParcelMusicURL(string url)
  6154. {
  6155. m_host.AddScriptLPS(1);
  6156. ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
  6157. if (land.LandData.OwnerID != m_host.OwnerID)
  6158. return;
  6159. land.SetMusicUrl(url);
  6160. ScriptSleep(2000);
  6161. }
  6162. public LSL_Vector llGetRootPosition()
  6163. {
  6164. m_host.AddScriptLPS(1);
  6165. return new LSL_Vector(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y,
  6166. m_host.ParentGroup.AbsolutePosition.Z);
  6167. }
  6168. /// <summary>
  6169. /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetRot
  6170. /// http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
  6171. /// Also tested in sl in regards to the behaviour in attachments/mouselook
  6172. /// In the root prim:-
  6173. /// Returns the object rotation if not attached
  6174. /// Returns the avatars rotation if attached
  6175. /// Returns the camera rotation if attached and the avatar is in mouselook
  6176. /// </summary>
  6177. public LSL_Rotation llGetRootRotation()
  6178. {
  6179. m_host.AddScriptLPS(1);
  6180. Quaternion q;
  6181. if (m_host.ParentGroup.RootPart.AttachmentPoint != 0)
  6182. {
  6183. ScenePresence avatar = World.GetScenePresence(m_host.AttachedAvatar);
  6184. if (avatar != null)
  6185. if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
  6186. q = avatar.CameraRotation; // Mouselook
  6187. else
  6188. q = avatar.Rotation; // Currently infrequently updated so may be inaccurate
  6189. else
  6190. q = m_host.ParentGroup.GroupRotation; // Likely never get here but just in case
  6191. }
  6192. else
  6193. q = m_host.ParentGroup.GroupRotation; // just the group rotation
  6194. return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
  6195. }
  6196. public LSL_String llGetObjectDesc()
  6197. {
  6198. return m_host.Description!=null?m_host.Description:String.Empty;
  6199. }
  6200. public void llSetObjectDesc(string desc)
  6201. {
  6202. m_host.AddScriptLPS(1);
  6203. m_host.Description = desc!=null?desc:String.Empty;
  6204. }
  6205. public LSL_String llGetCreator()
  6206. {
  6207. m_host.AddScriptLPS(1);
  6208. return m_host.CreatorID.ToString();
  6209. }
  6210. public LSL_String llGetTimestamp()
  6211. {
  6212. m_host.AddScriptLPS(1);
  6213. return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
  6214. }
  6215. public LSL_Integer llGetNumberOfPrims()
  6216. {
  6217. m_host.AddScriptLPS(1);
  6218. List<ScenePresence> presences = World.GetScenePresences();
  6219. if (presences.Count == 0)
  6220. return 0;
  6221. int avatarCount = 0;
  6222. foreach (ScenePresence presence in presences)
  6223. {
  6224. if (!presence.IsChildAgent && presence.ParentID != 0)
  6225. {
  6226. if (m_host.ParentGroup.HasChildPrim(presence.ParentID))
  6227. {
  6228. avatarCount++;
  6229. }
  6230. }
  6231. }
  6232. return m_host.ParentGroup.PrimCount + avatarCount;
  6233. }
  6234. /// <summary>
  6235. /// A partial implementation.
  6236. /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox
  6237. /// So far only valid for standing/flying/ground sitting avatars and single prim objects.
  6238. /// If the object has multiple prims and/or a sitting avatar then the bounding
  6239. /// box is for the root prim only.
  6240. /// </summary>
  6241. public LSL_List llGetBoundingBox(string obj)
  6242. {
  6243. m_host.AddScriptLPS(1);
  6244. UUID objID = UUID.Zero;
  6245. LSL_List result = new LSL_List();
  6246. if (!UUID.TryParse(obj, out objID))
  6247. {
  6248. result.Add(new LSL_Vector());
  6249. result.Add(new LSL_Vector());
  6250. return result;
  6251. }
  6252. ScenePresence presence = World.GetScenePresence(objID);
  6253. if (presence != null)
  6254. {
  6255. if (presence.ParentID == 0) // not sat on an object
  6256. {
  6257. LSL_Vector lower;
  6258. LSL_Vector upper;
  6259. if (presence.Animations.DefaultAnimation.AnimID == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
  6260. {
  6261. // This is for ground sitting avatars
  6262. float height = presence.Appearance.AvatarHeight / 2.66666667f;
  6263. lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
  6264. upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
  6265. }
  6266. else
  6267. {
  6268. // This is for standing/flying avatars
  6269. float height = presence.Appearance.AvatarHeight / 2.0f;
  6270. lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
  6271. upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
  6272. }
  6273. result.Add(lower);
  6274. result.Add(upper);
  6275. return result;
  6276. }
  6277. else
  6278. {
  6279. // sitting on an object so we need the bounding box of that
  6280. // which should include the avatar so set the UUID to the
  6281. // UUID of the object the avatar is sat on and allow it to fall through
  6282. // to processing an object
  6283. SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
  6284. objID = p.UUID;
  6285. }
  6286. }
  6287. SceneObjectPart part = World.GetSceneObjectPart(objID);
  6288. // Currently only works for single prims without a sitting avatar
  6289. if (part != null)
  6290. {
  6291. Vector3 halfSize = part.Scale / 2.0f;
  6292. LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f);
  6293. LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z);
  6294. result.Add(lower);
  6295. result.Add(upper);
  6296. return result;
  6297. }
  6298. // Not found so return empty values
  6299. result.Add(new LSL_Vector());
  6300. result.Add(new LSL_Vector());
  6301. return result;
  6302. }
  6303. public LSL_Vector llGetGeometricCenter()
  6304. {
  6305. return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z);
  6306. }
  6307. public LSL_List llGetPrimitiveParams(LSL_List rules)
  6308. {
  6309. m_host.AddScriptLPS(1);
  6310. return GetLinkPrimitiveParams(m_host, rules);
  6311. }
  6312. public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules)
  6313. {
  6314. LSL_List res = new LSL_List();
  6315. int idx=0;
  6316. while (idx < rules.Length)
  6317. {
  6318. int code=(int)rules.GetLSLIntegerItem(idx++);
  6319. int remain=rules.Length-idx;
  6320. switch (code)
  6321. {
  6322. case (int)ScriptBaseClass.PRIM_MATERIAL:
  6323. res.Add(new LSL_Integer(part.Material));
  6324. break;
  6325. case (int)ScriptBaseClass.PRIM_PHYSICS:
  6326. if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0)
  6327. res.Add(new LSL_Integer(1));
  6328. else
  6329. res.Add(new LSL_Integer(0));
  6330. break;
  6331. case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
  6332. if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0)
  6333. res.Add(new LSL_Integer(1));
  6334. else
  6335. res.Add(new LSL_Integer(0));
  6336. break;
  6337. case (int)ScriptBaseClass.PRIM_PHANTOM:
  6338. if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
  6339. res.Add(new LSL_Integer(1));
  6340. else
  6341. res.Add(new LSL_Integer(0));
  6342. break;
  6343. case (int)ScriptBaseClass.PRIM_POSITION:
  6344. res.Add(new LSL_Vector(part.AbsolutePosition.X,
  6345. part.AbsolutePosition.Y,
  6346. part.AbsolutePosition.Z));
  6347. break;
  6348. case (int)ScriptBaseClass.PRIM_SIZE:
  6349. res.Add(new LSL_Vector(part.Scale.X,
  6350. part.Scale.Y,
  6351. part.Scale.Z));
  6352. break;
  6353. case (int)ScriptBaseClass.PRIM_ROTATION:
  6354. res.Add(GetPartRot(part));
  6355. break;
  6356. case (int)ScriptBaseClass.PRIM_TYPE:
  6357. // implementing box
  6358. PrimitiveBaseShape Shape = part.Shape;
  6359. int primType = getScriptPrimType(part.Shape);
  6360. res.Add(new LSL_Integer(primType));
  6361. switch (primType)
  6362. {
  6363. case ScriptBaseClass.PRIM_TYPE_BOX:
  6364. case ScriptBaseClass.PRIM_TYPE_CYLINDER:
  6365. case ScriptBaseClass.PRIM_TYPE_PRISM:
  6366. res.Add(new LSL_Integer(Shape.ProfileCurve));
  6367. res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
  6368. res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
  6369. res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
  6370. res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
  6371. res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0));
  6372. break;
  6373. case ScriptBaseClass.PRIM_TYPE_SPHERE:
  6374. res.Add(new LSL_Integer(Shape.ProfileCurve));
  6375. res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
  6376. res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
  6377. res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
  6378. res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
  6379. break;
  6380. case ScriptBaseClass.PRIM_TYPE_SCULPT:
  6381. res.Add(Shape.SculptTexture.ToString());
  6382. res.Add(new LSL_Integer(Shape.SculptType));
  6383. break;
  6384. case ScriptBaseClass.PRIM_TYPE_RING:
  6385. case ScriptBaseClass.PRIM_TYPE_TUBE:
  6386. case ScriptBaseClass.PRIM_TYPE_TORUS:
  6387. // holeshape
  6388. res.Add(new LSL_Integer(Shape.ProfileCurve));
  6389. // cut
  6390. res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
  6391. // hollow
  6392. res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
  6393. // twist
  6394. res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
  6395. // vector holesize
  6396. res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
  6397. // vector topshear
  6398. res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0));
  6399. // vector profilecut
  6400. res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
  6401. // vector tapera
  6402. res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
  6403. // float revolutions
  6404. res.Add(new LSL_Float(Shape.PathRevolutions / 50.0)); // needs fixing :(
  6405. // float radiusoffset
  6406. res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));
  6407. // float skew
  6408. res.Add(new LSL_Float(Shape.PathSkew / 100.0));
  6409. break;
  6410. }
  6411. break;
  6412. case (int)ScriptBaseClass.PRIM_TEXTURE:
  6413. if (remain < 1)
  6414. return res;
  6415. int face = (int)rules.GetLSLIntegerItem(idx++);
  6416. Primitive.TextureEntry tex = part.Shape.Textures;
  6417. if (face == ScriptBaseClass.ALL_SIDES)
  6418. {
  6419. for (face = 0 ; face < GetNumberOfSides(part) ; face++)
  6420. {
  6421. Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
  6422. res.Add(new LSL_String(texface.TextureID.ToString()));
  6423. res.Add(new LSL_Vector(texface.RepeatU,
  6424. texface.RepeatV,
  6425. 0));
  6426. res.Add(new LSL_Vector(texface.OffsetU,
  6427. texface.OffsetV,
  6428. 0));
  6429. res.Add(new LSL_Float(texface.Rotation));
  6430. }
  6431. }
  6432. else
  6433. {
  6434. if (face >= 0 && face < GetNumberOfSides(part))
  6435. {
  6436. Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
  6437. res.Add(new LSL_String(texface.TextureID.ToString()));
  6438. res.Add(new LSL_Vector(texface.RepeatU,
  6439. texface.RepeatV,
  6440. 0));
  6441. res.Add(new LSL_Vector(texface.OffsetU,
  6442. texface.OffsetV,
  6443. 0));
  6444. res.Add(new LSL_Float(texface.Rotation));
  6445. }
  6446. }
  6447. break;
  6448. case (int)ScriptBaseClass.PRIM_COLOR:
  6449. if (remain < 1)
  6450. return res;
  6451. face=(int)rules.GetLSLIntegerItem(idx++);
  6452. tex = part.Shape.Textures;
  6453. Color4 texcolor;
  6454. if (face == ScriptBaseClass.ALL_SIDES)
  6455. {
  6456. for (face = 0 ; face < GetNumberOfSides(part) ; face++)
  6457. {
  6458. texcolor = tex.GetFace((uint)face).RGBA;
  6459. res.Add(new LSL_Vector(texcolor.R,
  6460. texcolor.G,
  6461. texcolor.B));
  6462. res.Add(new LSL_Float(texcolor.A));
  6463. }
  6464. }
  6465. else
  6466. {
  6467. texcolor = tex.GetFace((uint)face).RGBA;
  6468. res.Add(new LSL_Vector(texcolor.R,
  6469. texcolor.G,
  6470. texcolor.B));
  6471. res.Add(new LSL_Float(texcolor.A));
  6472. }
  6473. break;
  6474. case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
  6475. // TODO--------------
  6476. if (remain < 1)
  6477. return res;
  6478. face=(int)rules.GetLSLIntegerItem(idx++);
  6479. res.Add(new LSL_Integer(0));
  6480. res.Add(new LSL_Integer(0));
  6481. break;
  6482. case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
  6483. // TODO--------------
  6484. if (remain < 1)
  6485. return res;
  6486. face=(int)rules.GetLSLIntegerItem(idx++);
  6487. res.Add(new LSL_Integer(0));
  6488. break;
  6489. case (int)ScriptBaseClass.PRIM_FLEXIBLE:
  6490. PrimitiveBaseShape shape = part.Shape;
  6491. if (shape.FlexiEntry)
  6492. res.Add(new LSL_Integer(1)); // active
  6493. else
  6494. res.Add(new LSL_Integer(0));
  6495. res.Add(new LSL_Integer(shape.FlexiSoftness));// softness
  6496. res.Add(new LSL_Float(shape.FlexiGravity)); // gravity
  6497. res.Add(new LSL_Float(shape.FlexiDrag)); // friction
  6498. res.Add(new LSL_Float(shape.FlexiWind)); // wind
  6499. res.Add(new LSL_Float(shape.FlexiTension)); // tension
  6500. res.Add(new LSL_Vector(shape.FlexiForceX, // force
  6501. shape.FlexiForceY,
  6502. shape.FlexiForceZ));
  6503. break;
  6504. case (int)ScriptBaseClass.PRIM_TEXGEN:
  6505. // TODO--------------
  6506. // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
  6507. if (remain < 1)
  6508. return res;
  6509. face=(int)rules.GetLSLIntegerItem(idx++);
  6510. res.Add(new LSL_Integer(0));
  6511. break;
  6512. case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
  6513. shape = part.Shape;
  6514. if (shape.LightEntry)
  6515. res.Add(new LSL_Integer(1)); // active
  6516. else
  6517. res.Add(new LSL_Integer(0));
  6518. res.Add(new LSL_Vector(shape.LightColorR, // color
  6519. shape.LightColorG,
  6520. shape.LightColorB));
  6521. res.Add(new LSL_Float(shape.LightIntensity)); // intensity
  6522. res.Add(new LSL_Float(shape.LightRadius)); // radius
  6523. res.Add(new LSL_Float(shape.LightFalloff)); // falloff
  6524. break;
  6525. case (int)ScriptBaseClass.PRIM_GLOW:
  6526. // TODO--------------
  6527. if (remain < 1)
  6528. return res;
  6529. face=(int)rules.GetLSLIntegerItem(idx++);
  6530. res.Add(new LSL_Float(0));
  6531. break;
  6532. }
  6533. }
  6534. return res;
  6535. }
  6536. // <remarks>
  6537. // <para>
  6538. // The .NET definition of base 64 is:
  6539. // <list>
  6540. // <item>
  6541. // Significant: A-Z a-z 0-9 + -
  6542. // </item>
  6543. // <item>
  6544. // Whitespace: \t \n \r ' '
  6545. // </item>
  6546. // <item>
  6547. // Valueless: =
  6548. // </item>
  6549. // <item>
  6550. // End-of-string: \0 or '=='
  6551. // </item>
  6552. // </list>
  6553. // </para>
  6554. // <para>
  6555. // Each point in a base-64 string represents
  6556. // a 6 bit value. A 32-bit integer can be
  6557. // represented using 6 characters (with some
  6558. // redundancy).
  6559. // </para>
  6560. // <para>
  6561. // LSL requires a base64 string to be 8
  6562. // characters in length. LSL also uses '/'
  6563. // rather than '-' (MIME compliant).
  6564. // </para>
  6565. // <para>
  6566. // RFC 1341 used as a reference (as specified
  6567. // by the SecondLife Wiki).
  6568. // </para>
  6569. // <para>
  6570. // SL do not record any kind of exception for
  6571. // these functions, so the string to integer
  6572. // conversion returns '0' if an invalid
  6573. // character is encountered during conversion.
  6574. // </para>
  6575. // <para>
  6576. // References
  6577. // <list>
  6578. // <item>
  6579. // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64
  6580. // </item>
  6581. // <item>
  6582. // </item>
  6583. // </list>
  6584. // </para>
  6585. // </remarks>
  6586. // <summary>
  6587. // Table for converting 6-bit integers into
  6588. // base-64 characters
  6589. // </summary>
  6590. protected static readonly char[] i2ctable =
  6591. {
  6592. 'A','B','C','D','E','F','G','H',
  6593. 'I','J','K','L','M','N','O','P',
  6594. 'Q','R','S','T','U','V','W','X',
  6595. 'Y','Z',
  6596. 'a','b','c','d','e','f','g','h',
  6597. 'i','j','k','l','m','n','o','p',
  6598. 'q','r','s','t','u','v','w','x',
  6599. 'y','z',
  6600. '0','1','2','3','4','5','6','7',
  6601. '8','9',
  6602. '+','/'
  6603. };
  6604. // <summary>
  6605. // Table for converting base-64 characters
  6606. // into 6-bit integers.
  6607. // </summary>
  6608. protected static readonly int[] c2itable =
  6609. {
  6610. -1,-1,-1,-1,-1,-1,-1,-1, // 0x
  6611. -1,-1,-1,-1,-1,-1,-1,-1,
  6612. -1,-1,-1,-1,-1,-1,-1,-1, // 1x
  6613. -1,-1,-1,-1,-1,-1,-1,-1,
  6614. -1,-1,-1,-1,-1,-1,-1,-1, // 2x
  6615. -1,-1,-1,63,-1,-1,-1,64,
  6616. 53,54,55,56,57,58,59,60, // 3x
  6617. 61,62,-1,-1,-1,0,-1,-1,
  6618. -1,1,2,3,4,5,6,7, // 4x
  6619. 8,9,10,11,12,13,14,15,
  6620. 16,17,18,19,20,21,22,23, // 5x
  6621. 24,25,26,-1,-1,-1,-1,-1,
  6622. -1,27,28,29,30,31,32,33, // 6x
  6623. 34,35,36,37,38,39,40,41,
  6624. 42,43,44,45,46,47,48,49, // 7x
  6625. 50,51,52,-1,-1,-1,-1,-1,
  6626. -1,-1,-1,-1,-1,-1,-1,-1, // 8x
  6627. -1,-1,-1,-1,-1,-1,-1,-1,
  6628. -1,-1,-1,-1,-1,-1,-1,-1, // 9x
  6629. -1,-1,-1,-1,-1,-1,-1,-1,
  6630. -1,-1,-1,-1,-1,-1,-1,-1, // Ax
  6631. -1,-1,-1,-1,-1,-1,-1,-1,
  6632. -1,-1,-1,-1,-1,-1,-1,-1, // Bx
  6633. -1,-1,-1,-1,-1,-1,-1,-1,
  6634. -1,-1,-1,-1,-1,-1,-1,-1, // Cx
  6635. -1,-1,-1,-1,-1,-1,-1,-1,
  6636. -1,-1,-1,-1,-1,-1,-1,-1, // Dx
  6637. -1,-1,-1,-1,-1,-1,-1,-1,
  6638. -1,-1,-1,-1,-1,-1,-1,-1, // Ex
  6639. -1,-1,-1,-1,-1,-1,-1,-1,
  6640. -1,-1,-1,-1,-1,-1,-1,-1, // Fx
  6641. -1,-1,-1,-1,-1,-1,-1,-1
  6642. };
  6643. // <summary>
  6644. // Converts a 32-bit integer into a Base64
  6645. // character string. Base64 character strings
  6646. // are always 8 characters long. All iinteger
  6647. // values are acceptable.
  6648. // </summary>
  6649. // <param name="number">
  6650. // 32-bit integer to be converted.
  6651. // </param>
  6652. // <returns>
  6653. // 8 character string. The 1st six characters
  6654. // contain the encoded number, the last two
  6655. // characters are padded with "=".
  6656. // </returns>
  6657. public LSL_String llIntegerToBase64(int number)
  6658. {
  6659. // uninitialized string
  6660. char[] imdt = new char[8];
  6661. m_host.AddScriptLPS(1);
  6662. // Manually unroll the loop
  6663. imdt[7] = '=';
  6664. imdt[6] = '=';
  6665. imdt[5] = i2ctable[number<<4 & 0x3F];
  6666. imdt[4] = i2ctable[number>>2 & 0x3F];
  6667. imdt[3] = i2ctable[number>>8 & 0x3F];
  6668. imdt[2] = i2ctable[number>>14 & 0x3F];
  6669. imdt[1] = i2ctable[number>>20 & 0x3F];
  6670. imdt[0] = i2ctable[number>>26 & 0x3F];
  6671. return new string(imdt);
  6672. }
  6673. // <summary>
  6674. // Converts an eight character base-64 string
  6675. // into a 32-bit integer.
  6676. // </summary>
  6677. // <param name="str">
  6678. // 8 characters string to be converted. Other
  6679. // length strings return zero.
  6680. // </param>
  6681. // <returns>
  6682. // Returns an integer representing the
  6683. // encoded value providedint he 1st 6
  6684. // characters of the string.
  6685. // </returns>
  6686. // <remarks>
  6687. // This is coded to behave like LSL's
  6688. // implementation (I think), based upon the
  6689. // information available at the Wiki.
  6690. // If more than 8 characters are supplied,
  6691. // zero is returned.
  6692. // If a NULL string is supplied, zero will
  6693. // be returned.
  6694. // If fewer than 6 characters are supplied, then
  6695. // the answer will reflect a partial
  6696. // accumulation.
  6697. // <para>
  6698. // The 6-bit segments are
  6699. // extracted left-to-right in big-endian mode,
  6700. // which means that segment 6 only contains the
  6701. // two low-order bits of the 32 bit integer as
  6702. // its high order 2 bits. A short string therefore
  6703. // means loss of low-order information. E.g.
  6704. //
  6705. // |<---------------------- 32-bit integer ----------------------->|<-Pad->|
  6706. // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->|
  6707. // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P|
  6708. // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P|
  6709. // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] |
  6710. //
  6711. // </para>
  6712. // </remarks>
  6713. public LSL_Integer llBase64ToInteger(string str)
  6714. {
  6715. int number = 0;
  6716. int digit;
  6717. m_host.AddScriptLPS(1);
  6718. // Require a well-fromed base64 string
  6719. if (str.Length > 8)
  6720. return 0;
  6721. // The loop is unrolled in the interests
  6722. // of performance and simple necessity.
  6723. //
  6724. // MUST find 6 digits to be well formed
  6725. // -1 == invalid
  6726. // 0 == padding
  6727. if ((digit = c2itable[str[0]]) <= 0)
  6728. {
  6729. return digit < 0 ? (int)0 : number;
  6730. }
  6731. number += --digit<<26;
  6732. if ((digit = c2itable[str[1]]) <= 0)
  6733. {
  6734. return digit < 0 ? (int)0 : number;
  6735. }
  6736. number += --digit<<20;
  6737. if ((digit = c2itable[str[2]]) <= 0)
  6738. {
  6739. return digit < 0 ? (int)0 : number;
  6740. }
  6741. number += --digit<<14;
  6742. if ((digit = c2itable[str[3]]) <= 0)
  6743. {
  6744. return digit < 0 ? (int)0 : number;
  6745. }
  6746. number += --digit<<8;
  6747. if ((digit = c2itable[str[4]]) <= 0)
  6748. {
  6749. return digit < 0 ? (int)0 : number;
  6750. }
  6751. number += --digit<<2;
  6752. if ((digit = c2itable[str[5]]) <= 0)
  6753. {
  6754. return digit < 0 ? (int)0 : number;
  6755. }
  6756. number += --digit>>4;
  6757. // ignore trailing padding
  6758. return number;
  6759. }
  6760. public LSL_Float llGetGMTclock()
  6761. {
  6762. m_host.AddScriptLPS(1);
  6763. return DateTime.UtcNow.TimeOfDay.TotalSeconds;
  6764. }
  6765. public LSL_String llGetHTTPHeader(LSL_Key request_id, string header)
  6766. {
  6767. m_host.AddScriptLPS(1);
  6768. if (m_UrlModule != null)
  6769. return m_UrlModule.GetHttpHeader(new UUID(request_id), header);
  6770. return String.Empty;
  6771. }
  6772. public LSL_String llGetSimulatorHostname()
  6773. {
  6774. m_host.AddScriptLPS(1);
  6775. return System.Environment.MachineName;
  6776. }
  6777. // <summary>
  6778. // Scan the string supplied in 'src' and
  6779. // tokenize it based upon two sets of
  6780. // tokenizers provided in two lists,
  6781. // separators and spacers.
  6782. // </summary>
  6783. //
  6784. // <remarks>
  6785. // Separators demarcate tokens and are
  6786. // elided as they are encountered. Spacers
  6787. // also demarcate tokens, but are themselves
  6788. // retained as tokens.
  6789. //
  6790. // Both separators and spacers may be arbitrarily
  6791. // long strings. i.e. ":::".
  6792. //
  6793. // The function returns an ordered list
  6794. // representing the tokens found in the supplied
  6795. // sources string. If two successive tokenizers
  6796. // are encountered, then a NULL entry is added
  6797. // to the list.
  6798. //
  6799. // It is a precondition that the source and
  6800. // toekizer lisst are non-null. If they are null,
  6801. // then a null pointer exception will be thrown
  6802. // while their lengths are being determined.
  6803. //
  6804. // A small amount of working memoryis required
  6805. // of approximately 8*#tokenizers.
  6806. //
  6807. // There are many ways in which this function
  6808. // can be implemented, this implementation is
  6809. // fairly naive and assumes that when the
  6810. // function is invooked with a short source
  6811. // string and/or short lists of tokenizers, then
  6812. // performance will not be an issue.
  6813. //
  6814. // In order to minimize the perofrmance
  6815. // effects of long strings, or large numbers
  6816. // of tokeizers, the function skips as far as
  6817. // possible whenever a toekenizer is found,
  6818. // and eliminates redundant tokenizers as soon
  6819. // as is possible.
  6820. //
  6821. // The implementation tries to avoid any copying
  6822. // of arrays or other objects.
  6823. // </remarks>
  6824. public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
  6825. {
  6826. int beginning = 0;
  6827. int srclen = src.Length;
  6828. int seplen = separators.Length;
  6829. object[] separray = separators.Data;
  6830. int spclen = spacers.Length;
  6831. object[] spcarray = spacers.Data;
  6832. int mlen = seplen+spclen;
  6833. int[] offset = new int[mlen+1];
  6834. bool[] active = new bool[mlen];
  6835. int best;
  6836. int j;
  6837. // Initial capacity reduces resize cost
  6838. LSL_List tokens = new LSL_List();
  6839. m_host.AddScriptLPS(1);
  6840. // All entries are initially valid
  6841. for (int i = 0; i < mlen; i++)
  6842. active[i] = true;
  6843. offset[mlen] = srclen;
  6844. while (beginning < srclen)
  6845. {
  6846. best = mlen; // as bad as it gets
  6847. // Scan for separators
  6848. for (j = 0; j < seplen; j++)
  6849. {
  6850. if (active[j])
  6851. {
  6852. // scan all of the markers
  6853. if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1)
  6854. {
  6855. // not present at all
  6856. active[j] = false;
  6857. }
  6858. else
  6859. {
  6860. // present and correct
  6861. if (offset[j] < offset[best])
  6862. {
  6863. // closest so far
  6864. best = j;
  6865. if (offset[best] == beginning)
  6866. break;
  6867. }
  6868. }
  6869. }
  6870. }
  6871. // Scan for spacers
  6872. if (offset[best] != beginning)
  6873. {
  6874. for (j = seplen; (j < mlen) && (offset[best] > beginning); j++)
  6875. {
  6876. if (active[j])
  6877. {
  6878. // scan all of the markers
  6879. if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
  6880. {
  6881. // not present at all
  6882. active[j] = false;
  6883. }
  6884. else
  6885. {
  6886. // present and correct
  6887. if (offset[j] < offset[best])
  6888. {
  6889. // closest so far
  6890. best = j;
  6891. }
  6892. }
  6893. }
  6894. }
  6895. }
  6896. // This is the normal exit from the scanning loop
  6897. if (best == mlen)
  6898. {
  6899. // no markers were found on this pass
  6900. // so we're pretty much done
  6901. tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
  6902. break;
  6903. }
  6904. // Otherwise we just add the newly delimited token
  6905. // and recalculate where the search should continue.
  6906. tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning)));
  6907. if (best < seplen)
  6908. {
  6909. beginning = offset[best] + (separray[best].ToString()).Length;
  6910. }
  6911. else
  6912. {
  6913. beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
  6914. tokens.Add(new LSL_String(spcarray[best - seplen].ToString()));
  6915. }
  6916. }
  6917. // This an awkward an not very intuitive boundary case. If the
  6918. // last substring is a tokenizer, then there is an implied trailing
  6919. // null list entry. Hopefully the single comparison will not be too
  6920. // arduous. Alternatively the 'break' could be replced with a return
  6921. // but that's shabby programming.
  6922. if (beginning == srclen)
  6923. {
  6924. if (srclen != 0)
  6925. tokens.Add(new LSL_String(""));
  6926. }
  6927. return tokens;
  6928. }
  6929. public LSL_Integer llGetObjectPermMask(int mask)
  6930. {
  6931. m_host.AddScriptLPS(1);
  6932. int permmask = 0;
  6933. if (mask == ScriptBaseClass.MASK_BASE)//0
  6934. {
  6935. permmask = (int)m_host.BaseMask;
  6936. }
  6937. else if (mask == ScriptBaseClass.MASK_OWNER)//1
  6938. {
  6939. permmask = (int)m_host.OwnerMask;
  6940. }
  6941. else if (mask == ScriptBaseClass.MASK_GROUP)//2
  6942. {
  6943. permmask = (int)m_host.GroupMask;
  6944. }
  6945. else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
  6946. {
  6947. permmask = (int)m_host.EveryoneMask;
  6948. }
  6949. else if (mask == ScriptBaseClass.MASK_NEXT)//4
  6950. {
  6951. permmask = (int)m_host.NextOwnerMask;
  6952. }
  6953. return permmask;
  6954. }
  6955. public void llSetObjectPermMask(int mask, int value)
  6956. {
  6957. m_host.AddScriptLPS(1);
  6958. if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
  6959. {
  6960. if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
  6961. {
  6962. if (mask == ScriptBaseClass.MASK_BASE)//0
  6963. {
  6964. m_host.BaseMask = (uint)value;
  6965. }
  6966. else if (mask == ScriptBaseClass.MASK_OWNER)//1
  6967. {
  6968. m_host.OwnerMask = (uint)value;
  6969. }
  6970. else if (mask == ScriptBaseClass.MASK_GROUP)//2
  6971. {
  6972. m_host.GroupMask = (uint)value;
  6973. }
  6974. else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
  6975. {
  6976. m_host.EveryoneMask = (uint)value;
  6977. }
  6978. else if (mask == ScriptBaseClass.MASK_NEXT)//4
  6979. {
  6980. m_host.NextOwnerMask = (uint)value;
  6981. }
  6982. }
  6983. }
  6984. }
  6985. public LSL_Integer llGetInventoryPermMask(string item, int mask)
  6986. {
  6987. m_host.AddScriptLPS(1);
  6988. lock (m_host.TaskInventory)
  6989. {
  6990. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  6991. {
  6992. if (inv.Value.Name == item)
  6993. {
  6994. switch (mask)
  6995. {
  6996. case 0:
  6997. return (int)inv.Value.BasePermissions;
  6998. case 1:
  6999. return (int)inv.Value.CurrentPermissions;
  7000. case 2:
  7001. return (int)inv.Value.GroupPermissions;
  7002. case 3:
  7003. return (int)inv.Value.EveryonePermissions;
  7004. case 4:
  7005. return (int)inv.Value.NextPermissions;
  7006. }
  7007. }
  7008. }
  7009. }
  7010. return -1;
  7011. }
  7012. public void llSetInventoryPermMask(string item, int mask, int value)
  7013. {
  7014. m_host.AddScriptLPS(1);
  7015. NotImplemented("llSetInventoryPermMask");
  7016. }
  7017. public LSL_String llGetInventoryCreator(string item)
  7018. {
  7019. m_host.AddScriptLPS(1);
  7020. lock (m_host.TaskInventory)
  7021. {
  7022. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  7023. {
  7024. if (inv.Value.Name == item)
  7025. {
  7026. return inv.Value.CreatorID.ToString();
  7027. }
  7028. }
  7029. }
  7030. llSay(0, "No item name '" + item + "'");
  7031. return String.Empty;
  7032. }
  7033. public void llOwnerSay(string msg)
  7034. {
  7035. m_host.AddScriptLPS(1);
  7036. World.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0,
  7037. m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
  7038. // IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  7039. // wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg);
  7040. }
  7041. public LSL_String llRequestSecureURL()
  7042. {
  7043. m_host.AddScriptLPS(1);
  7044. if (m_UrlModule != null)
  7045. return m_UrlModule.RequestSecureURL(m_ScriptEngine.ScriptModule, m_host, m_itemID).ToString();
  7046. return UUID.Zero.ToString();
  7047. }
  7048. public LSL_String llRequestSimulatorData(string simulator, int data)
  7049. {
  7050. IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_itemID, "OSSL");
  7051. try
  7052. {
  7053. m_host.AddScriptLPS(1);
  7054. string reply = String.Empty;
  7055. GridRegion info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator);
  7056. switch (data)
  7057. {
  7058. case 5: // DATA_SIM_POS
  7059. if (info == null)
  7060. {
  7061. ScriptSleep(1000);
  7062. return UUID.Zero.ToString();
  7063. }
  7064. reply = new LSL_Vector(
  7065. info.RegionLocX * Constants.RegionSize,
  7066. info.RegionLocY * Constants.RegionSize,
  7067. 0).ToString();
  7068. break;
  7069. case 6: // DATA_SIM_STATUS
  7070. if (info != null)
  7071. reply = "up"; // Duh!
  7072. else
  7073. reply = "unknown";
  7074. break;
  7075. case 7: // DATA_SIM_RATING
  7076. if (info == null)
  7077. {
  7078. ScriptSleep(1000);
  7079. return UUID.Zero.ToString();
  7080. }
  7081. int access = info.Maturity;
  7082. if (access == 0)
  7083. reply = "PG";
  7084. else if (access == 1)
  7085. reply = "MATURE";
  7086. else if (access == 2)
  7087. reply = "ADULT";
  7088. else
  7089. reply = "UNKNOWN";
  7090. break;
  7091. case 128:
  7092. if (ossl != null)
  7093. ossl.CheckThreatLevel(ThreatLevel.High, "llRequestSimulatorData");
  7094. reply = "OpenSim";
  7095. break;
  7096. default:
  7097. ScriptSleep(1000);
  7098. return UUID.Zero.ToString(); // Raise no event
  7099. }
  7100. UUID rq = UUID.Random();
  7101. UUID tid = AsyncCommands.
  7102. DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString());
  7103. AsyncCommands.
  7104. DataserverPlugin.DataserverReply(rq.ToString(), reply);
  7105. ScriptSleep(1000);
  7106. return tid.ToString();
  7107. }
  7108. catch(Exception)
  7109. {
  7110. //m_log.Error("[LSL_API]: llRequestSimulatorData" + e.ToString());
  7111. return UUID.Zero.ToString();
  7112. }
  7113. }
  7114. public LSL_String llRequestURL()
  7115. {
  7116. m_host.AddScriptLPS(1);
  7117. if (m_UrlModule != null)
  7118. return m_UrlModule.RequestURL(m_ScriptEngine.ScriptModule, m_host, m_itemID).ToString();
  7119. return UUID.Zero.ToString();
  7120. }
  7121. public void llForceMouselook(int mouselook)
  7122. {
  7123. m_host.AddScriptLPS(1);
  7124. m_host.SetForceMouselook(mouselook != 0);
  7125. }
  7126. public LSL_Float llGetObjectMass(string id)
  7127. {
  7128. m_host.AddScriptLPS(1);
  7129. UUID key = new UUID();
  7130. if (UUID.TryParse(id, out key))
  7131. {
  7132. try
  7133. {
  7134. SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
  7135. if (obj != null)
  7136. return (double)obj.GetMass();
  7137. // the object is null so the key is for an avatar
  7138. ScenePresence avatar = World.GetScenePresence(key);
  7139. if (avatar != null)
  7140. if (avatar.IsChildAgent)
  7141. // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
  7142. // child agents have a mass of 1.0
  7143. return 1;
  7144. else
  7145. return (double)avatar.PhysicsActor.Mass;
  7146. }
  7147. catch (KeyNotFoundException)
  7148. {
  7149. return 0; // The Object/Agent not in the region so just return zero
  7150. }
  7151. }
  7152. return 0;
  7153. }
  7154. /// <summary>
  7155. /// illListReplaceList removes the sub-list defined by the inclusive indices
  7156. /// start and end and inserts the src list in its place. The inclusive
  7157. /// nature of the indices means that at least one element must be deleted
  7158. /// if the indices are within the bounds of the existing list. I.e. 2,2
  7159. /// will remove the element at index 2 and replace it with the source
  7160. /// list. Both indices may be negative, with the usual interpretation. An
  7161. /// interesting case is where end is lower than start. As these indices
  7162. /// bound the list to be removed, then 0->end, and start->lim are removed
  7163. /// and the source list is added as a suffix.
  7164. /// </summary>
  7165. public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end)
  7166. {
  7167. LSL_List pref = null;
  7168. m_host.AddScriptLPS(1);
  7169. // Note that although we have normalized, both
  7170. // indices could still be negative.
  7171. if (start < 0)
  7172. {
  7173. start = start+dest.Length;
  7174. }
  7175. if (end < 0)
  7176. {
  7177. end = end+dest.Length;
  7178. }
  7179. // The comventional case, remove a sequence starting with
  7180. // start and ending with end. And then insert the source
  7181. // list.
  7182. if (start <= end)
  7183. {
  7184. // If greater than zero, then there is going to be a
  7185. // surviving prefix. Otherwise the inclusive nature
  7186. // of the indices mean that we're going to add the
  7187. // source list as a prefix.
  7188. if (start > 0)
  7189. {
  7190. pref = dest.GetSublist(0,start-1);
  7191. // Only add a suffix if there is something
  7192. // beyond the end index (it's inclusive too).
  7193. if (end + 1 < dest.Length)
  7194. {
  7195. return pref + src + dest.GetSublist(end + 1, -1);
  7196. }
  7197. else
  7198. {
  7199. return pref + src;
  7200. }
  7201. }
  7202. // If start is less than or equal to zero, then
  7203. // the new list is simply a prefix. We still need to
  7204. // figure out any necessary surgery to the destination
  7205. // based upon end. Note that if end exceeds the upper
  7206. // bound in this case, the entire destination list
  7207. // is removed.
  7208. else
  7209. {
  7210. if (end + 1 < dest.Length)
  7211. {
  7212. return src + dest.GetSublist(end + 1, -1);
  7213. }
  7214. else
  7215. {
  7216. return src;
  7217. }
  7218. }
  7219. }
  7220. // Finally, if start > end, we strip away a prefix and
  7221. // a suffix, to leave the list that sits <between> ens
  7222. // and start, and then tag on the src list. AT least
  7223. // that's my interpretation. We can get sublist to do
  7224. // this for us. Note that one, or both of the indices
  7225. // might have been negative.
  7226. else
  7227. {
  7228. return dest.GetSublist(end + 1, start - 1) + src;
  7229. }
  7230. }
  7231. public void llLoadURL(string avatar_id, string message, string url)
  7232. {
  7233. m_host.AddScriptLPS(1);
  7234. IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
  7235. if (null != dm)
  7236. dm.SendUrlToUser(
  7237. new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url);
  7238. ScriptSleep(10000);
  7239. }
  7240. public void llParcelMediaCommandList(LSL_List commandList)
  7241. {
  7242. // TODO: Not implemented yet (missing in libomv?):
  7243. // PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
  7244. m_host.AddScriptLPS(1);
  7245. // according to the docs, this command only works if script owner and land owner are the same
  7246. // lets add estate owners and gods, too, and use the generic permission check.
  7247. ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
  7248. if (!World.Permissions.CanEditParcel(m_host.OwnerID, landObject)) return;
  7249. bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)?
  7250. byte loop = 0;
  7251. LandData landData = landObject.LandData;
  7252. string url = landData.MediaURL;
  7253. string texture = landData.MediaID.ToString();
  7254. bool autoAlign = landData.MediaAutoScale != 0;
  7255. string mediaType = ""; // TODO these have to be added as soon as LandData supports it
  7256. string description = "";
  7257. int width = 0;
  7258. int height = 0;
  7259. ParcelMediaCommandEnum? commandToSend = null;
  7260. float time = 0.0f; // default is from start
  7261. ScenePresence presence = null;
  7262. for (int i = 0; i < commandList.Data.Length; i++)
  7263. {
  7264. ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i];
  7265. switch (command)
  7266. {
  7267. case ParcelMediaCommandEnum.Agent:
  7268. // we send only to one agent
  7269. if ((i + 1) < commandList.Length)
  7270. {
  7271. if (commandList.Data[i + 1] is LSL_String)
  7272. {
  7273. UUID agentID;
  7274. if (UUID.TryParse((LSL_String)commandList.Data[i + 1], out agentID))
  7275. {
  7276. presence = World.GetScenePresence(agentID);
  7277. }
  7278. }
  7279. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key");
  7280. ++i;
  7281. }
  7282. break;
  7283. case ParcelMediaCommandEnum.Loop:
  7284. loop = 1;
  7285. commandToSend = command;
  7286. update = true; //need to send the media update packet to set looping
  7287. break;
  7288. case ParcelMediaCommandEnum.Play:
  7289. loop = 0;
  7290. commandToSend = command;
  7291. update = true; //need to send the media update packet to make sure it doesn't loop
  7292. break;
  7293. case ParcelMediaCommandEnum.Pause:
  7294. case ParcelMediaCommandEnum.Stop:
  7295. case ParcelMediaCommandEnum.Unload:
  7296. commandToSend = command;
  7297. break;
  7298. case ParcelMediaCommandEnum.Url:
  7299. if ((i + 1) < commandList.Length)
  7300. {
  7301. if (commandList.Data[i + 1] is LSL_String)
  7302. {
  7303. url = (LSL_String)commandList.Data[i + 1];
  7304. update = true;
  7305. }
  7306. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_URL must be a string.");
  7307. ++i;
  7308. }
  7309. break;
  7310. case ParcelMediaCommandEnum.Texture:
  7311. if ((i + 1) < commandList.Length)
  7312. {
  7313. if (commandList.Data[i + 1] is LSL_String)
  7314. {
  7315. texture = (LSL_String)commandList.Data[i + 1];
  7316. update = true;
  7317. }
  7318. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or key.");
  7319. ++i;
  7320. }
  7321. break;
  7322. case ParcelMediaCommandEnum.Time:
  7323. if ((i + 1) < commandList.Length)
  7324. {
  7325. if (commandList.Data[i + 1] is LSL_Float)
  7326. {
  7327. time = (float)(LSL_Float)commandList.Data[i + 1];
  7328. }
  7329. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TIME must be a float.");
  7330. ++i;
  7331. }
  7332. break;
  7333. case ParcelMediaCommandEnum.AutoAlign:
  7334. if ((i + 1) < commandList.Length)
  7335. {
  7336. if (commandList.Data[i + 1] is LSL_Integer)
  7337. {
  7338. autoAlign = (LSL_Integer)commandList.Data[i + 1];
  7339. update = true;
  7340. }
  7341. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer.");
  7342. ++i;
  7343. }
  7344. break;
  7345. case ParcelMediaCommandEnum.Type:
  7346. if ((i + 1) < commandList.Length)
  7347. {
  7348. if (commandList.Data[i + 1] is LSL_String)
  7349. {
  7350. mediaType = (LSL_String)commandList.Data[i + 1];
  7351. update = true;
  7352. }
  7353. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string.");
  7354. ++i;
  7355. }
  7356. break;
  7357. case ParcelMediaCommandEnum.Desc:
  7358. if ((i + 1) < commandList.Length)
  7359. {
  7360. if (commandList.Data[i + 1] is LSL_String)
  7361. {
  7362. description = (LSL_String)commandList.Data[i + 1];
  7363. update = true;
  7364. }
  7365. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_DESC must be a string.");
  7366. ++i;
  7367. }
  7368. break;
  7369. case ParcelMediaCommandEnum.Size:
  7370. if ((i + 2) < commandList.Length)
  7371. {
  7372. if (commandList.Data[i + 1] is LSL_Integer)
  7373. {
  7374. if (commandList.Data[i + 2] is LSL_Integer)
  7375. {
  7376. width = (LSL_Integer)commandList.Data[i + 1];
  7377. height = (LSL_Integer)commandList.Data[i + 2];
  7378. update = true;
  7379. }
  7380. else ShoutError("The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer.");
  7381. }
  7382. else ShoutError("The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer.");
  7383. i += 2;
  7384. }
  7385. break;
  7386. default:
  7387. NotImplemented("llParcelMediaCommandList parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString());
  7388. break;
  7389. }//end switch
  7390. }//end for
  7391. // if we didn't get a presence, we send to all and change the url
  7392. // if we did get a presence, we only send to the agent specified, and *don't change the land settings*!
  7393. // did something important change or do we only start/stop/pause?
  7394. if (update)
  7395. {
  7396. if (presence == null)
  7397. {
  7398. // we send to all
  7399. landData.MediaID = new UUID(texture);
  7400. landData.MediaAutoScale = autoAlign ? (byte)1 : (byte)0;
  7401. // do that one last, it will cause a ParcelPropertiesUpdate
  7402. landObject.SetMediaUrl(url);
  7403. // now send to all (non-child) agents
  7404. List<ScenePresence> agents = World.GetAvatars();
  7405. foreach (ScenePresence agent in agents)
  7406. {
  7407. agent.ControllingClient.SendParcelMediaUpdate(landData.MediaURL,
  7408. landData.MediaID,
  7409. landData.MediaAutoScale,
  7410. mediaType,
  7411. description,
  7412. width, height,
  7413. loop);
  7414. }
  7415. }
  7416. else if (!presence.IsChildAgent)
  7417. {
  7418. // we only send to one (root) agent
  7419. presence.ControllingClient.SendParcelMediaUpdate(url,
  7420. new UUID(texture),
  7421. autoAlign ? (byte)1 : (byte)0,
  7422. mediaType,
  7423. description,
  7424. width, height,
  7425. loop);
  7426. }
  7427. }
  7428. if (commandToSend != null)
  7429. {
  7430. // the commandList contained a start/stop/... command, too
  7431. if (presence == null)
  7432. {
  7433. // send to all (non-child) agents
  7434. List<ScenePresence> agents = World.GetAvatars();
  7435. foreach (ScenePresence agent in agents)
  7436. {
  7437. agent.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this?
  7438. (ParcelMediaCommandEnum)commandToSend,
  7439. time);
  7440. }
  7441. }
  7442. else if (!presence.IsChildAgent)
  7443. {
  7444. presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this?
  7445. (ParcelMediaCommandEnum)commandToSend,
  7446. time);
  7447. }
  7448. }
  7449. ScriptSleep(2000);
  7450. }
  7451. public LSL_List llParcelMediaQuery(LSL_List aList)
  7452. {
  7453. m_host.AddScriptLPS(1);
  7454. LSL_List list = new LSL_List();
  7455. //TO DO: make the implementation for the missing commands
  7456. //PARCEL_MEDIA_COMMAND_TEXTURE key uuid Use this to get or set the parcel's media texture.
  7457. //PARCEL_MEDIA_COMMAND_URL string url Used to get or set the parcel's media url.
  7458. //PARCEL_MEDIA_COMMAND_TYPE string mime_type Use this to get or set the parcel media MIME type (e.g. "text/html"). (1.19.1 RC0 or later)
  7459. //PARCEL_MEDIA_COMMAND_SIZE integer x, integer y Use this to get or set the parcel media pixel resolution. (1.19.1 RC0 or later)
  7460. //PARCEL_MEDIA_COMMAND_DESC string desc Use this to get or set the parcel media description. (1.19.1 RC0 or later)
  7461. //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
  7462. for (int i = 0; i < aList.Data.Length; i++)
  7463. {
  7464. if (aList.Data[i] != null)
  7465. {
  7466. switch ((ParcelMediaCommandEnum) aList.Data[i])
  7467. {
  7468. case ParcelMediaCommandEnum.Url:
  7469. list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
  7470. break;
  7471. case ParcelMediaCommandEnum.Desc:
  7472. list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description));
  7473. break;
  7474. case ParcelMediaCommandEnum.Texture:
  7475. list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString()));
  7476. break;
  7477. default:
  7478. ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
  7479. NotImplemented("llParcelMediaQuery parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString());
  7480. break;
  7481. }
  7482. }
  7483. }
  7484. ScriptSleep(2000);
  7485. return list;
  7486. }
  7487. public LSL_Integer llModPow(int a, int b, int c)
  7488. {
  7489. m_host.AddScriptLPS(1);
  7490. Int64 tmp = 0;
  7491. Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp);
  7492. ScriptSleep(1000);
  7493. return Convert.ToInt32(tmp);
  7494. }
  7495. public LSL_Integer llGetInventoryType(string name)
  7496. {
  7497. m_host.AddScriptLPS(1);
  7498. lock (m_host.TaskInventory)
  7499. {
  7500. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  7501. {
  7502. if (inv.Value.Name == name)
  7503. {
  7504. return inv.Value.Type;
  7505. }
  7506. }
  7507. }
  7508. return -1;
  7509. }
  7510. public void llSetPayPrice(int price, LSL_List quick_pay_buttons)
  7511. {
  7512. m_host.AddScriptLPS(1);
  7513. if (quick_pay_buttons.Data.Length < 4)
  7514. {
  7515. LSLError("List must have at least 4 elements");
  7516. return;
  7517. }
  7518. m_host.ParentGroup.RootPart.PayPrice[0]=price;
  7519. m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0];
  7520. m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1];
  7521. m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2];
  7522. m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3];
  7523. m_host.ParentGroup.HasGroupChanged = true;
  7524. }
  7525. public LSL_Vector llGetCameraPos()
  7526. {
  7527. m_host.AddScriptLPS(1);
  7528. UUID invItemID = InventorySelf();
  7529. if (invItemID == UUID.Zero)
  7530. return new LSL_Vector();
  7531. lock (m_host.TaskInventory)
  7532. {
  7533. if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
  7534. return new LSL_Vector();
  7535. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
  7536. {
  7537. ShoutError("No permissions to track the camera");
  7538. return new LSL_Vector();
  7539. }
  7540. }
  7541. ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  7542. if (presence != null)
  7543. {
  7544. LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
  7545. return pos;
  7546. }
  7547. return new LSL_Vector();
  7548. }
  7549. public LSL_Rotation llGetCameraRot()
  7550. {
  7551. m_host.AddScriptLPS(1);
  7552. UUID invItemID = InventorySelf();
  7553. if (invItemID == UUID.Zero)
  7554. return new LSL_Rotation();
  7555. lock (m_host.TaskInventory)
  7556. {
  7557. if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
  7558. return new LSL_Rotation();
  7559. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
  7560. {
  7561. ShoutError("No permissions to track the camera");
  7562. return new LSL_Rotation();
  7563. }
  7564. }
  7565. ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  7566. if (presence != null)
  7567. {
  7568. return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W);
  7569. }
  7570. return new LSL_Rotation();
  7571. }
  7572. /// <summary>
  7573. /// The SL implementation does nothing, it is deprecated
  7574. /// This duplicates SL
  7575. /// </summary>
  7576. public void llSetPrimURL(string url)
  7577. {
  7578. m_host.AddScriptLPS(1);
  7579. ScriptSleep(2000);
  7580. }
  7581. /// <summary>
  7582. /// The SL implementation shouts an error, it is deprecated
  7583. /// This duplicates SL
  7584. /// </summary>
  7585. public void llRefreshPrimURL()
  7586. {
  7587. m_host.AddScriptLPS(1);
  7588. ShoutError("llRefreshPrimURL - not yet supported");
  7589. ScriptSleep(20000);
  7590. }
  7591. public LSL_String llEscapeURL(string url)
  7592. {
  7593. m_host.AddScriptLPS(1);
  7594. try
  7595. {
  7596. return Uri.EscapeDataString(url);
  7597. }
  7598. catch (Exception ex)
  7599. {
  7600. return "llEscapeURL: " + ex.ToString();
  7601. }
  7602. }
  7603. public LSL_String llUnescapeURL(string url)
  7604. {
  7605. m_host.AddScriptLPS(1);
  7606. try
  7607. {
  7608. return Uri.UnescapeDataString(url);
  7609. }
  7610. catch (Exception ex)
  7611. {
  7612. return "llUnescapeURL: " + ex.ToString();
  7613. }
  7614. }
  7615. public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector lookAt)
  7616. {
  7617. m_host.AddScriptLPS(1);
  7618. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0);
  7619. if (detectedParams == null) return; // only works on the first detected avatar
  7620. ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
  7621. if (avatar != null)
  7622. {
  7623. avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname,
  7624. new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
  7625. new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
  7626. }
  7627. ScriptSleep(1000);
  7628. }
  7629. public void llAddToLandBanList(string avatar, double hours)
  7630. {
  7631. m_host.AddScriptLPS(1);
  7632. UUID key;
  7633. LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  7634. if (land.OwnerID == m_host.OwnerID)
  7635. {
  7636. ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
  7637. if (UUID.TryParse(avatar, out key))
  7638. {
  7639. entry.AgentID = key;
  7640. entry.Flags = AccessList.Ban;
  7641. entry.Time = DateTime.Now.AddHours(hours);
  7642. land.ParcelAccessList.Add(entry);
  7643. }
  7644. }
  7645. ScriptSleep(100);
  7646. }
  7647. public void llRemoveFromLandPassList(string avatar)
  7648. {
  7649. m_host.AddScriptLPS(1);
  7650. UUID key;
  7651. LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  7652. if (land.OwnerID == m_host.OwnerID)
  7653. {
  7654. if (UUID.TryParse(avatar, out key))
  7655. {
  7656. foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
  7657. {
  7658. if (entry.AgentID == key && entry.Flags == AccessList.Access)
  7659. {
  7660. land.ParcelAccessList.Remove(entry);
  7661. break;
  7662. }
  7663. }
  7664. }
  7665. }
  7666. ScriptSleep(100);
  7667. }
  7668. public void llRemoveFromLandBanList(string avatar)
  7669. {
  7670. m_host.AddScriptLPS(1);
  7671. UUID key;
  7672. LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  7673. if (land.OwnerID == m_host.OwnerID)
  7674. {
  7675. if (UUID.TryParse(avatar, out key))
  7676. {
  7677. foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
  7678. {
  7679. if (entry.AgentID == key && entry.Flags == AccessList.Ban)
  7680. {
  7681. land.ParcelAccessList.Remove(entry);
  7682. break;
  7683. }
  7684. }
  7685. }
  7686. }
  7687. ScriptSleep(100);
  7688. }
  7689. public void llSetCameraParams(LSL_List rules)
  7690. {
  7691. m_host.AddScriptLPS(1);
  7692. // our key in the object we are in
  7693. UUID invItemID = InventorySelf();
  7694. if (invItemID == UUID.Zero) return;
  7695. // the object we are in
  7696. UUID objectID = m_host.ParentUUID;
  7697. if (objectID == UUID.Zero) return;
  7698. UUID agentID;
  7699. lock (m_host.TaskInventory)
  7700. {
  7701. // we need the permission first, to know which avatar we want to set the camera for
  7702. agentID = m_host.TaskInventory[invItemID].PermsGranter;
  7703. if (agentID == UUID.Zero) return;
  7704. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
  7705. }
  7706. ScenePresence presence = World.GetScenePresence(agentID);
  7707. // we are not interested in child-agents
  7708. if (presence.IsChildAgent) return;
  7709. SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
  7710. object[] data = rules.Data;
  7711. for (int i = 0; i < data.Length; ++i) {
  7712. int type = Convert.ToInt32(data[i++].ToString());
  7713. if (i >= data.Length) break; // odd number of entries => ignore the last
  7714. // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
  7715. switch (type) {
  7716. case ScriptBaseClass.CAMERA_FOCUS:
  7717. case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
  7718. case ScriptBaseClass.CAMERA_POSITION:
  7719. LSL_Vector v = (LSL_Vector)data[i];
  7720. parameters.Add(type + 1, (float)v.x);
  7721. parameters.Add(type + 2, (float)v.y);
  7722. parameters.Add(type + 3, (float)v.z);
  7723. break;
  7724. default:
  7725. // TODO: clean that up as soon as the implicit casts are in
  7726. if (data[i] is LSL_Float)
  7727. parameters.Add(type, (float)((LSL_Float)data[i]).value);
  7728. else if (data[i] is LSL_Integer)
  7729. parameters.Add(type, (float)((LSL_Integer)data[i]).value);
  7730. else parameters.Add(type, Convert.ToSingle(data[i]));
  7731. break;
  7732. }
  7733. }
  7734. if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters);
  7735. }
  7736. public void llClearCameraParams()
  7737. {
  7738. m_host.AddScriptLPS(1);
  7739. // our key in the object we are in
  7740. UUID invItemID=InventorySelf();
  7741. if (invItemID == UUID.Zero) return;
  7742. // the object we are in
  7743. UUID objectID = m_host.ParentUUID;
  7744. if (objectID == UUID.Zero) return;
  7745. // we need the permission first, to know which avatar we want to clear the camera for
  7746. UUID agentID;
  7747. lock (m_host.TaskInventory)
  7748. {
  7749. agentID = m_host.TaskInventory[invItemID].PermsGranter;
  7750. if (agentID == UUID.Zero) return;
  7751. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
  7752. }
  7753. ScenePresence presence = World.GetScenePresence(agentID);
  7754. // we are not interested in child-agents
  7755. if (presence.IsChildAgent) return;
  7756. presence.ControllingClient.SendClearFollowCamProperties(objectID);
  7757. }
  7758. public LSL_Float llListStatistics(int operation, LSL_List src)
  7759. {
  7760. m_host.AddScriptLPS(1);
  7761. LSL_List nums = LSL_List.ToDoubleList(src);
  7762. switch (operation)
  7763. {
  7764. case ScriptBaseClass.LIST_STAT_RANGE:
  7765. return nums.Range();
  7766. case ScriptBaseClass.LIST_STAT_MIN:
  7767. return nums.Min();
  7768. case ScriptBaseClass.LIST_STAT_MAX:
  7769. return nums.Max();
  7770. case ScriptBaseClass.LIST_STAT_MEAN:
  7771. return nums.Mean();
  7772. case ScriptBaseClass.LIST_STAT_MEDIAN:
  7773. return nums.Median();
  7774. case ScriptBaseClass.LIST_STAT_NUM_COUNT:
  7775. return nums.NumericLength();
  7776. case ScriptBaseClass.LIST_STAT_STD_DEV:
  7777. return nums.StdDev();
  7778. case ScriptBaseClass.LIST_STAT_SUM:
  7779. return nums.Sum();
  7780. case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
  7781. return nums.SumSqrs();
  7782. case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
  7783. return nums.GeometricMean();
  7784. case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
  7785. return nums.HarmonicMean();
  7786. default:
  7787. return 0.0;
  7788. }
  7789. }
  7790. public LSL_Integer llGetUnixTime()
  7791. {
  7792. m_host.AddScriptLPS(1);
  7793. return Util.UnixTimeSinceEpoch();
  7794. }
  7795. public LSL_Integer llGetParcelFlags(LSL_Vector pos)
  7796. {
  7797. m_host.AddScriptLPS(1);
  7798. return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).LandData.Flags;
  7799. }
  7800. public LSL_Integer llGetRegionFlags()
  7801. {
  7802. m_host.AddScriptLPS(1);
  7803. IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
  7804. if (estate == null)
  7805. return 67108864;
  7806. return (int)estate.GetRegionFlags();
  7807. }
  7808. public LSL_String llXorBase64StringsCorrect(string str1, string str2)
  7809. {
  7810. m_host.AddScriptLPS(1);
  7811. string ret = String.Empty;
  7812. string src1 = llBase64ToString(str1);
  7813. string src2 = llBase64ToString(str2);
  7814. int c = 0;
  7815. for (int i = 0; i < src1.Length; i++)
  7816. {
  7817. ret += (char) (src1[i] ^ src2[c]);
  7818. c++;
  7819. if (c >= src2.Length)
  7820. c = 0;
  7821. }
  7822. return llStringToBase64(ret);
  7823. }
  7824. public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
  7825. {
  7826. // Partial implementation: support for parameter flags needed
  7827. // see http://wiki.secondlife.com/wiki/LlHTTPRequest
  7828. // parameter flags support are implemented in ScriptsHttpRequests.cs
  7829. // in StartHttpRequest
  7830. m_host.AddScriptLPS(1);
  7831. IHttpRequestModule httpScriptMod =
  7832. m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>();
  7833. List<string> param = new List<string>();
  7834. foreach (object o in parameters.Data)
  7835. {
  7836. param.Add(o.ToString());
  7837. }
  7838. Vector3 position = m_host.AbsolutePosition;
  7839. Vector3 velocity = m_host.Velocity;
  7840. Quaternion rotation = m_host.RotationOffset;
  7841. string ownerName = String.Empty;
  7842. ScenePresence scenePresence = World.GetScenePresence(m_host.OwnerID);
  7843. if (scenePresence == null)
  7844. ownerName = resolveName(m_host.OwnerID);
  7845. else
  7846. ownerName = scenePresence.Name;
  7847. RegionInfo regionInfo = World.RegionInfo;
  7848. Dictionary<string, string> httpHeaders = new Dictionary<string, string>();
  7849. string shard = "OpenSim";
  7850. IConfigSource config = m_ScriptEngine.ConfigSource;
  7851. if (config.Configs["Network"] != null)
  7852. {
  7853. shard = config.Configs["Network"].GetString(
  7854. "user_server_url", "http://127.0.0.1:" + ConfigSettings.DefaultUserServerHttpPort.ToString());
  7855. shard = config.Configs["Network"].GetString("shard", shard);
  7856. }
  7857. httpHeaders["X-SecondLife-Shard"] = shard;
  7858. httpHeaders["X-SecondLife-Object-Name"] = m_host.Name;
  7859. httpHeaders["X-SecondLife-Object-Key"] = m_host.UUID.ToString();
  7860. httpHeaders["X-SecondLife-Region"] = string.Format("{0} ({1}, {2})", regionInfo.RegionName, regionInfo.RegionLocX, regionInfo.RegionLocY);
  7861. httpHeaders["X-SecondLife-Local-Position"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", position.X, position.Y, position.Z);
  7862. httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z);
  7863. httpHeaders["X-SecondLife-Local-Rotation"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})", rotation.X, rotation.Y, rotation.Z, rotation.W);
  7864. httpHeaders["X-SecondLife-Owner-Name"] = ownerName;
  7865. httpHeaders["X-SecondLife-Owner-Key"] = m_host.OwnerID.ToString();
  7866. string userAgent = config.Configs["Network"].GetString("user_agent", null);
  7867. if (userAgent != null)
  7868. httpHeaders["User-Agent"] = userAgent;
  7869. string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$";
  7870. Regex r = new Regex(authregex);
  7871. int[] gnums = r.GetGroupNumbers();
  7872. Match m = r.Match(url);
  7873. if (m.Success) {
  7874. for (int i = 1; i < gnums.Length; i++) {
  7875. //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
  7876. //CaptureCollection cc = g.Captures;
  7877. }
  7878. if (m.Groups.Count == 5) {
  7879. httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
  7880. url = m.Groups[1].ToString() + m.Groups[4].ToString();
  7881. }
  7882. }
  7883. UUID reqID = httpScriptMod.
  7884. StartHttpRequest(m_localID, m_itemID, url, param, httpHeaders, body);
  7885. if (reqID != UUID.Zero)
  7886. return reqID.ToString();
  7887. else
  7888. return null;
  7889. }
  7890. public void llHTTPResponse(LSL_Key id, int status, string body)
  7891. {
  7892. // Partial implementation: support for parameter flags needed
  7893. // see http://wiki.secondlife.com/wiki/llHTTPResponse
  7894. m_host.AddScriptLPS(1);
  7895. if (m_UrlModule != null)
  7896. m_UrlModule.HttpResponse(new UUID(id), status,body);
  7897. }
  7898. public void llResetLandBanList()
  7899. {
  7900. m_host.AddScriptLPS(1);
  7901. LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  7902. if (land.OwnerID == m_host.OwnerID)
  7903. {
  7904. foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
  7905. {
  7906. if (entry.Flags == AccessList.Ban)
  7907. {
  7908. land.ParcelAccessList.Remove(entry);
  7909. }
  7910. }
  7911. }
  7912. ScriptSleep(100);
  7913. }
  7914. public void llResetLandPassList()
  7915. {
  7916. m_host.AddScriptLPS(1);
  7917. LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  7918. if (land.OwnerID == m_host.OwnerID)
  7919. {
  7920. foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
  7921. {
  7922. if (entry.Flags == AccessList.Access)
  7923. {
  7924. land.ParcelAccessList.Remove(entry);
  7925. }
  7926. }
  7927. }
  7928. ScriptSleep(100);
  7929. }
  7930. public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide)
  7931. {
  7932. m_host.AddScriptLPS(1);
  7933. LandData land = World.GetLandData((float)pos.x, (float)pos.y);
  7934. if (land == null)
  7935. {
  7936. return 0;
  7937. }
  7938. else
  7939. {
  7940. if (sim_wide != 0)
  7941. {
  7942. if (category == 0)
  7943. {
  7944. return land.SimwidePrims;
  7945. }
  7946. else
  7947. {
  7948. //public int simwideArea = 0;
  7949. return 0;
  7950. }
  7951. }
  7952. else
  7953. {
  7954. if (category == 0)//Total Prims
  7955. {
  7956. return 0;//land.
  7957. }
  7958. else if (category == 1)//Owner Prims
  7959. {
  7960. return land.OwnerPrims;
  7961. }
  7962. else if (category == 2)//Group Prims
  7963. {
  7964. return land.GroupPrims;
  7965. }
  7966. else if (category == 3)//Other Prims
  7967. {
  7968. return land.OtherPrims;
  7969. }
  7970. else if (category == 4)//Selected
  7971. {
  7972. return land.SelectedPrims;
  7973. }
  7974. else if (category == 5)//Temp
  7975. {
  7976. return 0;//land.
  7977. }
  7978. }
  7979. }
  7980. return 0;
  7981. }
  7982. public LSL_List llGetParcelPrimOwners(LSL_Vector pos)
  7983. {
  7984. m_host.AddScriptLPS(1);
  7985. LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
  7986. LSL_List ret = new LSL_List();
  7987. if (land != null)
  7988. {
  7989. foreach (KeyValuePair<UUID, int> detectedParams in land.GetLandObjectOwners())
  7990. {
  7991. ret.Add(detectedParams.Key.ToString());
  7992. ret.Add(detectedParams.Value);
  7993. }
  7994. }
  7995. ScriptSleep(2000);
  7996. return ret;
  7997. }
  7998. public LSL_Integer llGetObjectPrimCount(string object_id)
  7999. {
  8000. m_host.AddScriptLPS(1);
  8001. SceneObjectPart part = World.GetSceneObjectPart(new UUID(object_id));
  8002. if (part == null)
  8003. {
  8004. return 0;
  8005. }
  8006. else
  8007. {
  8008. return part.ParentGroup.PrimCount;
  8009. }
  8010. }
  8011. public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide)
  8012. {
  8013. m_host.AddScriptLPS(1);
  8014. // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation
  8015. // Which probably will be irrelevent in OpenSim....
  8016. LandData land = World.GetLandData((float)pos.x, (float)pos.y);
  8017. float bonusfactor = (float)World.RegionInfo.RegionSettings.ObjectBonus;
  8018. if (land == null)
  8019. {
  8020. return 0;
  8021. }
  8022. if (sim_wide != 0)
  8023. {
  8024. decimal v = land.SimwideArea * (decimal)(0.22) * (decimal)bonusfactor;
  8025. return (int)v;
  8026. }
  8027. else
  8028. {
  8029. decimal v = land.Area * (decimal)(0.22) * (decimal)bonusfactor;
  8030. return (int)v;
  8031. }
  8032. }
  8033. public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param)
  8034. {
  8035. m_host.AddScriptLPS(1);
  8036. LandData land = World.GetLandData((float)pos.x, (float)pos.y);
  8037. if (land == null)
  8038. {
  8039. return new LSL_List(0);
  8040. }
  8041. LSL_List ret = new LSL_List();
  8042. foreach (object o in param.Data)
  8043. {
  8044. switch (o.ToString())
  8045. {
  8046. case "0":
  8047. ret = ret + new LSL_List(land.Name);
  8048. break;
  8049. case "1":
  8050. ret = ret + new LSL_List(land.Description);
  8051. break;
  8052. case "2":
  8053. ret = ret + new LSL_List(land.OwnerID.ToString());
  8054. break;
  8055. case "3":
  8056. ret = ret + new LSL_List(land.GroupID.ToString());
  8057. break;
  8058. case "4":
  8059. ret = ret + new LSL_List(land.Area);
  8060. break;
  8061. default:
  8062. ret = ret + new LSL_List(0);
  8063. break;
  8064. }
  8065. }
  8066. return ret;
  8067. }
  8068. public LSL_String llStringTrim(string src, int type)
  8069. {
  8070. m_host.AddScriptLPS(1);
  8071. if (type == (int)ScriptBaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); }
  8072. if (type == (int)ScriptBaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); }
  8073. if (type == (int)ScriptBaseClass.STRING_TRIM) { return src.Trim(); }
  8074. return src;
  8075. }
  8076. public LSL_List llGetObjectDetails(string id, LSL_List args)
  8077. {
  8078. m_host.AddScriptLPS(1);
  8079. LSL_List ret = new LSL_List();
  8080. UUID key = new UUID();
  8081. if (UUID.TryParse(id, out key))
  8082. {
  8083. ScenePresence av = World.GetScenePresence(key);
  8084. if (av != null)
  8085. {
  8086. foreach (object o in args.Data)
  8087. {
  8088. switch (o.ToString())
  8089. {
  8090. case "1":
  8091. ret.Add(av.Firstname + " " + av.Lastname);
  8092. break;
  8093. case "2":
  8094. ret.Add("");
  8095. break;
  8096. case "3":
  8097. ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z));
  8098. break;
  8099. case "4":
  8100. ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W));
  8101. break;
  8102. case "5":
  8103. ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z));
  8104. break;
  8105. case "6":
  8106. ret.Add(id);
  8107. break;
  8108. case "7":
  8109. ret.Add(UUID.Zero.ToString());
  8110. break;
  8111. case "8":
  8112. ret.Add(UUID.Zero.ToString());
  8113. break;
  8114. }
  8115. }
  8116. return ret;
  8117. }
  8118. SceneObjectPart obj = World.GetSceneObjectPart(key);
  8119. if (obj != null)
  8120. {
  8121. foreach (object o in args.Data)
  8122. {
  8123. switch (o.ToString())
  8124. {
  8125. case "1":
  8126. ret.Add(obj.Name);
  8127. break;
  8128. case "2":
  8129. ret.Add(obj.Description);
  8130. break;
  8131. case "3":
  8132. ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z));
  8133. break;
  8134. case "4":
  8135. ret.Add(new LSL_Rotation(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W));
  8136. break;
  8137. case "5":
  8138. ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z));
  8139. break;
  8140. case "6":
  8141. ret.Add(obj.OwnerID.ToString());
  8142. break;
  8143. case "7":
  8144. ret.Add(obj.GroupID.ToString());
  8145. break;
  8146. case "8":
  8147. ret.Add(obj.CreatorID.ToString());
  8148. break;
  8149. }
  8150. }
  8151. return ret;
  8152. }
  8153. }
  8154. return new LSL_List();
  8155. }
  8156. internal UUID ScriptByName(string name)
  8157. {
  8158. lock (m_host.TaskInventory)
  8159. {
  8160. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  8161. {
  8162. if (item.Type == 10 && item.Name == name)
  8163. return item.ItemID;
  8164. }
  8165. }
  8166. return UUID.Zero;
  8167. }
  8168. internal void ShoutError(string msg)
  8169. {
  8170. llShout(ScriptBaseClass.DEBUG_CHANNEL, msg);
  8171. }
  8172. internal void NotImplemented(string command)
  8173. {
  8174. if (throwErrorOnNotImplemented)
  8175. throw new NotImplementedException("Command not implemented: " + command);
  8176. }
  8177. internal void Deprecated(string command)
  8178. {
  8179. throw new Exception("Command deprecated: " + command);
  8180. }
  8181. internal void LSLError(string msg)
  8182. {
  8183. throw new Exception("LSL Runtime Error: " + msg);
  8184. }
  8185. public delegate void AssetRequestCallback(UUID assetID, AssetBase asset);
  8186. protected void WithNotecard(UUID assetID, AssetRequestCallback cb)
  8187. {
  8188. World.AssetService.Get(assetID.ToString(), this,
  8189. delegate(string i, object sender, AssetBase a)
  8190. {
  8191. UUID uuid = UUID.Zero;
  8192. UUID.TryParse(i, out uuid);
  8193. cb(uuid, a);
  8194. });
  8195. }
  8196. public LSL_String llGetNumberOfNotecardLines(string name)
  8197. {
  8198. m_host.AddScriptLPS(1);
  8199. TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
  8200. UUID assetID = UUID.Zero;
  8201. if (!UUID.TryParse(name, out assetID))
  8202. {
  8203. foreach (TaskInventoryItem item in itemsDictionary.Values)
  8204. {
  8205. if (item.Type == 7 && item.Name == name)
  8206. {
  8207. assetID = item.AssetID;
  8208. break;
  8209. }
  8210. }
  8211. }
  8212. if (assetID == UUID.Zero)
  8213. {
  8214. // => complain loudly, as specified by the LSL docs
  8215. ShoutError("Notecard '" + name + "' could not be found.");
  8216. return UUID.Zero.ToString();
  8217. }
  8218. // was: UUID tid = tid = AsyncCommands.
  8219. UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_localID, m_itemID, assetID.ToString());
  8220. if (NotecardCache.IsCached(assetID))
  8221. {
  8222. AsyncCommands.
  8223. DataserverPlugin.DataserverReply(assetID.ToString(),
  8224. NotecardCache.GetLines(assetID).ToString());
  8225. ScriptSleep(100);
  8226. return tid.ToString();
  8227. }
  8228. WithNotecard(assetID, delegate (UUID id, AssetBase a)
  8229. {
  8230. if (a == null || a.Type != 7)
  8231. {
  8232. ShoutError("Notecard '" + name + "' could not be found.");
  8233. return;
  8234. }
  8235. System.Text.UTF8Encoding enc =
  8236. new System.Text.UTF8Encoding();
  8237. string data = enc.GetString(a.Data);
  8238. //m_log.Debug(data);
  8239. NotecardCache.Cache(id, data);
  8240. AsyncCommands.
  8241. DataserverPlugin.DataserverReply(id.ToString(),
  8242. NotecardCache.GetLines(id).ToString());
  8243. });
  8244. ScriptSleep(100);
  8245. return tid.ToString();
  8246. }
  8247. public LSL_String llGetNotecardLine(string name, int line)
  8248. {
  8249. m_host.AddScriptLPS(1);
  8250. TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
  8251. UUID assetID = UUID.Zero;
  8252. if (!UUID.TryParse(name, out assetID))
  8253. {
  8254. foreach (TaskInventoryItem item in itemsDictionary.Values)
  8255. {
  8256. if (item.Type == 7 && item.Name == name)
  8257. {
  8258. assetID = item.AssetID;
  8259. break;
  8260. }
  8261. }
  8262. }
  8263. if (assetID == UUID.Zero)
  8264. {
  8265. // => complain loudly, as specified by the LSL docs
  8266. ShoutError("Notecard '" + name + "' could not be found.");
  8267. return UUID.Zero.ToString();
  8268. }
  8269. // was: UUID tid = tid = AsyncCommands.
  8270. UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_localID, m_itemID, assetID.ToString());
  8271. if (NotecardCache.IsCached(assetID))
  8272. {
  8273. AsyncCommands.DataserverPlugin.DataserverReply(assetID.ToString(),
  8274. NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
  8275. ScriptSleep(100);
  8276. return tid.ToString();
  8277. }
  8278. WithNotecard(assetID, delegate (UUID id, AssetBase a)
  8279. {
  8280. if (a == null || a.Type != 7)
  8281. {
  8282. ShoutError("Notecard '" + name + "' could not be found.");
  8283. return;
  8284. }
  8285. System.Text.UTF8Encoding enc =
  8286. new System.Text.UTF8Encoding();
  8287. string data = enc.GetString(a.Data);
  8288. //m_log.Debug(data);
  8289. NotecardCache.Cache(id, data);
  8290. AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(),
  8291. NotecardCache.GetLine(id, line, m_notecardLineReadCharsMax));
  8292. });
  8293. ScriptSleep(100);
  8294. return tid.ToString();
  8295. }
  8296. }
  8297. public class NotecardCache
  8298. {
  8299. protected class Notecard
  8300. {
  8301. public string[] text;
  8302. public DateTime lastRef;
  8303. }
  8304. protected static Dictionary<UUID, Notecard> m_Notecards =
  8305. new Dictionary<UUID, Notecard>();
  8306. public static void Cache(UUID assetID, string text)
  8307. {
  8308. CacheCheck();
  8309. lock (m_Notecards)
  8310. {
  8311. if (m_Notecards.ContainsKey(assetID))
  8312. return;
  8313. Notecard nc = new Notecard();
  8314. nc.lastRef = DateTime.Now;
  8315. nc.text = ParseText(text.Replace("\r", "").Split('\n'));
  8316. m_Notecards[assetID] = nc;
  8317. }
  8318. }
  8319. protected static string[] ParseText(string[] input)
  8320. {
  8321. int idx = 0;
  8322. int level = 0;
  8323. List<string> output = new List<string>();
  8324. string[] words;
  8325. while (idx < input.Length)
  8326. {
  8327. if (input[idx] == "{")
  8328. {
  8329. level++;
  8330. idx++;
  8331. continue;
  8332. }
  8333. if (input[idx]== "}")
  8334. {
  8335. level--;
  8336. idx++;
  8337. continue;
  8338. }
  8339. switch (level)
  8340. {
  8341. case 0:
  8342. words = input[idx].Split(' '); // Linden text ver
  8343. // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard)
  8344. if (words.Length < 3)
  8345. return new String[0];
  8346. int version = int.Parse(words[3]);
  8347. if (version != 2)
  8348. return new String[0];
  8349. break;
  8350. case 1:
  8351. words = input[idx].Split(' ');
  8352. if (words[0] == "LLEmbeddedItems")
  8353. break;
  8354. if (words[0] == "Text")
  8355. {
  8356. int len = int.Parse(words[2]);
  8357. idx++;
  8358. int count = -1;
  8359. while (count < len)
  8360. {
  8361. // int l = input[idx].Length;
  8362. string ln = input[idx];
  8363. int need = len-count-1;
  8364. if (ln.Length > need)
  8365. ln = ln.Substring(0, need);
  8366. output.Add(ln);
  8367. count += ln.Length + 1;
  8368. idx++;
  8369. }
  8370. return output.ToArray();
  8371. }
  8372. break;
  8373. case 2:
  8374. words = input[idx].Split(' '); // count
  8375. if (words[0] == "count")
  8376. {
  8377. int c = int.Parse(words[1]);
  8378. if (c > 0)
  8379. return new String[0];
  8380. break;
  8381. }
  8382. break;
  8383. }
  8384. idx++;
  8385. }
  8386. return output.ToArray();
  8387. }
  8388. public static bool IsCached(UUID assetID)
  8389. {
  8390. lock (m_Notecards)
  8391. {
  8392. return m_Notecards.ContainsKey(assetID);
  8393. }
  8394. }
  8395. public static int GetLines(UUID assetID)
  8396. {
  8397. if (!IsCached(assetID))
  8398. return -1;
  8399. lock (m_Notecards)
  8400. {
  8401. m_Notecards[assetID].lastRef = DateTime.Now;
  8402. return m_Notecards[assetID].text.Length;
  8403. }
  8404. }
  8405. public static string GetLine(UUID assetID, int line, int maxLength)
  8406. {
  8407. if (line < 0)
  8408. return "";
  8409. string data;
  8410. if (!IsCached(assetID))
  8411. return "";
  8412. lock (m_Notecards)
  8413. {
  8414. m_Notecards[assetID].lastRef = DateTime.Now;
  8415. if (line >= m_Notecards[assetID].text.Length)
  8416. return "\n\n\n";
  8417. data = m_Notecards[assetID].text[line];
  8418. if (data.Length > maxLength)
  8419. data = data.Substring(0, maxLength);
  8420. return data;
  8421. }
  8422. }
  8423. public static void CacheCheck()
  8424. {
  8425. foreach (UUID key in new List<UUID>(m_Notecards.Keys))
  8426. {
  8427. Notecard nc = m_Notecards[key];
  8428. if (nc.lastRef.AddSeconds(30) < DateTime.Now)
  8429. m_Notecards.Remove(key);
  8430. }
  8431. }
  8432. }
  8433. }