Damian Zhaoying 2 лет назад
Сommit
dd47899f28
100 измененных файлов с 8115 добавлено и 0 удалено
  1. 38 0
      README
  2. 4 0
      iar/archive.xml
  3. 63 0
      iar/assets/00000000-0000-0000-0000-000000000000_bodypart.txt
  4. BIN
      iar/assets/00000000-0000-2222-3333-100000001007_texture.jp2
  5. BIN
      iar/assets/00be3606-0246-4b9f-9d3e-dd4e0b15c172_texture.jp2
  6. 155 0
      iar/assets/0127c661-90af-ba1f-d770-488416278d00_script.lsl
  7. BIN
      iar/assets/0187b628-6f2d-48a0-b785-95e75fc384b1_texture.jp2
  8. 138 0
      iar/assets/024309af-b426-483c-7565-b156ae45fc3b_script.lsl
  9. 337 0
      iar/assets/049367a6-8ec5-0162-a24c-34bcceef21c6_script.lsl
  10. BIN
      iar/assets/04cce2f4-785a-4855-8ba3-1e370c1c2c2d_texture.jp2
  11. 0 0
      iar/assets/04ddcf72-b9de-474a-950e-8cf77ed58443_object.xml
  12. 89 0
      iar/assets/052c2183-f8a7-967b-13af-353bfd112421_script.lsl
  13. 339 0
      iar/assets/05b3af22-0fe6-7bad-0a45-00f8b21eebae_script.lsl
  14. BIN
      iar/assets/0621d24e-7dda-46ad-a9f5-43bc016b2599_texture.jp2
  15. BIN
      iar/assets/0648e879-ede7-43d1-9f65-389fe88a49a1_texture.jp2
  16. BIN
      iar/assets/06e4c064-c447-4d98-8fdc-4093abf909da_texture.jp2
  17. BIN
      iar/assets/07ea778e-d96c-4964-a6cc-9ef77694d764_sound.ogg
  18. BIN
      iar/assets/0a68cb4e-4993-4e76-8430-f0b5acc3a0eb_texture.jp2
  19. BIN
      iar/assets/0cd006d4-4717-4c3c-b218-5924ea5f0f2f_texture.jp2
  20. BIN
      iar/assets/0d55946d-e8f8-464f-8a2f-95b2ac2c1b55_texture.jp2
  21. 478 0
      iar/assets/0e5abbde-22d1-9a7d-d67f-c570629ab371_script.lsl
  22. 0 0
      iar/assets/0ed3aad5-337f-4f2f-84f3-dedd341bcfd6_object.xml
  23. BIN
      iar/assets/0f2cccbb-305e-4c7f-b108-ecdc33af9d0c_texture.jp2
  24. 35 0
      iar/assets/0fa2b92f-cdfa-3bd7-8638-f4c78d02ff84_script.lsl
  25. 331 0
      iar/assets/0fca899b-5276-f63e-ea5c-41e3e8477ad2_script.lsl
  26. 78 0
      iar/assets/10494eb1-6911-9467-09e7-b7e64c0312fb_script.lsl
  27. BIN
      iar/assets/10679de3-324f-4a85-ab45-54a409608ade_animation.bvh
  28. BIN
      iar/assets/125db676-fc3b-4a52-801b-5c7c2c60826e_texture.jp2
  29. 59 0
      iar/assets/128bdc62-9af8-5b13-06ca-7354d923456d_script.lsl
  30. BIN
      iar/assets/16cbe30a-f753-4f0e-94e6-5b1b56965950_texture.jp2
  31. 321 0
      iar/assets/16d8d4c4-6427-f346-8b5c-554469d623b6_script.lsl
  32. BIN
      iar/assets/17ff929d-7905-4efa-ad7d-b064591fd225_texture.jp2
  33. 73 0
      iar/assets/1a8672e3-b191-de07-a075-22ad58dd48a2_script.lsl
  34. BIN
      iar/assets/1b173b2c-9d2c-4f7a-8239-b715f8d94174_texture.jp2
  35. BIN
      iar/assets/1c3f1858-4b3e-4b4d-9c2c-3cfd7b153be0_texture.jp2
  36. BIN
      iar/assets/1dffe964-adf4-44ce-8fca-79727db814f0_texture.jp2
  37. BIN
      iar/assets/1e32f5c9-9083-4a83-b11d-b39d9705bb0b_sound.ogg
  38. 486 0
      iar/assets/1ff5939a-4da0-c9b8-00a9-6ac86803b543_script.lsl
  39. BIN
      iar/assets/242a849f-9f63-40ad-b3e2-98135b326d42_texture.jp2
  40. 0 0
      iar/assets/24d0383f-b931-4966-8f05-912dea15ba40_object.xml
  41. BIN
      iar/assets/2507e9d9-dfcc-478a-a18f-f4ad719daba3_sound.ogg
  42. BIN
      iar/assets/25b1caca-f1dd-4fc1-89bc-238d25e5de50_texture.jp2
  43. BIN
      iar/assets/25dd51e6-5d6b-4f8a-b2f7-8bef574f2aa0_texture.jp2
  44. 72 0
      iar/assets/263e78b2-cb75-7cbd-012c-d6d900b8b62e_script.lsl
  45. BIN
      iar/assets/2875e885-2f83-4ae6-bfb3-067f36e18773_sound.ogg
  46. 452 0
      iar/assets/28b36c20-b296-2f40-1159-8a8e49169079_script.lsl
  47. 338 0
      iar/assets/2a04deec-21ff-f997-f719-c7d45ad8f575_script.lsl
  48. BIN
      iar/assets/2ca24bdc-c2c1-40e0-813a-8ab2f61208f8_texture.jp2
  49. 0 0
      iar/assets/2e032d59-aef7-4e92-b1e4-ae8d95aa503f_object.xml
  50. BIN
      iar/assets/2f7ea399-2265-4e93-a438-e77e3be270f9_texture.jp2
  51. BIN
      iar/assets/3260992b-4721-4603-acce-e240c5dc76c2_texture.jp2
  52. 0 0
      iar/assets/32dec74d-95b7-4d5d-bdf2-88e53f791011_object.xml
  53. 0 0
      iar/assets/3385a309-bdbc-4f9b-b996-a31a50544fad_object.xml
  54. BIN
      iar/assets/34178b86-6836-4b2d-8d55-4dbde770bc25_sound.ogg
  55. 0 0
      iar/assets/3489df28-10cd-443c-81e5-96645715044b_object.xml
  56. BIN
      iar/assets/365e73c3-4cff-4fb0-93df-89b74e9fc54b_texture.jp2
  57. 0 0
      iar/assets/37e7fcca-f8f5-4b5d-97ae-3a4f66352c26_object.xml
  58. BIN
      iar/assets/3887be04-03b5-45e6-9762-b77989f49a46_texture.jp2
  59. 501 0
      iar/assets/39dc01c9-3546-9073-1c35-dc6a46cf0b77_script.lsl
  60. BIN
      iar/assets/3bd547dc-3ab0-4b6f-811b-4b15def62202_texture.jp2
  61. BIN
      iar/assets/3e5cdbe2-678f-4708-a69a-506f15335b3e_texture.jp2
  62. 143 0
      iar/assets/424d4a18-96f5-408a-9a29-7257a0691e6d_notecard.txt
  63. BIN
      iar/assets/46538c19-3ccd-434e-a32a-b9e7126a1528_texture.jp2
  64. BIN
      iar/assets/4901aa6f-e258-4e9d-b5b4-a54dd7a0de3f_texture.jp2
  65. BIN
      iar/assets/49356f8d-19a2-4a75-aed8-cfe471b32d1d_texture.jp2
  66. BIN
      iar/assets/496a64a8-ca72-41c4-a3db-d3db4fd9866d_texture.jp2
  67. BIN
      iar/assets/49add369-c134-4190-a367-a8c319f25262_texture.jp2
  68. BIN
      iar/assets/4a5e0f0e-5ec8-4709-897a-4d52f07b8848_texture.jp2
  69. 72 0
      iar/assets/4c43d94a-d657-8238-e9e7-9f01ce60ceff_script.lsl
  70. BIN
      iar/assets/4cf64d18-4186-4c42-a1ee-089bbb8ba0c0_animation.bvh
  71. 344 0
      iar/assets/4d9d75f2-767e-9d59-15b0-ec9b9330328f_script.lsl
  72. BIN
      iar/assets/4f630a4c-fb72-405e-889e-41f2fbab3091_texture.jp2
  73. BIN
      iar/assets/4feb0e8b-52cc-4e56-a7cd-2baf903bf817_texture.jp2
  74. BIN
      iar/assets/50770476-ba85-4e8a-8cdd-7e4660bc9c6d_sound.ogg
  75. BIN
      iar/assets/51262c74-5c4a-437a-b7a9-efb324bfdbf7_texture.jp2
  76. BIN
      iar/assets/551a3475-5465-417b-a2e0-977c6118d44b_texture.jp2
  77. BIN
      iar/assets/5748decc-f629-461c-9a36-a35a221fe21f_texture.jp2
  78. BIN
      iar/assets/5799410c-785d-44de-8412-0397bbab02da_texture.jp2
  79. BIN
      iar/assets/59c93ffb-100b-4489-bd8e-9ede0af5a0bf_texture.jp2
  80. 309 0
      iar/assets/5a427f6d-acd8-8e50-20cd-df42e7b6f11c_script.lsl
  81. BIN
      iar/assets/5bf8f055-2835-4e4f-8269-047ba8e4c124_texture.jp2
  82. BIN
      iar/assets/5cc21038-0a07-4111-88bb-a631f56ca9d3_texture.jp2
  83. BIN
      iar/assets/5d778e6b-8dd6-4713-b43b-db3b0f4a1e83_texture.jp2
  84. 746 0
      iar/assets/5fba4668-a2e7-60ce-f7a0-2eb174feab09_script.lsl
  85. 143 0
      iar/assets/60aec86a-180a-2e02-5689-9c6f43f5db25_script.lsl
  86. BIN
      iar/assets/60fb5674-f500-4522-b176-0aba4418edae_texture.jp2
  87. 582 0
      iar/assets/6219fb67-fd6e-0181-3472-f206795a274f_script.lsl
  88. 361 0
      iar/assets/62a5f1dc-ccdd-df39-de68-36a1087a2dfa_script.lsl
  89. BIN
      iar/assets/6395670a-f392-482b-8833-7b691cbe29eb_sound.ogg
  90. BIN
      iar/assets/6764b59f-fe5f-4a46-9b8b-401fc0c840df_animation.bvh
  91. 407 0
      iar/assets/68bf8913-cf9f-c581-ce72-aecc8a7a8905_script.lsl
  92. BIN
      iar/assets/6969bc92-e498-4cbc-ba37-d377cec437cf_animation.bvh
  93. 216 0
      iar/assets/696f7f0e-d61a-8241-71c5-80a1d0b9110a_script.lsl
  94. 52 0
      iar/assets/6b000664-a9cb-b6c7-eab7-1868b0547779_script.lsl
  95. BIN
      iar/assets/6b265e92-3f9f-41a8-a3b6-ec1fb5e034c6_texture.jp2
  96. 191 0
      iar/assets/6be2920f-64b3-316c-b5a2-35c2e59371f1_script.lsl
  97. BIN
      iar/assets/6c6c690a-c338-4bc8-adea-88bf1e7782c9_texture.jp2
  98. 0 0
      iar/assets/6d0350c7-8088-4bf2-8026-7d23f7658212_object.xml
  99. BIN
      iar/assets/6e69433e-9b9c-4b55-ba3a-5c90ceb9b455_texture.jp2
  100. 162 0
      iar/assets/6e7f4324-411b-8919-6333-4381db503da5_script.lsl

+ 38 - 0
README

