Combined LockMeister Handle Post and Collar

From Second Life Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

LockMeister+ Handles, Posts and Collar

Overview

The LockMeister system protocol for cuffs, collars and leash handles has been around from many years and in that time a number of extensions to the protocol have been added and have been documented.

LockMeister+ is an effort to bring together those extensions and define a set of expected behaviours to allow greater interoperability and functionality between devices that use the extended protocol. The aims of LockMeister+ are:

  • To gather up the existing extensions into a new extended protocol.
  • To add functionality that can be gained from combining those extensions.
  • To define the expected behaviour for a number if classes of devices.
  • To be 100% backwards compatible with what has gone before.

The LockMeister+ Handle reference script

The LockMeister+ Handle:

  • MUST respond to basic "handle" messages with an "ok".
  • MUST implement the "here" and "gone" messages.

<lsl>/////////////////////////////////////////////////////////////////////// // // Lockmeister+ Handle Reference Script // // Tianna Violet // 20 Jan 2010 // // http://wiki.secondlife.com/wiki/LSL_Protocol/LockMeister_System // // Note that this script will only work in the ROOT PRIM ONLY as it // uses an "attach" event which aren't handled properly in child prims. /////////////////////////////////////////////////////////////////////// // The lockmeister name of the handle. string LOCKMEISTER_NAME = "handle"; /////////////////////////////////////////////////////////////////////// string gCuffMessage;

default {

   state_entry()
   {
       gCuffMessage = (string) llGetOwner() + LOCKMEISTER_NAME;
       llListen(-8888, "", NULL_KEY, "");
   }
   attach(key id)
   {
       string message;
       message = " gone";
       if (id)
       {
           gCuffMessage = (string) llGetOwner() + LOCKMEISTER_NAME;
           message = " here";
       }
       llSay(-8888, gCuffMessage + message);	// send the "here" and "gone" message
   }
   listen(integer channel, string name, key id, string message)
   {
       if (message == gCuffMessage)
       {
           llSay(-8888, gCuffMessage + " ok");	// the basic response
           return;
       }
   }

} </lsl>

The LockMeister+ Post reference script

The LockMeister+ Post:

  • MUST send a "posk ok" message when the post is touched the key being the toucher's UUID
  • MUST respond to basic "handle" messages where the message key is its own UUID with an "ok".
  • SHOULD contain 'post' in its name and script SHOULD be in the root prim so that a post that is found through a scan of nearby objects can be confirmed as a LockMeister+ post.

<lsl>/////////////////////////////////////////////////////////////////////// // // Lockmeister+ Post Reference Script // // Tianna Violet // 21 Jan 2010 // // http://wiki.secondlife.com/wiki/LSL_Protocol/LockMeister_System /////////////////////////////////////////////////////////////////////// // The lockmeister name of the leash. string LOCKMEISTER_NAME = "handle"; ///////////////////////////////////////////////////////////////////////

default {

   state_entry()
   {
       llListen(-8888, "", NULL_KEY, "");
   }
   touch_start(integer total_number)
   {
       llSay(-8888, (string) llDetectedKey(0) + "post ok");
   }
   listen(integer channel, string name, key id, string message)
   {
       string postMessage;
       postMessage = (string) llGetKey() + LOCKMEISTER_NAME;
       if (message == postMessage)
       {
           llSay(-8888, postMessage + " ok");
           return;
       }
   }

} </lsl>

The LockMeister+ Collar reference script

The LockMeister+ Collar:

  • MUST look for a handle using the basic LockMeister query/response.
  • MUST monitor "here" messages in order to connect to a handle should it appear.
  • MUST monitor the "gone" event to remove the leash should the handle disappear.
  • MUST send out new target requests should the current handle disappear.
  • MUST support the "post ok" message and basic query/response to the post.
  • SHOULD support basic LockMeister query/responses for the "collar" attach point.
  • SHOULD reconnect the leash when the AV logs on if the attach point is still available.
  • SHOULD support one touch transfer of the leash from the leash holder to a post.
  • SHOULD support one touch transfer of the leash from a post to an AV with leash access.

