Jump to content
You are about to reply to a thread that has been inactive for 4244 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Posted

Hello :)

I will have many objects on my sim that will have a listener into them. Since I read that having a lot of listeners cause lags i thought about to activate the listeners only when a my Alt (Created only for this purpose) enters the region. When she left the region, the listeners will close. Since I still didnt understood at 100% the llListen and the listen event, I write here the simple script I did for that purpose, and I need someone to tell me if it will work (If it will really remove the listeners when the Alt will leave. I don't know how to check if there are listeners that I didnt removed).

Sorry for my english, I hope what I wrote makes some sense.

Thank you very much for the help.

 

integer Exit = 0;
integer Listener;
integer ListenerNotCreated = 1;

default
{
    state_entry()
    {
        do
        {
            llSleep (30);               // Do the loop once every 30 seconds
            if (llGetAgentSize("my Alt agent key here"))
            {
                // - Sim Controller is in the Region
                if (ListenerNotCreated == 1)
                {
                    llSay (0,"Creating Listener");  
                    Listener = llListen(0, "", "", "");
                    ListenerNotCreated = 0;   
                }
            }
            else
            {
                // - Sim Controller is not in the Region
                if (ListenerNotCreated == 0)
                {
                    llSay (0,"Removing Listener");  
                    llListenRemove(Listener);
                    ListenerNotCreated = 1;   
                }
               
            }
        }
        while (Exit == 0);
    }
   
    listen(integer chan, string name, key id, string msg)
    {
        if (msg == "Do the thing")
        {
            // Something happens here
        }
       
    }
}

Posted

Simply having a listener open isn't particularly laggy.    The problems come when you've got a listener open on a busy channel, which means there's a lot of work for the them and the script to do.  That's why having an open listener on channel 0, without any filters at all (which is what you're doing) is not a good idea at all, at least not if you can possibly avoid it.

So in my revised example, I have the listener working on channel 5, to the sim won't have so many messages to process, and I also filter it only to listen to my alt (so if anyone or anything else uses channel 5, the sim immediately knows the message isn't for my object, and leaves it out consideration.

The classic explanation of how listeners work is given by Kelly Linden here (that's before we got llRegionSayTo, which is the least laggy way of doing things, but it gives you the idea).

Anyway, here's my revised version of your script.   It takes advantage of the fact a state change closes listeners automatically.

key myalt= "my alt's uuid";default{	state_entry()	{		llSetTimerEvent(30.0);// call an event every 30 seconds on a time -- don't use llSleep as an alternative	}	timer()	{		if(llGetAgentSize(myalt)!=ZERO_VECTOR){// my alt must be on the sim			state listening;		}	}}state listening{	state_entry()	{		llListen(5,"",myalt,"");  // listen to my alt on channel 5	}	listen(integer channel, string name, key id, string message)	{		// do stuff	}	timer()	{		if(llGetAgentSize(myalt)==ZERO_VECTOR){// my alt must have left the sim			state default; // state change will close the listener		}	}}

 

  • Like 1
Posted

Ok, thank you very much for the script and the link.

The script as made by you looks much more elegant. Will not by MyAlt do give the messages, an objet will do it, but it is an easy fix. Since the script will be putted on severeal objects simwide, the llRegionsay will be my choice. I will try to find if in the LLlisten i can filter several chat strings, something like this:

If you , please, can give me the correct syntax for doing it, i will appreciate a lot :) Finding out correct systaxs is hard for the beginners like me.

I read that the -5 channel should be even better, since it will said by script.

Thank you very much again, Pepite

 

llListen(-5,"",object uuid,("msg1","msg2","msg3"));  // listen to my alt on channel 5
Posted

Since you are doing it with objects communicating with each other, I would do it a bit differently.   This is because objects change their UUIDs each time you rez them, so they aren't so reliable as avatars' UUIDs.

Unfortunately, you can't filter, in a listener, for an item in a list of possible messages.  You either have to listen for a particular message or have an open filter.

This, I think, is how I would do it.  I am not clear how you want to have the main object communicate with the listening objects, so you will have to work that out for yourself, but I have set this up so that the listeners check for the presence of the "speaking" object by getting its UUID -- by saying "boo" and listening for it to reply "yikes" -- and then keep on checking that the object is still on the sim.

Meanwhile, the object grabs the UUIDs of the objects that say "boo" to it and uses llRegionSayTo to communicate with them, while checking every 30 seconds to make sure they're still there.

I have not tested these, but they do compile.

For the main, speaking, object

//main objectinteger myChannel;integer offset= 99;list listeners;//use this to hold uuids of listening objectsdefault{	state_entry()	{		myChannel = offset + ((integer)("0x"+llGetSubString((string)llGetOwner(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;		llListen(myChannel,"","","boo");//listen for the message "boo" on my channel		llSetTimerEvent(30.0);	}	listen(integer channel, string name, key id, string message)	{		llRegionSayTo(id,myChannel,"yikes");		if(!~llListFindList(listeners,[id])){//if the uuid of the object that's said "boo" to me isn't on my list			listeners +=[id];  // add it		}	}	touch_start(integer total_number)	{		integer max = -llGetListLength(listeners); //nb max is negative		if(max){ //if there any listening objects			do { // loop through the list, saying something to them				llRegionSayTo(llList2Key(listeners,max),myChannel,"msg1");			}			while (++max);		}	}	timer()	{		integer max = llGetListLength(listeners)-1;//nb max is positive		if (max){			do {				if (llGetObjectDetails(llList2Key(listeners,max),[OBJECT_POS])==[]){//not there					listeners = llDeleteSubList(listeners,max,max);//remove it from the list				}			}			while (--max>-1);		}	}}

 For the listening objects

 

integer handle;integer myChannel;integer offset= 99;key myalt="";list myMessages =["msg1","msg2","msg3"];default{	state_entry()	{		myChannel = offset + ((integer)("0x"+llGetSubString((string)llGetOwner(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;		//returns a very long negative number based on the owner's uuid.  Add the offset in case anything else is using this method to create keys		llSetTimerEvent(30.0);			}	timer()	{		if (llGetObjectDetails(myalt,[OBJECT_POS])==[]){//not there on the sim			myalt="";			llListenRemove(handle);//clear any previous listeners			handle = llListen(myChannel,"","","");//open listener on myChannel			llRegionSay(myChannel,"boo");//see if there's an object to listen to		}	}	listen(integer channel, string name, key id, string message)	{		message = llToLower(message);//make sure case isn't an issue		if ("yikes"==message){//heard back from the object			llListenRemove(handle);//close the open listener			myalt=id;//remember the uuid of the "myalt" object			handle = llListen(myChannel,"",myalt,"");//and listen only to messages from that object		}		else if (~llListFindList( myMessages,[message])){//if it's one of the messages we listen for			//process it		}	}}

 

Posted

Ok, thank you very much again.

Not only the fact that you did the script is nice, even more useful is to see the better way to write them than my way of doing it. My background knowlegdes comes from in school learned Basic.
I understood what the script in general is doing, I will have to study better it in depth, some grammars on it are stranger for me (my fault :P )

 

I will now elaborate it for the use I need, I will repost it when ready.

Thank you very much to show me the way :)

PS: Scripting is so fun :)

Posted

That “do { llSleep(30); } while” loop in your first posting made my hair stand on end! I'm glad Innula told you better, but I would like to emphasize this. Any time you are using an indefinite loop, you are violating the principles of event-driven-programming. Loops are for looking at lists, doing other things that won't take much time. You should strive to return AS SOON AS POSSIBLE from any event.

I don't know how Linden Labs does it, but in Open Simulator it turns out that llSleep blocks the thread that is running your script. The simulator has a limited number of threads, so if enough scripts call llSleep at the same time, it could lock up all scripting (on Open Simulator at least). Your first posting was potentially spending HOURS in that do loop, hogging system resources to do nothing!

Is there a page in the Wiki that has a list of "good programming practices" for LSL?

 

Posted


Kayaker Magic wrote:

[ ... ]

Is there a page in the Wiki that has a list of "good programming practices" for LSL?

 

There should be, but the closest we have AFAIK is http://wiki.secondlife.com/wiki/LSL_Script_Efficiency .  There's also a short but helpful style guide at http://wiki.secondlife.com/wiki/LSL_Style_Guide.  Both of those are bare-bones starters, though.  It may make sense to look at generic programming guidelines like http://en.wikipedia.org/wiki/Best_Coding_Practices .

Posted

Thank you very much for the answers.

Kayaker: The Do While thing I did surely is a mistake, but I read in the LSL wiki that a sleeping script does, very very little, but still create a lag. llSleep, instead, has lag 0.00.

Rolig: I saw the LSL links, very intresting the "Best Coding Pratices", thank you very much :)

Innula, my Lady Teacher :) :

I had not much time, I was able to rewrite just the "Speaking Object" script to fit my needs, here the code I did. I fullfilled it with a lots of comments to let you know my thoughts when I was doing it and my issues on some operators:

PS: I used the "Insert Code" option, but it is all black.... sorry, this will make you all much more hard to read it.

 

// ------------------------------------------------------------// --------------- Speaker Script -----------------------------// ------------------------------------------------------------integer gChannel; // Channel generated for objects comunicationsinteger gOffset= 99; // Offset for Comunication Channel genatorlist gListeners; // Holds UUIDs of listening objectsinteger gDebug = 1; // Setted to 1 when debugging the scriptdefault{    state_entry()    {        gChannel = gOffset + ((integer)("0x"+llGetSubString((string)llGetOwner(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;        /* NOTE: I CHANGED THE llListen BELOW TO MAKE IT TO READ EVERY MESSAGE, I NEED IT TO DO THAT,         THE OBJECT WILL LISTEN ITSELF SEVERAL ORDERS AND WILL SEND THEM TO THE         LISTENER OBJECTS SIM WIDE */        llListen(gChannel,"","","");        llSetTimerEvent(30.0); // Timer to regularily update the Listener Object List    }    listen(integer channel, string name, key id, string message)    {        if (message == "i exist")        {            llRegionSayTo(id,gChannel,"Ok,kid"); // Answers to the Listener Object            if(!~llListFindList(gListeners,[id]))   // If the UUID of the object isn't in the list            {                                       // so                gListeners +=[id];                  // add it                if (gDebug)                                                         // DEBUGGING                {                                                                   // DEBUGGING                    llOwnerSay("Adding an Listener Object that exists in the Sim");  // DEBUGGING                }                                                                   // DEBUGGING            }        }        if (message == "order1")    // I will add several "if" for the several instructions i need to send out        {            integer max = -llGetListLength(gListeners); //nb max is negative            if(max) //if there any listening objects            {                if (gDebug)                                  // DEBUGGING                {                                            // DEBUGGING                    llOwnerSay("Sending Order1 Sim Wide");   // DEBUGGING                }                                            // DEBUGGING                do // loop through the list, saying something to them                {                    llRegionSayTo(llList2Key(gListeners,max),gChannel,"order1");                }                while (++max); // WHAT THIS OPERATORS MEANS? WHAT IT DOES? CAN YOU WRITE IT IN A SIMPLER WAY?            }        }    }        timer()    {        integer max = llGetListLength(gListeners)-1; //nb max is positive        if (max)        // SOMETHING BROKEN IN THE "if (max)" ABOVE, THE DEBUGGING KEEPS TO TELL ME ONCE PER SCAN THAT IT DELETES AN OBJECT        // MAYBE SOMETHING WITH THE "while (--max>-1)"? I STILL DONT UNDERSTAND WHAT IT MEANS        // TONIGHT I WILL TRY TO CHECK IT AND FIND OUT BY MYSELF            {            do {                if (llGetObjectDetails(llList2Key(gListeners,max),[OBJECT_POS])==[]) //not there                {                    gListeners = llDeleteSubList(gListeners,max,max); //remove it from the list                    if (gDebug)                                                                                     // DEBUGGING                    {                                                                                               // DEBUGGING                        llOwnerSay("Deletes a Listener Object from the list cause it is not anymore in the Sim");   // DEBUGGING                    }                                                                                                                  // DEBUGGING                }            }            while (--max>-1); // WHAT THIS OPERATORS MEANS? WHAT IT DOES? CAN YOU WRITE IT IN A SIMPLER WAY?        }    }}

 

 

Posted

To get code to highlight, you need to use a web browser with Greasemonkey or Tampermonkey or something similar installed, so you can run javascript, and then install  Cerise Sorbet's LSL Posting Tool from userscripts.org.

I don't quite understand the problem with my loop in the timer.  I may have got it wrong -- I didn't test it.   When you're running  through a list deleting things you have to count backwards, because otherwise the index numbers of the list entries keep changing each time you delete something.

So what I am trying to do is check that the list actually has some members and, if it has, work from the last item in the list, check if the item is still on the sim, and, if it isn't, remove it from the list.   

The way LSL numbers list items can be confusing.  

If you say list test = ["a","b","c"]. then llGetListLength(test) will return 3.   However, list indexes in LSL start from 0, so the three elements of test are llList2String(test,0), llList2String(test,1) and llList2String(test,2) respectively.    (You probably know this, but I'm spelling it out for anyone else who is reading).

I need to check each element in list gListeners.   The first element is, obviously, llList2Key(gListeners,0).  The index of the last element is llGetListLength(gListeners)-1.   So I need to start with integer max = llGetListLength(gListeners-1) and decrease that by one until I have tested llList2Key(gListeners,0).   Or, to put it another way, I need to keep decreasing the value of max by 1 each time, until max == -1.   Or, to put it another way

while (--max > -1) 

Does that help?

I am not completely sure what the problem is in the timer event.  It may be I got something wrong -- as I said, I haven't tested the code, but it looks right to me (famous last words.. ).

I have re-written it a bit.  Maybe that makes it clearer.  It will also remove any invalid keys  in the list, in case it's trying to read a blank line or something.

	timer()	{		if (gListeners!=[]){ // if the list is not empty			integer max = llGetListLength(gListeners -1;			do {				key k = llList2Key(gListeners,max);				if (k){ // if K is a valid key					llOwnerSay("Checking "+(string)k);					if (llGetObjectDetails(llList2Key(gListeners,max),[OBJECT_POS])==[]) //not there					{						llOwnerSay((string) k+" is not here any more");						gListeners = llDeleteSubList(gListeners,max,max); //remove it from the list						if (gDebug)                                                                                     // DEBUGGING						{                                                                                               // DEBUGGING							llOwnerSay("Deletes a Listener Object from the list cause it is not anymore in the Sim");   // DEBUGGING						}						// DEBUGGING					}					else {						llOwnerSay((string( k +" is still here");					}				}				else { // if it's not a valid key it shouldn't be there, anyway					llOwnerSay(k+" is  not a valid key");					gListeners = llDeleteSubList(gListeners,max,max); //remove it from the list				}			}			while (--max>-1); // WHAT THIS OPERATORS MEANS? WHAT IT DOES? CAN YOU WRITE IT IN A SIMPLER WAY?		}	}

 

Posted

Ok, now I fully understood what "(--max>-1)" does and how it works. Thank you very much.

I will try if the "Valid Key" code lines resolve the problem.

Please don't do other codes :) I want to try myself (even if the most you just did :P )

Im still reading the Wiki tutorials, I will soon "Fast-Read" every instruction of LSL to at least know what this language can do and what is the best commad to issue for any particular task.


Thank you very much, I will test and modify for my needs the listener script too and I will let you know it it works as I wanted.

 

For the knowledges I have now, I think this way is the best way to temporanely have a lot of objects in listning mode (Lets say I can have 50-100 objects doing it...).

My Sim will be not "Fixed", it will rezz things (RP areas) at needs, for example i can rez in a part of it a city, llDie it all for rezzing a forest when I want it and things like this. Homesteads are poor in prims count, so this is the why I need such scripts (Telling you in the case you are wondering :P )

Posted

Ok, I found where the bug was:

 

timer()    {        integer max = llGetListLength(gListeners)-1; //nb max is positive        if (max)

 if listlenght is 0, as in this case (there are not listeners rezzed yet....) "max" becomes -1 at the first function of the timer event.

The "if (max)" just checks if it is FALSE (aka 0). Since it is -1 now, LSL reads it as TRUE....

A "if (max >= 0)"  should solve the issue. (PS Tested and works)

Posted

Or if (~max), which is the same thing as if (-(max+1) ) .  That's a handy one to remember, because it is always true as long as max ≠ -1.  If you write if (max >= 0) , then all negative values of max will return FALSE.  In this particular application, of course, that will never be the case, but there are plenty of times when you want to exclude only a value of -1.  This is one of those places where you have to be sure that you understand what TRUE and FALSE mean in a scripting language.

 

You are about to reply to a thread that has been inactive for 4244 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...