@@ -0,0 +1,38 @@
+This repo is for the IAR archive of the SLOODLE rezzer.
+
+The contents of the IAR archive is stored in decompressed form.
+To import it into an OpenSim grid, you need to archive it with tar / gzip.
+
+Example:
+
+# Go into the directory containing the IAR. 
+cd iar/
+
+# Archive the contents as a file called /tmp/sloodle.iar.
+# NB OpenSim may choke on the archive unless the files are archived in the specified order.
+# Also it prefers the directory/* formulation to avoid spurious errors.
+tar zcvf /tmp/sloodle.iar archive.xml inventory/* assets/*
+
+# In the OpenSim console, you should now be able to load the archive:
+load iar Your Avatar / yourpassw0rd /tmp/sloodle.iar
+
+
+To recreate this iar and update the Git repo, do the following:
+
+# Make a directory in inventory - recommend iar/export/sloodle
+
+# Make a directory on the disk that the opensim user can write to - recommend /tmp/iar/export
+mkdir /tmp/iar/export
+
+# In the OpenSim console, export the iar: 
+save iar Your Avatar /iar/export/sloodle/ yourpassw0rd /tmp/iar/export/sloodle.iar
+
+# Remove the contents of the current iar directory, and unpack the new iar instead.
+rm -rf iar/*
+cd iar
+tar zxvf /tmp/iar/export/sloodle.iar
+
+# Tell Git to accept all the changes, commit and push
+git add .
+git commit -a
+git push 

+ 4 - 0
iar/archive.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-16"?>
+<archive major_version="0" minor_version="3">
+  <assets_included>True</assets_included>
+</archive>

+ 63 - 0
iar/assets/00000000-0000-0000-0000-000000000000_bodypart.txt

@@ -0,0 +1,63 @@
+LLWearable version 22
+New Hair
+
+	permissions 0
+	{
+		base_mask	7fffffff
+		owner_mask	7fffffff
+		group_mask	00000000
+		everyone_mask	00000000
+		next_owner_mask	00082000
+		creator_id	a52db6d0-e96c-4454-85e5-3523722daa25
+		owner_id	a52db6d0-e96c-4454-85e5-3523722daa25
+		last_owner_id	00000000-0000-0000-0000-000000000000
+		group_id	00000000-0000-0000-0000-000000000000
+	}
+	sale_info	0
+	{
+		sale_type	not
+		sale_price	10
+	}
+type 2
+parameters 39
+16 0
+31 .5
+112 0
+113 0
+114 .5
+115 0
+119 .5
+130 .45
+131 .5
+132 .39
+133 .25
+134 .5
+135 .55
+136 .5
+137 .5
+140 0
+141 0
+142 0
+143 .13
+166 0
+167 0
+168 0
+169 0
+177 0
+181 .14
+182 .7
+183 .05
+184 0
+192 0
+674 -.3
+750 .7
+752 .5
+754 0
+755 .05
+757 -1
+762 0
+763 .55
+785 0
+789 0
+textures 1
+4 7ca39b4c-bd19-4699-aff7-f93fd03d3e7b

BIN
iar/assets/00000000-0000-2222-3333-100000001007_texture.jp2


BIN
iar/assets/00be3606-0246-4b9f-9d3e-dd4e0b15c172_texture.jp2


+ 155 - 0
iar/assets/0127c661-90af-ba1f-d770-488416278d00_script.lsl

@@ -0,0 +1,155 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle Choice (for Sloodle 0.3)
+// This script represents a single bar on the bar graph display.
+//
+// Copyright (c) 2008 Sloodle
+// Released under the GNU GPL
+//
+// Contributors:
+//  Peter R. Bloomfield
+//
+
+
+integer SLOODLE_CHANNEL_OBJECT_CHOICE = -1639270051;
+
+
+// Choice commands
+// Update the specified option. Followed by "|num|text|colour|count|prop"
+//  - num is a local option identifier
+//  - text is the caption to display for this option
+//  - colour is a colour vector (cast to a string)
+//  - count is the number selected so far (or -1 if we don't want to display any)
+//  - prop is the proportion of maximum size to show (between 0 and 1)
+string SLOODLE_CHOICE_UPDATE_OPTION = "do:updateoption";
+// Select the specified option. Followed by "|num" (num is a local option identifier) 
+string SLOODLE_CHOICE_SELECT_OPTION = "do:selectoption";
+
+
+// The option scales on on the X axis.
+// Define the boundary sizes of this option, on the X axis.
+// (This actually represents double the visible size: only half will be visible due to path cutting).
+// (That easily allows a bar graph that grows only in one direction.)
+float MAX_SIZE = 5.0;
+float MIN_SIZE = 0.1;
+
+// This value determines if a number should be shown on this bar to indicate the number of selections so far.
+integer SHOW_SELECTIONS_NUM = FALSE;
+
+
+// The local number of this option
+integer myoptionnum = -1;
+
+
+// Set the scale of this option to the specified proportion
+set_scale(float prop)
+{
+    // Validate the proportion
+    if (prop < 0.0) prop = 0.0;
+    if (prop > 1.0) prop = 1.0;
+
+    // Get the current scale
+    vector myscale = llGetScale();
+    // Interpolate between the minimum and maximum sizes on the appropriate axis
+    myscale.x = MIN_SIZE + ((MAX_SIZE - MIN_SIZE) * prop);
+    
+    // Set the scale
+    llSetScale(myscale);
+}
+
+// Process an update command.
+// (parts should be a list of parts from the incoming command).
+// Returns true if successful, or false otherwise.
+integer process_update_command(list parts)
+{
+    // Get our option number
+    myoptionnum = (integer)llGetObjectDesc();
+
+    // We should have several parameters: "command|num|text|colour|count|prop"
+    if (llGetListLength(parts) < 6) return FALSE;
+    // Make sure the option number matches this one
+    if (myoptionnum != (integer)llList2String(parts, 1)) return FALSE;
+    
+    // Extract the data
+    vector mycol = (vector)llList2String(parts, 3);
+    integer mycount = (integer)llList2String(parts, 4);
+    float myprop = (float)llList2String(parts, 5);
+    
+    // Set our attributes
+    llSetColor(mycol, ALL_SIDES);
+    if (mycount >= 0 && SHOW_SELECTIONS_NUM) llSetText((string)mycount, mycol, 0.9);
+    else llSetText("", mycol, 0.0);
+    set_scale(myprop);
+    
+    return TRUE;
+}
+
+// Reset this option back to defaults
+reset_option()
+{
+    myoptionnum = -1;
+    llSetText("", <0.0, 0.0, 0.0>, 0.0);
+    llSetColor(<1.0,1.0,1.0>, ALL_SIDES);
+    set_scale(0.0);
+}
+
+
+// Uninitialised
+default
+{
+    state_entry()
+    {
+        reset_option();
+    }
+    
+    link_message(integer sender_num, integer num, string sval, key kval)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_CHOICE) {
+            // Parse the string
+            list parts = llParseString2List(sval, ["|"], []);
+            string cmd = llList2String(parts, 0);
+            
+            // Check the command
+            if (cmd == "do:reset") {
+                reset_option();
+            } else if (cmd == SLOODLE_CHOICE_UPDATE_OPTION) {
+               if (process_update_command(parts)) state ready;
+            }
+        }
+    }
+}
+
+
+// Ready and responding to interactions
+state ready
+{
+    link_message(integer sender_num, integer num, string sval, key kval)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_CHOICE) {
+            // Parse the string
+            list parts = llParseString2List(sval, ["|"], []);
+            string cmd = llList2String(parts, 0);
+            
+            // Check the command
+            if (cmd == "do:reset") {
+                state default;
+            } else if (cmd == SLOODLE_CHOICE_UPDATE_OPTION) {
+               process_update_command(parts);
+            }
+        }
+    }
+    
+    touch_start(integer num)
+    {
+        // Go through each toucher, and notify the choice
+        integer i;
+        for (i = 0; i < num; i++) {
+            llMessageLinked(LINK_SET, SLOODLE_CHANNEL_OBJECT_CHOICE, SLOODLE_CHOICE_SELECT_OPTION + "|" + (string)myoptionnum, llDetectedKey(i));
+        }
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/choice-1.0/objects/default/assets/sloodle_choice_option.lslp 

BIN
iar/assets/0187b628-6f2d-48a0-b785-95e75fc384b1_texture.jp2


+ 138 - 0
iar/assets/024309af-b426-483c-7565-b156ae45fc3b_script.lsl

@@ -0,0 +1,138 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle PrimDrop inventory checker.
+// Receives dropped prims, and checks for the most recently added one
+// Part of the Sloodle project (www.sloodle.org)
+//
+// Copyright (c) 2007-8 Sloodle
+// Released under the GNU GPL
+//
+// Contributors:
+//  Jeremy Kemp
+//  Peter R. Bloomfield
+//
+
+
+///// DATA /////
+
+// Link message channel
+integer SLOODLE_CHANNEL_PRIMDROP_INVENTORY = -1639270071;
+// Link message identifiers
+string PRIMDROP_RECEIVE_DROP = "do:receivedrop"; // Instructs the object to receive a drop
+string PRIMDROP_CANCEL_DROP = "do:canceldrop"; // Cancel drop receiving
+string PRIMDROP_FINISHED_DROP = "set:droppedobject"; // The drop has finished (object name passed as parameter after pipe character)
+
+// Stores the inventory
+list inventory = [];
+
+
+///// FUNCTIONS /////
+
+
+// Returns a list of all inventory (all types)
+list get_inventory(integer type)
+{
+    list inv = [];
+    integer num = llGetInventoryNumber(type);
+    integer i;
+    for (i = 0; i < num; i++) {
+        inv += [llGetInventoryName(type, i)];
+    }
+    
+    return inv;
+}
+
+
+// Compares 2 lists
+// Returns the first item on list1 that is not on list2
+// Returns an empty string if nothing is found
+string ListDiff(list list1, list list2) {
+    integer i;
+
+    for (i = 0; i < llGetListLength(list1); i++) {
+        if (llListFindList(list2, llList2List(list1, i, i)) == -1) {
+            return(llList2String(list1, i));
+        }
+    }
+    return("");
+}
+
+///// STATES /////
+
+// Idle state - waiting to be instructed to receive a drop
+default
+{
+    state_entry()
+    {
+        llAllowInventoryDrop(FALSE);
+    }
+    
+    link_message(integer sender_num, integer num, string sval, key kval)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_PRIMDROP_INVENTORY) {
+            if (sval == PRIMDROP_RECEIVE_DROP) {
+                // Start awaiting a drop
+                state drop;
+                return;
+            }
+        }
+    }
+}
+
+// Waiting for a drop to take place
+state drop
+{
+    state_entry()
+    {
+        // Check our current inventory
+        inventory = get_inventory(INVENTORY_ALL);
+        // Prepare to receive drops
+        llAllowInventoryDrop(TRUE);
+    }
+    
+    state_exit()
+    {
+        llAllowInventoryDrop(FALSE);
+    }
+    
+    changed(integer change)
+    {
+        // Has out inventory changed?
+        if ((change & CHANGED_INVENTORY) || (change & CHANGED_ALLOWED_DROP)) {
+            // Stop receiving inventory drops
+            llAllowInventoryDrop(FALSE);
+            // Check our new inventory, and find what's changed
+            list new_inventory = get_inventory(INVENTORY_ALL);
+            string submit_obj = ListDiff(new_inventory, inventory);
+            new_inventory = [];
+            inventory = [];
+            
+            // Notify the other script(s)
+            llMessageLinked(LINK_SET, SLOODLE_CHANNEL_PRIMDROP_INVENTORY, PRIMDROP_FINISHED_DROP + "|" + submit_obj, NULL_KEY);
+            state default;
+            return;
+        }
+    }
+    
+    link_message(integer sender_num, integer num, string sval, key kval)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_PRIMDROP_INVENTORY) {
+            if (sval == PRIMDROP_CANCEL_DROP) {
+                // Stop waiting for a drop
+                llAllowInventoryDrop(FALSE);
+                state default;
+                return;
+            }
+        }
+    }
+    
+    on_rez(integer par)
+    {
+        llResetScript();
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/primdrop-1.0/objects/default/assets/sloodle_primdrop_inventory.lslp 

+ 337 - 0
iar/assets/049367a6-8ec5-0162-a24c-34bcceef21c6_script.lsl

@@ -0,0 +1,337 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Standard translation script for Sloodle.
+// Contains the common, re-usable words and phrases.
+//
+// The "locstrings" list is pairs of strings.
+// The first of each pair is the name, and second is the translation.
+//
+// This script is part of the Sloodle project.
+// Copyright (c) 2008 Sloodle (various contributors)
+// Released under the GNU GPL v3
+//
+// Contributors:
+//  Peter R. Bloomfield
+//  Paul G. Preibisch
+
+// Note: where a translation string contains {{x}} (where x is a number),
+//  it means that a parameter can be inserted. Please make sure to include these
+//  parameters in the appropriate location in your translation.
+// It may be sensible to add comments after your string to indicate what its parameters mean.
+// NOTE: parameter numbering starts at 0 (unlike previous versions, which started at 1).
+
+// Translations can be requested by sending a link message on the SLOODLE_CHANNEL_TRANSLATION_REQUEST channel.
+// It is advisable simply to use the "sloodle_translation_request" function provided in this script.
+
+
+///// TRANSLATION /////
+
+// Localization batch - indicates the purpose of this file
+string mybatch = "distributor";
+
+
+// List of string names and translation pairs.
+// The name is the first of each pair, and should not be translated.
+// The second of each pair is the translation.
+// Additional comments are sometimes given afterward to aid translations.
+list locstrings = [
+    //  Distributor
+    "openingxmlrpc", "Opening XMLRPC channel...",
+    "establishingconnection", "Establishing connection with outside server...",
+    "dialog:distributorcommandmenu", "Sloodle Distributor.\nSelect an action:\n\n{{0}} = Reconnect\n{{1}} = Reset\n{{2}} = Shutdown", // Each parameter is a button label
+    "dialog:distributorobjectmenu", "Sloodle Distributor.\n\n{{0}}", // The parameter should be a set of button labels and object names, e.g. "1 = WebIntercom, 2 = MetaGloss"
+    "dialog:distributorobjectmenu:cmd", "Sloodle Distributor.\n\n{{0}}{{1}} = Command menu\n{{2}} = Visit Distributer on MOODLE", // As above, but the second parameter gives the command menu button label
+    "dialog:distributorobjectmenu:visitmoodle", "Click \"Go to page\" to visit the distributer on MOODLE", // As above, but the second parameter gives the command menu button label
+    "distributor:notconnected", "The distributer is currently not connected, or is shut down.  So we can not redirect you to the webpage for this distributer.",
+     "distributor:distributerisempty", "This distributer currently has no items in it."
+    
+];
+
+///// ----------- /////
+
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";                     // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";                       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";                   // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";          // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";            // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";                 // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";              // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_LOAD_URL_PARALLEL = "loadurlpar";  // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";          // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";             // Recipient avatar should be identified in link message keyval. No output parameters.
+
+
+// Used for sending parallel URL loading messages
+integer SLOODLE_CHANNEL_OBJECT_LOAD_URL = -1639270041;
+
+///// FUNCTIONS /////
+
+
+// Send a translation request link message
+// (Here for reference only)
+// Parameter: output_method = should identify an output method, as given by the "SLOODLE_TRANSLATE_..." constants above
+// Parameter: output_params = a list of parameters which controls the output, such as chat channel or buttons for a dialog
+// Parameter: string_name = the name of the localization string to output
+// Parameter: string_params = a list of parameters which will be included in the translated string (or an empty list if none)
+// Parameter: keyval = a key to send in the link message
+// Parameter: batch = the name of the localization batch which should handle this request
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+// Send a translation response link message
+sloodle_translation_response(integer target, string name, string translation)
+{
+    llMessageLinked(target, SLOODLE_CHANNEL_TRANSLATION_RESPONSE, name + "|" + translation + "|" + mybatch, NULL_KEY);
+}
+
+// Get the translation of a particular string
+string sloodle_get_string(string name)
+{
+    // Attempt to find the string name
+    integer numstrings = llGetListLength(locstrings);
+    integer pos = llListFindList(locstrings, [name]);
+    
+    // IMPORTANT: we must be careful not to match a translations instead of a name.
+    // If this was an even number, then we have a string name.
+    if ((pos % 2) == 0) {
+        // Make sure there is a subsequent translation in the list
+        if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
+        // The translation is not there
+        pos = -1;
+    }
+    
+    // If we could not find the string, then return a placeholder
+    if (pos < 0) return "[[" + name + "]]";
+    
+    // If we got here, then we matched a translation instead of a string name.
+    // As such, we need to resort to searching through the list manually (which can be very slow).
+    // To saved time, we can start from the position just beyond where we got to.
+    // We advance by 2 each time to skip the translations completely.
+    
+    for (pos += 1; pos < numstrings; pos += 2) {
+        // Do we have a match?
+        if (llList2String(locstrings, pos) == name) {
+            // Yes - make sure there is a translation following it
+            if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
+            // The translation is not there - skip the rest of the search
+            pos = numstrings;
+        }
+    }
+    
+    // If we reached this point, then the string is not available. Return a placeholder.
+    return "[[" + name + "]]";
+}
+
+// Send a debug link message
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+
+// Get a formatted translation of a string
+string sloodle_get_string_f(string name, list params)
+{
+    // Get the string itself
+    string str = sloodle_get_string(name);
+    // How many parameters do we have?
+    integer numparams = llGetListLength(params);
+    
+    // Go through each parameter we have been provided
+    integer curparamnum = 0;
+    string curparamtok = "{{x}}";
+    integer curparamtoklength = 0;
+    string curparamstr = "";
+    integer tokpos = -1;
+    for (curparamnum = 0; curparamnum < numparams; curparamnum++) {
+        // Construct this parameter token
+        curparamtok = "{{" + (string)(curparamnum) + "}}";
+        curparamtoklength = llStringLength(curparamtok);
+        // Fetch the parameter text
+        curparamstr = llList2String(params, curparamnum);
+        
+        // Ensure the parameter text does NOT contain double braces (this avoids an infinite loop!)
+        if (llSubStringIndex(curparamstr, "{{") < 0 && llSubStringIndex(curparamstr, "}}") < 0) {            
+            // Go through every instance of this parameter's token
+            while ((tokpos = llSubStringIndex(str, curparamtok)) >= 0) {
+                // Replace the token with the parameter string
+                str = llDeleteSubString(str, tokpos, tokpos + curparamtoklength - 1);
+                str = llInsertString(str, tokpos, curparamstr);
+            }
+        }
+    }
+    
+    return str;
+}
+
+
+///// STATES /////
+
+default
+{
+    state_entry()
+    {
+    }
+    
+    link_message(integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_TRANSLATION_REQUEST) {            
+            
+            // // PROCESS REQUEST // //
+        
+            // Split the incoming message into fields
+            
+            list fields = llParseStringKeepNulls(str, ["|"], []);
+            integer numfields = llGetListLength(fields);
+            
+            // Extract and check the localization batch
+            string batch = "";
+            if (numfields > 4) batch = llList2String(fields, 4);
+            if (batch != mybatch) return;
+            
+            // We expect at least 3 fields
+            // ... or 4 if there are insertion parameters...
+            // ... or 5 if there is a language code
+            // ... anybody up for a 6th parameter? :)
+            if (numfields < 3) {
+                sloodle_debug("ERROR: Insufficient fields for translation of string.");
+                return;
+            }
+            
+            // Extract the key parts of the request
+            string output_method = llList2String(fields, 0);
+            list output_params = llCSV2List(llList2String(fields, 1));
+            integer num_output_params = llGetListLength(output_params);
+            string string_name = llList2String(fields, 2);
+            list string_params = [];
+            if (numfields > 3) {
+                // Extract the string parameters (extra text added to the output)
+                string string_param_text = llList2String(fields, 3);               
+                if (string_param_text != "") string_params = llCSV2List(string_param_text);
+            }
+            
+            // // TRANSLATE STRING // //
+            
+            // This string will store the translation
+            string trans = "";
+            // Do nothing if the string name is empty
+            if (string_name != "") {
+                // If there are no string parameters, then it is only a basic translation
+                if (llGetListLength(string_params) == 0) {
+                    // Get the basic translation
+                    trans = sloodle_get_string(string_name);
+                } else {
+                    // Construct the formatted string
+                    trans = sloodle_get_string_f(string_name, string_params);
+                }
+            }
+            
+            // // OUTPUT STRING // //
+            
+            // Check what output method has been requested
+            if (output_method == SLOODLE_TRANSLATE_LINK) {
+                // Return the string via link message
+                sloodle_translation_response(sender_num, string_name, trans);
+                
+            } else if (output_method == SLOODLE_TRANSLATE_SAY) {
+                // Say the string
+                if (num_output_params > 0) llSay(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to say string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_WHISPER) {
+                // Whisper the string
+                if (num_output_params > 0) llWhisper(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to whisper string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_SHOUT) {
+                // Shout the string
+                if (num_output_params > 0) llShout(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to shout string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_REGION_SAY) {
+                // RegionSay the string
+                if (num_output_params > 0) llRegionSay(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to region-say string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_OWNER_SAY) {
+                // Ownersay the string
+                llOwnerSay(trans);
+                
+            } else if (output_method == SLOODLE_TRANSLATE_DIALOG) {
+                // Display a dialog - we need a valid key
+             
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to show dialog with string \"" + string_name + "\".");
+                    return;
+                }
+                        //llOwnerSay("message: "+str+" id: "+(string)id+ " trans: "+trans+" buttons: "+" chanel: "); 
+                // We need at least 2 additional output parameters (channel, and at least 1 button)
+                if (num_output_params >= 2) {
+                    // Extract the channel number
+                    integer channel = llList2Integer(output_params, 0);
+                    // Extract up to 12 button values
+                    list buttons = llList2List(output_params, 1, 12);
+              
+                    // Display the dialog
+                    llDialog(id, trans, buttons, channel);
+                    
+                } else sloodle_debug("ERROR: Insufficient output parameters to show dialog with string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL) {
+                // Display a URL - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
+                    return;
+                }                
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 1) llLoadURL(id, trans, llList2String(output_params, 0));
+                else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL_PARALLEL) {
+                // Display a URL - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
+                    return;
+                }
+                
+                // NOTE: currently the parallel URL loaders will drop any text.
+                // TODO: make parallel URL loaders use text as well.
+                
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 1) llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_LOAD_URL, llList2String(output_params, 0), id);
+                else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_HOVER_TEXT) {
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 2) llSetText(trans, (vector)llList2String(output_params, 0), (float)llList2String(output_params, 1));
+                else sloodle_debug("ERROR: Insufficient output parameters to show hover text with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_IM) {
+                // Send an IM - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to send IM with string \"" + string_name + "\".");
+                    return;
+                }                
+                // Send the IM
+                llInstantMessage(id, trans);
+
+            } else {
+                // Don't know the output method
+                sloodle_debug("ERROR: unrecognised output method \"" + output_method + "\".");
+            }
+        }
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/distributor-1.0/objects/default/assets/lang/en/sloodle_translation_distributor_en.lslp 

BIN
iar/assets/04cce2f4-785a-4855-8ba3-1e370c1c2c2d_texture.jp2


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
iar/assets/04ddcf72-b9de-474a-950e-8cf77ed58443_object.xml


+ 89 - 0
iar/assets/052c2183-f8a7-967b-13af-353bfd112421_script.lsl

@@ -0,0 +1,89 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+//////////
+// SLODLE Quiz Chair Poseball (www.sloodle.org)
+// For SLOODLE 0.4
+//
+// Note: designed for the "myCourse Quiz Chair" design, supplied by Solent University
+//
+// Copyright (c) 2009 SLOODLE Project (various contributors)
+//
+// Released under the GNU GPL v3.
+//////////
+
+
+// Name of the animation to use
+string anim = "sit";
+// Stores the key of the avatar who's sitting on us
+key sitter = NULL_KEY;
+
+
+// Start the poseball animation
+startPoseballAnimation()
+{
+    if (anim != "sit") {
+        llStopAnimation("sit"); // Stop the regular sit animation first
+        llStartAnimation(anim);
+    }
+}
+
+// Stop the poseball animation
+stopPoseballAnimation()
+{
+    if (anim != "sit") {
+        llStopAnimation(anim);
+    }
+}
+
+// Checks if we have animation permissions for the current sitter.
+integer gotAnimationPermissions()
+{
+    if (sitter == NULL_KEY) return FALSE;
+    if ((llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) && (llGetPermissionsKey() == sitter)) return TRUE;
+    return FALSE;
+}
+
+
+default
+{
+    state_entry()
+    {
+        // Set our sit target
+        llSitTarget(<0.25, 0.0, 0.4>, ZERO_ROTATION);
+    }
+    
+    on_rez(integer par)
+    {
+        llResetScript();
+    }
+    
+    changed(integer change)
+    {
+        // Has it been a link change?
+        if (change & CHANGED_LINK) {
+            // Is there an avatar sitting on us?
+            key av = llAvatarOnSitTarget();
+            if (av == NULL_KEY) {
+                // Stop the animation
+                if (gotAnimationPermissions()) stopPoseballAnimation();
+                sitter = NULL_KEY;
+                
+            } else if (av != sitter) {
+                // Make sure we have animation permission
+                sitter = av;
+                if (gotAnimationPermissions()) startPoseballAnimation();
+                else llRequestPermissions(sitter, PERMISSION_TRIGGER_ANIMATION);    
+            }
+        }
+        
+    }
+    
+    run_time_permissions(integer perm)
+    {
+        // Permissions have been granted - start the animation
+        if (perm & PERMISSION_TRIGGER_ANIMATION) startPoseballAnimation();
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/quiz-1.0/objects/default/assets/sloodle_quiz_chair_poseball.lslp 

+ 339 - 0
iar/assets/05b3af22-0fe6-7bad-0a45-00f8b21eebae_script.lsl

@@ -0,0 +1,339 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Translation strings for the Sloodle Quiz object(s).
+//
+// The "locstrings" list is pairs of strings.
+// The first of each pair is the name, and second is the translation.
+//
+// This script is part of the Sloodle project.
+// Copyright (c) 2008 Sloodle (various contributors)
+// Released under the GNU GPL v3
+//
+// Contributors:
+//  Peter R. Bloomfield
+//
+
+// Note: where a translation string contains {{x}} (where x is a number),
+//  it means that a parameter can be inserted. Please make sure to include these
+//  parameters in the appropriate location in your translation.
+// It may be sensible to add comments after your string to indicate what its parameters mean.
+// NOTE: parameter numbering starts at 0 (unlike previous versions, which started at 1).
+
+// Translations can be requested by sending a link message on the SLOODLE_CHANNEL_TRANSLATION_REQUEST channel.
+// It is advisable simply to use the "sloodle_translation_request" function provided in this script.
+
+
+///// TRANSLATION /////
+
+// Localization batch - indicates the purpose of this file
+string mybatch = "quiz";
+
+
+// List of string names and translation pairs.
+// The name is the first of each pair, and should not be translated.
+// The second of each pair is the translation.
+// Additional comments are sometimes given afterward to aid translations.
+list locstrings = [
+    "invalidchoice", "Sorry {{0}}. Your selection was not in the list of available choices. Please try again.", // Parameter: avatar name
+    "invalidtype", "Error: this object cannot handle quiz questions of type: {{0}}", // Parameter: question type name
+    "complete", "Quiz complete {{0}}. Your final score was {{1}}.", // Parameters: avatar name, score
+    "complete:noscore", "Quiz complete.",
+    "repeating", "Repeating...",
+    "starting", "Starting quiz for {{0}}", // Parameter: avatar name
+    "noquestions", "ERROR: there are no questions available",
+    "noattemptsleft", "Sorry {{0}}. You are not allowed to attempt this quiz again.", // Parameter: avatar name
+    "fetchingquiz", "Fetching quiz data...",
+    "ready", "Ready to attempt: {{0}}.", // Parameter: name of quiz
+    "correct", "Correct {{0}}.", // Parameter: name of avatar
+    "incorrect", "Incorrect {{0}}.", // Parameter: name of avatar
+    
+    "pileonmenu:start", "Start a quiz?\n\n{{0}} = Start\n{{1}} = Cancel", // Parameters: button labels
+    "pileonmenu:next", "Quiz Options\n\n{{0}} = Next\n{{1}} = End Quiz\n{{2}} = Cancel", // Parameters: button labels
+    "pileonmenu:answer", "Quiz Options\n\n{{0}} = Answer\n{{1}} = End Quiz\n{{2}} = Cancel" // Parameters: button labels
+];
+
+///// ----------- /////
+
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";                     // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";                       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";                   // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";          // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";            // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";                 // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";              // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_LOAD_URL_PARALLEL = "loadurlpar";  // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";          // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";             // Recipient avatar should be identified in link message keyval. No output parameters.
+
+
+// Used for sending parallel URL loading messages
+integer SLOODLE_CHANNEL_OBJECT_LOAD_URL = -1639270041;
+
+///// FUNCTIONS /////
+
+
+// Send a translation request link message
+// (Here for reference only)
+// Parameter: output_method = should identify an output method, as given by the "SLOODLE_TRANSLATE_..." constants above
+// Parameter: output_params = a list of parameters which controls the output, such as chat channel or buttons for a dialog
+// Parameter: string_name = the name of the localization string to output
+// Parameter: string_params = a list of parameters which will be included in the translated string (or an empty list if none)
+// Parameter: keyval = a key to send in the link message
+// Parameter: batch = the name of the localization batch which should handle this request
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+// Send a translation response link message
+sloodle_translation_response(integer target, string name, string translation)
+{
+    llMessageLinked(target, SLOODLE_CHANNEL_TRANSLATION_RESPONSE, name + "|" + translation + "|" + mybatch, NULL_KEY);
+}
+
+// Get the translation of a particular string
+string sloodle_get_string(string name)
+{
+    // Attempt to find the string name
+    integer numstrings = llGetListLength(locstrings);
+    integer pos = llListFindList(locstrings, [name]);
+    
+    // IMPORTANT: we must be careful not to match a translations instead of a name.
+    // If this was an even number, then we have a string name.
+    if ((pos % 2) == 0) {
+        // Make sure there is a subsequent translation in the list
+        if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
+        // The translation is not there
+        pos = -1;
+    }
+    
+    // If we could not find the string, then return a placeholder
+    if (pos < 0) return "[[" + name + "]]";
+    
+    // If we got here, then we matched a translation instead of a string name.
+    // As such, we need to resort to searching through the list manually (which can be very slow).
+    // To saved time, we can start from the position just beyond where we got to.
+    // We advance by 2 each time to skip the translations completely.
+    pos += 1;
+    for (; pos < numstrings; pos += 2) {
+        // Do we have a match?
+        if (llList2String(locstrings, pos) == name) {
+            // Yes - make sure there is a translation following it
+            if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
+            // The translation is not there - skip the rest of the search
+            pos = numstrings;
+        }
+    }
+    
+    // If we reached this point, then the string is not available. Return a placeholder.
+    return "[[" + name + "]]";
+}
+
+// Send a debug link message
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+
+// Get a formatted translation of a string
+string sloodle_get_string_f(string name, list params)
+{
+    // Get the string itself
+    string str = sloodle_get_string(name);
+    // How many parameters do we have?
+    integer numparams = llGetListLength(params);
+    
+    // Go through each parameter we have been provided
+    integer curparamnum = 0;
+    string curparamtok = "{{x}}";
+    integer curparamtoklength = 0;
+    string curparamstr = "";
+    integer tokpos = -1;
+    for (; curparamnum < numparams; curparamnum++) {
+        // Construct this parameter token
+        curparamtok = "{{" + (string)(curparamnum) + "}}";
+        curparamtoklength = llStringLength(curparamtok);
+        // Fetch the parameter text
+        curparamstr = llList2String(params, curparamnum);
+        
+        // Ensure the parameter text does NOT contain double braces (this avoids an infinite loop!)
+        if (llSubStringIndex(curparamstr, "{{") < 0 && llSubStringIndex(curparamstr, "}}") < 0) {            
+            // Go through every instance of this parameter's token
+            while ((tokpos = llSubStringIndex(str, curparamtok)) >= 0) {
+                // Replace the token with the parameter string
+                str = llDeleteSubString(str, tokpos, tokpos + curparamtoklength - 1);
+                str = llInsertString(str, tokpos, curparamstr);
+            }
+        }
+    }
+    
+    return str;
+}
+
+
+///// STATES /////
+
+default
+{
+    state_entry()
+    {
+    }
+    
+    link_message(integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_TRANSLATION_REQUEST) {            
+            
+            // // PROCESS REQUEST // //
+        
+            // Split the incoming message into fields
+            list fields = llParseStringKeepNulls(str, ["|"], []);
+            integer numfields = llGetListLength(fields);
+            
+            // Extract and check the localization batch
+            string batch = "";
+            if (numfields > 4) batch = llList2String(fields, 4);
+            if (batch != mybatch) return;
+            
+            // We expect at least 3 fields
+            // ... or 4 if there are insertion parameters...
+            // ... anybody up for a 6th parameter? :)
+            if (numfields < 3) {
+                sloodle_debug("ERROR: Insufficient fields for translation of string.");
+                return;
+            }
+            
+            // Extract the key parts of the request
+            string output_method = llList2String(fields, 0);
+            list output_params = llCSV2List(llList2String(fields, 1));
+            integer num_output_params = llGetListLength(output_params);
+            string string_name = llList2String(fields, 2);
+            list string_params = [];
+            if (numfields > 3) {
+                // Extract the string parameters (extra text added to the output)
+                string string_param_text = llList2String(fields, 3);
+                if (string_param_text != "") string_params = llCSV2List(string_param_text);
+            }
+            
+            // // TRANSLATE STRING // //
+            
+            // This string will store the translation
+            string trans = "";
+            // Do nothing if the string name is empty
+            if (string_name != "") {
+                // If there are no string parameters, then it is only a basic translation
+                if (llGetListLength(string_params) == 0) {
+                    // Get the basic translation
+                    trans = sloodle_get_string(string_name);
+                } else {
+                    // Construct the formatted string
+                    trans = sloodle_get_string_f(string_name, string_params);
+                }
+            }
+            
+            // // OUTPUT STRING // //
+            
+            // Check what output method has been requested
+            if (output_method == SLOODLE_TRANSLATE_LINK) {
+                // Return the string via link message
+                sloodle_translation_response(sender_num, string_name, trans);
+                
+            } else if (output_method == SLOODLE_TRANSLATE_SAY) {
+                // Say the string
+                if (num_output_params > 0) llSay(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to say string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_WHISPER) {
+                // Whisper the string
+                if (num_output_params > 0) llWhisper(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to whisper string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_SHOUT) {
+                // Shout the string
+                if (num_output_params > 0) llShout(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to shout string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_REGION_SAY) {
+                // RegionSay the string
+                if (num_output_params > 0) llRegionSay(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to region-say string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_OWNER_SAY) {
+                // Ownersay the string
+                llOwnerSay(trans);
+                
+            } else if (output_method == SLOODLE_TRANSLATE_DIALOG) {
+                // Display a dialog - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to show dialog with string \"" + string_name + "\".");
+                    return;
+                }
+                // We need at least 2 additional output parameters (channel, and at least 1 button)
+                if (num_output_params >= 2) {
+                    // Extract the channel number
+                    integer channel = llList2Integer(output_params, 0);
+                    // Extract up to 12 button values
+                    list buttons = llList2List(output_params, 1, 12);
+                    
+                    // Display the dialog
+                    llDialog(id, trans, buttons, channel);
+                    
+                } else sloodle_debug("ERROR: Insufficient output parameters to show dialog with string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL) {
+                // Display a URL - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
+                    return;
+                }                
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 1) llLoadURL(id, trans, llList2String(output_params, 0));
+                else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL_PARALLEL) {
+                // Display a URL - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
+                    return;
+                }
+                
+                // NOTE: currently the parallel URL loaders will drop any text.
+                // TODO: make parallel URL loaders use text as well.
+                
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 1) llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_LOAD_URL, llList2String(output_params, 0), id);
+                else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_HOVER_TEXT) {
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 2) llSetText(trans, (vector)llList2String(output_params, 0), (float)llList2String(output_params, 1));
+                else sloodle_debug("ERROR: Insufficient output parameters to show hover text with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_IM) {
+                // Send an IM - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to send IM with string \"" + string_name + "\".");
+                    return;
+                }                
+                // Send the IM
+                llInstantMessage(id, trans);
+
+            } else {
+                // Don't know the output method
+                sloodle_debug("ERROR: unrecognised output method \"" + output_method + "\".");
+            }
+        }
+    }
+}
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/quiz_pile_on-1.0/objects/default/assets/lang/en/sloodle_translation_quiz_pile_on_en.lslp

BIN
iar/assets/0621d24e-7dda-46ad-a9f5-43bc016b2599_texture.jp2


BIN
iar/assets/0648e879-ede7-43d1-9f65-389fe88a49a1_texture.jp2


BIN
iar/assets/06e4c064-c447-4d98-8fdc-4093abf909da_texture.jp2


BIN
iar/assets/07ea778e-d96c-4964-a6cc-9ef77694d764_sound.ogg


BIN
iar/assets/0a68cb4e-4993-4e76-8430-f0b5acc3a0eb_texture.jp2


BIN
iar/assets/0cd006d4-4717-4c3c-b218-5924ea5f0f2f_texture.jp2


BIN
iar/assets/0d55946d-e8f8-464f-8a2f-95b2ac2c1b55_texture.jp2


+ 478 - 0
iar/assets/0e5abbde-22d1-9a7d-d67f-c570629ab371_script.lsl

@@ -0,0 +1,478 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle Presenter (for Sloodle 0.4.1)
+// Lets the educator display a presentation of images. videos and webpages hosted on the web.
+// Part of the Sloodle project (www.sloodle.org)
+//
+// Copyright (c) 2008-9 Sloodle project contributors
+// Released under the GNU GPL
+//
+// Contributors:
+//  Peter R. Bloomfield
+//  Paul G. Preibisch (Fire Centaur)
+//  
+integer SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST=-1828374651; // this channel is used to send status codes for translation to the error_messages lsl script
+integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;
+string SLOODLE_PRESENTER_LINKER = "/mod/sloodle/mod/presenter-2.0/linker.php";
+string SLOODLE_EOF = "sloodleeof";
+list parcelInfo = []; //var for parcel owner 
+integer MENU_CHANNEL = -1;
+string SLOODLE_OBJECT_TYPE = "presenter-2.0";
+integer reset;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC = 0;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_OWNER = 1;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_GROUP = 2;
+
+string sloodleserverroot = "";
+string sloodlepwd = "";
+integer sloodlecontrollerid = 0;
+integer sloodlemoduleid = 0;
+integer sloodleobjectaccesslevelctrl = 1; // Who can control this object?
+
+
+string PRESENTER_TEXTURE= "sloodle_presenter_texture";
+integer isconfigured = FALSE; // Do we have all the configuration data we need?
+integer eof = FALSE; // Have we reached the end of the configuration data?
+
+key httploadpresentation = NULL_KEY; // Request for presentation data
+
+string presentername = ""; // The name of the Presenter
+integer numslides = 0; // Total number of slides in the presentation
+integer curslidenum = 0; // Number of the current slide in the presentation (starting from 1)
+string curslidetype = ""; // Mimetype of the current slide
+string curslidesource = ""; // Source of the current slide media (usually a URL)
+string curslidename = ""; // Name of the current slide
+
+// requestConfigData = 0 this is set to 1 after the presenter has been deeded - afterwhich if "update" is 
+//  selected, the presenter will go back into the default state and re-request config data.  This is necessary since the teacher may change prentations the presenter is pointing to via the web.  
+integer requestConfigData = 0;
+
+key myOwnerKey; // The key of the agent who initially rezzed this object -- useful for remembering permission after group deeding.
+
+
+///// TRANSLATION /////
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";             // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";           // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";  // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";    // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";         // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";      // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";  // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";     // Recipient avatar should be identified in link message keyval. No output parameters.
+string SLOODLE_TRANSLATE_HOVER_TEXT_BASIC = "hovertextbasic";
+
+
+// Send a translation request link message
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+// Request the translation of a standard SLOODLE error code
+sloodle_error_code(string method, key avuuid,integer statuscode)
+{
+    llMessageLinked(LINK_SET, SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST, method+"|"+(string)avuuid+"|"+(string)statuscode, NULL_KEY);
+}
+
+///// ----------- /////
+
+
+///// FUNCTIONS /////
+
+// Just returns a random integer - used for setting channels
+integer random_integer( integer min, integer max )
+{
+    return min + (integer)( llFrand( max - min + 1 ) );
+}
+
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+// Configure by receiving a linked message from another script in the object
+// Returns TRUE if the object has all the data it needs
+integer sloodle_handle_command(string str) 
+{
+    list bits = llParseString2List(str,["|"],[]);
+    integer numbits = llGetListLength(bits);
+    string name = llList2String(bits,0);
+    string value1 = "";
+    string value2 = "";
+    
+    if (numbits > 1) value1 = llList2String(bits,1);
+    if (numbits > 2) value2 = llList2String(bits,2);
+    
+    if (name == "set:sloodleserverroot") sloodleserverroot = value1;
+    else if (name == "set:sloodlepwd") {
+        // The password may be a single prim password, or a UUID and a password
+        if (value2 != "") sloodlepwd = value1 + "|" + value2;
+        else sloodlepwd = value1;
+        
+    } else if (name == "set:sloodlecontrollerid") sloodlecontrollerid = (integer)value1;
+    else if (name == "set:sloodlemoduleid") sloodlemoduleid = (integer)value1;
+    else if (name == "set:sloodleobjectaccesslevelctrl") sloodleobjectaccesslevelctrl = (integer)value1;
+    else if (name == SLOODLE_EOF) eof = TRUE;
+    
+    return (sloodleserverroot != "" && sloodlepwd != "" && sloodlecontrollerid > 0 && sloodlemoduleid > 0);
+}
+
+// Checks if the given agent is permitted to control this object
+// Returns TRUE if so, or FALSE if not
+integer sloodle_check_access_ctrl(key id)
+{
+    // Check the access mode
+    if (sloodleobjectaccesslevelctrl == SLOODLE_OBJECT_ACCESS_LEVEL_GROUP) {
+        return llSameGroup(id);
+    } else if (sloodleobjectaccesslevelctrl == SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC) {
+        return TRUE;
+    }
+    
+    // Assume it's owner mode
+    return (id == llGetOwner());
+}
+
+// Update the image display (e.g. change the media URL).
+// Does nothing if the data we currently have isn't valid
+update_image_display()
+{
+        
+    // Make sure an error didn't occur with the slide plugin
+    if (curslidetype == "ERROR") return;
+    // Make sure we have a valid slide number and valid data
+    if (curslidenum < 1 || curslidenum > numslides) return;
+    if (curslidetype == "" || curslidesource == "") return;
+   // llOwnerSay(curslidetype);
+    string showurl;
+    if (curslidetype == "image/*") {
+        // Wrap in an HTML page to force the scaling to happen right.
+        showurl = "data:text/html," + "<html><body><img width=\"1000\" height=\"1000\" src=\""+curslidesource+"\"></body></html>";
+    } else {
+        showurl = curslidesource;
+    }
+
+    llSetPrimMediaParams( 2, [ PRIM_MEDIA_CONTROLS, PRIM_MEDIA_CONTROLS_MINI, PRIM_MEDIA_CURRENT_URL, showurl, PRIM_MEDIA_AUTO_PLAY, 1, PRIM_MEDIA_AUTO_SCALE, 1, PRIM_MEDIA_PERMS_INTERACT, PRIM_MEDIA_PERM_NONE, PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE ] );
+    vector size = llGetScale();
+    
+    doAlign((integer)size.x,(integer)size.y,(integer)size.x);
+}
+
+// Request the specified slide
+request_slide(integer num)
+{
+    // Indicate that we are requesting a slide
+    sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<1.29037, 1.42417, 0.00000>, 0.9], "loadingslide", [num], NULL_KEY, "presenter");
+
+    // Construct and send our HTTP request for data
+    string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+    body += "&sloodlepwd=" + sloodlepwd;
+    body += "&sloodlemoduleid=" + (string)sloodlemoduleid;
+    body += "&sloodleslidenum=" + (string)num;
+    
+    httploadpresentation = llHTTPRequest(sloodleserverroot + SLOODLE_PRESENTER_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+    llSetTimerEvent(8.0);
+}
+
+doAlign(integer w, integer h, integer face)
+{
+    // compute scale factors based on next bigger power of 2
+    integer div;
+    div = 2;
+    while (div < w) div*=2;    
+    float scale_s = (float)w / div;
+    div = 2;
+    while (div < h) div*=2;
+    float scale_t = (float)h / div;
+ 
+    // compute offset from scale
+    float offset_u = -(1.0 - scale_s) / 2.0;
+    float offset_v = -(1.0 - scale_t) / 2.0;
+ 
+    // do the "Align":   
+    llOffsetTexture(offset_u, offset_v, face);
+    llScaleTexture(scale_s, scale_t, face);
+}
+    
+// Move to the next slide
+next_slide()
+{
+    if (curslidenum < 1 || curslidenum >= numslides) request_slide(1);
+    else request_slide(curslidenum + 1);
+}
+
+// Move to the previous slide
+previous_slide()
+{
+    if (curslidenum <= 1 || curslidenum > numslides) request_slide(numslides);
+    else request_slide(curslidenum - 1);
+}
+
+// Update the hover text to indicate which image is being displayed
+update_hover_text()
+{
+    // Make sure we actually have some slide data
+    if (numslides == 0) {
+        sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.5, 0.0, 0.0>, 1.0], "error:nodata", [], NULL_KEY, "presenter");
+        return;
+    }
+    
+    // Make sure an error didn't occur with the slide plugin
+    if (curslidetype == "ERROR") {
+        sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.5, 0.0, 0.0>, 1.0], "error:pluginnotfound", [presentername, curslidenum, numslides], NULL_KEY, "presenter");
+        return;
+    }
+    sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.0, 1.0, 0.0>, 1.0], "showingslidename", [presentername, curslidenum, numslides, curslidename], NULL_KEY, "presenter");
+    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "showingentryurl", [curslidenum, numslides, curslidesource], NULL_KEY, "presenter");
+}
+
+
+///// STATES /////
+
+
+// Default state - waiting for configuration
+// Default state - waiting for configuration
+default{
+ on_rez(integer start_param) {    
+        myOwnerKey = llGetOwner();            
+    }
+ state_entry() {
+         myOwnerKey = llGetOwner();
+        // llOwnerSay("Owner set to: " + llKey2Name(llGetOwner())+ " with UUID: " + (string)llGetOwner());
+         reset=FALSE; //used in the last state - if someone deletes the sloodle_presenter_texture, we set a timer, so need to distinguish in timer event, what to do - ie: was the timer set because the texture was deleted? then set reset to TRUE. 
+         state initialize; 
+         
+ }
+
+}
+
+state initialize
+{
+
+    on_rez(integer start_param) {  
+       // llOwnerSay("Reseting...");  
+        myOwnerKey = llGetOwner();
+        llResetScript();
+                  
+    }
+    
+    state_entry()
+    {
+        llClearPrimMedia(2);    
+           if ((string)llGetInventoryKey("sloodle_config")!="00000000-0000-0000-0000-000000000000")
+              sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT_BASIC, [<0.00000,1, 0>, 1.0], "touchforwebconfig", [], NULL_KEY, "presenter");
+        // Starting again with a new configuration
+        llSetText("", <0.0,0.0,0.0>, 0.0);
+        isconfigured = FALSE;
+        eof = FALSE;
+        // Reset our data
+        sloodleserverroot = "";
+        sloodlepwd = "";
+        sloodlecontrollerid = 0;
+        sloodlemoduleid = 0;
+        sloodleobjectaccesslevelctrl = 0;
+        if (requestConfigData==1){
+         llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:requestconfig", NULL_KEY);                 
+        }
+        requestConfigData=1;
+    }
+    
+    link_message( integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Split the message into lines
+            list lines = llParseString2List(str, ["\n"], []);
+            integer numlines = llGetListLength(lines);
+            integer i;
+            for (i = 0; i < numlines; i++) {
+                isconfigured = sloodle_handle_command(llList2String(lines, i));
+            }
+            
+            // If we've got all our data AND reached the end of the configuration data, then move on
+            if (eof == TRUE) {
+                if (isconfigured == TRUE) {
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configurationreceived", [], NULL_KEY, "");
+                    state running;
+                } else {
+                    // Go all configuration but, it's not complete... request reconfiguration
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configdatamissing", [], NULL_KEY, "");
+                    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:reconfigure", NULL_KEY);
+                    eof = FALSE;
+                }
+            }
+        }
+    }
+    
+    touch_start(integer num_detected)
+    {
+        // Attempt to request a reconfiguration
+        //if (llDetectedKey(0) == llGetOwner()) {
+            llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:requestconfig", NULL_KEY);
+        //}
+    }
+}
+
+state running
+{
+    state_entry()
+    {
+        // Request the first slide
+        request_slide(1);
+    }
+    
+    state_exit()
+    {
+        llSetText("", <0.0, 0.0, 0.0>, 0.0);
+        llSetTimerEvent(0.0);
+    }
+    
+    touch_start(integer num)
+    {
+        // Find out what was touched
+        string buttonname = llGetLinkName(llDetectedLinkNumber(0));
+        if (buttonname == "next") {
+            next_slide();
+        } else if (buttonname == "previous") {
+            previous_slide();
+        } else if (buttonname == "reset") {
+            request_slide(1);
+        } else if (buttonname == "update") {
+            requestConfigData=1; // in default data state request config data to ensure
+            //controller settings proliferate into SL - ie: someone changed the presentation this presenter is pointing to via the             requestConfigData=1; // in default data state request config data to ensure
+            //controller settings proliferate into SL - ie: someone changed the presentation this presenter is pointing to via the web
+            state default;
+        }
+    }
+    
+    on_rez(integer par) { llResetScript(); }
+    
+    timer()
+    {
+        
+        llSetTimerEvent(0.0);
+        if (reset == TRUE){
+            reset = FALSE;
+            llResetScript();
+        } else {
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "httptimeout", [], NULL_KEY, "");
+            update_hover_text();
+            update_image_display();
+        }
+    }
+    
+    http_response(key id, integer status, list meta, string body)
+    {
+        // Is this the expected data?
+        if (id != httploadpresentation) {
+            return;
+        }
+        httploadpresentation = NULL_KEY;
+        llSetTimerEvent(0.0);
+        
+        // Make sure the request worked
+        if (status != 200) {
+            sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,status); //send message to error_message.lsl
+            return;
+        }
+
+        // Make sure there is a body to the request
+        if (body == "") {
+            sloodle_debug("Body of HTTP response was empty.");
+            return;
+        }
+        
+        // Split the data up into lines
+        list lines = llParseStringKeepNulls(body, ["\n"], []);  
+        integer numlines = llGetListLength(lines);
+        if (numlines < 2) {
+            sloodle_debug("HTTP response contained only 1 line - expected at least 2 for a correctly formatted response.");
+            return;
+        }
+        // Extract all the status fields
+        list statusfields = llParseStringKeepNulls( llList2String(lines,0), ["|"], [] );
+        // Get the statuscode
+        integer statuscode = llList2Integer(statusfields,0);
+        
+        // Was it an error code?
+        if (statuscode == -131) {
+            sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.0, 1.0, 0.0>, 1.0], "error:noplugins", [], NULL_KEY, "presenter");
+            return;
+            
+        } else if (statuscode == -10501) {
+            sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.0, 1.0, 0.0>, 1.0], "error:noslides", [], NULL_KEY, "presenter");
+            return;
+            
+        } else if (statuscode <= 0) {
+            
+            // Do we have an error message to go with it?
+            if (numlines > 1) {
+                sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "sloodleerror:desc", [statuscode, llList2String(lines, 1)], NULL_KEY, "");
+            } else {
+               // sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "sloodleerror", [statuscode], NULL_KEY, "");
+               sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,statuscode); //send message to error_message.lsl
+            }
+            
+            return;
+        }
+        
+        // The first data line contains two things: the number of slides, and the name of the Presenter
+        list fields = llParseStringKeepNulls(llList2String(lines, 1), ["|"], []);
+        if (llGetListLength(fields) < 2) {
+            sloodle_debug("Expected at least 2 fields on first data line.");
+            return;
+        }
+        numslides = (integer)llList2String(fields, 0);
+        presentername = llList2String(fields, 1);
+        fields = [];
+        
+        // Make sure we have another line, which will be the current slide data.
+        if (numlines < 3) {
+            sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.0, 1.0, 0.0>, 1.0], "error:noslides", [], NULL_KEY, "presenter");
+            return;
+        }
+        
+        // This line should contain at least 4 fields: num | type | source | name.
+        // If the "type" value is "ERROR" then the plugin could not be loaded.
+        fields = llParseStringKeepNulls(llList2String(lines, 2), ["|"], []);
+        if (llGetListLength(fields) < 4) {
+            sloodle_debug("Expected at least 4 fields of slide data in second data line.");
+            return;
+        }
+        curslidenum = (integer)llList2String(fields, 0);
+        curslidetype = llList2String(fields, 1);
+        curslidesource = llList2String(fields, 2);
+        curslidename = llList2String(fields, 3);
+        
+        // Now that we've got all that data, update the display
+        update_hover_text();
+        update_image_display();
+    }
+    
+    changed(integer change) {
+     if (change ==CHANGED_INVENTORY){         
+        if ((string)llGetInventoryKey(PRESENTER_TEXTURE)=="00000000-0000-0000-0000-000000000000"){                 
+                  sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT_BASIC, [<0.92748, 0.00000, 0.42705>, 1.0], "stilldoesntexistininventory", [], NULL_KEY, "presenter"); 
+                  
+            }else{
+                llSetTexture(PRESENTER_TEXTURE,ALL_SIDES);
+                sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT_BASIC, [<0.92748, 0.00000, 0.42705>, 1.0], "foundsloodletexture", [], NULL_KEY, "presenter");
+                reset=TRUE;
+                llSetTimerEvent(3.0);
+                      
+            }
+     }
+    }
+
+}
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/presenter-2.0/objects/default/assets/sloodle_mod_presenter-shared-media-2.0.lslp

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
iar/assets/0ed3aad5-337f-4f2f-84f3-dedd341bcfd6_object.xml


BIN
iar/assets/0f2cccbb-305e-4c7f-b108-ecdc33af9d0c_texture.jp2


+ 35 - 0
iar/assets/0fa2b92f-cdfa-3bd7-8638-f4c78d02ff84_script.lsl

@@ -0,0 +1,35 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+default
+{// zFire Xue Prim Animator Generator 5.1 Fastest Web Version.
+// Script belongs to Fire Centaur
+// This script goes into prim named: CONNECT HUD
+on_rez(integer r){llResetScript();} 
+link_message(integer s, integer n, string m, key id)
+{integer stat=llGetStatus(1);
+
+if(m=="p12"){ //zF Animation Frame #12
+vector r=<0.32424,0.06091,0.19606>;
+llSetScale(r);
+vector Zfire=llGetScale();
+vector zFire=<0.34291,-0.12018,1.33655>;
+vector zfIre=<0.32424,0.06091,0.19606>;
+vector zfiRe=< zFire.x/zfIre.x,zFire.y/zfIre.y,zFire.z/zfIre.z>;
+vector zfirE=< Zfire.x*zfiRe.x,Zfire.y*zfiRe.y,Zfire.z*zfiRe.z>;
+llSetPrimitiveParams([6, zfirE,8, <0.0,0.0,-0.00223,1.0> / llGetRootRotation(),9,0,0,<0.0, 1.0, 0.0>,0.0,<0.0, 0.0, 0.0>,<1.0, 1.0, 0.0>,<0.0, 0.0, 0.0>,18,0,<0.239216, 0.239216, 0.239216>,1.000000,18,1,<1.0, 1.0, 1.0>,1.000000,18,2,<0.239216, 0.239216, 0.239216>,1.000000,18,3,<0.239216, 0.239216, 0.239216>,1.000000,18,4,<0.239216, 0.239216, 0.239216>,1.000000,18,5,<0.239216, 0.239216, 0.239216>,1.000000,25,0,0.0,25,1,0.0,25,2,0.0,25,3,0.0,25,4,0.0,25,5,0.0]); }
+
+if(m=="p13"){ //zF Animation Frame #13
+vector r=<0.32424,0.06091,0.19606>;
+llSetScale(r);
+vector Zfire=llGetScale();
+vector zFire=<0.34291,-0.04047,1.33655>;
+vector zfIre=<0.32424,0.06091,0.19606>;
+vector zfiRe=< zFire.x/zfIre.x,zFire.y/zfIre.y,zFire.z/zfIre.z>;
+vector zfirE=< Zfire.x*zfiRe.x,Zfire.y*zfiRe.y,Zfire.z*zfiRe.z>;
+llSetPrimitiveParams([6, zfirE,8, <0.0,0.0,-0.00223,1.0> / llGetRootRotation(),9,0,0,<0.0, 1.0, 0.0>,0.0,<0.0, 0.0, 0.0>,<1.0, 1.0, 0.0>,<0.0, 0.0, 0.0>,18,0,<0.239216, 0.239216, 0.239216>,1.000000,18,1,<1.0, 1.0, 1.0>,1.000000,18,2,<0.239216, 0.239216, 0.239216>,1.000000,18,3,<0.239216, 0.239216, 0.239216>,1.000000,18,4,<0.239216, 0.239216, 0.239216>,1.000000,18,5,<0.239216, 0.239216, 0.239216>,1.000000,25,0,0.0,25,1,0.0,25,2,0.0,25,3,0.0,25,4,0.0,25,5,0.0]); }
+
+if(stat){llSetStatus(1,1);}}}
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/scoreboard-1.0/objects/default/assets/sloodle_connect_button_anim.lslp 

+ 331 - 0
iar/assets/0fca899b-5276-f63e-ea5c-41e3e8477ad2_script.lsl

@@ -0,0 +1,331 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Standard translation script for Sloodle.
+// Contains the common, re-usable words and phrases.
+//
+// The "locstrings" list is pairs of strings.
+// The first of each pair is the name, and second is the translation.
+//
+// This script is part of the Sloodle project.
+// Copyright (c) 2008 Sloodle (various contributors)
+// Released under the GNU GPL v3
+//
+// Contributors:
+//  Peter R. Bloomfield
+//
+
+// Note: where a translation string contains {{x}} (where x is a number),
+//  it means that a parameter can be inserted. Please make sure to include these
+//  parameters in the appropriate location in your translation.
+// It may be sensible to add comments after your string to indicate what its parameters mean.
+// NOTE: parameter numbering starts at 0 (unlike previous versions, which started at 1).
+
+// Translations can be requested by sending a link message on the SLOODLE_CHANNEL_TRANSLATION_REQUEST channel.
+// It is advisable simply to use the "sloodle_translation_request" function provided in this script.
+
+
+///// TRANSLATION /////
+
+// Localization batch - indicates the purpose of this file
+string mybatch = "pwreset";
+
+
+// List of string names and translation pairs.
+// The name is the first of each pair, and should not be translated.
+// The second of each pair is the translation.
+// Additional comments are sometimes given afterward to aid translations.
+list locstrings = [
+	//  Password reset
+	"pwresetready:site", "Password Reset\nSite: {{0}}", // Parameter gives address of site
+	"pwresetready:course", "Password Reset\nSite: {{0}}\nCourse: {{1}}", // Address of site and name of course
+	"pwresetready:staff", "Password Reset\nSite: {{0}}\nCourse: {{1}}\nSTAFF ONLY", // Address of site and name of course
+	"pwreseterror:hasemail", "Sorry {{0}}. There is an email address associated with your Moodle account at {{1}}. Please use Moodle to reset your password.", // Parameter 0 should be an avatar name, and 1 should be a site address.
+	"pwreseterror:failed:code", "Sorry {{0}}. Error {{1}} occured while trying to reset your password.", // Parameters: avatar name and error code
+	"pwreset:success", "Thank you {{0}}. Your password has been successfully reset.\nSite: {{1}} \nUsername: {{2}} \nPassword: {{3}}" // Parameters: avatar name, site address, username, password
+];
+
+///// ----------- /////
+
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";                     // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";                       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";                   // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";          // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";            // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";                 // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";              // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_LOAD_URL_PARALLEL = "loadurlpar";  // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";          // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";             // Recipient avatar should be identified in link message keyval. No output parameters.
+
+
+// Used for sending parallel URL loading messages
+integer SLOODLE_CHANNEL_OBJECT_LOAD_URL = -1639270041;
+
+///// FUNCTIONS /////
+
+
+// Send a translation request link message
+// (Here for reference only)
+// Parameter: output_method = should identify an output method, as given by the "SLOODLE_TRANSLATE_..." constants above
+// Parameter: output_params = a list of parameters which controls the output, such as chat channel or buttons for a dialog
+// Parameter: string_name = the name of the localization string to output
+// Parameter: string_params = a list of parameters which will be included in the translated string (or an empty list if none)
+// Parameter: keyval = a key to send in the link message
+// Parameter: batch = the name of the localization batch which should handle this request
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+// Send a translation response link message
+sloodle_translation_response(integer target, string name, string translation)
+{
+    llMessageLinked(target, SLOODLE_CHANNEL_TRANSLATION_RESPONSE, name + "|" + translation + "|" + mybatch, NULL_KEY);
+}
+
+// Get the translation of a particular string
+string sloodle_get_string(string name)
+{
+    // Attempt to find the string name
+    integer numstrings = llGetListLength(locstrings);
+    integer pos = llListFindList(locstrings, [name]);
+    
+    // IMPORTANT: we must be careful not to match a translations instead of a name.
+    // If this was an even number, then we have a string name.
+    if ((pos % 2) == 0) {
+        // Make sure there is a subsequent translation in the list
+        if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
+        // The translation is not there
+        pos = -1;
+    }
+    
+    // If we could not find the string, then return a placeholder
+    if (pos < 0) return "[[" + name + "]]";
+    
+    // If we got here, then we matched a translation instead of a string name.
+    // As such, we need to resort to searching through the list manually (which can be very slow).
+    // To saved time, we can start from the position just beyond where we got to.
+    // We advance by 2 each time to skip the translations completely.
+    // pos += 1; remove pos +=1 mod 23 apr TW
+    for (pos += 1; pos < numstrings; pos += 2) {
+        // Do we have a match?
+        if (llList2String(locstrings, pos) == name) {
+            // Yes - make sure there is a translation following it
+            if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
+            // The translation is not there - skip the rest of the search
+            pos = numstrings;
+        }
+    }
+    
+    // If we reached this point, then the string is not available. Return a placeholder.
+    return "[[" + name + "]]";
+}
+
+// Send a debug link message
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+
+// Get a formatted translation of a string
+string sloodle_get_string_f(string name, list params)
+{
+    // Get the string itself
+    string str = sloodle_get_string(name);
+    // How many parameters do we have?
+    integer numparams = llGetListLength(params);
+    
+    // Go through each parameter we have been provided
+    integer curparamnum;
+    string curparamtok = "{{x}}";
+    integer curparamtoklength = 0;
+    string curparamstr = "";
+    integer tokpos = -1;
+    for (curparamnum = 0; curparamnum < numparams; curparamnum++) {
+        // Construct this parameter token
+        curparamtok = "{{" + (string)(curparamnum) + "}}";
+        curparamtoklength = llStringLength(curparamtok);
+        // Fetch the parameter text
+        curparamstr = llList2String(params, curparamnum);
+        
+        // Ensure the parameter text does NOT contain double braces (this avoids an infinite loop!)
+        if (llSubStringIndex(curparamstr, "{{") < 0 && llSubStringIndex(curparamstr, "}}") < 0) {            
+            // Go through every instance of this parameter's token
+            while ((tokpos = llSubStringIndex(str, curparamtok)) >= 0) {
+                // Replace the token with the parameter string
+                str = llDeleteSubString(str, tokpos, tokpos + curparamtoklength - 1);
+                str = llInsertString(str, tokpos, curparamstr);
+            }
+        }
+    }
+    
+    return str;
+}
+
+
+///// STATES /////
+
+default
+{
+    state_entry()
+    {
+    }
+    
+    link_message(integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_TRANSLATION_REQUEST) {            
+            
+            // // PROCESS REQUEST // //
+        
+            // Split the incoming message into fields
+            list fields = llParseStringKeepNulls(str, ["|"], []);
+            integer numfields = llGetListLength(fields);
+            
+            // Extract and check the localization batch
+            string batch = "";
+            if (numfields > 4) batch = llList2String(fields, 4);
+            if (batch != mybatch) return;
+            
+            // We expect at least 3 fields
+            // ... or 4 if there are insertion parameters...
+            // ... or 5 if there is a language code
+            // ... anybody up for a 6th parameter? :)
+            if (numfields < 3) {
+                sloodle_debug("ERROR: Insufficient fields for translation of string.");
+                return;
+            }
+            
+            // Extract the key parts of the request
+            string output_method = llList2String(fields, 0);
+            list output_params = llCSV2List(llList2String(fields, 1));
+            integer num_output_params = llGetListLength(output_params);
+            string string_name = llList2String(fields, 2);
+            list string_params = [];
+            if (numfields > 3) {
+                // Extract the string parameters (extra text added to the output)
+                string string_param_text = llList2String(fields, 3);
+                if (string_param_text != "") string_params = llCSV2List(string_param_text);
+            }
+            
+            // // TRANSLATE STRING // //
+            
+            // This string will store the translation
+            string trans = "";
+            // Do nothing if the string name is empty
+            if (string_name != "") {
+                // If there are no string parameters, then it is only a basic translation
+                if (llGetListLength(string_params) == 0) {
+                    // Get the basic translation
+                    trans = sloodle_get_string(string_name);
+                } else {
+                    // Construct the formatted string
+                    trans = sloodle_get_string_f(string_name, string_params);
+                }
+            }
+            
+            // // OUTPUT STRING // //
+            
+            // Check what output method has been requested
+            if (output_method == SLOODLE_TRANSLATE_LINK) {
+                // Return the string via link message
+                sloodle_translation_response(sender_num, string_name, trans);
+                
+            } else if (output_method == SLOODLE_TRANSLATE_SAY) {
+                // Say the string
+                if (num_output_params > 0) llSay(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to say string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_WHISPER) {
+                // Whisper the string
+                if (num_output_params > 0) llWhisper(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to whisper string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_SHOUT) {
+                // Shout the string
+                if (num_output_params > 0) llShout(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to shout string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_REGION_SAY) {
+                // RegionSay the string
+                if (num_output_params > 0) llRegionSay(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to region-say string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_OWNER_SAY) {
+                // Ownersay the string
+                llOwnerSay(trans);
+                
+            } else if (output_method == SLOODLE_TRANSLATE_DIALOG) {
+                // Display a dialog - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to show dialog with string \"" + string_name + "\".");
+                    return;
+                }
+                // We need at least 2 additional output parameters (channel, and at least 1 button)
+                if (num_output_params >= 2) {
+                    // Extract the channel number
+                    integer channel = llList2Integer(output_params, 0);
+                    // Extract up to 12 button values
+                    list buttons = llList2List(output_params, 1, 12);
+                    
+                    // Display the dialog
+                    llDialog(id, trans, buttons, channel);
+                    
+                } else sloodle_debug("ERROR: Insufficient output parameters to show dialog with string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL) {
+                // Display a URL - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
+                    return;
+                }                
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 1) llLoadURL(id, trans, llList2String(output_params, 0));
+                else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL_PARALLEL) {
+                // Display a URL - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
+                    return;
+                }
+                
+                // NOTE: currently the parallel URL loaders will drop any text.
+                // TODO: make parallel URL loaders use text as well.
+                
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 1) llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_LOAD_URL, llList2String(output_params, 0), id);
+                else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_HOVER_TEXT) {
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 2) llSetText(trans, (vector)llList2String(output_params, 0), (float)llList2String(output_params, 1));
+                else sloodle_debug("ERROR: Insufficient output parameters to show hover text with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_IM) {
+                // Send an IM - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to send IM with string \"" + string_name + "\".");
+                    return;
+                }                
+                // Send the IM
+                llInstantMessage(id, trans);
+
+            } else {
+                // Don't know the output method
+                sloodle_debug("ERROR: unrecognised output method \"" + output_method + "\".");
+            }
+        }
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/pwreset-1.0/objects/default/assets/lang/en/sloodle_translation_pwreset_en.lslp 

+ 78 - 0
iar/assets/10494eb1-6911-9467-09e7-b7e64c0312fb_script.lsl

@@ -0,0 +1,78 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle Set object simple door script.
+//
+// Part of the Sloodle project (www.sloodle.org).
+// Copyright (c) 2007-8 Sloodle
+// Released under the GNU GPL v3
+//
+// Contributors:
+//  Edmund Edgar
+//  Paul Preibisch
+
+
+integer open=FALSE; 
+integer SLOODLE_CHANNEL_SET_SIMPLE_DOOR_OPEN =-1639270101;
+integer SLOODLE_CHANNEL_SET_SIMPLE_DOOR_CLOSED = -1639270102;
+integer SLOODLE_CHANNEL_OBJECT_DIALOG                   = -3857343;
+
+integer last_touch_ts = 0;
+
+default 
+{  
+    state_entry() 
+    {      
+        llSetLocalRot(llEuler2Rot( <0, 0, 270.00 * DEG_TO_RAD> ));       
+        llTriggerSound("close",1.0);
+        llSleep(2); // Give it a couple of seconds for the texture inside the door to load, before we allow the user to open it. This prevents problems with auto-zoom that occur if you click too early.        
+    }  
+    link_message(integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // What was the message?
+            if (str == "do:reset") llResetScript();
+        }
+    }
+    touch_start(integer total_number)  
+    { 
+        // if(llDetectedKey(0) == llGetOwner()) 
+        integer j=0;
+        for (j=0;j<total_number;j++){
+            if (llDetectedKey(j)!=llGetOwner()){
+                llInstantMessage(llDetectedKey(j),"Sorry, but you must be the owner to open this rezzer");
+                return;
+            }
+        }
+        
+        // If less than three seconds have elapsed since the last touch we handled, ignore it.
+        // This prevents a double-click closing the door as soon as it finishes opening.
+        if (llGetUnixTime() - last_touch_ts < 2) {
+            return;
+        }
+        
+        vector theRot = llRot2Euler(llGetLocalRot());
+        float theRotZ = theRot.z*RAD_TO_DEG;
+        //the reason we are comparing to -80 instead of -90 is because opensim and sl have different precision for rotations, 90 would probably be ok, but lets be safe!
+        if (theRotZ<=-80){ 
+            llSetLocalRot(llEuler2Rot( <0, 0, 45 * DEG_TO_RAD> ));
+            llMessageLinked(LINK_ALL_OTHERS,SLOODLE_CHANNEL_SET_SIMPLE_DOOR_CLOSED,"",NULL_KEY);  
+            llTriggerSound("open",1.0);     
+            llTriggerSound("powerup",1.0); 
+            llMessageLinked(LINK_SET, -99, "turn glow on", NULL_KEY);                       
+        } else { 
+            llMessageLinked(LINK_ALL_OTHERS,SLOODLE_CHANNEL_SET_SIMPLE_DOOR_OPEN,"",NULL_KEY);   
+           // llSetPos( llGetRootPosition() );
+            llTriggerSound("close",1.0);
+            llTriggerSound("powerdown",1.0); 
+            llSetLocalRot(llEuler2Rot( <0, 0, 270 * DEG_TO_RAD> ));   open = TRUE; 
+            llMessageLinked(LINK_SET, -99, "turn glow off", NULL_KEY);          
+        } 
+        last_touch_ts = llGetUnixTime();
+    }
+}
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/set-1.0/objects/default/assets/sloodle_set_simple_door.lslp
+

BIN
iar/assets/10679de3-324f-4a85-ab45-54a409608ade_animation.bvh


BIN
iar/assets/125db676-fc3b-4a52-801b-5c7c2c60826e_texture.jp2


+ 59 - 0
iar/assets/128bdc62-9af8-5b13-06ca-7354d923456d_script.lsl

@@ -0,0 +1,59 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+/*
+*  Part of the Sloodle project (www.sloodle.org)
+*
+*  Copyright (c) 2011-06 contributors (see below)
+*  Released under the GNU GPL v3
+*  -------------------------------------------
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*
+*  All scripts must maintain this copyrite information, including the contributer information listed
+*
+*  Contributors:
+*   Paul Preibisch
+*   Edmund Edgar
+*
+*  DESCRIPTION
+*/
+
+
+string view_url;
+string admin_url;
+string sloodleserverroot = "";
+string paramstr;
+integer SLOODLE_CHANNEL_OPEN_IN_BROWSER= -1639277000;
+
+
+default{
+    on_rez(integer start_param) {
+        llResetScript();
+    }
+touch_start( integer total_number){
+    integer j;
+    for (j=0;j<total_number;j++){
+        if (llDetectedKey(j)!=llGetOwner())return;
+        llMessageLinked(LINK_ALL_OTHERS, SLOODLE_CHANNEL_OPEN_IN_BROWSER, "", llDetectedKey(j));
+    }
+
+
+
+    }
+}
+
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/scoreboard-1.0/objects/default/assets/btn_open_in_browser.lslp

