User:Nexii Malthus/Script API

From Second Life Wiki
Jump to navigation Jump to search

Based from LSL To Client Communication I decided to go ahead and attempt to fully implement a modified version of the protocol.

Please see Dale's implementation first, so not everything has to be repeated here and you might see the slight differences in my protocol.

Protocol

Before anything can be queried, a connection has to be made with the client by agreeing on a common channel for receiving responses. The protocol uses tokens like Dale's implementation. Any message addressed to the viewer has to begin with 'Vwr'.

The connection is made with the command Connect, followed by a channel number. Query: $Vwr$Connect$123456

The client will then verify this connection by an 'Ok.' on the channel. Repeating the query with a different channel will change the agreed upon channel to the new one.

Once a connection is made, the LSL Script can execute all the other queries

There are some general basic functions. $Vwr$Capabilities $Vwr$Client $Vwr$Creator $Vwr$OperatingSystem

Then there are 'Packages' or 'Extensions', much like in Dale's implementation, but not really requiring a full name of the creator.

The two current extensions are 'Nexii' and 'Permission'.

Permission is used to request permission from the user for client-side powers of various functions that may need special User permission granted first. $Vwr$Permission$NexiiPicker

'Nexii' is empty at the time of writing but im implementing a function for being able to receive 'touches' in the world or clicks aka Picker. $Vwr$Nexii$Picker$<Arguments> $Vwr$Nexii$Picker$World|Once $Vwr$Nexii$Picker$HUD|All $Vwr$Nexii$Picker$Once|HUD|World

Examples

These work from Vertical Life v1.5 on.

Picker

<lsl> default {

   state_entry(){
       llListen( 9000, "", llGetOwner(), "" );
       llOwnerSay( "$Vwr$Ping$9000" );
   }
   
   listen( integer ch, string nm, key k, string msg ){
       if( msg == "pong:0" ) state Main;
   }
   
   on_rez( integer p ){ llResetScript(); }

}

state Main {

   state_entry(){
       llListen( 9001, "", llGetOwner(), "" );
       llOwnerSay( "$Vwr$Connect$9001" );
   }
   
   run_time_permissions( integer p ){
       if( p & (0x1<<31) ) llOwnerSay( "$Vwr$Nexii$Picker$World|All" );
   }
   
   listen( integer ch, string nm, key k, string msg ){
       if( msg == "Ok." ){
           llOwnerSay( "Connection Created" );
           llRequestPermissions( llGetOwner(), (0x1<<31) );
       } else {
           list t = llParseString2List( msg, ["$"], [] );
           vector Pos = (vector)llList2String(t,0);
           vector Scale = llGetScale();
           rotation Rot = llRotBetween( <0,0,1>, (vector)llList2String(t,1) );
           if( Pos != ZERO_VECTOR && Pos != llGetPos() )// Sanity Check
               llSetPrimitiveParams([PRIM_POSITION,Pos+(<0,0,Scale.z/2>*Rot),PRIM_ROTATION,Rot]);
       }
   }
   
   on_rez( integer p ){ llResetScript(); }

} </lsl>

Benchmark

<lsl> list Data = []; integer Tick;

default{

   state_entry(){
       llSetColor( <1,0,0>, -1 );
       llListen( 30, "", llGetOwner(), "" );
   }
   
   touch_start( integer dn ){
       llSetColor( <1,0,0>, -1 );
       llOwnerSay( "Creating connection to owner..." );
       llOwnerSay( "$Vwr$Connect$30" );
   }
   
   listen( integer ch, string nm, key k, string msg ){
       if( msg == "Ok." ) state Two;
   }

}

state Two{

   state_entry(){
       llOwnerSay( "Connection successful." );
       llSetColor( <1,1,0>, -1 );
       llListen( 30, "", llGetOwner(), "" );
       Tick = 0; Data = [];
       llOwnerSay( "Executing functions..." );
       llOwnerSay( "$Vwr$Capabilities" );
   }
   
   listen( integer ch, string nm, key k, string msg ){
       if( Tick == 0 ){
           Data += msg; ++Tick;
           llOwnerSay( "$Vwr$Creator" );
       } else if( Tick == 1 ){
           Data += msg; ++Tick;
           llOwnerSay( "$Vwr$OperatingSystem" );
       } else if( Tick == 2 ){
           Data += msg;
           state Three;
       }
   }

}

state Three{

   state_entry(){
       llSetColor( <0,1,0>, -1 );
       llOwnerSay( "Complete. Debug:\n"+
           "Capabilities: "+llList2String(Data,0) +"\n"+
           "Creator: "+llList2String(Data,1) +"\n"+
           "OS: "+llList2String(Data,2) );
       llListen( 30, "", llGetOwner(), "" );
       llRequestPermissions( llGetOwner(), (0x1<<32)|(0x1<<31) );
   }
   
   run_time_permissions( integer p ){
       if( p && 1073741824 ){
           llOwnerSay( "Selection Permission granted." );
       }
   }
       
   touch_start( integer dn ){
       if( llDetectedKey(0) == llGetOwner() ){
           llOwnerSay( "$Vwr$Nexii$Picker$World|All" );
           //llOwnerSay( "$Vwr$Nexii$Selection$FirstObject" );
       }
   }
   
   listen( integer ch, string nm, key k, string msg ){
       list t = llParseString2List( msg, ["$"], [] );
       vector Pos = (vector)llList2String(t,0);
       rotation Rot = llRotBetween(<0,0,1>,(vector)llList2String(t,1));
       if( Pos != ZERO_VECTOR ){
           llSetPrimitiveParams([PRIM_POSITION,Pos,PRIM_ROTATION,Rot]);
       }
       //if( llStringLength(msg) == 36 ){
       //    list t = llGetObjectDetails( msg, [OBJECT_NAME, OBJECT_POS] );
       //    llSay( 0, "Selected Object: "+llList2String(t,0)+" @ "+(string)llList2Vector(t,1) );
       //} else {
       //    llOwnerSay( msg );
       //}
   }

} </lsl>

Supported Clients

Currently the Vertical Life Client is the only client currently with a working version of "Script Collaboration" LSL-Client communication.

Official Vertical Life Client Forum http://nexii.ordoimperialis.com/index.php

Updated executable with added Script Collaboration feature http://nexii.ordoimperialis.com/client/VerticalLife%20v1.4.1.7z