corrade-lsl-templates – Diff between revs 25 and 26
?pathlinks?
Rev 25 | Rev 26 | |||
---|---|---|---|---|
1 | /////////////////////////////////////////////////////////////////////////// |
1 | /////////////////////////////////////////////////////////////////////////// |
|
2 | // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 // |
2 | // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 // |
|
3 | /////////////////////////////////////////////////////////////////////////// |
3 | /////////////////////////////////////////////////////////////////////////// |
|
4 | // |
4 | // |
|
5 | // A template HUD script for Corrade that reads a configuration notecard |
5 | // A template HUD script for Corrade that reads a configuration notecard |
|
6 | // and then feeds that configuration to various other components of the HUD |
6 | // and then feeds that configuration to various other components of the HUD |
|
7 | // that request the configuration. Additionally, this HUD is programmed to |
7 | // that request the configuration. Additionally, this HUD is programmed to |
|
8 | // "fold" and "unfold" depending on whether Corrade is online or not. For |
8 | // "fold" and "unfold" depending on whether Corrade is online or not. For |
|
9 | // more information on the Corrade scripted agent please see the URL: |
9 | // more information on the Corrade scripted agent please see the URL: |
|
10 | // http://grimore.org/secondlife/scripted_agents/corrade |
10 | // http://grimore.org/secondlife/scripted_agents/corrade |
|
11 | // |
11 | // |
|
12 | /////////////////////////////////////////////////////////////////////////// |
12 | /////////////////////////////////////////////////////////////////////////// |
|
13 | |
13 | |
|
14 | /////////////////////////////////////////////////////////////////////////// |
14 | /////////////////////////////////////////////////////////////////////////// |
|
15 | // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
15 | // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
|
16 | /////////////////////////////////////////////////////////////////////////// |
16 | /////////////////////////////////////////////////////////////////////////// |
|
17 | string wasKeyValueGet(string k, string data) { |
17 | string wasKeyValueGet(string k, string data) { |
|
18 | if(llStringLength(data) == 0) return ""; |
18 | if(llStringLength(data) == 0) return ""; |
|
19 | if(llStringLength(k) == 0) return ""; |
19 | if(llStringLength(k) == 0) return ""; |
|
20 | list a = llParseString2List(data, ["&", "="], []); |
20 | list a = llParseString2List(data, ["&", "="], []); |
|
21 | integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]); |
21 | integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]); |
|
22 | if(i != -1) return llList2String(a, 2*i+1); |
22 | if(i != -1) return llList2String(a, 2*i+1); |
|
23 | return ""; |
23 | return ""; |
|
24 | } |
24 | } |
|
25 | |
25 | |
|
26 | /////////////////////////////////////////////////////////////////////////// |
26 | /////////////////////////////////////////////////////////////////////////// |
|
27 | // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // |
27 | // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // |
|
28 | /////////////////////////////////////////////////////////////////////////// |
28 | /////////////////////////////////////////////////////////////////////////// |
|
29 | string wasKeyValueEncode(list data) { |
29 | string wasKeyValueEncode(list data) { |
|
30 | list k = llList2ListStrided(data, 0, -1, 2); |
30 | list k = llList2ListStrided(data, 0, -1, 2); |
|
31 | list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2); |
31 | list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2); |
|
32 | data = []; |
32 | data = []; |
|
33 | do { |
33 | do { |
|
34 | data += llList2String(k, 0) + "=" + llList2String(v, 0); |
34 | data += llList2String(k, 0) + "=" + llList2String(v, 0); |
|
35 | k = llDeleteSubList(k, 0, 0); |
35 | k = llDeleteSubList(k, 0, 0); |
|
36 | v = llDeleteSubList(v, 0, 0); |
36 | v = llDeleteSubList(v, 0, 0); |
|
37 | } while(llGetListLength(k) != 0); |
37 | } while(llGetListLength(k) != 0); |
|
38 | return llDumpList2String(data, "&"); |
38 | return llDumpList2String(data, "&"); |
|
39 | } |
39 | } |
|
40 | |
40 | |
|
41 | /////////////////////////////////////////////////////////////////////////// |
41 | /////////////////////////////////////////////////////////////////////////// |
|
42 | // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
42 | // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
|
43 | /////////////////////////////////////////////////////////////////////////// |
43 | /////////////////////////////////////////////////////////////////////////// |
|
44 | // escapes a string in conformance with RFC1738 |
44 | // escapes a string in conformance with RFC1738 |
|
45 | string wasURLEscape(string i) { |
45 | string wasURLEscape(string i) { |
|
46 | string o = ""; |
46 | string o = ""; |
|
47 | do { |
47 | do { |
|
48 | string c = llGetSubString(i, 0, 0); |
48 | string c = llGetSubString(i, 0, 0); |
|
49 | i = llDeleteSubString(i, 0, 0); |
49 | i = llDeleteSubString(i, 0, 0); |
|
50 | if(c == "") jump continue; |
50 | if(c == "") jump continue; |
|
51 | if(c == " ") { |
51 | if(c == " ") { |
|
52 | o += "+"; |
52 | o += "+"; |
|
53 | jump continue; |
53 | jump continue; |
|
54 | } |
54 | } |
|
55 | if(c == "\n") { |
55 | if(c == "\n") { |
|
56 | o += "%0D" + llEscapeURL(c); |
56 | o += "%0D" + llEscapeURL(c); |
|
57 | jump continue; |
57 | jump continue; |
|
58 | } |
58 | } |
|
59 | o += llEscapeURL(c); |
59 | o += llEscapeURL(c); |
|
60 | @continue; |
60 | @continue; |
|
61 | } while(i != ""); |
61 | } while(i != ""); |
|
62 | return o; |
62 | return o; |
|
63 | } |
63 | } |
|
64 | |
64 | |
|
65 | // for notecard reading |
65 | // for notecard reading |
|
66 | integer line = 0; |
66 | integer line = 0; |
|
67 | |
67 | |
|
68 | // key-value data will be read into this list |
68 | // key-value data will be read into this list |
|
69 | list tuples = []; |
69 | list tuples = []; |
|
70 | // Corrade's online status. |
70 | // Corrade's online status. |
|
71 | integer online = FALSE; |
71 | integer online = FALSE; |
|
72 | integer open = FALSE; |
72 | integer open = FALSE; |
|
73 | string URL = ""; |
73 | string URL = ""; |
|
74 | |
74 | |
|
75 | default { |
75 | default { |
|
76 | state_entry() { |
76 | state_entry() { |
|
77 | if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) { |
77 | if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) { |
|
78 | llOwnerSay("Sorry, could not find a configuration inventory notecard."); |
78 | llOwnerSay("Sorry, could not find a configuration inventory notecard."); |
|
79 | return; |
79 | return; |
|
80 | } |
80 | } |
|
81 | // DEBUG |
81 | // DEBUG |
|
82 | llOwnerSay("Reading configuration file..."); |
82 | llOwnerSay("Reading configuration file..."); |
|
83 | llGetNotecardLine("configuration", line); |
83 | llGetNotecardLine("configuration", line); |
|
84 | } |
84 | } |
|
85 | dataserver(key id, string data) { |
85 | dataserver(key id, string data) { |
|
86 | if(data == EOF) { |
86 | if(data == EOF) { |
|
87 | // invariant, length(tuples) % 2 == 0 |
87 | // invariant, length(tuples) % 2 == 0 |
|
88 | if(llGetListLength(tuples) % 2 != 0) { |
88 | if(llGetListLength(tuples) % 2 != 0) { |
|
89 | llOwnerSay("Error in configuration notecard."); |
89 | llOwnerSay("Error in configuration notecard."); |
|
90 | return; |
90 | return; |
|
91 | } |
91 | } |
|
92 | key CORRADE = llList2Key( |
92 | key CORRADE = llList2Key( |
|
93 | tuples, |
93 | tuples, |
|
94 | llListFindList( |
94 | llListFindList( |
|
95 | tuples, |
95 | tuples, |
|
96 | [ |
96 | [ |
|
97 | "corrade" |
97 | "corrade" |
|
98 | ] |
98 | ] |
|
99 | ) |
99 | ) |
|
100 | +1); |
100 | +1); |
|
101 | if(CORRADE == NULL_KEY) { |
101 | if(CORRADE == NULL_KEY) { |
|
102 | llOwnerSay("Error in configuration notecard: corrade"); |
102 | llOwnerSay("Error in configuration notecard: corrade"); |
|
103 | return; |
103 | return; |
|
104 | } |
104 | } |
|
105 | string GROUP = llList2String( |
105 | string GROUP = llList2String( |
|
106 | tuples, |
106 | tuples, |
|
107 | llListFindList( |
107 | llListFindList( |
|
108 | tuples, |
108 | tuples, |
|
109 | [ |
109 | [ |
|
110 | "group" |
110 | "group" |
|
111 | ] |
111 | ] |
|
112 | ) |
112 | ) |
|
113 | +1); |
113 | +1); |
|
114 | if(GROUP == "") { |
114 | if(GROUP == "") { |
|
115 | llOwnerSay("Error in configuration notecard: group"); |
115 | llOwnerSay("Error in configuration notecard: group"); |
|
116 | return; |
116 | return; |
|
117 | } |
117 | } |
|
118 | string PASSWORD = llList2String( |
118 | string PASSWORD = llList2String( |
|
119 | tuples, |
119 | tuples, |
|
120 | llListFindList( |
120 | llListFindList( |
|
121 | tuples, |
121 | tuples, |
|
122 | [ |
122 | [ |
|
123 | "password" |
123 | "password" |
|
124 | ] |
124 | ] |
|
125 | ) |
125 | ) |
|
126 | +1); |
126 | +1); |
|
127 | if(PASSWORD == "") { |
127 | if(PASSWORD == "") { |
|
128 | llOwnerSay("Error in configuration notecard: password"); |
128 | llOwnerSay("Error in configuration notecard: password"); |
|
129 | return; |
129 | return; |
|
130 | } |
130 | } |
|
131 | string VERSION = llList2String( |
131 | string VERSION = llList2String( |
|
132 | tuples, |
132 | tuples, |
|
133 | llListFindList( |
133 | llListFindList( |
|
134 | tuples, |
134 | tuples, |
|
135 | [ |
135 | [ |
|
136 | "version" |
136 | "version" |
|
137 | ] |
137 | ] |
|
138 | ) |
138 | ) |
|
139 | +1); |
139 | +1); |
|
140 | if(VERSION == "") { |
140 | if(VERSION == "") { |
|
141 | llOwnerSay("Error in configuration notecard: version"); |
141 | llOwnerSay("Error in configuration notecard: version"); |
|
142 | return; |
142 | return; |
|
143 | } |
143 | } |
|
144 | // DEBUG |
144 | // DEBUG |
|
145 | llOwnerSay("Read configuration notecard..."); |
145 | llOwnerSay("Read configuration notecard..."); |
|
146 | state configuration; |
146 | state configuration; |
|
147 | } |
147 | } |
|
148 | if(data == "") jump continue; |
148 | if(data == "") jump continue; |
|
149 | integer i = llSubStringIndex(data, "#"); |
149 | integer i = llSubStringIndex(data, "#"); |
|
150 | if(i != -1) data = llDeleteSubString(data, i, -1); |
150 | if(i != -1) data = llDeleteSubString(data, i, -1); |
|
151 | list o = llParseString2List(data, ["="], []); |
151 | list o = llParseString2List(data, ["="], []); |
|
152 | // get rid of starting and ending quotes |
152 | // get rid of starting and ending quotes |
|
153 | string k = llDumpList2String( |
153 | string k = llDumpList2String( |
|
154 | llParseString2List( |
154 | llParseString2List( |
|
155 | llStringTrim( |
155 | llStringTrim( |
|
156 | llList2String( |
156 | llList2String( |
|
157 | o, |
157 | o, |
|
158 | 0 |
158 | 0 |
|
159 | ), |
159 | ), |
|
160 | STRING_TRIM), |
160 | STRING_TRIM), |
|
161 | ["\""], [] |
161 | ["\""], [] |
|
162 | ), "\""); |
162 | ), "\""); |
|
163 | string v = llDumpList2String( |
163 | string v = llDumpList2String( |
|
164 | llParseString2List( |
164 | llParseString2List( |
|
165 | llStringTrim( |
165 | llStringTrim( |
|
166 | llList2String( |
166 | llList2String( |
|
167 | o, |
167 | o, |
|
168 | 1 |
168 | 1 |
|
169 | ), |
169 | ), |
|
170 | STRING_TRIM), |
170 | STRING_TRIM), |
|
171 | ["\""], [] |
171 | ["\""], [] |
|
172 | ), "\""); |
172 | ), "\""); |
|
173 | if(k == "" || v == "") jump continue; |
173 | if(k == "" || v == "") jump continue; |
|
174 | tuples += k; |
174 | tuples += k; |
|
175 | tuples += v; |
175 | tuples += v; |
|
176 | @continue; |
176 | @continue; |
|
177 | llGetNotecardLine("configuration", ++line); |
177 | llGetNotecardLine("configuration", ++line); |
|
178 | } |
178 | } |
|
179 | attach(key id) { |
179 | attach(key id) { |
|
180 | llResetScript(); |
180 | llResetScript(); |
|
181 | } |
181 | } |
|
182 | on_rez(integer num) { |
182 | on_rez(integer num) { |
|
183 | llResetScript(); |
183 | llResetScript(); |
|
184 | } |
184 | } |
|
185 | changed(integer change) { |
185 | changed(integer change) { |
|
186 | if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { |
186 | if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { |
|
187 | llResetScript(); |
187 | llResetScript(); |
|
188 | } |
188 | } |
|
189 | } |
189 | } |
|
190 | } |
190 | } |
|
191 | |
191 | |
|
192 | state configuration { |
192 | state configuration { |
|
193 | state_entry() { |
193 | state_entry() { |
|
194 | // DEBUG |
194 | // DEBUG |
|
195 | llOwnerSay("Configuration ready..."); |
195 | llOwnerSay("Configuration ready..."); |
|
196 | llMessageLinked(LINK_SET, 0, "retract", NULL_KEY); |
196 | llMessageLinked(LINK_SET, 0, "retract", NULL_KEY); |
|
197 | llSetTimerEvent(1); |
197 | llSetTimerEvent(1); |
|
198 | } |
198 | } |
|
199 | timer() { |
199 | timer() { |
|
200 | llRequestAgentData( |
200 | llRequestAgentData( |
|
201 | (key)wasKeyValueGet( |
201 | (key)wasKeyValueGet( |
|
202 | "corrade", |
202 | "corrade", |
|
203 | wasKeyValueEncode(tuples) |
203 | wasKeyValueEncode(tuples) |
|
204 | ), |
204 | ), |
|
205 | DATA_ONLINE |
205 | DATA_ONLINE |
|
206 | ); |
206 | ); |
|
207 | llSetTimerEvent(5); |
207 | llSetTimerEvent(5); |
|
208 | } |
208 | } |
|
209 | dataserver(key id, string data) { |
209 | dataserver(key id, string data) { |
|
210 | if(data != "1") { |
210 | if(data != "1") { |
|
211 | if(online == TRUE) { |
211 | if(online == TRUE) { |
|
212 | // DEBUG |
212 | // DEBUG |
|
213 | llOwnerSay("Corrade is not online, shutting down..."); |
213 | llOwnerSay("Corrade is not online, shutting down..."); |
|
214 | llMessageLinked(LINK_SET, 0, "retract", NULL_KEY); |
214 | llMessageLinked(LINK_SET, 0, "retract", NULL_KEY); |
|
215 | online = FALSE; |
215 | online = FALSE; |
|
216 | } |
216 | } |
|
217 | return; |
217 | return; |
|
218 | } |
218 | } |
|
219 | online = TRUE; |
219 | online = TRUE; |
|
220 | } |
220 | } |
|
221 | touch_start(integer total_number) { |
221 | touch_start(integer total_number) { |
|
222 | if(!open && online) { |
222 | if(!open && online) { |
|
223 | // DEBUG |
223 | // DEBUG |
|
224 | llOwnerSay("Getting URL..."); |
224 | llOwnerSay("Getting URL..."); |
|
225 | llRequestURL(); |
225 | llRequestURL(); |
|
226 | return; |
226 | return; |
|
227 | } |
227 | } |
|
228 | llMessageLinked(LINK_SET, 0, "retract", NULL_KEY); |
228 | llMessageLinked(LINK_SET, 0, "retract", NULL_KEY); |
|
229 | open = FALSE; |
229 | open = FALSE; |
|
230 | } |
230 | } |
|
231 | http_request(key id, string method, string body) { |
231 | http_request(key id, string method, string body) { |
|
232 | llHTTPResponse(id, 200, "OK"); |
232 | llHTTPResponse(id, 200, "OK"); |
|
233 | llReleaseURL(URL); |
233 | llReleaseURL(URL); |
|
234 | string configuration = wasKeyValueEncode(tuples); |
234 | string configuration = wasKeyValueEncode(tuples); |
|
235 | if(method == URL_REQUEST_GRANTED) { |
235 | if(method == URL_REQUEST_GRANTED) { |
|
236 | llOwnerSay("Checking version..."); |
236 | llOwnerSay("Checking version..."); |
|
237 | |
237 | |
|
238 | URL = body; |
238 | URL = body; |
|
239 | llInstantMessage( |
239 | llInstantMessage( |
|
240 | wasKeyValueGet( |
240 | wasKeyValueGet( |
|
241 | "corrade", |
241 | "corrade", |
|
242 | configuration |
242 | configuration |
|
243 | ), |
243 | ), |
|
244 | wasKeyValueEncode( |
244 | wasKeyValueEncode( |
|
245 | [ |
245 | [ |
|
246 | "command", "version", |
246 | "command", "version", |
|
247 | "group", wasURLEscape( |
247 | "group", wasURLEscape( |
|
248 | wasKeyValueGet( |
248 | wasKeyValueGet( |
|
249 | "group", |
249 | "group", |
|
250 | configuration |
250 | configuration |
|
251 | ) |
251 | ) |
|
252 | ), |
252 | ), |
|
253 | "password", wasURLEscape( |
253 | "password", wasURLEscape( |
|
254 | wasKeyValueGet( |
254 | wasKeyValueGet( |
|
255 | "password", |
255 | "password", |
|
256 | configuration |
256 | configuration |
|
257 | ) |
257 | ) |
|
258 | ), |
258 | ), |
|
259 | "callback", wasURLEscape(URL) |
259 | "callback", wasURLEscape(URL) |
|
260 | ] |
260 | ] |
|
261 | ) |
261 | ) |
|
262 | ); |
262 | ); |
|
263 | return; |
263 | return; |
|
264 | } |
264 | } |
|
265 | if(wasKeyValueGet("command", body) != "version" || |
265 | if(wasKeyValueGet("command", body) != "version" || |
|
266 | wasKeyValueGet("success", body) != "True") { |
266 | wasKeyValueGet("success", body) != "True") { |
|
267 | llOwnerSay("Version check failed..."); |
267 | llOwnerSay("Version check failed..."); |
|
268 | return; |
268 | return; |
|
269 | } |
269 | } |
|
270 | list v = llParseString2List( |
270 | list corradeVersion = llParseString2List( |
|
271 | wasKeyValueGet( |
271 | wasKeyValueGet( |
|
272 | "data", |
272 | "data", |
|
273 | body |
273 | body |
|
274 | ), |
274 | ), |
|
275 | ["."], |
275 | ["."], |
|
276 | [] |
276 | [] |
|
277 | ); |
277 | ); |
|
278 | integer receivedVersion = (integer)(llList2String(v, 0) + llList2String(v, 1)); |
278 | //integer receivedVersion = (integer)(llList2String(v, 0) + llList2String(v, 1)); |
|
279 | v = llParseString2List( |
279 | list notecardVersion = llParseString2List( |
|
280 | wasKeyValueGet( |
280 | wasKeyValueGet( |
|
281 | "version", |
281 | "version", |
|
282 | configuration |
282 | configuration |
|
283 | ), |
283 | ), |
|
284 | ["."], |
284 | ["."], |
|
285 | [] |
285 | [] |
|
286 | ); |
286 | ); |
|
- | 287 | //llOwnerSay((string)receivedVersion); |
||
287 | integer notecardVersion = (integer)(llList2String(v, 0) + llList2String(v, 1)); |
288 | //integer notecardVersion = (integer)(llList2String(v, 0) + llList2String(v, 1)); |
|
- | 289 | if(llList2Integer(corradeVersion, 0) >= llList2Integer(notecardVersion, 0) || llList2Integer(corradeVersion, 1) >= llList2Integer(notecardVersion, 1)) { |
||
288 | if(receivedVersion < notecardVersion) { |
290 | llOwnerSay("Version is compatible. Deploying HUD..."); |
|
- | 291 | llMessageLinked(LINK_SET, 0, "deploy", NULL_KEY); |
||
- | 292 | open = TRUE; |
||
- | 293 | return; |
||
- | 294 | } |
||
289 | llOwnerSay("HUD version is incompatible! You need a Corrade of at least version: " + |
295 | llOwnerSay("HUD version is incompatible! You need a Corrade of at least version: " + |
|
290 | wasKeyValueGet( |
296 | wasKeyValueGet( |
|
291 | "version", |
297 | "version", |
|
292 | configuration |
298 | configuration |
|
293 | ) + |
299 | ) + |
|
294 | " for this HUD." |
300 | " for this HUD." |
|
295 | ); |
301 | ); |
|
296 | llMessageLinked(LINK_SET, 0, "retract", NULL_KEY); |
302 | llMessageLinked(LINK_SET, 0, "retract", NULL_KEY); |
|
297 | open = FALSE; |
303 | open = FALSE; |
|
298 | return; |
304 | return; |
|
299 | } |
- | ||
300 | llOwnerSay("Version is compatible. Deploying HUD..."); |
- | ||
301 | llMessageLinked(LINK_SET, 0, "deploy", NULL_KEY); |
- | ||
302 | open = TRUE; |
- | ||
303 | return; |
- | ||
304 | } |
305 | } |
|
305 | link_message(integer sender, integer num, string message, key id) { |
306 | link_message(integer sender, integer num, string message, key id) { |
|
306 | if(message != "configuration") return; |
307 | if(message != "configuration") return; |
|
307 | llMessageLinked(sender, 0, wasKeyValueEncode(tuples), "configuration"); |
308 | llMessageLinked(sender, 0, wasKeyValueEncode(tuples), "configuration"); |
|
308 | } |
309 | } |
|
309 | attach(key id) { |
310 | attach(key id) { |
|
310 | llResetScript(); |
311 | llResetScript(); |
|
311 | } |
312 | } |
|
312 | on_rez(integer num) { |
313 | on_rez(integer num) { |
|
313 | llResetScript(); |
314 | llResetScript(); |
|
314 | } |
315 | } |
|
315 | changed(integer change) { |
316 | changed(integer change) { |
|
316 | if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { |
317 | if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { |
|
317 | llResetScript(); |
318 | llResetScript(); |
|
318 | } |
319 | } |
|
319 | } |
320 | } |
|
320 | } |
321 | } |
|
321 | |
322 | |