xs_cryocrate.lsl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. // :CATEGORY:XS Pet
  2. // :NAME:XS Pet Xundra Snowpaw Original Quail
  3. // :AUTHOR:Xundra Snowpaw
  4. // :CREATED:2013-09-06
  5. // :EDITED:2013-09-18 15:39:11
  6. // :ID:989
  7. // :NUM:1484
  8. // :REV:1
  9. // :WORLD:Second Life, Opensim
  10. // :DESCRIPTION:
  11. // Original Pet Quail
  12. // :CODE:
  13. integer API_CHANNEL = -999198;
  14. float VERSION = 0.22;
  15. string SECRET_PASSWORD = "top secret";
  16. integer SECRET_NUMBER = 99999;
  17. key YOUR_UUID = "00000000-0000-0000-0000-000000000000";
  18. integer ANIMAL_CHANNEL = -999192;
  19. integer BOX_CHANNEL = -999195;
  20. // DON'T CHANGE THE FOLLOWING! (Unless you know what you are doing!)
  21. integer XTEA_DELTA = 0x9E3779B9; // (sqrt(5) - 1) * 2^31
  22. integer xtea_num_rounds = 6;
  23. list xtea_key = [0, 0, 0, 0];
  24. integer hex2int(string hex) {
  25. if(llGetSubString(hex,0,1) == "0x")
  26. return (integer)hex;
  27. if(llGetSubString(hex,0,0) == "x")
  28. return (integer)("0"+hex);
  29. return(integer)("0x"+hex);
  30. }
  31. // Convers any string to a 32 char MD5 string and then to a list of
  32. // 4 * 32 bit integers = 128 bit Key. MD5 ensures always a specific
  33. // 128 bit key is generated for any string passed.
  34. list xtea_key_from_string( string str )
  35. {
  36. str = llMD5String(str,0); // Use Nonce = 0
  37. return [ hex2int(llGetSubString( str, 0, 7)),
  38. hex2int(llGetSubString( str, 8, 15)),
  39. hex2int(llGetSubString( str, 16, 23)),
  40. hex2int(llGetSubString( str, 24, 31))];
  41. }
  42. // Encipher two integers and return the result as a 12-byte string
  43. // containing two base64-encoded integers.
  44. string xtea_encipher( integer v0, integer v1 )
  45. {
  46. integer num_rounds = xtea_num_rounds;
  47. integer sum = 0;
  48. do {
  49. // LSL does not have unsigned integers, so when shifting right we
  50. // have to mask out sign-extension bits.
  51. v0 += (((v1 << 4) ^ ((v1 >> 5) & 0x07FFFFFF)) + v1) ^ (sum + llList2Integer(xtea_key, sum & 3));
  52. sum += XTEA_DELTA;
  53. v1 += (((v0 << 4) ^ ((v0 >> 5) & 0x07FFFFFF)) + v0) ^ (sum + llList2Integer(xtea_key, (sum >> 11) & 3));
  54. } while( num_rounds = ~-num_rounds );
  55. //return only first 6 chars to remove "=="'s and compact encrypted text.
  56. return llGetSubString(llIntegerToBase64(v0),0,5) +
  57. llGetSubString(llIntegerToBase64(v1),0,5);
  58. }
  59. // Decipher two base64-encoded integers and return the FIRST 30 BITS of
  60. // each as one 10-byte base64-encoded string.
  61. string xtea_decipher( integer v0, integer v1 )
  62. {
  63. integer num_rounds = xtea_num_rounds;
  64. integer sum = XTEA_DELTA*xtea_num_rounds;
  65. do {
  66. // LSL does not have unsigned integers, so when shifting right we
  67. // have to mask out sign-extension bits.
  68. v1 -= (((v0 << 4) ^ ((v0 >> 5) & 0x07FFFFFF)) + v0) ^ (sum + llList2Integer(xtea_key, (sum>>11) & 3));
  69. sum -= XTEA_DELTA;
  70. v0 -= (((v1 << 4) ^ ((v1 >> 5) & 0x07FFFFFF)) + v1) ^ (sum + llList2Integer(xtea_key, sum & 3));
  71. } while ( num_rounds = ~-num_rounds );
  72. return llGetSubString(llIntegerToBase64(v0), 0, 4) +
  73. llGetSubString(llIntegerToBase64(v1), 0, 4);
  74. }
  75. // Encrypt a full string using XTEA.
  76. string xtea_encrypt_string( string str )
  77. {
  78. // encode string
  79. str = llStringToBase64(str);
  80. // remove trailing =s so we can do our own 0 padding
  81. integer i = llSubStringIndex( str, "=" );
  82. if ( i != -1 )
  83. str = llDeleteSubString( str, i, -1 );
  84. // we don't want to process padding, so get length before adding it
  85. integer len = llStringLength(str);
  86. // zero pad
  87. str += "AAAAAAAAAA=";
  88. string result;
  89. i = 0;
  90. do {
  91. // encipher 30 (5*6) bits at a time.
  92. result += xtea_encipher(llBase64ToInteger(llGetSubString(str, i, i + 4) + "A="), llBase64ToInteger(llGetSubString(str, i+5, i + 9) + "A="));
  93. i+=10;
  94. } while ( i < len );
  95. return result;
  96. }
  97. // Decrypt a full string using XTEA
  98. string xtea_decrypt_string( string str ) {
  99. integer len = llStringLength(str);
  100. integer i=0;
  101. string result;
  102. //llOwnerSay(str);
  103. do {
  104. integer v0;
  105. integer v1;
  106. v0 = llBase64ToInteger(llGetSubString(str, i, i + 5) + "==");
  107. i+= 6;
  108. v1 = llBase64ToInteger(llGetSubString(str, i, i + 5) + "==");
  109. i+= 6;
  110. result += xtea_decipher(v0, v1);
  111. } while ( i < len );
  112. // Replace multiple trailing zeroes with a single one
  113. i = llStringLength(result) - 1;
  114. while ( llGetSubString(result, i - 1, i) == "AA" ){
  115. result = llDeleteSubString(result, i, i);
  116. i--;
  117. }
  118. i = llStringLength(result) - 1;
  119. // while (llGetSubString(result, i, i + 1) == "A" ) {
  120. // i--;
  121. // }
  122. result = llGetSubString(result, 0, i+1);
  123. i = llStringLength(result);
  124. integer mod = i%4; //Depending on encoded length diffrent appends are needed
  125. if(mod == 1) result += "A==";
  126. else if(mod == 2 ) result += "==";
  127. else if(mod == 3) result += "=";
  128. return llBase64ToString(result);
  129. }
  130. string base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  131. vector colour1;
  132. vector colour2;
  133. integer gen;
  134. integer shine;
  135. float glow;
  136. key uuid;
  137. integer listener;
  138. integer owner_touch;
  139. integer sex;
  140. integer age;
  141. integer hunger;
  142. string myname;
  143. integer glow_gene;
  144. string special;
  145. say_details()
  146. {
  147. string mysex;
  148. string myshine;
  149. if (sex == 1) {
  150. mysex = "Male";
  151. } else
  152. if (sex == 2) {
  153. mysex = "Female";
  154. } else {
  155. mysex = (string)sex;
  156. }
  157. if (shine == 0) {
  158. myshine = "None";
  159. } else
  160. if (shine == 1) {
  161. myshine = "Low";
  162. } else
  163. if (shine == 2) {
  164. myshine = "Medium";
  165. } else
  166. if (shine == 3) {
  167. myshine = "High";
  168. }
  169. llWhisper(0, "Head/Body Colour: " + (string)colour1);
  170. llWhisper(0, "Tail/Wing Colour: " + (string)colour2);
  171. llWhisper(0, "Shine: " + myshine);
  172. llWhisper(0, "Glow: " + (string)((integer)(glow * 100)) + "%");
  173. llWhisper(0, "Special: " + special);
  174. llWhisper(0, "Sex: " + mysex);
  175. llWhisper(0, "Age: " + (string)age + " days");
  176. llWhisper(0, "Generation: " + (string)gen);
  177. llSay(API_CHANNEL, "XSQuail^" + (string)llGetKey() + "^" + (string)colour1 + "^" + (string)colour2 + "^" + (string)shine + "^" + (string)glow + "^" + special + "^" + (string)gen + "^" + (string)sex + "^" + (string)age + "^XSQuailEnd");
  178. }
  179. set_colours(vector c1, vector c2, integer shine, float glow)
  180. {
  181. llSetPrimitiveParams([PRIM_COLOR, 0, c1, 1.0, PRIM_COLOR, 1, c1, 1.0, PRIM_COLOR, 3, c1, 1.0, PRIM_COLOR, 5, c1, 1.0, PRIM_COLOR, 2, c2, 1.0, PRIM_COLOR, 4, c2, 1.0, PRIM_BUMP_SHINY, ALL_SIDES, shine, PRIM_BUMP_NONE, PRIM_GLOW, ALL_SIDES, glow]);
  182. }
  183. default
  184. {
  185. state_entry()
  186. {
  187. xtea_key = xtea_key_from_string(SECRET_PASSWORD);
  188. uuid = NULL_KEY;
  189. listener = llListen(BOX_CHANNEL, "", "", "");
  190. }
  191. touch_start(integer num)
  192. {
  193. llWhisper(0, "This Cryo-Crate is v" + (string)VERSION);
  194. }
  195. listen(integer channel, string name, key id, string msg)
  196. {
  197. if (llGetOwnerKey(id) != llGetOwner()) {
  198. return;
  199. }
  200. list data = llParseString2List(xtea_decrypt_string(msg), ["^"], []);
  201. if (uuid == NULL_KEY) {
  202. if (llList2String(data, 0) == "XSPET" && llList2String(data, 2) == "CRATE_PING") {
  203. uuid = id;
  204. llSay(ANIMAL_CHANNEL, xtea_encrypt_string("XSPET^CRATE_PONG^" + (string)id + "^" + (string)VERSION));
  205. llSetTimerEvent(15.0);
  206. }
  207. } else if (uuid == id) {
  208. if (llList2String(data, 0) == "XSPET" && llList2Key(data, 1) == llGetKey()) {
  209. llSetTimerEvent(0.0);
  210. colour1 = (vector)llList2String(data, 2);
  211. colour2 = (vector)llList2String(data, 3);
  212. shine = llList2Integer(data, 4);
  213. glow = llList2Float(data, 5);
  214. gen = llList2Integer(data, 6);
  215. sex = llList2Integer(data, 7);
  216. age = llList2Integer(data, 8);
  217. hunger = llList2Integer(data, 9);
  218. myname = llList2String(data, 10);
  219. glow_gene = llList2Integer(data, 11);
  220. special = llList2String(data, 12);
  221. llListenRemove(listener);
  222. llSay(ANIMAL_CHANNEL, xtea_encrypt_string("XSPET^CRATE_DIE^" + (string)id + "^" + (string)VERSION));
  223. state full;
  224. } else
  225. if (llList2String(data, 0) == "XSPET" && llList2Key(data, 1) != llGetKey()) {
  226. uuid = NULL_KEY;
  227. }
  228. }
  229. }
  230. timer()
  231. {
  232. llSetTimerEvent(0.0);
  233. uuid = NULL_KEY;
  234. }
  235. }
  236. state full
  237. {
  238. state_entry()
  239. {
  240. llSetObjectName("XS Cryo-Crate: " + myname);
  241. set_colours(colour1, colour2, shine, glow);
  242. llListen(API_CHANNEL, "", "", "");
  243. }
  244. touch_start(integer num)
  245. {
  246. owner_touch = 0;
  247. say_details();
  248. if (llDetectedKey(0) == llGetOwner()) {
  249. owner_touch = 1;
  250. integer chan = (integer)llFrand(10000.0) + 1000;
  251. listener = llListen(chan, "", llGetOwner(), "");
  252. llDialog(llGetOwner(), "Would you like to unpackage me?", ["Yes", "No"], chan);
  253. }
  254. llSetTimerEvent(20.0);
  255. }
  256. timer()
  257. {
  258. //llOwnerSay("Menu timeout.");
  259. if (owner_touch == 1) {
  260. llListenRemove(listener);
  261. }
  262. llSetTimerEvent(0.0);
  263. }
  264. listen(integer channel, string name, key id, string msg)
  265. {
  266. if (channel == API_CHANNEL) {
  267. list data = llParseString2List(msg, ["^"], []);
  268. if (llList2String(data, 0) == "XSQuail" && llList2Key(data, 1) == llGetKey()) {
  269. llSay(API_CHANNEL, "XSQuail^" + (string)llGetKey() + "^" + (string)colour1 + "^" + (string)colour2 + "^" + (string)shine + "^" + (string)glow + "^" + special + "^" + (string)gen + "^" + (string)sex + "^" + (string)age + "^XSQuailEnd");
  270. }
  271. } else {
  272. llListenRemove(listener);
  273. if (msg == "Yes") {
  274. state unbox;
  275. }
  276. }
  277. }
  278. }
  279. state unbox
  280. {
  281. state_entry()
  282. {
  283. llRezObject("Quail", llGetPos() + <0.0, 0.0, 0.25>, ZERO_VECTOR, ZERO_ROTATION, SECRET_NUMBER);
  284. }
  285. object_rez(key id)
  286. {
  287. listener = llListen(BOX_CHANNEL, "", id, "");
  288. }
  289. listen(integer channel, string name, key id, string msg)
  290. {
  291. if (channel == BOX_CHANNEL) {
  292. list data = llParseString2List(xtea_decrypt_string(msg), ["^"], []);
  293. if (llList2String(data, 0) == "XSPET" && llList2String(data, 1) == "READY") {
  294. llGiveInventory(id, "XS Egg");
  295. llGiveInventory(id, "Quail");
  296. llSay(ANIMAL_CHANNEL, xtea_encrypt_string("XSPET^CONFIG^" + (string)id + "^" + (string)colour1 + "^" + (string)colour2 + "^" + (string)sex + "^" + (string)shine + "^" + (string)glow + "^" + (string)gen + "^" +(string)age + "^" + (string)hunger + "^" + myname + "^" + (string)glow_gene + "^" + special));
  297. llDie();
  298. }
  299. }
  300. }
  301. }