Jump to content

Miranda Umino

Resident
  • Posts

    411
  • Joined

  • Last visited

Everything posted by Miranda Umino

  1. If you don t want to modify the settings , you can try to make your script with the two contitions from Kelly linden above . I have tried to make a version based on your script . I have not tested it intensively , but the first hour is ok Probably there is something to change when the URL doesn t answer , but i don t know what Have a look on the timer event in the state "running" below integer NEW_URL_MSG = -9955;float REQ_INTERVAL = 900; // 20 seconds * 45 FPSinteger REQ_CAP = 25;string sendToURL;key urlRequestID;integer isFirstBucket = TRUE;integer numberInOldBucket;integer numberInNewBucket;integer numberBuckets;integer numberRequests;integer startTime;integer referenceFrame;integer currentFrame;integer COUNTERMAX = 40 ;integer counter ; // time in second before to clean and to start the scriptdefault{ state_entry() { llOwnerSay("Be warned : if you reset the script you should wait 40 seconds to clean the buckets . If you don t clean them you could have wrong results"); } touch_end(integer n) { if ( llDetectedKey(0) == llGetOwner()) { counter = COUNTERMAX; llSetTimerEvent(1.0); } } timer() { llSetLinkPrimitiveParamsFast(LINK_THIS , [ PRIM_TEXT, "The requests will start in "+ (string)(counter--) +" seconds ", <1,1,1>,1]); if ( counter <= 0) { llSetTimerEvent(0.0); state running; } }}state running{ state_entry() { llReleaseURL(urlRequestID); urlRequestID = llRequestURL(); } http_request(key id, string method, string body) { if (id == urlRequestID) { if (method == "URL_REQUEST_GRANTED") { llOwnerSay(body); // llResetTime(); referenceFrame = (integer)llGetEnv("frame_number"); sendToURL = body; llSetTimerEvent(1/45.0); startTime = llGetUnixTime(); numberBuckets =0; numberRequests =0; } else llOwnerSay("Request for URL failed with method = "+ method); } else llHTTPResponse(id, 200, "if you say so"); } timer() { // I wont mesure time with llGetTime , llGetUnixTime , because they are real world time . // I ll prefer to measure time in Frames of sim . If the sim lags , the script is dilated , // but the throttle is maybe dilated too // llSetTimerEvent(llFrand(0.5)); // Way too fast currentFrame = (integer)llGetEnv("frame_number") - referenceFrame; if (currentFrame > REQ_INTERVAL) { referenceFrame = (integer)llGetEnv("frame_number"); isFirstBucket = FALSE; numberInOldBucket = numberInNewBucket; numberInNewBucket = 0; numberBuckets++; return; } // this is the formula from Kelly Linden // In fact i don t know if KellyLinden counts the current request when it hits the throttle // I prefer count it and add one to the variables numberInNewBucket and numberInOldBucket // To add , to be safer , i prefer to limit my throttle to 24 requests and not 25 requests // It can be safer when time to left in the bucket is low , and the numberInNewBucket //and numberInOldBucket are high ( because of rounding float 32 bits approximations) // As i don t know how round Kelly Linden his percent of time to left , i prefer // to keep a little margin . if ( (numberInNewBucket + 1 + llCeil((REQ_INTERVAL - currentFrame ) / REQ_INTERVAL * (numberInOldBucket+1)) >= REQ_CAP - 1)) { return; } else if ( isFirstBucket && (numberInNewBucket < REQ_CAP )) { numberInNewBucket++; } else if ( isFirstBucket && (numberInNewBucket >= REQ_CAP )) { return; } else if ( !isFirstBucket && (numberInNewBucket >= REQ_CAP )) { return; } else if ( !isFirstBucket && (numberInNewBucket < REQ_CAP )) { numberInNewBucket++; } else { return; } key reqID = llHTTPRequest(sendToURL, [ HTTP_METHOD, "PUT" , HTTP_VERBOSE_THROTTLE, FALSE // remove this to see the script error ], ""); numberRequests++; list rules = [ PRIM_TEXT , "numberRequests : " + (string)numberRequests + "\n" + "numberBuckets : " +(string) numberBuckets + "\n" + "realtime : " + (string)(llGetUnixTime()-startTime ) , <1,1,1>, 1 ]; llSetLinkPrimitiveParamsFast(LINK_THIS , rules); if (NULL_KEY == reqID) { llOwnerSay("HTTP REQUEST EXCEEDED THROTTLE (But how?)"); // llSetTimerEvent(llFabs(now - REQ_INTERVAL)); llOwnerSay(llList2CSV( [ "numberRequests", numberRequests, "\n", "numberBuckets", numberBuckets, "\n", "time", llGetUnixTime()-startTime, "\n", "new", numberInNewBucket, "\n", "old", numberInOldBucket, "\n", "frame", currentFrame, "\n", "test", numberInNewBucket + llCeil((REQ_INTERVAL - currentFrame ) / REQ_INTERVAL * (numberInOldBucket+1)) , "\n" ])); llSetTimerEvent(0.0); state default; } } }
  2. I think : there is a throttle of 25/ request per 20 seconds . When an llhttprequest is called : - it fills a stack or a queue .with a timestamp - it tests if the size of this queue is > 25 ( if TRUE trigges the throttle , , if false call the URL ) - it deletes the elements of the queue older than 40 seconds *** correction : see below So .. Your script should work with parameters : integer REQ_INTERVAL = 40; integer REQ_CAP = 25; Wel , i have tried your script with these setting and changed too by endSustainedInterval = llGetUnixTime()+500; to watch longer . It looks work wthout trigger the throttle ***edit *** Oh .. in fact the old answer of Kelly Linden from http://forums-archive.secondlife.com/139/2c/109571/1.html seems always right . But we need just to replace 100 seconds by 20 seconds and 20 requests by 25 requests . So it gives Long answer: The throttle uses a moving window to continue to block things that don't slow down. Starting with the first request, requests are counted in 20 second buckets. For 20 seconds from the first request all requests go into a single bucket, 20 seconds later a new bucket is started ... but the last bucket is kept around. condition 1 : If the current bucket has more than the throttle limit (25 ) then requests will be blocked. condition 2 : If the current total + (% of time remaining in this bucket * total from last bucket) is more than the throttle (25) then requests are blocked. Of course , after 40 seconds , the old bucket is empty . so the second condition is equivalent to total from current bucket + ( %time * 0 ) < 25 ; so it s equivalent to the first condition Thats why i have found with REQ_INTERVAL = 40 and REQ_CAP = 25 , your script doesn t trigger throttle . Normally your script could use only two conters , you shouldn t need to use lists of timestamps
  3. You need to sequence the comportment of your script . To sequence , use the states For instance : one state ( the default ) to manage the touch one state to manage the option menu one state to manage the avatars menu list listOptions = [ "banana", "egg", "cheese" , "pizza" ];list listAvatarsSensor;integer channelDialog ;integer handleListener;string choicedOption ;string avatarNameHavingMenu;key avatarKeyHavingMenu;float timerDialog = 15.0;float range = 10.0;default{ // We dont want several users using at the same time the menu touch_end(integer total_number) { // lets s store the avatar havaing the menu to be able to dialog with him in teh other states avatarNameHavingMenu = llDetectedName(0); avatarKeyHavingMenu =llDetectedKey(0); state firstDialog; }}// This state starts to display the menu of option to the user // After his choice , this state will scan the avatars around the prim// and go to the next state ( display the second menu )state firstDialog{ state_entry() { channelDialog= (integer)(llFrand(-1000000000.0) - 1000000000.0); handleListener = llListen(channelDialog, avatarNameHavingMenu , avatarKeyHavingMenu , ""); llDialog(avatarKeyHavingMenu, "Choose an option" , listOptions, channelDialog ); llSetTimerEvent(timerDialog); } listen( integer i, string n , key k, string m) { // the user having the menu has answered his choice of option . // let s scan the avatars to be able to build the second menu choicedOption = m; llSensor("",NULL_KEY,AGENT,range,PI); } sensor(integer n) { integer i ; listAvatarsSensor = []; do { listAvatarsSensor += llGetSubString(llDetectedName(i), 0, 23) ; i++; } while ( i < n); state secondDialog; } timer() { // the user doesn t answer . Ok . Let s give up and we return in the default state state default; } state_exit() { // normally we don t need to release the listener . It s released automatically after change states llListenRemove(handleListener); llSetTimerEvent(0.0); }} state secondDialog{ state_entry() { channelDialog= (integer)(llFrand(-1000000000.0) - 1000000000.0); handleListener = llListen(channelDialog, avatarNameHavingMenu, avatarKeyHavingMenu , ""); llDialog( avatarKeyHavingMenu, "Choose an avatar" , listAvatarsSensor, channelDialog ); llSetTimerEvent(timerDialog); } listen( integer i, string n , key k, string m) { // the user having the menu has answered his choice of avatar . // let s do our action "llownerSay" and let s go back at the default state to be able to detect other touch events llOwnerSay( choicedOption + " for " + m ); state default; } timer() { // the user doesn t answer . Ok . Let s give up and we return in the default state state default; } state_exit() { // normally we don t needd to release the listener . It s released automatically after change states llListenRemove(handleListener); llSetTimerEvent(0.0); } }
  4. Your script won t work if your object is physical , or if your object is worn Verify the "secification" part in http://wiki.secondlife.com/wiki/LlSetPos
  5. In fact , you can be warned of the end of the video in some specific cases . The video should be hosted by a provider who provides too an API For instance an API can be controlled by javascript ; and so the javascript who controls your video can be warned when the video starts or stops You will need to create a page to embed the video of the provider and some javascript who controls your video ( eventually you can serve this page inside the prim , but only the owner of the prim could see this page with your video correctly ) Your prim should accept some http requests from outside . The javascript on your page should call the URL of the prim when the video has finished Your LSL script receiving the message from the javascript changes the prim . ( but it could cause troubles if several avatars watch the video , one avatar has finished to watch , one another has not finished ) Nevertheless , if you deal with videos from different providers ( youtue , vimeo, dailymotion ) you will need a complex javascript who works with each of these providers For a prove of concept , this below an instance where the status of the video is displayed on the local chat string sUrl = "";integer face = 4;key idRequest;string videoID = "r74hkI-JcHY";string getPage(string urlStatus ){return "<html> <head> <meta http-equiv='content-type' content='text/html; charset=utf-8'/> <title>Sample for Second life</title> <style type='text/css'> #videoDiv { margin-right: 3px; } #videoInfo { margin-left: 3px; } </style> <script src='http://www.google.com/jsapi' type='text/javascript'></script> <script type='text/javascript'> google.load('swfobject', '2.1'); </script> <script type='text/javascript'> /* * Polling the player for information */ // Update a particular HTML element with a new value function updateHTML(elmId, value) { document.getElementById(elmId).innerHTML = value; } // sends the status of the video to our Prim , using a http call function updatePrim(value) { var xmlhttp=new XMLHttpRequest(); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { } } xmlhttp.open('GET','" + urlStatus + "' + '?state=' + value ,true); xmlhttp.send(); } // This function is called when an error is thrown by the player function onPlayerError(errorCode) { alert('An error occured of type:' + errorCode); } // This function is called when the player changes state function onPlayerStateChange(newState) { updatePrim(newState); } // This function is automatically called by the player once it loads function onYouTubePlayerReady(playerId) { ytplayer = document.getElementById('ytPlayer'); ytplayer.addEventListener('onStateChange', 'onPlayerStateChange'); ytplayer.addEventListener('onError', 'onPlayerError'); } // The 'main method' of this sample. Called when someone clicks 'Run'. function loadPlayer() { // The video to load var videoID = '" + videoID + "' // Lets Flash from another domain call JavaScript var params = { allowScriptAccess: 'always' }; // The element id of the Flash embed var atts = { id: 'ytPlayer' }; // All of the magic handled by SWFObject (http://code.google.com/p/swfobject/) swfobject.embedSWF('http://www.youtube.com/watch?v=' + videoID + '?version=3&enablejsapi=1&playerapiid=player1', 'videoDiv', '480', '480', '9', null, null, params, atts); } function _run() { loadPlayer(); } google.setOnLoadCallback(_run); </script> </head> <body bgcolor=\"#000000\"> <table> <tr> <td><div id='videoDiv'>Loading...</div></td> </tr> </table> </body></html>";}browse(integer face, string url){ llSetPrimMediaParams(face,[ PRIM_MEDIA_CONTROLS, PRIM_MEDIA_CONTROLS_MINI, PRIM_MEDIA_AUTO_PLAY,TRUE, PRIM_MEDIA_CURRENT_URL, url, PRIM_MEDIA_HOME_URL, url, PRIM_MEDIA_HEIGHT_PIXELS,512, PRIM_MEDIA_WIDTH_PIXELS,512]);}default{ state_entry() { llRequestURL(); } http_request(key id, string methode, string corps) { if (methode == URL_REQUEST_GRANTED) { sUrl = corps; browse(face, corps); } else if(methode == "POST") { } else { if ( llGetHTTPHeader(id, "x-path-info") == "/status" ) { string querystring = llGetHTTPHeader(id, "x-query-string" ); list l = llParseString2List(querystring, ["="], [] ); integer status = llList2Integer(l, -1);/*-1 (unstarted)0 (ended)1 (playing)2 (paused)3 (buffering)5 (video cued).*/ if ( status == 0 ) { llSay(0, "Video stopped"); } else if ( status == 1 ) { llSay(0, "Video playing"); } else if ( status == 2 ) { llSay(0, "Video paused"); } else if ( status == 3 ) { llSay(0, "Video buffering"); } else if ( status == 5 ) { llSay(0, "Video cued"); } else if ( status == -1 ) { llSay(0, "Video unstarted"); } else llSay(0, "Status of video unknown"); llSetContentType(id, CONTENT_TYPE_HTML); llHTTPResponse(id, 200, ""); } if ( llGetHTTPHeader(id, "x-path-info") == "" ) { llSetContentType(id, CONTENT_TYPE_HTML); llHTTPResponse(id, 200, getPage( sUrl + "/status" )); } } } on_rez(integer i) { llRequestURL(); } changed(integer change) { if(change & ( CHANGED_REGION | CHANGED_TELEPORT | CHANGED_REGION_START)) { llRequestURL();} }}
  6. float NewYorkLatitude = 40.71;float NewYorkLongitude = -74.00;float ParisLatitude = 48.87;float ParisLongitude = 2.34; vector interp( float destLatitude, float destLongitude, float sourceLatitude, float sourceLongitude , float t ){ vector result; result.x = ( 1.0 - t ) * sourceLatitude + t * destLatitude; result.y = ( 1.0 - t ) * sourceLongitude + t * destLongitude; return result;}vector latitudeLongitude2Cartesian(float lat , float lon, float R ){ vector result; result.x = R * llCos(lat * DEG_TO_RAD) * llCos(lon * DEG_TO_RAD); result.y = R * llCos(lat* DEG_TO_RAD) * llSin(lon* DEG_TO_RAD); result.z = R * llSin(lat* DEG_TO_RAD); return result;}default{ state_entry() {llSetLinkPrimitiveParams( 1, [ PRIM_SLICE , <0.000000, 1.000000, 0.000000>, PRIM_SIZE, <0.500000, 0.500000, 0.500000>, PRIM_TYPE, PRIM_TYPE_SPHERE, 0, <0.000000, 1.000000, 0.000000>, 0.000000, <0.000000, 0.000000, 0.000000>, <0.000000, 1.000000, 0.000000> ] );llSetLinkPrimitiveParams( 2, [ PRIM_SLICE ,<0.000000, 1.000000, 0.000000>, PRIM_SIZE, <0.020000, 0.020000, 0.010000>, PRIM_TYPE, PRIM_TYPE_CYLINDER, 0, <0.000000, 1.000000, 0.000000>, 0.000000, <0.000000, 0.000000, 0.000000>, <1.000000, 1.000000, 0.000000>, <0.000000, 0.000000, 0.000000>,PRIM_COLOR, ALL_SIDES, <1,0,0>, 1.0 ]); } touch_start(integer total_number) { float lat ; // latitude float lon ; // longitude vector coord; // cartesian coordinates in the frame of the sphere float t = 0.0; vector size = llList2Vector( llGetLinkPrimitiveParams( 1, [ PRIM_SIZE] ), 0); float R = size.x / 2.0 ; // diameter of the sphere / 2.0 vector P; do { coord = interp( ParisLatitude, ParisLongitude, NewYorkLatitude, NewYorkLongitude , t); lat = coord.x; lon = coord.y; P = latitudeLongitude2Cartesian(lat, lon, R); vector spot = P / llGetRot(); vector normal = spot;// the vector normal to a surface for an uniform sphere is equal to // the vector between the center of the sphere and the spot // so , it s equal to the vector spot.// It won t be the case if your "earth" is ellipsis like the real earth rotation r = llRotBetween(<0.0,0.0,1.0>, llVecNorm(normal) ); llSetLinkPrimitiveParamsFast(2,[ PRIM_POSITION,spot,PRIM_ROT_LOCAL,r] ); t += 0.01; llSleep(1/45.0); } while ( t <= 1.0 ); }}
  7. let s try with an instance ... float thinSlice;default{ state_entry() { // prim root is a sphere size 2*2*2 llSetLinkPrimitiveParams(1, [ 35, <0.000000, 1.000000, 0.000000>, 7, <2.000000, 2.000000, 2.000000>, 9, 3, 0, <0.000000, 1.000000, 0.000000>, 0.000000, <0.000000, 0.000000, 0.000000>, <0.000000, 1.000000, 0.000000> ]); // prim child is a sphere size 0.01*0.5*0.5 with a thin slice from 0.48 to 0.5 llSetLinkPrimitiveParams( 2 , [ 35, <0.480990, 0.501000, 0.000000>, 7, <0.010000, 0.500000, 0.50000>, 9, 3, 0, <0.000000, 1.000000, 0.000000>, 0.000000, <0.000000, 0.000000, 0.000000>, <0.480990, 0.501000, 0.000000> ] ); vector slice = llList2Vector(llGetLinkPrimitiveParams( 2, [ PRIM_SLICE] ),0); thinSlice = (slice.y - slice.x)/2.0 ; } touch(integer total_number) { if ( llDetectedLinkNumber(0) == 1) { vector P = llDetectedTouchPos(0); if ( P != ZERO_VECTOR ) { vector N = llDetectedTouchNormal(0); vector left = llVecNorm(N % llRot2Fwd(llGetLocalRot())); vector fwd = left % N; rotation curRot = llAxes2Rot( fwd, left, N); // i add a rotation along Y to have the disk tangent to the sphere curRot = llEuler2Rot(<0,PI_BY_TWO,0>) * curRot ; llSetLinkPrimitiveParamsFast(2, [ PRIM_POS_LOCAL, (P - llGetPos() + thinSlice * N )/llGetLocalRot() , PRIM_ROT_LOCAL, curRot/llGetLocalRot()]); } } }} note : in this instance , we could add too the size of the child prim following X ( to compute the final position) , but it s neglictable compared to the thin of the slice. the script must be in the root prim
  8. The "bug" is to your side , caused by you . It s your code who is bugged ; the compiler is not If you choose a classic compiler , you will get the same error if you manipulate floats . With doubles , you will get less errors , but you could have some too . For instance on the classic C compiler : #include<stdio.h>main(){float Task = 3.13;if(Task == 3.13){ printf("bad test equality gives TRUE\n");}else{ printf("bad test equality gives FALSE\n");}return 0;} your test will fail : see in this online compiler the output : test on C compiler Other point : you have told than summing some floats give errors when you try equality next Task = 3.0; Task +=0.1 ; Task +=0.03; and after if ( Task == 3.13) return FALSE. Your script is bugged there too . When you add some floats , you start to add the little floats before the big floats . If not , you create some rounding errors This rule of coding is available to other languages too ( C, java etc ) Hopefully you can use list stats function to help you . default{ touch_start(integer total_number) { list l ; float Task = 3; list Task2 = [3] ; float Task3 = 0.03; Task += 0.1; Task2 += 0.1; Task3 += 0.1; Task += 0.03; Task2 += 0.03; Task3 += 3; if(Task == 3.13){ llOwnerSay("Works"); } if(llListStatistics(LIST_STAT_SUM, Task2) == 3.13){ llOwnerSay("Works2"); } if(Task3 == 3.13){ llOwnerSay("Works3"); } }}// OUTPUT :// // Works2// Works3 An another method to sum floats correctly is to use the Kahan summation algorithm http://en.wikipedia.org/wiki/Kahan_summation_algorithm
  9. Personnaly i have no issues , except of course if you try to detect alt+keys or control+keys (alt+keys and control+keys are used by the viewer ) Below an instance where the javascript receives the keyboard event onKeyPress string sUrl = "";integer face = 4;key idRequest;string getPage( ){return "<html><head> <style> body{ font-size: 12px; font-family: Arial; }input:focus{ background-color:orange;} </style></head><body><p>The following example uses the Event Object and keyboard related properties to only allow alphabetical keys plus BACKSPACE and SPACE in a form field.<br><ul><li> Give focus to the textbox ( bg color of textbox should change to orange)<li> Press some alphabetical keys ( a-z,A-Z ) . <li> Verify if they are shown in the textbox<li> Press now some non-alphabetics characters ( 0-9 for instance)<li> Verify the textbox is unchanged<li> if the textbox has the focus , the event of return key will submit the form</ul></p><form action='"+ sUrl + "/text/' method='post'><input name='myinput' type='text' id='alphanumeric' size='25'></textarea><input type='submit' style='visibility: hidden;' /></form><script type='text/javascript'>document.getElementById('alphanumeric').focus()document.getElementById('alphanumeric').onkeypress=function(e){var e=window.event || evar keyunicode=e.charCode || e.keyCode//Allow alphabetical keys, plus BACKSPACE and SPACEif(e.which == 10 || e.which == 13) this.form.submit();return (keyunicode>=65 && keyunicode<=122 || keyunicode==8 || keyunicode==32)? true : false}</script></body></html> ";}browse(integer face, string url){ llSetPrimMediaParams(face,[ PRIM_MEDIA_CONTROLS, PRIM_MEDIA_CONTROLS_MINI, PRIM_MEDIA_AUTO_PLAY,TRUE, PRIM_MEDIA_CURRENT_URL, url, PRIM_MEDIA_HOME_URL, url, PRIM_MEDIA_HEIGHT_PIXELS,512, PRIM_MEDIA_WIDTH_PIXELS,512]);}default{ state_entry() { llRequestURL(); } http_request(key id, string methode, string corps) { llOwnerSay(llList2CSV([methode,llGetHTTPHeader(id, "x-path-info"), corps] )); if (methode == URL_REQUEST_GRANTED) { sUrl = corps; browse(face, corps); } else if(methode == "POST") { if ( llGetHTTPHeader(id, "x-path-info") == "/text/" ) { llSetContentType(id, CONTENT_TYPE_TEXT); llHTTPResponse(id, 200, corps); } } else { if ( llGetHTTPHeader(id, "x-path-info") == "" ) { llSetContentType(id, CONTENT_TYPE_HTML); llHTTPResponse(id, 200, getPage( )); } } } on_rez(integer i) { llRequestURL(); } changed(integer change) { if(change & ( CHANGED_REGION | CHANGED_TELEPORT | CHANGED_REGION_START)) { llRequestURL();} }}
  10. 65 listens can simultaneously be open in any single script. http://wiki.secondlife.com/wiki/LlListen
  11. In the advanced menu , check if you have ticked the option rendering / attached particles http://wiki.secondlife.com/wiki/Advanced_menu
  12. You are wrong : "its impact to the sim is not exactly accurately measure" The measures by llGetObjectDetails are very far away from the reality . You can have a script who takes 6Kbytes of memory , but your reporter will report 64kb of memory . it s not a "light error of accuracy" : it s an HUGE error of accuracy : You have 967% of margin error in this case ! And it s not the worst case ! To add , you can t have measures from scripts who have been created from t the same asset : the memory used in a script is the sum of its code used and its datas used . For several scripts from the same asset , the memory of code is instancied only one time , because it s the same code . The datas can be different between the scripts . So you can have 50 scripts from the same asset , who take 6 kbytes : 5kbytes of code , 1 kbytes of data . In the simulator , you will have 5 bytes of code X 1 ( X1 because it s the same bytecode compiled ) + 1 kbytes of data X 50 = 55 kbytes . ( less than a big script ) Your reporter will report number of scripts in mono * 64 kBytes = 50* 64 Kbytes = 3200 Kbytes ( margin error (3200 -55)/55 = 5 700 %) Your reporter is very far away from the reality . There are NO WAY to create a reporter who will have a correct measure , even inaccurate because to have a correct measure , you will need to use llGetUsedMemory who can t be called for an external prim , and , so , you will need to change every scripts in the land and the attachments of avatars . Thing impossible to do because you won t have the rights You write too it is still a resource the sim has to contend with. No : ressources are usage of CPU of the sim , network connections of the sim , bandwidth of the sim, I/O input,outputs disks of the sim .. You have no way to know if a script use these resources or not , and if so , how much . You can t neither get an approximative idea . A script can use no ressources at all because it s idle To elaj Scripted wearable attachments do increase Avatar Rendering Cost and therefore do contribute to a sim lag You ar wrong too : EVERY attachments increase the avatar rendering cost : scripted or not scripted If you attach an object without scripts , yyour ARC will increase; you look your ARC , and next, you add the default "hello avatar" script , your ARC is NOT Changed . Your ARC will be changed only if your script changes the display of the object ( for instance a script who emits partcles will change ARC because ARC increase when there are some particles . But if your script doesn t emit particles ( 99% of scripts ) your script won t change ARC . A prim can emit particles without script . ( you have deleted the script creating the emitter) and will have the same impact . ARC is not changed by scripts ) See ARC how is computed By the way , ARC is more a lag viewer measure than a lag sim measure . So the owner of a land can t take in consideration this measure to kick people . He doesn t know which graphic gard have the people
  13. Give up this idea . the memory of scripts can t be detected exactly outside scripts . For instance , if you compile in mono this script : default{ state_entry() { llOwnerSay("This script uses " +(string)llGetUsedMemory() + " but the reporters outside the object will report " + (string) llGetObjectDetails(llGetKey(), [ OBJECT_SCRIPT_MEMORY])); }} You will get : [18:06] Object: This script uses 3876 but the reporters outside the object will report 65536 So , 20 X less Only the scripter can know really how much memory is used in HIS script. An another script can t detect the memory used by an another script About number of scripts : wrong idea too . Scripts who don t work ... don t work ... and have no impacts . And if you want to talk about thetime to load the scripts : Someone can have 10 scripts different from 10 different Assets . Someone can have 100 identical scripts from only 1 Asset . The man with 10 scripts from 10 different assets will take more time to load the scripts when he will come in the sim An external script can t know the assets used by an another object Number of scripts doesn t mean number of assets
  14. When i copy paste some text from the clipboad ( a notice or a script with several lines ) , the chat dialog display several lines .And when i validate by enter key , the local chat have several lines. But how write in the local chat "line 1 line 2 line 3" with the help of the new-multiline chat box ? I have tried by some comnination keys as alt+enter , shift enter , without succes
  15. loop using PARCEL_DETAILS_ID by 4 meters steps ( a parcel dimension is always mutiple of 4 meters ) If the PARCEL_DETAILS_ID change , you will detect the borders of your land . Some parcels are merged and can be neither squared , neither rectangular . They can be U-shape , L-Shape , S-shape , O-shape etc ... They can have some holes too .
  16. You get the point... It makes SEVERAL YEARS since the beginning of mono that Linden has promised us new types because it would be easier for Linden to implement new features of language in Mono . It makes SEVERAL YEARS there are no evolutions of the language for something more clever . So , clearly , you have ZERO solution to solve efficiently your problem . Nevertheless ,you can always use a totally crappy and inneficient code in changing the structure of the datas . For instance , you could merge all your lists in a big one , and build an another list who references their names and their positons in the merged list . It s of course some bull**bleep** because you manipulate bigger lists ;. And as ther accessors set/get list are not linear time with the lenght of the list , it will make your code laggier. Nvertheles if you think it s useful ... For instance , you could use this : list singletonRegisteredLists;list singletonDictionnaryRegisteredLists;errorOutput(string s){ llRegionSayTo(llGetOwner(), PUBLIC_CHANNEL , "ERROR :" + llGetScriptName() + " " + s); }infoOutput(string s){ llRegionSayTo(llGetOwner(), PUBLIC_CHANNEL , "INFO :" + llGetScriptName() + " " + s); }registerList(list dataList, string nameList){ if ( llListFindList( singletonDictionnaryRegisteredLists , (list)nameList ) != -1 ) { errorOutput( "This name of list is already registered . Call update the list or change the name of the list"); } else { integer i = llGetListLength(singletonRegisteredLists); singletonRegisteredLists += dataList; singletonDictionnaryRegisteredLists += [ nameList, i, i+llGetListLength(dataList)]; }}list getListFromRegistered(string nameList){ integer idx = llListFindList( singletonDictionnaryRegisteredLists , (list)nameList ); if ( idx == -1 ) { errorOutput( "The name of the list is not existing in the dictionnary" ); return []; } else { return llList2List(singletonRegisteredLists, llList2Integer(singletonDictionnaryRegisteredLists, idx + 1) , llList2Integer(singletonDictionnaryRegisteredLists, idx + 2) ); }} integer getListLengthFromRegistered(string nameList){ list local = getListFromRegistered(nameList); integer lengthLocal = llGetListLength(local); local = []; return lengthLocal;}default{ on_rez(integer start_param) { llResetScript(); } state_entry() { list first = ["antimony", "arsenic", "aluminum", "selenium", "hydrogen", "oxygen", "nitrogen", "rhenium"]; list second = ["nickel", "neodymium", "neptunium", "germanium", "iron", "americium", "ruthenium", "uranium", "Europium", "zirconium", "lutetium", "vanadium"]; list third = ["plutonium", "argent" ]; registerList(first, "first"); registerList(second, "second"); registerList(third, "third"); llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION); } run_time_permissions(integer perm) { if(PERMISSION_TRIGGER_ANIMATION & perm) { infoOutput( " has PERMISSION_TRIGGER_ANIMATION perms for "+(string)llGetPermissionsKey()); llSetTimerEvent(2); //Cause the timer event to be triggered a maximum of once every 2 seconds. } if (perm == 0) { errorOutput( " has NO perms for "+ (string)llGetPermissionsKey()); } llListen( 0, "", "", "" ); } listen(integer channel, string name, key id, string message) { list input = llParseString2List(message, [" "], []); //the input is three variables, separated by spaces("song first 3") llSay(0, (string)input); //checks to see if its heard me by repeating what I said. It does. It works. The next three “llSay”s prove the Parsing workes. It does. string gate = llList2String(input, 0) ; // “gate” assures that only a message starting with the “magic word” will initiate the animations. string action = llList2String(input, 1); // “action” is the name of the list that contains the name of the animations. From this, also, my problem starts. string level = llList2String(input, 2); // “level” is an integer will control the “action” (maybe – still in the planning stage: llSay(0, (string)gate); // works = repeats the magic word llSay(0, (string)action);// works = says the name of the list;first” or “second” llSay(0, (string)level); // works = repeats the integer if (gate == "off") // when told "off".. { llSay (0, "bye."); llResetScript(); } //OK, but trouble then starts (next) else if (llList2String(input, 0) == "song") //assures chat starts with { list listAction = getListFromRegistered(action); llOwnerSay("The list selected is :" + llList2CSV(listAction)); integer length = llGetListLength(listAction); // Error : Function call mismatches type or number of arguments llOwnerSay("The numbe of elements of the list selected is :" + (string)llGetListLength(listAction)); } }}
  17. If you use a loop with llsetlinkprimitiveparamsfast or llsetalpha , you can get some prims displayed in one frame of the simulator and the others in the other frame . Generally it s not annoying ( 1 frame is only 22 millisseconds) . But when there are are many datas sent between the simulator and the viewer , it could be noticed But if you want to be sure your prims changed at the same frame , you need to use PRIM_LINK_TARGET PRIM_LINK_TARGET is available for LlSetPrimitiveParams , LlGetLinkPrimitiveParams, LlSetLinkPrimitiveParamsFast For your instance if you want to change to change the face 2 and 4 you use integer FACE_2 = 2; integer FACE_4 = 4;vector defaultColor = <1,1,1>;integer noLink = !!llGetLinkNumber(); float alphaValue = 0.5;llSetLinkPrimitiveParamsFast( noLink , [ PRIM_LINK_TARGET, noLink , PRIM_COLOR, FACE_2, defaultColor, alphaValue, PRIM_LINK_TARGET, noLink , PRIM_COLOR, FACE_4, defaultColor, alphaValue]);
  18. integer ON;default { touch_end(integer num_detected) { if(IS_ON) { llMessageLinked(LINK_SET, 0, "Start", NULL_KEY); } else { llMessageLinked(LINK_SET, 0, "Stop", NULL_KEY); } IS_ON = !IS_ON; }} You could replace with this above If you keep your old code and you add a script with linkedmessage , you will trigger twice the particles
  19. Of course you can do it . But you will need to play with the player API of youtube https://developers.google.com/youtube/ There are some parameters to play automataticly , or to to seek a position , to mask youtube controls etc .... This page could help you to url parameters correctly https://developers.google.com/youtube/youtube_player_demo By the way it s pretty useless and inneficient : why to oblige the users to communicate to the simulator to interact with their youtube video ? And if the user prefers to look the video in his external browser ( for instance to have a better vew , or a better framerate ) , you forbid him to use the youtube controls and , so , you annoy him If you don t like the youtube controls , you can hide them and warp your iframe inside an html with your own controls . And use the youtube javascript api (https://developers.google.com/youtube/js_api_reference) to control the video
  20. It s possible if you meet the conditions i have wroten . Nevertheless , there are so much condition than the scripter of the object B knows the script of the Object A . There is an another case where you may use some features (RLV ) of the third part viewers to force a touch event on the object A .But by default , theses features are off in the viewer , and a script can t turn on them if theay are off. To add , even with these features , it forces a touch event , it can t directly display a menu . If the touch event displays a menu , it will , but it the menu is displayed inside an another event , it won t Probably , you have touched two different prims of the same object . In this case , the Prim B of the the Linked object can brings the menu of the script inside the Prim B . But it s the same object
  21. string SCAN_NAME = "Object A"; // rezzer object's namekey SCAN_KEY = NULL_KEY;float SCAN_RANGE = 10; // Normally we can rez only in a 10m range float SCAN_INTERVAL = 1.0 ;string MESSAGE_DIALOG = "Are you Ok?";list MENU_DIALOG = [ "Yes", "No" , "So-So" ];integer CHANNEL_DIALOG ;float TIMEOUT_DIALOG = 30; // if the user doesn t answer before the tiemout , we close the listenerinteger LISTENER ;default{ state_entry() { CHANNEL_DIALOG = (integer)llFrand(1000000); LISTENER = llListen(CHANNEL_DIALOG, "", llGetOwner(), "" ); llListenControl(LISTENER, FALSE); } on_rez(integer start) { llSensorRepeat( SCAN_NAME, SCAN_KEY, ACTIVE|PASSIVE|SCRIPTED , SCAN_RANGE, PI, SCAN_INTERVAL ); } sensor(integer n ) { // We have detected an object with the same name // We ad a test to know if the owner of the rezzer is the same as the owner of the rezzee if ( llDetectedOwner(0) == llGetOwner() ) { // close the sensor llSensorRemove( ); llListenControl(LISTENER, TRUE); llSetTimerEvent(TIMEOUT_DIALOG); llDialog( llGetOwner(), MESSAGE_DIALOG, MENU_DIALOG, CHANNEL_DIALOG); } } timer() { llListenControl(LISTENER, FALSE); llOwnerSay("Time out dialog"); } listen(integer c, string s, key k, string m) { llListenControl(LISTENER, FALSE); llSay(0, "You wave picked up : " + m); } changed(integer c) { if ( c & CHANGED_OWNER ) { llResetScript(); } }} You have not specified who should receive the dialog box . I have guessed the dialog box should be shown to the owner Maybe it s not the menu of the Object B , but the menu of the Object A , you want to display . In this case , it s impossible. The better you may hope is to know if Object A has : its listener active and opened for its menu AND you know its channel AND its listener doesn t filter out your Object B AND to emulate the same menu in the Object B AND in the listen event f the emulated dialog box fom Object B , you script to talk from Object B to Object A with llRegionSayTo
  22. It s useless to use a range detection for an Orb Security : let s guess the orb is on the ground at Z = 20 m . One avatar come on the parcel exactly at the same position X,Y but at the altitude Z = 4000m, so the distance is 3980 meters To limit the range won t detect him ... If your customers use the NO-FLY tag on their parcel , and have for instance several skyboxes at different altitudes , and request you to detect which skybox has traffic , it will be better to check the altitudes of the avatars and not the distances. If your customers don t use the NO-FLY tag , it makes no sense to check the altitude of avatars. In the first case , for every elements of the result list from llGetAgentList , you call llGetObjectDetails(OBJECT_POS) and you check the Z altitude from the vector Give up this awful laggy idea to rez several sensors on the parcel .To rez objects is more laggy than to do some list operations ; to move object to the spot after the rez is more laggy than to do some list operations . It s by far the worst solution. And generally , people are closed to be able to chat , so with a big sensor , you will need several operations to detect if there are are more than 16 avatars in your sensor range . Awful .
  23. The numbers are wrong : they tell 64kb per mono script even if the mono script takes less memory . and 16kb per script not-mono . 32 KB = 2 scripts not compiled in mono (2 * 16) ; 80 kb = 1 script compiled in mono , 1 script not compiled in mono ( 64 +16) If you want to know memory , use the function llGetUsedMemory inside the code of your script s
  24. Every bots i know n SL use english AIML if they are some talking bots ( except maybe some words like "hello", "hola", "buena noce" ) Tell a sentence in english with sometypo errors . Record the reaction of the human or the bot. Tell a sentence in non-english laguage . Record the second reaction. Compare. The AIML bots have some problems too with accents who are used in non-english languages I have some doubts you could dot better in LSL. Nevertheless , there are some not-talking bots who use libomv . If i remember , the bots with libomv may detect themselves ( of course it won t detect the bots who don t use libomv )
  25. nowadays , nobody scripts a sim-monitor with sensors to record who enters and who leaves Either we use a phantom invisible mega prim at the size of your parcel with a collision_start and collision_end event ( if there are no rez and no object entry in the parcel) , either we use the function llGetAgentList inside a timer You may call too llGetRegionAgentCount to detect some changes in the sim and reduce the number of calls to llGetAgentList. And don t call some functions if you may call them later once time when you generate the report . For instance , if you want the names of the people , don t call some function to collect the names and don t store the names in your script : but wait the end of day and use later llRequestUsername with your stored keys
×
×
  • Create New...