Difference between revisions of "MLPV2 RLV Plugin"

From Second Life Wiki
Jump to navigation Jump to search
(Version 1.02)
Line 7: Line 7:


<lsl>// ----------------------------------------------------------------------------------
<lsl>// ----------------------------------------------------------------------------------
// MLPV2 Plugin for RLV Script V1.0
// MLPV2 Plugin for RLV Script V1.02
//
//
// Use with a notecard named .RLV with the format:
// Use with a notecard named .RLV with the format:
Line 13: Line 13:
// e.g.
// e.g.
// Missionary|1|@unsit=n
// Missionary|1|@unsit=n
// stand|*|!release
// ----------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------
// Copyright (c) 2010, Jenni Eales. All rights reserved.
// Copyright (c) 2010, Jenni Eales. All rights reserved.
Line 40: Line 41:
// Changes:
// Changes:
// ----------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------
// Version 1.02
// - use | as seperator
// - support multiple lines for one pose
// - additional link message for direct call from ball menu
//
// Version 1.01
// Version 1.01
// - use ; instead of | as seperator
// - use ; instead of | as seperator
//  
//
// Version 1.0
// Version 1.0
// - first version released
// - first version released
Line 48: Line 54:
//
//
// constants
// constants
string NOTECARD        = ".RLV";
string NOTECARD        = ".RLV"; // name of config notecard
integer DEBUG          = FALSE;
integer DEBUG          = FALSE; // switch debug on/off
integer RELAY_CHANNEL  = -1812221819;
integer RELAY_CHANNEL  = -1812221819; // channel for RLV relay
float TIMER_SEC        = 1800.0; // 30 min.
float TIMER_SEC        = 1800.0; // 30 min.
string CMD_RELEASE      = "!release";
string CMD_RELEASE      = "!release"; // release command
 
integer LM_NUMBER      = -1819;  // number for link message
// internal use
// internal use
key kQuery;
key kQuery;
integer iLine;
integer iLine;


string pose = "stand";
string pose = "stand"; // pose set by the Ball Menu
list poses    = [];
list poses    = [];   // configured poses
list balls    = [];
list balls    = [];   // configured balls
list commands = [];
list commands = [];   // configured commands
list avatars  = [NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY];
list avatars  = [];   // avatars sitting on balls


// log a message
// log a message
log(string message)
log(string message)
{
{
    if(DEBUG) llOwnerSay(message);
if(DEBUG) llOwnerSay(message);
}
 
// only for testing purposes
log_data()
{
log("List:");
integer total_number = llGetListLength(commands);
integer i;
for(i=0; i<total_number; i++)
{
log("- " + llList2String(poses, i) + ": (" + llList2String(balls, i) + ") "+ llList2String(commands, i));
}
}
}


Line 73: Line 92:
relay(key avatar, string message)
relay(key avatar, string message)
{
{
    log("RLV: MLPV2," + (string) avatar + "," + message);
list tokens = llParseString2List(message, ["|"], [""]);
    llSay(RELAY_CHANNEL, "MLPV2," + (string) avatar + "," + message);
integer total_number = llGetListLength(tokens);
integer i;
for(i=0; i<total_number; i++)
{
string token = llList2String(tokens, i);
log("RLV: MLPV2," + (string) avatar + "," + token);
llSay(RELAY_CHANNEL, "MLPV2," + (string) avatar + "," + token);
}
}
}