BIN
iar/assets/16cbe30a-f753-4f0e-94e6-5b1b56965950_texture.jp2


+ 321 - 0
iar/assets/16d8d4c4-6427-f346-8b5c-554469d623b6_script.lsl

@@ -0,0 +1,321 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// LoginZone script (for Sloodle 0.3).
+// Allows avatar-Moodle identification by teleporting into pre-defined space in-world.
+//
+// Part of the Sloodle project (www.sloodle.org).
+// Copyright (c) 2007-8 Sloodle
+// Released under the GNU GPL v3
+//
+// Contributors:
+//  Edmund Edgar
+//  Peter R. Bloomfield
+
+
+///// DATA /////
+integer SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST=-1828374651; // this channel is used to send status codes for translation to the error_messages lsl script
+integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;
+integer SLOODLE_CHANNEL_AVATAR_DIALOG = 1001;
+string SLOODLE_LOGINZONE_LINKER = "/mod/sloodle/mod/loginzone-1.0/linker.php";
+string SLOODLE_EOF = "sloodleeof";
+
+string SLOODLE_OBJECT_TYPE = "pwreset-1.0";
+
+string sloodleserverroot = "";
+string sloodlepwd = "";
+integer sloodlecontrollerid = 0;
+string sloodlecoursename_full = "";
+integer sloodlerefreshtime = 0; // How often to automatically update
+
+integer isconfigured = FALSE; // Do we have all the configuration data we need?
+integer eof = FALSE; // Have we reached the end of the configuration data?
+
+key httpupdate = NULL_KEY; // The request for sending an update
+list httpreqs = []; // A list of HTTP requests we're expecting
+
+
+///// TRANSLATION /////
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";             // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";           // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";  // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";    // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";         // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";      // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";  // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";     // Recipient avatar should be identified in link message keyval. No output parameters.
+
+// Send a translation request link message
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+///// ----------- /////
+
+
+///// FUNCTIONS /////
+/******************************************************************************************************************************
+* sloodle_error_code - 
+* Author: Paul Preibisch
+* Description - This function sends a linked message on the SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST channel
+* The error_messages script hears this, translates the status code and sends an instant message to the avuuid
+* Params: method - SLOODLE_TRANSLATE_SAY, SLOODLE_TRANSLATE_IM etc
+* Params:  avuuid - this is the avatar UUID to that an instant message with the translated error code will be sent to
+* Params: status code - the status code of the error as on our wiki: http://slisweb.sjsu.edu/sl/index.php/Sloodle_status_codes
+*******************************************************************************************************************************/
+sloodle_error_code(string method, key avuuid,integer statuscode){
+            llMessageLinked(LINK_SET, SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST, method+"|"+(string)avuuid+"|"+(string)statuscode, NULL_KEY);
+}
+
+// Send debug info
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+
+// Tell Sloodle our position, size and region.
+sloodle_update_server()
+{
+    // Construct the data
+    string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+    body += "&sloodlepwd=" + sloodlepwd;
+    body += "&sloodlepos=" + (string)llGetPos();
+    body += "&sloodlesize=" + (string)llGetScale();
+    body += "&sloodleregion=" + llEscapeURL(llGetRegionName());
+    // Send the request to update the server (we don't care about the response)
+    httpupdate = llHTTPRequest(sloodleserverroot + SLOODLE_LOGINZONE_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+}
+
+// Tell Sloodle about a detected avatar
+sloodle_detected_avatar(key id, vector pos)
+{
+    // Construct the data
+    string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+    body += "&sloodlepwd=" + sloodlepwd;
+    body += "&sloodlepos=" + (string)pos;
+    body += "&sloodleuuid=" + (string)id;
+    body += "&sloodleavname=" + llEscapeURL(llKey2Name(id));
+    // Send the request to update the server (we don't care about the response)
+    key newhttp = llHTTPRequest(sloodleserverroot + SLOODLE_LOGINZONE_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+    if (newhttp != NULL_KEY) httpreqs += [newhttp];
+}
+
+// Configure by receiving a linked message from another script in the object
+// Returns TRUE if the object has all the data it needs
+integer sloodle_handle_command(string str) 
+{
+    list bits = llParseString2List(str,["|"],[]);
+    integer numbits = llGetListLength(bits);
+    string name = llList2String(bits,0);
+    string value1 = "";
+    string value2 = "";
+    
+    if (numbits > 1) value1 = llList2String(bits,1);
+    if (numbits > 2) value2 = llList2String(bits,2);
+    
+    if (name == "set:sloodleserverroot") sloodleserverroot = value1;
+    if (name == "set:sloodlecoursename_full") sloodlecoursename_full = value1;
+    else if (name == "set:sloodlepwd") {
+        // The password may be a single prim password, or a UUID and a password
+        if (value2 != "") sloodlepwd = value1 + "|" + value2;
+        else sloodlepwd = value1;
+        
+    } else if (name == "set:sloodlecontrollerid") sloodlecontrollerid = (integer)value1;
+    else if (name == "set:sloodlerefreshtime") sloodlerefreshtime = (integer)value1;
+    else if (name == SLOODLE_EOF) eof = TRUE;
+    
+    return (sloodleserverroot != "" && sloodlepwd != "" && sloodlecontrollerid > 0);
+}
+
+
+
+default
+{
+    state_entry()
+    {
+        // Starting again with a new configuration
+        llSetText("", <0.0,0.0,0.0>, 0.0);
+        isconfigured = FALSE;
+        eof = FALSE;
+        // Reset our data
+        sloodleserverroot = "";
+        sloodlepwd = "";
+        sloodlecontrollerid = 0;
+        sloodlecoursename_full = "";
+    }
+    
+    link_message(integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Split the message into lines
+            list lines = llParseString2List(str, ["\n"], []);
+            integer numlines = llGetListLength(lines);
+            integer i = 0;
+            for (; i < numlines; i++) {
+                isconfigured = sloodle_handle_command(llList2String(lines, i));
+            }
+            
+            // If we've got all our data AND reached the end of the configuration data, then move on
+            if (eof == TRUE) {
+                if (isconfigured == TRUE) {
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configurationreceived", [], NULL_KEY, "");
+                    state running;
+                } else {
+                    // Got all configuration but, it's not complete... request reconfiguration
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configdatamissing", [], NULL_KEY, "");
+                    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:reconfigure", NULL_KEY);
+                    eof = FALSE;
+                }
+            }
+        }  
+    }
+    
+    touch_start(integer num_detected)
+    {
+        // Attempt to request a reconfiguration
+        if (llDetectedKey(0) == llGetOwner()) {
+            llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:requestconfig", NULL_KEY);
+        }
+    }
+    
+    on_rez(integer par)
+    {
+        llResetScript();
+    }
+}
+
+
+state running
+{
+    on_rez(integer param)
+    {
+        state default;
+    }
+
+    state_entry()
+    {
+        // Update the server
+        sloodle_update_server();
+        // Enable volume detection
+        llVolumeDetect(TRUE);
+        
+        // Validate the update timer
+        if (sloodlerefreshtime < 0) sloodlerefreshtime = 0;
+        else if (sloodlerefreshtime > 0 && sloodlerefreshtime < 60) sloodlerefreshtime = 60;
+        // Regularly update the server
+        llSetTimerEvent((float)sloodlerefreshtime);
+    }
+
+    collision_start(integer num_detected)
+    {
+        // Go through each detected avatar
+        integer i = 0;
+        for (; i < num_detected; i++)
+        {
+            sloodle_detected_avatar(llDetectedKey(i), llDetectedPos(i));
+        }
+    }
+
+    timer() 
+    {
+        sloodle_update_server();
+    }
+
+    moving_end()
+    {
+        sloodle_update_server();
+        // We don't need to automatically update right away again
+        llSetTimerEvent((float)sloodlerefreshtime);
+    }
+    
+    http_response(key id, integer status, list meta, string body)
+    {
+        integer statuscode; // added for OpenSim
+        // Was this our update response?
+        if (id == httpupdate) {
+            httpupdate = NULL_KEY;
+            sloodle_debug("HTTP response: " + body);
+            // Check the HTTP response
+            if (status != 200) {
+                sloodle_debug("Update failed with HTTP status " + (string)status);
+                sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,status); //send message to error_message.lsl
+                return;
+            }
+            // Extract the status code of the response
+            list bits = llParseString2List(body, ["|"], []);
+            statuscode = (integer)llList2String(bits, 0); // deleted "integer" for OpenSim
+            if (statuscode <= 0) {
+                sloodle_debug("Update failed with Sloodle status " + (string)statuscode);
+                sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,statuscode); //send message to error_message.lsl
+                return;
+            }
+            return;
+        }
+    
+        // Was this an avatar response?
+        integer listpos = llListFindList(httpreqs, [id]);
+        if (listpos < 0) return;
+        httpreqs = llDeleteSubList(httpreqs, listpos, listpos);
+        sloodle_debug("HTTP response: " + body);
+        
+        // Check that it was a successful response
+        if (status != 200) {
+            sloodle_debug("Avatar notification failed with HTTP status " + (string)status);
+            sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,status); //send message to error_message.lsl
+            return;
+        }
+        if (body == "") {
+            sloodle_debug("Empty response body from avatar notification.");
+            return;
+        }
+        
+        // Parse the response
+        list lines = llParseStringKeepNulls(body, ["\n"], []);
+        integer numlines = llGetListLength(lines);
+        list statusfields = llParseStringKeepNulls(llList2String(lines, 0), ["|"], []);
+        integer numfields = llGetListLength(statusfields);
+        statuscode = (integer)llList2String(statusfields, 0); // deleted "integer" for OpenSim
+        key av = NULL_KEY;
+        if (numfields >= 7) av = (key)llList2String(statusfields, 6);
+        
+        // Check if it was successful
+        if (statuscode == 301) {
+            if (av != NULL_KEY) {
+                sloodle_translation_request(SLOODLE_TRANSLATE_IM, [], "alreadyauthenticated", [llKey2Name(av)], av, "regenrol");
+                return;
+            }
+        } else if (statuscode > 0) {
+            if (av != NULL_KEY) {
+                sloodle_translation_request(SLOODLE_TRANSLATE_IM, [], "userauthenticated", [llKey2Name(av)], av, "regenrol");
+                return;
+            }
+        } else if (statuscode == -301) {
+            // No user found with the specified position allocated
+            // Nothing to do...
+            sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,statuscode); //send message to error_message.lsl
+            return;
+        } else {
+            if (av != NULL_KEY) {
+                sloodle_translation_request(SLOODLE_TRANSLATE_IM, [], "userauthenticationfailed:code", [llKey2Name(av), statuscode], av, "regenrol");
+                return;
+            } else {
+                sloodle_debug("Authentication of unknown avatar failed with status code " + (string)statuscode);
+                sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,statuscode); //send message to error_message.lsl
+                return;
+            }
+        }
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/loginzone-1.0/objects/default/assets/sloodle_mod_loginzone-1.0.lslp

BIN
iar/assets/17ff929d-7905-4efa-ad7d-b064591fd225_texture.jp2


+ 73 - 0
iar/assets/1a8672e3-b191-de07-a075-22ad58dd48a2_script.lsl

@@ -0,0 +1,73 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+/*
+*  Part of the Sloodle project (www.sloodle.org)
+*
+*  Copyright (c) 2011-06 contributors (see below)
+*  Released under the GNU GPL v3
+*  -------------------------------------------
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*
+*  All scripts must maintain this copyrite information, including the contributer information listed
+*
+*  Contributors:
+*  Paul Preibisch
+*
+*  DESCRIPTION
+* Contributors:
+*  Edmund Edgar
+*  Paul Preibisch
+*/
+
+string currentUrl;
+integer SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_OWNER = -1639270111; // set the main shared media panel to the specified URL, accessible to the owner
+integer SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_GROUP = -1639270112; // set the main shared media panel to the specified URL, accessible to the group
+integer SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_ANYONE = -1639270114; // set the main shared media panel to the specified URL, accessible to anyone
+
+
+integer SLOODLE_LOAD_CURRENT_URL= -1639271137; //send message to shared media to open url that it is currently displaying in a browser.
+integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;
+default
+{
+    on_rez(integer start_param) {
+        llClearPrimMedia(3);  
+        currentUrl = "";  
+    }
+    state_entry(){
+      currentUrl = ""; 
+   }
+    link_message( integer sender_num, integer num, string str, key id ){        
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            if (str=="do:reconfigure"||str=="do:reset"){
+                llClearPrimMedia(3);  
+            }
+        }else if ( (num == SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_OWNER) || (num == SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_GROUP) ||(num == SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_ANYONE ) ) {
+llSetColor(<1.00000, 1.00000, 1.00000>,3);
+            integer perms = PRIM_MEDIA_PERM_OWNER;
+            if (num == SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_GROUP) {
+                perms = PRIM_MEDIA_PERM_GROUP;
+            } else if (num == SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_ANYONE) {
+                perms = PRIM_MEDIA_PERM_GROUP;
+            }
+            currentUrl = str;
+            llSetPrimMediaParams( 3, [ PRIM_MEDIA_CURRENT_URL, str, PRIM_MEDIA_HOME_URL, str, PRIM_MEDIA_FIRST_CLICK_INTERACT, TRUE, PRIM_MEDIA_AUTO_ZOOM, TRUE, PRIM_MEDIA_AUTO_PLAY, TRUE, PRIM_MEDIA_PERMS_INTERACT, perms, PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE ] );
+        }
+    }
+    
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/set-1.0/objects/default/assets/sloodle_shared_media_screen.lslp
+

BIN
iar/assets/1b173b2c-9d2c-4f7a-8239-b715f8d94174_texture.jp2


BIN
iar/assets/1c3f1858-4b3e-4b4d-9c2c-3cfd7b153be0_texture.jp2


BIN
iar/assets/1dffe964-adf4-44ce-8fca-79727db814f0_texture.jp2


BIN
iar/assets/1e32f5c9-9083-4a83-b11d-b39d9705bb0b_sound.ogg


+ 486 - 0
iar/assets/1ff5939a-4da0-c9b8-00a9-6ac86803b543_script.lsl

@@ -0,0 +1,486 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle Glossary (for Sloodle 0.3)
+// Allows users in-world to search a Moodle glossary.
+// Part of the Sloodle project (www.sloodle.org)
+//
+// Copyright (c) 2006-8 Sloodle
+// Released under the GNU GPL
+//
+// Contributors:
+//  Jeremy Kemp
+//  Peter R. Bloomfield
+//  Paul Preibisch (Fire Centaur in SL)
+integer SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST=-1828374651; // this channel is used to send status codes for translation to the error_messages lsl script
+integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;
+integer SLOODLE_CHANNEL_AVATAR_DIALOG = 1001;
+string SLOODLE_GLOSSARY_LINKER = "/mod/sloodle/mod/glossary-1.0/linker.php";
+string SLOODLE_EOF = "sloodleeof";
+
+string SLOODLE_OBJECT_TYPE = "glossary-1.0";
+
+integer SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC = 0;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_OWNER = 1;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_GROUP = 2;
+
+string sloodleserverroot = "";
+string sloodlepwd = "";
+integer sloodlecontrollerid = 0;
+integer sloodlemoduleid = 0;
+integer sloodleobjectaccessleveluse = 0; // Who can use this object?
+integer sloodleserveraccesslevel = 0; // Who can use the server resource? (Value passed straight back to Moodle)
+integer sloodlepartialmatches = 1;
+integer sloodlesearchaliases = 0;
+integer sloodlesearchdefinitions = 0;
+integer sloodleidletimeout = 120; // How many seconds before automatic idle timeout? (0 means don't timeout)
+string sloodleglossaryname = ""; // Name of the glossary
+
+integer isconfigured = FALSE; // Do we have all the configuration data we need?
+integer eof = FALSE; // Have we reached the end of the configuration data?
+
+key httpcheck = NULL_KEY; // Request used to check the glossary
+key httpsearch = NULL_KEY; // Request used to search the glossary
+float HTTP_TIMEOUT = 10.0; // Period of time to wait for an HTTP response before giving up
+
+string SLOODLE_METAGLOSS_COMMAND = "/def "; // The command prefix for searching via chat message
+string searchterm = ""; // The term to be searched
+key searcheruuid = NULL_KEY; // Key of the avatar searching
+
+
+///// TRANSLATION /////
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";             // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";           // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";  // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";    // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";         // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";      // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";  // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";     // Recipient avatar should be identified in link message keyval. No output parameters.
+
+// Send a translation request link message
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+///// ----------- /////
+
+
+///// FUNCTIONS /////
+/******************************************************************************************************************************
+* sloodle_error_code - 
+* Author: Paul Preibisch
+* Description - This function sends a linked message on the SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST channel
+* The error_messages script hears this, translates the status code and sends an instant message to the avuuid
+* Params: method - SLOODLE_TRANSLATE_SAY, SLOODLE_TRANSLATE_IM etc
+* Params:  avuuid - this is the avatar UUID to that an instant message with the translated error code will be sent to
+* Params: status code - the status code of the error as on our wiki: http://slisweb.sjsu.edu/sl/index.php/Sloodle_status_codes
+*******************************************************************************************************************************/
+sloodle_error_code(string method, key avuuid,integer statuscode){
+            llMessageLinked(LINK_SET, SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST, method+"|"+(string)avuuid+"|"+(string)statuscode, NULL_KEY);
+}
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+sloodle_reset()
+{
+    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "resetting", [], NULL_KEY, "");
+    llMessageLinked(LINK_SET, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:reset", NULL_KEY);
+    llResetScript();
+}
+
+// Configure by receiving a linked message from another script in the object
+// Returns TRUE if the object has all the data it needs
+integer sloodle_handle_command(string str) 
+{
+    list bits = llParseString2List(str,["|"],[]);
+    integer numbits = llGetListLength(bits);
+    string name = llList2String(bits,0);
+    string value1 = "";
+    string value2 = "";
+    
+    if (numbits > 1) value1 = llList2String(bits,1);
+    if (numbits > 2) value2 = llList2String(bits,2);
+    
+    if (name == "set:sloodleserverroot") sloodleserverroot = value1;
+    else if (name == "set:sloodlepwd") {
+        // The password may be a single prim password, or a UUID and a password
+        if (value2 != "") sloodlepwd = value1 + "|" + value2;
+        else sloodlepwd = value1;
+        
+    } else if (name == "set:sloodlecontrollerid") sloodlecontrollerid = (integer)value1;
+    else if (name == "set:sloodlemoduleid") sloodlemoduleid = (integer)value1;
+    else if (name == "set:sloodleobjectaccessleveluse") sloodleobjectaccessleveluse = (integer)value1;
+    else if (name == "set:sloodleserveraccesslevel") sloodleserveraccesslevel = (integer)value1;
+    else if (name == "set:sloodlepartialmatches") sloodlepartialmatches = (integer)value1;
+    else if (name == "set:sloodlesearchaliases") sloodlesearchaliases = (integer)value1;
+    else if (name == "set:sloodlesearchdefinitions") sloodlesearchdefinitions = (integer)value1;
+    else if (name == "set:sloodleidletimeout") sloodleidletimeout = (integer)value1;
+    else if (name == SLOODLE_EOF) eof = TRUE;
+    
+    return (sloodleserverroot != "" && sloodlepwd != "" && sloodlecontrollerid > 0 && sloodlemoduleid > 0);
+}
+
+// Checks if the given agent is permitted to user this object
+// Returns TRUE if so, or FALSE if not
+integer sloodle_check_access_use(key id)
+{
+    // Check the access mode
+    if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_GROUP) {
+        return llSameGroup(id);
+    } else if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC) {
+        return TRUE;
+    }
+    
+    // Assume it's owner mode
+    return (id == llGetOwner());
+}
+
+
+///// STATES /////
+
+// Default state - waiting for configuration
+default
+{
+    state_entry()
+    {
+        // Starting again with a new configuration
+        isconfigured = FALSE;
+        eof = FALSE;
+        // Reset our data
+        sloodleserverroot = "";
+        sloodlepwd = "";
+        sloodlecontrollerid = 0;
+        sloodlemoduleid = 0;
+        sloodleobjectaccessleveluse = 0;
+        sloodleserveraccesslevel = 0;
+        sloodlepartialmatches = 1;
+        sloodlesearchaliases = 0;
+        sloodlesearchdefinitions = 0;
+        sloodleidletimeout = 120;
+        sloodleglossaryname = "";
+    }
+    
+    link_message( integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Split the message into lines
+            list lines = llParseString2List(str, ["\n"], []);
+            integer numlines = llGetListLength(lines);
+            integer i = 0;
+            for (; i < numlines; i++) {
+                isconfigured = sloodle_handle_command(llList2String(lines, i));
+            }
+            
+            // If we've got all our data AND reached the end of the configuration data, then move on
+            if (eof == TRUE) {
+                if (isconfigured == TRUE) {
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configurationreceived", [], NULL_KEY, "");
+                    state check_glossary;
+                } else {
+                    // Go all configuration but, it's not complete... request reconfiguration
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configdatamissing", [], NULL_KEY, "");
+                    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:reconfigure", NULL_KEY);
+                    eof = FALSE;
+                }
+            }
+        }
+    }
+    
+    touch_start(integer num_detected)
+    {
+        // Attempt to request a reconfiguration
+        if (llDetectedKey(0) == llGetOwner()) {
+            llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:requestconfig", NULL_KEY);
+        }
+    }
+}
+
+
+// If necessary, check the name of the glossary
+state check_glossary
+{
+    on_rez(integer par)
+    {
+        state default;
+    }
+    
+    link_message( integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Is it a reset message?
+            if (str == "do:reset") llResetScript();
+        }
+    }
+
+    state_entry()
+    {
+        // Lookup the glossary name
+        sloodleglossaryname = "";
+        sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.0,1.0,0.0>, 0.8], "metagloss:checking", [], NULL_KEY, "metagloss");        
+        httpcheck = llHTTPRequest(sloodleserverroot + SLOODLE_GLOSSARY_LINKER + "?sloodlecontrollerid=" + (string)sloodlecontrollerid + "&sloodlepwd=" + sloodlepwd + "&sloodlemoduleid=" + (string)sloodlemoduleid, [HTTP_METHOD, "GET"], "");
+        llSetTimerEvent(0.0);
+        llSetTimerEvent(HTTP_TIMEOUT);
+    }
+    
+    state_exit()
+    {
+        llSetTimerEvent(0.0);
+    }
+    
+    timer()
+    {
+        llSetTimerEvent(0.0);
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "httptimeout", [], NULL_KEY, "");
+        llSleep(0.1);
+        sloodle_reset();
+    }
+    
+    http_response(key id, integer status, list meta, string body)
+    {
+        // Make sure this is the response we're expecting
+        if (id != httpcheck) return;
+        if (status != 200) {
+        sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,status); //send message to error_message.lsl
+            sloodle_reset();
+            return;
+        }
+
+        // Split the response into lines
+        list lines = llParseStringKeepNulls(body, ["\n"], []);
+        integer numlines = llGetListLength(lines);
+        list statusfields = llParseStringKeepNulls(llList2String(lines, 0), ["|"], []);
+        integer statuscode = (integer)llList2String(statusfields, 0);
+        
+        // Check the statuscode
+        if (statuscode <= 0) {
+            //sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "servererror", [statuscode], NULL_KEY, "");
+            sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,statuscode); //send message to error_message.lsl
+            sloodle_reset();
+            return;
+        }
+        
+        // Make sure we have enough data
+        if (numlines < 2) {
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "badresponseformat", [], NULL_KEY, "");
+            sloodle_reset();
+            return;
+        }
+        
+        // Store the glossary name
+        sloodleglossaryname = llList2String(lines, 1);
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "metagloss:checkok", [sloodleglossaryname], NULL_KEY, "metagloss");
+        state ready;
+    }
+}
+
+
+// Ready for definition requests
+state ready
+{
+    on_rez( integer param)
+    {
+        state default;
+    }
+    
+    link_message( integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Is it a reset message?
+            if (str == "do:reset") llResetScript();
+        }
+    }
+    
+    state_entry()
+    {
+        // Update the hover text
+        sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<1.0,0.0,0.0>, 0.9], "metagloss:ready", [sloodleglossaryname, SLOODLE_METAGLOSS_COMMAND], NULL_KEY, "metagloss");
+        // Listen for chat messages
+        llListen(0, "", NULL_KEY, "");
+    
+        // We may need to de-activate after a period of idle time
+        llSetTimerEvent(0.0);
+        if (sloodleidletimeout > 0) llSetTimerEvent((float)sloodleidletimeout);
+    }
+    
+    state_exit()
+    {
+        llSetTimerEvent(0.0);
+    }
+    
+    listen( integer channel, string name, key id, string message)
+    {
+        // Check the channel
+        if (channel == 0) {
+            // Check use of this object
+            if (sloodle_check_access_use(id) == FALSE) return;
+            // Is this a definition request?
+            if (llSubStringIndex(message, SLOODLE_METAGLOSS_COMMAND) != 0) return;
+    
+            // Store the term to be searched and search it
+            searchterm = llGetSubString(message, llStringLength(SLOODLE_METAGLOSS_COMMAND), -1);
+            searcheruuid = id;
+            state search;
+            return;
+        }
+    }
+
+    timer()
+    {
+        // Shutdown due to idle timeout
+        state shutdown;
+    }
+    
+}
+
+state shutdown
+{
+    on_rez(integer par)
+    {
+        state default;
+    }
+    
+    link_message( integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Is it a reset message?
+            if (str == "do:reset") llResetScript();
+        }
+    }
+    
+    state_entry()
+    {
+        sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.5,0.1,0.1>, 0.6], "metagloss:idle", [sloodleglossaryname], NULL_KEY, "metagloss");
+    }
+    
+    touch_start(integer num_detected)
+    {
+        // Go through each toucher
+        integer i = 0;
+        key id = NULL_KEY;
+        for (; i < num_detected; i++) {
+            id = llDetectedKey(i);
+            // Does this user have permission to use this object?
+            if (sloodle_check_access_use(id)) {
+                state ready;
+            } else {
+                sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "nopermission:use", [], NULL_KEY, "");
+            }
+        }
+    }
+}
+
+state search
+{
+    on_rez(integer par)
+    {
+        state default;
+    }
+    
+    link_message( integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Is it a reset message?
+            if (str == "do:reset") llResetScript();
+        }
+    }
+
+    state_entry()
+    {
+        // Search the specified term
+        sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<1.0,0.5,0.0>, 0.9], "metagloss:searching", [sloodleglossaryname], NULL_KEY, "metagloss");
+        string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+        body += "&sloodlepwd=" + sloodlepwd;
+        body += "&sloodlemoduleid=" + (string)sloodlemoduleid;
+        body += "&sloodleuuid=" + (string)searcheruuid;
+        body += "&sloodleavname=" + llEscapeURL(llKey2Name(searcheruuid));
+        body += "&sloodleserveraccesslevel=" + (string)sloodleserveraccesslevel;
+        body += "&sloodleterm=" + searchterm;
+        body += "&sloodlepartialmatches=" + (string)sloodlepartialmatches;
+        body += "&sloodlesearchaliases=" + (string)sloodlesearchaliases;
+        body += "&sloodlesearchdefinitions=" + (string)sloodlesearchdefinitions;
+        // Check if it's an object sending this message
+        if (searcheruuid != llGetOwnerKey(searcheruuid)) {
+            // This makes sure Moodle doesn't try to auto-register an object
+            body += "&sloodleisobject=true";
+        }
+        // Send the request
+        httpsearch = llHTTPRequest(sloodleserverroot + SLOODLE_GLOSSARY_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+        
+        llSetTimerEvent(0.0);
+        llSetTimerEvent(HTTP_TIMEOUT);
+    }
+    
+    state_exit()
+    {
+        llSetTimerEvent(0.0);
+    }
+    
+    timer()
+    {
+        llSetTimerEvent(0.0);
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "httptimeout", [], NULL_KEY, "");
+        state ready;
+    }
+    
+    http_response(key id, integer status, list meta, string body)
+    {
+        // Make sure this is the response we're expecting
+        if (id != httpsearch) return;
+        if (status != 200) {
+            sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,status); //send message to error_message.lsl
+            sloodle_reset();
+            return;
+        }
+        
+        // Split the response into lines
+        list lines = llParseStringKeepNulls(body, ["\n"], []);
+        integer numlines = llGetListLength(lines);
+        list statusfields = llParseStringKeepNulls(llList2String(lines, 0), ["|"], []);
+        integer statuscode = (integer)llList2String(statusfields, 0);
+        
+        // Check the statuscode
+        if (statuscode <= 0) {
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "servererror", [statuscode], NULL_KEY, "");
+            sloodle_reset();
+            return;
+        }
+        
+        // Indicate how many definitions were found
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "metagloss:numdefs", [searchterm, (numlines - 1)], NULL_KEY, "metagloss");
+        
+        // Go through each definition
+        integer defnum = 1;
+        list fields = [];
+        for (; defnum < numlines; defnum++) {
+            // Split this definition into fields
+            fields = llParseStringKeepNulls(llList2String(lines, defnum), ["|"], []);
+            if (llGetListLength(fields) >= 2) {
+                llSay(0, llList2String(fields, 0) + " = " + llList2String(fields, 1));
+            } else {
+                llSay(0, llList2String(fields, 0));
+            }
+        }
+
+        state ready;
+    }
+}
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/glossary-1.0/objects/default/assets/sloodle_mod_glossary-1.0.lslp 

BIN
iar/assets/242a849f-9f63-40ad-b3e2-98135b326d42_texture.jp2


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
iar/assets/24d0383f-b931-4966-8f05-912dea15ba40_object.xml


BIN
iar/assets/2507e9d9-dfcc-478a-a18f-f4ad719daba3_sound.ogg


BIN
iar/assets/25b1caca-f1dd-4fc1-89bc-238d25e5de50_texture.jp2


BIN
iar/assets/25dd51e6-5d6b-4f8a-b2f7-8bef574f2aa0_texture.jp2


+ 72 - 0
iar/assets/263e78b2-cb75-7cbd-012c-d6d900b8b62e_script.lsl

