Difference between revisions of "LSL 101/The Structure of a Script"

From Second Life Wiki
Jump to navigation Jump to search
m (<lsl> tag to <source>)
 
(20 intermediate revisions by 5 users not shown)
Line 1: Line 1:
{{NavNextPrev|prev=A Gentle Introduction|next=Simple Script Skeleton}} 
{{LSL Wikibook Index}}
==The Structure of a Script==
==The Structure of a Script==


Here is the simplest possible valid LSL script.  It doesn't actually ask the computer to do anything but all scripts have, at minimum, this structure:
Here is the simplest possible valid LSL script.  It doesn't actually ask the computer to do anything but all scripts have, at minimum, this structure:


<lsl>
<source lang="lsl2">
default {
default  
     state_entry() {
{
     state_entry()  
    {
     }
     }
}
}
</lsl>
</source>


In order to explain even this short piece of code we need to introduce you to some terms that will probably be new to you.
In order to explain even this short piece of code we need to introduce a few terms.


LSL scripts use two concepts called ''states'' and ''events''.
LSL scripts use ''states'', ''events'', ''functions'' and ''variables''.  We'll use this example to show how they work together and go into detail below.


Edit: I did not write the above text but the rest of the text in this section is mine.
We'll use ''comments'' (two forward // slashes) to talk inside the script.  Anything on a line after // will not execute so you can leave yourself notes like this:


I would like to say that while the structure above is valid and does work, the way it is formatted can sometimes be confusing to new scripters and can cause grief when you get into longer scripts later on. The important thing is to just pick one structure and stay with it.
<source lang="lsl2">
default                                //  this is the only *state* in this script
{                                      //  opening bracket for default state


This is the way that I learned and also the way I suggest that anyone who is new to LSL (Linden Scripting Language) structure there scripts. This structure, which is virtually the same as the above structure, can help when your scripts begin to get longer and more complicated. It helps by allowing you to see the curly brackets ("{" "}" these things) line up so that you know you have opened and closed the sate/event correctly.
    state_entry()                     //  this is the only *event* in this script


<lsl>
    {                                  // opening bracket for this *event*
//The only changes made are the brackets being moved
//I move the brackets to make it easier to read the script
//and find errors later when your scripts get bigger


default
      llOwnerSay("Hello, creator!")// this is the only *statement* inside the event. It is invoking a library function.
{ //Opening bracket
    state_entry()
    { //Opening bracket
    } //Closing bracket
} //Closing bracket
</lsl>


Now lets explain some of the things in the above script encase you skipped right to this section instead of reading [[LSL 101/In the Beginning|In the Beginning]]. Anything after the double back-slashes (these "//") is a comment but only if and only if it is on the same line so if you type "//this is a comment" then go to a new line the comment is over. Example:
    }                                  // closing bracket for this *event*
<lsl>
//This is a comment
This is not
</lsl>


==States==
}                                      //  closing bracket for default state
</source>


''State'' is actually a very good name for what states do in LSL. If you think of a car, it can either be moving or stopped. We can say its state is moving (when it is moving) and its state is stopped (when it is stopped).  Another example is your own state of being: you can be awake, asleep, active, sitting, standing, hungry, bored, confused, etc.
Always formatting like this makes it a lot easier to read and debug your code later. There is no "right" or "wrong" in the actual arrangement of white space on the page, in fact, some scripters prefer a more compact style. However careful attention to indenting will greatly help you to see what lines "belong together" and as the placement of { and } is so important, and their pairing is vital, it can greatly help if you code matching pairs so that they appear in the same column, giving visual vertical alignment.


All LSL scripts have at least one state: the ''default'' state. This is the state when no other states are active.  You can see in the code above the word ''default'' is used to tell the script about what happens in the default state.
''For more information on this section, please see''  
*[[LSL 101/Simple Script Skeleton | Simple Script Skeleton]]
*[[LSL 101/Comments, White-space and Formatting | Comments, White-space and Formatting]]


Here is an example with two states:
==[[State |States]]==


<lsl>
While the majority of LSL scripts can and are written with just one ''State'' (the default state), it is possible (and at times useful) to define additional states yourself, perhaps to focus your coding on the processing required at a particular stage of proceedings.
default {
    state_entry() {
        llOwnerSay("Switching to the hungry state...");
        state hungry;
    }
}


state hungry {
A ''State'' in LSL contains events which relate to each other.  For example, cars can either be moving or stopped. When the car is in *state moving* it's going forward and when it's at rest it is in *state stopped*.  There may be other states (*state reverse, *state stolen, *state wrecked, *state repaired) but *state moving* and *state stopped* are probably the most common states for a car!
    state_entry() {
        llOwnerSay("I am very hungry! Does anyone have any spam?");
    }
}
</lsl>