Line 80: Line 106:
rlv(string pose)
rlv(string pose)
{
{
    log("command for " + pose);
log("command for: " + pose);
    llSetTimerEvent(TIMER_SEC);
llSetTimerEvent(TIMER_SEC);


    // get index for pose in poses
integer total_number = llGetListLength(poses);
    integer index = llListFindList(poses, [pose]);
integer i;
    if (index == -1) return;
for(i=0; i<total_number; i++)
{
if (pose == llList2String(poses, i))
{
string ball = llList2String(balls, i);
log("command for pose: " + pose + " (" + ball + ")");
if (ball == "*")
{
integer b;
for (b=0; b<6; b++)
{
// get avatar for ball index
key avatar = llList2Key(avatars, b);
if(avatar != NULL_KEY) relay(avatar, llList2String(commands, i));
}
}
else
{
key avatar = llList2Key(avatars, (integer) ball);
if(avatar != NULL_KEY) relay(avatar, llList2String(commands, i));
}
}
}
}


    // get command from entries
// new find: pose and ball needs to match
    string command = llList2String(commands, index);
integer find_pose(string pose, string ball)
{
integer total_number = llGetListLength(poses);
integer i;
for(i=0; i<total_number; i++)
{
if (pose == llList2String(poses, i) && ball == llList2String(balls, i))
{
return i;
}
}
return -1;
}


    // get ball from balls
// add a pose/ball/command entry
    string ball = llList2String(balls, index);
add_pose(string pose, string ball, string command)
 
{
    if (ball == "*")
// look for existing entry for pose
    {
integer found = find_pose(pose, ball);
        integer i;
if (found == -1)
        for (i=0; i<6; i++)
{
        {
// add a new pose
            // get avatar for ball index
poses += [pose];
            key avatar = llList2Key(avatars, i);
balls += [ball];
commands += [command];


            // if not null send command
log("Added from " + NOTECARD + ": " + pose + " | " + ball + " | " + command);
            if(avatar != NULL_KEY)
}
            {
else
                relay(avatar, command);
{
            }
// append to existing pose
        }
string c = llList2String(commands, found) + "|" + command;
    }
commands = llListReplaceList(commands, [c], found, found);
    else
    {
        // get avatar for ball index
        key avatar = llList2Key(avatars, (integer) ball);


        // if not null send command
log("Added " + command + " to pose " + pose);
        if(avatar != NULL_KEY)
}
        {
            relay(avatar, command);
        }
    }
}
}


Line 124: Line 178:
process_line(string line)
process_line(string line)
{
{
    list tokens = llParseString2List(line, [";"], [""]);
list tokens = llParseString2List(line, [" |  ","  | "," |  "," | "," |","| ","|"],[""]);
    if(llGetListLength(tokens) != 3) return;
if(llGetListLength(tokens) < 3) return;


    string pose = llList2String(tokens, 0);
string pose = llList2String(tokens, 0);
    string ball = llList2String(tokens, 1);
string ball = llList2String(tokens, 1);
    string command = llList2String(tokens, 2);


    poses += [pose];
integer total_number = llGetListLength(tokens);
    balls += [ball];
integer i;
    commands += [command];
for(i=2; i<total_number; i++)
 
{
    log("Added from " + NOTECARD + ": " + pose + " ; " + ball + "  ; " + command);
add_pose(pose, ball, llList2String(tokens, i));
}
}
}


// check if object is in the inventory
// check if object is in the inventory
integer exists_notecard(string notecard) {
integer exists_notecard(string notecard) {
    return llGetInventoryType(notecard) == INVENTORY_NOTECARD;
return llGetInventoryType(notecard) == INVENTORY_NOTECARD;
}
}


// initialize me
// initialize me
reset()
initialize()
{
{
    poses = [];
log("Initializing...");
    balls = [];
poses = [];
    commands = [];
balls = [];
    avatars = [NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY];
commands = [];
    log("Reset");
avatars = [NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY];


    if (exists_notecard(NOTECARD))
if (exists_notecard(NOTECARD))
    {
{
        log("Reading " + NOTECARD + "...");
log("Reading " + NOTECARD + "...");
        iLine = 0;
iLine = 0;
        kQuery = llGetNotecardLine(NOTECARD, iLine);
kQuery = llGetNotecardLine(NOTECARD, iLine);
    }
}
    else
else
    {
{
        llOwnerSay("Not found: " + NOTECARD );
llOwnerSay("Not found: " + NOTECARD );
    }
}
}
}