@@ -0,0 +1,72 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle parallel URL loader
+// Allows the loading of a single URL on a specified channel.
+// (NOTE: should be in the same prim as a "sloodle_multi_url_loader.lsl" script)
+// Part of the Sloodle project (www.sloodle.org)
+//
+// Copyright (c) 2007 Sloodle (various contributors)
+// Released under the GNU GPL
+//
+// Contributors:
+//  Peter R. Bloomfield
+//
+
+//
+// When receiving a link message, this script will load a URL for a given user.
+// The URL should be in the string, and the user specified by their key.
+// The integer number in the link message should be SLOODLE_CHANNEL_OBJECT_LOAD_URL
+//
+// NOTE: you MUST customize the "MY_CHANNEL_INDEX" value to indicate which script number this is.
+//  Each of these scripts in a given object should have a unique channel index.
+//  This identifies where the object appears in the sequence.
+//  Channel indices should be numbered sequentially from 0.
+//  It is recommended that you replace the "x" in the script name to correspond to the channel index.
+
+
+///// DATA /////
+
+// The index of the channel this script will receive requests on
+// (NOTE: corresponds to indices in the list below)
+integer MY_CHANNEL_INDEX = 3;
+
+
+// OUTGOING link message numbers for parallel load requests
+list SLOODLE_CHANNEL_LIST_LOAD_URL_x =  [
+                                        -1699000001, //SLOODLE_CHANNEL_LOAD_URL_0
+                                        -1699000002, //SLOODLE_CHANNEL_LOAD_URL_1
+                                        -1699000003, //SLOODLE_CHANNEL_LOAD_URL_2
+                                        -1699000004, //SLOODLE_CHANNEL_LOAD_URL_3
+                                        -1699000005, //SLOODLE_CHANNEL_LOAD_URL_4
+                                        -1699000006, //SLOODLE_CHANNEL_LOAD_URL_5
+                                        -1699000007, //SLOODLE_CHANNEL_LOAD_URL_6
+                                        -1699000008, //SLOODLE_CHANNEL_LOAD_URL_7
+                                        -1699000009, //SLOODLE_CHANNEL_LOAD_URL_8
+                                        -1699000010  //SLOODLE_CHANNEL_LOAD_URL_9
+                                        ];
+
+///// ---- /////
+
+default
+{
+    state_entry()
+    {
+        if (MY_CHANNEL_INDEX < 0 || MY_CHANNEL_INDEX > llGetListLength(SLOODLE_CHANNEL_LIST_LOAD_URL_x)) {
+            llOwnerSay("WARNING: script \"" + llGetScriptName() + "\" has an invalid channel index. Please alter value \"MY_CHANNEL_INDEX\".");
+        }
+    }
+    
+    link_message( integer sender_num, integer msg_num, string str, key id )
+    {
+        // Ignore this message if the variables are empty
+        if (str == "" || id == NULL_KEY) return;
+        // If this message is not on the correct channel, then ignore it
+        if (msg_num != llList2Integer(SLOODLE_CHANNEL_LIST_LOAD_URL_x, MY_CHANNEL_INDEX)) return;
+        
+        // Load the URL
+        llLoadURL(id, "", str);
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: assets/sloodle_parallel_url_loader_3.lslp 

BIN
iar/assets/2875e885-2f83-4ae6-bfb3-067f36e18773_sound.ogg


+ 452 - 0
iar/assets/28b36c20-b296-2f40-1159-8a8e49169079_script.lsl

@@ -0,0 +1,452 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+       // Sloodle quiz chair
+        // Allows SL users to take Moodle quizzes in-world
+        // Part of the Sloodle project (www.sloodle.org)
+        //
+        // Copyright (c) 2006-9 Sloodle (various contributors)
+        // Released under the GNU GPL
+        //
+        // Contributors:
+        //  Edmund Edgar
+        //  Paul Preibisch
+        //  Peter R. Bloomfield
+
+        // Once configured in the usual way, this script waits for a request to ask a question in the form of a linked message with num SLOODLE_CHANNEL_QUIZ_ASK_QUESTION.
+        // When the student answers the question, it sends out a linked message with num SLOODLE_CHANNEL_QUESTION_ANSWERED_AVATAR.
+        // Note that it doesn't handle timeouts in case the user doesn't respond - all that should be done by the calling script.
+        
+        integer SLOODLE_CHANNEL_QUIZ_STOP_FOR_AVATAR = -1639271119; //Tells us to STOP a quiz for the avatar
+        integer SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST=-1828374651;
+        integer doRepeat = 0; // whether we should run through the questions again when we're done
+        integer doDialog = 1; // whether we should ask the questions using dialog rather than chat
+        integer menu_channel;
+        string sloodlehttpvars;
+        integer answerDialogListenHandler;
+        integer answerChatListenHandler;
+        integer answerChatListenHandlerNonPublic;
+        
+        integer SLOODLE_CHANNEL_QUESTION_ASKED_AVATAR = -1639271105; //Sent by main quiz script to tell UI scripts that question has been asked to avatar with key. String contains question ID + "|" + question text
+        integer SLOODLE_CHANNEL_QUESTION_ANSWERED_AVATAR = -1639271106;  //Sent by main quiz script to tell UI scripts that question has been answered by avatar with key. String contains selected option ID + "|" + option text + "|"
+        integer SLOODLE_CHANNEL_QUIZ_LOADING_QUESTION = -1639271107; 
+        integer SLOODLE_CHANNEL_ANSWER_SCORE_FOR_AVATAR = -1639271113; // Tells anyone who might be interested that we scored the answer. Score in string, avatar in key.
+        integer SLOODLE_CHANNEL_QUIZ_STATE_ENTRY_QUIZZING = -1639271117; //mod quiz script is in state quizzing
+        integer SLOODLE_CHANNEL_QUIZ_ERROR_INVALID_QUESION = -1639271121;  //
+        integer SLOODLE_CHANNEL_QUIZ_ERROR_NO_ATTEMPTS_LEFT= -1639271123;  //
+        integer SLOODLE_CHANNEL_QUIZ_ERROR_NO_QUESTIONS= -1639271124;  //          
+        integer SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_CHAT = -1639271125; // Tells the question handler scripts to ask the question with the ID in str to the avatar with key VIA CHAT.
+        integer SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_DIALOG = -1639271126; // Tells the question handler scripts to ask the question with the ID in str to the avatar with key VIA DIALOG.
+        ///// TRANSLATION /////
+        // Link message channels
+        integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+        // Translation output methods
+        string SLOODLE_TRANSLATE_WHISPER = "whisper";               // 1 output parameter: chat channel number
+        string SLOODLE_TRANSLATE_SAY = "say";               // 1 output parameter: chat channel number
+        string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";    // No output parameters
+        string SLOODLE_TRANSLATE_DIALOG = "dialog";         // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+        string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";      // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+        string SLOODLE_TRANSLATE_IM = "instantmessage";     // Recipient avatar should be identified in link message keyval. No output parameters.
+        string sloodle_full_quiz_url;
+        key httpfetchquestionquery = NULL_KEY;
+        key feedbackreq = NULL_KEY;
+        float request_timeout = 20.0;
+        integer question_id = -1;
+        // Text and type of the current and next question
+        string qtext = "";
+        string qtype = "";
+        // Lists of option information for the current question
+        list opids = []; // IDs
+        list optext = []; // Texts
+        list opgrade = []; // Grades
+        list opfeedback = []; // Feedback if this option is selected
+        // Avatar currently using this cahir
+        key sitter = NULL_KEY; 
+
+                    
+        ///// FUNCTIONS /////
+        /******************************************************************************************************************************
+        * sloodle_error_code - 
+        * Author: Paul Preibisch
+        * Description - This function sends a linked message on the SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST channel
+        * The error_messages script hears this, translates the status code and sends an instant message to the avuuid
+        * Params: method - SLOODLE_TRANSLATE_SAY, SLOODLE_TRANSLATE_IM etc
+        * Params:  avuuid - this is the avatar UUID to that an instant message with the translated error code will be sent to
+        * Params: status code - the status code of the error as on our wiki: http://slisweb.sjsu.edu/sl/index.php/Sloodle_status_codes
+        *******************************************************************************************************************************/
+        sloodle_error_code(string method, key avuuid,integer statuscode){
+                    llMessageLinked(LINK_SET, SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST, method+"|"+(string)avuuid+"|"+(string)statuscode, NULL_KEY);
+        }        sloodle_debug(string msg)
+        {
+            llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+        }        
+        integer random_integer( integer min, integer max )
+        {
+          return min + (integer)( llFrand( max - min + 1 ) );
+        }
+        // Query the server for the identified question (request by global question ID)
+        key request_question( integer qid )
+        {
+            
+            llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_LOADING_QUESTION, (string)qid, sitter);            
+            
+            // Request the identified question from Moodle
+            
+            string body = sloodlehttpvars+"&ltq=" + (string)qid;
+            key newhttp = llHTTPRequest(sloodle_full_quiz_url, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+            
+            llSetTimerEvent(0.0);
+            llSetTimerEvent(request_timeout);
+            
+            return newhttp;
+        }
+        
+        // Query the server for the feedback for a particular choice.
+        // This is only called if the server has told us that the feedback is too long to go in the regular request
+        // It does this by substituting the feedback [[[LONG]]]
+        key request_feedback( integer qid, string fid ) {
+            // Request the identified question from Moodle
+            string body = sloodlehttpvars;
+            body += "&ltq=" + (string)qid;
+            body += "&fid=" + (string)fid;                                    
+            
+            key reqid = llHTTPRequest(sloodle_full_quiz_url, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+            llSleep(3.0); // Hopefully the message will come back before the next question is asked. But if it comes back out of order, we won't insist.
+            
+            return reqid;
+            
+        }
+        
+        // Notify the server of a response
+        notify_server(string qtype, integer questioncode, string responsecode, float scorechange)
+        {
+            string body =sloodlehttpvars;
+            body += "&resp" + (string)questioncode + "_=" + responsecode;
+            body += "&resp" + (string)questioncode + "_submit=1";
+            body += "&questionids=" + (string)questioncode;
+            body += "&action=notify";
+            body += "&scorechange="+(string)scorechange;
+            
+            llHTTPRequest(sloodle_full_quiz_url, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+        }
+        
+        
+        // Ask the current question
+        ask_question() 
+        {     
+                                  
+            // Are we using dialogs?
+            if (doDialog == 1) {
+                
+                // We want to create a dialog with the option texts embedded into the main text,
+                //  and numbers on the buttons
+                integer qi;
+                list qdialogoptions = [];
+                
+                string qdialogtext = qtext + "\n";
+                // Go through each option
+                integer num_options = llGetListLength(optext);
+                
+                if ((qtype == "numerical")|| (qtype == "shortanswer")) {
+                   // Ask the question via IM
+                   llInstantMessage(sitter, qtext);
+                } else {
+                    for (qi = 1; qi <= num_options; qi++) {
+                        // Append this option to the main dialog (remebering buttons are 1-based, but lists 0-based)
+                        qdialogtext += (string)qi + ": " + llList2String(optext,qi-1) + "\n";
+                        // Add a button for this option
+                        qdialogoptions = qdialogoptions + [(string)qi];
+                    }
+                    // Present the dialog to the user
+                    answerDialogListenHandler = llListen(menu_channel, "", sitter, "");
+                    llDialog(sitter, qdialogtext, qdialogoptions, menu_channel);
+                }
+            } else {
+                
+                // Ask the question via IM
+                llListenRemove(answerChatListenHandler); // cancel any existing listens before creating a new one
+                answerChatListenHandler = llListen(0, "", sitter, "");                
+                
+                // Listen on channel 111 to allow people to give answers without everyone else hearing them.                
+                llListenRemove(answerChatListenHandlerNonPublic); // cancel any existing listens before creating a new one
+                answerChatListenHandlerNonPublic = llListen(111, "", sitter, "");                
+                                
+                llInstantMessage(sitter, qtext);
+                // Offer the options via IM
+                integer x = 0;
+                integer num_options = llGetListLength(optext);
+                for (x = 0; x < num_options; x++) {
+                    llInstantMessage(sitter, (string)(x + 1) + ". " + llList2String(optext, x));
+                }        
+            }
+            
+            llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUESTION_ASKED_AVATAR, (string)question_id+"|"+qtext, sitter);
+            
+        }
+        // Send a translation request link message
+        sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch){
+            llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+        }
+        ///// ----------- /////
+        ///// STATES /////
+        default{
+            on_rez(integer param)
+            {
+                llResetScript();
+            }
+            
+            link_message(integer sender_num, integer num, string str, key id){
+                if (num ==SLOODLE_CHANNEL_QUIZ_STOP_FOR_AVATAR){
+                    llListenRemove(answerDialogListenHandler);
+                    llListenRemove(answerChatListenHandler);
+                    llListenRemove(answerChatListenHandlerNonPublic);            
+                }                
+                else
+                if (num == SLOODLE_CHANNEL_QUIZ_STATE_ENTRY_QUIZZING){
+                    sitter=id;
+                
+                    llListenRemove(answerDialogListenHandler); // Cancel any existing listens
+                    menu_channel = random_integer(-90000,-900000);                                    
+                }
+                else
+                if (num == SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_DIALOG||num == SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_CHAT) {//todo add to dia
+                    list data = llParseString2List(str, ["|"], []);
+                    question_id = llList2Integer(data, 0);
+                    sloodle_full_quiz_url = llList2String(data, 1);//todo add to dia
+                    integer offset = llStringLength(llList2String(data,0)+"|"+sloodle_full_quiz_url+"|");
+                    sloodlehttpvars = llGetSubString(str, offset, -1);//-1 is the end of the list
+                    sitter = id;
+                    if (num == SLOODLE_CHANNEL_QUIZ_ASK_QUESTION_DIALOG) {//todo add to dia
+                        doDialog=TRUE; //todo add to dia
+                    }else{
+                        doDialog=FALSE;//todo add to dia
+                    }
+                    httpfetchquestionquery = request_question((integer)str);                    
+                } 
+            }
+            state_exit()
+            {
+                llSetTimerEvent(0.0);
+            }
+            
+            listen(integer channel, string name, key id, string message)
+            {
+                // If using dialogs, then only listen to the dialog channel
+                
+                if (doDialog && ((qtype == "multichoice") || (qtype == "truefalse"))) {
+                    if (channel != menu_channel) {
+                        sloodle_translation_request(SLOODLE_TRANSLATE_IM, [0], "usedialogs", [llKey2Name(sitter)], sitter, "quiz");
+                        return;
+                    }
+                } else {
+                    if (channel != 0) return;
+                }
+            
+                string opid; // used when the feedback is too long, and we have to fetch it off the server
+                // Only listen to the sitter
+                if (id == sitter) {
+                    // Handle the answer...
+                    float scorechange = 0;
+                    string feedback = "";
+                    string answeroptext = "";
+                    
+                    // Check the type of question this was
+                    if ((qtype == "multichoice") || (qtype == "truefalse")) {
+                        // Multiple choice - the response should be a number from the dialog box (1-based)
+                        integer answer_num = (integer)message;
+                        // Make sure it's valid
+                        if ((answer_num > 0) && (answer_num <= llGetListLength(opids))) {
+                            // Correct to 0-based
+                            answer_num -= 1;
+                            
+                            feedback = llList2String(opfeedback, answer_num);
+                            scorechange = llList2Float(opgrade, answer_num);
+                            opid = llList2String(opids, answer_num);
+                            answeroptext = llList2String(optext, answer_num);
+
+                            // Notify the server of the response
+                            notify_server(qtype, question_id, llList2String(opids, answer_num),scorechange);
+                        } else {
+                            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "invalidchoice", [llKey2Name(sitter)], NULL_KEY, "quiz");
+                            ask_question();
+                        }        
+                     } else if (qtype == "shortanswer") {
+                               // Notify the server of the response 
+                               integer x = 0;
+                               integer num_options = llGetListLength(optext);
+                               for (x = 0; x < num_options; x++) {
+                                   if (llToLower(message) == llToLower(llList2String(optext, x))) {
+                                      feedback = llList2String(opfeedback, x);
+                                      scorechange = llList2Float(opgrade, x);
+                                      opid = llList2String(opids, x);
+                                      answeroptext = llList2String(optext, x);
+                                   }
+                               notify_server(qtype, question_id, message, scorechange);
+                               }        
+                    } else if (qtype == "numerical") {
+                               // Notify the server of the response
+                               float number = (float)message;
+                               integer x = 0;
+                               integer num_options = llGetListLength(optext);
+                               for (x = 0; x < num_options; x++) {
+                                   if (number == (float)llList2String(optext, x)) {
+                                      feedback = llList2String(opfeedback, x);
+                                      scorechange = llList2Float(opgrade, x);
+                                      opid = llList2String(opids, x);
+                                      answeroptext = llList2String(optext, x);                                      
+                                   }
+                                   notify_server(qtype, question_id, message, scorechange);
+                               }        
+                    } 
+                    
+                    
+                     else {
+                        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "invalidtype", [qtype], NULL_KEY, "quiz");
+                    }                
+                    
+                    llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUESTION_ANSWERED_AVATAR, opid+"|"+answeroptext, sitter);    
+                    
+                    if (feedback == "[[LONG]]") // special long feedback placeholder for when there is too much feedback to give to the script
+                        feedbackreq = request_feedback( question_id, opid );
+                    else if (feedback != "") llInstantMessage(sitter, feedback); // Text feedback
+                    else if (scorechange > 0.0) {                                                    
+                        sloodle_translation_request(SLOODLE_TRANSLATE_IM, [0], "correct", [llKey2Name(sitter)], sitter, "quiz");
+                        //num_correct += 1; SAL commented out this
+                    } else {
+                        sloodle_translation_request(SLOODLE_TRANSLATE_IM, [0], "incorrect",  [llKey2Name(sitter)], sitter, "quiz");
+                    }
+                    llSleep(1.);  //wait to finish the sloodle_translation_request before next question.
+                    
+                    // Clear out our current data (a feeble attempt to save memory!)
+                    qtext = "";
+                    qtype = "";
+                    opids = [];
+                    optext = [];
+                    opgrade = [];
+                    opfeedback = [];              
+                    
+                    llMessageLinked(LINK_SET, SLOODLE_CHANNEL_ANSWER_SCORE_FOR_AVATAR, (string)scorechange, sitter);                                                                              
+    
+                }
+            }
+            
+            timer()
+            {
+                // There has been a timeout of the HTTP request
+                sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "httptimeout", [], NULL_KEY, "");
+                llSetTimerEvent(0.0);
+                
+                if (question_id > -1) {
+                    httpfetchquestionquery = request_question(question_id);
+                }
+            }            
+        
+            http_response(key request_id, integer status, list metadata, string body)
+            {
+                
+                // This response will always contain question data.
+                // If the current question is being loaded, then ask it right away, and load the next.
+                // If the next question is being loaded, then just store it.
+                // It will be made current and asked whenever the current one gets answered.
+                // If the user ever gets ahead of our loading, then they will be waiting on the 'current' question.
+                // As soon as that is loaded, it will get asked.
+            
+                // Is this the response we are expecting?
+                if (request_id == httpfetchquestionquery) {                
+                    httpfetchquestionquery = NULL_KEY;
+                    llSetTimerEvent(0.0);
+                } else if (request_id != feedbackreq) {
+                    return;
+                }
+                
+                // Make sure the response was OK
+                if (status != 200) {
+                    sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,status); //send message to error_message.lsl
+                    if (request_id!=feedbackreq){
+                        request_question( question_id );//TODO update DIA
+                    } 
+                    
+                }
+                
+                // Split the response into several lines
+                list lines = llParseStringKeepNulls(body, ["\n"], []);
+                integer numlines = llGetListLength(lines);
+                body = "";
+                list statusfields = llParseStringKeepNulls(llList2String(lines,0), ["|"], []);
+                integer statuscode = llList2Integer(statusfields, 0);
+                
+                // Was it an error code?
+                if (statuscode == -10301) {
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "noattemptsleft", [llKey2Name(sitter)], NULL_KEY, "");
+                    llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_ERROR_NO_ATTEMPTS_LEFT, (string)question_id, sitter);//todo add to dia
+                    return;
+                    
+                } else if (statuscode == -10302) {
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "noquestions", [], NULL_KEY, "");
+                    llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_ERROR_NO_QUESTIONS, (string)question_id, sitter);//todo add to dia
+                    
+                    return;
+                    
+                } else if (statuscode <= 0) {
+                    //sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "servererror", [statuscode], NULL_KEY, "");
+                     sloodle_error_code(SLOODLE_TRANSLATE_IM, sitter,statuscode); //send message to error_message.lsl
+                    // Check if an error message was reported
+                    if (numlines > 1) sloodle_debug(llList2String(lines, 1));
+                    return;
+                }
+                
+                if (request_id == feedbackreq) {
+                    llInstantMessage( sitter, llList2String(lines, 1) );
+                    return;
+                }
+                
+                // Save a tiny bit of memory!
+                statusfields = [];
+        
+                // Go through each line of the response
+               
+                integer i = 0;
+                for (i = 1; i < numlines; i++) {
+        
+                    // Extract and parse the current line
+                    list thisline = llParseStringKeepNulls(llList2String(lines, i),["|"],[]);
+                    string rowtype = llList2String( thisline, 0 );
+        
+                    // Check what type of line this is
+                    if ( rowtype == "question" ) {
+                        
+                        // Grab the question information and reset the options
+
+                            qtext = llList2String(thisline, 4);
+                            qtype = llList2String(thisline, 7);
+                            
+                            opids = [];
+                            optext = [];
+                            opgrade = [];
+                            opfeedback = [];
+                            
+                            // Make sure it's a valid question type
+                            if ((qtype != "multichoice") && (qtype != "truefalse") && (qtype != "numerical") && (qtype != "shortanswer")) {
+                                sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "invalidtype", [qtype], NULL_KEY, "quiz");
+                                sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "resetting", [], NULL_KEY, "");
+                                llMessageLinked(LINK_SET, SLOODLE_CHANNEL_QUIZ_ERROR_INVALID_QUESION, (string)question_id, sitter);//todo add to dia
+                                
+                                return;
+                            }
+                        
+                    } else if ( rowtype == "questionoption" ) {                        
+                        // Add this option to the appropriate place
+                        opids += [(integer)llList2String(thisline, 2)];
+                        optext += [llList2String(thisline, 4)];
+                        opgrade += [(float)llList2String(thisline, 5)];
+                        opfeedback += [llList2String(thisline, 6)];
+                    }
+                }
+                
+                // Automatically ask this question
+                ask_question();
+            }
+            
+        }
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/quiz-1.0/objects/default/assets/sloodle_quiz_question_handler.lslp

+ 338 - 0
iar/assets/2a04deec-21ff-f997-f719-c7d45ad8f575_script.lsl

@@ -0,0 +1,338 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Standard translation script for Sloodle.
+// Contains the common, re-usable words and phrases.
+//
+// The "locstrings" list is pairs of strings.
+// The first of each pair is the name, and second is the translation.
+//
+// This script is part of the Sloodle project.
+// Copyright (c) 2008 Sloodle (various contributors)
+// Released under the GNU GPL v3
+//
+// Contributors:
+//  Peter R. Bloomfield
+//
+//  6 Apr 09 TW Opensim init changes
+
+// Note: where a translation string contains {{x}} (where x is a number),
+//  it means that a parameter can be inserted. Please make sure to include these
+//  parameters in the appropriate location in your translation.
+// It may be sensible to add comments after your string to indicate what its parameters mean.
+// NOTE: parameter numbering starts at 0 (unlike previous versions, which started at 1).
+
+// Translations can be requested by sending a link message on the SLOODLE_CHANNEL_TRANSLATION_REQUEST channel.
+// It is advisable simply to use the "sloodle_translation_request" function provided in this script.
+
+
+///// TRANSLATION /////
+
+// Localization batch - indicates the purpose of this file
+string mybatch = "choice";
+
+
+// List of string names and translation pairs.
+// The name is the first of each pair, and should not be translated.
+// The second of each pair is the translation.
+// Additional comments are sometimes given afterward to aid translations.
+list locstrings = [
+    
+    // Success
+    "selectionmade", "Thank you {{0}}. Your selection has been made.", // Parameter: avatar name
+    "selectionupdated", "Thank you {{0}}. Your selection has been updated.", // Parameter: avatar name
+    "selectionalreadymade", "Thank you {{0}}. You had already selected that option.", // Parameter: avatar name
+    
+    
+    // Errors
+    "selectionerror", "Sorry {{0}}. There was an unknown error making your selection.", // Parameter: avatar name
+    "noupdate", "Sorry {{0}}. You cannot update your selection.", // Parameter: avatar name
+    "maxselections", "Sorry {{0}}. The maximum number of selections for that option have already been made.", // Parameter: avatar name
+    "notopen", "Sorry {{0}}. This choice is not yet open for selections.", // Parameter: avatar name
+    "closed", "Sorry {{0}}. This choice has been closed." // Parameter: avatar name
+];
+
+///// ----------- /////
+
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";                     // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";                       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";                   // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";          // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";            // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";                 // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";              // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_LOAD_URL_PARALLEL = "loadurlpar";  // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";          // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";             // Recipient avatar should be identified in link message keyval. No output parameters.
+
+
+// Used for sending parallel URL loading messages
+integer SLOODLE_CHANNEL_OBJECT_LOAD_URL = -1639270041;
+
+///// FUNCTIONS /////
+
+
+// Send a translation request link message
+// (Here for reference only)
+// Parameter: output_method = should identify an output method, as given by the "SLOODLE_TRANSLATE_..." constants above
+// Parameter: output_params = a list of parameters which controls the output, such as chat channel or buttons for a dialog
+// Parameter: string_name = the name of the localization string to output
+// Parameter: string_params = a list of parameters which will be included in the translated string (or an empty list if none)
+// Parameter: keyval = a key to send in the link message
+// Parameter: batch = the name of the localization batch which should handle this request
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+// Send a translation response link message
+sloodle_translation_response(integer target, string name, string translation)
+{
+    llMessageLinked(target, SLOODLE_CHANNEL_TRANSLATION_RESPONSE, name + "|" + translation + "|" + mybatch, NULL_KEY);
+}
+
+// Get the translation of a particular string
+string sloodle_get_string(string name)
+{
+    // Attempt to find the string name
+    integer numstrings = llGetListLength(locstrings);
+    integer pos = llListFindList(locstrings, [name]);
+    
+    // IMPORTANT: we must be careful not to match a translations instead of a name.
+    // If this was an even number, then we have a string name.
+    if ((pos % 2) == 0) {
+        // Make sure there is a subsequent translation in the list
+        if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
+        // The translation is not there
+        pos = -1;
+    }
+    
+    // If we could not find the string, then return a placeholder
+    if (pos < 0) return "[[" + name + "]]";
+    
+    // If we got here, then we matched a translation instead of a string name.
+    // As such, we need to resort to searching through the list manually (which can be very slow).
+    // To saved time, we can start from the position just beyond where we got to.
+    // We advance by 2 each time to skip the translations completely.
+    //pos += 1;
+    for (pos += 1; pos < numstrings; pos += 2) {
+        // Do we have a match?
+        if (llList2String(locstrings, pos) == name) {
+            // Yes - make sure there is a translation following it
+            if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
+            // The translation is not there - skip the rest of the search
+            pos = numstrings;
+        }
+    }
+    
+    // If we reached this point, then the string is not available. Return a placeholder.
+    return "[[" + name + "]]";
+}
+
+// Send a debug link message
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+
+// Get a formatted translation of a string
+string sloodle_get_string_f(string name, list params)
+{
+    // Get the string itself
+    string str = sloodle_get_string(name);
+    // How many parameters do we have?
+    integer numparams = llGetListLength(params);
+    
+    // Go through each parameter we have been provided
+    integer curparamnum;
+    string curparamtok = "{{x}}";
+    integer curparamtoklength = 0;
+    string curparamstr = "";
+    integer tokpos = -1;
+    for (curparamnum = 0; curparamnum < numparams; curparamnum++) {
+        // Construct this parameter token
+        curparamtok = "{{" + (string)(curparamnum) + "}}";
+        curparamtoklength = llStringLength(curparamtok);
+        // Fetch the parameter text
+        curparamstr = llList2String(params, curparamnum);
+        
+        // Ensure the parameter text does NOT contain double braces (this avoids an infinite loop!)
+        if (llSubStringIndex(curparamstr, "{{") < 0 && llSubStringIndex(curparamstr, "}}") < 0) {            
+            // Go through every instance of this parameter's token
+            while ((tokpos = llSubStringIndex(str, curparamtok)) >= 0) {
+                // Replace the token with the parameter string
+                str = llDeleteSubString(str, tokpos, tokpos + curparamtoklength - 1);
+                str = llInsertString(str, tokpos, curparamstr);
+            }
+        }
+    }
+    
+    return str;
+}
+
+
+///// STATES /////
+
+default
+{
+    state_entry()
+    {
+    }
+    
+    link_message(integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_TRANSLATION_REQUEST) {            
+            
+            // // PROCESS REQUEST // //
+        
+            // Split the incoming message into fields
+            list fields = llParseStringKeepNulls(str, ["|"], []);
+            integer numfields = llGetListLength(fields);
+            
+            // Extract and check the localization batch
+            string batch = "";
+            if (numfields > 4) batch = llList2String(fields, 4);
+            if (batch != mybatch) return;
+            
+            // We expect at least 3 fields
+            // ... or 4 if there are insertion parameters...
+            // ... or 5 if there is a language code
+            // ... anybody up for a 6th parameter? :)
+            if (numfields < 3) {
+                sloodle_debug("ERROR: Insufficient fields for translation of string.");
+                return;
+            }
+            
+            // Extract the key parts of the request
+            string output_method = llList2String(fields, 0);
+            list output_params = llCSV2List(llList2String(fields, 1));
+            integer num_output_params = llGetListLength(output_params);
+            string string_name = llList2String(fields, 2);
+            list string_params = [];
+            if (numfields > 3) {
+                // Extract the string parameters (extra text added to the output)
+                string string_param_text = llList2String(fields, 3);
+                if (string_param_text != "") string_params = llCSV2List(string_param_text);
+            }
+            
+            // // TRANSLATE STRING // //
+            
+            // This string will store the translation
+            string trans = "";
+            // Do nothing if the string name is empty
+            if (string_name != "") {
+                // If there are no string parameters, then it is only a basic translation
+                if (llGetListLength(string_params) == 0) {
+                    // Get the basic translation
+                    trans = sloodle_get_string(string_name);
+                } else {
+                    // Construct the formatted string
+                    trans = sloodle_get_string_f(string_name, string_params);
+                }
+            }
+            
+            // // OUTPUT STRING // //
+            
+            // Check what output method has been requested
+            if (output_method == SLOODLE_TRANSLATE_LINK) {
+                // Return the string via link message
+                sloodle_translation_response(sender_num, string_name, trans);
+                
+            } else if (output_method == SLOODLE_TRANSLATE_SAY) {
+                // Say the string
+                if (num_output_params > 0) llSay(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to say string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_WHISPER) {
+                // Whisper the string
+                if (num_output_params > 0) llWhisper(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to whisper string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_SHOUT) {
+                // Shout the string
+                if (num_output_params > 0) llShout(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to shout string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_REGION_SAY) {
+                // RegionSay the string
+                if (num_output_params > 0) llRegionSay(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to region-say string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_OWNER_SAY) {
+                // Ownersay the string
+                llOwnerSay(trans);
+                
+            } else if (output_method == SLOODLE_TRANSLATE_DIALOG) {
+                // Display a dialog - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to show dialog with string \"" + string_name + "\".");
+                    return;
+                }
+                // We need at least 2 additional output parameters (channel, and at least 1 button)
+                if (num_output_params >= 2) {
+                    // Extract the channel number
+                    integer channel = llList2Integer(output_params, 0);
+                    // Extract up to 12 button values
+                    list buttons = llList2List(output_params, 1, 12);
+                    
+                    // Display the dialog
+                    llDialog(id, trans, buttons, channel);
+                    
+                } else sloodle_debug("ERROR: Insufficient output parameters to show dialog with string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL) {
+                // Display a URL - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
+                    return;
+                }                
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 1) llLoadURL(id, trans, llList2String(output_params, 0));
+                else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL_PARALLEL) {
+                // Display a URL - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
+                    return;
+                }
+                
+                // NOTE: currently the parallel URL loaders will drop any text.
+                // TODO: make parallel URL loaders use text as well.
+                
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 1) llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_LOAD_URL, llList2String(output_params, 0), id);
+                else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_HOVER_TEXT) {
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 2) llSetText(trans, (vector)llList2String(output_params, 0), (float)llList2String(output_params, 1));
+                else sloodle_debug("ERROR: Insufficient output parameters to show hover text with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_IM) {
+                // Send an IM - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to send IM with string \"" + string_name + "\".");
+                    return;
+                }                
+                // Send the IM
+                llInstantMessage(id, trans);
+
+            } else {
+                // Don't know the output method
+                sloodle_debug("ERROR: unrecognised output method \"" + output_method + "\".");
+            }
+        }
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/choice-1.0/objects/default/assets/lang/en/sloodle_translation_choice_en.lslp 

BIN
iar/assets/2ca24bdc-c2c1-40e0-813a-8ab2f61208f8_texture.jp2


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
iar/assets/2e032d59-aef7-4e92-b1e4-ae8d95aa503f_object.xml


BIN
iar/assets/2f7ea399-2265-4e93-a438-e77e3be270f9_texture.jp2


BIN
iar/assets/3260992b-4721-4603-acce-e240c5dc76c2_texture.jp2


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
iar/assets/32dec74d-95b7-4d5d-bdf2-88e53f791011_object.xml


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
iar/assets/3385a309-bdbc-4f9b-b996-a31a50544fad_object.xml


BIN
iar/assets/34178b86-6836-4b2d-8d55-4dbde770bc25_sound.ogg


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
iar/assets/3489df28-10cd-443c-81e5-96645715044b_object.xml


BIN
iar/assets/365e73c3-4cff-4fb0-93df-89b74e9fc54b_texture.jp2


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
iar/assets/37e7fcca-f8f5-4b5d-97ae-3a4f66352c26_object.xml


BIN
iar/assets/3887be04-03b5-45e6-9762-b77989f49a46_texture.jp2


+ 501 - 0
iar/assets/39dc01c9-3546-9073-1c35-dc6a46cf0b77_script.lsl

