Differences

This shows you the differences between two versions of the page.

Link to this comparison view

wiki:scripting_portal:inline_events [2018/10/23 02:48] (current)
Royale Mobian created
Line 1: Line 1:
 +====== YEngine inline events ======
 +\\
 +===== INLINE EVENT HANDLING =====
 +Sometimes using the event handler model can be inconvenient and lead to distored code. These built-in functions can lead to simpler code when dealing with such situations.
  
 +Note: Inline event handling just involves some built-in functions, therefore no yoption statement is needed. ​
 +
 +==== Call an arbitrary event handler in the current state ====
 +<code ossl>
 +   ​xmrEventCallHandler (list ev)
 +       ev = event to be processed
 +           ev[0] = (integer) event code (XMREVENTCODE_<​eventname>,​ eg, 
 +                   ​XMREVENTCODE_touch_start)
 +           ​ev[1..n] = call parameters to the event, if any
 +</​code>​
 +<code ossl>
 +Note:
 +  1) The event handler is called immediately and when that event handler ​
 +     ​completes,​ xmrEventCallHandler() returns to its caller. ​ Contrast with 
 +     ​xmrEventEnqueue() which places the event in the event queue for 
 +     ​processing after the current event handler completes.
 +</​code>​
 +\\
 +==== Block script execution until an event is queued or a timeout is reached ====
 +<code ossl>
 +   list xmrEventDequeue (float timeout, integer rm1, integer rm2, 
 +                                        integer bm1, integer bm2)
 +</​code>​
 +<code ossl>
 +       ​timeout = maximum number of seconds to wait
 +       ​rm1,​rm2 = if an event is queued that matches these mask bits, the 
 +                 ​script is woken, that event is dequeued and returned to the 
 +                 ​caller. ​ the normal event handler defined in the current ​
 +                 state for the event is not executed.
 +       ​bm1,​bm2 = if an event is queued that matches these mask bits, the 
 +                 ​script is woken, that event is dequeued and its normal event 
 +                 ​handler for the current statis is executed. ​ then the script ​
 +                 ​resumes waiting for what's left of the timeout or for another ​
 +                 event to be queued.
 +</​code>​
 +<code ossl>
 +       ​returns empty list: no event was queued that matched rm1,rm2 and the 
 +                           ​timeout was reached
 +                     else: list giving parameters of the event, same format as 
 +                           is passed to xmrEventCallHandler()
 +</​code>​
 +**Notes:**
 +\\
 +\\
 +  - Scripts should use XMREVENTMASKn_<​eventname>​ symbols for the mask arguments, where n is 1 or 2 for mask1 or mask2 arguments. ​ The list[0] return argument can be decoded by using XMREVENTCODE_<​eventname>​ symbols.
 +  - If all masks are zero, the call ends up acting like llSleep.
 +  - If an event is enabled in both rm1,rm2 and bm1,bm2, the rm1,rm2 bit action takes precedence, ie, the event is returned. ​ This allows a simple specification -1 for both bm1,bm2 arguments to indicate that all events not enabled to be returned by the rm1,rm2 arguments should be handled in the background.
 +  - Any events not listed in either rm1,rm2 or bm1,bm2 arguments will be queued for later processing (subject to normal queue limits).
 +  - Background event handlers execute as calls from within XMREventDequeue,​ they do not execute as separate threads. ​ Thus any background event handlers must return before the call to xmrEventDequeue will return.
 +  - If a background event handler changes state (eg, via '​state'​ statement), the state is immediately changed and the script-level xmrEventDequeue call does not return.
 +  - For returned events, the detect parameters are overwritten by the returned event. ​ For background events, the detect parameters are saved and restored.
 +  - Scripts must contain dummy event handler definitions for any event types that may be returned by XMREventDequeue(),​ to let the runtime know that the script is capable of processing that event type.  Otherwise, the event may not be queued to the script.
 +\\     
 +\\
 +==== Event codes: ====   
 +<code ossl>
 +       ​XMREVENTCODE_attach
 +       ​XMREVENTCODE_state_exit
 +       ​XMREVENTCODE_timer
 +       ​XMREVENTCODE_touch
 +       ​XMREVENTCODE_collision
 +       ​XMREVENTCODE_collision_end
 +       ​XMREVENTCODE_collision_start
 +       ​XMREVENTCODE_control
 +       ​XMREVENTCODE_dataserver
 +       ​XMREVENTCODE_email
 +       ​XMREVENTCODE_http_response
 +       ​XMREVENTCODE_land_collision
 +       ​XMREVENTCODE_land_collision_end
 +       ​XMREVENTCODE_land_collision_start
 +       ​XMREVENTCODE_at_target
 +       ​XMREVENTCODE_listen
 +       ​XMREVENTCODE_money
 +       ​XMREVENTCODE_moving_end
 +       ​XMREVENTCODE_moving_start
 +       ​XMREVENTCODE_not_at_rot_target
 +       ​XMREVENTCODE_not_at_target
 +       ​XMREVENTCODE_touch_start
 +       ​XMREVENTCODE_object_rez
 +       ​XMREVENTCODE_remote_data
 +       ​XMREVENTCODE_at_rot_target
 +       ​XMREVENTCODE_run_time_permissions
 +       ​XMREVENTCODE_touch_end
 +       ​XMREVENTCODE_state_entry
 +       ​XMREVENTCODE_changed
 +       ​XMREVENTCODE_link_message
 +       ​XMREVENTCODE_no_sensor
 +       ​XMREVENTCODE_on_rez
 +       ​XMREVENTCODE_sensor
 +       ​XMREVENTCODE_http_request
 +</​code>​
 +\\
 +\\
 +==== Event masks: ====
 +<code ossl>
 +       ​XMREVENTMASK1_attach
 +       ​XMREVENTMASK1_state_exit
 +       ​XMREVENTMASK1_timer
 +       ​XMREVENTMASK1_touch
 +       ​XMREVENTMASK1_collision
 +       ​XMREVENTMASK1_collision_end
 +       ​XMREVENTMASK1_collision_start
 +       ​XMREVENTMASK1_control
 +       ​XMREVENTMASK1_dataserver
 +       ​XMREVENTMASK1_email
 +       ​XMREVENTMASK1_http_response
 +       ​XMREVENTMASK1_land_collision
 +       ​XMREVENTMASK1_land_collision_end
 +       ​XMREVENTMASK1_land_collision_start
 +       ​XMREVENTMASK1_at_target
 +       ​XMREVENTMASK1_listen
 +       ​XMREVENTMASK1_money
 +       ​XMREVENTMASK1_moving_end
 +       ​XMREVENTMASK1_moving_start
 +       ​XMREVENTMASK1_not_at_rot_target
 +       ​XMREVENTMASK1_not_at_target
 +       ​XMREVENTMASK1_touch_start
 +       ​XMREVENTMASK1_object_rez
 +       ​XMREVENTMASK1_remote_data
 +       ​XMREVENTMASK1_at_rot_target
 +       ​XMREVENTMASK1_run_time_permissions
 +       ​XMREVENTMASK1_touch_end
 +       ​XMREVENTMASK1_state_entry
 +       ​XMREVENTMASK2_changed
 +       ​XMREVENTMASK2_link_message
 +       ​XMREVENTMASK2_no_sensor
 +       ​XMREVENTMASK2_on_rez
 +       ​XMREVENTMASK2_sensor
 +       ​XMREVENTMASK2_http_request
 +</​code>​
 +
 +**Example 1**
 +<code ossl>
 +   ​yoption advflowctl;
 +   ​yoption trycatch;
 +   
 +   ​default {
 +       ​state_entry ()
 +       {
 +           /*
 +            * Send request to a webserver.
 +            */
 +           key reqid = llHTTPRequest ("​http://​dreamnation.net/",​ [], ""​);​
 +   
 +           /*
 +            * Wait here up to 30 seconds for the reply.
 +            * If any other events come in meanwhile, process them as background ​
 +            * calls.
 +            */
 +           while (1) {
 +               list reply = xmrEventDequeue (30.0, XMREVENTMASK1_http_response, ​
 +                                             0, -1, -1);
 +   
 +               if (llGetListLength (reply) == 0) {
 +                   ​llOwnerSay ("​timed out waiting for reply"​);​
 +                   ​break;​
 +               }
 +   
 +               ​integer eventcode = (integer)reply[0];​
 +               if (eventcode != XMREVENTCODE_http_response) {
 +                   // fatal error - should never happen
 +                   throw "bad event code " + eventcode;
 +               }
 +               key request_id = (key)reply[1];​
 +               if (request_id != reqid) {
 +                   // got reply for somthing else, ignore and look again
 +                   ​continue;​
 +               }
 +               ​integer status ​  = (integer)reply[2];​
 +               ​list ​   metadata = (list)reply[3];​
 +               ​string ​ body     = (string)reply[4];​
 +               ​llOwnerSay ("​reply body: " + body);
 +               ​break;​
 +           }
 +       }
 +   
 +       /*
 +        * This dummy event handler must be present so the runtime knows this script ​
 +        * can handle http_response events.
 +        */
 +       ​http_response (key request_id, integer status, list metadata, string body)
 +       {
 +           throw "​should never get here";
 +       }
 +   
 +       /*
 +        * These event handlers will get called by xmrEventDequeue if the event is 
 +        * received while waiting for the reply from the webserver.
 +        *
 +        * They also get called normally once the start_entry() event handler ​
 +        * completes.
 +        */
 +       ​touch_start (integer num_detected)
 +       {
 +           ​llOwnerSay ("​touched!"​);​
 +       }
 +       ​changed (integer change)
 +       {
 +           ​llOwnerSay ("​changed!"​);​
 +       }
 +   }
 +</​code>​
 +\\
 +\\
 +**Example 2**
 +<code ossl>
 +   ​yoption advflowctl;
 +   ​yoption trycatch;
 +   
 +   ​default {
 +       ​state_entry ()
 +       {
 +           /*
 +            * Tell runtime to queue all messages on channel 0 to us.
 +            */
 +           ​llListen (0, "",​ NULL_KEY, ""​);​
 +   
 +           while (1) {
 +   
 +               /*
 +                * Tell xmrEventDequeue() to wait up to 5 seconds per call for one 
 +                * of the events listed in the rm1,rm2 arguments. ​ Meanwhile, if 
 +                * any events listed in the bm1,bm2 arguments are received, process ​
 +                * them via the normal event handlers.
 +                */
 +               list ev = xmrEventDequeue (5.0, 
 +                       ​XMREVENTMASK1_touch_start | XMREVENTMASK1_listen, ​
 +                       ​XMREVENTMASK2_changed, ​
 +                       -1, -1);  // -1,-1 means everything else
 +               if (llGetListLength (ev) == 0) {
 +                   ​llOwnerSay ("​nothing happened in the past five seconds"​);​
 +                   ​continue;​
 +               }
 +               ​integer eventcode = (integer)ev[0];​
 +               ​switch (eventcode) {
 +                   case XMREVENTCODE_touch_start:​ {
 +                       ​integer num_detected = (integer)ev[1];​
 +                       ​llOwnerSay ("​touched " + num_detected + " time(s)"​);​
 +                       ​break;​
 +                   }
 +                   case XMREVENTCODE_listen:​ {
 +                       ​integer channel = (integer)ev[1];​
 +                       ​string ​ name    = (string)ev[2];​
 +                       ​key ​    ​id ​     = (key)ev[3];
 +                       ​string ​ message = (string)ev[4];​
 +                       ​llOwnerSay ("​Heard from " + name + "​("​ + id + ") on " + 
 +                               ​channel + ": " + message);
 +                       ​break;​
 +                   }
 +                   case XMREVENTCODE_changed:​ {
 +                       ​integer change = (integer)ev[1];​
 +                       ​llOwnerSay ("​something changed: " + change);
 +                       ​break;​
 +                   }
 +                   ​default:​ {
 +                       // fatal error - should never happen
 +                       throw "​don'​t know why I got event " + eventcode;
 +                   }
 +               }
 +           }
 +       }
 +   
 +       /*
 +        * These dummy handlers must be present so the runtime knows the script ​
 +        * wants these events to be queued to the script. ​ But they never get 
 +        * called because the xmrEventDequeue() has them listed in its rm1,​rm2 ​
 +        * mask arguments.
 +        */
 +       ​touch_start (integer num_detected)
 +       {
 +           throw "​should never get to the regular touch_start() handler";​
 +       }
 +       ​listen (integer channel, string name, key id, string message)
 +       {
 +           throw "​should never get to the regular listen() handler";​
 +       }
 +       ​changed (integer change)
 +       {
 +           throw "​should never get to the regular changed() handler";​
 +       }
 +   
 +       /*
 +        * Since this event is not listed in the rm1,rm2 arguments but is listed in 
 +        * the bm1,bm2 arguments, it will be called normally in the background by 
 +        * xmrEventDequeue() whenever this event is received.
 +        */
 +       ​collision_start (integer num_detected)
 +       {
 +           ​llOwnerSay ("​collided with " + num_detected + " thing(s)"​);​
 +       }
 +   }
 +</​code>​
 +
 +==== Queue an event to the calling script ====
 +<code ossl>
 +   ​xmrEventEnqueue (list ev)
 +       ev = event to be enqueued, see xmrEventCallHandler()
 +</​code>​
 +\\
 +Note:
 + The event is queued to execute along with any other events that might be pending, subject to event queuing limits, and executes after the current event handler completes. ​ Contrast with xmrEventCallHandler(),​ which directly calls the event handler immediately.
 +
 +==== Load current detect params from a list ====
 +<code ossl>
 +   ​xmrEventLoadDets (list dp)
 +       dp = as returned by xmrEventSaveDets()
 +</​code>​
 +==== Save current detect params into a list ====
 +<code ossl>
 +   list xmrEventSaveDets ()
 +       ​returns list giving detect params for current event
 +</​code>​
QR Code
QR Code wiki:scripting_portal:inline_events (generated for current page)