corrade-lsl-templates – Blame information for rev 31

Subversion Repositories:
Rev:
Rev Author Line No. Line
2 office 1 ///////////////////////////////////////////////////////////////////////////
29 office 2 // Copyright (C) Wizardry and Steamworks 2016 - License: CC BY 2.0 //
2 office 3 ///////////////////////////////////////////////////////////////////////////
4 //
5 // This script will make Corrade scan for primitives in the vicinity and
6 // will then offer a dialog for you to pick which primitive to touch.
7 //
8 // For more information on Corrade, please see:
9 // http://grimore.org/secondlife/scripted_agents/corrade
10 //
11 ///////////////////////////////////////////////////////////////////////////
12  
13 ///////////////////////////////////////////////////////////////////////////
29 office 14 // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 15 ///////////////////////////////////////////////////////////////////////////
16 string wasKeyValueGet(string k, string data) {
17 if(llStringLength(data) == 0) return "";
18 if(llStringLength(k) == 0) return "";
19 list a = llParseString2List(data, ["&", "="], []);
20 integer i = llListFindList(a, [ k ]);
21 if(i != -1) return llList2String(a, i+1);
22 return "";
23 }
24  
25 ///////////////////////////////////////////////////////////////////////////
29 office 26 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 27 ///////////////////////////////////////////////////////////////////////////
28 string wasKeyValueEncode(list data) {
29 list k = llList2ListStrided(data, 0, -1, 2);
30 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2);
31 data = [];
32 do {
33 data += llList2String(k, 0) + "=" + llList2String(v, 0);
34 k = llDeleteSubList(k, 0, 0);
35 v = llDeleteSubList(v, 0, 0);
36 } while(llGetListLength(k) != 0);
37 return llDumpList2String(data, "&");
38 }
39  
40 ///////////////////////////////////////////////////////////////////////////
29 office 41 // Copyright (C) 2011 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 42 ///////////////////////////////////////////////////////////////////////////
43 // http://was.fm/secondlife/wanderer
44 vector wasCirclePoint(float radius) {
45 float x = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
46 float y = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
47 if(llPow(x,2) + llPow(y,2) <= llPow(radius,2))
48 return <x, y, 0>;
49 return wasCirclePoint(radius);
50 }
51  
52 ///////////////////////////////////////////////////////////////////////////
29 office 53 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 54 ///////////////////////////////////////////////////////////////////////////
55 // escapes a string in conformance with RFC1738
56 string wasURLEscape(string i) {
57 string o = "";
58 do {
59 string c = llGetSubString(i, 0, 0);
60 i = llDeleteSubString(i, 0, 0);
61 if(c == "") jump continue;
62 if(c == " ") {
63 o += "+";
64 jump continue;
65 }
66 if(c == "\n") {
67 o += "%0D" + llEscapeURL(c);
68 jump continue;
69 }
70 o += llEscapeURL(c);
71 @continue;
72 } while(i != "");
73 return o;
74 }
75  
76 ///////////////////////////////////////////////////////////////////////////
29 office 77 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 78 ///////////////////////////////////////////////////////////////////////////
79 list wasCSVToList(string csv) {
80 list l = [];
81 list s = [];
82 string m = "";
83 do {
84 string a = llGetSubString(csv, 0, 0);
85 csv = llDeleteSubString(csv, 0, 0);
86 if(a == ",") {
87 if(llList2String(s, -1) != "\"") {
88 l += m;
89 m = "";
90 jump continue;
91 }
92 m += a;
93 jump continue;
94 }
95 if(a == "\"" && llGetSubString(csv, 0, 0) == a) {
96 m += a;
97 csv = llDeleteSubString(csv, 0, 0);
98 jump continue;
99 }
100 if(a == "\"") {
101 if(llList2String(s, -1) != a) {
102 s += a;
103 jump continue;
104 }
105 s = llDeleteSubList(s, -1, -1);
106 jump continue;
107 }
108 m += a;
109 @continue;
110 } while(csv != "");
111 // postcondition: length(s) = 0
112 return l + m;
113 }
114  
115 ///////////////////////////////////////////////////////////////////////////
29 office 116 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 117 ///////////////////////////////////////////////////////////////////////////
118 string wasListToCSV(list l) {
119 list v = [];
120 do {
121 string a = llDumpList2String(
122 llParseStringKeepNulls(
123 llList2String(
124 l,
125  
126 ),
127 ["\""],
128 []
129 ),
130 "\"\""
131 );
132 if(llParseStringKeepNulls(
133 a,
134 [" ", ",", "\n", "\""], []
135 ) !=
136 (list) a
137 ) a = "\"" + a + "\"";
138 v += a;
139 l = llDeleteSubList(l, 0, 0);
140 } while(l != []);
141 return llDumpList2String(v, ",");
142 }
143  
144 ///////////////////////////////////////////////////////////////////////////
29 office 145 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 146 ///////////////////////////////////////////////////////////////////////////
147 // unescapes a string in conformance with RFC1738
148 string wasURLUnescape(string i) {
149 return llUnescapeURL(
150 llDumpList2String(
151 llParseString2List(
152 llDumpList2String(
153 llParseString2List(
154 i,
155 ["+"],
156 []
157 ),
158 " "
159 ),
160 ["%0D%0A"],
161 []
162 ),
163 "\n"
164 )
165 );
166 }
167  
168 ///////////////////////////////////////////////////////////////////////////
29 office 169 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 170 ///////////////////////////////////////////////////////////////////////////
171 integer wasMenuIndex = 0;
172 list wasDialogMenu(list input, list actions, string direction) {
173 integer cut = 11-wasListCountExclude(actions, [""]);
174 if(direction == ">" && (wasMenuIndex+1)*cut+wasMenuIndex+1 < llGetListLength(input)) {
175 ++wasMenuIndex;
176 jump slice;
177 }
178 if(direction == "<" && wasMenuIndex-1 >= 0) {
179 --wasMenuIndex;
180 jump slice;
181 }
182 @slice;
183 integer multiple = wasMenuIndex*cut;
184 input = llList2List(input, multiple+wasMenuIndex, multiple+cut+wasMenuIndex);
185 input = wasListMerge(input, actions, "");
186 return input;
187 }
188  
189 ///////////////////////////////////////////////////////////////////////////
29 office 190 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 191 ///////////////////////////////////////////////////////////////////////////
192 integer wasListCountExclude(list input, list exclude) {
193 if(llGetListLength(input) == 0) return 0;
194 if(llListFindList(exclude, (list)llList2String(input, 0)) == -1)
195 return 1 + wasListCountExclude(llDeleteSubList(input, 0, 0), exclude);
196 return wasListCountExclude(llDeleteSubList(input, 0, 0), exclude);
197 }
198  
199 ///////////////////////////////////////////////////////////////////////////
29 office 200 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 201 ///////////////////////////////////////////////////////////////////////////
202 list wasListMerge(list l, list m, string merge) {
203 if(llGetListLength(l) == 0 && llGetListLength(m) == 0) return [];
204 string a = llList2String(m, 0);
205 if(a != merge) return [ a ] + wasListMerge(l, llDeleteSubList(m, 0, 0), merge);
206 return [ llList2String(l, 0) ] + wasListMerge(llDeleteSubList(l, 0, 0), llDeleteSubList(m, 0, 0), merge);
207 }
208  
209 // configuration data
210 string configuration = "";
211 // callback URL
212 string callback = "";
213 // scanned primitives
214 list names = [];
215 list UUIDs = [];
216 // temporary list for button name normalization
217 list menu = [];
218 integer select = -1;
219  
220 default {
221 state_entry() {
222 llSetTimerEvent(1);
223 }
224 link_message(integer sender, integer num, string message, key id) {
225 if(sender != 1 || id != "configuration") return;
226 configuration = message;
227 state off;
228 }
229 timer() {
230 llMessageLinked(LINK_ROOT, 0, "configuration", NULL_KEY);
231 }
232 attach(key id) {
233 llResetScript();
234 }
235 on_rez(integer num) {
236 llResetScript();
237 }
238 changed(integer change) {
239 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
240 llResetScript();
241 }
242 }
243 state_exit() {
244 llSetTimerEvent(0);
245 }
246 }
247  
248 state off {
249 state_entry() {
250 llSetColor(<.5,0,0>, ALL_SIDES);
251 }
252 touch_end(integer num) {
253 state on;
254 }
255 attach(key id) {
256 llResetScript();
257 }
258 on_rez(integer num) {
259 llResetScript();
260 }
261 changed(integer change) {
262 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
263 llResetScript();
264 }
265 }
266 }
267  
268 state on {
269 state_entry() {
270 llSetColor(<0,.5,0>, ALL_SIDES);
271 state url;
272 }
273 attach(key id) {
274 llResetScript();
275 }
276 on_rez(integer num) {
277 llResetScript();
278 }
279 changed(integer change) {
280 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
281 llResetScript();
282 }
283 }
284 }
285  
286 state url {
287 state_entry() {
288 // DEBUG
289 llOwnerSay("Requesting URL...");
290 llRequestURL();
291 }
292 touch_end(integer num) {
293 llSetColor(<.5,0,0>, ALL_SIDES);
294 llResetScript();
295 }
296 http_request(key id, string method, string body) {
297 if(method != URL_REQUEST_GRANTED) return;
298 callback = body;
299 // DEBUG
300 llOwnerSay("Got URL...");
301 state scan;
302 }
303 attach(key id) {
304 llResetScript();
305 }
306 on_rez(integer num) {
307 llResetScript();
308 }
309 changed(integer change) {
310 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
311 llResetScript();
312 }
313 }
314 }
315  
316 state scan {
317 state_entry() {
318 // DEBUG
31 office 319 llOwnerSay("Getting primitives...");
2 office 320 llInstantMessage(
321 wasKeyValueGet(
322 "corrade",
323 configuration
324 ),
325 wasKeyValueEncode(
326 [
31 office 327 "command", "getprimitivesdata",
2 office 328 "group", wasURLEscape(
329 wasKeyValueGet(
330 "group",
331 configuration
332 )
333 ),
334 "password", wasURLEscape(
335 wasKeyValueGet(
336 "password",
337 configuration
338 )
339 ),
340 "entity", "world",
341 "range", wasURLEscape(
342 wasKeyValueGet(
343 "radar",
344 configuration
345 )
346 ),
347 "data", wasListToCSV(
348 [
349 "Properties.Name",
350 "ID"
351 ]
352 ),
353 "sift", wasListToCSV(
354 [
355 "take", 32
356 ]
357 ),
358 "callback", wasURLEscape(callback)
359 ]
360 )
361 );
362 }
363 touch_end(integer num) {
364 llSetColor(<.5,0,0>, ALL_SIDES);
365 llResetScript();
366 }
367 http_request(key id, string method, string body) {
368 llHTTPResponse(id, 200, "OK");
31 office 369 if(wasKeyValueGet("command", body) != "getprimitivesdata" ||
2 office 370 wasKeyValueGet("success", body) != "True") {
371 // DEBUG
372 llOwnerSay("Unable to query primitives data: " +
373 wasURLUnescape(
374 wasKeyValueGet(
375 "error",
376 body
377 )
378 )
379 );
380 llResetScript();
381 }
382 string dataKey = wasURLUnescape(
383 wasKeyValueGet(
384 "data",
385 body
386 )
387 );
388 if(dataKey == "") {
389 // DEBUG
390 llOwnerSay("No data for scanned primitives...");
391 llResetScript();
392 }
393 list data = wasCSVToList(dataKey);
394 // Copy the names and UUIDs of the primitives.
395 names = [];
396 UUIDs = [];
397 do {
398 string v = llList2String(data, -1);
399 data = llDeleteSubList(data, -1, -1);
400 string k = llList2String(data, -1);
401 data = llDeleteSubList(data, -1, -1);
402 if(k == "Properties.Name") {
403 names += v;
404 jump continue;
405 }
406 UUIDs += (key)v;
407 @continue;
408 } while(llGetListLength(data));
409 state choose;
410 }
411 attach(key id) {
412 llResetScript();
413 }
414 on_rez(integer num) {
415 llResetScript();
416 }
417 changed(integer change) {
418 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
419 llResetScript();
420 }
421 }
422 state_exit() {
423 llSetTimerEvent(0);
424 }
425 }
426  
427 state choose {
428 state_entry() {
429 // DEBUG
430 llOwnerSay("Sending menu...");
431 menu = [];
432 integer i = 0;
433 do {
434 menu += llGetSubString(llList2String(names, i), 0, 23);
435 } while(++i < llGetListLength(names));
436 llListen(-10, "", llGetOwner(), "");
437 llDialog(llGetOwner(), "\nPlease choose a primitive for Corrade to sit on from the list below:\n", wasDialogMenu(menu, ["⟵ Back", "", "Next ⟶"], ""), -10);
438 llSetTimerEvent(60);
439 }
440 touch_end(integer num) {
441 llSetColor(<.5,0,0>, ALL_SIDES);
442 llResetScript();
443 }
444 listen(integer channel, string name, key id, string message) {
445 if(message == "⟵ Back") {
446 llDialog(id, "\nPlease choose a primitive for Corrade to sit on from the list below:\n", wasDialogMenu(menu, ["⟵ Back", "", "Next ⟶"], "<"), -10);
447 return;
448 }
449 if(message == "Next ⟶") {
450 llDialog(id, "\nPlease choose a primitive for Corrade to sit on from the list below:\n", wasDialogMenu(menu, ["⟵ Back", "", "Next ⟶"], ">"), -10);
451 return;
452 }
453 integer i = llGetListLength(menu) - 1;
454 do {
455 string v = llList2String(menu, i);
456 if(llSubStringIndex(v, message) != -1)
457 jump sit;
458 } while(--i > -1);
459 // GC
460 menu = [];
461 // DEBUG
462 llOwnerSay("Invalid menu item selected...");
463 llResetScript();
464 @sit;
465 // GC
466 menu = [];
467 select = i;
468 // Got a menu item so bind to permission notifications and sit.
469 state touch_primitive;
470  
471 }
472 timer() {
473 // DEBUG
474 llOwnerSay("Dialog menu timeout...");
475 llResetScript();
476 }
477 attach(key id) {
478 llResetScript();
479 }
480 on_rez(integer num) {
481 llResetScript();
482 }
483 changed(integer change) {
484 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
485 llResetScript();
486 }
487 }
488 state_exit() {
489 llSetTimerEvent(0);
490 }
491 }
492  
493 state touch_primitive {
494 state_entry() {
495 // DEBUG
496 llOwnerSay("Touching: " +
497 llList2String(names, select) +
498 " UUID: " +
499 llList2String(UUIDs, select)
500 );
501 llInstantMessage(
502 (key)wasKeyValueGet(
503 "corrade",
504 configuration
505 ),
506 wasKeyValueEncode(
507 [
508 "command", "touch",
509 "group", wasURLEscape(
510 wasKeyValueGet(
511 "group",
512 configuration
513 )
514 ),
515 "password", wasURLEscape(
516 wasKeyValueGet(
517 "password",
518 configuration
519 )
520 ),
521 "item", wasURLEscape(
522 llList2String(UUIDs, select)
523 ),
524 "range", wasURLEscape(
525 wasKeyValueGet(
526 "radar",
527 configuration
528 )
529 ),
530 "callback", wasURLEscape(callback)
531 ]
532 )
533 );
534 llSetTimerEvent(60);
535 }
536 touch_end(integer num) {
537 llSetColor(<.5,0,0>, ALL_SIDES);
538 llResetScript();
539 }
540 http_request(key id, string method, string body) {
541 llHTTPResponse(id, 200, "OK");
542 if(wasKeyValueGet("command", body) != "touch" ||
543 wasKeyValueGet("success", body) != "True") {
544 // DEBUG
545 llOwnerSay("Failed to touch primitive...");
546 llResetScript();
547 }
548 // DEBUG
549 llOwnerSay("Touched...");
550 llResetScript();
551 }
552 timer() {
553 llResetScript();
554 }
555 attach(key id) {
556 llResetScript();
557 }
558 on_rez(integer num) {
559 llResetScript();
560 }
561 changed(integer change) {
562 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
563 llResetScript();
564 }
565 }
566 state_exit() {
567 llSetTimerEvent(0);
568 }
569 }