Monday, September 17, 2007

SL Scripter/Builder: Random thoughts on LSL and Scripting Quality Attributes

I'm digging lately into the LSL jungle. So there were a number of things that came to my attention: I will summarize some of them:

  • LSL scripts are finite state machines in general. It's very intuitive trying to map the states from the problem doman to states in LSL. Let's say, we have to develop a door , which have to open when avatar is detected and then closed automatically. From the problems doman(a door) we know that the door may be open or closed , e.g. we have two states: OPEN, CLOSED. Using LSL will looks like that:

    default
    {
    state_entry()
    {
    state closed;
    }
    }

    state open
    {
    state_entry()
    {
    //allow avatars to get through the door
    llSetStatus(STATUS_PHANTOM,FALSE);
    //make it invisble
    llSetAlpha(ALL_SIDES,0.2);
    //hook to the sensor event
    llSensorRepeat("",NULL_KEY,AGENT,SCAN_RANGE,PI,SCAN_RATE);
    }

    sensor(integer num_detected)
    {

    }

    no_sensor()
    {
    //close the door if nothing is detected
    state close;
    }
    }

    state closed
    {
    state_entry()
    {
    //block avatars to get through the door
    llSetPrimStatus(STATUS_PHANTOM,TRUE);
    //make it visible
    llSetAlpha(ALL_SIDES,1);
    //hook to the sensor event
    l lSensorRepeat("",NULL_KEY,AGENT,SCAN_RANGE,PI,SCAN_RATE);
    }

    sensor(integer num_detected)
    {
    //open the door by using state transition
    state open;
    }
    }

    Note that event hooks(llListen,llSensor,llSetTimerEvent, etc) are valid within the state they are started. State transitions make event hooks unavailable. If you want the door to respond to chat commands, you should invoke llListen and implement listen() event on every state. However you may place the listen logic in a global routine and invoke it in every state's listen event in order to avoid duplicate code sections.

  • Note that llSensor and llSensorRepeat support event no_sensor . It may be used to trigger processing, when nothing is detected. Event sensor is raised only when something is sensed. In other words the following snipset is useless:


    sensor(integer num_detected)
    {
    if(num_detected>0)
    {
    //something is sensed, process it here
    }
    else
    {
    //script flow will never reach here.
    }
    }

    instead use the following one:
    ...
    llSensorRepeat("","",SCAN_RANGE,PI,SCAN_RATE);
    ...

    sensor(integer num_detected)
    {
    //num_detected is always greater than 0, e.g. something is detected
    }

    no_sensor()
    {
    //nothing is detected withing the SCAN_RATE seconds
    }
  • Faciliating communication between multiple scripts in a single prim should be done via llLinkedMessage. Routines llSay and llRegionSay do not work in this case
I've looked into a lot of scripts published into the Script Library , freebies and commercial objects, lately. I found it strange that most of them lack of coding practicies, which are considered as must for the software industry these days. Some of them are:
I'm aware that LSL has its own limitations and that these practices on max will increase the memory and performance preassure during runtime. However, this may not be an argument to fully forget about these concepts. We have to find the balance between maintability and usabilty.
I just don't understand, how a quality product and customer service(in-world) with a longer life cycle may be provided, when the unerlying code base does not have basic quality attributes.

1 comment:

  1. Loved your comment where you wonder how SL got to be so effective without the bells and whistles of typical s/w enginering practice evident. I passed that way too. Still unanswered.

    Canis Oh (SL resident)

    ReplyDelete