<lsl>/////////////////////////////////////////////////////////////////////// // // Lockmeister+ Collar Reference Script // // Tianna Violet // 31 Jan 2010 // // http://wiki.secondlife.com/wiki/LSL_Protocol/LockMeister_System // // the collar reponds on channel 53 // // /53xxleash - grab the leash // /53xxunleash - unleash // /53xxleashpost - leash to a previously touch post // // xx = the initials of the wearer or * to effect all collars // // Note that this script will only work in the ROOT PRIM ONLY as it // uses an "attach" event which aren't handled properly in child prims. /////////////////////////////////////////////////////////////////////// // The lockmeister name of the collar. string LOCKMEISTER_NAME = "collar"; string gCuffMessage; key gLeashHolder; key gCurrentTarget; key gPostToucher; key gPost; key gPending; integer isLeashed; string gPrefix;


// Who has access to the collar // This is where the owner list etc is checked integer hasAccess(key id) {

   return TRUE;    // everyone has access

}

// Start or update the particle stream updateParticles() {

   llParticleSystem( [PSYS_PART_START_SCALE, <0.1, 0.1, 0>, PSYS_PART_END_SCALE, <1, 1, 0>,
       PSYS_PART_START_COLOR, <1, 1, 1>, PSYS_PART_END_COLOR, <1, 1, 1>,
       PSYS_PART_START_ALPHA, 1.0, PSYS_PART_END_ALPHA, 1.0,
       PSYS_SRC_TEXTURE, "1ffb37fa-2fc1-dbec-d8ea-0607583a03c6",
       PSYS_SRC_BURST_PART_COUNT, 1, PSYS_SRC_BURST_RATE, 0.0, PSYS_PART_MAX_AGE, 2,
       PSYS_SRC_MAX_AGE, 0.0, PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_DROP, PSYS_SRC_BURST_RADIUS, 0.5,
       PSYS_SRC_INNERANGLE, 0.0, PSYS_SRC_OUTERANGLE, 0.0, PSYS_SRC_OMEGA, <0, 0, 0>,
       PSYS_SRC_ACCEL, <0, 0, -0.7>, PSYS_SRC_BURST_SPEED_MIN, 1000.0,
       PSYS_SRC_BURST_SPEED_MAX, 1000.0, PSYS_SRC_TARGET_KEY, gCurrentTarget,
       PSYS_PART_FLAGS, PSYS_PART_FOLLOW_VELOCITY_MASK | PSYS_PART_FOLLOW_SRC_MASK | PSYS_PART_TARGET_POS_MASK]);

}

setPrefix() {

   list l;
   l = llParseString2List(llToLower(llKey2Name(llGetOwner())), [" "], []);
   gPrefix = llGetSubString(llList2String(l, 0), 0, 0) + llGetSubString(llList2String(l, 1), 0, 0);

}

releash() {

   if (isLeashed)
   {
       if (gLeashHolder)
       {
           llSensor("", gLeashHolder, AGENT, 30.0, PI);
       } else {
           gPending = gCurrentTarget;
           llSay(-8888, ((string) gPending + "handle"));
       }
       llParticleSystem([]);
       isLeashed = 0;
       gLeashHolder = NULL_KEY;
       gCurrentTarget = NULL_KEY;
   }

}

