Difference between revisions of "User:Kimm Paulino/Scripts1"
Kimm Paulino (talk | contribs) |
Kimm Paulino (talk | contribs) (Added my HTTP POST example too) |
||
Line 565: | Line 565: | ||
{ | { | ||
llWhisper (PUBLIC_CHANNEL, "Response: " + (string)body); | llWhisper (PUBLIC_CHANNEL, "Response: " + (string)body); | ||
} | |||
} | |||
</lsl> | |||
== HTTP POST Client and Server Example == | |||
This is similar to the above pair of scripts, but uses HTTP POST to send a message from the client to the server. The message is entered using a text box. It also uses the text box to enter in the server's URL when it first starts up. | |||
<lsl> | |||
// Very, very simple HTTP server test script, as seen on | |||
// http://wiki.secondlife.com/wiki/LSL_http_server/examples | |||
// | |||
// but configured to accept and display what gets sent to | |||
// it via a POST request. | |||
// | |||
// Note: It gets a new public URL each time it runs or | |||
// when the object moves Sims ... | |||
// | |||
// So, you'll need to update the URL used by any client objects, | |||
// or use some kind of dynamic URL service - there are some around | |||
// on the Internet - search/read about HTTP-in. | |||
// | |||
// Also, as this is a demo script, it doesn't do things like clean | |||
// up URLs and so on - see the wikis for details. | |||
// | |||
// Kimm Paulino, Nov 2012 | |||
default | |||
{ | |||
on_rez (integer start_param) | |||
{ | |||
llResetScript(); | |||
} | |||
state_entry() | |||
{ | |||
llRequestURL(); | |||
} | |||
http_request(key id, string method, string body) | |||
{ | |||
if (method == URL_REQUEST_GRANTED) | |||
{ | |||
llOwnerSay("URL: " + body); | |||
} | |||
else if (method == "GET") | |||
{ | |||
llOwnerSay ("Handling Response ..."); | |||
llHTTPResponse(id,200,"Post me something and I'll display it ..."); | |||
} | |||
else if (method == "POST") | |||
{ | |||
llOwnerSay ("Received: " + body); | |||
llHTTPResponse (id, 200, ""); | |||
} | |||
} | |||
} | |||
</lsl> | |||
And the client ... | |||
<lsl> | |||
// HTTP Test. This will POST a message to the specified | |||
// gUrl. The idea is that the gUrl is provided by a companion object | |||
// in SL. Note that the gUrl created by the llHRequestgUrl call changes | |||
// when the server object is rezzed or moves sims though ... | |||
// | |||
// There are some services on the Net that provide a semi-permanent | |||
// gUrl for use with HTTP-in like this though ... | |||
// | |||
// The message is entered using a textbox on touch. When the script | |||
// first starts up, you need to paste in the URL of the server prim | |||
// using the same text box. | |||
// | |||
// This is just a demo script. You'll need to do proper listen and | |||
// channel handling and so on. | |||
// | |||
// Kimm Paulino, Nov 2012 | |||
string gUrl = ""; | |||
integer gChannel; | |||
integer randChannel () | |||
{ | |||
// Based on http://tali.appspot.com/html/scripting/snippets.html | |||
// Always leaves 17th bit set (so never a number less than 65535) | |||
// Always leaves sign bit unset (so is always positive) | |||
integer pos_int = (((integer)llFrand(16384)) << 17) | 65536 | ((integer)llFrand(65535)); | |||
return -pos_int; | |||
} | |||
default | |||
{ | |||
on_rez (integer start_param) | |||
{ | |||
llResetScript(); | |||
} | |||
state_entry () | |||
{ | |||
gChannel = randChannel(); | |||
llListen (gChannel, "", "", ""); // Uses simplest and laggiest form of listen/channel handling | |||
} | |||
touch_start(integer total_number) | |||
{ | |||
if (gUrl == "") | |||
{ | |||
llTextBox (llDetectedKey (0), "Paste in the URL from the server prim and click submit", gChannel); | |||
} | |||
else | |||
{ | |||
llTextBox (llDetectedKey (0), "Type in your message to send to the HTTP server", gChannel); | |||
} | |||
} | |||
listen (integer channel, string name, key id, string message) | |||
{ | |||
if (channel != gChannel) | |||
{ | |||
return; | |||
} | |||
if (llSubStringIndex (message, "http://") == 0) | |||
{ | |||
// this is a new gUrl ... | |||
gUrl = message; | |||
} | |||
else if (gUrl != "") | |||
{ | |||
llHTTPRequest (gUrl, [HTTP_METHOD, "POST"], message); | |||
} | |||
else | |||
{ | |||
llOwnerSay ("You need to provide the URL of the server prim before sending any messages"); | |||
} | |||
} | |||
http_response(key id, integer status, list meta, string body) | |||
{ | |||
if (body != "") | |||
{ | |||
llWhisper (PUBLIC_CHANNEL, "Response: " + (string)body); | |||
} | |||
} | } | ||
} | } | ||
</lsl> | </lsl> |
Revision as of 14:45, 17 November 2012
Rez and Sense
<lsl> // Rezzer that will only rez an object (from inventory) if it // can't detect the specified number of objects in the region nearby already. // // Note: Sensing is limitd to a maximum of 96m in all directions. If the // objects pass out of that range, this won't find them. // // Always looks for (and rezzes) the first object found in inventory. // NB: This must have copy permissions if you want to rez it more than once! // // Kimm Paulino, July 2012
integer MAX_REZZED_OBJECTS = 5; vector REZ_POSITION = <1.0, 0.0, 0.0>; // Relative to the rezzing prim, must be less than 10m away vector REZ_ROTATION = <0.0, 0.0, 0.0>; // In degrees
string gObjectName;
rezObject () {
llRezObject (gObjectName, llGetPos() + REZ_POSITION, ZERO_VECTOR, llEuler2Rot (REZ_ROTATION * DEG_TO_RAD), 0);
}
default {
on_rez (integer start_param) { llResetScript(); } state_entry () { gObjectName = llGetInventoryName (INVENTORY_OBJECT, 0); if (gObjectName == "") { llOwnerSay ("Note to owner: No objects found in this prims inventory"); } } touch_start (integer num_detected) { if (gObjectName != "") { // Trigger a single sensor event for the full range/arc looking for any non-avatar // objects with the same name as our rezzing object. llSensor (gObjectName, NULL_KEY, (ACTIVE|PASSIVE), 96.0, PI); } } sensor (integer num_detected) { if (num_detected < MAX_REZZED_OBJECTS) { rezObject(); } else { llOwnerSay ("Max Objects detected ..."); // Nothing to do } } no_sensor () { // None found, so ok to rez one rezObject(); } changed (integer change) { if (change & CHANGED_INVENTORY) { llResetScript(); } }
} </lsl>
Derez After Sitting
<lsl> // This will kill the prim it is in, the specified time after someone // sits on the prim. It will unsit them before derezzing. // // Note: This only works when the prim has a sittarget defined. // But this script does not have to be the thing setting it, // if the sit target is set to <0.0,0.0,0.0> in this script, // then no call to llSitTarget is made - so another script // can do it instead. // // It can optionally derez on unsit too - i.e. when they get up // or derez a defined time after they unsit. // // Note: It doesn't unsit any other avatars sitting on other // prims prior to derezzing, but derezzing will unsit them anyway! // // It will also (optionally) automatically derez itself after a specified // time if noone sits down on it. // // Kimm Paulino, July 2012
// TRUE if want to immediately auto derez when av gets up. // (overrides DEREZ_AFTER_UNSIT_TIMEOUT) integer DEREZ_ON_UNSIT = FALSE;
// Time to derez if noone sits down // (in seconds - 0.0 to disable) float DEREZ_TIMEOUT = 60.0;
// Once an av sits down, this timer starts // and will derez when it times out. // (in seconds - 0.0 to disable) float DEREZ_AFTER_SIT_TIMEOUT = 30.0;
// Once an av gets up, this timer starts // and will derez when it times out. // (in seconds - 0.0 to disable) float DEREZ_AFTER_UNSIT_TIMEOUT = 0.0;
// Position of the sittarget vector SIT_VECTOR = <0.0, 0.0, 0.5>; // In metres - ZERO_VECTOR to disable vector SIT_ROTATION = <0.0, 0.0, 0.0>; // In degrees
key gAvUuid; integer gSitting = FALSE;
default {
on_rez (integer start_param) { llResetScript(); }
state_entry() { if (SIT_VECTOR != ZERO_VECTOR) { llSitTarget (SIT_VECTOR, llEuler2Rot (SIT_ROTATION * DEG_TO_RAD)); } llSetTimerEvent (DEREZ_TIMEOUT); } timer () { if (gAvUuid) { llUnSit (gAvUuid); } llSetTimerEvent (0.0); llDie(); } changed (integer change) { // When someone sits on an object, the av is considered to be // a linked-in child prim, so the link number changes if (change & CHANGED_LINK) { gAvUuid = llAvatarOnSitTarget(); if (gAvUuid) { // Avatar has just sat down gSitting = TRUE; llSetTimerEvent (DEREZ_AFTER_SIT_TIMEOUT); } else if (gSitting) { // Assume av just got up - it was sitting and now isn't ... gSitting = FALSE; if (DEREZ_ON_UNSIT) { // Want to derez straight away llDie(); } llSetTimerEvent (DEREZ_AFTER_UNSIT_TIMEOUT); } else { // Could be unlinking going on // or maybe there is another sit target in a linked prim // that someone has just sat on or vacated } } }
} </lsl>
Timer Action Template
<lsl> // Basic timer-driven state changing script. // NB: Does not use the LSL ability to define // states, but uses a counter to manage a simple // incrementing state machine. // // Every time interval, it will change its record of state // and you can add code to do something, then it will move // to the next state. // // To add more things, just add more // else if (gState == 4) // { // // and the next // } // statements in the appropriate place. // // If you want the timer interval to be different for different // states, then you could add more llSetTimerEvent() calls // in each state to set the timer for the next one. // // Kimm Paulino // Sept 2012
// Timer interval in seconds float TIMER_INTERVAL = 5.0;
integer gState;
default {
on_rez (integer start_param) { llResetScript(); } state_entry () { gState = 0; llSetTimerEvent (TIMER_INTERVAL); } timer () { gState ++; if (gState == 1) { // Do the first thing here } else if (gState == 2) { // After the timer interval this is next } else if (gState == 3) { // and the next } // add more else if () statements here else { // Once all states are complete, reset the counter ready for the next time gState = 0; } }
} </lsl>
Multiple Notecard Reading Template
<lsl> // Example showing multiple notecard reading. // // Kimm Paulino, Oct 2012
key gNCQueryId; integer gNCLine; integer gNCNumber; string gNCName;
default {
on_rez (integer start_param) { llResetScript(); } state_entry () { gNCNumber = 0; gNCLine = 0; gNCName = llGetInventoryName (INVENTORY_NOTECARD, gNCNumber); if (gNCName != "") { llOwnerSay ("=== Reading notecard " + gNCName + " (" + (string)gNCNumber + ")"); gNCQueryId = llGetNotecardLine (gNCName, gNCLine); } } dataserver (key query_id, string data) { if (query_id != gNCQueryId) { // Not for us return; }
// Note: If the notecard contains embedded objects (like scripts, landmarks, etc) // then EOF is returned - so this will move onto the next one as if the notecard // was empty. if (data == EOF) { // Move to the next notecard gNCNumber++; gNCLine = 0; gNCName = llGetInventoryName (INVENTORY_NOTECARD, gNCNumber); if (gNCName != "") { llOwnerSay ("=== Reading notecard " + gNCName + " (" + (string)gNCNumber + ")"); gNCQueryId = llGetNotecardLine (gNCName, gNCLine); } else { llOwnerSay ("=== Complete"); }
// Wait for the next line to be read return; }
// Do something with the notecard line // Note: Only get first 255 characters of each line llOwnerSay (data); // and read the next line gNCLine++; gNCQueryId = llGetNotecardLine(gNCName, gNCLine); } changed (integer change) { if (change & CHANGED_INVENTORY) { llResetScript(); } }
} </lsl>
Alarm Script
<lsl> // Simple script to trigger at a certain time and perform a function, // in the default case send an IM to the specified avatar // // Notes // Can specify a time in GMT (ie no seasonal changes) or SLT // Uses 24 hour times // Can include touch control if required // Sends the specified message to the specified UUID // // If you want it to do something else, code it in the alarm() function // // Kimm Paulino // Oct 2012 // http://kimmscripts.wordpress.com/
integer gHour = 7; // 24 hour clock integer gMin = 30; integer gSec = 0; integer gGMT = TRUE; // GMT or SL time integer gTouchControl = TRUE; string gMsg = "Wake up!"; key gAv = "00000000-0000-0000-0000-000000000000";
integer gArmed;
setAlarm () {
// set a timer event for destination time - current time float desttime = (float)(gHour*60*60 + gMin*60 + gSec);
// This is the number of seconds since midnight // so the required setting until the destination time // will depend on if the time is in the past or not. // If we happen to get lucky and float nowtime = llGetWallclock (); if (gGMT) { nowtime = llGetGMTclock (); } if (nowtime >= desttime) { // Need to add 24 hours before subtracting desttime = desttime + 24.0*60.0*60.0; llOwnerSay ("Dest: " + (string)desttime + " Now: " + (string)nowtime); llSetTimerEvent (desttime - nowtime); } else { llOwnerSay ("Dest: " + (string)desttime + " Now: " + (string)nowtime); llSetTimerEvent (desttime - nowtime); }
}
disableAlarm() {
llSetTimerEvent (0.0);
}
// This is what happens on the alarm alarm () {
//llOwnerSay ("Alarm"); llInstantMessage (gAv, gMsg);
}
default {
state_entry() { string zone = " SLT"; if (gGMT) { zone = " GMT"; } llOwnerSay ("Alarm set for " + (string)gHour + " h " + (string)gMin + " m" + (string)gSec + " s " + zone); gArmed = TRUE; setAlarm(); } touch_start (integer num_detected) { if (gTouchControl) { if (gArmed) { gArmed = FALSE; disableAlarm(); } else { gArmed = TRUE; setAlarm(); } } } timer () { alarm(); // Reset alarm each time, to allow for any drift in time setAlarm(); }
} </lsl>
Simple Channel Relay
<lsl> // Simple relay script. Listens on one channel and relays // everything to the another channel. // // Can be useful for testing things - e.g. if you are listening // on a negative channel in your main script and want a way // to send it test strings, you could drop this in a nearby // prim and have it listen on a chat channel and pass the messages // onto your prim under test. // // Kimm Paulino // Nov 2012
integer gListenChannel = 88; integer gSpeakChannel = -88;
relayMessage (string message) {
// Only use one of these as required: // whisper = <10m; say = 20m; shout > 20m; region = whole region
//llWhisper (gSpeakChannel, message); llSay (gSpeakChannel, message); //llShout (gSpeakChannel, message); //llRegionSay (gSpeakChannel, message);
}
default {
on_rez (integer start_param) { llResetScript(); }
state_entry () { llListen (gListenChannel, "", "", ""); } listen (integer channel, string name, key id, string message) { if (channel == gListenChannel) { relayMessage (message); } }
} </lsl>
HTTP Server and Client Example
These two scripts can be used (once you've hard-coded in the right URL into the client script) to highlight basic prim to prim communications using HTTP without requiring an external server.
<lsl> // Very, very simple HTTP server test script, as seen on // http://wiki.secondlife.com/wiki/LSL_http_server/examples // // Note: It gets a new public URL each time it runs or // when the object moves Sims ... // // So, you'll need to update the URL used by any client objects, // or use some kind of dynamic URL service - there are some around // on the Internet - search/read about HTTP-in // // Kimm Paulino, Nov 2009
default {
on_rez (integer start_param) { llResetScript(); } state_entry() { llRequestURL(); } http_request(key id, string method, string body) { if (method == URL_REQUEST_GRANTED) { llOwnerSay("URL: " + body); } else if (method == "GET") { llOwnerSay ("Handling Response ..."); llHTTPResponse(id,200,"Hello From Kimm's HTTP Test"); } }
} </lsl>
<lsl> // HTTP Test. This will request the contents of the specified // URL. The idea is that the URL is provided by a companion object // in SL. Note that the URL created by the llRequestURL call changes // when the server object is rezzed or moves sims though ... // // There are some services on the Net that provide a semi-permanent // URL for use with HTTP-in like this though ... // // Kimm Paulino, Nov 2009
string URL = "past in your URL from the server script here";
default {
touch_start(integer total_number) { llHTTPRequest (URL, [HTTP_METHOD, "GET"], ""); } http_response(key id, integer status, list meta, string body) { llWhisper (PUBLIC_CHANNEL, "Response: " + (string)body); }
} </lsl>
HTTP POST Client and Server Example
This is similar to the above pair of scripts, but uses HTTP POST to send a message from the client to the server. The message is entered using a text box. It also uses the text box to enter in the server's URL when it first starts up.
<lsl> // Very, very simple HTTP server test script, as seen on // http://wiki.secondlife.com/wiki/LSL_http_server/examples // // but configured to accept and display what gets sent to // it via a POST request. // // Note: It gets a new public URL each time it runs or // when the object moves Sims ... // // So, you'll need to update the URL used by any client objects, // or use some kind of dynamic URL service - there are some around // on the Internet - search/read about HTTP-in. // // Also, as this is a demo script, it doesn't do things like clean // up URLs and so on - see the wikis for details. // // Kimm Paulino, Nov 2012
default {
on_rez (integer start_param) { llResetScript(); } state_entry() { llRequestURL(); } http_request(key id, string method, string body) { if (method == URL_REQUEST_GRANTED) { llOwnerSay("URL: " + body); } else if (method == "GET") { llOwnerSay ("Handling Response ..."); llHTTPResponse(id,200,"Post me something and I'll display it ..."); } else if (method == "POST") { llOwnerSay ("Received: " + body); llHTTPResponse (id, 200, ""); } }
} </lsl>
And the client ...
<lsl> // HTTP Test. This will POST a message to the specified // gUrl. The idea is that the gUrl is provided by a companion object // in SL. Note that the gUrl created by the llHRequestgUrl call changes // when the server object is rezzed or moves sims though ... // // There are some services on the Net that provide a semi-permanent // gUrl for use with HTTP-in like this though ... // // The message is entered using a textbox on touch. When the script // first starts up, you need to paste in the URL of the server prim // using the same text box. // // This is just a demo script. You'll need to do proper listen and // channel handling and so on. // // Kimm Paulino, Nov 2012
string gUrl = ""; integer gChannel;
integer randChannel () { // Based on http://tali.appspot.com/html/scripting/snippets.html // Always leaves 17th bit set (so never a number less than 65535) // Always leaves sign bit unset (so is always positive) integer pos_int = (((integer)llFrand(16384)) << 17) | 65536 | ((integer)llFrand(65535));
return -pos_int;
}
default {
on_rez (integer start_param) { llResetScript(); } state_entry () { gChannel = randChannel(); llListen (gChannel, "", "", ""); // Uses simplest and laggiest form of listen/channel handling }
touch_start(integer total_number) { if (gUrl == "") { llTextBox (llDetectedKey (0), "Paste in the URL from the server prim and click submit", gChannel); } else { llTextBox (llDetectedKey (0), "Type in your message to send to the HTTP server", gChannel); } } listen (integer channel, string name, key id, string message) { if (channel != gChannel) { return; } if (llSubStringIndex (message, "http://") == 0) { // this is a new gUrl ... gUrl = message; } else if (gUrl != "") { llHTTPRequest (gUrl, [HTTP_METHOD, "POST"], message); } else { llOwnerSay ("You need to provide the URL of the server prim before sending any messages"); } } http_response(key id, integer status, list meta, string body) { if (body != "") { llWhisper (PUBLIC_CHANNEL, "Response: " + (string)body); } }
} </lsl>