Guest User

HGBoard v2.0

a guest
Sep 7th, 2020
166
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.32 KB | None | 0 0
  1. // (c) The owner of Avatar Jeff Kelley, 2010
  2. //
  3. // This script is licensed under Creative Commons BY-NC-SA
  4. // See <http://creativecommons.org/licenses/by-nc-sa/3.0/>
  5. //
  6. // You may not use this work for commercial purposes.
  7. // You must attribute the work to the author, Jeff Kelley.
  8. // You may distribute, alter, transform, or build upon this work
  9. // as long as you do not delete the name of the original author.
  10. //
  11. // Version 2.0 of August, 2020
  12. // Removed coordinates check since no longer a viewer limitation.
  13. // Removed the LSL notecard server datasource since barely used.
  14. // Changed HTTP allowed satuses for opensim 0.9.2.0 and onward.
  15. // Removed map teleport option (because it is not fun).
  16. // Added an administration menu.
  17. //
  18. // The script reads a list of destinations from a datasource.
  19. // A datasource may be either a notecard or a web text document.
  20. // The format of the datasource is :
  21. //
  22. // display_name|hg_address|x,y,z
  23. // display_name : The name to appear on the board
  24. // hg_address : Hypergrid address (e.g. hg.osgrid.org:80)
  25. // x,y,z : Optional landing point, comma separated
  26. //
  27. // Examples:
  28. //
  29. // OSGrid|hg.osgrid.org:80
  30. // OSGrid LBSA Plaza|hg.osgrid.org:80:LBSA Plaza
  31. // OSGrid Sandbox Plaza|hg.osgrid.org:80:Sandbox Plaza|60,80,20
  32. //
  33. // Empty lines and lines beginning with // are comments.
  34. // For backward compatibility, the V1 format is supported.
  35. //
  36. // The datasource locator has two forms :
  37. //
  38. // http://your_server/path_to_file A web file
  39. // card://name_of_card A notecard
  40. //
  41. // ***** EDIT THIS TO CHOOSE YOUR DATASOURCE
  42. string datasource = "card://Destinations";
  43.  
  44.  
  45.  
  46. integer DEBUG_ON = FALSE;
  47. DEBUG(string message) {if (DEBUG_ON) llOwnerSay(message);}
  48.  
  49. SetDebug (integer on) {
  50. DEBUG_ON = on;
  51. if (DEBUG_ON) llSetLinkColor (LINK_ROOT, <1.0,0.4,0.0>, ALL_SIDES);
  52. else llSetLinkColor (LINK_ROOT, <1.0,1.0,1.0>, ALL_SIDES);
  53. }
  54.  
  55. ///////////////////////////////////////////////////////////////////
  56. // Part 1 : Datasource -- Read a file in script's memory
  57. ///////////////////////////////////////////////////////////////////
  58.  
  59. string datasorceData; // Place for the content of the datasource
  60.  
  61. readDataSource(string source) {
  62. list parse = llParseString2List (source, ["/"],[]);
  63. string s0 = llList2String (parse, 0);
  64. string s1 = llList2String (parse, 1);
  65.  
  66. // Web server : falls through http_response event
  67. if (s0 == "http:") sendHTTPRequest (source);
  68.  
  69. // Notecard : falls through dataserver event
  70. if (s0 == "card:") readNotecard (s1);
  71. }
  72.  
  73. ///////////////////
  74. // Notecard reader
  75. ///////////////////
  76.  
  77. // Since osGetNotecard has Threat Level = VeryHigh
  78. // we stick to the old, slow, clunky notecard reader
  79.  
  80. string ncName; // Name of the notecard to be read
  81. key ncQueryID; // id of dataserver queries
  82. integer ncLine; // Current line being read
  83.  
  84. readNotecard (string name) {
  85. ncName = name;
  86. ncLine = 0;
  87. ncQueryID = llGetNotecardLine(ncName, ncLine++); // request first line
  88. }
  89.  
  90. addFromNotecard (string data) {
  91. datasorceData += data+"\n";
  92. ncQueryID = llGetNotecardLine(ncName, ncLine++); // Request next line
  93. }
  94.  
  95. ///////////////////
  96. // Http stuff
  97. ///////////////////
  98.  
  99. key httpQueryId;
  100.  
  101. sendHTTPRequest (string url) {
  102. httpQueryId = llHTTPRequest(url,
  103. [ HTTP_METHOD, "GET",
  104. HTTP_BODY_MAXLENGTH, 16384,
  105. HTTP_MIMETYPE,"text/plain;charset=utf-8"
  106. ], "");
  107. }
  108.  
  109. string URI2hostport (string uri) {
  110. list parse = llParseString2List (uri, [":"], []);
  111. return llList2String (parse, 0)
  112. +":" + llList2String (parse, 1);
  113. }
  114.  
  115.  
  116. ///////////////////////////////////////////////////////////////////
  117. // Part 2 : Datasource parsing
  118. ///////////////////////////////////////////////////////////////////
  119.  
  120. parseDataSource (string data) {
  121. DEBUG ("--Parsing datasource");
  122. list lines = llParseString2List (data,["\n"],[]);
  123. integer nl = llGetListLength (lines);
  124. integer i; for (i=0;i<nl;i++)
  125. parseLine (llList2String(lines,i));
  126. }
  127.  
  128. parseLine (string line) {
  129. if (line == "") return; // Ignore empty lines
  130. if (llGetSubString (line,0,1) == "//") return; // This is a comment
  131.  
  132. string display_name;
  133. string hg_address;
  134. string landing_pt;
  135.  
  136. list parse = llParseStringKeepNulls (line, ["|"],[]);
  137. integer numFields = llGetListLength (parse);
  138.  
  139. if (numFields > 3) {
  140. // Parse a V1 destination
  141. string v1_grid = llList2String (parse, 0);
  142. string v1_region = llList2String (parse, 1);
  143. string v1_location = llList2String (parse, 2);
  144. string v1_address = llList2String (parse, 3);
  145. string v1_landing = llList2String (parse, 4);
  146. display_name = v1_grid+" "+v1_region;
  147. hg_address = v1_address;
  148. landing_pt = v1_landing;
  149. } else {
  150. // Parse a V2 destination
  151. display_name = llList2String (parse, 0);
  152. hg_address = llList2String (parse, 1);
  153. landing_pt = llList2String (parse, 2);
  154. }
  155.  
  156. // Parse landing point "x,y,z" to vector
  157.  
  158. parse = llParseString2List (landing_pt, [","],[]);
  159. integer x = llList2Integer (parse, 0);
  160. integer y = llList2Integer (parse, 1);
  161. integer z = llList2Integer (parse, 2);
  162.  
  163. vector landing_vec = <x, y, z>;
  164. if (landing_vec == ZERO_VECTOR) landing_vec = <128,128,20>;
  165.  
  166. // Add to destination database
  167.  
  168. DEBUG ("Adding destination "+display_name
  169. +" at address "+hg_address+" @ "+(string)landing_vec);
  170.  
  171. add_destination (display_name, hg_address, landing_vec);
  172. }
  173.  
  174. ////////////////////////
  175. // Destinations database
  176. ////////////////////////
  177.  
  178. list destinations; // Strided list for destinations
  179. integer DESC_IDX = 0; // Index of description in list
  180. integer ADDR_IDX = 1; // Index of hg address in list
  181. integer LAND_IDX = 2; // Index of landing point in list
  182. integer N_FIELDS = 3; // Total number of fields
  183.  
  184. init_destinations() {
  185. destinations = [];
  186. }
  187.  
  188. add_destination (string desc, string addr, vector land) {
  189. destinations += [ desc, addr, land ];
  190. }
  191.  
  192. string get_dst_displayname (integer n) { // Get description for destination n
  193. return llList2String (destinations, N_FIELDS*n +DESC_IDX);
  194. }
  195.  
  196. string get_dst_hgaddress (integer n) { // Get hg address for destination n
  197. return llList2String (destinations, N_FIELDS*n +ADDR_IDX);
  198. }
  199.  
  200. vector get_dst_landingpoint (integer n) { // Get landing point for destination n
  201. return llList2Vector (destinations, N_FIELDS*n +LAND_IDX);
  202. }
  203.  
  204. ////////////////////////////////////////////////////////////
  205. // Part 3 : Drawing
  206. ////////////////////////////////////////////////////////////
  207.  
  208. integer TEXTURE_SIZE = 512;
  209. integer DISPLAY_SIDE = 4;
  210. integer FONT_SIZE = 10; // Depends on TEXTURE_SIZE
  211. integer COLUMNS = 3;
  212. integer ROWS = 16;
  213.  
  214. string validCellColor = "CadetBlue";
  215. string invalCellColor = "IndianRed";
  216. string emptyCellColor = "DarkGray";
  217. string cellBorderColor = "White";
  218. string backgroundColor = "Gray";
  219.  
  220. string drawList;
  221.  
  222. displayBegin() {
  223. drawList = "";
  224. }
  225.  
  226. displayEnd() {
  227. osSetDynamicTextureData ( "", "vector", drawList,
  228. "width:"+(string)TEXTURE_SIZE+",height:"+(string)TEXTURE_SIZE, 0);
  229. }
  230.  
  231. drawCell (integer x, integer y) {
  232. integer CELL_HEIGHT = TEXTURE_SIZE / ROWS;
  233. integer CELL_WIDHT = TEXTURE_SIZE / COLUMNS;
  234. integer xTopLeft = x*CELL_WIDHT;
  235. integer yTopLeft = y*CELL_HEIGHT;
  236.  
  237. // Draw grid
  238.  
  239. drawList = osSetPenColor (drawList, cellBorderColor);
  240. drawList = osMovePen (drawList, xTopLeft, yTopLeft);
  241. drawList = osDrawRectangle (drawList, CELL_WIDHT, CELL_HEIGHT);
  242.  
  243. integer index = (y+x*ROWS);
  244. string cellName = get_dst_displayname(index);
  245. integer cellValid = TRUE; // Distance check no longer necessary
  246.  
  247. string cellBbackground;
  248. if (cellName == "") cellBbackground = emptyCellColor; else
  249. if (cellValid) cellBbackground = validCellColor; else
  250. cellBbackground = invalCellColor;
  251.  
  252. // Fill background
  253.  
  254. drawList = osSetPenColor (drawList, cellBbackground);
  255. drawList = osMovePen (drawList, xTopLeft+2, yTopLeft+2);
  256. drawList = osDrawFilledRectangle (drawList, CELL_WIDHT-3, CELL_HEIGHT-3);
  257.  
  258. xTopLeft += 2; // Center text in cell
  259. yTopLeft += 6; // Center text in cell
  260. drawList = osSetPenColor (drawList, "Black");
  261. drawList = osMovePen (drawList, xTopLeft, yTopLeft);
  262. drawList = osDrawText (drawList, cellName);
  263. }
  264.  
  265. drawTable() {
  266. displayBegin();
  267.  
  268. drawList = osSetPenSize (drawList, 1);
  269. drawList = osSetFontSize (drawList, FONT_SIZE);
  270.  
  271. drawList = osMovePen (drawList, 0, 0);
  272. drawList = osSetPenColor (drawList, backgroundColor);
  273. drawList = osDrawFilledRectangle (drawList, TEXTURE_SIZE, TEXTURE_SIZE);
  274.  
  275. integer x; integer y;
  276. for (x=0; x<COLUMNS; x++)
  277. for (y=0; y<ROWS; y++)
  278. drawCell (x, y);
  279.  
  280. displayEnd();
  281. }
  282.  
  283. integer getCellClicked(vector point) {
  284. integer y = (ROWS-1) - llFloor(point.y*ROWS); // Top to bottom
  285. integer x = llFloor(point.x*COLUMNS); // Left to right
  286. integer index = (y+x*ROWS);
  287. return index;
  288. }
  289.  
  290.  
  291. //////////////////////////////////////////////////////////////////
  292. // Part 4 : Action routines: When touched ; When http test returns
  293. //////////////////////////////////////////////////////////////////
  294.  
  295. string CLICK_SOUND = "clickSound"; // Sound to play when board clicked
  296. string TELPT_SOUND = "teleportSound"; // Sound to play when teleported
  297. integer HTTP_TIMEOUT = 10; // Timeout for remote HTTP check
  298. integer TIMEOUT_STATUS = -1; // Pseudo HTTP status to return upon timeout
  299. integer JUMP_DELAY = 2; // Time to wait before teleport
  300.  
  301. string hippo_url; // URL for http check
  302. key telep_agent; // For osTeleportAgent
  303. string telep_address; // For osTeleportAgent
  304. vector telep_landing; // For osTeleportAgent
  305.  
  306. integer HandleTouch (integer dst_index, key who) {
  307. string dest = get_dst_displayname (dst_index);
  308. string addr = get_dst_hgaddress (dst_index);
  309. vector land = get_dst_landingpoint (dst_index);
  310.  
  311. if (dest == "") return FALSE; // Empty cell
  312.  
  313. llWhisper (0, "You have selected "+dest+". Checking host...");
  314.  
  315. // Prepare globals before jumping
  316.  
  317. telep_agent = who; // Pass to HTTPCheckCallback below
  318. telep_address = addr; // Pass to HTTPCheckCallback below
  319. telep_landing = land; // Pass to HTTPCheckCallback below
  320.  
  321. hippo_url = "http://"+URI2hostport(addr); // Pass to http check
  322.  
  323. llTriggerSound (CLICK_SOUND, 1.0);
  324. return TRUE;
  325. }
  326.  
  327. HTTPCheckCallback(integer http_status) {
  328. // Accept 200 for legacy ROBUST and WIFI enabled ROBUST
  329. // Accept 404 for WIFI-less ROBUST 0.9.2.0 and onwards
  330. if ((http_status == 200) || (http_status == 404)) {
  331. llWhisper (0, "Fasten your seat belt, we move!!!");
  332. if (DEBUG_ON) return;
  333. llPlaySound (TELPT_SOUND, 1.0); llSleep (JUMP_DELAY);
  334. osTeleportAgent(telep_agent, telep_address, telep_landing, ZERO_VECTOR);
  335. } else {
  336. llWhisper (0, "Sorry, host is not available (HTTP status "+(integer)http_status+")");
  337. }
  338. }
  339.  
  340. // Admin menu
  341.  
  342. string adminmenuTitle = "Admin menu";
  343. string adminmenuOpt1 = "Reload";
  344. string adminmenuOpt2 = "Debug On";
  345. string adminmenuOpt3 = "Debug Off";
  346. integer admindialogChannel = -9000;
  347. integer admindialogHandle;
  348.  
  349. AdminMenu() {
  350. list adminmenuOptions = [ adminmenuOpt1, adminmenuOpt2, adminmenuOpt3 ];
  351. admindialogHandle = llListen(admindialogChannel, "", llGetOwner(), "");
  352. llDialog (llGetOwner(), adminmenuTitle, adminmenuOptions, admindialogChannel);
  353. llSetTimerEvent(30);
  354. }
  355.  
  356. AdminMenuCallback(string message) {
  357. if (message == adminmenuOpt1) state default;
  358. if (message == adminmenuOpt2) SetDebug(TRUE);
  359. if (message == adminmenuOpt3) SetDebug(FALSE);
  360. llListenRemove (admindialogHandle);
  361. llSetTimerEvent (0);
  362. }
  363.  
  364. AdminMenuTimetout() {
  365. llListenRemove (admindialogHandle);
  366. llSetTimerEvent (0);
  367. }
  368.  
  369. ///////////////////////////////////////////////////////////////////
  370. // State 1 : read the data and draw the board
  371. ///////////////////////////////////////////////////////////////////
  372.  
  373. default {
  374.  
  375. state_entry() {
  376. SetDebug (DEBUG_ON);
  377. init_destinations();
  378. llOwnerSay ("Reading data from "+datasource);
  379. readDataSource (datasource);
  380. }
  381.  
  382. // Handler for card:// datasource
  383. dataserver(key id, string data) {
  384. // Internal card reader
  385. if (id == ncQueryID) {
  386. if (data != EOF) addFromNotecard (data);
  387. else state ready; // File in datasorceData
  388. }
  389. }
  390.  
  391. // Handler fot http:// datasource
  392. http_response(key id,integer status, list meta, string body) {
  393. if (id != httpQueryId) return;
  394. datasorceData = body;
  395. state ready; // File in datasorceData
  396. }
  397.  
  398. state_exit() {
  399. llOwnerSay ("Done. Initializing board");
  400. parseDataSource(datasorceData);
  401. drawTable();
  402. }
  403.  
  404. }
  405.  
  406. ///////////////////////////////////////////////////////////////////
  407. // State 2 : running, we pass most of our time here
  408. ///////////////////////////////////////////////////////////////////
  409.  
  410. state ready {
  411.  
  412. state_entry() {
  413. llWhisper (0, llGetScriptName()+" Ready");
  414. }
  415.  
  416. touch_start (integer n) {
  417. key whoClick = llDetectedKey(0);
  418. vector point = llDetectedTouchST(0);
  419. integer face = llDetectedTouchFace(0);
  420. integer link = llDetectedLinkNumber(0);
  421.  
  422. // If owner touched outside board, display admin menu
  423.  
  424. if (link != LINK_ROOT) {
  425. if ( (whoClick == llGetOwner())
  426. || (whoClick == llGetCreator()) )
  427. AdminMenu();
  428. return;
  429. }
  430.  
  431. if (point == TOUCH_INVALID_TEXCOORD) return;
  432. if (face != DISPLAY_SIDE) return;
  433.  
  434. integer ok = HandleTouch (getCellClicked(point), whoClick);
  435. if (!ok) return; // Empty cell
  436.  
  437. // Proceed to http check
  438.  
  439. state hippos; // Perform HTTP check
  440. }
  441.  
  442. changed(integer what) {
  443. if (what & CHANGED_REGION) llResetScript();
  444. if (what & CHANGED_INVENTORY) llResetScript();
  445. if (what & CHANGED_REGION_RESTART) llResetScript();
  446. }
  447.  
  448. listen(integer channel, string name, key id, string message) {
  449. if (channel == admindialogChannel)
  450. AdminMenuCallback (message);
  451. }
  452.  
  453. timer() {
  454. AdminMenuTimetout();
  455. }
  456.  
  457. on_rez (integer parm) {
  458. llResetScript();
  459. }
  460. }
  461.  
  462. ///////////////////////////////////////////////////////////////////
  463. // State 3 : HTTP host check
  464. ///////////////////////////////////////////////////////////////////
  465.  
  466. state hippos {
  467.  
  468. state_entry() {
  469. DEBUG ("HTTP "+hippo_url);
  470. sendHTTPRequest (hippo_url);
  471. llSetTimerEvent (HTTP_TIMEOUT);
  472. }
  473.  
  474. http_response(key id,integer status, list meta, string body) {
  475. DEBUG ("HTTP "+(string)status);
  476. if (id != httpQueryId) return;
  477. HTTPCheckCallback (status);
  478. state ready;
  479. }
  480.  
  481. timer() {
  482. llSetTimerEvent (0);
  483. HTTPCheckCallback (TIMEOUT_STATUS);
  484. state ready;
  485. }
  486.  
  487. }
Add Comment
Please, Sign In to add comment