Jump to content

Gayngel

Resident
  • Posts

    183
  • Joined

  • Last visited

Everything posted by Gayngel

  1. llOwnerSay("DisplayName1 "+ displayName) in state_entry wont give the display name because you haven't assigned a value to the displayName value yet. You can either assign a value with llGetDisplayName before the ownersay message or wait for the dataserver event to trigger and return the data and then assign it and show it in an ownersay as you have.
  2. https://www.facebook.com/zuck/videos/1898414763675286/?notif_id=1635440492255451&notif_t=live_video&ref=notif
  3. https://www.facebook.com/zuck/posts/10114026953010521
  4. Here is a persistent URL system to store the URL of an inworld server replacing the Grid URL Persister. For a number years I've used Google App Script to store a server URL and data persistently in a Google Sheet. Had no downtime or need to make changes to the script once deployed. As we all know the URL of a script changes often for reasons. This script will update and store the script's URL to a spreadsheet whenever it changes. You can then use this for anything you need an inworld server for such as a store drop box, game HUD, greeter, etc. Google App Script: https://pastebin.com/Cc9ZbYyj Barebones Server Script: https://pastebin.com/DjDzZMHA Barebones Client Script: https://pastebin.com/hYZ0Jf3c Here is an example of a drop box redelivery system: Drop Box Server (server): https://pastebin.com/L1byiSgH Redelivery Terminal (client): https://pastebin.com/PDMqzRgP
  5. Here is a simple redelivery terminal / drop box system: Server: // Script by Gayngel of The Script Yard. //Join The Script Yard Group: secondlife:///app/group/4921b4f0-c21e-7866-c0c2-791d10bb5502/about //Visit The Script Yard Marketplace: https://marketplace.secondlife.com/stores/149734 // This is a simple dropbox system. Redelivery systems will request redeliveries of the object you have stored in it and the drop box will deliver the object to avatar who requested a redelivery. // The drop box saves it's url to a Google Sheet via Google App Script. The redelivery client will request the url of the drop box from the spreadsheet and then request a redeivery from the drop box. // Get the Google App Script from https://pastebin.com/Cc9ZbYyj and follow the instructions in the app script to setup. // Once set up paste the app url below. string app_url = "https://script.google.com/macros/s/AKfycbyX-qKC0mpHFSa8iMDMBQyQtKzGQMdtxyICF5-pF2cebpm_HmU/exec"; // place the url of Google App Script here. string spreadsheet = ""; // The Google App Script will create a spreadsheet in your Google Drive to store the url of the drop box. You can write a name here or leave it blank. If you leave the string blank the spreadsheet will automatically be called the "NameOfParcelDropBoxIsOn Dropbox". list parceldetails; string parcelname; string url; key reqURL; key http_req; key sheet_req; integer allow =FALSE; default { on_rez(integer start_param) { llSetObjectDesc(""); llResetScript(); } state_entry() { allow = FALSE; // verbosity just in case llReleaseURL(url); // verbosity just in case parceldetails = llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_NAME]); parcelname = llList2String(parceldetails,0); reqURL =llRequestURL(); } http_request(key id, string method, string body) { if (id == reqURL) { if (method == URL_REQUEST_DENIED) llOwnerSay("The following error occurred while attempting to get a free URL for this device:\n \n" + body); else if (method == URL_REQUEST_GRANTED) { url = body; } if(app_url != "") { http_req = llHTTPRequest(app_url+"?server_url="+url+"&obj_key="+(string)llGetKey(),[HTTP_METHOD,"GET"],""); // send the server's url to the spreadsheet to be stored. } else llOwnerSay("Please add the URL of the Google App Script at the top of the script"); } // if (id == reqURL) else if (method == "POST") { list tmp = llParseString2List(body,["="],[""]); string cmd = llToLower(llList2String(tmp,0)); string ref = llList2String(tmp,1); if(cmd == "url_ok") { string ssID = llGetObjectDesc(); if(ssID == "") // if the spreadsheet doesn't exist create one { if(spreadsheet == "") { spreadsheet = parcelname + " drop box."; } llOwnerSay("Creating spreadsheet named " + spreadsheet); if(app_url != "") sheet_req = llHTTPRequest(app_url+ "?url="+url+"&spreadsheet=" + llEscapeURL(spreadsheet),[HTTP_METHOD,"POST"],"Create"); // instruct the App Script to create a spreadsheet } else if(ssID != "") // if the spreadsheet exists { llOwnerSay("The spreadsheet database is ready."); llOwnerSay("This drop box will now allow redeliveries"); allow = TRUE; sheet_req = llHTTPRequest(app_url+ "?url="+url,[HTTP_METHOD,"POST"],"Send_URL"); // update the url of the server and store in the spreadsheet } } //if(cmd == "url_ok") else if(cmd == "url_invalid") { llSetObjectDesc(""); llOwnerSay("Can not save this server's URL to the spreadsheet as the Google App Script is tied to another server. Please create a new app script and paste it's url at the top of the script."); } else if(cmd == "spreadsheetready") { llSetObjectDesc(ref); llOwnerSay("The spreadsheet database has been created."); allow = TRUE; sheet_req = llHTTPRequest(app_url+ "?url="+url,[HTTP_METHOD,"POST"],"Send_URL"); llOwnerSay("This drop box will now allow redeliveries"); } else if(cmd == "url_added") { llOwnerSay("The url of your server has been updated in the spreadsheet database."); } else if(cmd == "request_redelivery") { key av = (key)ref; if(allow == TRUE) { if(llGetInventoryNumber(INVENTORY_OBJECT) > 0) // if the drop box contains an object { llInstantMessage(av,"Redelivering your object."); string obj = llGetInventoryName(INVENTORY_OBJECT,0); llGiveInventory(av,obj); llHTTPResponse(id,200,"redelivery_complete"); } else llInstantMessage(av,"Sorry there is nothing to redeliver"); } } //else if(cmd == "request_redelivery") } // method is post } changed(integer change) { if(change & CHANGED_REGION_START || change & CHANGED_REGION || change & CHANGED_INVENTORY || change & CHANGED_TELEPORT) { llReleaseURL(url); // verbosity just in case llResetScript(); } } } Client: // Script by Gayngel of The Script Yard. //Join The Script Yard Group: secondlife:///app/group/4921b4f0-c21e-7866-c0c2-791d10bb5502/about //Visit The Script Yard Marketplace: https://marketplace.secondlife.com/stores/149734 // This is a simple dropbox system. Redelivery systems will request redeliveries of the object you have stored in it and the drop box will deliver the object to avatar who requested a redelivery. // The drop box saves it's url to a Google Sheet via Google App Script. The redelivery client will request the url of the drop box from the spreadsheet and then request a redeivery from the drop box. // Get the Google App Script from https://pastebin.com/Cc9ZbYyj and follow the instructions in the app script to setup. // Once set up paste the app url below. string app = "https://script.google.com/macros/s/AKfycbyX-qKC0mpHFSa8iMDMBQyQtKzGQMdtxyICF5-pF2cebpm_HmU/exec"; // place the url of Google App Script here. string url; key reqURL; key server_req; key app_req; integer allow =FALSE; integer wait = FALSE; // if someone is using the terminal the next user must wait their turn integer listen_chan; integer listen_handle; key recipient; default { on_rez(integer start_param) { llResetScript(); } state_entry() { allow = FALSE; // verbosity just in case llReleaseURL(url); // verbosity just in case reqURL =llRequestURL(); } http_request(key id, string method, string body) { if (id == reqURL) { if (method == URL_REQUEST_DENIED) llOwnerSay("The following error occurred while attempting to get a free URL for this device:\n \n" + body); else if (method == URL_REQUEST_GRANTED) { url = body; if(app != "") { llOwnerSay("This terminal can now request redeliveries"); allow = TRUE; } else llOwnerSay("Please add the URL of the Google App Script at the top of the script"); } } else if(id == server_req) { if(body == "redelivery_ok") { wait = TRUE; // verbosity just in case allow = TRUE; // verbosity just in case llListenRemove(listen_handle); // verbosity just in case } } else if(method == "POST") { list tmp = llParseString2List(body,["="],[""]); string cmd = llToLower(llList2String(tmp,0)); string ref = llList2String(tmp,1); if(cmd == "server_url") { server_req = llHTTPRequest(llUnescapeURL(ref),[HTTP_METHOD,"POST"],"request_redelivery="+(string)recipient); // instruct server to redeliver object llOwnerSay("Requesting redelivery from server please wait..."); llSetTimerEvent(0.0); llSetTimerEvent(10.0); } } } http_response(key id, integer status, list metadata ,string body) { if(body == "redelivery_complete") { llOwnerSay("Delivery successful"); llSetTimerEvent(0.0); // redelivery was successful // do other stuff here } } touch_end(integer num) { key toucher = llDetectedKey(0); if(allow == TRUE) { if(wait == FALSE) { wait = TRUE; // other users must wait their turn llListenRemove(listen_handle); listen_chan = ((integer)("0x"+llGetSubString((string)toucher,-8,-1)) - 723) | 0x8000000; listen_handle = llListen(listen_chan,"",toucher,""); llDialog(toucher,"\nSelect redeliver to redeliver your object.",["Redeliver"],listen_chan); } else { llRegionSayTo(toucher,0,"Someone is already using this terminal, please wait."); } } else { llRegionSayTo(toucher,0,"This redelivery terminal is currently offline."); } } listen(integer chan, string name, key id, string msg) { if(chan == listen_chan) { if(msg == "Redeliver") { llListenRemove(listen_handle); wait = FALSE; //allow next user to use the terminal allow = TRUE; // verbosity just in case //http request to google app script to get url of drop box recipient = id; app_req = llHTTPRequest(app+"?client_url="+url,[HTTP_METHOD,"GET"],""); // request url of server from spreadsheet database } } } timer() { llSetTimerEvent(0.0); llInstantMessage(recipient,"There was no response from the server. Please try again."); } changed(integer change) { if(change & CHANGED_REGION_START || change & CHANGED_REGION || change & CHANGED_INVENTORY || change & CHANGED_TELEPORT) { llReleaseURL(url); // verbosity just in case llResetScript(); } } }
  6. Client: // Script by Gayngel of The Script Yard. //Join The Script Yard Group: secondlife:///app/group/4921b4f0-c21e-7866-c0c2-791d10bb5502/about //Visit The Script Yard Marketplace: https://marketplace.secondlife.com/stores/149734 // This is a barebones script to store the scripts url persistently in a Google Sheet. // The server will send a greeting when requested by a client terminal. // The server saves it's url to a Google Sheet via Google App Script. The client will request the url of the server from the spreadsheet and then request the server to greet the avatar who touched the object and requested a greeting from the menu. // Get the Google App Script from https://pastebin.com/Cc9ZbYyj and follow the instructions in the app script to setup. // Once set up paste the app url below. string app = "https://script.google.com/macros/s/AKfycbz-rAtEqm5clysDSL3l3-9kYqfwrDjSpFg7u4PuF9208F-ON3g/exec"; // place the url of Google App Script here. string url; key reqURL; key server_req; key app_req; integer allow =FALSE; integer wait = FALSE; // if someone is using the terminal the next user must wait their turn integer listen_chan; integer listen_handle; key recipient; default { on_rez(integer start_param) { llResetScript(); } state_entry() { allow = FALSE; // verbosity just in case llReleaseURL(url); // verbosity just in case reqURL =llRequestURL(); } http_request(key id, string method, string body) { if (id == reqURL) { if (method == URL_REQUEST_DENIED) llOwnerSay("The following error occurred while attempting to get a free URL for this device:\n \n" + body); else if (method == URL_REQUEST_GRANTED) { url = body; if(app != "") { llOwnerSay("This terminal can now request greetings from the server"); allow = TRUE; } else llOwnerSay("Please add the URL of the Google App Script at the top of the script"); } } else if(id == server_req) { if(body == "redelivery_ok") { wait = TRUE; // verbosity just in case allow = TRUE; // verbosity just in case llListenRemove(listen_handle); // verbosity just in case } } else if(method == "POST") { list tmp = llParseString2List(body,["="],[""]); string cmd = llToLower(llList2String(tmp,0)); string ref = llList2String(tmp,1); if(cmd == "server_url") { server_req = llHTTPRequest(llUnescapeURL(ref),[HTTP_METHOD,"POST"],"request_greeting="+(string)recipient); // instruct server to redeliver object } } } touch_end(integer num) { key toucher = llDetectedKey(0); if(allow == TRUE) { if(wait == FALSE) { wait = TRUE; // other users must wait their turn llListenRemove(listen_handle); listen_chan = ((integer)("0x"+llGetSubString((string)toucher,-8,-1)) - 723) | 0x8000000; listen_handle = llListen(listen_chan,"",toucher,""); llDialog(toucher,"\nSelect Greet to get a greeting from the server.",["Greet"],listen_chan); } else { llRegionSayTo(toucher,0,"Someone is already using this terminal, please wait."); } } else { llRegionSayTo(toucher,0,"This server is currently offline."); } } listen(integer chan, string name, key id, string msg) { if(chan == listen_chan) { if(msg == "Greet") { llListenRemove(listen_handle); wait = FALSE; //allow next user to use the terminal allow = TRUE; // verbosity just in case //http request to google app script to get url of drop box recipient = id; app_req = llHTTPRequest(app+"?client_url="+url,[HTTP_METHOD,"GET"],""); // request url of server from spreadsheet database } } } changed(integer change) { if(change & CHANGED_REGION_START || change & CHANGED_REGION || change & CHANGED_INVENTORY || change & CHANGED_TELEPORT) { llReleaseURL(url); // verbosity just in case llResetScript(); } } }
  7. @Xiija You don't need to go through a 3rd party service communicate between Google App Script and SL. I've been meaning to post this for a looong time but haven't had time to create the example scripts until now. Google App Script: /* Google App Script Code by Gayngel of The Script Yard. Join The Script Yard Group: secondlife:///app/group/4921b4f0-c21e-7866-c0c2-791d10bb5502/about Visit The Script Yard Marketplace: https://marketplace.secondlife.com/stores/149734 Description: This Google App Script keeps track of an LSL script's URL when it changes. The object the script is in can then be used as a server to retrieve persistent data from for a drop box and redelivery terminal system or scoreboard or HUD or whatever object/system you create that requires persistent stored data. The URL and stored data is saved to a spreadsheet and the data can be retrieved by a client script. Instructions: 1. Open your Google Drive and select New > More > Google App Script. 2. Before doing anything in the editor you must switch to the legacy editor. This is a very important step as some features don't work yet in the new editor. On the top right corner under your account button select "Use Legacy Editor". You can ignore and close the opt out survey. 3. Copy and paste this script into the code editor. 4. Select the save icon to save the script and give it a name. N.B: It is very important you save the script before publishing it to the web. 5. Select "Publish" on the menu bar and select "Deploy as Web App" 6. Select the Project Version dropdown and select New. 7. Under "Execute App As:" select Me(youremail@gmail.com) 8. Under "Who has access to the app:" select "Anyone, even anonymous". 9. Select "Deploy" and "Review Permissions". 10. Sign in to your google account. 11. If you get the "Google hasn't verified this app" message select "Advanced" and then select "Go to app_name(unsafe)". 12. Review and Allow Permissions. 13. Copy the web app url and paste it both in the server and client scripts in the line string app = ""; paste the url in between the quotation marks. If you make any changes to the script you must save and publish again. You must also select a new project version. */ function doGet(e) { var props = PropertiesService.getScriptProperties(); // Properties service can store properties/metadata. You can find properties by selecting File > Project Properties > Script Properties tab var url; if(e.parameter.server_url) { url = e.parameter.server_url; // gets the url of the server var obj_key = e.parameter.obj_key; var prop_obj = props.getProperty('prop_obj'); // get the prop_obj property from script properties if(prop_obj) { if(obj_key == prop_obj) // prevents two servers sharing the same app script/database { props.setProperty('URL',url); var payload = { "URL_OK":"URL_OK" // body of method (POST,GET,PUT,etc). Sent as key/value pair. Can be parsed by llParseString2List(body,["="],[]) }; var options = { "method" : "post", // Method like HTTP_METHOD in the llHTTPRequest() function. We'll make a POST. "payload" : payload // what variables we are sending back to the server/client. }; var response = UrlFetchApp.fetch(url,options); // Make a http request back to the URL of the server or client that made the request. } else // server uuid is different to stored server uuid. can not share same app script / database { var payload = { "URL_INVALID":"URL_INVALID" // body of method (POST,GET,PUT,etc). Sent as key/value pair. Can be parsed by llParseString2List(body,["="],[]) }; var options = { "method" : "post", // Method like HTTP_METHOD in the llHTTPRequest() function. We'll make a POST. "payload" : payload // what variables we are sending back to the server/client. }; var response = UrlFetchApp.fetch(url,options); // Make a http request back to the URL of the server or client that made the request. } } else { props.setProperty('prop_obj', obj_key); // sets a property prop_obj as object_key props.setProperty('URL',url); var payload = { "URL_OK":"URL_OK" // body of method (POST,GET,PUT,etc). Sent as key/value pair. Can be parsed by llParseString2List(body,["="],[]) }; var options = { "method" : "post", // Method like HTTP_METHOD in the llHTTPRequest() function. We'll make a POST. "payload" : payload // what variables we are sending back to the server/client. }; var response = UrlFetchApp.fetch(url,options); // Make a http request back to the URL of the server or client that made the request. } } else if(e.parameter.client_url) { url = e.parameter.client_url; // gets the url of the client var ssNew; var ssId = props.getProperty('ssId'); //gets the id of the spreadsheet by retrieving the stored id in script properties ssNew = SpreadsheetApp.openById(ssId); //open the spreadsheet var sheet = ssNew.getSheets()[0]; // get the first sheet in the spreadsheet var cell = sheet.getRange("A1"); // gets the range of cells. var payload = { "server_url":cell.getValue() // body of method (POST,GET,PUT,etc). Sent as key/value pair. Can be parsed by llParseString2List(body,["="],[]) Sends the value of cell A1. }; var options = { "method" : "post", // Method like HTTP_METHOD in the llHTTPRequest() function. We'll make a POST. "payload" : payload // what variables we are sending back to the server/client. }; var response = UrlFetchApp.fetch(url,options); // Make a http request back to the URL of the server or client that made the request. } } function doPost(e) { var url = e.parameter.url; var props = PropertiesService.getScriptProperties(); // Properties service can store properties/metadata. You can find properties by selecting File > Project Properties > Script Properties tab var ssNew; var ssId = props.getProperty('ssId'); // get the ssId property from script properties if(ssId) // if the spreadsheet is created. I.E If the property ssId exists { ssNew = SpreadsheetApp.openById(ssId); // open the spreadsheet var sheet = ssNew.getSheets()[0]; // get first sheet of spreadsheet var cell = sheet.getRange("A1"); // target the first cell in the spreadsheet - A1 cell.clear(); // clear the data in A1 cell.setValue(e.parameter.url); // set the value of the A1 cell to the url of the server props.setProperty('URL',url); // sets a property URL as the url of the server var payload = { "url_added":"url_added" // body of method (POST,GET,PUT,etc). Sent as key/value pair. Can be parsed by llParseString2List(body,["="],[]) }; var options = { "method" : "post", // Method like HTTP_METHOD in the llHTTPRequest() function. We'll make a POST. "payload" : payload // what variables we are sending back to the server/client. }; var response = UrlFetchApp.fetch(url,options); // Make a http request back to the URL of the server or client that made the request. } // if(ssId) else // if spreadsheet is not created i.e there is no property named ssId in script properties { var ssName = e.parameter.spreadsheet; // the name of the spreadsheet set in the server script ssNew = SpreadsheetApp.create(ssName); // create a new spread sheet props.setProperty('ssId', ssNew.getId()); // sets a property ssID and set the vaue of the property to the id of the spreadsheet var payload = { "SpreadsheetReady":ssNew.getId() // body of method (POST,GET,PUT,etc). Sent as key/value pair. Can be parsed by llParseString2List(body,["="],[]) }; var options = { "method" : "post", // Method like HTTP_METHOD in the llHTTPRequest() function. We'll make a POST. "payload" : payload // what variables we are sending back to the server/client. }; var response = UrlFetchApp.fetch(url,options); // Make a http request back to the URL of the server or client that made the request. } } Here is barebones system to make send a message from a client script to request a greeting from the server to the avatar that touches the terminal and requests the greeting from the menu: Server: // Script by Gayngel of The Script Yard. //Join The Script Yard Group: secondlife:///app/group/4921b4f0-c21e-7866-c0c2-791d10bb5502/about //Visit The Script Yard Marketplace: https://marketplace.secondlife.com/stores/149734 // This is a barebones script to store the scripts url persistently in a Google Sheet. // The server will send a greeting when requested by a client terminal. // The server saves it's url to a Google Sheet via Google App Script. The client will request the url of the server from the spreadsheet and then request the server to greet the avatar who touched the object and requested a greeting from the menu. // Get the Google App Script from https://pastebin.com/Cc9ZbYyj and follow the instructions in the app script to setup. // Once set up paste the app url below. string app_url = "https://script.google.com/macros/s/AKfycbz-rAtEqm5clysDSL3l3-9kYqfwrDjSpFg7u4PuF9208F-ON3g/exec"; // place the url of Google App Script here. string spreadsheet = ""; // The Google App Script will create a spreadsheet in your Google Drive to store the url of the drop box. You can write a name here or leave it blank. If you leave the string blank the spreadsheet will automatically be called the "NameOfParcelDropBoxIsOn Dropbox". list parceldetails; string parcelname; string url; key reqURL; key http_req; key sheet_req; integer allow =FALSE; default { on_rez(integer start_param) { llSetObjectDesc(""); llResetScript(); } state_entry() { allow = FALSE; // verbosity just in case llReleaseURL(url); // verbosity just in case parceldetails = llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_NAME]); parcelname = llList2String(parceldetails,0); reqURL =llRequestURL(); } http_request(key id, string method, string body) { if (id == reqURL) { if (method == URL_REQUEST_DENIED) llOwnerSay("The following error occurred while attempting to get a free URL for this device:\n \n" + body); else if (method == URL_REQUEST_GRANTED) { url = body; } if(app_url != "") { http_req = llHTTPRequest(app_url+"?server_url="+url+"&obj_key="+(string)llGetKey(),[HTTP_METHOD,"GET"],""); // send the server's url to the spreadsheet to be stored. } else llOwnerSay("Please add the URL of the Google App Script at the top of the script"); } // if (id == reqURL) else if (method == "POST") { list tmp = llParseString2List(body,["="],[""]); string cmd = llToLower(llList2String(tmp,0)); string ref = llList2String(tmp,1); if(cmd == "url_ok") { string ssID = llGetObjectDesc(); if(ssID == "") // if the spreadsheet doesn't exist create one { if(spreadsheet == "") { spreadsheet = parcelname + " greeter."; } llOwnerSay("Creating spreadsheet named " + spreadsheet); if(app_url != "") sheet_req = llHTTPRequest(app_url+ "?url="+url+"&spreadsheet=" + llEscapeURL(spreadsheet),[HTTP_METHOD,"POST"],"Create"); // instruct the App Script to create a spreadsheet } else if(ssID != "") // if the spreadsheet exists { llOwnerSay("The spreadsheet database is ready."); llOwnerSay("This server can now be contacted"); allow = TRUE; sheet_req = llHTTPRequest(app_url+ "?url="+url,[HTTP_METHOD,"POST"],"Send_URL"); // update the url of the server and store in the spreadsheet } } //if(cmd == "url_ok") else if(cmd == "url_invalid") { llSetObjectDesc(""); llOwnerSay("Can not save this server's URL to the spreadsheet as the Google App Script is tied to another server. Please create a new app script and paste it's url at the top of the script."); } else if(cmd == "spreadsheetready") { llSetObjectDesc(ref); llOwnerSay("The spreadsheet database has been created."); allow = TRUE; sheet_req = llHTTPRequest(app_url+ "?url="+url,[HTTP_METHOD,"POST"],"Send_URL"); llOwnerSay("This server can now be contacted"); } else if(cmd == "url_added") { llOwnerSay("The url of your server has been updated in the spreadsheet database."); } else if(cmd == "request_greeting") { key av = (key)ref; if(allow == TRUE) { llInstantMessage(av,"Hello World!"); } } //else if(cmd == "request_redelivery") } // method is post } changed(integer change) { if(change & CHANGED_REGION_START || change & CHANGED_REGION || change & CHANGED_INVENTORY || change & CHANGED_TELEPORT) { llReleaseURL(url); // verbosity just in case llResetScript(); } } }
  8. Reading a notecard every time someone clicks is slow and inefficient. You should read the notecard in state_entry and pass each piece of data into a strided list as [site_name, weblink, site_name, web_link]. Then when the user touches the button for the link you can search the list with llListFindList. Each line of the notecard should be comma seperated values: Facebook, https://facebook.com Youtube, https://youtube.com Marketplace, https://marketplace.secondlife.com/ Then your code should look like this: key notecardQueryId; integer line; string link_name; list websites; integer allow = FALSE; // only allow touches if the notecard has been read completely; getURL(key id, string site) { site = llToLower(site); integer idx = llListFindList(websites,[site]); // searches the list for the name of the site and gets its index number. llRegionSayTo(id,0,"Visit our [ "+llList2String(websites,idx)+": "+llList2String(websites,idx+1)+"]!"); } default { state_entry() { line = 0; notecardQueryId = llGetNotecardLine("config", line); } changed(integer change) // editing the notecard triggers an inventory change so let's re-read the notecard. { if(change & CHANGED_INVENTORY) llResetScript(); } dataserver(key what, string data) { if (notecardQueryId == what) { if (data != EOF) { if(data !="") //if the line is not blank { list tmp = llPareStringToList(data,[","],[]) string link_name = llStringTrim(llToLower(llList2String(tmp, 0)),STRING_TRIM); // make all website names lower case so it's easier to search for in the list. string link = llStringTrim(llList2String(tmp, 1),STRING_TRIM); websites += [link_name] + [link]; } ++line; notecardQueryId = llGetNotecardLine("config", line); } else { llSay(0,"Reading of notecard complete"); allow = TRUE; } } } touch_start(integer total_number) { if(allow == TRUE) { string button = llGetLinkName(llDetectedLinkNumber(0)); key id = llDetectedKey(0); if (button == "marketplace") // Button's name { getUrl(id,"Marketplace"); } else if (button == "facebook") { getUrl(id,"Facebook"); } else if (button == "youtube") { getUrl(id,"Youtube"); } } } } I'm not really sure why you need a notecard in the first place though. Since you have to hard code the button names in the touch event you can just hard code the web links in it too. getURL(key id, string site, string url) { llRegionSayTo(id,0,"Visit our [ "+site+": "+url+"]!"); } default { touch_start(integer total_number) { string button = llGetLinkName(llDetectedLinkNumber(0)); key id = llDetectedKey(0); if (button == "marketplace") // Button's name { getURL(id, "Marketplace", "https://marketplace.secondlife.com/"); } else if (button == "facebook") { getURL(id, "Facebook", "https://facebook.com"); } else if (button == "youtube") { getURL(id, "Youtube", "https://youtube.com"); } } }
  9. I'm experimenting with storing data off-world using free resources and right now I'm trying out making pastes in pastebin. When I try make a new paste I get this error in http_response: The pastebin api at https://pastebin.com/doc_api says that data must be sent as UTF-8 so I've set MIMETYPE and ACCEPT to "text/plain;charset=utf-8" but still getting the error. Can anyone figure how to get past this error? // Script created by Gayngel of The Script Yard. // Follow the numbered steps in this script to set up and understand how this script works.. // Step 1: string api_key = ""; //To make a paste to pastebin you must have a pastebin account. Once you have created a pastebin account go to the pastebin api to retrieve you unique api key. The pastebin api is at https://pastebin.com/doc_api. You can also click the api button at the top of the website on pastebin.com to go to the api. Look for the section that shows your unique api key like in this screenshot https://i.imgur.com/Q1ul8Th.png. For example if your unique pi key is c46e0524312gbgh103bedh1aba2zj1l3 then the line in this script should be: string api_key = "c46e0524312gbgh103bedh1aba2zj1l3"; // N.B: Do NOT ever give out your api key to anyone!!! If you intend to sell this script in your object make the script no mod as no one should ever see your api key. If someone accesses your api key they can create spam pastes on your account and/or delete your pastes. It is probably best not to sell this in an object because each copy of the object will create a new paste on your account. You can only have a limited amount of unlisted/private pastes on a free pastebin account. // Step 2: string privacy = "2"; // Set the privacy of the paste your are going to make. // Set this 0 if you want the paste to be public for everyone to see on pastebin. // Set this to 1 if you want the paste to be public on pastebin but unlisted. // Set this to 2 if you want the paste to be private so only you can see it on pastebin. // Step 3: string paste_lang = ""; // If the text you are pasting is a programming/scripting language you can set this as the language key to make the paste highlight the program's syntax. For exmple if you want your paste to highlight in LSL the line in this script should look like this: string paste_lang = "lsl2"; //You can see a list of all highlighting keys on the pastebin api https://i.imgur.com/K5caEju.png // Leave this blank if the text you want to paste is not a program/script string paste_url = ""; //The url you get returned from pastebin when you make a paste. Leave this blank on first creating the paste. Once you get the URL to the created paste the script will tell you the URL to it. You can then copy and paste the URL to this line. string paste_message; // The message you want to send as a paste. You will set/write this in an event or function. integer coins; // a variable you can paste to and get from your paste. Number of coins collected. integer lives; // another variable you can paste to and get from your paste. Number of lives you have. integer goombahs; // another variable you can paste to and get from your paste. Number of goombahs you squashed. integer koopas; // another variable you can paste to and get from your paste. Number of koopa shell you kicked. key owner; key req; default { state_entry() { owner = llGetOwner(); } touch_end(integer num) { ++ coins; // increment coins ++lives; // increment lives; ++goombahs; // increment goombahs; ++koopas; // increment koopas; //Step 4 //Write the data you want to send as a paste paste_message = "message=Itsa you Mario! You have " + (string)lives + "lives left. You collected " + (string)coins + "coins. Your princess is in another castle\ngoombahs="+(string)goombahs+"\nkoopas="+(string)koopas; if(paste_url == "") // This will create the new paste. Since you haven't made a paste before the paste_url is blank. So a new paste will be created and return a url to the paste. { // curl_setopt($ch, CURLOPT_POSTFIELDS, 'api_option=paste&api_user_key='.$api_user_key.'&api_paste_private='.$api_paste_private.'&api_paste_name='.$api_paste_name.'&api_paste_expire_date='.$api_paste_expire_date.'&api_paste_format='.$api_paste_format.'&api_dev_key='.$api_dev_key.'&api_paste_code='.$api_paste_code.''); req = llHTTPRequest("https://pastebin.com/api/api_post.php?api_option=paste&api_dev_key="+llEscapeURL(api_key)+"&api_paste_private="+llEscapeURL(privacy)+"&api_paste_name="+llEscapeURL("test_lsl")+"&api_paste_code="+llEscapeURL(paste_message),[HTTP_MIMETYPE,"text/plain;charset=utf-8",HTTP_METHOD,"POST",HTTP_EXTENDED_ERROR,TRUE, HTTP_ACCEPT, "text/plain;charset=utf-8"],"Ping"); } else // This will update the paste. Since a paste was created there is a URL to it. Delete the paste and create a new one. { } } http_request(key reqID, string method, string body ) { llOwnerSay("REQUEST: " + body); } http_response(key reqID, integer status, list metadata, string body) { llOwnerSay("RESPONSE:" +body + " STATUS:" + (string)status + "METADATA: " + llList2CSV(metadata)); } }
  10. That math and rotation stuff gives me a headache.🥴 It works though, thank you Lucia.
  11. I really want to detect if a sitter on an object presses the ESC key to reset the camera, but of course that is not possible. The next best thing is to get the camera pos/rot and compare to the desired pos/rot. I defined a camera rot/pos using llSetCameraEyeOffset and llSetCameraAtOffset so when the ESC key is pressed the camera snaps to my defined pos/rot. I want to be able to get the camera pos/rot from when an avatar is sitting on the object and see if the camera is say <2,3,1> and at 90 degrees both pos&rot relative to the object. Using a timer I want to compare if the camera is at the desired pos/rot but llGetCameraPos and llGetCameraRot use region co-ordinates while llSetCameraEyeOffset and llSetCameraAtOffset use local co-ordinates. Is there a way to get local pos from a region pos or vice versa so I can compare? The script would looksomething like: vector cam_pos; roatation sitRot; default { state_entry() { llSitTarget(<0.3,0.0,0.2>,ZERO_ROTATION); sitRot = llAxisAngle2Rot(<0.0, 0.0, 90.0>, 0.0 * DEG_TO_RAD); cam_pos = <2, 0, 1> * sitRot; llSetCameraEyeOffset(<0.05, 0.1, 1.5> * sitRot); llSetCameraAtOffset(cam_pos); } changed(integer change) { if(change & CHANGED_LINK) { if(llAvatarOnSitTarget() != NULL_KEY) llRequestPermissions(llAvatarOnSitTarget() PERMISSION_TRACK_CAMERA); else lSetTimerEvent(0.0); } } run_time_permissions(integer perm) { if(perm & PERMISSION_TRACK_CAMERA) { llSetTimerEvent(0.0); llSetTimerEvent(1.0); } } timer() { vector avi_pos = llGetCameraPos(); if(cam_pos == avi_pos) // this is what I need to compare. How can I compare a region pos to a local pos? { // do stuff } } }
  12. https://about.fb.com/news/2021/08/introducing-horizon-workrooms-remote-collaboration-reimagined/
  13. Well I thought this post was about me (since you spoke to me inworld about it) up until you saying the scripter gave you a cost to produce this ban/security system, but I did not give you any quote on cost. I said to you that my RL commitments are taking priority right now. I don't know who else you spoke to, but all I'll say is if I did have the time to produce the system: bells, whistles, security features & all; for L$50k I would give you the system full perm and all rights.
  14. You can write a check for a sim restart with llRequestSimulatorData before storing your data or processing it: http://wiki.secondlife.com/wiki/LlRequestSimulatorData There is a "stopping" value returned when calling DATA_SIM_STATUS which will tell you if a region is about to stop/shutdown/restart.
  15. I need to resize some meshes with llSetScale() but I only want to resize one side of the mesh. Is there way to do a path cut in Blender?
  16. I've been trying to work with Google App Script in Open Sim using the same scripts I have in SL but get no input/response from the App script. It seems like OpenSim URLs are not recognized by Google. If anyone can get scripts in Open Sim to work with Google App Script please let me know how you did it.
  17. @Xiija You can use URL parameters to send variables. Instead of using the body of the POST, just append the variables to the URL. i.e: After the App Script URL add a "?" then a key/id pair separated by "&" e.g: llHTTPRequest("https://script.google.com/macros/s/AKlycby72IWfkiup3YZdHtGk2bHSX147nhalhawYCKufV5vgvAFXsrNQ/exec?uuid=a9ba2797-81af-429d-9833-51127ad5593c&name=Gayngel&timestamp=2021/02/27-10:32",[HTTP_METHOD,POST],"") In the App Script you then retrieve the data from the e argument in doPost(e). The e argument represents the group of requests parameters you specify. To get each data separately you append the specified key to the e parameter field. doPost(e) { var uuid = e.parameter.uuid; // Will be a9ba2797-81af-429d-9833-51127ad5593c var name = e.parameter.name; // Will be Gayngel var timestamp = e.paramter.timestamp; // Wil be 2021/02/27-10:32 }
  18. MP4 doesn't work actually. Issues with licensing. Live streams encode to MP4 which is why they don't work. @Qie Niangao How are you getting them to play? Edit: Nevermind I read previous posts elsewhere. Needs FS Beta or the newest SL Viewer.
  19. If you have the SURL you can trying logging into the place. Copy and paste the SURL to a notepad or something and extract the region and co-ordinates of the place. i.e everything that comes after "https://maps.secondlife.com/secondlife/" For example: https://maps.secondlife.com/secondlife/Bonaire03/111/130/22/ <------ Copy out Bonaire03/111/130/22/ At the login second life paste the region and co-ordinates in the "Last Location / Home / Type region box". Then just click login. You will either be logged into the place you want to visit or a safe zone if it does not exist anymore.
  20. I've been using Google App Script to store date in a sheet for scripts for about 3-4 years now. I sell a greeter that can store about 200k visitor UUIDs and data like responses to ""Can we use display your profile pic here?", who took a landmdark, how long the avatar stayed on the parcel, unique visitor counts, etc. Google Sheets and App Script are really a robust way to store persistent data.
  21. Looking to rent a private island 1/4 sim residential/commercial use and club allowed. Club will be used only once a month.
  22. Is there a UDF somewhere that can iterate over multiple lists and delete duplicate elements and keep the element in just one list? (sort of like the .zip()function in Python) e.g: list a = ["Apples"]; list b = ["Apples"]; list c = ["Apples"]; if the element "Apples" in list a is also in list b and list c delete it from both list b and c.
  23. I am a programmer with 5 years experience in scripting with LSL. I enjoy building custom systems ground-up and will provide low lag solutions to my customer's specifications. I can write simple, minor fixes to existing scripts, tip jars, club systems, dialog menus, detections, HUDs and vendors to more advanced systems such as pose systems, RLV, vehicles, pathfinding, weaponry, SL experiences and HTTP for external coms to websites and databases. (Also experienced in HTML/CSS, php, SQL, Ruby, Rails, Python and Javascript ) Script adaptations and library resources if used will be fully cited. I work closely with my clients providing working demos of their products with full perm models (with user license) on completion and delivery. Note: Models will be mockups to present the functioning script, clients must finalise prim designs and builds themselves. Clients may also visit my workshop to see the progress made on their projects. Price is dependent on complexity of the project. Scripts will be full perm on payment . Delivery may be a few hours to weeks also dependent on script complexity and work load. IM me inworld or visit The Script Yard for a consultation. If I'm offline IMs will go to email and will get back to you ASAP. (Forwarning: Adult rated profile) Copy/paste this link to the nearby chat window in your viewer, press enter then click on my name in chat to open my profile: secondlife:///app/agent/a9ba2797-81af-429d-9833-51127ad5593c/about Marketplace Store: https://marketplace.secondlife.com/stores/149734
  24. I have a json string that consists of key/value pairs, each pair a JSON_OBJECT. The values are JSON_OBJECTs that contain key/value pairs themselves. So JSON_OBJECTs nested in a JSON_OBJECT. e.g: {main_key, {nested_key,nested_value,nested_key,nested_value,nested_key,nested_value},{main_key,{nested_key,nested_value,nested_key,nested_value}},{main_key,{nested_key,nested_value,nested_key,nested_value}}} Is there a way to get the main_key in the JSON_OBJECT by searching the nested_value? Like can I llListFindList(blah blah blah) - 1 or something similar?
×
×
  • Create New...