@@ -0,0 +1,501 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle Choice (for Sloodle 0.3)
+// Allows avatars to interact graphically with a Moodle choice.
+//
+// Copyright (c) 2007-8 Sloodle
+// Released under the GNU GPL
+//
+// Contributors:
+//  Peter R. Bloomfield
+//  Paul Preibisch (Fire Centaur in SL)
+integer SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST=-1828374651; // this channel is used to send status codes for translation to the error_messages lsl script
+integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;
+integer SLOODLE_CHANNEL_AVATAR_DIALOG = 1001;
+integer SLOODLE_CHANNEL_OBJECT_CHOICE = -1639270051;
+string SLOODLE_CHOICE_LINKER = "/mod/sloodle/mod/choice-1.0/linker.php";
+string SLOODLE_EOF = "sloodleeof";
+
+string SLOODLE_OBJECT_TYPE = "choice-1.0";
+
+// Choice commands
+// Update the specified option. Followed by "|num|text|colour|count|prop"
+//  - num is a local option identifier
+//  - text is the caption to display for this option
+//  - colour is a colour vector (cast to a string)
+//  - count is the number selected so far (or -1 if we don't want to display any)
+//  - prop is the proportion of maximum size to show (between 0 and 1)
+string SLOODLE_CHOICE_UPDATE_OPTION = "do:updateoption";
+// Update the choice text. Followed by "|text"
+string SLOODLE_CHOICE_UPDATE_TEXT = "do:updatetext";
+// Select the specified option. Followed by "|num" (num is a local option identifier).
+// The UUID of the toucher should be passed as the key value.
+string SLOODLE_CHOICE_SELECT_OPTION = "do:selectoption";
+
+integer SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC = 0;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_OWNER = 1;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_GROUP = 2;
+
+string sloodleserverroot = "";
+string sloodlepwd = "";
+integer sloodlecontrollerid = 0;
+integer sloodlemoduleid = 0;
+integer sloodlerefreshtime = 600; // Number of seconds between automatic refreshes
+integer sloodlerelative = FALSE; // Should the results be displayed in a relativistic way?
+integer sloodleobjectaccessleveluse = 0; // Who can use this object?
+integer sloodleserveraccesslevel = 0; // Who can use the server resource? (Value passed straight back to Moodle)
+
+integer isconfigured = FALSE; // Do we have all the configuration data we need?
+integer eof = FALSE; // Have we reached the end of the configuration data?
+
+key httpstatus = NULL_KEY; // Request to check status of choice
+list httpselect = []; // Requests to make selections
+
+string choicetext = ""; // The choice text... i.e. the question being asked.
+list optionids = []; // List of IDs of available options (integers)
+list optiontexts = []; // List of option texts (strings)
+list optionselections = []; // Number of times each option has been selected (integers)
+integer numunanswered = -1; // Number of people who have not answered yet
+
+// A list of colors for the options (note: after running out of colours, the list will wrap around)
+list optioncolours = [
+    <1.0, 0.0, 0.0>, // Red
+    <0.0, 1.0, 0.0>, // Green
+    <0.0, 0.0, 1.0>, // Blue
+    <1.0, 1.0, 0.0>, // Yellow
+    <1.0, 0.0, 1.0>, // Magenta
+    <0.0, 1.0, 1.0>, // Cyan
+    <0.5, 0.0, 0.0>, // Dark red
+    <0.0, 0.5, 0.0>, // Dark green
+    <0.0, 0.0, 0.5>, // Dark blue
+    <1.0, 0.5, 0.0>, // Orange
+    <0.5, 0.0, 0.5>, // Purple
+    <0.0, 0.5, 0.5> // Indigo
+];
+
+
+///// TRANSLATION /////
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";             // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";           // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";  // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";    // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";         // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";      // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";  // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";     // Recipient avatar should be identified in link message keyval. No output parameters.
+
+// Send a translation request link message
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+///// ----------- /////
+
+
+///// FUNCTIONS /////
+/******************************************************************************************************************************
+* sloodle_error_code - 
+* Author: Paul Preibisch
+* Description - This function sends a linked message on the SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST channel
+* The error_messages script hears this, translates the status code and sends an instant message to the avuuid
+* Params: method - SLOODLE_TRANSLATE_SAY, SLOODLE_TRANSLATE_IM etc
+* Params:  avuuid - this is the avatar UUID to that an instant message with the translated error code will be sent to
+* Params: status code - the status code of the error as on our wiki: http://slisweb.sjsu.edu/sl/index.php/Sloodle_status_codes
+*******************************************************************************************************************************/
+sloodle_error_code(string method, key avuuid,integer statuscode){
+            llMessageLinked(LINK_SET, SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST, method+"|"+(string)avuuid+"|"+(string)statuscode, NULL_KEY);
+}
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+// Configure by receiving a linked message from another script in the object
+// Returns TRUE if the object has all the data it needs
+integer sloodle_handle_command(string str) 
+{
+    list bits = llParseString2List(str,["|"],[]);
+    integer numbits = llGetListLength(bits);
+    string name = llList2String(bits,0);
+    string value1 = "";
+    string value2 = "";
+    
+    if (numbits > 1) value1 = llList2String(bits,1);
+    if (numbits > 2) value2 = llList2String(bits,2);
+    
+    if (name == "set:sloodleserverroot") sloodleserverroot = value1;
+    else if (name == "set:sloodlepwd") {
+        // The password may be a single prim password, or a UUID and a password
+        if (value2 != "") sloodlepwd = value1 + "|" + value2;
+        else sloodlepwd = value1;
+        
+    } else if (name == "set:sloodlecontrollerid") sloodlecontrollerid = (integer)value1;
+    else if (name == "set:sloodlemoduleid") sloodlemoduleid = (integer)value1;
+    else if (name == "set:sloodlerefreshtime") sloodlerefreshtime = (integer)value1;
+    else if (name == "set:sloodlerelative") sloodlerelative = (integer)value1;
+    else if (name == "set:sloodleobjectaccessleveluse") sloodleobjectaccessleveluse = (integer)value1;
+    else if (name == "set:sloodleserveraccesslevel") sloodleserveraccesslevel = (integer)value1;
+    else if (name == SLOODLE_EOF) eof = TRUE;
+    
+    return (sloodleserverroot != "" && sloodlepwd != "" && sloodlecontrollerid > 0 && sloodlemoduleid > 0);
+}
+
+// Checks if the given agent is permitted to user this object
+// Returns TRUE if so, or FALSE if not
+integer sloodle_check_access_use(key id)
+{
+    // Check the access mode
+    if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_GROUP) {
+        return llSameGroup(id);
+    } else if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC) {
+        return TRUE;
+    }
+    
+    // Assume it's owner mode
+    return (id == llGetOwner());
+}
+
+// Gets the colour for a specified option (local option number)
+vector get_option_colour(integer num)
+{
+    // Make sure we don't run out of colours
+    num = num % llGetListLength(optioncolours);
+    return llList2Vector(optioncolours, num);
+}
+
+// Send a reset command to all options
+send_reset()
+{
+    llMessageLinked(LINK_SET, SLOODLE_CHANNEL_OBJECT_CHOICE, "do:reset", NULL_KEY);
+}
+
+// Send an update to all parts of the display
+send_update()
+{
+    // Update the choice text itself
+    llMessageLinked(LINK_SET, SLOODLE_CHANNEL_OBJECT_CHOICE, SLOODLE_CHOICE_UPDATE_TEXT + "|" + choicetext, NULL_KEY);
+    
+    // We want to determine the value that represents a full bar on the graph.
+    // In relative mode, this is the maximum number of selections for a given option (so everything is relative to that).
+    // Otherwise, it is the total number of people who have selected or could have selected.
+    integer fullbar = 0;
+    integer num_options = llGetListLength(optionids);
+    integer i = 0;
+    integer numsels = 0;
+    for (i = 0; i < num_options; i++) {
+        // Get the number of selections for this option
+        numsels = llList2Integer(optionselections, i);
+        // Relative mode?
+        if (sloodlerelative) {
+            // Store the maximum
+            if (numsels > fullbar) fullbar = numsels;
+        } else {
+            // Add to the total
+            fullbar += numsels;
+        }
+    }
+    
+    // Add the number who have not answered yet, if necessary
+    if (sloodlerelative == 0 && numunanswered > 0) fullbar += numunanswered;
+
+    // Go through each option we have
+    string data = "";
+    for (i = 0; i < num_options; i++) {
+        // Send all the data
+        data = SLOODLE_CHOICE_UPDATE_OPTION;
+        data += "|" + (string)i;
+        data += "|" + llList2String(optiontexts, i);
+        data += "|" + (string)get_option_colour(i);
+        data += "|" + (string)llList2Integer(optionselections, i);
+        
+        // Do we have results to add?
+        numsels = llList2Integer(optionselections, i);
+        if (numsels > 0 && fullbar > 0) {
+            // At this point, all results are relative to the 'fullbar' value
+            data += "|" + (string)((float)numsels / (float)fullbar);
+        } else {
+            data += "|0.0";
+        }
+        
+        llMessageLinked(LINK_SET, SLOODLE_CHANNEL_OBJECT_CHOICE, data, NULL_KEY);
+    }
+}
+
+// Request an update of the choice status.
+// Returns the HTTP key.
+key request_status()
+{
+    // Send a request to select the option
+    string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+    body += "&sloodlepwd=" + sloodlepwd;
+    body += "&sloodlemoduleid=" + (string)sloodlemoduleid;
+    
+    return llHTTPRequest(sloodleserverroot + SLOODLE_CHOICE_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+}
+
+
+///// STATES /////
+
+// Default state - waiting for configuration
+default
+{
+    state_entry()
+    {
+        // Starting again with a new configuration
+        llSetText("", <0.0,0.0,0.0>, 0.0);
+        isconfigured = FALSE;
+        eof = FALSE;
+        // Reset our data
+        sloodleserverroot = "";
+        sloodlepwd = "";
+        sloodlecontrollerid = 0;
+        sloodlemoduleid = 0;
+        sloodlerefreshtime = 0;
+        sloodleobjectaccessleveluse = 0;
+        sloodleserveraccesslevel = 0;
+        // Reset our display
+        send_reset();
+    }
+    
+    link_message( integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Split the message into lines
+            list lines = llParseString2List(str, ["\n"], []);
+            integer numlines = llGetListLength(lines);
+            integer i = 0;
+            for (; i < numlines; i++) {
+                isconfigured = sloodle_handle_command(llList2String(lines, i));
+            }
+            
+            // If we've got all our data AND reached the end of the configuration data, then move on
+            if (eof == TRUE) {
+                if (isconfigured == TRUE) {
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configurationreceived", [], NULL_KEY, "");
+                    state ready;
+                } else {
+                    // Go all configuration but, it's not complete... request reconfiguration
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configdatamissing", [], NULL_KEY, "");
+                    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:reconfigure", NULL_KEY);
+                    eof = FALSE;
+                }
+            }
+        }
+    }
+    
+    touch_start(integer num_detected)
+    {
+        // Attempt to request a reconfiguration
+        if (llDetectedKey(0) == llGetOwner()) {
+            llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:requestconfig", NULL_KEY);
+        }
+    }
+}
+
+state ready
+{
+    on_rez( integer param)
+    {
+        state default;
+    }
+    
+    state_entry()
+    {
+        // Start by requesting an update
+        httpstatus = request_status();
+        httpselect = [];
+        
+        // If we've been given a refresh timer, then use it
+        llSetTimerEvent(0.0);
+        if (sloodlerefreshtime > 0) {
+            // Validate the value - shouldn't check more often than every 10 seconds
+            if (sloodlerefreshtime < 10) sloodlerefreshtime = 10;
+            llSetTimerEvent((float)sloodlerefreshtime);
+        }
+    }
+    
+    timer()
+    {
+        // Request another status update
+        httpstatus = request_status();
+    }
+    
+    touch_start(integer total_number)
+    {
+        // Request another status update (but only if it this exact prim which was touched)
+        if (llDetectedLinkNumber(0) == llGetLinkNumber()) {
+            httpstatus = request_status();
+        }
+    }
+    
+    http_response(key id, integer status, list meta, string body)
+    {
+        // Is this a status update?
+        if (id == httpstatus) {
+            httpstatus = NULL_KEY;
+            //sloodle_debug("HTTP response: " + body);
+            
+            // Make sure the HTTP response was OK
+            if (status != 200) {
+                sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,status); //send message to error_message.lsl
+                return;
+            }
+            
+            // Parse the response data
+            list lines = llParseStringKeepNulls(body, ["\n"], []);
+            integer numlines = llGetListLength(lines);
+            list statusfields = llParseStringKeepNulls(llList2String(lines, 0), ["|"], []);
+            integer statuscode = (integer)llList2String(statusfields, 0);
+            
+            // Did an error occur?
+            if (statuscode <= 0) {
+                //sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "servererror", [statuscode], NULL_KEY, "");
+                sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,statuscode); //send message to error_message.lsl
+                sloodle_debug(body);
+                return;
+            }
+            
+            // Make sure we have enough body data
+            if (numlines < 5) {
+                sloodle_debug("Not enough response data.");
+                return;
+            }
+            
+            // Extract the necessary choice data
+            choicetext = llList2String(lines, 1) + "\n\"" + llList2String(lines, 2) + "\"";
+            numunanswered = (integer)llList2String(lines, 4);
+            // (There is more data provided that we could use later)
+            
+            // Determine how many options there are.
+            // If there are a different number now than we already had, then reset all our options
+            integer numoptions = numlines - 5;
+            if (numoptions != llGetListLength(optionids)) {
+                send_reset();
+            }
+            
+            // Reset our data
+            optionids = [];
+            optiontexts = [];
+            optionselections = [];
+            
+            // Go through each option
+            integer i = 5;
+            list fields = [];
+            for (; i < numlines; i++) {
+                // Parse the option data
+                fields = llParseStringKeepNulls(llList2String(lines, i), ["|"], []);
+                if (llGetListLength(fields) >= 3) {
+                    optionids += [(integer)llList2String(fields, 0)];
+                    optiontexts += [llList2String(fields, 1)];
+                    optionselections += [(integer)llList2String(fields, 2)];
+                }
+            }
+            
+            sloodle_debug("Number of options received: " + (string)llGetListLength(optionids));
+            
+            // Update all our components
+            send_update();
+            
+            return;
+        }
+        
+        // Is this a selection response?
+        integer pos = llListFindList(httpselect, [id]);
+        if (pos >= 0) {
+            httpselect = llDeleteSubList(httpselect, pos, pos);
+            
+            // Make sure the HTTP response was OK
+            if (status != 200) {
+                sloodle_debug("HTTP request failed with status code " + (string)status);
+                return;
+            }
+            
+            // Parse the response
+            list lines = llParseStringKeepNulls(body, ["\n"], []);
+            integer numlines = llGetListLength(lines);
+            list statusfields = llParseStringKeepNulls(llList2String(lines, 0), ["|"], []);
+            integer numstatusfields = llGetListLength(statusfields);
+            if (numstatusfields < 7) return;
+            
+            // Extract the relevant data
+            integer statuscode = (integer)llList2String(statusfields, 0);
+            key uuid = (key)llList2String(statusfields, 6);
+            string name = llKey2Name(uuid);
+            
+            // Did an error occur?
+            if (statuscode == -10011) sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "noupdate", [name], NULL_KEY, "choice");
+            else if (statuscode == -10012) sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "maxselections", [name], NULL_KEY, "choice");
+            else if (statuscode == -10013) sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "notopen", [name], NULL_KEY, "choice");
+            else if (statuscode == -10014) sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "closed", [name], NULL_KEY, "choice");
+            else if (statuscode == -10016) sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "selectionerror", [name], NULL_KEY, "choice");
+            else if (statuscode <= 0) {
+                //    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "servererror", [statuscode], NULL_KEY, "");
+                sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,statuscode); //send message to error_message.lsl
+            }
+            if (statuscode <= 0) {
+                sloodle_debug(body);
+                return;
+            }
+            
+            // What was the nature of the selection?
+            if (statuscode == 10012) sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "selectionupdated", [name], NULL_KEY, "choice");
+            else if (statuscode == 10013) sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "selectionalreadymade", [name], NULL_KEY, "choice");
+            else sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "selectionmade", [name], NULL_KEY, "choice");
+            
+            // Make sure to update the status
+            httpstatus = request_status();
+            return;
+        }
+    }
+    
+    link_message(integer sender_num, integer num, string sval, key kval)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_CHOICE) {
+            // Parse the string
+            list parts = llParseString2List(sval, ["|"], []);
+            integer numparts = llGetListLength(parts);
+            string cmd = llList2String(parts, 0);
+            
+            // Check the command
+            if (cmd == SLOODLE_CHOICE_SELECT_OPTION && kval != NULL_KEY && numparts > 1) {
+                // Determine which option ID is being selected
+                integer optionnum = (integer)llList2String(parts, 1);
+                if (optionnum < 0 || optionnum >= llGetListLength(optionids)) return;
+                integer optionid = llList2Integer(optionids, optionnum);
+                string name = llKey2Name(kval);
+                
+                sloodle_debug("Selecting option ID " + (string)optionid + " for " + name);
+                
+                // Send a request to select the option
+                string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+                body += "&sloodlepwd=" + sloodlepwd;
+                body += "&sloodlemoduleid=" + (string)sloodlemoduleid;
+                body += "&sloodleuuid=" + (string)kval;
+                body += "&sloodleavname=" + llEscapeURL(name);
+                body += "&sloodleserveraccesslevel=" + (string)sloodleserveraccesslevel;
+                body += "&sloodleoptionid=" + (string)optionid;
+                
+                key newhttp = llHTTPRequest(sloodleserverroot + SLOODLE_CHOICE_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+                httpselect += [newhttp];
+            }
+            
+        } else if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            if (sval == "do:reset") llResetScript();
+        }
+    }
+}
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/choice-1.0/objects/default/assets/sloodle_mod_choice-1.0.lslp 

BIN
iar/assets/3bd547dc-3ab0-4b6f-811b-4b15def62202_texture.jp2


BIN
iar/assets/3e5cdbe2-678f-4708-a69a-506f15335b3e_texture.jp2


+ 143 - 0
iar/assets/424d4a18-96f5-408a-9a29-7257a0691e6d_notecard.txt

@@ -0,0 +1,143 @@
+Linden text version 2
+{
+LLEmbeddedItems version 1
+{
+count 1
+{
+ext char index 0
+	inv_item	0
+	{
+		item_id	a15011f9-3add-f3ff-74d2-5ba63c28ed21
+		parent_id	f7658828-21d2-4fec-bc4d-b76d8c8449f8
+	permissions 0
+	{
+		base_mask	7fffffff
+		owner_mask	7fffffff
+		group_mask	7fffffff
+		everyone_mask	7fffbfff
+		next_owner_mask	7fffffff
+		creator_id	2102f5ab-6854-4ec3-aec5-6cd6233c31c6
+		owner_id	2102f5ab-6854-4ec3-aec5-6cd6233c31c6
+		last_owner_id	00000000-0000-0000-0000-000000000000
+		group_id	00000000-0000-0000-0000-000000000000
+	}
+		asset_id	82af2152-8d1d-6002-841d-537944c010f3
+		type	notecard
+		inv_type	notecard
+		flags	00000000
+	sale_info	0
+	{
+		sale_type	not
+		sale_price	10
+	}
+		name	SLOODLE FREEMAIL BLOGGER|
+		desc	2009-04-06 13:30:11 note card|
+		creation_date	1239057040
+	}
+}
+}
+Text length 9677
+SLOODLE TOOLBAR 0.4
+************************************************************************************************
+For updated information, please visit our wiki: http://slisweb.sjsu.edu/sl/index.php/Sloodle_Toolbar
+
+Summary
+************************************************************************************************
+The Sloodle Toolbar is a 'HUD object' (Heads-Up Display). This means it will be displayed as an interface item on your screen, with buttons you can interact with. The latest version has 3 main functions: blog, gestures, and AviLister.
+
+NOTE
+************************************************************************************************
+A NEW BLOGGING TOOL - FREEMAIL BLOGGER was released in the 0.4 version of the Sloodle Set, and is an alternate way to submit blogs than this SLOODLE Toolbar.  For more information - see: 􀀀
+
+Compatibility
+************************************************************************************************
+The Sloodle Toolbar is independent of the other Sloodle tools, and its compatibility is shown in the table below. You can see the version number of the Toolbar in the object name, such as "Sloodle Toolbar v1.2", where "1.2" is the version number. For Sloodle and Moodle versions, see Sloodle Versions.
+
+DETAILS
+************************************************************************************************
+The main purpose of the Toolbar is to let you write blog entries to the Moodle site. To do that, make sure the "Blog HUD" is visible (if not, click the "Blog" tab at the top). To start your entry, click the button which says "Click here to start". You then chat your entry subject and press enter. Next, chat your blog body, and press enter. As of version 1.3, you can use as many chat messages as you like to write your blog body, up to a total limit of 1000 characters -- you will see the progress meter at the bottom fill up as you chat more.
+
+When you have chatted the subject and body, they should both appear on the Toolbar itself. The ends of the messages may be cut-off, because not much text can fit, but they should be visible. You can then press "Save changes" to send your entry to the Moodle site, or "Cancel" to reset it.
+
+
+
+Advanced options
+************************************************************************************************
+When you have mastered the basics of writing a blog entry, there are two advanced options you can use. The first is the channel number, which is available on version 1.3 and later -- you can click "Channel" to select which chat channel you would like to use. Select 0 for the normal public chat, and 1 or 2 if you would like privacy. To chat on channels 1 or 2, start your chat messages with /1 or /2, like this:
+
+/1 This is my blog entry
+
+The other advanced option is only available as of version 1.4 -- it is the visibility setting. You will see "Site", "Public" or "Private" displayed on the blog HUD... click it to get a menu of options, and select which visibility setting you want. "Site" will make your entry visible to anybody registered on the site, "Public" can be viewed by anybody (including guest users of the site), and "Private" can only be viewed by you.
+
+
+Viewing
+************************************************************************************************
+The default visibility setting for blog entries is "site". You can view "site" and "public" entries by visiting your Moodle site's frontpage, and putting "/blog" after it. For example, the Sloodle.org blog entries are visible here:
+
+http://www.sloodle.org/blog
+
+To view private blog entries, login to your Moodle site, and click your name at the top-right to visit your user profile. You should then see a tab at the top saying "Blog" -- click it to read your private (or 'draft') entries.
+
+
+Gestures
+************************************************************************************************
+The classroom gestures is a series of icons. If you cannot see them on the Toolbar, then click the "Classroom Gestures" tab at the top. Click on each icon to perform that gesture/animation. Note that some animation are toggled (click once to turn on, and once again to turn off), while others will happen once when you click them.
+
+
+AviLister
+************************************************************************************************
+The "AviLister" button was introduced in version 1.3, and when clicked, it will scan the local area for avatars (up to a maximum of 16). It will then send the list of avatar names to your Moodle site, and request their Moodle names. (In many cases, the Moodle name will be the real name). The association of avatar to Moodle names will then be chatted back to you (in owner chat, so that only you can see it).
+
+The AviLister button should be visible at the top-right of your Toolbar. If it is red, then it has not been configured yet, or your Moodle site does not support it (this will happen with Sloodle 0.2 or earlier when using Toolbar v1.3). When the AviLister button is white, it is ready for use, and when it is blue/purple, it is scanning the area.
+
+
+Minimizing
+************************************************************************************************
+If you find that the Toolbar takes up too much space on your screen, you can minimize it by clicking on the box with a dash through it at the top right. It will then be reduced to a simple Sloodle logo (white with 2 circles). Click that logo to make the Toolbar visible again. (Note: this feature is only available as of Toolbar v1.3).
+
+Reset
+************************************************************************************************
+When using Toolbar v1.4, it is sometimes necessary to reset the Toolbar completely. For example, if you want to change the URL (especially if you are/were using a URL in the description field). A complete reset can be achieved by clicking the cross button at the top right (it should be a red box with a white cross through it). Note that you will need to re-authorise the Toolbar after this. Before attempting it, try detaching and re-attaching it.
+
+
+Configuration
+************************************************************************************************
+The configuration method for the Toolbar has changed between versions, so please be sure to select which version is right for you:
+Version 1.4
+
+Sloodle Versions: 0.3 (?)
+
+Unlike all the other Sloodle tools, the Toolbar needs to be configured for each individual user. As of Sloodle 0.3, a new concept, known as user-centric authorization, has been developed. This allows each user to authorize their own toolbar, without having to rely on a teacher to pre-configure it. However, it is useful if the teacher does a small amount of pre-configuration.
+
+Optionally, before giving copies of the Toolbar out to students, the teacher can right-click it in his/her inventory, and select "Properties". It is advisable to enter a name which identifies your school or class in the name of the Toolbar, and then enter the URL of your Moodle site in the object's description. This should start with "http" but not have a trailing slash (/) at the end. Press Enter and close the properties window. The Toolbar can then be given out.
+
+
+When an avatar first attaches the Toolbar, it will check its Description field for the URL. If it is not present, then the user will need to chat it on channel 0 or 1. Thereafter, it will give the user a URL which s/he should load in their browser and login to Moodle if necessary. It will then report that the Toolbar has been authorised. Go back to Second Life, and wait a few seconds, or click an empty area on the surface of the Toolbar, and it should detect that it has been authorized, and configure itself ready for use.
+
+Note: as part of the process, the Toolbar will also register your avatar if necessary.
+
+
+Known Problems
+************************************************************************************************
+If you use an avatar which has been registered to a Moodle account, but then attempt to authorise your Toolbar using a different Moodle login, then the page in your browser will report the following error: "Expected parameter 'sloodleuuid'". This issue error message will hopefully be made more meaningful in future releases!
+
+
+ Versions 1.2 and 1.3
+************************************************************************************************
+Sloodle Versions: 0.2, 0.21 (?)
+
+These versions of the Toolbar rely on a basic 'sloodle_config' notecard, containing the URL of the Moodle site and the site's Prim Password. Due to a glitch in the scripts, it also requires a course number, but that value is ignored. The contents of the notecard should as follows:
+
+sloodleserverroot|http://www.sloodle.org
+sloodlepwd|123456789
+sloodle_courseid|1
+
+Replace the URL and prim password with the relevant values for your site, or use the notecard setup page on your site to generate all the text for you. Place the notecard into the Toolbar, making sure the notecard is called "sloodle_config". Ensure Copy/Modify permissions on the notecard are disabled, and that the Modify permission on the Toolbar itself is disabled, to prevent people stealing your prim password. You can then give out copies of the Toolbar to your students.
+
+
+Earlier Versions
+************************************************************************************************
+Sloodle Versions: 0.1x (?)
+
+Old versions of the Toolbar relied on their own name/format of configuration notecard. You are highly advised not to use a Sloodle installation as old as this, but if you need to, then please request the information on our forums at Sloodle.org. }
+

BIN
iar/assets/46538c19-3ccd-434e-a32a-b9e7126a1528_texture.jp2


BIN
iar/assets/4901aa6f-e258-4e9d-b5b4-a54dd7a0de3f_texture.jp2


BIN
iar/assets/49356f8d-19a2-4a75-aed8-cfe471b32d1d_texture.jp2


BIN
iar/assets/496a64a8-ca72-41c4-a3db-d3db4fd9866d_texture.jp2


BIN
iar/assets/49add369-c134-4190-a367-a8c319f25262_texture.jp2


BIN
iar/assets/4a5e0f0e-5ec8-4709-897a-4d52f07b8848_texture.jp2


+ 72 - 0
iar/assets/4c43d94a-d657-8238-e9e7-9f01ce60ceff_script.lsl

@@ -0,0 +1,72 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle parallel URL loader
+// Allows the loading of a single URL on a specified channel.
+// (NOTE: should be in the same prim as a "sloodle_multi_url_loader.lsl" script)
+// Part of the Sloodle project (www.sloodle.org)
+//
+// Copyright (c) 2007 Sloodle (various contributors)
+// Released under the GNU GPL
+//
+// Contributors:
+//  Peter R. Bloomfield
+//
+
+//
+// When receiving a link message, this script will load a URL for a given user.
+// The URL should be in the string, and the user specified by their key.
+// The integer number in the link message should be SLOODLE_CHANNEL_OBJECT_LOAD_URL
+//
+// NOTE: you MUST customize the "MY_CHANNEL_INDEX" value to indicate which script number this is.
+//  Each of these scripts in a given object should have a unique channel index.
+//  This identifies where the object appears in the sequence.
+//  Channel indices should be numbered sequentially from 0.
+//  It is recommended that you replace the "x" in the script name to correspond to the channel index.
+
+
+///// DATA /////
+
+// The index of the channel this script will receive requests on
+// (NOTE: corresponds to indices in the list below)
+integer MY_CHANNEL_INDEX = 2;
+
+
+// OUTGOING link message numbers for parallel load requests
+list SLOODLE_CHANNEL_LIST_LOAD_URL_x =  [
+                                        -1699000001, //SLOODLE_CHANNEL_LOAD_URL_0
+                                        -1699000002, //SLOODLE_CHANNEL_LOAD_URL_1
+                                        -1699000003, //SLOODLE_CHANNEL_LOAD_URL_2
+                                        -1699000004, //SLOODLE_CHANNEL_LOAD_URL_3
+                                        -1699000005, //SLOODLE_CHANNEL_LOAD_URL_4
+                                        -1699000006, //SLOODLE_CHANNEL_LOAD_URL_5
+                                        -1699000007, //SLOODLE_CHANNEL_LOAD_URL_6
+                                        -1699000008, //SLOODLE_CHANNEL_LOAD_URL_7
+                                        -1699000009, //SLOODLE_CHANNEL_LOAD_URL_8
+                                        -1699000010  //SLOODLE_CHANNEL_LOAD_URL_9
+                                        ];
+
+///// ---- /////
+
+default
+{
+    state_entry()
+    {
+        if (MY_CHANNEL_INDEX < 0 || MY_CHANNEL_INDEX > llGetListLength(SLOODLE_CHANNEL_LIST_LOAD_URL_x)) {
+            llOwnerSay("WARNING: script \"" + llGetScriptName() + "\" has an invalid channel index. Please alter value \"MY_CHANNEL_INDEX\".");
+        }
+    }
+    
+    link_message( integer sender_num, integer msg_num, string str, key id )
+    {
+        // Ignore this message if the variables are empty
+        if (str == "" || id == NULL_KEY) return;
+        // If this message is not on the correct channel, then ignore it
+        if (msg_num != llList2Integer(SLOODLE_CHANNEL_LIST_LOAD_URL_x, MY_CHANNEL_INDEX)) return;
+        
+        // Load the URL
+        llLoadURL(id, "", str);
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: assets/sloodle_parallel_url_loader_2.lslp 

BIN
iar/assets/4cf64d18-4186-4c42-a1ee-089bbb8ba0c0_animation.bvh


+ 344 - 0
iar/assets/4d9d75f2-767e-9d59-15b0-ec9b9330328f_script.lsl

@@ -0,0 +1,344 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle Password Reset object
+// Allows avatar with auto-registered Moodle accounts to reset their Moodle password from in-world.
+// Part of the Sloodle project (www.sloodle.org)
+//
+// Copyright (c) 2008 Sloodle
+// Released under the GNU GPL v3
+//
+// Contributors:
+//  Peter R. Bloomfield
+//
+
+integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;
+integer SLOODLE_CHANNEL_AVATAR_DIALOG = 1001;
+string SLOODLE_PWRESET_LINKER = "/mod/sloodle/mod/pwreset-1.0/linker.php";
+string SLOODLE_EOF = "sloodleeof";
+
+string SLOODLE_OBJECT_TYPE = "pwreset-1.0";
+
+integer SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC = 0;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_OWNER = 1;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_GROUP = 2;
+
+string sloodleserverroot = "";
+string sloodlecoursename_full = "";
+string sloodlepwd = "";
+integer sloodlecontrollerid = 0;
+integer sloodleobjectaccessleveluse = 0; // Who can use this object?
+integer sloodleobjectaccesslevelctrl = 0; // Who can control this object?
+integer sloodleserveraccesslevel = 0; // Who can use the server resource? (Value passed straight back to Moodle)
+
+integer isconfigured = FALSE; // Do we have all the configuration data we need?
+integer eof = FALSE; // Have we reached the end of the configuration data?
+
+list avatars = []; // A list of avatars with pending requests
+list httprequests = []; // A list of http request keys, corresponding to the "avatars" list
+
+
+///// TRANSLATION /////
+
+// Link message channels
+integer SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST=-1828374651; // this channel is used to send status codes for translation to the error_messages lsl script
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";             // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";           // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";  // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";    // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";         // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";      // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";  // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";     // Recipient avatar should be identified in link message keyval. No output parameters.
+
+// Send a translation request link message
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+///// ----------- /////
+
+
+///// FUNCTIONS /////
+/******************************************************************************************************************************
+* sloodle_error_code - 
+* Author: Paul Preibisch
+* Description - This function sends a linked message on the SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST channel
+* The error_messages script hears this, translates the status code and sends an instant message to the avuuid
+* Params: method - SLOODLE_TRANSLATE_SAY, SLOODLE_TRANSLATE_IM etc
+* Params:  avuuid - this is the avatar UUID to that an instant message with the translated error code will be sent to
+* Params: status code - the status code of the error as on our wiki: http://slisweb.sjsu.edu/sl/index.php/Sloodle_status_codes
+*******************************************************************************************************************************/
+sloodle_error_code(string method, key avuuid,integer statuscode){
+            llMessageLinked(LINK_SET, SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST, method+"|"+(string)avuuid+"|"+(string)statuscode, NULL_KEY);
+}
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+// Configure by receiving a linked message from another script in the object
+// Returns TRUE if the object has all the data it needs
+integer sloodle_handle_command(string str) 
+{
+    list bits = llParseString2List(str,["|"],[]);
+    integer numbits = llGetListLength(bits);
+    string name = llList2String(bits,0);
+    string value1 = "";
+    string value2 = "";
+    
+    if (numbits > 1) value1 = llList2String(bits,1);
+    if (numbits > 2) value2 = llList2String(bits,2);
+    
+    if (name == "set:sloodleserverroot") sloodleserverroot = value1;
+    if (name == "set:sloodlecoursename_full") sloodlecoursename_full = value1;
+    else if (name == "set:sloodlepwd") {
+        // The password may be a single prim password, or a UUID and a password
+        if (value2 != "") sloodlepwd = value1 + "|" + value2;
+        else sloodlepwd = value1;
+        
+    } else if (name == "set:sloodlecontrollerid") sloodlecontrollerid = (integer)value1;
+    else if (name == "set:sloodleobjectaccessleveluse") sloodleobjectaccessleveluse = (integer)value1;
+    else if (name == "set:sloodleobjectaccesslevelctrl") sloodleobjectaccesslevelctrl = (integer)value1;
+    else if (name == "set:sloodleserveraccesslevel") sloodleserveraccesslevel = (integer)value1;
+    else if (name == SLOODLE_EOF) eof = TRUE;
+    
+    return (sloodleserverroot != "" && sloodlepwd != "" && sloodlecontrollerid > 0);
+}
+
+// Checks if the given agent is permitted to control this object
+// Returns TRUE if so, or FALSE if not
+integer sloodle_check_access_ctrl(key id)
+{
+    // Check the access mode
+    if (sloodleobjectaccesslevelctrl == SLOODLE_OBJECT_ACCESS_LEVEL_GROUP) {
+        return llSameGroup(id);
+    } else if (sloodleobjectaccesslevelctrl == SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC) {
+        return TRUE;
+    }
+    
+    // Assume it's owner mode
+    return (id == llGetOwner());
+}
+
+// Checks if the given agent is permitted to user this object
+// Returns TRUE if so, or FALSE if not
+integer sloodle_check_access_use(key id)
+{
+    // Check the access mode
+    if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_GROUP) {
+        return llSameGroup(id);
+    } else if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC) {
+        return TRUE;
+    }
+    
+    // Assume it's owner mode
+    return (id == llGetOwner());
+}
+
+// Initiate a password reset
+sloodle_password_reset(key av)
+{
+    // Start the request
+    string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+    body += "&sloodlepwd=" + sloodlepwd;
+    body += "&sloodleuuid=" + (string)av;
+    body += "&sloodleavname=" + llEscapeURL(llKey2Name(av));
+    body += "&sloodleserveraccesslevel=" + (string)sloodleserveraccesslevel;
+    key newhttp = llHTTPRequest(sloodleserverroot + SLOODLE_PWRESET_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+
+    // Is the avatar already in the list?
+    integer pos = llListFindList(avatars, [av]);
+    if (pos >= 0) {
+        // Yes - replace the entry
+        httprequests = llListReplaceList(httprequests, [newhttp], pos, pos);
+    } else {
+        // No - add a new entry
+        avatars += [av];
+        httprequests += [newhttp];
+    }
+}
+
+// Remove an avatar from the lists
+sloodle_remove_password_reset(key av)
+{
+    // Check for the entry in the list
+    integer pos = llListFindList(avatars, [av]);
+    if (pos >= 0) {
+        avatars = llDeleteSubList(avatars, pos, pos);
+        httprequests = llDeleteSubList(httprequests, pos, pos);
+    }
+}
+
+
+// Default state - waiting for configuration
+default
+{
+    state_entry()
+    {
+        // Starting again with a new configuration
+        llSetText("", <0.0,0.0,0.0>, 0.0);
+        isconfigured = FALSE;
+        eof = FALSE;
+        // Reset our data
+        sloodleserverroot = "";
+        sloodlepwd = "";
+        sloodlecontrollerid = 0;
+        sloodleobjectaccessleveluse = 0;
+        sloodleobjectaccesslevelctrl = 0;
+        sloodleserveraccesslevel = 0;
+    }
+    
+    link_message( integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Split the message into lines
+            list lines = llParseString2List(str, ["\n"], []);
+            integer numlines = llGetListLength(lines);
+            integer i = 0;
+            for (; i < numlines; i++) {
+                isconfigured = sloodle_handle_command(llList2String(lines, i));
+            }
+            
+            // If we've got all our data AND reached the end of the configuration data, then move on
+            if (eof == TRUE) {
+                if (isconfigured == TRUE) {
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configurationreceived", [], NULL_KEY, "");
+                    state ready;
+                } else {
+                    // Got all configuration but, it's not complete... request reconfiguration
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configdatamissing", [], NULL_KEY, "");
+                    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:reconfigure", NULL_KEY);
+                    eof = FALSE;
+                }
+            }
+        }
+    }
+    
+    touch_start(integer num_detected)
+    {
+        // Attempt to request a reconfiguration
+        if (llDetectedKey(0) == llGetOwner()) {
+            llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:requestconfig", NULL_KEY);
+        }
+    }
+}
+
+// Ready to receive requests for password resets
+state ready
+{
+    on_rez( integer param)
+    {
+        state default;
+    }    
+    
+    state_entry()
+    {
+        // Display status
+        if (sloodleserveraccesslevel == 2) {
+            sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.0,1.0,0.0>, 0.9], "pwresetready:course", [sloodleserverroot, sloodlecoursename_full], NULL_KEY, "pwreset");
+        } else if (sloodleserveraccesslevel == 3) {
+            sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.0,1.0,0.0>, 0.9], "pwresetready:staff", [sloodleserverroot, sloodlecoursename_full], NULL_KEY, "pwreset");
+        } else {
+            sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.0,1.0,0.0>, 0.9], "pwresetready:site", [sloodleserverroot], NULL_KEY, "pwreset");
+        }
+    }
+    
+    state_exit()
+    {
+        // Clear status tet
+        llSetText("", <0.0,0.0,0.0>, 0.0);
+    }
+        
+    touch_start( integer total_number)
+    {
+        // Activating this requires access permission
+        if (sloodle_check_access_use(llDetectedKey(0)) == FALSE) {
+            llWhisper(0, "Sorry " + llDetectedName(0) + ". You do not have permission to control this object.");
+            return;
+        }
+        // Do the password reset
+        sloodle_password_reset(llDetectedKey(0));
+    }
+    
+    http_response(key id, integer status, list meta, string body)
+    {
+        // Ignore any unexpected responses
+        integer pos = llListFindList(httprequests, [id]);
+        if (pos < 0) return;
+        // Extract the data
+        key av = llList2Key(avatars, pos);
+        string name = llKey2Name(av);
+        sloodle_remove_password_reset(av);
+        
+        // Check the response status
+        if (status != 200) {
+            sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,status); //send message to error_message.lsl
+            return;
+        }
+        
+        // Check the response body
+        if (body == "") {
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "httpempty", [], NULL_KEY, "");
+            return;
+        }
+        
+        // Parse the response
+        list lines = llParseStringKeepNulls(body, ["\n"], []);
+        integer numlines = llGetListLength(lines);
+        list statusfields = llParseStringKeepNulls(llList2String(lines, 0), ["|"], []);
+        integer statuscode = (integer)llList2String(statusfields, 0);
+        
+        // Check the status code
+        if (statuscode == -341) {
+            // User cannot have their password reset in-world
+            sloodle_translation_request(SLOODLE_TRANSLATE_IM, [], "pwreseterror:hasemail", [name, sloodleserverroot], av, "pwreset");
+            sloodle_debug("ERROR reported in response: " + body);
+            return;
+            
+        } else if (statuscode == -331) {
+            // User cannot use this device
+            sloodle_translation_request(SLOODLE_TRANSLATE_IM, [], "nopermission:use", [name], av, "");
+            return;
+            
+        } else if (statuscode <= 0) {
+            // Error occurred
+            //sloodle_translation_request(SLOODLE_TRANSLATE_IM, [], "pwreseterror:failed:code", [name, statuscode], av, "pwreset");
+            sloodle_error_code(SLOODLE_TRANSLATE_IM, av,statuscode); //send message to error_message.lsl
+            sloodle_debug("ERROR reported in response: " + body);
+            return;
+        }
+        
+        // Check that there are enough lines
+        if (numlines < 2) {
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "badresponseformat", [], NULL_KEY, "");
+            sloodle_debug("ERROR: not enough lines in response: " + body);
+            return;
+        }
+        
+        // Attempt to parse the data line
+        list datafields = llParseStringKeepNulls(llList2String(lines, 1), ["|"], []);
+        if (llGetListLength(datafields) < 2) {
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "badresponseformat", [], NULL_KEY, "");
+            sloodle_debug("ERROR: not enough data fields in response: " + body);
+            return;
+        }
+        
+        // Extract the data items
+        string username = llList2String(datafields, 0);
+        string password = llList2String(datafields, 1);
+        
+        // Inform the user of their new password
+        sloodle_translation_request(SLOODLE_TRANSLATE_IM, [], "pwreset:success", [name, sloodleserverroot, username, password], av, "pwreset");
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/pwreset-1.0/objects/default/assets/sloodle_mod_pwreset-1.0.lslp 

BIN
iar/assets/4f630a4c-fb72-405e-889e-41f2fbab3091_texture.jp2


BIN
iar/assets/4feb0e8b-52cc-4e56-a7cd-2baf903bf817_texture.jp2


BIN
iar/assets/50770476-ba85-4e8a-8cdd-7e4660bc9c6d_sound.ogg


BIN
iar/assets/51262c74-5c4a-437a-b7a9-efb324bfdbf7_texture.jp2


BIN
iar/assets/551a3475-5465-417b-a2e0-977c6118d44b_texture.jp2


BIN
iar/assets/5748decc-f629-461c-9a36-a35a221fe21f_texture.jp2


BIN
iar/assets/5799410c-785d-44de-8412-0397bbab02da_texture.jp2


BIN
iar/assets/59c93ffb-100b-4489-bd8e-9ede0af5a0bf_texture.jp2


+ 309 - 0
iar/assets/5a427f6d-acd8-8e50-20cd-df42e7b6f11c_script.lsl

