LSL_Api.cs 426 KB

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