Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // (c) The owner of Avatar Jeff Kelley, 2010
- //
- // This script is licensed under Creative Commons BY-NC-SA
- // See <http://creativecommons.org/licenses/by-nc-sa/3.0/>
- //
- // You may not use this work for commercial purposes.
- // You must attribute the work to the author, Jeff Kelley.
- // You may distribute, alter, transform, or build upon this work
- // as long as you do not delete the name of the original author.
- //
- // Version 2.0 of August, 2020
- // Removed coordinates check since no longer a viewer limitation.
- // Removed the LSL notecard server datasource since barely used.
- // Changed HTTP allowed satuses for opensim 0.9.2.0 and onward.
- // Removed map teleport option (because it is not fun).
- // Added an administration menu.
- //
- // The script reads a list of destinations from a datasource.
- // A datasource may be either a notecard or a web text document.
- // The format of the datasource is :
- //
- // display_name|hg_address|x,y,z
- // display_name : The name to appear on the board
- // hg_address : Hypergrid address (e.g. hg.osgrid.org:80)
- // x,y,z : Optional landing point, comma separated
- //
- // Examples:
- //
- // OSGrid|hg.osgrid.org:80
- // OSGrid LBSA Plaza|hg.osgrid.org:80:LBSA Plaza
- // OSGrid Sandbox Plaza|hg.osgrid.org:80:Sandbox Plaza|60,80,20
- //
- // Empty lines and lines beginning with // are comments.
- // For backward compatibility, the V1 format is supported.
- //
- // The datasource locator has two forms :
- //
- // http://your_server/path_to_file A web file
- // card://name_of_card A notecard
- //
- // ***** EDIT THIS TO CHOOSE YOUR DATASOURCE
- string datasource = "card://Destinations";
- integer DEBUG_ON = FALSE;
- DEBUG(string message) {if (DEBUG_ON) llOwnerSay(message);}
- SetDebug (integer on) {
- DEBUG_ON = on;
- if (DEBUG_ON) llSetLinkColor (LINK_ROOT, <1.0,0.4,0.0>, ALL_SIDES);
- else llSetLinkColor (LINK_ROOT, <1.0,1.0,1.0>, ALL_SIDES);
- }
- ///////////////////////////////////////////////////////////////////
- // Part 1 : Datasource -- Read a file in script's memory
- ///////////////////////////////////////////////////////////////////
- string datasorceData; // Place for the content of the datasource
- readDataSource(string source) {
- list parse = llParseString2List (source, ["/"],[]);
- string s0 = llList2String (parse, 0);
- string s1 = llList2String (parse, 1);
- // Web server : falls through http_response event
- if (s0 == "http:") sendHTTPRequest (source);
- // Notecard : falls through dataserver event
- if (s0 == "card:") readNotecard (s1);
- }
- ///////////////////
- // Notecard reader
- ///////////////////
- // Since osGetNotecard has Threat Level = VeryHigh
- // we stick to the old, slow, clunky notecard reader
- string ncName; // Name of the notecard to be read
- key ncQueryID; // id of dataserver queries
- integer ncLine; // Current line being read
- readNotecard (string name) {
- ncName = name;
- ncLine = 0;
- ncQueryID = llGetNotecardLine(ncName, ncLine++); // request first line
- }
- addFromNotecard (string data) {
- datasorceData += data+"\n";
- ncQueryID = llGetNotecardLine(ncName, ncLine++); // Request next line
- }
- ///////////////////
- // Http stuff
- ///////////////////
- key httpQueryId;
- sendHTTPRequest (string url) {
- httpQueryId = llHTTPRequest(url,
- [ HTTP_METHOD, "GET",
- HTTP_BODY_MAXLENGTH, 16384,
- HTTP_MIMETYPE,"text/plain;charset=utf-8"
- ], "");
- }
- string URI2hostport (string uri) {
- list parse = llParseString2List (uri, [":"], []);
- return llList2String (parse, 0)
- +":" + llList2String (parse, 1);
- }
- ///////////////////////////////////////////////////////////////////
- // Part 2 : Datasource parsing
- ///////////////////////////////////////////////////////////////////
- parseDataSource (string data) {
- DEBUG ("--Parsing datasource");
- list lines = llParseString2List (data,["\n"],[]);
- integer nl = llGetListLength (lines);
- integer i; for (i=0;i<nl;i++)
- parseLine (llList2String(lines,i));
- }
- parseLine (string line) {
- if (line == "") return; // Ignore empty lines
- if (llGetSubString (line,0,1) == "//") return; // This is a comment
- string display_name;
- string hg_address;
- string landing_pt;
- list parse = llParseStringKeepNulls (line, ["|"],[]);
- integer numFields = llGetListLength (parse);
- if (numFields > 3) {
- // Parse a V1 destination
- string v1_grid = llList2String (parse, 0);
- string v1_region = llList2String (parse, 1);
- string v1_location = llList2String (parse, 2);
- string v1_address = llList2String (parse, 3);
- string v1_landing = llList2String (parse, 4);
- display_name = v1_grid+" "+v1_region;
- hg_address = v1_address;
- landing_pt = v1_landing;
- } else {
- // Parse a V2 destination
- display_name = llList2String (parse, 0);
- hg_address = llList2String (parse, 1);
- landing_pt = llList2String (parse, 2);
- }
- // Parse landing point "x,y,z" to vector
- parse = llParseString2List (landing_pt, [","],[]);
- integer x = llList2Integer (parse, 0);
- integer y = llList2Integer (parse, 1);
- integer z = llList2Integer (parse, 2);
- vector landing_vec = <x, y, z>;
- if (landing_vec == ZERO_VECTOR) landing_vec = <128,128,20>;
- // Add to destination database
- DEBUG ("Adding destination "+display_name
- +" at address "+hg_address+" @ "+(string)landing_vec);
- add_destination (display_name, hg_address, landing_vec);
- }
- ////////////////////////
- // Destinations database
- ////////////////////////
- list destinations; // Strided list for destinations
- integer DESC_IDX = 0; // Index of description in list
- integer ADDR_IDX = 1; // Index of hg address in list
- integer LAND_IDX = 2; // Index of landing point in list
- integer N_FIELDS = 3; // Total number of fields
- init_destinations() {
- destinations = [];
- }
- add_destination (string desc, string addr, vector land) {
- destinations += [ desc, addr, land ];
- }
- string get_dst_displayname (integer n) { // Get description for destination n
- return llList2String (destinations, N_FIELDS*n +DESC_IDX);
- }
- string get_dst_hgaddress (integer n) { // Get hg address for destination n
- return llList2String (destinations, N_FIELDS*n +ADDR_IDX);
- }
- vector get_dst_landingpoint (integer n) { // Get landing point for destination n
- return llList2Vector (destinations, N_FIELDS*n +LAND_IDX);
- }
- ////////////////////////////////////////////////////////////
- // Part 3 : Drawing
- ////////////////////////////////////////////////////////////
- integer TEXTURE_SIZE = 512;
- integer DISPLAY_SIDE = 4;
- integer FONT_SIZE = 10; // Depends on TEXTURE_SIZE
- integer COLUMNS = 3;
- integer ROWS = 16;
- string validCellColor = "CadetBlue";
- string invalCellColor = "IndianRed";
- string emptyCellColor = "DarkGray";
- string cellBorderColor = "White";
- string backgroundColor = "Gray";
- string drawList;
- displayBegin() {
- drawList = "";
- }
- displayEnd() {
- osSetDynamicTextureData ( "", "vector", drawList,
- "width:"+(string)TEXTURE_SIZE+",height:"+(string)TEXTURE_SIZE, 0);
- }
- drawCell (integer x, integer y) {
- integer CELL_HEIGHT = TEXTURE_SIZE / ROWS;
- integer CELL_WIDHT = TEXTURE_SIZE / COLUMNS;
- integer xTopLeft = x*CELL_WIDHT;
- integer yTopLeft = y*CELL_HEIGHT;
- // Draw grid
- drawList = osSetPenColor (drawList, cellBorderColor);
- drawList = osMovePen (drawList, xTopLeft, yTopLeft);
- drawList = osDrawRectangle (drawList, CELL_WIDHT, CELL_HEIGHT);
- integer index = (y+x*ROWS);
- string cellName = get_dst_displayname(index);
- integer cellValid = TRUE; // Distance check no longer necessary
- string cellBbackground;
- if (cellName == "") cellBbackground = emptyCellColor; else
- if (cellValid) cellBbackground = validCellColor; else
- cellBbackground = invalCellColor;
- // Fill background
- drawList = osSetPenColor (drawList, cellBbackground);
- drawList = osMovePen (drawList, xTopLeft+2, yTopLeft+2);
- drawList = osDrawFilledRectangle (drawList, CELL_WIDHT-3, CELL_HEIGHT-3);
- xTopLeft += 2; // Center text in cell
- yTopLeft += 6; // Center text in cell
- drawList = osSetPenColor (drawList, "Black");
- drawList = osMovePen (drawList, xTopLeft, yTopLeft);
- drawList = osDrawText (drawList, cellName);
- }
- drawTable() {
- displayBegin();
- drawList = osSetPenSize (drawList, 1);
- drawList = osSetFontSize (drawList, FONT_SIZE);
- drawList = osMovePen (drawList, 0, 0);
- drawList = osSetPenColor (drawList, backgroundColor);
- drawList = osDrawFilledRectangle (drawList, TEXTURE_SIZE, TEXTURE_SIZE);
- integer x; integer y;
- for (x=0; x<COLUMNS; x++)
- for (y=0; y<ROWS; y++)
- drawCell (x, y);
- displayEnd();
- }
- integer getCellClicked(vector point) {
- integer y = (ROWS-1) - llFloor(point.y*ROWS); // Top to bottom
- integer x = llFloor(point.x*COLUMNS); // Left to right
- integer index = (y+x*ROWS);
- return index;
- }
- //////////////////////////////////////////////////////////////////
- // Part 4 : Action routines: When touched ; When http test returns
- //////////////////////////////////////////////////////////////////
- string CLICK_SOUND = "clickSound"; // Sound to play when board clicked
- string TELPT_SOUND = "teleportSound"; // Sound to play when teleported
- integer HTTP_TIMEOUT = 10; // Timeout for remote HTTP check
- integer TIMEOUT_STATUS = -1; // Pseudo HTTP status to return upon timeout
- integer JUMP_DELAY = 2; // Time to wait before teleport
- string hippo_url; // URL for http check
- key telep_agent; // For osTeleportAgent
- string telep_address; // For osTeleportAgent
- vector telep_landing; // For osTeleportAgent
- integer HandleTouch (integer dst_index, key who) {
- string dest = get_dst_displayname (dst_index);
- string addr = get_dst_hgaddress (dst_index);
- vector land = get_dst_landingpoint (dst_index);
- if (dest == "") return FALSE; // Empty cell
- llWhisper (0, "You have selected "+dest+". Checking host...");
- // Prepare globals before jumping
- telep_agent = who; // Pass to HTTPCheckCallback below
- telep_address = addr; // Pass to HTTPCheckCallback below
- telep_landing = land; // Pass to HTTPCheckCallback below
- hippo_url = "http://"+URI2hostport(addr); // Pass to http check
- llTriggerSound (CLICK_SOUND, 1.0);
- return TRUE;
- }
- HTTPCheckCallback(integer http_status) {
- // Accept 200 for legacy ROBUST and WIFI enabled ROBUST
- // Accept 404 for WIFI-less ROBUST 0.9.2.0 and onwards
- if ((http_status == 200) || (http_status == 404)) {
- llWhisper (0, "Fasten your seat belt, we move!!!");
- if (DEBUG_ON) return;
- llPlaySound (TELPT_SOUND, 1.0); llSleep (JUMP_DELAY);
- osTeleportAgent(telep_agent, telep_address, telep_landing, ZERO_VECTOR);
- } else {
- llWhisper (0, "Sorry, host is not available (HTTP status "+(integer)http_status+")");
- }
- }
- // Admin menu
- string adminmenuTitle = "Admin menu";
- string adminmenuOpt1 = "Reload";
- string adminmenuOpt2 = "Debug On";
- string adminmenuOpt3 = "Debug Off";
- integer admindialogChannel = -9000;
- integer admindialogHandle;
- AdminMenu() {
- list adminmenuOptions = [ adminmenuOpt1, adminmenuOpt2, adminmenuOpt3 ];
- admindialogHandle = llListen(admindialogChannel, "", llGetOwner(), "");
- llDialog (llGetOwner(), adminmenuTitle, adminmenuOptions, admindialogChannel);
- llSetTimerEvent(30);
- }
- AdminMenuCallback(string message) {
- if (message == adminmenuOpt1) state default;
- if (message == adminmenuOpt2) SetDebug(TRUE);
- if (message == adminmenuOpt3) SetDebug(FALSE);
- llListenRemove (admindialogHandle);
- llSetTimerEvent (0);
- }
- AdminMenuTimetout() {
- llListenRemove (admindialogHandle);
- llSetTimerEvent (0);
- }
- ///////////////////////////////////////////////////////////////////
- // State 1 : read the data and draw the board
- ///////////////////////////////////////////////////////////////////
- default {
- state_entry() {
- SetDebug (DEBUG_ON);
- init_destinations();
- llOwnerSay ("Reading data from "+datasource);
- readDataSource (datasource);
- }
- // Handler for card:// datasource
- dataserver(key id, string data) {
- // Internal card reader
- if (id == ncQueryID) {
- if (data != EOF) addFromNotecard (data);
- else state ready; // File in datasorceData
- }
- }
- // Handler fot http:// datasource
- http_response(key id,integer status, list meta, string body) {
- if (id != httpQueryId) return;
- datasorceData = body;
- state ready; // File in datasorceData
- }
- state_exit() {
- llOwnerSay ("Done. Initializing board");
- parseDataSource(datasorceData);
- drawTable();
- }
- }
- ///////////////////////////////////////////////////////////////////
- // State 2 : running, we pass most of our time here
- ///////////////////////////////////////////////////////////////////
- state ready {
- state_entry() {
- llWhisper (0, llGetScriptName()+" Ready");
- }
- touch_start (integer n) {
- key whoClick = llDetectedKey(0);
- vector point = llDetectedTouchST(0);
- integer face = llDetectedTouchFace(0);
- integer link = llDetectedLinkNumber(0);
- // If owner touched outside board, display admin menu
- if (link != LINK_ROOT) {
- if ( (whoClick == llGetOwner())
- || (whoClick == llGetCreator()) )
- AdminMenu();
- return;
- }
- if (point == TOUCH_INVALID_TEXCOORD) return;
- if (face != DISPLAY_SIDE) return;
- integer ok = HandleTouch (getCellClicked(point), whoClick);
- if (!ok) return; // Empty cell
- // Proceed to http check
- state hippos; // Perform HTTP check
- }
- changed(integer what) {
- if (what & CHANGED_REGION) llResetScript();
- if (what & CHANGED_INVENTORY) llResetScript();
- if (what & CHANGED_REGION_RESTART) llResetScript();
- }
- listen(integer channel, string name, key id, string message) {
- if (channel == admindialogChannel)
- AdminMenuCallback (message);
- }
- timer() {
- AdminMenuTimetout();
- }
- on_rez (integer parm) {
- llResetScript();
- }
- }
- ///////////////////////////////////////////////////////////////////
- // State 3 : HTTP host check
- ///////////////////////////////////////////////////////////////////
- state hippos {
- state_entry() {
- DEBUG ("HTTP "+hippo_url);
- sendHTTPRequest (hippo_url);
- llSetTimerEvent (HTTP_TIMEOUT);
- }
- http_response(key id,integer status, list meta, string body) {
- DEBUG ("HTTP "+(string)status);
- if (id != httpQueryId) return;
- HTTPCheckCallback (status);
- state ready;
- }
- timer() {
- llSetTimerEvent (0);
- HTTPCheckCallback (TIMEOUT_STATUS);
- state ready;
- }
- }
Add Comment
Please, Sign In to add comment