@@ -0,0 +1,309 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle Scoreboard
+// 
+// Part of the Sloodle project (www.sloodle.org)
+//
+// Copyright (c) 2011-06 contributors (see below)
+// Released under the GNU GPL v3
+//
+// Contributors:
+//  Edmund Edgar
+//  Paul Preibisch
+//
+integer SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST=-1828374651; // this channel is used to send status codes for translation to the error_messages lsl script
+integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;
+integer SLOODLE_CHANNEL_AVATAR_DIALOG = 1001;
+integer SLOODLE_AWARDS_POINTS_CHANGE_NOTIFICATION= 10601;
+integer SLOODLE_CHANNEL_SCOREBOARD_SHARED_MEDIA_SET_ADMIN_URL_CHANNEL= -1639271128; // This is the channel that the scoreboard shouts out its admin URL
+integer SLOODLE_CHANNEL_SCOREBOARD_SHARED_MEDIA_CHANGE_ADMIN_URL_CHANNEL= -1639271129; // This is the channel that the scoreboard shouts out its admin URL WHEN It has changed due to a region event (lost its url etc)
+integer SLOODLE_SCOREBOARD_CONNECT_HUD= -1639271130; // channel which gets sent a linked message by the connect a hud button when it is touched.
+ 
+string SLOODLE_EOF = "sloodleeof";
+
+string SLOODLE_OBJECT_TYPE = "chat-1.0";
+
+integer SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC = 0;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_OWNER = 1; 
+integer SLOODLE_OBJECT_ACCESS_LEVEL_GROUP = 2;
+
+string sloodleserverroot = "";
+string sloodlepwd = "";
+integer sloodlecontrollerid = 0;
+integer sloodlemoduleid = 0;
+integer sloodlelistentoobjects = 0; // Should this object listen to other objects?
+integer sloodleobjectaccessleveluse = 0; // Who can use this object?
+integer sloodleobjectaccesslevelctrl = 0; // Who can control this object?
+integer sloodleserveraccesslevel = 0; // Who can use the server resource? (Value passed straight back to Moodle)
+integer sloodlegroupid = 0;
+integer sloodleshowallcontrollers = 0;
+integer sloodleroundid = 0;
+integer sloodlerefreshtime  = 0;
+
+integer isconfigured = FALSE; // Do we have all the configuration data we need?
+integer eof = FALSE; // Have we reached the end of the configuration data?
+
+integer lastmessagetimestamp = 0;
+integer messagetimestamp = 0;
+ 
+///// TRANSLATION /////
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";             // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";           // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";  // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";    // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";         // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";      // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";  // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";     // Recipient avatar should be identified in link message keyval. No output parameters.
+integer MENU_CHANNEL; //random channel used for dialogs
+integer listenHandle;
+string paramstr;
+string view_url;
+string admin_url;
+
+// Send a translation request link message
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+///// ----------- /////
+
+
+///// FUNCTIONS /////
+integer randInt(integer n)
+{
+     return (integer)llFrand(n + 1);
+}
+
+integer randIntBetween(integer min, integer max)
+{
+    return min + randInt(max - min);
+}
+sloodle_error_code(string method, key avuuid,integer statuscode)
+{
+    llMessageLinked(LINK_SET, SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST, method+"|"+(string)avuuid+"|"+(string)statuscode, NULL_KEY);
+} 
+
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+handle_points_notification(string str) {
+
+    string changeduserid;
+    string newbalance;
+
+    list lines = llParseStringKeepNulls(str,["\n"],[]);
+    integer l;
+   // llOwnerSay("points notification: "+str);
+    for(l=0; l<llGetListLength(lines); l++) {
+        string line = llList2String(lines, l);
+        list bits = llParseStringKeepNulls(line,["|"],[]);
+        integer numbits = llGetListLength(bits);
+        string name = llList2String(bits,0);
+        string value = ""; 
+        if (llGetListLength(bits) > 1) {
+            value = llList2String(bits,1);
+        }
+        if (name == "balance") newbalance = value;
+        if (name == "userid") changeduserid = value;
+        if (name == "lastmessagetimestamp") lastmessagetimestamp = (integer)value;
+        if (name == "messagetimestamp") messagetimestamp = (integer)value;
+    }
+
+    string hash = "#"+changeduserid+"_"+newbalance+"_"+(string)lastmessagetimestamp+"_"+(string)messagetimestamp;
+   // llOwnerSay("About to update scoreboard for "+newbalance+" for user "+changeduserid);
+    update_media(hash);
+    
+    lastmessagetimestamp = messagetimestamp;
+ 
+}
+//update screen    
+update_media(string hash) {
+    
+    string url = view_url+hash;
+    llSetPrimMediaParams( 1, [     PRIM_MEDIA_CURRENT_URL, url,
+                                PRIM_MEDIA_HOME_URL,  url, 
+                                PRIM_MEDIA_AUTO_ZOOM, TRUE, 
+                                PRIM_MEDIA_AUTO_PLAY, TRUE, 
+                                PRIM_MEDIA_PERMS_INTERACT, 
+                                PRIM_MEDIA_PERM_ANYONE ] );  
+    // setup the control screen
+    integer media_control;
+    if ( sloodleobjectaccesslevelctrl == 0 ) media_control = PRIM_MEDIA_PERM_ANYONE;
+    else if ( sloodleobjectaccesslevelctrl == 2 ) media_control = PRIM_MEDIA_PERM_GROUP;
+    else media_control = PRIM_MEDIA_PERM_OWNER;
+    
+    
+}
+
+// Configure by receiving a linked message from another script in the object
+// Returns TRUE if the object has all the data it needs
+integer sloodle_handle_command(string str) 
+{
+
+       // llOwnerSay(str);
+    list bits = llParseString2List(str,["|"],[]);
+    integer numbits = llGetListLength(bits);
+    string name = llList2String(bits,0);
+    string value1 = "";
+    string value2 = "";
+
+    if (numbits > 1) value1 = llList2String(bits,1); 
+    if (numbits > 2) value2 = llList2String(bits,2);
+    
+    if (name == "set:sloodleserverroot") sloodleserverroot = value1;
+    else if (name == "set:sloodlepwd") {
+        // The password may be a single prim password, or a UUID and a password
+        if (value2 != "") sloodlepwd = value1 + "|" + value2;
+        else sloodlepwd = value1;
+        
+    } else if (name == "set:sloodlecontrollerid") sloodlecontrollerid = (integer)value1;
+    else if (name == "set:sloodleobjectaccessleveluse") sloodleobjectaccessleveluse = (integer)value1;
+    else if (name == "set:sloodleserveraccesslevel") sloodleserveraccesslevel = (integer)value1;
+    else if (name == "set:sloodleobjectaccesslevelctrl") sloodleobjectaccesslevelctrl = (integer)value1;    
+    else if (name == "set:sloodlerefreshtime") sloodlerefreshtime = (integer)value1;
+    else if (name == "set:sloodleshowallcontrollers") sloodleshowallcontrollers = (integer)value1;
+    else if (name == "set:sloodlegroupid") sloodlegroupid = (integer)value1;
+    else if (name == "set:sloodleroundid") sloodleroundid = (integer)value1;
+    
+    else if (name == SLOODLE_EOF) eof = TRUE;
+    
+    return (sloodleserverroot != "" && sloodlepwd != "" && sloodlecontrollerid > 0);
+}
+
+// Default state - waiting for configuration
+integer face=4;
+default
+{
+    on_rez( integer param)
+    {
+       llResetScript();
+    }
+    state_entry()
+    {
+     
+        llClearPrimMedia(face);    
+    
+        // Starting again with a new configuration
+        isconfigured = FALSE;
+        eof = FALSE;
+        // Reset our data
+        sloodleserverroot = "";
+        sloodlepwd = "";
+        sloodlecontrollerid = 0;
+        sloodlemoduleid = 0;
+        sloodleobjectaccessleveluse = 0;
+        sloodleobjectaccesslevelctrl = 0;
+        sloodlegroupid = 0;
+        sloodleshowallcontrollers = 0;
+        sloodleroundid = 0;
+        sloodlerefreshtime = 0;
+        
+    }
+    
+    link_message( integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Split the message into lines
+            list lines = llParseString2List(str, ["\n"], []);
+            integer numlines = llGetListLength(lines);
+            integer i = 0;
+            for (i=0; i < numlines; i++) {
+                isconfigured = sloodle_handle_command(llList2String(lines, i));
+            }
+            
+            // If we've got all our data AND reached the end of the configuration data, then move on
+            if (eof == TRUE) {
+                if (isconfigured == TRUE) {
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configurationreceived", [], NULL_KEY, "");
+                    state ready;
+                } else {
+                    // Go all configuration but, it's not complete... request reconfiguration
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configdatamissing", [], NULL_KEY, "");
+                    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:reconfigure", NULL_KEY);
+                    eof = FALSE;
+                }
+            }
+        }
+        
+    }
+    
+    touch_start(integer num_detected)
+    {
+        // Attempt to request a reconfiguration
+        if (llDetectedKey(0) == llGetOwner()) {
+            llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:requestconfig", NULL_KEY);
+        }
+    }
+}
+
+state ready
+{
+    on_rez( integer param)
+    {
+       llResetScript();
+    }    
+    
+    state_entry()
+    {  
+       llClearPrimMedia(face);  
+        paramstr = "&sloodleobjuuid=" + (string)llGetKey();
+        view_url= sloodleserverroot+"/mod/sloodle/mod/scoreboard-1.0/shared_media/index.php?" + paramstr;
+        admin_url =  sloodleserverroot+"/mod/sloodle/mod/scoreboard-1.0/shared_media/index.php?" + paramstr + "&mode=admin";
+        update_media("");
+                                      
+    }
+    
+    state_exit()
+    {
+        llSetTimerEvent(0.0);
+    } 
+        
+ 
+    
+   
+
+    
+    link_message( integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Split the message into lines
+            list lines = llParseString2List(str, ["\n"], []);
+            integer numlines = llGetListLength(lines);
+            integer i = 0;
+            for (i=0; i < numlines; i++) {
+                isconfigured = sloodle_handle_command(llList2String(lines, i));
+            }
+            
+        } else if (num == SLOODLE_AWARDS_POINTS_CHANGE_NOTIFICATION) { // Awards points change notification
+            handle_points_notification( str );
+
+        }else
+        if (num == SLOODLE_SCOREBOARD_CONNECT_HUD){
+               llOwnerSay("Transmitting Scoreboard UUID to Owner's HUD");
+               llRegionSay(SLOODLE_CHANNEL_SCOREBOARD_SHARED_MEDIA_SET_ADMIN_URL_CHANNEL, (string)admin_url+"|"+(string)id+"|"+(string)llGetKey());
+               llShout(SLOODLE_CHANNEL_SCOREBOARD_SHARED_MEDIA_SET_ADMIN_URL_CHANNEL,(string)admin_url+"|"+(string)id+"|"+(string)llGetKey());
+        
+        } 
+    } 
+    
+    
+}
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/scoreboard-1.0/objects/default/assets/sloodle_mod_scoreboard.lslp
+

BIN
iar/assets/5bf8f055-2835-4e4f-8269-047ba8e4c124_texture.jp2


BIN
iar/assets/5cc21038-0a07-4111-88bb-a631f56ca9d3_texture.jp2


BIN
iar/assets/5d778e6b-8dd6-4713-b43b-db3b0f4a1e83_texture.jp2


+ 746 - 0
iar/assets/5fba4668-a2e7-60ce-f7a0-2eb174feab09_script.lsl

@@ -0,0 +1,746 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle PrimDrop (for Sloodle 0.3)
+// Allows students to submit SL objects as Moodle assignments.
+// Part of the Sloodle project (www.sloodle.org)
+//
+// Copyright (c) 2007-8 Sloodle
+// Released under the GNU GPL
+//
+// Contributors:
+//  Jeremy Kemp
+//  Peter R. Bloomfield
+//  Paul Preibisch (Fire Centaur in SL)
+
+
+/// DATA ///
+
+// Sloodle constants
+integer SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST=-1828374651; // this channel is used to send status codes for translation to the error_messages lsl script
+integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;
+integer SLOODLE_CHANNEL_AVATAR_DIALOG = 1001;
+string SLOODLE_PRIMDROP_LINKER = "/mod/sloodle/mod/primdrop-1.0/linker.php";
+string SLOODLE_ASSIGNMENT_VIEW = "/mod/assignment/view.php";
+string SLOODLE_EOF = "sloodleeof";
+integer SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC = 0;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_OWNER = 1;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_GROUP = 2;
+
+string SLOODLE_OBJECT_TYPE = "primdrop-1.0";
+
+
+integer SLOODLE_CHANNEL_PRIMDROP_INVENTORY = -1639270071;
+string PRIMDROP_RECEIVE_DROP = "do:receivedrop"; // Instructs the object to receive a drop
+string PRIMDROP_CANCEL_DROP = "do:canceldrop"; // Cancel drop receiving
+string PRIMDROP_FINISHED_DROP = "set:droppedobject"; // The drop has finished (object name passed as parameter after pipe character)
+
+
+// Configuration settings
+string sloodleserverroot = "";
+string sloodlepwd = "";
+integer sloodlecontrollerid = 0;
+integer sloodlemoduleid = 0;
+integer sloodleobjectaccessleveluse = 0; // Who can use this object?
+integer sloodleobjectaccesslevelctrl = 0; // Who can control this object?
+integer sloodleserveraccesslevel = 0; // Who can use the server resource? (Value passed straight back to Moodle)
+
+// Configuration status
+integer isconfigured = FALSE; // Do we have all the configuration data we need?
+integer eof = FALSE; // Have we reached the end of the configuration data?
+
+// This defines who is currently dropping or rezzing an item
+key current_user = NULL_KEY;
+
+// These lists are used when determining what inventory has been added
+list old_inventory = [];
+list new_inventory = [];
+// The name of the object which is being submitted
+string submit_obj = "";
+
+// HTTP request keys
+key httpcheck = NULL_KEY; // Request used to check the assignment
+key httpsubmit = NULL_KEY; // Request used to submit objects
+
+// Assignment information
+string assignmentname = "";
+string assignmentsummary = "";
+
+// Alternating list of keys, timestamps and page numbers, indicating who activated a dialog and when
+list cmddialog = [];
+
+// Menu button labels
+string MENU_BUTTON_CANCEL = "0";
+string MENU_BUTTON_SUMMARY = "1";
+string MENU_BUTTON_SUBMIT = "2";
+string MENU_BUTTON_ONLINE = "3";
+string MENU_BUTTON_TAKE_ALL = "4";
+
+// List of button labels ('cos otherwise the compiler runs out of memory!)
+//list teacherbuttons = [MENU_BUTTON_SUBMIT, MENU_BUTTON_ONLINE,  MENU_BUTTON_TAKE_ALL,MENU_BUTTON_CANCEL, MENU_BUTTON_SUMMARY];
+ // OpenSim chokes on this
+list teacherbuttons = ["3", "2",  "4", "0", "1"];
+//list userbuttons = [MENU_BUTTON_SUMMARY, MENU_BUTTON_SUBMIT,MENU_BUTTON_ONLINE,MENU_BUTTON_CANCEL];
+list userbuttons = ["1", "2",  "3", "0"];
+
+// The relative position at which items will be rezzed
+vector rez_pos = <0.0, 2.0, 1.0>;
+
+///// TRANSLATION /////
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_SAY = "say";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";    // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";         // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";      // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";  // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";     // Recipient avatar should be identified in link message keyval. No output parameters.
+
+// Send a translation request link message
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+///// ----------- /////
+
+
+/// FUNCTIONS ///
+/******************************************************************************************************************************
+* sloodle_error_code - 
+* Author: Paul Preibisch
+* Description - This function sends a linked message on the SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST channel
+* The error_messages script hears this, translates the status code and sends an instant message to the avuuid
+* Params: method - SLOODLE_TRANSLATE_SAY, SLOODLE_TRANSLATE_IM etc
+* Params:  avuuid - this is the avatar UUID to that an instant message with the translated error code will be sent to
+* Params: status code - the status code of the error as on our wiki: http://slisweb.sjsu.edu/sl/index.php/Sloodle_status_codes
+*******************************************************************************************************************************/
+sloodle_error_code(string method, key avuuid,integer statuscode){
+            llMessageLinked(LINK_SET, SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST, method+"|"+(string)avuuid+"|"+(string)statuscode, NULL_KEY);
+}
+
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+sloodle_reset()
+{
+    llSetText("", <0.0,0.0,0.0>, 0.0);
+    llMessageLinked(LINK_SET, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:reset", NULL_KEY);
+    llResetScript();
+}
+
+// Configure by receiving a linked message from another script in the object
+// Returns TRUE if the object has all the data it needs
+integer sloodle_handle_command(string str) 
+{
+    list bits = llParseString2List(str,["|"],[]);
+    integer numbits = llGetListLength(bits);
+    string name = llList2String(bits,0);
+    string value1 = "";
+    string value2 = "";
+    
+    if (numbits > 1) value1 = llList2String(bits,1);
+    if (numbits > 2) value2 = llList2String(bits,2);
+    
+    if (name == "set:sloodleserverroot") sloodleserverroot = value1;
+    else if (name == "set:sloodlepwd") {
+        // The password may be a single prim password, or a UUID and a password
+        if (value2 != "") sloodlepwd = value1 + "|" + value2;
+        else sloodlepwd = value1;
+        
+    } else if (name == "set:sloodlecontrollerid") sloodlecontrollerid = (integer)value1;
+    else if (name == "set:sloodlemoduleid") sloodlemoduleid = (integer)value1;
+    else if (name == "set:sloodleobjectaccessleveluse") sloodleobjectaccessleveluse = (integer)value1;
+    else if (name == "set:sloodleobjectaccesslevelctrl") sloodleobjectaccesslevelctrl = (integer)value1;
+    else if (name == "set:sloodleserveraccesslevel") sloodleserveraccesslevel = (integer)value1;
+    else if (name == SLOODLE_EOF) eof = TRUE;
+    
+    return (sloodleserverroot != "" && sloodlepwd != "" && sloodlecontrollerid > 0 && sloodlemoduleid > 0);
+}
+
+// Checks if the given agent is permitted to control this object
+// Returns TRUE if so, or FALSE if not
+integer sloodle_check_access_ctrl(key id)
+{
+    // Check the access mode
+    if (sloodleobjectaccesslevelctrl == SLOODLE_OBJECT_ACCESS_LEVEL_GROUP) {
+        return llSameGroup(id);
+    } else if (sloodleobjectaccesslevelctrl == SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC) {
+        return TRUE;
+    }
+    
+    // Assume it's owner mode
+    return (id == llGetOwner());
+}
+
+// Checks if the given agent is permitted to user this object
+// Returns TRUE if so, or FALSE if not
+integer sloodle_check_access_use(key id)
+{
+    // Check the access mode
+    if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_GROUP) {
+        return llSameGroup(id);
+    } else if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC) {
+        return TRUE;
+    }
+    
+    // Assume it's owner mode
+    return (id == llGetOwner());
+}
+
+// Add the given agent to our command dialog list
+sloodle_add_cmd_dialog(key id)
+{
+    // Does the person already exist?
+    integer pos = llListFindList(cmddialog, [id]);
+    if (pos < 0) {
+        // No - add the agent to the end
+        cmddialog += [id, llGetUnixTime()];
+    } else {
+        // Yes - update the time
+        cmddialog = llListReplaceList(cmddialog, [llGetUnixTime()], pos + 1, pos + 1);
+    }
+}
+
+// Remove the given agent from our command dialog list
+sloodle_remove_cmd_dialog(key id)
+{
+    // Is the person in the list?
+    integer pos = llListFindList(cmddialog, [id]);
+    if (pos >= 0) {
+        // Yes - remove them and their timestamp
+        cmddialog = llDeleteSubList(cmddialog, pos, pos + 1);
+    }
+}
+
+// Purge the command dialog list of old activity
+sloodle_purge_cmd_dialog()
+{
+    // Store the current timestamp
+    integer curtime = llGetUnixTime();
+    // Go through each command dialog
+    integer i = 0;
+    while (i < llGetListLength(cmddialog)) {
+        // Is the current timestamp more than 12 seconds old?
+        if ((curtime - llList2Integer(cmddialog, i + 1)) > 12) {
+            // Yes - remove it
+            cmddialog = llDeleteSubList(cmddialog, i, i + 1);
+        } else {
+            // No - advance to the next
+            i += 2;
+        }
+    }
+}
+
+// Does the object have valid permissions?
+// Returns TRUE if so, or FALSE otherwise
+integer valid_perms(string obj)
+{
+    integer perms_owner = llGetInventoryPermMask(obj, MASK_OWNER);
+    integer perms_next = llGetInventoryPermMask(obj, MASK_NEXT);
+    
+    return (!((perms_owner & PERM_COPY) && (perms_owner & PERM_TRANSFER) && (perms_next & PERM_COPY) && (perms_next & PERM_TRANSFER)));
+}
+
+// Returns a list of all inventory
+list get_inventory(integer type)
+{
+    list inv = [];
+    integer num = llGetInventoryNumber(type);
+    integer i = 0;
+    for (i=0; i < num; i++) {
+        if (llGetInventoryName(type, i)!="sloodle_config") //dont give away configuration files!
+            inv += [llGetInventoryName(type, i)];
+    }
+    
+    return inv;
+}
+
+// Checks and validates an inventory drop.
+// Returns TRUE if it is OK, or FALSE if not.
+integer sloodle_check_drop()
+{
+    // Our new object is stored in variable "submit_obj"
+    sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<1.0,0.0,0.0>, 0.9], "assignment:checkingitem", [], NULL_KEY, "assignment");
+    
+    // Make sure it exists
+    if (llGetInventoryType(submit_obj) == INVENTORY_NONE || submit_obj == "") {
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:submissionerror", [], NULL_KEY, "assignment");
+        return FALSE;
+    }
+    
+    // Make sure it is the correct type  
+    // *** Fire Centaur Change January 2010
+    //--- changed this to accept all objects EXCEPT scripts.
+    //if (llGetInventoryType(submit_obj) == INVENTORY_OBJECT) {
+    if (llGetInventoryType(submit_obj) == INVENTORY_SCRIPT) {
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:objectsonly", [], NULL_KEY, "assignment");
+        llRemoveInventory(submit_obj);
+        return FALSE;
+    }
+
+    // Determine the object ID and creator
+    key obj_id = llGetInventoryKey(submit_obj);
+    key obj_creator = llGetInventoryCreator(submit_obj);
+    
+    // Make sure the creator is the expected user
+    if (obj_creator != current_user) {
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:creatoronly", [], NULL_KEY, "assignment");
+        llRemoveInventory(submit_obj);
+        return FALSE;
+    }
+    
+    // Make sure the permissions are correct
+    if (valid_perms(submit_obj)) {
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:invalidperms", [], NULL_KEY, "assignment");
+        llRemoveInventory(submit_obj);
+        return FALSE;
+    }
+
+    // Seems OK - submit it
+    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:itemok", [submit_obj, llKey2Name(current_user)], NULL_KEY, "assignment");
+    return TRUE;
+}
+
+
+/// STATES ///
+
+// Default state - waiting for configuration
+default
+{
+    state_entry()
+    {
+        // Starting again with a new configuration
+        isconfigured = FALSE;
+        eof = FALSE;
+        // Reset our data
+        sloodleserverroot = "";
+        sloodlepwd = "";
+        sloodlecontrollerid = 0;
+        sloodlemoduleid = 0;
+        sloodleobjectaccessleveluse = 0;
+        sloodleobjectaccesslevelctrl = 0;
+        sloodleserveraccesslevel = 0;
+    }
+    
+    link_message( integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Split the message into lines
+            list lines = llParseString2List(str, ["\n"], []);
+            integer numlines = llGetListLength(lines);
+            integer i = 0;
+            for (i=0; i < numlines; i++) {
+                isconfigured = sloodle_handle_command(llList2String(lines, i));
+            }
+            
+            // If we've got all our data AND reached the end of the configuration data, then move on
+            if (eof == TRUE) {
+                if (isconfigured == TRUE) {
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configurationreceived", [], NULL_KEY, "");
+                    state check_assignment;
+                } else {
+                    // Got all configuration but, it's not complete... request reconfiguration
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configdatamissing", [], NULL_KEY, "");
+                    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:reconfigure", NULL_KEY);
+                    eof = FALSE;
+                }
+            }
+        }
+    }
+    
+    touch_start(integer num_detected)
+    {
+        // Attempt to request a reconfiguration
+        if (llDetectedKey(0) == llGetOwner()) {
+            llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:requestconfig", NULL_KEY);
+        }
+    }
+}
+
+// Checking that the assignment is accessible
+state check_assignment
+{
+    state_entry()
+    {
+        // Check the assignment details
+        sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.0,1.0,0.0>, 0.9], "assignment:checking", [], NULL_KEY, "assignment");
+        string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+        body += "&sloodlepwd=" + sloodlepwd;
+        body += "&sloodlemoduleid=" + (string)sloodlemoduleid;
+        httpcheck = llHTTPRequest(sloodleserverroot + SLOODLE_PRIMDROP_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+        
+        llSetTimerEvent(0.0);
+        llSetTimerEvent(8.0);
+    }
+    
+    state_exit()
+    {
+        llSetTimerEvent(0.0);
+        httpcheck = NULL_KEY;
+        llSetText("", <0.0,0.0,0.0>, 0.0);
+    }
+    
+    timer()
+    {
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "httptimeout", [], NULL_KEY, "");
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "resetting", [], NULL_KEY, "");
+        sloodle_reset();
+    }
+    
+    http_response(key id, integer status, list meta, string body)
+    {
+        // Is this the expected data?
+        if (id != httpcheck) return;
+        httpcheck = NULL_KEY;
+        // Check that we got a proper response
+        if (status != 200) {
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "httperror:code", [status], NULL_KEY, "");
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "resetting", [], NULL_KEY, "");
+            sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,status); //send message to error_message.lsl
+            sloodle_reset();
+            return;
+        }
+        if (body == "") {
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "httpempty", [], NULL_KEY, "");
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "resetting", [], NULL_KEY, "");
+            sloodle_reset();
+            return;
+        }
+        
+        // Split the data up into lines
+        list lines = llParseStringKeepNulls(body, ["\n"], []);  
+        integer numlines = llGetListLength(lines);
+        // Extract all the status fields
+        list statusfields = llParseStringKeepNulls( llList2String(lines,0), ["|"], [] );
+        // Get the statuscode
+        integer statuscode = llList2Integer(statusfields,0);
+        
+        // Was it an error code?
+        if (statuscode == -601) {
+            // Failed to connect to the assignment, possibly because it is the wrong type, or because it is invisible
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:connectionfailed", [], NULL_KEY, "assignment");
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "resetting", [], NULL_KEY, "");
+            sloodle_reset();
+            return;
+            
+        } else if (statuscode <= 0) {
+            // Get the error message if one was given
+            if (numlines > 1) {
+                string errmsg = llList2String(lines, 1);
+                sloodle_debug("ERROR " + (string)statuscode + ": " + errmsg);
+            }
+            //sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "servererror", [statuscode], NULL_KEY, "");
+            sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,statuscode); //send message to error_message.lsl
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "resetting", [], NULL_KEY, "");
+            sloodle_reset();
+            return;
+        }
+        
+        // Extract the assignment information
+        assignmentname = llList2String(lines, 1);
+        assignmentsummary = llList2String(lines, 2);
+        llSay(0, assignmentsummary);
+        
+        state ready;
+    }
+    
+    on_rez(integer param)
+    {
+        state default;
+    }
+}
+
+
+// Ready to be used
+state ready
+{
+    state_entry()
+    {
+        // Display summary information
+        sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<1.0,0.5,0.0>, 1.0], "assignment:ready", [assignmentname], NULL_KEY, "assignment");
+        
+        // Listen for dialog commands from any avatar
+        llListen(SLOODLE_CHANNEL_AVATAR_DIALOG, "", NULL_KEY, "");
+        
+        // Regularly purge the list of dialog user entries
+        llSetTimerEvent(0.0);
+        llSetTimerEvent(12.0);
+        
+        // Clear our current user, to avoid any confusion
+        current_user = NULL_KEY;
+    }
+    
+    state_exit()
+    {
+        llSetTimerEvent(0.0);
+        llSetText("", <0.0,0.0,0.0>, 0.0);
+    }
+    
+    touch_start(integer num_detected)
+    {
+        // Go through each toucher
+        integer i = 0;
+        key id = NULL_KEY;
+        integer level = 0;
+        for (i=0; i < num_detected; i++) {
+            id = llDetectedKey(i);
+            // Can this avatar use and/or control this item?
+            if (sloodle_check_access_ctrl(id)) level = 2;
+            else if (sloodle_check_access_use(id)) level = 1;
+            // Show the appropriate menu, or report the lack of permission
+            if (level == 2) {
+                // Teacher menu
+                sloodle_add_cmd_dialog(id);
+                sloodle_translation_request(SLOODLE_TRANSLATE_DIALOG, [SLOODLE_CHANNEL_AVATAR_DIALOG] + teacherbuttons, "assignment:primdropteachermenu", [0,1,2,3,4], id, "assignment");
+            } else if (level == 1) {
+                // General user menu
+                sloodle_add_cmd_dialog(id);
+                sloodle_translation_request(SLOODLE_TRANSLATE_DIALOG, [SLOODLE_CHANNEL_AVATAR_DIALOG] + userbuttons, "assignment:primdropmenu", [0,1,2,3], id, "assignment");
+            } else {
+                // Report the lack of permission
+                sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "nopermission:use", [llDetectedName(i)], NULL_KEY, "");
+            }
+        }
+    }
+
+    listen(integer channel, string name, key id, string msg)
+    {
+        // Check the channel
+        if (channel == SLOODLE_CHANNEL_AVATAR_DIALOG) {
+            // Ignore non-avatars
+            if (llGetOwnerKey(id) != id) return;
+            // Make sure we are listening to this user
+            if (llListFindList(cmddialog, [id]) < 0) return;
+            sloodle_remove_cmd_dialog(id);
+            
+            // Make sure the given user is allowed to use this object
+            if (!sloodle_check_access_use(id)) {
+                sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "nopermission:use", [name], NULL_KEY, "");
+                return;
+            }
+            // Check if the user can control this item
+            integer canctrl = sloodle_check_access_ctrl(id);
+            
+            // Store the user
+            current_user = id;
+            
+            // Check the command            
+            if (msg == MENU_BUTTON_CANCEL) {
+                // Cancel the menu
+                // Nothing to do
+                return;
+                
+            } else if (msg == MENU_BUTTON_SUMMARY) {
+                // Chat the assignment summary text
+                llSay(0, assignmentsummary);
+                
+            } else if (msg == MENU_BUTTON_SUBMIT) {
+                // Wait for a drop
+                state drop;
+            
+            } else if (msg == MENU_BUTTON_ONLINE) {
+                // Give the user a URL
+                llLoadURL(id, assignmentname, sloodleserverroot + SLOODLE_ASSIGNMENT_VIEW + "?id=" + (string)sloodlemoduleid);
+            
+            } else if (msg == MENU_BUTTON_TAKE_ALL && canctrl) {
+                // User wants to take all objects to their inventory
+                list inv;
+                inv+= get_inventory(INVENTORY_ANIMATION);
+                inv+= get_inventory(INVENTORY_GESTURE);
+                inv+= get_inventory(INVENTORY_LANDMARK);
+                inv+= get_inventory(INVENTORY_NOTECARD);
+                inv+= get_inventory(INVENTORY_OBJECT);
+                
+                
+                if (inv == []) {
+                    // No submissions available
+                    sloodle_translation_request(SLOODLE_TRANSLATE_IM, [], "assignment:nosubmissions", [], id, "assignment");
+                } else {
+                    // Give all items into a new folder
+                    llGiveInventoryList(id, assignmentname, inv);
+                    sloodle_translation_request(SLOODLE_TRANSLATE_IM, [], "assignment:allgiven", [assignmentname], id, "assignment");
+                }
+            }
+        }
+    }
+    
+    on_rez(integer param)
+    {
+        state default;
+    }
+}
+
+// Waiting for an object to be dropped
+state drop
+{
+    state_entry()
+    {
+        // Instruct the inventory manager to receive a drop
+        llMessageLinked(LINK_SET, SLOODLE_CHANNEL_PRIMDROP_INVENTORY, PRIMDROP_RECEIVE_DROP, NULL_KEY);
+    
+        // Prepare to receive a submission
+        sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.0,0.5,1.0>, 1.0], "assignment:waitingforsubmission", [llKey2Name(current_user)], NULL_KEY, "assignment");
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:dropsubmission", [llKey2Name(current_user)], NULL_KEY, "assignment");
+        
+        // Allow the user 60 seconds to make their submission
+        llSetTimerEvent(0.0);
+        llSetTimerEvent(60.0);
+    }
+    
+    state_exit()
+    {
+        llSetTimerEvent(0.0);
+    }
+    
+    timer()
+    {
+        // Submission timed-out
+        llSetTimerEvent(0.0);
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:submittimeout", [llKey2Name(current_user)], NULL_KEY, "assignment");
+        llMessageLinked(LINK_SET, SLOODLE_CHANNEL_PRIMDROP_INVENTORY, PRIMDROP_CANCEL_DROP, NULL_KEY);
+        state ready;
+    }
+    
+    link_message(integer sender_num, integer num, string sval, key kval)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_PRIMDROP_INVENTORY) {
+            // Split the message
+            list parts = llParseStringKeepNulls(sval, ["|"], []);
+            if (llGetListLength(parts) < 2) return;
+            string cmd = llList2String(parts, 0);
+            string val = llList2String(parts, 1);
+            // Check the command
+            if (cmd == PRIMDROP_FINISHED_DROP) {
+                // Cancel the timeout
+                llSetTimerEvent(0.0);
+                // Store the submitted object and check it
+                submit_obj = val;
+                if (sloodle_check_drop()) state submitting;
+                else state ready;
+            }
+        }
+    }
+    
+    on_rez(integer param)
+    {
+        state default;
+    }
+}
+
+// Submitting an object which was dropped
+state submitting
+{
+    state_entry()
+    {
+        if (submit_obj == "") {
+            llSay(0, "ERROR: no object to submit.");
+            state ready;
+            return;
+        }
+        
+        // Check the assignment details
+        sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<1.0,0.0,0.0>, 0.9], "assignment:submitting", [llKey2Name(current_user)], NULL_KEY, "assignment");
+        
+        // Build the body of data
+        string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+        body += "&sloodlepwd=" + sloodlepwd;
+        body += "&sloodlemoduleid=" + (string)sloodlemoduleid;
+        body += "&sloodleuuid=" + (string)current_user;
+        body += "&sloodleavname=" + llEscapeURL(llKey2Name(current_user));
+        body += "&sloodleserveraccesslevel=" + (string)sloodleserveraccesslevel;
+        body += "&sloodleobjname=" + submit_obj;
+        body += "&sloodleprimcount=" + (string)llGetObjectPrimCount(llGetInventoryKey(submit_obj));
+        body += "&sloodleprimdropname=" + llGetObjectName();
+        body += "&sloodleprimdropuuid=" + (string)llGetKey();
+        body += "&sloodleregion=" + llGetRegionName();
+        body += "&sloodlepos=" + (string)llGetPos();
+        // Send the HTTP request
+        httpsubmit = llHTTPRequest(sloodleserverroot + SLOODLE_PRIMDROP_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+        llSetTimerEvent(0.0);
+        llSetTimerEvent(8.0);
+    }
+    
+    state_exit()
+    {
+        llSetTimerEvent(0.0);
+        httpsubmit = NULL_KEY;
+        llSetText("", <0.0,0.0,0.0>, 0.0);
+    }
+    
+    timer()
+    {
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "httptimeout", [], NULL_KEY, "");
+        state ready;
+    }
+    
+    http_response(key id, integer status, list meta, string body)
+    {
+        // Is this the expected data?
+        if (id != httpsubmit) return;
+        httpsubmit = NULL_KEY;
+        // Check that we got a proper response
+        if (status != 200) {
+            sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,status); //send message to error_message.lsl
+            state ready;
+            return;
+        }
+        if (body == "") {
+            sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "httpempty", [], NULL_KEY, "");
+            state ready;
+            return;
+        }
+        
+        // Split the data up into lines
+        list lines = llParseStringKeepNulls(body, ["\n"], []);  
+        integer numlines = llGetListLength(lines);
+        // Extract all the status fields
+        list statusfields = llParseStringKeepNulls( llList2String(lines,0), ["|"], [] );
+        integer statuscode = llList2Integer(statusfields,0);
+        
+        // Get the user's name
+        string current_user_name = llKey2Name(current_user);
+        
+        // Has an error been reported?
+        if (statuscode < 0) {
+            // Check if it's a known code
+            if (statuscode == -10201)       sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:nopermission", [current_user_name], NULL_KEY, "assignment");
+            else if (statuscode == -10202)  sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:early", [current_user_name], NULL_KEY, "assignment");
+            else if (statuscode == -10203)  sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:late", [current_user_name], NULL_KEY, "assignment");
+            else if (statuscode == -10205)  sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:noresubmit", [current_user_name], NULL_KEY, "assignment");
+            else {
+                 sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:submissionfailed", [current_user_name, statuscode], NULL_KEY, "assignment");
+                 sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,statuscode); //send message to error_message.lsl
+            }
+            
+            // Debug output, if possible
+            if (numlines > 1) {
+                string errmsg = llList2String(lines, 1);
+                sloodle_debug("ERROR " + (string)statuscode + ": " + errmsg);
+            }
+            
+            state ready;
+            return;
+        }
+        
+        // Success
+        sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "assignment:submissionok", [current_user_name], NULL_KEY, "assignment");        
+        state ready;
+    }
+    
+    on_rez(integer param)
+    {
+        state default;
+    }
+}
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/primdrop-1.0/objects/default/assets/sloodle_mod_primdrop-1.0.lslp 
+

+ 143 - 0
iar/assets/60aec86a-180a-2e02-5689-9c6f43f5db25_script.lsl

