corrade-lsl-templates – Diff between revs 5 and 29

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 5 Rev 29
1 /////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 // 2 // Copyright (C) Wizardry and Steamworks 2016 - License: CC BY 2.0 //
3 /////////////////////////////////////////////////////////////////////////// 3 ///////////////////////////////////////////////////////////////////////////
4 // 4 //
5 // This is an automatic animation responder for the Corrade Second Life / 5 // This is an automatic animation responder for the Corrade Second Life /
6 // OpenSim bot that will accept to trigger animations - such as hugs sent 6 // OpenSim bot that will accept to trigger animations - such as hugs sent
7 // by various HUDs in SecondLife. You can find more details about the bot 7 // by various HUDs in SecondLife. You can find more details about the bot
8 // by following the URL: http://was.fm/secondlife/scripted_agents/corrade 8 // by following the URL: http://was.fm/secondlife/scripted_agents/corrade
9 // 9 //
10 // The script works together with a "configuration" notecard and an that 10 // The script works together with a "configuration" notecard and an that
11 // must be placed in the same primitive as this script. The purpose of 11 // must be placed in the same primitive as this script. The purpose of
12 // this script is to demonstrate accepting animations with Corrade and 12 // this script is to demonstrate accepting animations with Corrade and
13 // you are free to use, change, and commercialize it under the GNU/GPLv3 13 // you are free to use, change, and commercialize it under the CC BY 2.0
14 // license at: http://www.gnu.org/licenses/gpl.html 14 // license at: https://creativecommons.org/licenses/by/2.0
15 // 15 //
16 /////////////////////////////////////////////////////////////////////////// 16 ///////////////////////////////////////////////////////////////////////////
17   17  
18 /////////////////////////////////////////////////////////////////////////// 18 ///////////////////////////////////////////////////////////////////////////
19 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // 19 // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 //
20 /////////////////////////////////////////////////////////////////////////// 20 ///////////////////////////////////////////////////////////////////////////
21 string wasKeyValueGet(string k, string data) { 21 string wasKeyValueGet(string k, string data) {
22 if(llStringLength(data) == 0) return ""; 22 if(llStringLength(data) == 0) return "";
23 if(llStringLength(k) == 0) return ""; 23 if(llStringLength(k) == 0) return "";
24 list a = llParseString2List(data, ["&", "="], []); 24 list a = llParseString2List(data, ["&", "="], []);
25 integer i = llListFindList(a, [ k ]); 25 integer i = llListFindList(a, [ k ]);
26 if(i != -1) return llList2String(a, i+1); 26 if(i != -1) return llList2String(a, i+1);
27 return ""; 27 return "";
28 } 28 }
29 29
30 /////////////////////////////////////////////////////////////////////////// 30 ///////////////////////////////////////////////////////////////////////////
31 // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // 31 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
32 /////////////////////////////////////////////////////////////////////////// 32 ///////////////////////////////////////////////////////////////////////////
33 string wasKeyValueEncode(list data) { 33 string wasKeyValueEncode(list data) {
34 list k = llList2ListStrided(data, 0, -1, 2); 34 list k = llList2ListStrided(data, 0, -1, 2);
35 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2); 35 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2);
36 data = []; 36 data = [];
37 do { 37 do {
38 data += llList2String(k, 0) + "=" + llList2String(v, 0); 38 data += llList2String(k, 0) + "=" + llList2String(v, 0);
39 k = llDeleteSubList(k, 0, 0); 39 k = llDeleteSubList(k, 0, 0);
40 v = llDeleteSubList(v, 0, 0); 40 v = llDeleteSubList(v, 0, 0);
41 } while(llGetListLength(k) != 0); 41 } while(llGetListLength(k) != 0);
42 return llDumpList2String(data, "&"); 42 return llDumpList2String(data, "&");
43 } 43 }
44   44  
45 /////////////////////////////////////////////////////////////////////////// 45 ///////////////////////////////////////////////////////////////////////////
46 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // 46 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
47 /////////////////////////////////////////////////////////////////////////// 47 ///////////////////////////////////////////////////////////////////////////
48 // escapes a string in conformance with RFC1738 48 // escapes a string in conformance with RFC1738
49 string wasURLEscape(string i) { 49 string wasURLEscape(string i) {
50 string o = ""; 50 string o = "";
51 do { 51 do {
52 string c = llGetSubString(i, 0, 0); 52 string c = llGetSubString(i, 0, 0);
53 i = llDeleteSubString(i, 0, 0); 53 i = llDeleteSubString(i, 0, 0);
54 if(c == "") jump continue; 54 if(c == "") jump continue;
55 if(c == " ") { 55 if(c == " ") {
56 o += "+"; 56 o += "+";
57 jump continue; 57 jump continue;
58 } 58 }
59 if(c == "\n") { 59 if(c == "\n") {
60 o += "%0D" + llEscapeURL(c); 60 o += "%0D" + llEscapeURL(c);
61 jump continue; 61 jump continue;
62 } 62 }
63 o += llEscapeURL(c); 63 o += llEscapeURL(c);
64 @continue; 64 @continue;
65 } while(i != ""); 65 } while(i != "");
66 return o; 66 return o;
67 } 67 }
68   68  
69 // corrade data 69 // corrade data
70 string CORRADE = ""; 70 string CORRADE = "";
71 string GROUP = ""; 71 string GROUP = "";
72 string PASSWORD = ""; 72 string PASSWORD = "";
73   73  
74 // for holding the callback URL 74 // for holding the callback URL
75 string callback = ""; 75 string callback = "";
76   76  
77 // for notecard reading 77 // for notecard reading
78 integer line = 0; 78 integer line = 0;
79   79  
80 // key-value data will be read into this list 80 // key-value data will be read into this list
81 list tuples = []; 81 list tuples = [];
82 82
83 default { 83 default {
84 state_entry() { 84 state_entry() {
85 if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) { 85 if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) {
86 llOwnerSay("Sorry, could not find an inventory notecard."); 86 llOwnerSay("Sorry, could not find an inventory notecard.");
87 return; 87 return;
88 } 88 }
89 // DEBUG 89 // DEBUG
90 llOwnerSay("Reading configuration file..."); 90 llOwnerSay("Reading configuration file...");
91 llGetNotecardLine("configuration", line); 91 llGetNotecardLine("configuration", line);
92 } 92 }
93 dataserver(key id, string data) { 93 dataserver(key id, string data) {
94 if(data == EOF) { 94 if(data == EOF) {
95 // invariant, length(tuples) % 2 == 0 95 // invariant, length(tuples) % 2 == 0
96 if(llGetListLength(tuples) % 2 != 0) { 96 if(llGetListLength(tuples) % 2 != 0) {
97 llOwnerSay("Error in configuration notecard."); 97 llOwnerSay("Error in configuration notecard.");
98 return; 98 return;
99 } 99 }
100 CORRADE = llList2String( 100 CORRADE = llList2String(
101 tuples, 101 tuples,
102 llListFindList( 102 llListFindList(
103 tuples, 103 tuples,
104 [ 104 [
105 "corrade" 105 "corrade"
106 ] 106 ]
107 ) 107 )
108 +1 108 +1
109 ); 109 );
110 if(CORRADE == "") { 110 if(CORRADE == "") {
111 llOwnerSay("Error in configuration notecard: corrade"); 111 llOwnerSay("Error in configuration notecard: corrade");
112 return; 112 return;
113 } 113 }
114 GROUP = llList2String( 114 GROUP = llList2String(
115 tuples, 115 tuples,
116 llListFindList( 116 llListFindList(
117 tuples, 117 tuples,
118 [ 118 [
119 "group" 119 "group"
120 ] 120 ]
121 ) 121 )
122 +1 122 +1
123 ); 123 );
124 if(GROUP == "") { 124 if(GROUP == "") {
125 llOwnerSay("Error in configuration notecard: group"); 125 llOwnerSay("Error in configuration notecard: group");
126 return; 126 return;
127 } 127 }
128 PASSWORD = llList2String( 128 PASSWORD = llList2String(
129 tuples, 129 tuples,
130 llListFindList( 130 llListFindList(
131 tuples, 131 tuples,
132 [ 132 [
133 "password" 133 "password"
134 ] 134 ]
135 ) 135 )
136 +1 136 +1
137 ); 137 );
138 if(PASSWORD == "") { 138 if(PASSWORD == "") {
139 llOwnerSay("Error in configuration notecard: password"); 139 llOwnerSay("Error in configuration notecard: password");
140 return; 140 return;
141 } 141 }
142 // DEBUG 142 // DEBUG
143 llOwnerSay("Read configuration file..."); 143 llOwnerSay("Read configuration file...");
144 state url; 144 state url;
145 } 145 }
146 if(data == "") jump continue; 146 if(data == "") jump continue;
147 integer i = llSubStringIndex(data, "#"); 147 integer i = llSubStringIndex(data, "#");
148 if(i != -1) data = llDeleteSubString(data, i, -1); 148 if(i != -1) data = llDeleteSubString(data, i, -1);
149 list o = llParseString2List(data, ["="], []); 149 list o = llParseString2List(data, ["="], []);
150 // get rid of starting and ending quotes 150 // get rid of starting and ending quotes
151 string k = llDumpList2String( 151 string k = llDumpList2String(
152 llParseString2List( 152 llParseString2List(
153 llStringTrim( 153 llStringTrim(
154 llList2String( 154 llList2String(
155 o, 155 o,
156 0 156 0
157 ), 157 ),
158 STRING_TRIM), 158 STRING_TRIM),
159 ["\""], [] 159 ["\""], []
160 ), "\""); 160 ), "\"");
161 string v = llDumpList2String( 161 string v = llDumpList2String(
162 llParseString2List( 162 llParseString2List(
163 llStringTrim( 163 llStringTrim(
164 llList2String( 164 llList2String(
165 o, 165 o,
166 1 166 1
167 ), 167 ),
168 STRING_TRIM), 168 STRING_TRIM),
169 ["\""], [] 169 ["\""], []
170 ), "\""); 170 ), "\"");
171 if(k == "" || v == "") jump continue; 171 if(k == "" || v == "") jump continue;
172 tuples += k; 172 tuples += k;
173 tuples += v; 173 tuples += v;
174 @continue; 174 @continue;
175 llGetNotecardLine("configuration", ++line); 175 llGetNotecardLine("configuration", ++line);
176 } 176 }
177 on_rez(integer num) { 177 on_rez(integer num) {
178 llResetScript(); 178 llResetScript();
179 } 179 }
180 changed(integer change) { 180 changed(integer change) {
181 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 181 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
182 llResetScript(); 182 llResetScript();
183 } 183 }
184 } 184 }
185 } 185 }
186 186
187 state url { 187 state url {
188 state_entry() { 188 state_entry() {
189 // DEBUG 189 // DEBUG
190 llOwnerSay("Requesting URL..."); 190 llOwnerSay("Requesting URL...");
191 llRequestURL(); 191 llRequestURL();
192 } 192 }
193 http_request(key id, string method, string body) { 193 http_request(key id, string method, string body) {
194 if(method != URL_REQUEST_GRANTED) return; 194 if(method != URL_REQUEST_GRANTED) return;
195 callback = body; 195 callback = body;
196 // DEBUG 196 // DEBUG
197 llOwnerSay("Got URL..."); 197 llOwnerSay("Got URL...");
198 state detect; 198 state detect;
199 } 199 }
200 on_rez(integer num) { 200 on_rez(integer num) {
201 llResetScript(); 201 llResetScript();
202 } 202 }
203 changed(integer change) { 203 changed(integer change) {
204 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 204 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
205 llResetScript(); 205 llResetScript();
206 } 206 }
207 } 207 }
208 } 208 }
209 209
210 state detect { 210 state detect {
211 state_entry() { 211 state_entry() {
212 // DEBUG 212 // DEBUG
213 llOwnerSay("Detecting if Corrade is online..."); 213 llOwnerSay("Detecting if Corrade is online...");
214 llSetTimerEvent(5); 214 llSetTimerEvent(5);
215 } 215 }
216 timer() { 216 timer() {
217 llRequestAgentData((key)CORRADE, DATA_ONLINE); 217 llRequestAgentData((key)CORRADE, DATA_ONLINE);
218 } 218 }
219 dataserver(key id, string data) { 219 dataserver(key id, string data) {
220 if(data != "1") { 220 if(data != "1") {
221 // DEBUG 221 // DEBUG
222 llOwnerSay("Corrade is not online, sleeping..."); 222 llOwnerSay("Corrade is not online, sleeping...");
223 llSetTimerEvent(30); 223 llSetTimerEvent(30);
224 return; 224 return;
225 } 225 }
226 state notify; 226 state notify;
227 } 227 }
228 on_rez(integer num) { 228 on_rez(integer num) {
229 llResetScript(); 229 llResetScript();
230 } 230 }
231 changed(integer change) { 231 changed(integer change) {
232 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 232 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
233 llResetScript(); 233 llResetScript();
234 } 234 }
235 } 235 }
236 } 236 }
237 237
238 state notify { 238 state notify {
239 state_entry() { 239 state_entry() {
240 // DEBUG 240 // DEBUG
241 llOwnerSay("Binding to the permission Corrade notification..."); 241 llOwnerSay("Binding to the permission Corrade notification...");
242 llInstantMessage( 242 llInstantMessage(
243 (key)CORRADE, 243 (key)CORRADE,
244 wasKeyValueEncode( 244 wasKeyValueEncode(
245 [ 245 [
246 "command", "notify", 246 "command", "notify",
247 "group", wasURLEscape(GROUP), 247 "group", wasURLEscape(GROUP),
248 "password", wasURLEscape(PASSWORD), 248 "password", wasURLEscape(PASSWORD),
249 "action", "set", 249 "action", "set",
250 "type", "permission", 250 "type", "permission",
251 "URL", wasURLEscape(callback), 251 "URL", wasURLEscape(callback),
252 "callback", wasURLEscape(callback) 252 "callback", wasURLEscape(callback)
253 ] 253 ]
254 ) 254 )
255 ); 255 );
256 llSetTimerEvent(60); 256 llSetTimerEvent(60);
257 } 257 }
258 http_request(key id, string method, string body) { 258 http_request(key id, string method, string body) {
259 llHTTPResponse(id, 200, "OK"); 259 llHTTPResponse(id, 200, "OK");
260 if(wasKeyValueGet("command", body) != "notify" || 260 if(wasKeyValueGet("command", body) != "notify" ||
261 wasKeyValueGet("success", body) != "True") { 261 wasKeyValueGet("success", body) != "True") {
262 // DEBUG 262 // DEBUG
263 llOwnerSay("Failed to bind to the permission notification..."); 263 llOwnerSay("Failed to bind to the permission notification...");
264 state detect; 264 state detect;
265 } 265 }
266 // DEBUG 266 // DEBUG
267 llOwnerSay("Permission notification installed..."); 267 llOwnerSay("Permission notification installed...");
268 llSetTimerEvent(0); 268 llSetTimerEvent(0);
269 state main; 269 state main;
270 } 270 }
271 timer() { 271 timer() {
272 llSetTimerEvent(0); 272 llSetTimerEvent(0);
273 // DEBUG 273 // DEBUG
274 llOwnerSay("Timeout binding to permission notification..."); 274 llOwnerSay("Timeout binding to permission notification...");
275 state detect; 275 state detect;
276 } 276 }
277 on_rez(integer num) { 277 on_rez(integer num) {
278 llResetScript(); 278 llResetScript();
279 } 279 }
280 changed(integer change) { 280 changed(integer change) {
281 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 281 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
282 llResetScript(); 282 llResetScript();
283 } 283 }
284 } 284 }
285 } 285 }
286 286
287 state main { 287 state main {
288 state_entry() { 288 state_entry() {
289 // DEBUG 289 // DEBUG
290 llOwnerSay("Waiting for animation requests..."); 290 llOwnerSay("Waiting for animation requests...");
291 } 291 }
292 http_request(key id, string method, string body) { 292 http_request(key id, string method, string body) {
293 llHTTPResponse(id, 200, "OK"); 293 llHTTPResponse(id, 200, "OK");
294 if(wasKeyValueGet("type", body) != "permission" || 294 if(wasKeyValueGet("type", body) != "permission" ||
295 wasKeyValueGet("permissions", body) != "TriggerAnimation") 295 wasKeyValueGet("permissions", body) != "TriggerAnimation")
296 return; 296 return;
297 297
298 // DEBUG 298 // DEBUG
299 llOwnerSay("Corrade received the permission request to trigger an animation, replying..."); 299 llOwnerSay("Corrade received the permission request to trigger an animation, replying...");
300 300
301 llInstantMessage((key)CORRADE, 301 llInstantMessage((key)CORRADE,
302 wasKeyValueEncode( 302 wasKeyValueEncode(
303 [ 303 [
304 "command", "replytoscriptpermissionrequest", 304 "command", "replytoscriptpermissionrequest",
305 "group", wasURLEscape(GROUP), 305 "group", wasURLEscape(GROUP),
306 "password", wasURLEscape(PASSWORD), 306 "password", wasURLEscape(PASSWORD),
307 "item", wasKeyValueGet("item", body), 307 "item", wasKeyValueGet("item", body),
308 "task", wasKeyValueGet("task", body), 308 "task", wasKeyValueGet("task", body),
309 "action", "reply", 309 "action", "reply",
310 "permissions", "TriggerAnimation", 310 "permissions", "TriggerAnimation",
311 "region", wasKeyValueGet("region", body), 311 "region", wasKeyValueGet("region", body),
312 "callback", wasURLEscape(callback) 312 "callback", wasURLEscape(callback)
313 ] 313 ]
314 ) 314 )
315 ); 315 );
316 } 316 }
317 on_rez(integer num) { 317 on_rez(integer num) {
318 llResetScript(); 318 llResetScript();
319 } 319 }
320 changed(integer change) { 320 changed(integer change) {
321 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 321 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
322 llResetScript(); 322 llResetScript();
323 } 323 }
324 } 324 }
325 } 325 }
326   326