default
default
{
{
    state_entry()
// on state entry initialize me
    {
state_entry()
        reset();
{
    }
initialize();
}
 
// reset on Inventory change
changed(integer change)
{
if (change & CHANGED_INVENTORY) initialize();
}


    // reset on Inventory change
// read a line from notecard
    changed(integer change)
dataserver(key _query_id, string _data) {
    {
// were we called to work on notecard?
        if (change & CHANGED_INVENTORY) {
if (_query_id == kQuery) {
            reset();
// this is a line of our notecard
        }
if (_data == EOF) {
    }
if (DEBUG) log_data();
log(NOTECARD + " read.");
} else {
// increment line count
// data has the current line from this notecard
if(_data != "") {
process_line(_data);
}


    // read a line from notecard
// request next line
    dataserver(key _query_id, string _data) {
// read another line when you can
        // were we called to work on notecard?
iLine++;
        if (_query_id == kQuery) {
kQuery = llGetNotecardLine(NOTECARD, iLine);
            // this is a line of our notecard
}
            if (_data == EOF) {
}
                log(NOTECARD + " read.");
}
            } else {
                    // increment line count
                    // data has the current line from this notecard
                    if(_data != "") {
                        process_line(_data);
                    }


                // request next line
timer()
                // read another line when you can
{
                iLine++;
integer b;
                kQuery = llGetNotecardLine(NOTECARD, iLine);
for (b=0; b<6; b++)
            }
{
        }
// get avatar for ball index
    }
key avatar = llList2Key(avatars, b);


    timer()
// if not null send command
    {
if(avatar != NULL_KEY) relay(avatar, CMD_RELEASE);
        integer i;
}
        for (i=0; i<6; i++)
llSetTimerEvent(0.0);
        {
}
            // get avatar for ball index
            key avatar = llList2Key(avatars, i);


            // if not null send command
// link message from MLPV2
            if(avatar != NULL_KEY)
link_message(integer sender_number, integer number, string message, key id)
            {
{
                relay(avatar, CMD_RELEASE);
// pose from ball menu selected
            }
if (number == 0 && message == "POSEB") {
        }
pose = (string)id;
        llSetTimerEvent(0.0);
rlv(pose);
    }
return;
}


    // link message from MLPV2
// direct call from ball menu
    link_message(integer sender_number, integer number, string message, key id)
// configure in .MENUITEMS with
    {
// LINKMSG Resctriction | 0,-1,-1819,Restriction
        if (number == 0 && message == "POSEB") {
if (number == LM_NUMBER) {
            pose = (string)id;
pose = message;
            rlv(pose);
rlv(pose);
            return;
return;
        }
}


        // unsit avatar
// unsit avatar
        if (number == -11001)
if (number == -11001)
        {
{
            integer ball = (integer) message;
integer ball = (integer) message;
            log("Avatar unsit from ball " + (string) ball +": " + (string) llList2Key(avatars, ball));
log("Avatar unsit from ball " + (string) ball +": " + (string) llList2Key(avatars, ball));
            relay(llList2Key(avatars, ball), CMD_RELEASE);
relay(llList2Key(avatars, ball), CMD_RELEASE);
            avatars = llListReplaceList(avatars, [NULL_KEY], ball, ball);
avatars = llListReplaceList(avatars, [NULL_KEY], ball, ball);
        }
}


        // sit avatar
// sit avatar
        if (number == -11000)
if (number == -11000)
        {
{
            list tokens = llParseString2List(message, ["|"], [" "]);
list tokens = llParseString2List(message, ["|"], [" "]);
            integer ball = llList2Integer(tokens, 0);
integer ball = llList2Integer(tokens, 0);
            log("Avatar sit on ball " + (string) ball +": " + (string) id);
log("Avatar sit on ball " + (string) ball +": " + (string) id);
            avatars = llListReplaceList(avatars, [id], ball, ball);
avatars = llListReplaceList(avatars, [id], ball, ball);
            rlv(pose);
rlv(pose);
        }
}
    }
}
}</lsl>
}</lsl>


