LSL Protocol/Teleport Helper Protocol

From Second Life Wiki
Jump to navigation Jump to search

Teleport Helper Protocol

A protocol that fixes the limitations in the llTeleportAgent* functions, avoids broken content, and blocks any possible abuse.

   Useful for : Star Gates, Quantum Portals, Teleporter Platforms, Tours, etc...

The purpose of this protocol is to allow land owners to teleport visitors without the visitors needing to sit on objects.

The new Linden teleport functions are fantastic but they only work on the script's owner.

To make the new teleport functions useful they need to work on people who are visiting your land, while blocking any possibility for abuse.

The way to do this is to wear a script which will teleport you on request, while still asking you before doing so.

If enough people include this script into their HUDs, hair, shoes, etc the Linden teleport commands will become useful everywhere.

Details:-

   This script will listen on channel 86400000 for the teleport command. (and other commands as the protocol is expanded)
   command format "teleport[region_name~region_position~look_at_position]"
           region_name : is the plain text name of the target region
           region_position : is a vector for the local position in the region, <0-255, 0-255, 0-4096>
           look_at_position : is a vector for the position the avatar should be turned to face, <0-255, 0-255, 0>. 
           eg:  llRegionSayTo(AvatarUUID,86400000,"teleport[quantum~<128, 128, 500>~<0, 128, 0>]");

Note:

The ~ character is used as a field delimiter because it is not used by any variables, such as the comma in a vector, or the pipe in some chat commands.

Commands are a single word with their parameters enclosed in the [] brackets. Additional parameters may be added so long as they are added to the end of the existing parameters. eg: delete[object name] or teleport[quantum~<128, 128, 500>~<0, 128, 0>]]

llWhisper(), llSay(), llShout(), and llRegionSay() can all be used to deliver the teleport[] command to groups of people. While llRegionSayTo() is proffered for sending the command to one person only.


Features:-

   Only works if the request comes from an object owned by the land owner. Group owned land requires group owned objects.
   Limit of one teleport per minute to avoid spamming.
   Permissions are dropped after use.
   Only one teleport is offered, regardless of how many copies of the script is worn.


To Do:-

   Make this page look nice with some formatting
   Delete[object_name] Delete the script from the named object so people can remove duplicates they know they will never need. Must check that the owner send this command.
   Expand this script to support any other protocols that are used in custom products, such as some star gates.

<lsl>

vector global_coordinates;
vector region_coordinates;
vector look_at;
integer Priority;
integer Active = TRUE; // Default is Active
key reqID;
default
{
   on_rez(integer param)
   {
       llResetScript();
   }
   attach(key id)
   {
       if (id == NULL_KEY) llRegionSayTo(llGetOwner(),86400000,"1"); // on detach try to re-enable other scripts that may be inActive
   }
   state_entry()
   {
       llListen(86400000,"","",""); // used to receive teleport commands and set controller priority
       Priority = (integer)((llFrand(10000)*10000)+2); // Pick a Priority
       llRegionSayTo(llGetOwner(),86400000,(string)Priority); // share the Priority
   }
   listen(integer channel, string name, key id, string message)
   {
       if ((integer)message > 0) // Priority received
       {
           if ((integer)message > Priority) // compare my Priority with received one
           {
               Active = FALSE; // set inActive because I have a lower priority
               return;
           }
           else 
           {
               Active = TRUE; // set Active because I have a higher priority
               llRegionSayTo(llGetOwner(),86400000,(string)Priority); // share my higher priority to set other script(s) inActive
               return;
           }
       }
       
       if ((llSubStringIndex(message,"teleport[") == 0) && (Active == TRUE)) // teleport command & Active Mode
       {
           if (llGetLandOwnerAt(llGetPos()) != llGetOwnerKey(id)) return; // must come from owner of land under avatar
           list command =  llParseString2List(message,["teleport[","~","]"],[]); // extract destination details
           region_coordinates = (vector)llList2String(command,1); // save destination position
           look_at = (vector)llList2String(command,2); // save look at position
           reqID = llRequestSimulatorData(llList2String(command,0), DATA_SIM_POS); // request region position
           return;
       }
   }
   
   dataserver(key query_id, string data)
   {
       if (reqID != query_id) return; // filter out irralavant queries
       global_coordinates = (vector)data; // save region position
       llRequestPermissions(llGetOwner(), PERMISSION_TELEPORT); // request permission to teleport
       // Active = FALSE; // Optional to avoid spamming additional permission requests when the last one wasn't answered
   }
   
   run_time_permissions(integer perm)
   {
       if (perm & PERMISSION_TELEPORT)
       {
           llUnSit(llGetOwner()); // sitting avatar will not teleport
           llTeleportAgentGlobalCoords( llGetOwner(), global_coordinates, region_coordinates, look_at); // teleport
           // avoid teleport spam by resetting after a pause
           llSleep(60); 
           llResetScript(); 
       }
   }
}

</lsl>