default {

   state_entry()
   {
       gLeashHolder = NULL_KEY;
       gCurrentTarget = NULL_KEY;
       gPostToucher = NULL_KEY;
       gPost = NULL_KEY;
       gPending = NULL_KEY;
       isLeashed = 0;
       setPrefix();
       gCuffMessage = (string) llGetOwner() + LOCKMEISTER_NAME;
       llListen(-8888, "", NULL_KEY, "");
       llListen(53, "", NULL_KEY, "");
   }
   listen(integer channel, string name, key id, string message)
   {
       list commands = ["leash", "unleash", "leashpost"];
       list responses = ["handle ok", "handle here", "handle gone", "post ok"];
       key target;
       integer index;
       integer len;
       if (channel == 53 && hasAccess(id))
       {
           message = llStringTrim(llToLower(message), STRING_TRIM);
           index = -1;
           if (llGetSubString(message, 0, 0) == "*")
           {
               index = 1;
           } else {
               len = llStringLength(gPrefix);
               if (llGetSubString(message, 0, len - 1) == gPrefix)
               {
                   index = len;
               }
           }
           if (~index)
           {
               index = llListFindList(commands, [llGetSubString(message, index, -1)]);
           }
           if (~index)
           {
               gPending = NULL_KEY;
               if (!index)
               {
                   if (gLeashHolder == NULL_KEY)
                   {
                       gLeashHolder = id;
                       gCurrentTarget = id;
                       isLeashed = 1;
                       updateParticles();
                       llSay(-8888, ((string) id) + "handle");
                       gPending = id;
                   }
               }
               if (gLeashHolder == NULL_KEY || gLeashHolder == id)
               {
                   if (index == 1)
                   {
                       gLeashHolder = NULL_KEY;
                       isLeashed = 0;
                       llParticleSystem([]);
                   }
                   if (index == 2)
                   {
                       if (gPost != NULL_KEY && gPost != gCurrentTarget && gPostToucher == id)
                       {
                           llSay(-8888, ((string) gPost) + "handle");
                           gPending = gPost;
                       }
                   }
               }
           }
       }
       if (channel == -8888)
       {
           if (message == gCuffMessage)
           {
               llSay(-8888, gCuffMessage + " ok");    // the basic response
               return;
           }
           target = (key) llGetSubString(message, 0, 35);
           if (target)
           {
               index = llListFindList(responses, [llGetSubString(message, 36, -1)]);
               if (~index)
               {
                   if (!index && target == gPending)
                   {
                       gCurrentTarget = id;
                       isLeashed = 1;
                       if (id == target)
                       {
                           gLeashHolder = NULL_KEY;
                       }
                       gPending = NULL_KEY;
                       updateParticles();
                   }
                   if (target == gLeashHolder)
                   {
                       if (index == 1 && gCurrentTarget != id)
                       {
                           gCurrentTarget = id;
                           isLeashed = 1;
                           gPending = NULL_KEY;
                           updateParticles();
                       }
                       if (index == 2 && gCurrentTarget == id)
                       {
                           releash();
                       }
                   }
                   if (index == 3)
                   {
                       if (target == gLeashHolder || (gLeashHolder == NULL_KEY && hasAccess(target)))
                       {
                           gPostToucher = target;
                           gPost = id;
                           if (gPost != gCurrentTarget)
                           {
                               if (gLeashHolder != NULL_KEY)
                               {
                                   gLeashHolder = NULL_KEY;
                                   gCurrentTarget = gPost;
                                   isLeashed = 1;
                                   gPending = NULL_KEY;
                                   updateParticles();
                               }
                           } else {
                               gLeashHolder = target;
                               gCurrentTarget = target;
                               isLeashed = 1;
                               updateParticles();
                               gPending = target;
                               llSay(-8888, ((string) target) + "handle");
                           }
                       }
                   }
               }
           }
       }
   }
   attach(key id)
   {
       string message;
       message = " gone";
       if (id)
       {
           gCuffMessage = (string) llGetOwner() + LOCKMEISTER_NAME;
           message = " here";
           if (isLeashed)
           {
               releash();
           }
       }
       llSay(-8888, gCuffMessage + message);    // send the "here" and "gone" message
   }
   sensor(integer total_number)
   {
       gLeashHolder = llDetectedKey(0);
       gCurrentTarget = gLeashHolder;
       isLeashed = 1;
       updateParticles();
       llSay(-8888, ((string) gLeashHolder) + "handle");
       gPending = gLeashHolder;
   }
   on_rez(integer start_param)
   {
       setPrefix();
   }

} </lsl>