The .RLV notecard might be look like this:
The .RLV notecard might be look like this:


  Trapped;0;@unsit=n
  Trapped | 0 | @unsit=n
  Strip;0;@remoutfit:undershirt=force|@remoutfit:underpants=force|@remoutfit:shirt=force|@remoutfit:pants=force|@remoutfit:socks=force
  Strip | 0 | @remoutfit:shirt=force|@remoutfit:pants=force|@remoutfit:socks=force
  stand;*;!release
Strip | 0 | @remoutfit:undershirt=force|@remoutfit:underpants=force
  stand | * | !release


See also:
See also:
* [[LSL Protocol/RestrainedLoveAPI]]
* [[LSL Protocol/RestrainedLoveAPI]]
* [[LSL_Protocol/Restrained_Life_Relay/Specification]]
* [[LSL_Protocol/Restrained_Life_Relay/Specification]]

Revision as of 06:24, 28 August 2010

This Plugin combines the possibilities of MLPV2 with the commands of the Restrained Love Viewer.

It reads a notecard, which must me named .RLV to define a RLV command for a Pose.

<lsl>// ---------------------------------------------------------------------------------- // MLPV2 Plugin for RLV Script V1.02 // // Use with a notecard named .RLV with the format: // Pose|Ball no.: 0,1...*|@RLV-Command // e.g. // Missionary|1|@unsit=n // stand|*|!release // ---------------------------------------------------------------------------------- // Copyright (c) 2010, Jenni Eales. All rights reserved. // ---------------------------------------------------------------------------------- // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * The names of its contributors may not be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY // OF SUCH DAMAGE. // // Changes: // ---------------------------------------------------------------------------------- // Version 1.02 // - use | as seperator // - support multiple lines for one pose // - additional link message for direct call from ball menu // // Version 1.01 // - use ; instead of | as seperator // // Version 1.0 // - first version released // ---------------------------------------------------------------------------------- // // constants string NOTECARD = ".RLV"; // name of config notecard integer DEBUG = FALSE; // switch debug on/off integer RELAY_CHANNEL = -1812221819; // channel for RLV relay float TIMER_SEC = 1800.0; // 30 min. string CMD_RELEASE = "!release"; // release command integer LM_NUMBER = -1819; // number for link message

// internal use key kQuery; integer iLine;

string pose = "stand"; // pose set by the Ball Menu list poses = []; // configured poses list balls = []; // configured balls list commands = []; // configured commands list avatars = []; // avatars sitting on balls

// log a message log(string message) { if(DEBUG) llOwnerSay(message); }

// only for testing purposes log_data() { log("List:"); integer total_number = llGetListLength(commands); integer i; for(i=0; i<total_number; i++) { log("- " + llList2String(poses, i) + ": (" + llList2String(balls, i) + ") "+ llList2String(commands, i)); } }

// write a message to the RLV Relay relay(key avatar, string message) { list tokens = llParseString2List(message, ["|"], [""]); integer total_number = llGetListLength(tokens); integer i; for(i=0; i<total_number; i++) { string token = llList2String(tokens, i); log("RLV: MLPV2," + (string) avatar + "," + token); llSay(RELAY_CHANNEL, "MLPV2," + (string) avatar + "," + token); } }

// find commands for pose and play it for avatars on ball rlv(string pose) { log("command for: " + pose); llSetTimerEvent(TIMER_SEC);