@@ -0,0 +1,143 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle configuration notecard reader
+// Reads a configuration notecard and transmits the data via link messages to other scripts
+// If the notecard changes, then it automatically resets.
+//
+// Part of the Sloodle project (www.sloodle.org)
+// Copyright (c) 2007-8 Sloodle
+// Released under the GNU GPL v3
+//
+// Contributors:
+//  Edmund Edgar
+//  Peter R. Bloomfield
+
+
+integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;
+string SLOODLE_CONFIG_NOTECARD = "sloodle_config";
+string SLOODLE_EOF = "sloodleeof";
+
+key sloodle_notecard_key = NULL_KEY;
+integer sloodle_notecard_line = 0;
+
+string COMMENT_PREFIX = "//";
+
+key latestnotecard = NULL_KEY; // The most recently read notecard
+string notecarddata = "";
+string httpinurl = "";
+integer isnotecarddone = 0;
+
+string sloodlepwd = "";
+string sloodleserverroot = "";
+string sloodlecontrollerid = "";
+    
+
+string SLOODLE_HTTP_IN_REQUEST_LINKER = "/mod/sloodle/classroom/httpin_config_linker.php";
+integer SLOODLE_CHANNEL_OBJECT_CREATOR_REQUEST_CONFIGURATION_VIA_HTTP_IN_URL = -1639270089; //Object creator telling itself it wants to rez an object at a position (specified as key)
+
+sloodle_start_reading_notecard()
+{
+    // Do we have a configuratio notecard?
+    if (llGetInventoryType(SLOODLE_CONFIG_NOTECARD) == INVENTORY_NOTECARD) {
+        // Start reading it
+        sloodle_notecard_line = 0;
+        sloodle_notecard_key = llGetNotecardLine("sloodle_config", 0); // read the first line. The dataserver event will get the next one.
+        latestnotecard = llGetInventoryKey(SLOODLE_CONFIG_NOTECARD);
+    } else {
+        latestnotecard = NULL_KEY;
+    }
+}
+
+register_config_if_ready()
+{
+    if ( (httpinurl == "") || (isnotecarddone == 0) ) {
+        return;
+    }
+    if ( ( sloodleserverroot == "") || (sloodlepwd == "") ) {
+        return;
+    }
+
+   // llOwnerSay("need to talk to "+sloodleserverroot+" and have them register me and send me my config");
+                
+    //send to httpin_config_linker
+    string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+    body += "&sloodlepwd=" + sloodlepwd;
+    body += "&sloodleobjuuid=" + (string)llGetKey();
+    body += "&childobjectuuid=" + (string)llGetKey();
+    body += "&httpinurl=" + httpinurl;
+    body += "&sloodleobjname=" + llGetObjectName();
+    body += notecarddata;
+    //llOwnerSay("requested config with body "+body); 
+    llHTTPRequest(sloodleserverroot + SLOODLE_HTTP_IN_REQUEST_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);        
+}
+
+default 
+{
+    on_rez(integer start_param)
+    {
+        llResetScript();
+    }
+    
+    state_entry() 
+    {
+        // Pause for a moment, in case all scripts were reset at the same time
+        llSleep(0.2);
+        // Go!
+        sloodle_start_reading_notecard();
+    }
+    
+    dataserver(key requested, string data)
+    {
+        if ( requested == sloodle_notecard_key )  // make sure we are getting the data we want
+        {
+            sloodle_notecard_key = NULL_KEY;
+            if ( data != EOF )
+            {
+                // If this is a comment line, then do not forward it
+                string trimmeddata = llStringTrim(data, STRING_TRIM_HEAD);
+                if (llSubStringIndex(trimmeddata, COMMENT_PREFIX) != 0) {
+                
+                    list bits = llParseString2List(data,["|"],[]);
+                    integer numbits = llGetListLength(bits);
+                    string name = llList2String(bits,0);
+                    string value1 = "";    
+                    if (numbits > 1) value1 = llList2String(bits,1);
+                                    
+                    if (name == "set:sloodleserverroot") sloodleserverroot = value1;
+                    else if (name == "set:sloodlepwd") sloodlepwd = value1;
+                    else if (name == "set:sloodlecontrollerid") sloodlecontrollerid = value1;
+                    else notecarddata = notecarddata + "&" + name + "=" + value1;              
+                
+                }
+            
+                // Advance to the next line
+                sloodle_notecard_line++;
+                sloodle_notecard_key = llGetNotecardLine("sloodle_config",sloodle_notecard_line);
+            } else {
+                isnotecarddone = 1;
+                register_config_if_ready();
+            }
+        }
+    }
+    
+    link_message(integer sender_num, integer num, string str, key id) {
+        if (num == SLOODLE_CHANNEL_OBJECT_CREATOR_REQUEST_CONFIGURATION_VIA_HTTP_IN_URL) {
+            httpinurl = str;
+            register_config_if_ready();
+        }
+    }
+    
+    changed(integer change) {
+        // If the inventory is changed, and we have a Sloodle config notecard, then use it to re-initialise
+        if (change & CHANGED_INVENTORY && llGetInventoryType(SLOODLE_CONFIG_NOTECARD) == INVENTORY_NOTECARD) {
+            // If the current notecard is not the same as the one we read most recently, then reset
+            if (llGetInventoryKey(SLOODLE_CONFIG_NOTECARD) != latestnotecard) llResetScript();
+        }
+    }
+    
+    
+}
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/set-1.0/objects/default/assets/sloodle_notecard_httpin.lslp

BIN
iar/assets/60fb5674-f500-4522-b176-0aba4418edae_texture.jp2


+ 582 - 0
iar/assets/6219fb67-fd6e-0181-3472-f206795a274f_script.lsl

@@ -0,0 +1,582 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+/*********************************************
+*  Copyright (c) 2009 - 2011 various contributors (see below)
+*  Released under the GNU GPL 3.0
+*  This script can be used in your scripts, but you must include this copyright header as per the GPL Licence
+*  For more information about GPL 3.0 - see: http://www.gnu.org/copyleft/gpl.html
+*  This script is part of the SLOODLE Project see http://sloodle.org
+*
+*  sloodle_rezzer_object
+*  Copyright:
+*  Paul G. Preibisch (Fire Centaur in SL) fire@avatarclassroom.com  
+*  Edmund Edgar (Edmund Earp in SL) ed@avatarclassroom.com
+*
+*  This script will get an httpin url, and shout it out to the rezzer.  It will then wait to receive its config via httpin, and send it as a linked message to all other scripts
+*/
+
+integer SLOODLE_CHANNEL_HTTP_RESPONSE = -1639260101;  // Tells the sloodle_rezzer_object script to send the contents as an http-in response, to the key specified as key, which should be waiting for a response.
+
+integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;//configuration channel
+integer SLOODLE_CHANNEL_OBJECT_CREATOR_REQUEST_CONFIGURATION_VIA_HTTP_IN_URL = -1639270089; //Object creator telling itself it wants to rez an object at a position (specified as key)
+
+string SLOODLE_HTTP_IN_REQUEST_LINKER = "/mod/sloodle/classroom/httpin_config_linker.php";
+string SLOODLE_HTTP_IN_UPDATE_LINKER = "/mod/sloodle/classroom/httpin_url_update_linker.php";
+string SLOODLE_PING_LINKER = "/mod/sloodle/classroom/active_object_ping_linker.php";
+
+float refreshseconds = 3600.0; // Number of seconds between pings. Some jitter will sometimes be added to prevent killing the server this number of seconds after a sim full of objects starts up. We start with a fairly slow default, but this can be altered by the server when we ping or send out config.
+
+string SLOODLE_EOF = "sloodleeof";
+
+vector rezzer_position_offset;
+rotation rezzer_rotation_offset;
+key rezzer_uuid;
+integer isconfigured = 0;
+integer has_position = 0;
+integer http_in_password = 0;
+
+string sloodlepwd = "";
+string sloodleserverroot = "";
+string sloodlecontrollerid = "";
+
+string myUrl;
+string persistent_config; 
+
+integer is_pinging = 0;
+integer is_ping_retry = 0;
+key current_ping_http = NULL_KEY;
+
+move_to_layout_position() {
+    
+    // llOwnerSay("todo: move to position "+(string)rezzer_position_offset+", rot "+(string)rezzer_rotation_offset+ " in relation to rezzer "+(string)rezzer_uuid);
+    list rezzerdetails = llGetObjectDetails( rezzer_uuid, [ OBJECT_POS, OBJECT_ROT ] );
+    vector rezzerpos = llList2Vector( rezzerdetails, 0 );
+    rotation rezzerrot = llList2Rot( rezzerdetails, 1 );
+    sloodle_set_pos( rezzerpos + ( rezzer_position_offset * rezzerrot ) );
+    llSetRot( rezzerrot * rezzer_rotation_offset );
+
+}
+
+// Configure by receiving a linked message from another script in the object
+// Returns TRUE if the object has all the data it needs
+integer sloodle_handle_command(string str, integer do_persist) 
+{
+   // llOwnerSay("handling command "+str);
+    list bits = llParseString2List(str,["|"],[]);
+    integer numbits = llGetListLength(bits);
+    
+    if (numbits >= 1 ) {
+        string name = llList2String(bits,0);
+            
+        string value1 = "";
+        string value2 = "";
+            
+        if (numbits > 1) value1 = llList2String(bits,1);
+        if (numbits > 2) value2 = llList2String(bits,2);
+
+        if (name == "set:sloodleserverroot") { sloodleserverroot = value1;
+        } else if (name == "set:sloodlepwd") { sloodlepwd = value1 + "|" + value2;
+        } else if (name == "set:sloodlecontrollerid") { sloodlecontrollerid = value1;
+        } else if (name == "set:position") {        
+            rezzer_position_offset = (vector)llList2String(bits,1);
+            rezzer_rotation_offset = (rotation)llList2String(bits,2);
+            rezzer_uuid = llList2Key(bits,3);
+            has_position = 1;
+        } else if (name == "do:derez") {
+            llSleep(2); // This is needed to give the script a chance to finish making the http response.
+            llDie();
+        } else if ( (name=="do:requestconfig") || (name=="do:reset") ) {           
+            string this_script = llGetScriptName();                
+            integer n = llGetInventoryNumber(INVENTORY_SCRIPT); 
+            while(n) {
+                string script_name = llGetInventoryName(INVENTORY_SCRIPT, --n);
+                // Reset all sloodle scripts. If for some reason we make a sloodle script that we don't want reset, call it "sloodle_reset".
+                if ( (script_name != this_script) && (llGetSubString( script_name, 0, 7) == "sloodle_" ) && (llGetSubString( script_name, 0, 15) != "sloodle_noreset_" ) ) {
+                    llResetOtherScript( script_name );
+                    // llOwnerSay("resetting script "+script_name);
+                }
+            }
+            // Give them a second to get started to avoid trying to configure them before they're ready.
+            llSleep(1);
+           
+            state reinitialize;
+           
+        } else {
+            if (do_persist == 1) {
+              //  llOwnerSay("adding to persist");
+                    persistent_config = persistent_config + "&" + name + "=" + value1;                     
+            }
+        }
+    } 
+    
+    if ( (sloodleserverroot != "") && (sloodlecontrollerid != "") && (sloodlepwd != "") ) {
+        isconfigured = 1;
+    }                                        
+    
+    return isconfigured;
+}
+
+sloodle_tell_other_scripts(string msg, integer channel, key respond_key)
+{    
+    integer status_code;
+    if (channel == 0) {
+    // Don't know the channel yet - get it from the message.
+        list lines;
+        lines = llParseStringKeepNulls( msg, ["\n"], [] );
+        string status_line = llList2String(lines, 0);
+        list status_bits;
+        status_bits = llParseStringKeepNulls( status_line, ["|"], [] );
+       
+        status_code = (integer)llList2String(status_bits, 0);
+
+        if (status_code == 1) {
+            status_code = SLOODLE_CHANNEL_OBJECT_DIALOG;
+        }
+    } else {
+        status_code = channel;        
+    }
+    // config requests need a SLOODLE_EOF on the end.
+    // this is a legacy from sending notecards line-by-line. 
+    if (status_code == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+        msg = msg + "\n"+SLOODLE_EOF;
+    }
+   // llOwnerSay("sending msg with status code "+(string)status_code+": "+msg);
+    llMessageLinked(LINK_SET, status_code, msg, respond_key);
+    
+}
+
+initialize() 
+{
+        //set timer to ask for config if config not received
+        llSetTimerEvent(30);
+        llSetText("", <1.0, 1.0, 1.0>, 1.0);
+        rezzer_position_offset = <0,0,0>;
+        rezzer_rotation_offset = <0,0,0,0>;
+        rezzer_uuid = NULL_KEY;
+        isconfigured = 0;
+        has_position = 0;
+        
+        // http_in_password = 0;
+        //get an httpin url
+        if (myUrl != "") {
+            llReleaseURL(myUrl);
+        }        
+        llRequestURL();    
+//llOwnerSay("initialize requesting url");        
+} 
+//sends our configuration to the server
+configure_from_persistent_config()
+{
+        
+    //llOwnerSay("got a persistent config, trying to use that");    
+    //send to httpin_config_linker
+    string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+    body += "&sloodlepwd=" + sloodlepwd;
+    body += "&sloodleobjuuid=" + (string)llGetKey();
+    body += "&childobjectuuid=" + (string)llGetKey();
+    body += "&httpinurl=" + myUrl;
+    body += "&sloodleobjname=" + llGetObjectName();
+    body += persistent_config;
+    //llOwnerSay("requested config with body "+body); 
+    //tell the server to initialize via httpin using the specified parameters.  Server will respond by sending an http response, AND the config via httpin, however
+    //we will ingnore the http response, and instead, just use the httpin
+    llHTTPRequest(sloodleserverroot + SLOODLE_HTTP_IN_REQUEST_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body+persistent_config);
+             
+}
+
+update_http_in_url()
+{
+        
+    //llOwnerSay("got a persistent config, trying to use that");    
+    //send to httpin_config_linker
+    string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+    body += "&sloodlepwd=" + sloodlepwd;
+    body += "&sloodleobjuuid=" + (string)llGetKey();
+    body += "&httpinurl=" + myUrl;
+    //llOwnerSay("requested config with body "+body); 
+    llHTTPRequest(sloodleserverroot + SLOODLE_HTTP_IN_UPDATE_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+             
+}
+sloodle_set_pos(vector targetposition){
+    integer counter=0;
+    while ((llVecDist(llGetPos(), targetposition) > 0.001)&&(counter<50)) {
+        counter+=1;
+        llSetPos(targetposition);
+    }
+
+}
+
+default{
+    
+    state_entry() {
+           
+        llSleep(1.0);
+        initialize();
+        
+    }
+
+    on_rez(integer start_param) {
+        //llOwnerSay("default got start_param"+(string)start_param);
+        //http_in_password is sent from the server - it is a random password per object so that malicious users can't send
+        //commands to this object.
+        http_in_password = start_param;
+        //if no start_param, that means we were not rezzed by the rezzer (could have been by a user pulling fom inventory)
+        if (start_param > 0) {
+            //makesure config is clean
+            sloodleserverroot = "";
+            sloodlecontrollerid = "";
+            sloodlepwd = "";
+            persistent_config = "";
+        }
+        
+        initialize();        
+
+    }          
+        
+    http_request(key id, string method, string body){
+          if ((method == URL_REQUEST_GRANTED)){
+//llOwnerSay("got url");        
+                myUrl=body;
+                //shout it out to the rezzer our httpinUrl
+                //persistant config is the data in memory from previous initialization                
+                 // If we have a persistent config,  
+                if (persistent_config != "") {
+                   // llOwnerSay("config from persistent");
+                   //tell the server to configure us based on a configuration we had before which will will send via http request
+                   //we will then receive the returned config from the server via http-in
+                    configure_from_persistent_config();
+                } else {
+                   // llOwnerSay("no persistent, contacting rezzer");
+                   //tell the rezzer to send us a configuration.  Rezzer will tell the server to send us a configuration using our http-in
+                    llRegionSay(SLOODLE_CHANNEL_OBJECT_CREATOR_REQUEST_CONFIGURATION_VIA_HTTP_IN_URL,myUrl);
+                    //tell any other scripts our http-in
+                    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_CREATOR_REQUEST_CONFIGURATION_VIA_HTTP_IN_URL, myUrl, NULL_KEY);                    
+                }
+          } else if (method == "POST"){     
+                                                   
+               //this is where our object receives data from from our server via http-in
+                      
+                list lines;
+                lines = llParseStringKeepNulls( body, ["\n"], [] );
+                
+                list header_line;
+                header_line = llParseStringKeepNulls( llList2String(lines,0), ["|"], [] );
+                
+                // Position 10 should be the http_in_password
+                // This is set once on initial config.
+                // Once we've implemented object persistance, it should always be set.
+                if (http_in_password == 0) {
+                   // llOwnerSay("First time, setting http in password");                    
+                    http_in_password = (integer)llList2String(header_line, 10);
+                }
+                
+                if (http_in_password != (integer)llList2String(header_line, 10)) {
+                   // llOwnerSay("Ignoring message - password mismatch");
+                    llHTTPResponse(id, 401, "Unauthorized - HTTP-in password mismatch");
+                      
+                    return;
+                }                
+                
+                // If we don't expect a response from the script that handles this, respond now to say we got the message.
+                integer expect_response = 0;
+                if (llGetListLength(header_line) >= 12) {
+                    if (llList2Integer(header_line, 11) == 1) {
+                        expect_response = 1;
+                    }
+                }
+                if (expect_response != 1) {
+                    llHTTPResponse(id, 200, "OK"); 
+                }
+                
+                if (llGetListLength(header_line) >= 13) {
+                    if (llList2Float(header_line,12) > 0) {
+                        refreshseconds = llList2Float(header_line,12);
+                    }
+                }                     
+                                
+                string descriptor = "";
+                if (llGetListLength(header_line) > 1) descriptor = llList2String(header_line, 3);
+                integer do_persist = 0;   
+                if ( (descriptor == "CONFIG_PERSISTENT") || (descriptor == "CONFIG") ) {
+                    // blow the existing config away and start again
+                    sloodleserverroot = "";
+                    sloodlecontrollerid = "";
+                    sloodlepwd = "";
+                    persistent_config = "";
+                    //This CONFIG_PERSISTENT setting is primarily for development purposes.  We turn this setting off via serverside
+                    //when shipping, so our old settings are not saved in shipped versions.  However, users server always defaults to 
+                    //CONFIG_PERSISTENT so their settings are saved, not developmental ones
+                    //when the server sends a configuration via http-in, it tells the object to keep it in its resident memory
+                    if (descriptor == "CONFIG_PERSISTENT") {
+                        //this means that the script should store the config in its memory so that when it is taken into inventory, and re-rezzed, it will 
+                        //still have a configuration
+                        do_persist = 1;                        
+                    }
+                }
+                integer numlines = llGetListLength(lines);
+                integer i = 1;          
+                for (i=1; i < numlines; i++) {
+                    isconfigured = sloodle_handle_command(llList2String(lines, i), do_persist);                      
+                }                                                         
+                                
+                sloodle_tell_other_scripts(body,0, id);
+                // This is the end of the configuration data
+                llSleep(0.2);
+                sloodle_tell_other_scripts(SLOODLE_EOF, 0, id);
+                
+                if (isconfigured == 1) {   
+                    if (has_position == 1) {                                 
+                        move_to_layout_position();
+                    }
+                    llSetTimerEvent(0);
+                    state ready;
+                }                
+          }//endif
+     }//http
+     
+     changed(integer change) {
+
+        if ( (change & CHANGED_REGION_START) || (change & CHANGED_REGION ) ) {
+            //Request new URL
+            if (myUrl != "") {
+                llReleaseURL(myUrl);
+            }
+            llRequestURL();
+        }
+
+     }
+        
+    timer() {
+        initialize();
+    }    
+}
+
+state ready {    
+
+    on_rez(integer start_param)
+    {
+       // llOwnerSay("ready got start_param"+(string)start_param);
+        http_in_password = start_param;
+                
+        if (start_param > 0) {
+            sloodleserverroot = "";
+            sloodlecontrollerid = "";
+            sloodlepwd = "";
+            persistent_config = "";
+            // llSleep(2.0); // Give the rezzer time to register us. Seems to be an issue on OpenSim, where everything is faster than SL.
+        }
+                
+        state default;        
+        
+    }            
+                                    
+    state_entry()
+    {        
+        // llOwnerSay("ready state");
+        // llOwnerSay(persistent_config);
+        if (rezzer_uuid != NULL_KEY) {
+            llListen(232323, "", rezzer_uuid, "");   
+        }
+    
+    } 
+
+    listen(integer channel, string name, key id, string message) {
+    
+        // Listen to the rezzer telling us it's moved, and move accordingly.
+        
+        // llOwnerSay(message);
+    
+        list bits = llParseString2List( message, ["|"], [] );
+        vector change_pos = (vector)llList2String( bits, 0 );
+        rotation change_rot = (rotation)llList2String( bits, 1 );
+        vector parent_pos = (vector)llList2String( bits, 2);
+        // llOwnerSay("got message" + message);       
+
+        // Apply the position changes first, then the rotation
+        vector before_pos = llGetPos();
+        if (before_pos.z > 0) { // sometimes this comes out at 0, but we don't want to go to the corner of the sim
+            sloodle_set_pos( before_pos - change_pos );
+        }
+
+        before_pos = llGetPos();
+        rotation before_rot = llGetRot();
+
+        //llOwnerSay("Rot: "+(string)llRot2Euler(change_rot));
+        // llOwnerSay((string)(before_rot - change_rot));
+        // llOwnerSay("new pos: "+(string)(llGetPos() + ( before_pos - parent_pos) * change_rot));
+        //change_rot = llEuler2Rot( < 0, 0, 15 * DEG_TO_RAD > ); // pretend we rotated 15 degrees
+        vector currentPosition = llGetPos();
+        vector currentOffset = currentPosition - parent_pos;
+        //llOwnerSay("I plan to be "+(string)llVecDist(currentOffset, <0,0,0>)+" from parent");
+        vector rotatedOffset = currentOffset * change_rot;
+        vector newPosition = parent_pos + rotatedOffset;
+        sloodle_set_pos(newPosition);
+        
+        //llOwnerSay("new pos: "+(string)(llGetPos() + ( ( before_pos - parent_pos) * change_rot ) ) );        
+        // llSetPos( before_pos + ( ( parent_pos - before_pos ) * change_rot ) );        
+        
+        llSetRot( llGetRot() * change_rot );
+
+        //  llGetPos() + vPosOffset * llGetRot(), ZERO_VECTOR, llGetRot()        
+        
+    }    
+
+    timer()
+    {
+        // Send our ping request
+        string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
+        body += "&sloodlepwd=" + sloodlepwd;
+        body += "&sloodleobjuuid=" + (string)llGetKey();
+        is_pinging = 1;
+        current_ping_http = llHTTPRequest(sloodleserverroot + SLOODLE_PING_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
+    }
+
+    http_response( key request_id, integer status, list metadata, string body ){ 
+
+        if (request_id != current_ping_http) {
+            return;
+        }    
+
+        list lines = llParseStringKeepNulls(body, ["\n"], []);
+        list statusfields = llParseStringKeepNulls( llList2String(lines,0), ["|"], [] );
+        
+        if (llGetListLength(statusfields) >= 12) {
+            if (llList2Float(statusfields,12) > 0) {
+                refreshseconds = llList2Float(statusfields,12);
+            }
+        }   
+
+        is_pinging = 0;
+        if (status == 200) {
+            if (is_ping_retry == 1) {
+                // Reintroduce the randomness we may have lost if the server went down.
+                llSetTimerEvent(llFrand(refreshseconds));
+            } else {
+                llSetTimerEvent(refreshseconds);
+            }
+            is_ping_retry = 0;
+        } else {
+            is_ping_retry = 1;
+            llSetTimerEvent(llFrand(refreshseconds));
+        } 
+
+    }
+                
+    http_request(key id, string method, string body){
+
+        if (method == URL_REQUEST_GRANTED){
+
+            myUrl=body;            
+            update_http_in_url();
+                
+        } else if (method == "POST"){                            
+          
+               //this is where we receive data from from our server
+                list lines;
+                lines = llParseStringKeepNulls( body, ["\n"], [] );
+
+                list header_line;
+                header_line = llParseStringKeepNulls( llList2String(lines,0), ["|"], [] );
+                
+                // Position 10 should be the http_in_password
+                // This is set once on initial config.
+                // Once we've implemented object persistance, it should always be set.
+                if (http_in_password == 0) {
+                   // llOwnerSay("First time, setting http in password");                    
+                    http_in_password = (integer)llList2String(header_line, 10);
+                }
+                
+                if (http_in_password != (integer)llList2String(header_line, 10)) {
+                   // llOwnerSay("Ignoring message - password mismatch");
+                    llHTTPResponse(id, 401, "Unauthorized - HTTP-in password mismatch");  
+                    return;
+                }
+                                             
+                integer numlines = llGetListLength(lines);
+                integer i = 0;   
+              // llOwnerSay(body);
+                if (llList2String(header_line,3) == "REPORT_POSITION") {
+                    list rezzerdetails = llGetObjectDetails( rezzer_uuid, [ OBJECT_POS, OBJECT_ROT ] );
+                    vector rezzerpos = llList2Vector( rezzerdetails, 0 );
+                    rotation rezzerrot = llList2Rot( rezzerdetails, 1 );
+                    string reply = (string)( ( llGetPos() - rezzerpos ) / rezzerrot ) + "|" + (string)(llGetRot() / rezzerrot) + "|" + (string)rezzer_uuid;
+                    llHTTPResponse(id, 200, reply);
+                    return;
+                }
+              
+                 // If we don't expect a response from the script that handles this, respond now to say we got the message.
+                integer expect_response = 0;
+                if (llGetListLength(header_line) >= 12) {
+                    if (llList2Integer(header_line, 11) == 1) {
+                        expect_response = 1;
+                    }
+                };
+                if (expect_response != 1) {
+                    llHTTPResponse(id, 200, "OK"); 
+                }
+                
+                string status_descriptor = "";
+                string request_descriptor = "";                             
+                integer do_persist = 0;
+                if (llGetListLength(header_line) > 1) status_descriptor = llList2String(header_line, 1);
+                if (llGetListLength(header_line) > 2) request_descriptor = llList2String(header_line, 3);                
+                if ( (request_descriptor == "CONFIG_PERSISTENT") || (request_descriptor == "CONFIG") ) {
+                    // blow the existing config away and start again
+                    sloodleserverroot = "";
+                    sloodlecontrollerid = "";
+                    sloodlepwd = "";
+                    persistent_config = "";
+                    if (request_descriptor == "CONFIG_PERSISTENT") {
+                        do_persist = 1;                        
+                    }
+                }
+                if ( (status_descriptor == "CONFIG") || (status_descriptor=="SYSTEM") ){
+                    for (i=1; i < numlines; i++) {
+                        isconfigured = sloodle_handle_command(llList2String(lines, i), do_persist);
+                    }
+                } 
+                                
+                sloodle_tell_other_scripts(body, 0, id);
+                // This is the end of the configuration data
+                llSleep(0.2);
+                sloodle_tell_other_scripts(SLOODLE_EOF, 0, id);
+                
+                // Start pinging, with jitter                
+                llSetTimerEvent(llFrand(refreshseconds));
+                                                                       
+          }//endif 
+     }//http
+
+    changed(integer change) {
+        if ( (change & CHANGED_REGION_START) || (change & CHANGED_REGION ) ) {
+            //Request new URL
+            if (myUrl != "") {
+                llReleaseURL(myUrl);
+            }
+            llRequestURL();
+        }
+    }         
+
+    link_message(integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            sloodle_handle_command(str, 0);
+        } else if (num == SLOODLE_CHANNEL_HTTP_RESPONSE) {
+            llHTTPResponse(id, 200, str); 
+        }
+
+    }
+}
+        
+state reinitialize {
+    // force us to go into state default and run state_entry, which calls initialize
+    // this allows us to get to that state from a function that doesn't know whether it's already in state default or not.
+    state_entry() {
+        state default;
+    }
+}
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/set-1.0/objects/default/assets/sloodle_rezzer_object.lslp

+ 361 - 0
iar/assets/62a5f1dc-ccdd-df39-de68-36a1087a2dfa_script.lsl

@@ -0,0 +1,361 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Standard translation script for Sloodle.
+// Contains the common, re-usable words and phrases.
+//
+// The "locstrings" list is pairs of strings.
+// The first of each pair is the name, and second is the translation.
+//
+// This script is part of the Sloodle project.
+// Copyright (c) 2008 Sloodle (various contributors)
+// Released under the GNU GPL v3
+//
+// Contributors:
+//  Peter R. Bloomfield
+//
+
+// Note: where a translation string contains {{x}} (where x is a number),
+//  it means that a parameter can be inserted. Please make sure to include these
+//  parameters in the appropriate location in your translation.
+// It may be sensible to add comments after your string to indicate what its parameters mean.
+// NOTE: parameter numbering starts at 0 (unlike previous versions, which started at 1).
+
+// Translations can be requested by sending a link message on the SLOODLE_CHANNEL_TRANSLATION_REQUEST channel.
+// It is advisable simply to use the "sloodle_translation_request" function provided in this script.
+
+
+///// TRANSLATION /////
+
+// Localization batch - indicates the purpose of this file
+string mybatch = "assignment"; // Strings for all assignment types
+
+
+// List of string names and translation pairs.
+// The name is the first of each pair, and should not be translated.
+// The second of each pair is the translation.
+// Additional comments are sometimes given afterward to aid translations.
+list locstrings = [
+	//  Assignment
+	"assignment:checking", "Checking Assignment...",
+	"assignment:connectionfailed", "Failed to connect to assignment. It may be the wrong type, or it may not be visible.",
+	"assignment:lateaccepting", "The assignment deadline has passed, but late submissions are being accepted.",
+	"assignment:late", "Sorry {{0}}. The assignment deadline has passed, and late submissions are not being accepted.", // Parameter: avatar name
+	"assignment:early", "Sorry {{0}}. The assignment is not yet open for submissions.", // Parameter: avatar name
+	"assignment:noresubmit", "Sorry {{0}}. You have already submitted to this assignment, and resubmissions are not being accepted.", // Parameter: avatar name
+	"assignment:nopermission", "Sorry {{0}}. You do not have permission to submit to this assignment.", // Parameter: avatar name
+	"assignment:ready", "Sloodle Assignment Ready:\n{{0}}", // Parameter: name of the assignment
+	
+    "assignment:primdropmenu", "PrimDrop Menu\n{{0}} = Cancel\n{{1}} = Assignment summary\n{{2}} = Submit\n{{3}} = View Online", // Parameters: button labels
+	//"assignment:primdropteachermenu", "PrimDrop Teacher Menu\n{{0}} = Cancel\n{{1}} = Assignment summary\n{{2}} = Submit\n{{3}} = View Online\n{{4}} = Rez Submission\n{{5}} = Take a Submission\n{{6}} = Take All Objects", // Parameters: button labels
+	"assignment:primdropteachermenu", "PrimDrop Teacher Menu\n{{0}} = Cancel\n{{1}} = Assignment summary\n{{2}} = Submit\n{{3}} = View Online\n{{4}} = Take All Objects", // Parameters: button labels
+    
+    "assignment:allgiven", "All assignment submissions have been given to you in a folder called \"{{0}}\".", // Parameter: name of inventory folder
+	"assignment:nosubmissions", "ERROR: No submissions in inventory.",
+	"assignment:checkingpermission", "PLEASE WAIT\nChecking permission for {{0}}.", // Parameter: avatar name
+	"assignment:waitingforsubmission", "Waiting for submission from {{0}}", // Parameter: avatar name
+	"assignment:dropsubmission", "{{0}}, please make your submission by Ctrl+dragging ONE item from your inventory onto this dropbox.", // Parameter: avatar name
+	"assignment:checkinginventory", "PLEASE WAIT\nChecking inventory",
+	"assignment:submittimeout", "Sorry {{0}}. Submission timed-out. Please try again.", // Parameter: avatar name
+	"assignment:receiveditem", "Received item. Checking...",
+	"assignment:checkingitem", "PLEASE WAIT\nChecking item",
+	"assignment:submissionerror", "Error locating submitted item",
+	"assignment:objectsonly", "ERROR: only objects are accepted for this assignment",
+	"assignment:creatoronly", "ERROR: for security, only the item's creator may submit it",
+	"assignment:invalidperms", "ERROR: invald item permissions. Please ensure copy and transfer are enabled.",
+	"assignment:itemok", "Item \"{{0}}\" appears OK. Thank you {{1}}", // Parameters: object name, avatar name
+	"assignment:submitting", "PLEASE WAIT\nSending {{0}}'s submission", // Parameter: avatar name
+	"assignment:submissionok", "Assignment submission successful. Thank you {{0}}.", // Parameter: avatar name
+	"assignment:submissionfailed", "Sorry {{0}}. Assignment submission failed with error code {{1}}", // Parameters: avatar name, status code
+	"assignment:rezmode", "Rez Mode\nIn use by {{0}}", // Parameter: avatar name
+	"assignment:takemode", "Take Mode\nIn use by {{1}}", // Parameter: avatar name
+	"assignment:chatitemname", "{{0}}, chat the name of the submission you require on channel 0 or 1. (Note: names are case-sensitive)", // Parameter: avatar name
+	"assignment:submissionnotfound", "ERROR: submission \"{{0}}\" not found", // Parameter: item name
+	"assignment:rezzing", "Rezzing submission \"{{0}}\"...", // Parameter: item name
+	"assignment:giving", "Giving submission \"{{0}}\"..." // Parameter: item name
+];
+
+///// ----------- /////
+
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";                     // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";                       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";                   // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";          // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";            // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";                 // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";              // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_LOAD_URL_PARALLEL = "loadurlpar";  // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";          // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";             // Recipient avatar should be identified in link message keyval. No output parameters.
+
+
+// Used for sending parallel URL loading messages
+integer SLOODLE_CHANNEL_OBJECT_LOAD_URL = -1639270041;
+
+///// FUNCTIONS /////
+
+
+// Send a translation request link message
+// (Here for reference only)
+// Parameter: output_method = should identify an output method, as given by the "SLOODLE_TRANSLATE_..." constants above
+// Parameter: output_params = a list of parameters which controls the output, such as chat channel or buttons for a dialog
+// Parameter: string_name = the name of the localization string to output
+// Parameter: string_params = a list of parameters which will be included in the translated string (or an empty list if none)
+// Parameter: keyval = a key to send in the link message
+// Parameter: batch = the name of the localization batch which should handle this request
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+// Send a translation response link message
+sloodle_translation_response(integer target, string name, string translation)
+{
+    llMessageLinked(target, SLOODLE_CHANNEL_TRANSLATION_RESPONSE, name + "|" + translation + "|" + mybatch, NULL_KEY);
+}
+
+// Get the translation of a particular string
+string sloodle_get_string(string name)
+{
+    // Attempt to find the string name
+    integer numstrings = llGetListLength(locstrings);
+    integer pos = llListFindList(locstrings, [name]);
+    
+    // IMPORTANT: we must be careful not to match a translations instead of a name.
+    // If this was an even number, then we have a string name.
+    if ((pos % 2) == 0) {
+        // Make sure there is a subsequent translation in the list
+        if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
+        // The translation is not there
+        pos = -1;
+    }
+    
+    // If we could not find the string, then return a placeholder
+    if (pos < 0) return "[[" + name + "]]";
+    
+    // If we got here, then we matched a translation instead of a string name.
+    // As such, we need to resort to searching through the list manually (which can be very slow).
+    // To saved time, we can start from the position just beyond where we got to.
+    // We advance by 2 each time to skip the translations completely.
+    
+    for (pos += 1; pos < numstrings; pos += 2) {
+        // Do we have a match?
+        if (llList2String(locstrings, pos) == name) {
+            // Yes - make sure there is a translation following it
+            if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
+            // The translation is not there - skip the rest of the search
+            pos = numstrings;
+        }
+    }
+    
+    // If we reached this point, then the string is not available. Return a placeholder.
+    return "[[" + name + "]]";
+}
+
+// Send a debug link message
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+
+// Get a formatted translation of a string
+string sloodle_get_string_f(string name, list params)
+{
+    // Get the string itself
+    string str = sloodle_get_string(name);
+    // How many parameters do we have?
+    integer numparams = llGetListLength(params);
+    
+    // Go through each parameter we have been provided
+    integer curparamnum;
+    string curparamtok = "{{x}}";
+    integer curparamtoklength = 0;
+    string curparamstr = "";
+    integer tokpos = -1;
+    for (curparamnum = 0; curparamnum < numparams; curparamnum++) {
+        // Construct this parameter token
+        curparamtok = "{{" + (string)(curparamnum) + "}}";
+        curparamtoklength = llStringLength(curparamtok);
+        // Fetch the parameter text
+        curparamstr = llList2String(params, curparamnum);
+        
+        // Ensure the parameter text does NOT contain double braces (this avoids an infinite loop!)
+        if (llSubStringIndex(curparamstr, "{{") < 0 && llSubStringIndex(curparamstr, "}}") < 0) {            
+            // Go through every instance of this parameter's token
+            while ((tokpos = llSubStringIndex(str, curparamtok)) >= 0) {
+                // Replace the token with the parameter string
+                str = llDeleteSubString(str, tokpos, tokpos + curparamtoklength - 1);
+                str = llInsertString(str, tokpos, curparamstr);
+            }
+        }
+    }
+    
+    return str;
+}
+
+
+///// STATES /////
+
+default
+{
+    state_entry()
+    {
+    }
+    
+    link_message(integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_TRANSLATION_REQUEST) {            
+            
+            // // PROCESS REQUEST // //
+        
+            // Split the incoming message into fields
+            list fields = llParseStringKeepNulls(str, ["|"], []);
+            integer numfields = llGetListLength(fields);
+            
+            // Extract and check the localization batch
+            string batch = "";
+            if (numfields > 4) batch = llList2String(fields, 4);
+            if (batch != mybatch) return;
+            
+            // We expect at least 3 fields
+            // ... or 4 if there are insertion parameters...
+            // ... or 5 if there is a language code
+            // ... anybody up for a 6th parameter? :)
+            if (numfields < 3) {
+                sloodle_debug("ERROR: Insufficient fields for translation of string.");
+                return;
+            }
+            
+            // Extract the key parts of the request
+            string output_method = llList2String(fields, 0);
+            list output_params = llCSV2List(llList2String(fields, 1));
+            integer num_output_params = llGetListLength(output_params);
+            string string_name = llList2String(fields, 2);
+            list string_params = [];
+            if (numfields > 3) {
+                // Extract the string parameters (extra text added to the output)
+                string string_param_text = llList2String(fields, 3);
+                if (string_param_text != "") string_params = llCSV2List(string_param_text);
+            }
+            
+            // // TRANSLATE STRING // //
+            
+            // This string will store the translation
+            string trans = "";
+            // Do nothing if the string name is empty
+            if (string_name != "") {
+                // If there are no string parameters, then it is only a basic translation
+                if (llGetListLength(string_params) == 0) {
+                    // Get the basic translation
+                    trans = sloodle_get_string(string_name);
+                } else {
+                    // Construct the formatted string
+                    trans = sloodle_get_string_f(string_name, string_params);
+                }
+            }
+            
+            // // OUTPUT STRING // //
+            
+            // Check what output method has been requested
+            if (output_method == SLOODLE_TRANSLATE_LINK) {
+                // Return the string via link message
+                sloodle_translation_response(sender_num, string_name, trans);
+                
+            } else if (output_method == SLOODLE_TRANSLATE_SAY) {
+                // Say the string
+                if (num_output_params > 0) llSay(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to say string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_WHISPER) {
+                // Whisper the string
+                if (num_output_params > 0) llWhisper(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to whisper string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_SHOUT) {
+                // Shout the string
+                if (num_output_params > 0) llShout(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to shout string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_REGION_SAY) {
+                // RegionSay the string
+                if (num_output_params > 0) llRegionSay(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to region-say string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_OWNER_SAY) {
+                // Ownersay the string
+                llOwnerSay(trans);
+                
+            } else if (output_method == SLOODLE_TRANSLATE_DIALOG) {
+                // Display a dialog - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to show dialog with string \"" + string_name + "\".");
+                    return;
+                }
+                // We need at least 2 additional output parameters (channel, and at least 1 button)
+                if (num_output_params >= 2) {
+                    // Extract the channel number
+                    integer channel = llList2Integer(output_params, 0);
+                    // Extract up to 12 button values
+                    list buttons = llList2List(output_params, 1, 12);
+                    
+                    // Display the dialog
+                    llDialog(id, trans, buttons, channel);
+                    
+                } else sloodle_debug("ERROR: Insufficient output parameters to show dialog with string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL) {
+                // Display a URL - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
+                    return;
+                }                
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 1) llLoadURL(id, trans, llList2String(output_params, 0));
+                else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL_PARALLEL) {
+                // Display a URL - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
+                    return;
+                }
+                
+                // NOTE: currently the parallel URL loaders will drop any text.
+                // TODO: make parallel URL loaders use text as well.
+                
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 1) llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_LOAD_URL, llList2String(output_params, 0), id);
+                else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_HOVER_TEXT) {
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 2) llSetText(trans, (vector)llList2String(output_params, 0), (float)llList2String(output_params, 1));
+                else sloodle_debug("ERROR: Insufficient output parameters to show hover text with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_IM) {
+                // Send an IM - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to send IM with string \"" + string_name + "\".");
+                    return;
+                }                
+                // Send the IM
+                llInstantMessage(id, trans);
+
+            } else {
+                // Don't know the output method
+                sloodle_debug("ERROR: unrecognised output method \"" + output_method + "\".");
+            }
+        }
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/primdrop-1.0/objects/default/assets/lang/en/sloodle_translation_assignment_en.lslp 