The first thing to notice is that the hungry state needs the word ''state'', so that the script knows this describes a state rather than something else. The default state does not need to be proceeded by the word state because it is a state built into lsl and is required in every script. The reason you need the word ''state'' before hungry is because this is a state you a creating yourself.
For practical LSL purposes, one state might be used for setting up (e.g. reading a configuration notecard, seeking run time permissions etc.) and another state for the rest of the script, processing that would be inappropriate or impossible until after the set-up stage has been completed.


Next, notice the curly braces '{' and '}'.  These tell the script which lines are part of the default state, which are part of the hungry state, and which belong to the state_entry() event handler, which we describe next.
All LSL scripts have at least one state: the ''default'' state. This is the state when no other states are activeYou can see in the code above the word ''default'' is used to tell the script about what happens in the default state.


==Events==
Here is an example of a script with two states:


When something happens we can say an ''event'' has happenedLSL knows about many kinds of events and can respond to them depending on what kind of event happened.
<source lang="lsl2">
/* state */ default
{
//  state_entry()
//  {
//      llOwnerSay("Entering state 'default'.");
// }


LSL scripts don't run on your PC, they run on the server where the sim you are in is running. The server takes care of seeing when something changes - an avatar moves, you click something, the clock ticks, someone types something in text chat, you create an object, save a notecard, give someone a landmark, etc. - and it passes on information about those changes to the viewer running on your PC, which then displays those changes or shows a dialog or whatever is needed.  The server also passes those events on to any scripts that have asked to know about that particular kind of event.
    touch_end(integer num_detected)
    {
        llOwnerSay("Switching to 'state happy'.");


Your script can tell the server to inform it of events by including an event handler.  In the example above we have added event handlers called ''state_entry()'', which requires the server to tell it when the script enters that particular state.  When the script receives the state_entry() event it runs the instructions inside the curly braces belonging to the state_entry() event handler.
        state happy;
    }


Some events also pass other information from the server; for instance the ''listen()'' event receives a channel number (to indicate which channel the chat was heard on), the name of the avatar or object that sent the chat, their (or its) UUID key, and the text of the message that was typed or sent. The listen() event handler is declared like this:
// state_exit()
 
//  {
<lsl>
//      llOwnerSay("Leaving state 'default'.");
listen(integer channel, string name, key id, string message) {
// }
    // some actions to take when something is heard in text chat
}
}
</lsl>


We will discuss more about events but before we do, and in order to explain the code above, we need to introduce another concept: variables.
state happy
{
//  state_entry()
//  {
//      llOwnerSay("Entering 'state happy'.");
//  }


==Variables==
    touch_end(integer num_detected)
    {
        llOwnerSay("Switching to state 'default'.");


We said that the server can pass information about events and in our example above you can see that we refer to the different pieces of information by giving them different names: channel, name, id, message.  Not only are these separate pieces of information, they are different ''types'' of information: channel is a number, name is text, id is a special kind of number called a UUID key, message is text.
        state default;
    }


Variables, then, are declared by giving their type and their name. But variables would not be very useful if they did not also have a ''value''. When we give a value to a variable it can be said we ''defined'' the variable.
// state_exit()
 
//  {
Before you use a variable in LSL you ''must'' declare it and usually you will want to define it as well.  These can both be done on separate lines or on the same line of code. Here are two examples:
//      llOwnerSay("Leaving 'state happy'.");
 
//  }
<lsl>
}
string myName;
</source>
myName = "An Avatar";
 
// or
 
string myName = "An Avatar";
</lsl>
 
So what different types of variables does LSL know about?
 
===integer===
 
