Talk:Attach
In order for the attach() event to trigger while detaching, it must delay the detach long enough for it to process its contents.
There are a few things, such as processing time and certain functions, that will cause the detach to happen immediately while processing detach events. The next time the object is rezzed or attached, it will continue mid-event until it finishes, then begin the next event in the queue: on_rez(), then attach() (if it was attached).
What are the details of detach delay? I know that calling llSleep() while detaching will immediately stop the execution and detach the object. I've also noticed that calling llStartAnimation() and llStopAnimation() with an invalid animation will result in a script error, a script delay, and immediately stop further processing.
Is it as simple as "anything with a script delay causes immediate detachment"?
--Stickman Ingmann 20:24, 20 June 2008 (PDT)
- I would have said that if the event took longer then 0.1 (I'm guessing) seconds to run then it would pause execution of the event and detach. -- Strife Onizuka 06:38, 21 June 2008 (PDT)
I'm noticing that even with attach not doing much, it does not run at all when an avatar is logging out. Is this a new and permenant behaviour?
--Hoichi Soulstar 17:57, 19 January 2010 (PST)
- It never was a reliable logout event. It ran on some versions but mostly no. --Cerise Sorbet 02:32, 20 January 2010 (UTC)
Found a way to distinguish detach to inventory from drop:
default
{
attach( key id )
{
if ( id == NULL_KEY )
{
if ( llGetLocalPos() == llGetPos() ) llOwnerSay( "Dropped" );
else llOwnerSay( "Detached" );
}
}
}
The only case this wouldn't work would be when the avatar is at the region position of the same vector of the local position. ----Gregory Maurer 23:57, 18 September 2010 (UTC)
Triggers on log out?
This page says attach should trigger when the avatar wearing the object logs out. Although it would be really convenient if it did just that, this is obviously false. Should I fix this page?
--Satomi Ahn 14:16, 1 November 2010 (UTC)
- I cheated, to make it say that it does not happen but maybe it could. Then scripters won't be too astonished if some server code changes and it suddenly starts working. --Cerise Sorbet 18:15, 1 November 2010 (UTC)
- Could have sworn it trigged on logout, I guess I'm wrong. I like your solution to the situation btw. Keep up the good work. -- Strife (talk|contribs) 04:11, 2 November 2010 (UTC)
Temp attachments do trigger Attach
I just did a test with temporary attachments, detaching it by hand and by replacing outfits and in both instances does it trigger the attach event and is able to execute a llRegionSayTo function. If some more people can confirm it works in all occasions we can update the wiki. Frans Charming 14:20, 7 February 2013 (PST)
Race condition, or a deliberate functionality?
Elsewhere on this wiki, it is stated that, when an object is attached from inventory, since it also gets rezzed first, will trigger the on_rez event first, and then the attach event. This makes sense, conceptually speaking: after all, the object does get rezzed, it just happens to get rezzed as an attachment (which can also be a HUD!).
There are often good reasons to make sure that the item starts from a "clean" state before being used, and that's why we have llResetScript. As a rule of thumb, it's a good practice to call llResetScript when an object is not supposed to keep its state, but rather should start by entering the default state, every time it is freshly used. Now, for objects that are not supposed to be used as attachments, but always to be rezzed on the ground, on_rez is the appropriate event to do a reset. Conversely, for an item that is only supposed to be used as an attachment, and never to be rezzed on the ground, attach might make more sense for triggering llResetScript.
What about items that might be used in either way? One typical example are "unpack boxes" — any item bought from a vendor which needs to be "unpacked" (usually by touching it, sometimes by merely rezzing them) in order to get its contents. Traditionally, these would be placed on the ground and touched, because everybody used the sandboxes for that purpose. But when a newbie attempted to rez the box they bought outside a sandbox, it would immediately attach to the avatar's head, becoming a source of despair.
As time passed, with more and more people buying items inside shops, and wanting to immediately try out the bought items, the only solution was to allow rezzing on such shops, with a short autoreturn time. Nevertheless, managing all the litter became chaotic; also, with autoreturns sending objects to the Lost & Found folder, which many residents were unaware of, they would demanding refunds or redeliveries, making the situation untenable.
Therefore, merchants started offering items that you could attach to yourself instead of rezzing on the ground, and these would often look like paper bags (as they would be in "real" shops) and possibly even include a nice bag-carrying animation on it. Depending on the merchant, sometimes the content would be delivered immediately, as soon as the item was attached; others required the "unpack box" to be touched first; some even do both.
While this solution has the advantage of being more "realistic", so to speak, and neatly solves the problem of rezzing (by replacing it with attaching instead), t created further problems, namely, that the attached object might displace one's existing and essential avatar attachments — such as their clothes — resulting in a stark naked avatar in a very public area which might not have an adult rating.
This became even more prevalent these days, when most content creators, to avoid displacing the 'wrong' attachment, simply attach everything to the right hand instead. This, in turn, creates all sorts of other complications.
Furthermore, sometimes the attachment would not rez, or, if it was, it might just be slightly out of sight, and the resident might have some difficulty in touching it. As such, in the past two years or so (possibly more!), it became common to have the "unpack box" to attach as a HUD instead. This means it will always be visible. Even if it has not fully rezzed, that is irrelevant, since the resident will know that something is happening — they will see this huge grey rectangle blocking their sight, after all. Also, it is also private and convenient: you can go to an adult store full of kinky outfits and buy whatever you wish, because nobody will know — you'll just get a HUD, invisible to others, not something that anyone might 'see' or connect to a specific purchase.
And then, sometimes, content creators simply allow their "unpacking boxes" to work in the three different ways: it can be worn by your avatar (and it becomes a nice shopping bag). It can be rezzed on the ground, and it looks like, well, a shopping bag rezzed on the ground. And they can be attached as a HUD — in which case, a bit of LSL-fu will cleverly show a properly working HUD using some prims that weren't visible otherwise.
So, you have essentially a single item which can be used in (at least) three different ways.
Now, in theory, all these items must be rezzed in order to be used, and that means that the appropriate place for making sure the item is correctly initialised in every case, it should suffice to simply handle on_rez.
That's the theory, and, in fact, if you do some simple tests, it works as expected: whatever is done in on_rez is called before what comes in attach, as expected. I haven't done tests under extreme lag conditions, where the event queues might potentially be incorrectly filled, but, as far as I can say, this never happens: the only thing that might show up is a rather unexpected delay between the firing of the two events, i.e., they will not seem to accur 'almost instantly one after the other' (please correct me if I'm wrong on this assumption!).
There is a catch, which I only noticed today, and it relates to llResetScript.
If llResetScript is called on on_rez, apparently it will also clear the whole event queue, including the pending call to attach!
Now, again, I'm not 100% sure if this wasn't always the case. In my mind, however, for the past twenty years, I had never stumbled upon this issue before, things would just get reset either when an item was dropped on the ground or when it was attached — as intended. This time, however, I had a use case where the resident wearing the HUD should get a floating box with a link to click (via llLoadURL), but such link should not be sent if the HUD was dropped to he ground (presumably to allow the resident to inspect/configure it).
My theory was simple (and apparently wrong): ok, I'll do the reset first on on_rez, then I'm sure I'm on the default state, where I can catch the attach event if the HUD was attached, and handle the URL link from there.
Apparently, I was totally wrong about this. on_rez is called first, it properly resets the script, making sure it calls all appropriate initialisation procedures on start_event on the default state, and then... nothing.
'Nothing' because apparently the event queue was wiped out cleanly, so no queued events get fired, ever.
Now, this might be exactly as intended (and that's why I'm just placing a comment here — if it is, it should be mentioned, either here, or on the on_rez and llResetScript events, or perhaps I have misread/misinterpreted what these pages say, since at least llResetScript mentions that the event queue gets cleared, but it's not (for me) obvious what that exactly implies — since some things only happen after a "cycle" (whatever that means) or "until the queue has nothing else in it" — the latter being often a trigger of unexpected functionality, depending if the simulator is lagging a lot (meaning that some events in the queue might never have a chance to get fired before the object is de-rezzed) or is actually super-fast, way faster than usual (meaning that a lot of 'pending requests in the queue still have a chance to run before the item de-rezzes, some of which aren't "usual", i.e., under "normal" circumstances, there is never enough time to process them — and see their effects — before de-rezzing).
In my experience (which I admit that it's not a lot!), in the past, I never had issues in catching attach events after a script reset. In other words: llResetScript flushed the queue first (pending requests would be triggered), and then everything would be, well, 'reset' to a pristine condition (memory, state, queue, etc...), with the exception, of course, of primitive attributes (such as hovering text, for instance).
What is happening now seems to contradict my previous experience, namely, llResetScript immediately and instantly empties the event queue, no matter what might have been pending. And this happens silently, in the background, with no (direct) feedback, so to say.e
As a temporary workaround, what I do is simple: on on_rez I check if we're attached or not. If not, then I can safely do whatever initialisation is appropriate for a "HUD on the ground", and then launch llResetScript, since there will be no attach event to worry about. If the item is attached, then on_rez does nothing — it presumes that things get done on attach. And so it is: on attach, I check first for the avatar ID. If I get it, then it means the item is currently being attached and that llResetScript has not been called yet — so I do the proper initialisation (in this case, just sending the URL for the user to click) and then I do the llResetScript.
There is a catch, though. That code will ultimately depend on llGetAttached to run sufficiently fast — another bottleneck and/or potential race condition!
Note that this intricate scenario isn't that far-fetched as it might seem. For instance, some items might require being attached to work as they should, and this means correctly figuring out if they have been dropped to the ground and potentially self-re-attach themselves (or call llDie to return to inventory), and only then do the proper initialisation sequence. But you can only do that if you know in advance if and when there are further events queued ahead. To the best of my knowledge there is no function (yet) to check if there are pending events on the queue — you can only do some timeouts or something, giving a reasonable time to catch whatever events might be pending, and (potentially) forcing a reset afterwards. But how much time is "a reasonable time"? One minute? (No!) One second? (perhaps) One [insert abstract metric here, based on information retrieved on the simulator's statistics]? Also, setting a timer would only make things worse, since it would add yet another event on the queue. But doing a llSleep() to allow other seems to be radical
What would you suggest in this scenario?
— Gwyneth Llewelyn (talk) 23:20, 22 September 2024 (PDT)