Second Life LSL Problems: llGetOwner()

By Xah Lee. Date: . Last updated: .

This page documents a bad design in LSL.

When you use llGetOwner in llListen, and suppose you give the object to another person. The listen will still listen to you.

Here's a example code. Put it in a prim. Wear it. When you type, it'll respond to the owner. But when you pass this to someone, it still responds to you.

// 2010-06-10 testing llListen set to Owner only.  when this object is
// transfered to a new person, it still listens to the older owner
default
{
    state_entry()
    {
        // listen to owner only
        llListen(0, "", llGetOwner(), "");
    }

    listen(integer channel, string name, key id, string message)
    {
        // respond.
        llSay(0, "I heard: “" + (string) message + "”");
    }
}

This is because, llListen “remembers”. Here's a quote from lslwiki.net:

Is your script listening to or animating the object's old owner? It may seem like llGetOwner is broken, but this is not the case. Functions like llListen and llRequestPermissions remember the key that you passed to them and continue to act on that person even if ownership of the object changes. If you set up a llListen to listen for the owner of an object, the script will continue to listen to that specific person after ownership is changed. If you llRequestPermissions to animate the owner of an object and ownership changes, llStartAnimation will continue to animate the old owner of the object. If calling llResetScript in the on_rez event is unfeasible, consider checking the CHANGED_OWNER in the changed event to detect a change in ownership, and reinitialize llListens and call llRequestPermissions on the new owner as needed.

See also the official doc: wiki.secondlife.com llGetOwner.

It is said that this is not because llGetOwner is broken, but rather:

When the owner of an object changes, code that depends on this function's return value will not automatically update for the new owner or be automatically re-evaluated.

But that's just a excuse. The LSL language is basically broken, in so many ways.

If we take the point of view that it is not broken, then the situation is that LSL as a language have some special model of its environment, and in particular, llListen remembers its second parameter (the person to listen to). Now there isn't really a public specification on what all these sticky properties are (particles, floating text). When you give a object to someone, and if the script uses llGetOwner in anyway, the behavior of the object should just assume the new owner.

The sticky property of owner gets complex.

If your script contains a global constant “key owner;” and you have “owner = llGetOwner()” in your “state_entry” block, then, you really want the following line too:

changed(integer change) { 
    if (change & CHANGED_OWNER) {llResetScript();} 
}

Now, suppose you want a block of code to run when a object is rezzed. You read on lsl wiki that state_entry does not guarantee it, because obj maitain states. So, if your script is some state and not the default state, the state_entry in default block won't run when the obj is rezed. You are told to use “on_rez” event. However, when you have that owner change reset script line, then your init block in on_rez won't work the way you wanted, because, when the object is rezzed, it appears that “changed” event gets fired after the on_rez event, then your script is now reset, so code starts to run in default state_entry block again. Whatever your init in on_rez block was run but because now the script has been reset, so whatever your init code has done is now undone.

Actually, the solution here is simply to put your init code in the default state's state_entry block. That is guaranteed to run whenever script is reset. The wiki is misleading about on_rez. The “on_rez” event handler is no more guaranteed to run that state_entry, because, if your on_rez is in the “default” state block, and if the script is currently in another state, your on_rez event handler won't be triggered.