Difference between revisions of "Combined LockMeister Handle Post and Collar"
(Created page with '{{LSL Header}} == LockMeister+ Handles, Posts and Collar == === Overview === The LockMeister system protocol for cuffs, collars and leash h...') |
|||
Line 40: | Line 40: | ||
default | 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> | </lsl> | ||
Line 93: | Line 93: | ||
default | 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> | </lsl> | ||
Line 166: | Line 166: | ||
integer hasAccess(key id) | integer hasAccess(key id) | ||
{ | { | ||
return TRUE; // everyone has access | |||
} | } | ||
Line 172: | Line 172: | ||
updateParticles() | 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() | setPrefix() | ||
{ | { | ||
list l; | |||
l = llParseString2List(llToLower(llKey2Name(llGetOwner())), [" "], []); | |||
gPrefix = llGetSubString(llList2String(l, 0), 0, 0) + llGetSubString(llList2String(l, 1), 0, 0); | |||
} | } | ||
releash() | 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 | 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 (gLeashHolder != NULL_KEY && gPost != gCurrentTarget) | |||
{ | |||
gLeashHolder = NULL_KEY; | |||
gCurrentTarget = gPost; | |||
isLeashed = 1; | |||
gPending = NULL_KEY; | |||
updateParticles(); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
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> | </lsl> |
Revision as of 12:34, 31 January 2010
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
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.
<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 (gLeashHolder != NULL_KEY && gPost != gCurrentTarget) { gLeashHolder = NULL_KEY; gCurrentTarget = gPost; isLeashed = 1; gPending = NULL_KEY; updateParticles(); } } } } } }
}
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>