LSL_Api.cs 436 KB

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