integer total_number = llGetListLength(poses); integer i; for(i=0; i<total_number; i++) { if (pose == llList2String(poses, i)) { string ball = llList2String(balls, i); log("command for pose: " + pose + " (" + ball + ")"); if (ball == "*") { integer b; for (b=0; b<6; b++) { // get avatar for ball index key avatar = llList2Key(avatars, b); if(avatar != NULL_KEY) relay(avatar, llList2String(commands, i)); } } else { key avatar = llList2Key(avatars, (integer) ball); if(avatar != NULL_KEY) relay(avatar, llList2String(commands, i)); } } } }

// new find: pose and ball needs to match integer find_pose(string pose, string ball) { integer total_number = llGetListLength(poses); integer i; for(i=0; i<total_number; i++) { if (pose == llList2String(poses, i) && ball == llList2String(balls, i)) { return i; } } return -1; }

// add a pose/ball/command entry add_pose(string pose, string ball, string command) { // look for existing entry for pose integer found = find_pose(pose, ball); if (found == -1) { // add a new pose poses += [pose]; balls += [ball]; commands += [command];

log("Added from " + NOTECARD + ": " + pose + " | " + ball + " | " + command); } else { // append to existing pose string c = llList2String(commands, found) + "|" + command; commands = llListReplaceList(commands, [c], found, found);

log("Added " + command + " to pose " + pose); } }

// parse and store a line process_line(string line) { list tokens = llParseString2List(line, [" | "," | "," | "," | "," |","| ","|"],[""]); if(llGetListLength(tokens) < 3) return;

string pose = llList2String(tokens, 0); string ball = llList2String(tokens, 1);

integer total_number = llGetListLength(tokens); integer i; for(i=2; i<total_number; i++) { add_pose(pose, ball, llList2String(tokens, i)); } }

// check if object is in the inventory integer exists_notecard(string notecard) { return llGetInventoryType(notecard) == INVENTORY_NOTECARD; }

// initialize me initialize() { log("Initializing..."); poses = []; balls = []; commands = []; avatars = [NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY];

if (exists_notecard(NOTECARD)) { log("Reading " + NOTECARD + "..."); iLine = 0; kQuery = llGetNotecardLine(NOTECARD, iLine); } else { llOwnerSay("Not found: " + NOTECARD ); } }

default { // on state entry initialize me state_entry() { initialize(); }

// reset on Inventory change changed(integer change) { if (change & CHANGED_INVENTORY) initialize(); }

// read a line from notecard dataserver(key _query_id, string _data) { // were we called to work on notecard? if (_query_id == kQuery) { // this is a line of our notecard if (_data == EOF) { if (DEBUG) log_data(); log(NOTECARD + " read."); } else { // increment line count // data has the current line from this notecard if(_data != "") { process_line(_data); }

// request next line // read another line when you can iLine++; kQuery = llGetNotecardLine(NOTECARD, iLine); } } }

timer() { integer b; for (b=0; b<6; b++) { // get avatar for ball index key avatar = llList2Key(avatars, b);

// if not null send command if(avatar != NULL_KEY) relay(avatar, CMD_RELEASE); } llSetTimerEvent(0.0); }

// link message from MLPV2 link_message(integer sender_number, integer number, string message, key id) { // pose from ball menu selected if (number == 0 && message == "POSEB") { pose = (string)id; rlv(pose); return; }

// direct call from ball menu // configure in .MENUITEMS with // LINKMSG Resctriction | 0,-1,-1819,Restriction if (number == LM_NUMBER) { pose = message; rlv(pose); return; }

// unsit avatar if (number == -11001) { integer ball = (integer) message; log("Avatar unsit from ball " + (string) ball +": " + (string) llList2Key(avatars, ball)); relay(llList2Key(avatars, ball), CMD_RELEASE); avatars = llListReplaceList(avatars, [NULL_KEY], ball, ball); }

// sit avatar if (number == -11000) { list tokens = llParseString2List(message, ["|"], [" "]); integer ball = llList2Integer(tokens, 0); log("Avatar sit on ball " + (string) ball +": " + (string) id); avatars = llListReplaceList(avatars, [id], ball, ball); rlv(pose); } } }</lsl>

The .RLV notecard might be look like this:

Trapped | 0 | @unsit=n
Strip | 0 | @remoutfit:shirt=force|@remoutfit:pants=force|@remoutfit:socks=force
Strip | 0 | @remoutfit:undershirt=force|@remoutfit:underpants=force
stand | * | !release

See also: