Building in Second Life, By Example3.6 Authorizing Who Can Use a Door |
- Next Section: 3.7 Building and Scripting a Revolving Door
- Previous Section: 3.5 Scripting a Phantom Door
- Main Table of Contents
Building in Second Life, By Example3.6 Authorizing Who Can Use a Door |
Aside from keeping out the elements or preserving privacy, a door can provide security by being locked. If I don't define some way of opening a door via a script (say by sliding the door, swinging it open, or making it phantom, the door is locked, since it just stays in one place. Of more interest is the case when the door can only be opened by the owner or some designated group of people. In this section I'm going to look at some ways in which this might be done.

We have to start with some preliminaries with how objects know who is interacting with them.
For example, if I click on a door or walk into it, the door gets notified. It is not given my name,
in this case "Nigel Paravane," but is rather handed a key that you can think of as a
very large number that uniquely identifies me among all the avatars, all the objects,
and all the groups in Second Life
.
A key has 128 bits and so can represent 2128 non-negative integers, with the largest
being 340282366920938463463374607431768211455. That's pretty big.
Each avatar has its own unique key, but you never need to manipulate it directly other than passing it around as a kind of identitifcation number. In fact, that's how I'll use it in the code to follow.
Given a key, you can use the LSL function llKey2Name to get the name of the avatar.
This is mostly useful in recording the name of visitors or issuing messages like

"The door is locked, Nigel Paravane, you can't come in."
This function stops being useful when the avatar leaves the sim or is not in the same region as the object with which it is interacting. It may work for a little while after the avatar leaves the sim, but don't count on it. In a moment we'll see where a key comes from in the first place. Keys make it easy to compare whether two avatars are the same.
If you look at the picture on the right, there are two avatars and one group, and hence three keys associated with the door. The first is the "creator" of the door, and it is me. I haven't given or sold the door to anyone, so I am also the "owner" of the door. As the owner, I can set the "group" for the door to be any group to which I belong. For this object I set it to "NP Complete Design and Construction," which shows up in abbreviated form.
Right here we have three possibilities for giving permission to operate our door. We could open or close it only for the creator, the owner, or anyone who is in the group to which the door is set. We could also give permission to some combination of these.
Regarding the group option, suppose that you had a part of your building that was limited so that only certain people could get into it. These might be research scientists, financial managers, or VIPs for a nightclub. All these people could become members of a group and then have the door set to open only for people in that group. That way only they would be able to go in or out.
Actually, that's a bit simplistic because someone might tailgate behind an avatar who was authorized. That is, they might quickly follow an approved person through an open door. There are more extreme security measures to make sure that does not happen or else eject them if it does, but that is beyond the scope of this section.
To begin our coding, we'll modify the second script in the section on phantom doors so that the door will only open for the owner. We'll let anyone close it, to keep things simple. The basic idea is that when the door is closed and someone clicks on it, we get the identifying key of the avatar and then compare that with the identifying key of the door owner. If they are equal, we move the door into the open state. If not, we display a message and leave the door locked.
The original code was quite simple:
// What we do when the door is clicked ("touched") with the mouse
touch_start(integer total_number) {
state open; // Move to the open state
}
What is the integer parameter called total_number that is being passed to
touch_start that we are evidently not using?
Imagine that you and a friend are standing in front of the door and you both click it at the
same time. The value of 
total_number would be 2 since the two of you simultaneously touched the door.
Most of the time total_number will just be 1.
What does this do for us?
Remember how above I mentioned that we would use keys as identifiers for avatars?
Inside touch_start we can call

llDetectedKey with an argument of 0
to get the identifier key for the first (and probably only) avatar to touch the door at that moment.
In programming software, we usually start counting at 0 rather than 1, so if 
total_number were
equal to 3, we could get the identifying keys for the three avatars simultaneously touching the door via
llDetectedKey(0), llDetectedKey(1), and llDetectedKey(2).
That is, the maximum value we can hand to llDetectedKey is one less
than the value of 
total_number.
If you wanted to get the names of the avatars clicking the door, you could use
llDetectedName as in

llDetectedName(0), llDetectedName(1), and llDetectedName(2) for our example.
llDetectedName is a shorthand for using

llDetectedKey followed by 
llKey2Name .

We need one more thing before we can write some more code. To get the identifying key for the owner of an object,
a door in our case, use llGetOwner . Now we can write a version of

touch_start that gets the key of the first person listed who clicked the door,
compare it to the identifying key for the owner of the door, and only open the door if the keys match.

// What we do when the door is clicked ("touched") with the mouse
touch_start(integer total_number) {
// If the door was clicked by the owner of the door, open it,
// otherwise give a message.
if (llGetOwner() == llDetectedKey(0)) {
state open; // Move to the open state
}
else {
llSay(0, "Sorry, "+llDetectedName(0)+", this door can only be opened by the owner.");
}
}
You can see how this fits into the full script by clicking this link.
We print out a message via llSay in case someone other than the owner clicked the door.
The first argument to 
llSay is the channel, with 0 meaning that everyone within
20 meters can see the message. The second argument is the text to be shown, with a limit of 1024 characters.
The "
+" is used to glue together multiple strings of text into one single string, which is what
the function requires.
Before we leave this simple authorization test, we should think about the situation where multiple people click the door at the same time. Should we open the door if at least one of them is authorized or should we insist that they all must be authorized? My feeling is that the former case, having at least one authorized, should suffice. The person who is allowed to open the door should know who is around him or her and refrain from opening the door if the others should not pass through. Therefore we can extend our script in the following way:
// What we do when the door is clicked ("touched") with the mouse
touch_start(integer total_number) {
// If the door was clicked by the owner of the door, open it,
// otherwise give a message. Check everyone who clicked the door.
integer allow_access = FALSE;
integer i;
for (i = 0; i < total_number && ! allow_access; ++i) {
if (llGetOwner() == llDetectedKey(i)) {
allow_access = TRUE;
}
}
if (allow_access) {
state open; // Move to the open state
}
else {
llSay(0, "Sorry, you are not authorized to open the door.");
}
}
Here we use a variable called allow_access to hold the values TRUE
or FALSE to indicate whether we should open the door. The initial value is FALSE.
We then loop through everyone who clicked the door.
If the owner of the door is found, we set
allow_access to TRUE and stop checking the list of clickers.
After that, we move to an open state if allow_access is TRUE or else
we give a denial message via llSay .

Here are a couple of notes on the for loop:
&&" means "and". If we wanted to have "or" instead, we would have used "||".!" before allow_access means "not". So ! TRUE is
FALSE and ! FALSE is TRUE.
This provides the model for how we will determine whether we should open the door: apply some access authorization
tests and if they come back with TRUE, then open the door. Otherwise leave it closed and display a message.
Therefore we'll now look at making our access tests more sophisticated.
TO BE CONTINUED ...