Integers are numbers, but only a limited set of numbers. Integers in LSL are any numbers between −2,147,483,648 and +2,147,483,647, so long as they are 'whole' numbers (that is, they don't have a decimal point, like 1.5).
 
integers are declared and defined like this
 
<lsl>
integer myNumber = 42;
</lsl>
 
You are used to using the decimal number system (called ''base 10''), where numbers are counted using the digits 0 to 9, but you should also know there are other number systems that can be used with LSL, such as hexadecimal (''base 16''), which uses digits 0 to 9 and letters A to F.  You don't need to know about the hexadecimal system to write scripts but you may well come across hexadecimal numbers if you are modifying scripts someone else has written and you may later find that there are some places where it makes sense to use hexadecimal numbers instead of decimals.
 
Hexadecimal numbers are written as in this example (which does exactly the same as the example above):


<lsl>
Notice the happy state needs the word ''state'', so that the script knows this describes a state rather than something else.  The default state does not need the word state in front of it because it is built into lsl and is required in every script. The reason you need the word ''state'' before happy is because this is a user-created state and you have to be specific or the server will not know your intent. 
integer myNumber = 0x2a;
</lsl>


''2a in hexidecimal = 42 [(2 * 16) + 10 is the same as (4 * 10) + 2]''
Next, notice the curly braces '{' and '}'.  These tell the script which lines are part of the default state, which are part of the happy state, and which lines belong to the touch_start {event handlers}.


A note to those who have used other programming languages before: LSL does not have a binary variable type.  TRUE and FALSE are stored using integers with TRUE having a value of 1 and FALSE having a value of 0. We will discuss this in more detail later.
Notice also that in the above example we used touch_end events rather than touch_start. This is not the place to go fully into the reasons why, just note that is advisable not to do state changes from within the touch_start event.


===float===
'''The tutorial continues with [[LSL_101/Simple Script Skeleton|Simple Script Skeleton]].'''

Latest revision as of 13:47, 24 January 2015

← A Gentle Introduction ↑̲  LSL 101  ̲↑ Simple Script Skeleton →

The Structure of a Script

Here is the simplest possible valid LSL script. It doesn't actually ask the computer to do anything but all scripts have, at minimum, this structure:

default 
{
     state_entry() 
     {
     }
}

In order to explain even this short piece of code we need to introduce a few terms.

LSL scripts use states, events, functions and variables. We'll use this example to show how they work together and go into detail below.

We'll use comments (two forward // slashes) to talk inside the script. Anything on a line after // will not execute so you can leave yourself notes like this:

default                                 //  this is the only *state* in this script
{                                       //  opening bracket for default state

     state_entry()                      //  this is the only *event* in this script

     {                                  //  opening bracket for this *event*

       llOwnerSay("Hello, creator!");   //  this is the only *statement* inside the event. It is invoking a library function.

     }                                  //  closing bracket for this *event*

}                                       //  closing bracket for default state

Always formatting like this makes it a lot easier to read and debug your code later. There is no "right" or "wrong" in the actual arrangement of white space on the page, in fact, some scripters prefer a more compact style. However careful attention to indenting will greatly help you to see what lines "belong together" and as the placement of { and } is so important, and their pairing is vital, it can greatly help if you code matching pairs so that they appear in the same column, giving visual vertical alignment.

For more information on this section, please see

States

While the majority of LSL scripts can and are written with just one State (the default state), it is possible (and at times useful) to define additional states yourself, perhaps to focus your coding on the processing required at a particular stage of proceedings.

A State in LSL contains events which relate to each other. For example, cars can either be moving or stopped. When the car is in *state moving* it's going forward and when it's at rest it is in *state stopped*. There may be other states (*state reverse, *state stolen, *state wrecked, *state repaired) but *state moving* and *state stopped* are probably the most common states for a car!

For practical LSL purposes, one state might be used for setting up (e.g. reading a configuration notecard, seeking run time permissions etc.) and another state for the rest of the script, processing that would be inappropriate or impossible until after the set-up stage has been completed.

All LSL scripts have at least one state: the default state. This is the state when no other states are active. You can see in the code above the word default is used to tell the script about what happens in the default state.

Here is an example of a script with two states:

/* state */ default
{
//  state_entry()
//  {
//      llOwnerSay("Entering state 'default'.");
//  }

    touch_end(integer num_detected)
    {
        llOwnerSay("Switching to 'state happy'.");

        state happy;
    }

//  state_exit()
//  {
//      llOwnerSay("Leaving state 'default'.");
//  }
}

state happy
{
//  state_entry()
//  {
//      llOwnerSay("Entering 'state happy'.");
//  }

    touch_end(integer num_detected)
    {
        llOwnerSay("Switching to state 'default'.");

        state default;
    }

//  state_exit()
//  {
//      llOwnerSay("Leaving 'state happy'.");
//  }
}

Notice the happy state needs the word state, so that the script knows this describes a state rather than something else. The default state does not need the word state in front of it because it is built into lsl and is required in every script. The reason you need the word state before happy is because this is a user-created state and you have to be specific or the server will not know your intent.

Next, notice the curly braces '{' and '}'. These tell the script which lines are part of the default state, which are part of the happy state, and which lines belong to the touch_start {event handlers}.

Notice also that in the above example we used touch_end events rather than touch_start. This is not the place to go fully into the reasons why, just note that is advisable not to do state changes from within the touch_start event.

The tutorial continues with Simple Script Skeleton.