BIN
iar/assets/6395670a-f392-482b-8833-7b691cbe29eb_sound.ogg


BIN
iar/assets/6764b59f-fe5f-4a46-9b8b-401fc0c840df_animation.bvh


+ 407 - 0
iar/assets/68bf8913-cf9f-c581-ce72-aecc8a7a8905_script.lsl

@@ -0,0 +1,407 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Standard translation script for Sloodle.
+// Contains the common, re-usable words and phrases.
+//
+// The "locstrings" list is pairs of strings.
+// The first of each pair is the name, and second is the translation.
+//
+// This script is part of the Sloodle project.
+// Copyright (c) 2008-9 Sloodle (various contributors)
+// Released under the GNU GPL v3
+//
+// Contributors:
+//  Peter R. Bloomfield
+//
+
+// Note: where a translation string contains {{x}} (where x is a number),
+//  it means that a parameter can be inserted. Please make sure to include these
+//  parameters in the appropriate location in your translation.
+// It may be sensible to add comments after your string to indicate what its parameters mean.
+// NOTE: parameter numbering starts at 0 (unlike previous versions, which started at 1).
+
+// Translations can be requested by sending a link message on the SLOODLE_CHANNEL_TRANSLATION_REQUEST channel.
+// It is advisable simply to use the "sloodle_translation_request" function provided in this script.
+
+
+///// TRANSLATION /////
+
+// Localization batch - indicates the purpose of this file
+string mybatch = ""; // Blank - this is the common Sloodle batch
+
+
+// List of string names and translation pairs.
+// The name is the first of each pair, and should not be translated.
+// The second of each pair is the translation.
+// Additional comments are sometimes given afterward to aid translations.
+list locstrings = [
+    //  Common terms
+    "yes", "Yes",
+    "no", "No",
+    "on", "On",
+    "off", "Off",
+    "enabled", "Enabled",
+    "disabled", "Disabled",
+
+    //  Web-configuration
+    "webconfigmenu", "Sloodle Web-Configuration Menu\n\n{{0}} = Access web-configuration page\n{{1}} = Download configuration", // Parameters are button labels
+    "configlink", "Use this link to configure the object.",
+    "chatserveraddress", "Please chat the address of your Moodle site, without a trailing slash. For example: http://www.yoursite.blah/moodle",
+    "waitingforserveraddress", "Waiting for Moodle site address.\nPlease chat it on channel 0 or 1.",
+    "checkingserverat", "Checking Moodle site at:\n{{0}}", // Parameter gives the address of a Moodle site
+    "sendingconfig", "Sending configuration data...",
+    "touchforwebconfig", "Touch me to start web-configuration",
+    
+    // User-centric authorisation
+    "userauthurl", "Please login to Moodle with this URL to authorize the object for your own use.",
+
+    //  General connection and authorisation
+    "readynotconnected", "Ready\n[Not connected]",
+    "shutdown", "Shutdown",
+    "connected", "Connected successfully",
+    "readyconnectedto", "Ready\n[Connected to: {{0}}]", // Parameter should identify what is connected to (e.g. URL of website)
+    "readyconnectedto:sitecourse", "Ready\n[Site: {{0}}]\n[Course: {{1}}]", // Parameters: site address, course name
+    "connectionfailed", "Connection failed",
+    "httperror", "ERROR: HTTP request failed",
+    "httperror:code", "ERROR: HTTP request failed with code {{0}}",
+    "httpempty", "ERROR: HTTP response empty",
+    "httptimeout", "ERROR: HTTP request timed out.",
+    "servererror", "ERROR: server responded with status code {{0}}",
+    "notypeid", "ERROR: failed to identify object type ID",
+    "gottype", "Identified object type as {{0}}", // Parameter gives an object type ID
+    "failedcheckcompatibility", "ERROR: failed to check compatibility with site",
+    "badresponseformat", "ERROR: response from server was badly formatted",
+    "objectauthfailed:code", "ERROR: object authorisation failed with code {{0}}",
+    "objectconfigfailed:code", "ERROR: object configuration failed with code {{0}}",
+    "initobjectauth", "Initiating object authorisation...",
+    "autoreg:newaccount", "A new Moodle account has been automatically generated for you.\nWebsite: {{0}} \nUsername: {{1}}\nPassword: {{2}}", // Parameters: site address, username, password
+    "configurationreceived", "Ready",
+    "configdatamissing", "ERROR: some required data was missing from the configuration {{0}}",
+    "readingconfignotecard", "Reading configuration notecard...",
+    "checkingcourse", "Checking course...",
+    "errortouchtoreset", "ERROR\nTouch me to reset",
+    "notconfiguredyet", "Sorry {{0}}. I am not configured yet.", // Parameter: avatar name
+    "resetting", "Resetting...",
+    "noconfigavailable", "There is no configuration available to download. Please visit the configuration web-page first.",
+    "checkingauth", "Checking authorisation...",
+    "usedescriptioninstead", "If you can't see the shared media screen, please enter your Moodle URL (http://...) in the description field of the rezzer and press \"Reset\"",
+    "openrezzerurl", "Click the URL below to open the rezzer screen in your browser: \n{{0}}",
+
+    //  Sloodle installation/version
+    "sloodlenotinstalled", "ERROR: Sloodle is not installed on specified site.",
+    "sloodleversioninstalled", "Sloodle version installed on server: {{0}}", // Parameter gives a Sloodle version number
+    "sloodleversionrequired", "ERROR: you require at least Sloodle version {{0}}", // Parameter gives a Sloodle version number
+
+    //  Permissions
+    "nopermission:use", "Sorry {{0}}. You do not have permission to use this object.", // Parameter should be the name of an avatar
+    "nopermission:ctrl", "Sorry {{0}}. You do not have permission to control this object.", // Parameter should be the name of an avatar
+    "nopermission:authobjects", "Sorry {{0}}. You do not have permission to authorise objects on this course.", // Parameter should be the name of an avatar
+    
+    // Layout (duplicated deliberately)
+    "layout:failedretrying", "Failed to store layout position. Retrying...",
+    "layout:failedaborting", "Failed to store layout position. Aborting.",
+    "layout:toofar", "Failed to store layout position - too far from rezzer.",
+    "layout:storedobject", "Object stored in layout.",
+    
+    // General error
+    "sloodleerror", "SLOODLE error ({{0}}): please lookup SLOODLE wiki for error information", // Parameters: status code of error
+    "sloodleerror:desc", "SLOODLE error ({{0}}): {{1}}" // Parameters: status code of error, text description of error
+];
+
+///// ----------- /////
+
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";                     // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";                       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";                   // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";          // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";            // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";                 // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";              // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_LOAD_URL_PARALLEL = "loadurlpar";  // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";          // 2 output parameters: colour <r,g,b>, and alpha value
+integer SLOODLE_TRANSLATE_HOVER_TEXT_LINKED_PRIM= -1639277009; // 3 output parameters: colour <r,g,b>,  alpha value, link number
+string SLOODLE_TRANSLATE_IM = "instantmessage";             // Recipient avatar should be identified in link message keyval. No output parameters.
+string SLOODLE_TRANSLATE_TEXTBOX="textbox";//asks via a text box
+
+// Used for sending parallel URL loading messages
+integer SLOODLE_CHANNEL_OBJECT_LOAD_URL = -1639270041;
+
+///// FUNCTIONS /////
+
+
+// Send a translation request link message
+// (Here for reference only)
+// Parameter: output_method = should identify an output method, as given by the "SLOODLE_TRANSLATE_..." constants above
+// Parameter: output_params = a list of parameters which controls the output, such as chat channel or buttons for a dialog
+// Parameter: string_name = the name of the localization string to output
+// Parameter: string_params = a list of parameters which will be included in the translated string (or an empty list if none)
+// Parameter: keyval = a key to send in the link message
+// Parameter: batch = the name of the localization batch which should handle this request
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+// Send a translation response link message
+sloodle_translation_response(integer target, string name, string translation)
+{
+    llMessageLinked(target, SLOODLE_CHANNEL_TRANSLATION_RESPONSE, name + "|" + translation + "|" + mybatch, NULL_KEY);
+}
+
+// Get the translation of a particular string
+string sloodle_get_string(string name)
+{
+    // Attempt to find the string name
+    integer numstrings = llGetListLength(locstrings);
+    integer pos = llListFindList(locstrings, [name]);
+    
+    // IMPORTANT: we must be careful not to match a translations instead of a name.
+    // If this was an even number, then we have a string name.
+    if ((pos % 2) == 0) {
+        // Make sure there is a subsequent translation in the list
+        if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
+        // The translation is not there
+        pos = -1;
+    }
+    
+    // If we could not find the string, then return a placeholder
+    if (pos < 0) return "[[" + name + "]]";
+    
+    // If we got here, then we matched a translation instead of a string name.
+    // As such, we need to resort to searching through the list manually (which can be very slow).
+    // To saved time, we can start from the position just beyond where we got to.
+    // We advance by 2 each time to skip the translations completely.
+    //pos += 1;
+    for (pos += 1; pos < numstrings; pos += 2) {
+        // Do we have a match?
+        if (llList2String(locstrings, pos) == name) {
+            // Yes - make sure there is a translation following it
+            if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
+            // The translation is not there - skip the rest of the search
+            pos = numstrings;
+        }
+    }
+    
+    // If we reached this point, then the string is not available. Return a placeholder.
+    return "[[" + name + "]]";
+}
+
+// Send a debug link message
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+
+// Get a formatted translation of a string
+string sloodle_get_string_f(string name, list params)
+{
+    // Get the string itself
+    string str = sloodle_get_string(name);
+    // How many parameters do we have?
+    integer numparams = llGetListLength(params);
+    
+    // Go through each parameter we have been provided
+    integer curparamnum;
+    string curparamtok = "{{x}}";
+    integer curparamtoklength = 0;
+    string curparamstr = "";
+    integer tokpos = -1;
+    for (curparamnum=0; curparamnum < numparams; curparamnum++) {
+        // Construct this parameter token
+        curparamtok = "{{" + (string)(curparamnum) + "}}";
+        curparamtoklength = llStringLength(curparamtok);
+        // Fetch the parameter text
+        curparamstr = llList2String(params, curparamnum);
+        
+        // Ensure the parameter text does NOT contain double braces (this avoids an infinite loop!)
+        if (llSubStringIndex(curparamstr, "{{") < 0 && llSubStringIndex(curparamstr, "}}") < 0) {            
+            // Go through every instance of this parameter's token
+            while ((tokpos = llSubStringIndex(str, curparamtok)) >= 0) {
+                // Replace the token with the parameter string
+                str = llDeleteSubString(str, tokpos, tokpos + curparamtoklength - 1);
+                str = llInsertString(str, tokpos, curparamstr);
+            }
+        }
+    }
+    
+    return str;
+}
+
+
+///// STATES /////
+
+default
+{
+    state_entry()
+    {
+    }
+    
+    link_message(integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_TRANSLATION_REQUEST) {            
+            
+            // // PROCESS REQUEST // //
+        
+            // Split the incoming message into fields
+            list fields = llParseStringKeepNulls(str, ["|"], []);
+            integer numfields = llGetListLength(fields);
+            
+            // Extract and check the localization batch
+            string batch = "";
+            if (numfields > 4) batch = llList2String(fields, 4);
+            if (batch != mybatch) return;
+            
+            // We expect at least 3 fields
+            // ... or 4 if there are insertion parameters...
+            // ... anybody up for a 6th parameter? :)
+            if (numfields < 3) {
+                sloodle_debug("ERROR: Insufficient fields for translation of string.");
+                return;
+            }
+            
+            // Extract the key parts of the request
+            string output_method = llList2String(fields, 0);
+            list output_params = llCSV2List(llList2String(fields, 1));
+            integer num_output_params = llGetListLength(output_params);
+            string string_name = llList2String(fields, 2);
+            list string_params = [];
+            if (numfields > 3) {
+                // Extract the string parameters (extra text added to the output)
+                string string_param_text = llList2String(fields, 3);
+                if (string_param_text != "") string_params = llCSV2List(string_param_text);
+            }
+            
+            // // TRANSLATE STRING // //
+            
+            // This string will store the translation
+            string trans = "";
+            // Do nothing if the string name is empty
+            if (string_name != "") {
+                // If there are no string parameters, then it is only a basic translation
+                if (llGetListLength(string_params) == 0) {
+                    // Get the basic translation
+                    trans = sloodle_get_string(string_name);
+                } else {
+                    // Construct the formatted string
+                    trans = sloodle_get_string_f(string_name, string_params);
+                }
+            }
+            
+            // // OUTPUT STRING // //
+            
+            // Check what output method has been requested
+            if (output_method == SLOODLE_TRANSLATE_LINK) {
+                // Return the string via link message
+                sloodle_translation_response(sender_num, string_name, trans);
+                
+            } else if (output_method == SLOODLE_TRANSLATE_SAY) {
+                // Say the string
+                if (num_output_params > 0) llSay(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to say string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_WHISPER) {
+                // Whisper the string
+                if (num_output_params > 0) llWhisper(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to whisper string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_SHOUT) {
+                // Shout the string
+                if (num_output_params > 0) llShout(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to shout string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_REGION_SAY) {
+                // RegionSay the string
+                if (num_output_params > 0) llRegionSay(llList2Integer(output_params, 0), trans);
+                else sloodle_debug("ERROR: Insufficient output parameters to region-say string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_OWNER_SAY) {
+                // Ownersay the string
+                llOwnerSay(trans);
+                
+            } else if (output_method == SLOODLE_TRANSLATE_DIALOG) {
+                // Display a dialog - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to show dialog with string \"" + string_name + "\".");
+                    return;
+                }
+                // We need at least 2 additional output parameters (channel, and at least 1 button)
+                if (num_output_params >= 2) {
+                    // Extract the channel number
+                    integer channel = llList2Integer(output_params, 0);
+                    // Extract up to 12 button values
+                    list buttons = llList2List(output_params, 1, 12);
+                    
+                    // Display the dialog
+                    llDialog(id, trans, buttons, channel);
+                    
+                } else sloodle_debug("ERROR: Insufficient output parameters to show dialog with string \"" + string_name + "\".");
+                
+            } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL) {
+                // Display a URL - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
+                    return;
+                }                
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 1) llLoadURL(id, trans, llList2String(output_params, 0));
+                else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL_PARALLEL) {
+                // Display a URL - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
+                    return;
+                }
+                
+                // NOTE: currently the parallel URL loaders will drop any text.
+                // TODO: make parallel URL loaders use text as well.
+                
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 1) llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_LOAD_URL, llList2String(output_params, 0), id);
+                else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
+            
+            } else if (output_method == SLOODLE_TRANSLATE_HOVER_TEXT) {
+                //example usage: sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [BLUE, 1.0], "quizname", [quiz_name], llGetOwner(), "quizzer");
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 2) llSetText(trans, (vector)llList2String(output_params, 0), (float)llList2String(output_params, 1));
+                else sloodle_debug("ERROR: Insufficient output parameters to show hover text with string \"" + string_name + "\".");
+            } else if (output_method == SLOODLE_TRANSLATE_HOVER_TEXT_LINKED_PRIM) {
+                //example usage: sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT_LINKED_PRIM, [BLUE, 1.0,7], "quizname", [quiz_name], llGetOwner(), "quizzer");
+                // We need 1 additional parameter, containing the URL to load
+                if (num_output_params >= 3) {
+                    list rules = [ PRIM_TEXT, trans, (vector)llList2String(output_params, 0), (float)llList2String(output_params, 1) ];
+                    llSetLinkPrimitiveParamsFast( llList2Integer(output_params, 2), rules );
+                }
+                else sloodle_debug("ERROR: Insufficient output parameters to show hover text with string \"" + string_name + "\". Expecting translation text, color vector, alpha float.");
+            
+            }
+             else if (output_method == SLOODLE_TRANSLATE_IM) {
+                // Send an IM - we need a valid key
+                if (id == NULL_KEY) {
+                    sloodle_debug("ERROR: Non-null key value required to send IM with string \"" + string_name + "\".");
+                    return;
+                }                
+                // Send the IM
+                llInstantMessage(id, trans);
+
+            } else {
+                // Don't know the output method
+                sloodle_debug("ERROR: unrecognised output method \"" + output_method + "\".");
+            }
+        }
+    }
+}
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: assets/lang/en/sloodle_translation_en.lslp 
+

BIN
iar/assets/6969bc92-e498-4cbc-ba37-d377cec437cf_animation.bvh


+ 216 - 0
iar/assets/696f7f0e-d61a-8241-71c5-80a1d0b9110a_script.lsl

@@ -0,0 +1,216 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+//////////
+//
+// Sloodle Toolbar menu script (v2.0)
+// Controls the Toolbar as a whole, and runs the Classroom Gestures
+// Part of the Sloodle project (www.sloodle.org)
+//
+// Copyright (c) 2006-8 Sloodle (various contributors)
+// Released under the GNU GPL
+//
+// Contributors:
+//  - <unknown>
+//  - Peter R. Bloomfield
+//
+//////////
+//
+// Versions:
+//  2.1 - added auto-hide feature (although it might not be very good yet... I think we need a better method!)
+//  2.0 - centralised animation control in this script (rather than separate scripts)
+//  - <history unknown>
+//
+//////////
+//
+// Usage:
+//  This script should be in the *root* prim of an object, and expects that a series of linked
+//   child prims are given names such as "gesture:wave". These objects should *not* process their
+//   own "touch_start" events, but should pass them back to the parent (this is the default behaviour).
+//  When "touch_start" is called, this object will get the name of the prim that was touched, and
+//   look it up in a list of animation data. It will start/stop the associated animation as appropriate.
+//
+//  If the root prim is touched, then it flips between the two modes of operation.
+//  If the "minimize_button" is touched, then it auto-hides or unhides itself.
+//  
+//
+//////////
+
+// Name of the button objects
+string MINIMIZE_BUTTON = "minimize_button";
+string RESTORE_BUTTON = "restore_button";
+string HELP_BUTTON = "help_button";
+
+// Name of the help notecard
+string HELP_NOTECARD = "Sloodle Toolbar Help";
+
+// Is the toolbar flipped over? (i.e. is it on gestures?)
+integer flipped = 0;
+// Is the toolbar currently hidden ('minimized')?
+integer hidden = 0;
+// Sound to be played when the toolbar is touched
+string touchSound = "";
+
+// This list stores information in sets of 3:
+//  {string:name of gesture button} {string:name of animation} {integer:playing?}
+// The name of the gesture button is also used as the name of a language string in the "toolbar" batch.
+// That language string will be echoed to chat.
+// The "playing?" item can have one of 3 values. If the animation only plays once at a time, it should be -1.
+//  If the animation loops, but it is *not* currently playing, it should be 0. If it loops and is currently playing, it should be 1.
+list animdata = [   "gesture:handup", "LongRaise", 0,
+                    "gesture:wave", "Wave", 0,
+                    "gesture:clap", "clap", -1,
+                    "gesture:nodoff", "Nodoff", -1,
+                    "gesture:huh", "IDontUnderstand", -1,
+                    "gesture:gotit", "gotit", -1,
+                    "gesture:yes", "Yes", -1,
+                    "gesture:no", "No", -1
+                ];
+
+
+///// TRANSLATIONS /////
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";                     // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";                       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";                   // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";          // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";            // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";                 // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";              // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_LOAD_URL_PARALLEL = "loadurlpar";  // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";          // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";             // Recipient avatar should be identified in link message keyval. No output parameters.
+
+// Used for sending parallel URL loading messages
+integer SLOODLE_CHANNEL_OBJECT_LOAD_URL = -1639270041;
+
+// Send a translation request link message
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+                
+///// STATES /////
+
+default
+{
+    state_entry()
+    {
+        // We need to get animation permissions
+        llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION);
+        // Preload the touching sound
+        if(touchSound != ""){
+            llPreloadSound(touchSound); 
+        }
+
+    }
+    
+    on_rez(integer param)
+    {
+        llSetRot(ZERO_ROTATION);
+        llResetScript();
+    }
+    
+    run_time_permissions(integer id)
+    {
+    }
+
+    touch_start(integer total_number)
+    {
+        // Which link was touched?
+        integer linknumber = llDetectedLinkNumber(0);
+        string name = llGetLinkName(linknumber);
+
+        // Is the toolbar currently hidden?
+        if (hidden == 1) {
+            // If the restore button was pressed, then unhide it. Otherwise, ignore the touch.
+            if (name == RESTORE_BUTTON) {
+                hidden = 0;
+                if (flipped) llSetRot(llEuler2Rot(<0,PI,0>));
+                else llSetRot(ZERO_ROTATION);
+            }
+            return;
+        }
+        // Was the minimize button pressed?
+        if (name == MINIMIZE_BUTTON) {
+            // Hide it
+            hidden = 1;
+            llSetRot(llEuler2Rot(<0,PI * 0.5,0>));
+            return;
+        }
+
+        // Ignore any other touches if we are hidden
+        if (hidden == 1) return;
+        
+        // So what else was touched?
+        if (name == llGetObjectName()) {
+            // The toggle tabs were touched
+            // Toggle the rotation between gestures and blog
+            if (!flipped)
+            {
+                llSetRot(llEuler2Rot(<0,PI,0>));
+                flipped = 1;
+            }
+            else
+            {
+                llSetRot(ZERO_ROTATION);
+                flipped = 0;
+            }
+            return;
+        } else if (name == HELP_BUTTON) {
+            // The help button was touched - give the help notecard
+            if (llGetInventoryType(HELP_NOTECARD) == INVENTORY_NOTECARD) {
+                llGiveInventory(llDetectedKey(0), HELP_NOTECARD);
+            } else {
+                // Nothing to give
+                sloodle_translation_request(SLOODLE_TRANSLATE_OWNER_SAY, [], "helpnotecardnotfound", [HELP_NOTECARD], NULL_KEY, "toolbar");
+            }
+            return;
+        }
+        
+        // Was this a gesture command?
+        integer pos = llListFindList(animdata, [name]);
+        if (pos >= 0) {
+            // Make sure there is enough data (there should be 2 more elements beyond the button name)
+            if ((pos + 2) >= llGetListLength(animdata)) return;
+            // Extract the animation data
+            string animname = llList2String(animdata, pos + 1);
+            integer playing = llList2Integer(animdata, pos + 2);
+            string avname = llKey2Name(llGetOwner());
+            
+            // What do we do?
+            if (playing < 0) {
+                // Play the animation once and echo the gesture to chat
+                llStartAnimation(animname);
+                llSay(0, avname + " " + animtext);
+                sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], name, [avname], NULL_KEY, "toolbar");
+                
+            } else if (playing == 0) {
+                // Start playing the animation and echo the gesture to chat
+                llStartAnimation(animname);
+                sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], name, [avname], NULL_KEY, "toolbar");
+                // Set the "playing" flag to 1
+                animdata = llListReplaceList(animdata, [1], (pos + 2), (pos + 2));
+                // Highlight the button
+                llSetLinkColor(linknumber, <1.0,1.0,0.0>, ALL_SIDES);
+                
+            } else if (playing > 0) {
+                // Stop playing the animation
+                llStopAnimation(animname);
+                // Set the "playing" flag back to 0
+                animdata = llListReplaceList(animdata, [0], (pos + 2), (pos + 2));
+                // Deactivate the button highlight
+                llSetLinkColor(linknumber, <1.0,1.0,1.0>, ALL_SIDES);
+            }
+        }
+    }
+}
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/toolbar_giver-1.0/objects/toolbar/assets/toolbar-menu.lslp 

+ 52 - 0
iar/assets/6b000664-a9cb-b6c7-eab7-1868b0547779_script.lsl

@@ -0,0 +1,52 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+integer SLOODLE_CHANNEL_OBJECT_DIALOG                   = -3857343;//configuration channel
+integer counter;
+
+default
+{
+    state_entry()
+    {
+       llSetPrimitiveParams(    [ PRIM_GLOW,2,0.0 ] );
+                llSetPrimitiveParams(    [ PRIM_GLOW,0,0.0 ] );
+          counter=0;
+    }
+
+    link_message(integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+  // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // What was the message?
+            if (str == "do:reset"){
+                   llTriggerSound("powerdown",1.0);              
+                llSetPrimitiveParams(    [ PRIM_GLOW,2,0.0 ] );
+                llSetPrimitiveParams(    [ PRIM_GLOW,0,0.0 ] );
+                }
+        }
+        if (num != -99) return;
+        else {
+            if (str == "do:reset") llResetScript();
+            // What was the message?
+            else
+            if (str == "turn glow on"){
+                llTriggerSound("powerup",1.0);
+              llSetPrimitiveParams(    [ PRIM_GLOW,2,0.40 ] );
+              llSetPrimitiveParams(    [ PRIM_GLOW,0,0.40 ] );
+            }else
+            if (str == "turn glow off"){
+                llTriggerSound("powerdown",1.0);              
+                llSetPrimitiveParams(    [ PRIM_GLOW,2,0.0 ] );
+                llSetPrimitiveParams(    [ PRIM_GLOW,0,0.0 ] );
+            }
+
+        }  
+    }              
+   
+
+}
+
+
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/set-1.0/objects/default/assets/sloodle_set_back_glow.lslp 

BIN
iar/assets/6b265e92-3f9f-41a8-a3b6-ec1fb5e034c6_texture.jp2


+ 191 - 0
iar/assets/6be2920f-64b3-316c-b5a2-35c2e59371f1_script.lsl

@@ -0,0 +1,191 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle Registration / Enrolment Booth (for Sloodle 0.4)
+// Allows users to touch a panel to do manual registration of their avatar,
+//  and/or enrolment of their Moodle account.
+//
+// Copyright (c) 2007-9 Sloodle
+// Released under the GNU GPL
+//
+// Contributors:
+//  Edmund Edgar
+//  Peter R. Bloomfield
+//
+
+integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;
+string SLOODLE_EOF = "sloodleeof";
+
+string SLOODLE_OBJECT_TYPE = "regenrolbooth-1.0";
+
+integer SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC = 0;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_OWNER = 1;
+integer SLOODLE_OBJECT_ACCESS_LEVEL_GROUP = 2;
+
+string sloodleserverroot = "";
+string sloodlepwd = "";
+integer sloodlecontrollerid = 0;
+integer sloodleobjectaccessleveluse = 0; // Who can use this object?
+
+integer isconfigured = FALSE; // Do we have all the configuration data we need?
+integer eof = FALSE; // Have we reached the end of the configuration data?
+
+
+///// TRANSLATION /////
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";             // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";           // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";  // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";    // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";         // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";      // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";  // 2 output parameters: colour <r,g,b>, and alpha value
+string SLOODLE_TRANSLATE_IM = "instantmessage";     // Recipient avatar should be identified in link message keyval. No output parameters.
+
+// Send a translation request link message
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+///// ----------- /////
+
+
+///// FUNCTIONS /////
+
+sloodle_debug(string msg)
+{
+    llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
+}
+
+// Configure by receiving a linked message from another script in the object
+// Returns TRUE if the object has all the data it needs
+integer sloodle_handle_command(string str) 
+{
+    list bits = llParseString2List(str,["|"],[]);
+    integer numbits = llGetListLength(bits);
+    string name = llList2String(bits,0);
+    string value1 = "";
+    string value2 = "";
+    
+    if (numbits > 1) value1 = llList2String(bits,1);
+    if (numbits > 2) value2 = llList2String(bits,2);
+    
+    if (name == "set:sloodleserverroot") sloodleserverroot = value1;
+    else if (name == "set:sloodlepwd") {
+        // The password may be a single prim password, or a UUID and a password
+        if (value2 != "") sloodlepwd = value1 + "|" + value2;
+        else sloodlepwd = value1;
+        
+    } else if (name == "set:sloodlecontrollerid") sloodlecontrollerid = (integer)value1;
+    else if (name == "set:sloodleobjectaccessleveluse") sloodleobjectaccessleveluse = (integer)value1;
+    else if (name == SLOODLE_EOF) eof = TRUE;
+    
+    return (sloodleserverroot != "" && sloodlepwd != "" && sloodlecontrollerid > 0);
+}
+
+// Checks if the given agent is permitted to user this object
+// Returns TRUE if so, or FALSE if not
+integer sloodle_check_access_use(key id)
+{
+    // Check the access mode
+    if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_GROUP) {
+        return llSameGroup(id);
+    } else if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC) {
+        return TRUE;
+    }
+    
+    // Assume it's owner mode
+    return (id == llGetOwner());
+}
+
+
+///// STATES /////
+
+// Default state - waiting for configuration
+default
+{
+    
+    state_entry()
+    {
+        // Starting again with a new configuration
+        isconfigured = FALSE;
+        eof = FALSE;
+        // Reset our data
+        sloodleserverroot = "";
+        sloodlepwd = "";
+        sloodlecontrollerid = 0;
+        sloodleobjectaccessleveluse = 0;
+    }
+    
+    link_message( integer sender_num, integer num, string str, key id)
+    {
+        // Check the channel
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            // Split the message into lines
+            list lines = llParseString2List(str, ["\n"], []);
+            integer numlines = llGetListLength(lines);
+            integer i = 0;
+            for (i=0; i < numlines; i++) {
+                isconfigured = sloodle_handle_command(llList2String(lines, i));
+            }
+            
+            // If we've got all our data AND reached the end of the configuration data, then move on
+            if (eof == TRUE) {
+                if (isconfigured == TRUE) {
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configurationreceived", [], NULL_KEY, "");
+                    state ready;
+                } else {
+                    // Got all configuration but, it's not complete... request reconfiguration
+                    sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configdatamissing", [], NULL_KEY, "");
+                    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:reconfigure", NULL_KEY);
+                    eof = FALSE;
+                }
+            }
+        }
+    }
+    
+    touch_start(integer num_detected)
+    {
+        // Attempt to request a reconfiguration
+        if (llDetectedKey(0) == llGetOwner()) {
+            llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:requestconfig", NULL_KEY);
+        }
+    }
+}
+
+state ready
+{
+    on_rez( integer param)
+    {
+        state default;
+    }
+        
+    touch_start( integer total_number)
+    {
+        // Go through each toucher
+        integer i = 0;
+        key id = NULL_KEY;
+        string touched = "";
+        for (i=0; i < total_number; i++) {
+            id = llDetectedKey(i);
+            // Check if this user can use the device
+            if (sloodle_check_access_use(id)) {
+                // Was it the panel that was touched?
+                touched = llGetLinkName(llDetectedLinkNumber(i));
+                if (touched == "panel") llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:regenrol|" + sloodleserverroot + "|" + (string)sloodlecontrollerid + "|" + sloodlepwd, id);
+            } else {
+                sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "nopermission:use", [llKey2Name(id)], NULL_KEY, "");
+            }
+        }
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: mod/regenrolbooth-1.0/objects/default/assets/sloodle_mod_regenrolbooth-1.0.lslp 

BIN
iar/assets/6c6c690a-c338-4bc8-adea-88bf1e7782c9_texture.jp2


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
iar/assets/6d0350c7-8088-4bf2-8026-7d23f7658212_object.xml


BIN
iar/assets/6e69433e-9b9c-4b55-ba3a-5c90ceb9b455_texture.jp2


+ 162 - 0
iar/assets/6e7f4324-411b-8919-6333-4381db503da5_script.lsl

@@ -0,0 +1,162 @@
+//
+// The line above should be left blank to avoid script errors in OpenSim.
+
+// Sloodle configuration notecard reader
+// Reads a configuration notecard and transmits the data via link messages to other scripts
+// If the notecard changes, then it automatically resets.
+//
+// Part of the Sloodle project (www.sloodle.org)
+// Copyright (c) 2007-8 Sloodle
+// Released under the GNU GPL v3
+//
+// Contributors:
+//  Edmund Edgar
+//  Peter R. Bloomfield
+
+
+integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;
+string SLOODLE_CONFIG_NOTECARD = "sloodle_config";
+string SLOODLE_EOF = "sloodleeof";
+
+key sloodle_notecard_key = NULL_KEY;
+integer sloodle_notecard_line = 0;
+
+string COMMENT_PREFIX = "//";
+
+key latestnotecard = NULL_KEY; // The most recently read notecard
+
+
+
+///// TRANSLATION /////
+
+// Link message channels
+integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
+integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
+
+// Translation output methods
+string SLOODLE_TRANSLATE_LINK = "link";             // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
+string SLOODLE_TRANSLATE_SAY = "say";               // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_WHISPER = "whisper";       // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_SHOUT = "shout";           // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_REGION_SAY = "regionsay";  // 1 output parameter: chat channel number
+string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay";    // No output parameters
+string SLOODLE_TRANSLATE_DIALOG = "dialog";         // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
+string SLOODLE_TRANSLATE_LOAD_URL = "loadurl";      // Recipient avatar should be identified in link message keyval. 1 output parameter, containing the URL.
+string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext";  // 2 output parameters: colour <r,g,b>, and alpha value
+
+// Send a translation request link message
+sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
+{
+    llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
+}
+
+///// ----------- /////
+
+
+///// FUNCTIONS /////
+
+
+sloodle_tell_other_scripts(string msg)
+{
+    sloodle_debug("notecard sending message to other scripts: "+msg);
+    llMessageLinked(LINK_SET, SLOODLE_CHANNEL_OBJECT_DIALOG, msg, NULL_KEY);   
+}
+
+sloodle_debug(string msg)
+{
+    //llWhisper(0,msg);
+}
+
+sloodle_handle_command(string str) 
+{
+    list bits = llParseString2List(str,["|"],[]);
+    integer numbits = llGetListLength(bits);
+    
+    string name = llList2String(bits,0);
+    string value = "";
+    if (numbits >= 2) llList2String(bits,1);
+
+    // Check the command
+    if (name == "do:reset") {
+        // Reset
+        sloodle_debug("Resetting configuration notecard reader");
+        llResetScript();
+    } else if (name == "do:requestconfig") {
+        // Configuration request
+        sloodle_start_reading_notecard();
+    }
+}
+
+sloodle_start_reading_notecard()
+{
+    // Do we have a configuratio notecard?
+    if (llGetInventoryType(SLOODLE_CONFIG_NOTECARD) == INVENTORY_NOTECARD) {
+        // Start reading it
+        sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<0.0,1.0,0.0>, 1.0], "readingconfignotecard", [], NULL_KEY, "");
+        sloodle_debug("starting reading notecard");
+        sloodle_notecard_line = 0;
+        sloodle_notecard_key = llGetNotecardLine("sloodle_config", 0); // read the first line. The dataserver event will get the next one.
+        latestnotecard = llGetInventoryKey(SLOODLE_CONFIG_NOTECARD);
+    } else {
+        sloodle_debug("No notecard called "+SLOODLE_CONFIG_NOTECARD+" found - skipping notecard configuration");
+        latestnotecard = NULL_KEY;
+    }
+}
+
+
+default 
+{
+    on_rez(integer start_param)
+    {
+        llResetScript();
+    }
+    
+    state_entry() 
+    {
+        // Pause for a moment, in case all scripts were reset at the same time
+        llSleep(0.2);
+        // Go!
+        sloodle_start_reading_notecard();
+    }
+    
+    dataserver(key requested, string data)
+    {
+        if ( requested == sloodle_notecard_key )  // make sure we are getting the data we want
+        {
+            sloodle_notecard_key = NULL_KEY;
+            if ( data != EOF )
+            {
+                // If this is a comment line, then do not forward it
+                string trimmeddata = llStringTrim(data, STRING_TRIM_HEAD);
+                if (llSubStringIndex(trimmeddata, COMMENT_PREFIX) != 0) sloodle_tell_other_scripts(data);
+                // Advance to the next line
+                sloodle_notecard_line++;
+                sloodle_notecard_key = llGetNotecardLine("sloodle_config",sloodle_notecard_line);
+            } else {
+                // This is the end of the configuration data
+                llSleep(0.2);
+                sloodle_tell_other_scripts(SLOODLE_EOF);
+                llSetText("", <0.0,0.0,0.0>, 0.0);
+            }
+        }
+    }
+    
+    link_message(integer sender_num, integer num, string str, key id) {
+        // Ignore debug messages
+        if (num == DEBUG_CHANNEL) return;
+        // Is this an object dialog message?
+        if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
+            sloodle_handle_command(str);
+        }
+    }
+    
+    changed(integer change) {
+        // If the inventory is changed, and we have a Sloodle config notecard, then use it to re-initialise
+        if (change & CHANGED_INVENTORY && llGetInventoryType(SLOODLE_CONFIG_NOTECARD) == INVENTORY_NOTECARD) {
+            // If the current notecard is not the same as the one we read most recently, then reset
+            if (llGetInventoryKey(SLOODLE_CONFIG_NOTECARD) != latestnotecard) llResetScript();
+        }
+    }
+}
+// Please leave the following line intact to show where the script lives in Git:
+// SLOODLE LSL Script Git Location: assets/sloodle_setup_notecard.lslp 

Некоторые файлы не были показаны из-за большого количества измененных файлов