aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorMelanie Thielker2008-09-25 06:04:47 +0000
committerMelanie Thielker2008-09-25 06:04:47 +0000
commita3fcaef89091fea505eb9d359be87c82450db6d3 (patch)
treefa3c7244e5385b4afb0295bfdfe5a834583663b9 /OpenSim/Region
parentConvergence is almost complete. This brings the diff between the API to < 10k (diff)
downloadopensim-SC_OLD-a3fcaef89091fea505eb9d359be87c82450db6d3.zip
opensim-SC_OLD-a3fcaef89091fea505eb9d359be87c82450db6d3.tar.gz
opensim-SC_OLD-a3fcaef89091fea505eb9d359be87c82450db6d3.tar.bz2
opensim-SC_OLD-a3fcaef89091fea505eb9d359be87c82450db6d3.tar.xz
CONVERGENCE!!!!!!
The entire LSL API is now in the single, shared file OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api_Base.cs This is for both engines. The OSSL function are still separate.
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs8240
-rw-r--r--OpenSim/Region/ScriptEngine/Common/OSSL_BuilIn_Commands.cs18
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IEventReceiver.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs8242
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api_Base.cs8279
7 files changed, 8347 insertions, 16443 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
index 8e24543..8252bfc 100644
--- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
+++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
@@ -60,21 +60,15 @@ namespace OpenSim.Region.ScriptEngine.Common
60 /// <summary> 60 /// <summary>
61 /// Contains all LSL ll-functions. This class will be in Default AppDomain. 61 /// Contains all LSL ll-functions. This class will be in Default AppDomain.
62 /// </summary> 62 /// </summary>
63 public class LSL_BuiltIn_Commands : MarshalByRefObject, LSL_BuiltIn_Commands_Interface 63 public class LSL_BuiltIn_Commands : LSL_Api_Base, LSL_BuiltIn_Commands_Interface
64 { 64 {
65// private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 65// private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
66 66
67 internal ScriptEngineBase.ScriptEngine m_ScriptEngine; 67 internal ScriptEngineBase.ScriptEngine m_ScriptEngineDirect;
68 internal SceneObjectPart m_host;
69 internal uint m_localID;
70 internal UUID m_itemID;
71 internal bool throwErrorOnNotImplemented = true;
72 internal float m_ScriptDelayFactor = 1.0f;
73 internal float m_ScriptDistanceFactor = 1.0f;
74 internal AsyncCommandManager AsyncCommands = null;
75 68
76 public LSL_BuiltIn_Commands(ScriptEngineBase.ScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 69 public LSL_BuiltIn_Commands(ScriptEngineBase.ScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
77 { 70 {
71 m_ScriptEngineDirect = ScriptEngine;
78 m_ScriptEngine = ScriptEngine; 72 m_ScriptEngine = ScriptEngine;
79 m_host = host; 73 m_host = host;
80 m_localID = localID; 74 m_localID = localID;
@@ -95,8 +89,6 @@ namespace OpenSim.Region.ScriptEngine.Common
95 } 89 }
96 90
97 private string m_state = "default"; 91 private string m_state = "default";
98 private DateTime m_timer = DateTime.Now;
99 private bool m_waitingForScriptAnswer=false;
100 92
101 protected void ScriptSleep(int delay) 93 protected void ScriptSleep(int delay)
102 { 94 {
@@ -118,11 +110,6 @@ namespace OpenSim.Region.ScriptEngine.Common
118 return lease; 110 return lease;
119 } 111 }
120 112
121 public Scene World
122 {
123 get { return m_ScriptEngine.World; }
124 }
125
126 public string State 113 public string State
127 { 114 {
128 get { return m_state; } 115 get { return m_state; }
@@ -132,7 +119,7 @@ namespace OpenSim.Region.ScriptEngine.Common
132 { 119 {
133 try 120 try
134 { 121 {
135 m_ScriptEngine.m_EventManager.state_exit(m_localID); 122 m_ScriptEngineDirect.m_EventManager.state_exit(m_localID);
136 123
137 } 124 }
138 catch (AppDomainUnloadedException) 125 catch (AppDomainUnloadedException)
@@ -142,9 +129,9 @@ namespace OpenSim.Region.ScriptEngine.Common
142 m_state = value; 129 m_state = value;
143 try 130 try
144 { 131 {
145 int eventFlags = m_ScriptEngine.m_ScriptManager.GetStateEventFlags(m_localID, m_itemID); 132 int eventFlags = m_ScriptEngineDirect.m_ScriptManager.GetStateEventFlags(m_localID, m_itemID);
146 m_host.SetScriptEvents(m_itemID, eventFlags); 133 m_host.SetScriptEvents(m_itemID, eventFlags);
147 m_ScriptEngine.m_EventManager.state_entry(m_localID); 134 m_ScriptEngineDirect.m_EventManager.state_entry(m_localID);
148 } 135 }
149 catch (AppDomainUnloadedException) 136 catch (AppDomainUnloadedException)
150 { 137 {
@@ -160,2904 +147,7 @@ namespace OpenSim.Region.ScriptEngine.Common
160 return World.GetCommander(name); 147 return World.GetCommander(name);
161 } 148 }
162 149
163 private List<SceneObjectPart> GetLinkParts(int linkType) 150 public LSL_Integer llGetScriptState(string name)
164 {
165 List<SceneObjectPart> ret = new List<SceneObjectPart>();
166 ret.Add(m_host);
167
168 switch (linkType)
169 {
170 case ScriptBaseClass.LINK_SET:
171 if (m_host.ParentGroup != null)
172 return new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
173 return ret;
174
175 case ScriptBaseClass.LINK_ROOT:
176 if (m_host.ParentGroup != null)
177 {
178 ret = new List<SceneObjectPart>();
179 ret.Add(m_host.ParentGroup.RootPart);
180 return ret;
181 }
182 return ret;
183
184 case ScriptBaseClass.LINK_ALL_OTHERS:
185 if (m_host.ParentGroup == null)
186 return new List<SceneObjectPart>();
187 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
188 if (ret.Contains(m_host))
189 ret.Remove(m_host);
190 return ret;
191
192 case ScriptBaseClass.LINK_ALL_CHILDREN:
193 if (m_host.ParentGroup == null)
194 return new List<SceneObjectPart>();
195 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
196 if (ret.Contains(m_host.ParentGroup.RootPart))
197 ret.Remove(m_host.ParentGroup.RootPart);
198 return ret;
199
200 case ScriptBaseClass.LINK_THIS:
201 return ret;
202
203 default:
204 if (linkType < 0 || m_host.ParentGroup == null)
205 return new List<SceneObjectPart>();
206 SceneObjectPart target = m_host.ParentGroup.GetLinkNumPart(linkType);
207 if (target == null)
208 return new List<SceneObjectPart>();
209 ret = new List<SceneObjectPart>();
210 ret.Add(target);
211 return ret;
212
213 }
214 }
215
216 private UUID InventorySelf()
217 {
218 UUID invItemID = new UUID();
219
220 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
221 {
222 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
223 {
224 invItemID = inv.Key;
225 break;
226 }
227 }
228
229 return invItemID;
230 }
231
232 private UUID InventoryKey(string name, int type)
233 {
234 m_host.AddScriptLPS(1);
235 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
236 {
237 if (inv.Value.Name == name)
238 {
239 if (inv.Value.Type != type)
240 return UUID.Zero;
241
242 return inv.Value.AssetID.ToString();
243 }
244 }
245 return UUID.Zero;
246 }
247
248 private UUID InventoryKey(string name)
249 {
250 m_host.AddScriptLPS(1);
251 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
252 {
253 if (inv.Value.Name == name)
254 {
255 return inv.Value.AssetID.ToString();
256 }
257 }
258 return UUID.Zero;
259 }
260
261
262 /// <summary>
263 /// accepts a valid UUID, -or- a name of an inventory item.
264 /// Returns a valid UUID or UUID.Zero if key invalid and item not found
265 /// in prim inventory.
266 /// </summary>
267 /// <param name="k"></param>
268 /// <returns></returns>
269 private UUID KeyOrName(string k)
270 {
271 UUID key = UUID.Zero;
272
273 // if we can parse the string as a key, use it.
274 if (UUID.TryParse(k, out key))
275 {
276 return key;
277 }
278 // else try to locate the name in inventory of object. found returns key,
279 // not found returns UUID.Zero which will translate to the default particle texture
280 else
281 {
282 return InventoryKey(k);
283 }
284 }
285
286 //These are the implementations of the various ll-functions used by the LSL scripts.
287 public LSL_Float llSin(double f)
288 {
289 m_host.AddScriptLPS(1);
290 return (double)Math.Sin(f);
291 }
292
293 public LSL_Float llCos(double f)
294 {
295 m_host.AddScriptLPS(1);
296 return (double)Math.Cos(f);
297 }
298
299 public LSL_Float llTan(double f)
300 {
301 m_host.AddScriptLPS(1);
302 return (double)Math.Tan(f);
303 }
304
305 public LSL_Float llAtan2(double x, double y)
306 {
307 m_host.AddScriptLPS(1);
308 return (double)Math.Atan2(y, x);
309 }
310
311 public LSL_Float llSqrt(double f)
312 {
313 m_host.AddScriptLPS(1);
314 return (double)Math.Sqrt(f);
315 }
316
317 public LSL_Float llPow(double fbase, double fexponent)
318 {
319 m_host.AddScriptLPS(1);
320 return (double)Math.Pow(fbase, fexponent);
321 }
322
323 public LSL_Integer llAbs(int i)
324 {
325 m_host.AddScriptLPS(1);
326 return (int)Math.Abs(i);
327 }
328
329 public LSL_Float llFabs(double f)
330 {
331 m_host.AddScriptLPS(1);
332 return (double)Math.Abs(f);
333 }
334
335 public LSL_Float llFrand(double mag)
336 {
337 m_host.AddScriptLPS(1);
338 lock (Util.RandomClass)
339 {
340 return Util.RandomClass.NextDouble() * mag;
341 }
342 }
343
344 public LSL_Integer llFloor(double f)
345 {
346 m_host.AddScriptLPS(1);
347 return (int)Math.Floor(f);
348 }
349
350 public LSL_Integer llCeil(double f)
351 {
352 m_host.AddScriptLPS(1);
353 return (int)Math.Ceiling(f);
354 }
355
356 // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
357 public LSL_Integer llRound(double f)
358 {
359 m_host.AddScriptLPS(1);
360 return (int)Math.Round(f, MidpointRounding.AwayFromZero);
361 }
362
363 //This next group are vector operations involving squaring and square root. ckrinke
364 public LSL_Float llVecMag(LSL_Vector v)
365 {
366 m_host.AddScriptLPS(1);
367 return LSL_Vector.Mag(v);
368 }
369
370 public LSL_Vector llVecNorm(LSL_Vector v)
371 {
372 m_host.AddScriptLPS(1);
373 double mag = LSL_Vector.Mag(v);
374 LSL_Vector nor = new LSL_Vector();
375 nor.x = v.x / mag;
376 nor.y = v.y / mag;
377 nor.z = v.z / mag;
378 return nor;
379 }
380
381 public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
382 {
383 m_host.AddScriptLPS(1);
384 double dx = a.x - b.x;
385 double dy = a.y - b.y;
386 double dz = a.z - b.z;
387 return Math.Sqrt(dx * dx + dy * dy + dz * dz);
388 }
389
390 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
391
392 // Utility function for llRot2Euler
393
394 // normalize an angle between 0 - 2*PI (0 and 360 degrees)
395 private double NormalizeAngle(double angle)
396 {
397 angle = angle % (Math.PI * 2);
398 if (angle < 0) angle = angle + Math.PI * 2;
399 return angle;
400 }
401
402 // Old implementation of llRot2Euler, now normalized
403
404 public LSL_Vector llRot2Euler(LSL_Rotation r)
405 {
406 m_host.AddScriptLPS(1);
407 //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke
408 LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s);
409 double m = (t.x + t.y + t.z + t.s);
410 if (m == 0) return new LSL_Vector();
411 double n = 2 * (r.y * r.s + r.x * r.z);
412 double p = m * m - n * n;
413 if (p > 0)
414 return new LSL_Vector(NormalizeAngle(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s))),
415 NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))),
416 NormalizeAngle(Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))));
417 else if (n > 0)
418 return new LSL_Vector(0.0, Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
419 else
420 return new LSL_Vector(0.0, -Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
421 }
422
423 /* From wiki:
424 The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
425 in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
426 a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
427 vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
428 */
429
430 /* How we arrived at this llEuler2Rot
431 *
432 * Experiment in SL to determine conventions:
433 * llEuler2Rot(<PI,0,0>)=<1,0,0,0>
434 * llEuler2Rot(<0,PI,0>)=<0,1,0,0>
435 * llEuler2Rot(<0,0,PI>)=<0,0,1,0>
436 *
437 * Important facts about Quaternions
438 * - multiplication is non-commutative (a*b != b*a)
439 * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
440 *
441 * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
442 * Qx = c1+i*s1
443 * Qy = c2+j*s2;
444 * Qz = c3+k*s3;
445 *
446 * Rotations applied in order (from above) Z, Y, X
447 * Q = (Qz * Qy) * Qx
448 * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
449 * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
450 * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
451 * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3
452 * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3 -s1*s2*s3
453 * regroup: x=i*(s1*c2*c3+c1*s2*s3)
454 * y=j*(c1*s2*c3-s1*c2*s3)
455 * z=k*(s1*s2*c3+c1*c2*s3)
456 * s= c1*c2*c3-s1*s2*s3
457 *
458 * This implementation agrees with the functions found here:
459 * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
460 * And with the results in SL.
461 *
462 * It's also possible to calculate llEuler2Rot by direct multiplication of
463 * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
464 * from the wiki).
465 * Apparently in some cases this is better from a numerical precision perspective?
466 */
467
468 public LSL_Rotation llEuler2Rot(LSL_Vector v)
469 {
470 m_host.AddScriptLPS(1);
471
472 double x,y,z,s;
473
474 double c1 = Math.Cos(v.x/2.0);
475 double c2 = Math.Cos(v.y/2.0);
476 double c3 = Math.Cos(v.z/2.0);
477 double s1 = Math.Sin(v.x/2.0);
478 double s2 = Math.Sin(v.y/2.0);
479 double s3 = Math.Sin(v.z/2.0);
480
481 x = s1*c2*c3+c1*s2*s3;
482 y = c1*s2*c3-s1*c2*s3;
483 z = s1*s2*c3+c1*c2*s3;
484 s = c1*c2*c3-s1*s2*s3;
485
486 return new LSL_Rotation(x, y, z, s);
487 }
488
489 public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
490 {
491 m_host.AddScriptLPS(1);
492 double x, y, z, s;
493 int f = 0;
494 // Important Note: q1=<x,y,z,s> is equal to q2=<-x,-y,-z,-s>
495 // Computing quaternion x,y,z,s values
496 x = ((fwd.x - left.y - up.z + 1) / 4);
497 x *= x;
498 x = Math.Sqrt(Math.Sqrt(x));
499 y = ((1 - up.z) / 2 - x * x);
500 y *= y;
501 y = Math.Sqrt(Math.Sqrt(y));
502 z = ((1 - left.y) / 2 - x * x);
503 z *= z;
504 z = Math.Sqrt(Math.Sqrt(z));
505 s = (1 - x * x - y * y - z * z);
506 s *= s;
507 s = Math.Sqrt(Math.Sqrt(s));
508
509 // Set f for signs detection
510 if (fwd.y + left.x >= 0) { f += 1; }
511 if (fwd.z + up.x >= 0) { f += 2; }
512 if (left.z - up.y >= 0) { f += 4; }
513 // Set correct quaternion signs based on f value
514 if (f == 0) { x = -x; }
515 if (f == 1) { x = -x; y = -y; }
516 if (f == 2) { x = -x; z = -z; }
517 if (f == 3) { s = -s; }
518 if (f == 4) { x = -x; s = -s; }
519 if (f == 5) { z = -z; }
520 if (f == 6) { y = -y; }
521
522 LSL_Rotation result = new LSL_Rotation(x, y, z, s);
523
524 // a hack to correct a few questionable angles :(
525 if (llVecDist(llRot2Fwd(result), fwd) > 0.001 || llVecDist(llRot2Left(result), left) > 0.001)
526 result.s = -s;
527
528 return result;
529 }
530
531 public LSL_Vector llRot2Fwd(LSL_Rotation r)
532 {
533 m_host.AddScriptLPS(1);
534
535 double x, y, z, m;
536
537 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
538 // m is always greater than zero
539 // if m is not equal to 1 then Rotation needs to be normalized
540 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
541 {
542 m = 1.0 / Math.Sqrt(m);
543 r.x *= m;
544 r.y *= m;
545 r.z *= m;
546 r.s *= m;
547 }
548
549 // Fast Algebric Calculations instead of Vectors & Quaternions Product
550 x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s;
551 y = 2 * (r.x * r.y + r.z * r.s);
552 z = 2 * (r.x * r.z - r.y * r.s);
553 return (new LSL_Vector(x, y, z));
554 }
555
556 public LSL_Vector llRot2Left(LSL_Rotation r)
557 {
558 m_host.AddScriptLPS(1);
559
560 double x, y, z, m;
561
562 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
563 // m is always greater than zero
564 // if m is not equal to 1 then Rotation needs to be normalized
565 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
566 {
567 m = 1.0 / Math.Sqrt(m);
568 r.x *= m;
569 r.y *= m;
570 r.z *= m;
571 r.s *= m;
572 }
573
574 // Fast Algebric Calculations instead of Vectors & Quaternions Product
575 x = 2 * (r.x * r.y - r.z * r.s);
576 y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s;
577 z = 2 * (r.x * r.s + r.y * r.z);
578 return (new LSL_Vector(x, y, z));
579 }
580
581 public LSL_Vector llRot2Up(LSL_Rotation r)
582 {
583 m_host.AddScriptLPS(1);
584 double x, y, z, m;
585
586 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
587 // m is always greater than zero
588 // if m is not equal to 1 then Rotation needs to be normalized
589 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
590 {
591 m = 1.0 / Math.Sqrt(m);
592 r.x *= m;
593 r.y *= m;
594 r.z *= m;
595 r.s *= m;
596 }
597
598 // Fast Algebric Calculations instead of Vectors & Quaternions Product
599 x = 2 * (r.x * r.z + r.y * r.s);
600 y = 2 * (-r.x * r.s + r.y * r.z);
601 z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s;
602 return (new LSL_Vector(x, y, z));
603 }
604
605 public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
606 {
607 //A and B should both be normalized
608 m_host.AddScriptLPS(1);
609 double dotProduct = LSL_Vector.Dot(a, b);
610 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
611 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
612 double angle = Math.Acos(dotProduct / magProduct);
613 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
614 double s = Math.Sin(angle / 2);
615
616 double x = axis.x * s;
617 double y = axis.y * s;
618 double z = axis.z * s;
619 double w = Math.Cos(angle / 2);
620
621 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
622 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
623
624 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
625 }
626
627 public void llWhisper(int channelID, string text)
628 {
629 m_host.AddScriptLPS(1);
630
631 if (text.Length > 1023)
632 text = text.Substring(0, 1023);
633
634 World.SimChat(Utils.StringToBytes(text),
635 ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
636
637 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
638 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
639 }
640
641 public void llSay(int channelID, string text)
642 {
643 m_host.AddScriptLPS(1);
644
645 if (text.Length > 1023)
646 text = text.Substring(0, 1023);
647
648 World.SimChat(Utils.StringToBytes(text),
649 ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
650
651 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
652 wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
653 }
654
655 public void llShout(int channelID, string text)
656 {
657 m_host.AddScriptLPS(1);
658
659 if (text.Length > 1023)
660 text = text.Substring(0, 1023);
661
662 World.SimChat(Utils.StringToBytes(text),
663 ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, true);
664
665 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
666 wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
667 }
668
669 public void llRegionSay(int channelID, string text)
670 {
671 if (channelID == 0)
672 {
673 LSLError("Cannot use llRegionSay() on channel 0");
674 return;
675 }
676
677 if (text.Length > 1023)
678 text = text.Substring(0, 1023);
679
680 m_host.AddScriptLPS(1);
681
682 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
683 wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
684 }
685
686 public LSL_Integer llListen(int channelID, string name, string ID, string msg)
687 {
688 m_host.AddScriptLPS(1);
689 UUID keyID;
690 UUID.TryParse(ID, out keyID);
691 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
692 return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, keyID, msg);
693 }
694
695 public void llListenControl(int number, int active)
696 {
697 m_host.AddScriptLPS(1);
698 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
699 wComm.ListenControl(m_itemID, number, active);
700 }
701
702 public void llListenRemove(int number)
703 {
704 m_host.AddScriptLPS(1);
705 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
706 wComm.ListenRemove(m_itemID, number);
707 }
708
709 public void llSensor(string name, string id, int type, double range, double arc)
710 {
711 m_host.AddScriptLPS(1);
712 UUID keyID = UUID.Zero;
713 UUID.TryParse(id, out keyID);
714
715 AsyncCommands.SensorRepeatPlugin.SenseOnce(m_localID, m_itemID, name, keyID, type, range, arc, m_host);
716 }
717
718 public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
719 {
720 m_host.AddScriptLPS(1);
721 UUID keyID = UUID.Zero;
722 UUID.TryParse(id, out keyID);
723
724 AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_localID, m_itemID, name, keyID, type, range, arc, rate, m_host);
725 }
726
727 public void llSensorRemove()
728 {
729 m_host.AddScriptLPS(1);
730 AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_localID, m_itemID);
731 }
732
733 public string resolveName(UUID objecUUID)
734 {
735 // try avatar username surname
736 CachedUserInfo profile = World.CommsManager.UserProfileCacheService.GetUserDetails(objecUUID);
737 if (profile != null && profile.UserProfile != null)
738 {
739 string avatarname = profile.UserProfile.FirstName + " " + profile.UserProfile.SurName;
740 return avatarname;
741 }
742 // try an scene object
743 SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID);
744 if (SOP != null)
745 {
746 string objectname = SOP.Name;
747 return objectname;
748 }
749
750 EntityBase SensedObject;
751 lock (World.Entities)
752 {
753 World.Entities.TryGetValue(objecUUID, out SensedObject);
754 }
755
756 if (SensedObject == null)
757 return String.Empty;
758 return SensedObject.Name;
759 }
760
761 public LSL_String llDetectedName(int number)
762 {
763 m_host.AddScriptLPS(1);
764 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
765 if (d == null)
766 return String.Empty;
767 return d.Name;
768 }
769
770 public LSL_String llDetectedKey(int number)
771 {
772 m_host.AddScriptLPS(1);
773 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
774 if (d == null)
775 return String.Empty;
776 return d.Key.ToString();
777 }
778
779 public LSL_String llDetectedOwner(int number)
780 {
781 m_host.AddScriptLPS(1);
782 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
783 if (d == null)
784 return String.Empty;
785 return d.Owner.ToString();
786 }
787
788 public LSL_Integer llDetectedType(int number)
789 {
790 m_host.AddScriptLPS(1);
791 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
792 if (d == null)
793 return 0;
794 return new LSL_Integer(d.Type);
795 }
796
797 public LSL_Vector llDetectedPos(int number)
798 {
799 m_host.AddScriptLPS(1);
800 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
801 if (d == null)
802 return new LSL_Vector();
803 return d.Position;
804 }
805
806 public LSL_Vector llDetectedVel(int number)
807 {
808 m_host.AddScriptLPS(1);
809 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
810 if (d == null)
811 return new LSL_Vector();
812 return d.Velocity;
813 }
814
815 public LSL_Vector llDetectedGrab(int number)
816 {
817 m_host.AddScriptLPS(1);
818 DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number);
819 if (parms == null)
820 return new LSL_Vector(0, 0, 0);
821
822 return parms.OffsetPos;
823 }
824
825 public LSL_Rotation llDetectedRot(int number)
826 {
827 m_host.AddScriptLPS(1);
828 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
829 if (d == null)
830 return new LSL_Rotation();
831 return d.Rotation;
832 }
833
834 public LSL_Integer llDetectedGroup(int number)
835 {
836 m_host.AddScriptLPS(1);
837 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
838 if (d == null)
839 return new LSL_Integer(0);
840 if (m_host.GroupID == d.Group)
841 return new LSL_Integer(1);
842 return new LSL_Integer(0);
843 }
844
845 public LSL_Integer llDetectedLinkNumber(int number)
846 {
847 m_host.AddScriptLPS(1);
848 DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number);
849 if (parms == null)
850 return new LSL_Integer(0);
851
852 return new LSL_Integer(parms.LinkNum);
853 }
854
855 public LSL_Vector llDetectedTouchBinormal(int index)
856 {
857 m_host.AddScriptLPS(1);
858 NotImplemented("llDetectedTouchBinormal");
859 return new LSL_Vector();
860 }
861
862 public LSL_Integer llDetectedTouchFace(int index)
863 {
864 m_host.AddScriptLPS(1);
865 NotImplemented("llDetectedTouchFace");
866 return new LSL_Integer(0);
867 }
868
869 public LSL_Vector llDetectedTouchNormal(int index)
870 {
871 m_host.AddScriptLPS(1);
872 NotImplemented("llDetectedTouchNormal");
873 return new LSL_Vector();
874 }
875
876 public LSL_Vector llDetectedTouchPos(int index)
877 {
878 m_host.AddScriptLPS(1);
879 NotImplemented("llDetectedTouchPos");
880 return new LSL_Vector();
881 }
882
883 public LSL_Vector llDetectedTouchST(int index)
884 {
885 m_host.AddScriptLPS(1);
886 NotImplemented("llDetectedTouchST");
887 return new LSL_Vector();
888 }
889
890 public LSL_Vector llDetectedTouchUV(int index)
891 {
892 m_host.AddScriptLPS(1);
893 NotImplemented("llDetectedTouchUV");
894 return new LSL_Vector();
895 }
896
897 public void llDie()
898 {
899 m_host.AddScriptLPS(1);
900 World.DeleteSceneObject(m_host.ParentGroup);
901 }
902
903 public LSL_Float llGround(LSL_Vector offset)
904 {
905 m_host.AddScriptLPS(1);
906 int x = (int)(m_host.OffsetPosition.X + offset.x);
907 int y = (int)(m_host.OffsetPosition.Y + offset.y);
908 return World.GetLandHeight(x, y);
909 }
910
911 public LSL_Float llCloud(LSL_Vector offset)
912 {
913 m_host.AddScriptLPS(1);
914 return 0;
915 }
916
917 public LSL_Vector llWind(LSL_Vector offset)
918 {
919 m_host.AddScriptLPS(1);
920 return new LSL_Vector();
921 }
922
923 public void llSetStatus(int status, int value)
924 {
925 m_host.AddScriptLPS(1);
926
927 int statusrotationaxis = 0;
928
929 if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS)
930 {
931 if (value == 1)
932 {
933 SceneObjectGroup group = m_host.ParentGroup;
934 if (group == null)
935 return;
936 bool allow = true;
937 foreach (SceneObjectPart part in group.Children.Values)
938 {
939 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
940 {
941 allow = false;
942 break;
943 }
944 }
945
946 if (!allow)
947 return;
948 m_host.ScriptSetPhysicsStatus(true);
949 }
950 else
951 m_host.ScriptSetPhysicsStatus(false);
952 }
953
954 if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM)
955 {
956 if (value == 1)
957 m_host.ScriptSetPhantomStatus(true);
958 else
959 m_host.ScriptSetPhantomStatus(false);
960 }
961
962 if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS)
963 {
964 m_host.AddFlag(PrimFlags.CastShadows);
965 }
966
967 if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X)
968 {
969 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X;
970 }
971
972 if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y)
973 {
974 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y;
975 }
976
977 if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z)
978 {
979 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z;
980 }
981
982 if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB)
983 {
984 NotImplemented("llSetStatus - STATUS_BLOCK_GRAB");
985 }
986
987 if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE)
988 {
989 if (value == 1)
990 m_host.SetDieAtEdge(true);
991 else
992 m_host.SetDieAtEdge(false);
993 }
994
995 if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
996 {
997 NotImplemented("llSetStatus - STATUS_RETURN_AT_EDGE");
998 }
999
1000 if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX)
1001 {
1002 NotImplemented("llSetStatus - STATUS_SANDBOX");
1003 }
1004
1005 if (statusrotationaxis != 0)
1006 {
1007 m_host.SetAxisRotation(statusrotationaxis, value);
1008 }
1009 }
1010
1011 public LSL_Integer llGetStatus(int status)
1012 {
1013 m_host.AddScriptLPS(1);
1014 // Console.WriteLine(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString());
1015 switch (status)
1016 {
1017 case ScriptBaseClass.STATUS_PHYSICS:
1018 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics)
1019 {
1020 return 1;
1021 }
1022 return 0;
1023
1024 case ScriptBaseClass.STATUS_PHANTOM:
1025 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom)
1026 {
1027 return 1;
1028 }
1029 return 0;
1030
1031 case ScriptBaseClass.STATUS_CAST_SHADOWS:
1032 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows)
1033 {
1034 return 1;
1035 }
1036 return 0;
1037
1038 case ScriptBaseClass.STATUS_BLOCK_GRAB:
1039 NotImplemented("llGetStatus - STATUS_BLOCK_GRAB");
1040 return 0;
1041
1042 case ScriptBaseClass.STATUS_DIE_AT_EDGE:
1043 if (m_host.GetDieAtEdge())
1044 return 1;
1045 else
1046 return 0;
1047
1048 case ScriptBaseClass.STATUS_RETURN_AT_EDGE:
1049 NotImplemented("llGetStatus - STATUS_RETURN_AT_EDGE");
1050 return 0;
1051
1052 case ScriptBaseClass.STATUS_ROTATE_X:
1053 NotImplemented("llGetStatus - STATUS_ROTATE_X");
1054 return 0;
1055
1056 case ScriptBaseClass.STATUS_ROTATE_Y:
1057 NotImplemented("llGetStatus - STATUS_ROTATE_Y");
1058 return 0;
1059
1060 case ScriptBaseClass.STATUS_ROTATE_Z:
1061 NotImplemented("llGetStatus - STATUS_ROTATE_Z");
1062 return 0;
1063
1064 case ScriptBaseClass.STATUS_SANDBOX:
1065 NotImplemented("llGetStatus - STATUS_SANDBOX");
1066 return 0;
1067 }
1068 return 0;
1069 }
1070
1071 public void llSetScale(LSL_Vector scale)
1072 {
1073 m_host.AddScriptLPS(1);
1074 SetScale(m_host, scale);
1075 }
1076
1077 private void SetScale(SceneObjectPart part, LSL_Vector scale)
1078 {
1079 // TODO: this needs to trigger a persistance save as well
1080
1081 if (part == null || part.ParentGroup == null || part.ParentGroup.RootPart == null)
1082 return;
1083
1084 if (part.ParentGroup.RootPart.PhysActor != null && part.ParentGroup.RootPart.PhysActor.IsPhysical)
1085 {
1086 if (scale.x > World.m_maxPhys)
1087 scale.x = World.m_maxPhys;
1088 if (scale.y > World.m_maxPhys)
1089 scale.y = World.m_maxPhys;
1090 if (scale.z > World.m_maxPhys)
1091 scale.z = World.m_maxPhys;
1092 }
1093 if (scale.x > World.m_maxNonphys)
1094 scale.x = World.m_maxNonphys;
1095 if (scale.y > World.m_maxNonphys)
1096 scale.y = World.m_maxNonphys;
1097 if (scale.z > World.m_maxNonphys)
1098 scale.z = World.m_maxNonphys;
1099 Vector3 tmp = part.Scale;
1100 tmp.X = (float)scale.x;
1101 tmp.Y = (float)scale.y;
1102 tmp.Z = (float)scale.z;
1103 part.Scale = tmp;
1104 part.SendFullUpdateToAllClients();
1105 }
1106
1107 public LSL_Vector llGetScale()
1108 {
1109 m_host.AddScriptLPS(1);
1110 return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z);
1111 }
1112
1113 public void llSetClickAction(int action)
1114 {
1115 m_host.AddScriptLPS(1);
1116 NotImplemented("llSetClickAction");
1117 return;
1118 }
1119
1120 public void llSetColor(LSL_Vector color, int face)
1121 {
1122 m_host.AddScriptLPS(1);
1123
1124 SetColor(m_host, color, face);
1125 }
1126
1127 private void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1128 {
1129 Primitive.TextureEntry tex = part.Shape.Textures;
1130 Color4 texcolor;
1131 if (face >= 0 && face < GetNumberOfSides(part))
1132 {
1133 texcolor = tex.CreateFace((uint)face).RGBA;
1134 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1135 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1136 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1137 tex.FaceTextures[face].RGBA = texcolor;
1138 part.UpdateTexture(tex);
1139 return;
1140 }
1141 else if (face == ScriptBaseClass.ALL_SIDES)
1142 {
1143 for (uint i = 0; i < GetNumberOfSides(part); i++)
1144 {
1145 if (tex.FaceTextures[i] != null)
1146 {
1147 texcolor = tex.FaceTextures[i].RGBA;
1148 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1149 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1150 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1151 tex.FaceTextures[i].RGBA = texcolor;
1152 }
1153 texcolor = tex.DefaultTexture.RGBA;
1154 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1155 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1156 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1157 tex.DefaultTexture.RGBA = texcolor;
1158 }
1159 part.UpdateTexture(tex);
1160 return;
1161 }
1162 }
1163
1164 public void SetGlow(SceneObjectPart part, int face, float glow)
1165 {
1166 Primitive.TextureEntry tex = part.Shape.Textures;
1167 if (face >= 0 && face < GetNumberOfSides(part))
1168 {
1169 tex.CreateFace((uint) face);
1170 tex.FaceTextures[face].Glow = glow;
1171 part.UpdateTexture(tex);
1172 return;
1173 }
1174 else if (face == ScriptBaseClass.ALL_SIDES)
1175 {
1176 for (uint i = 0; i < GetNumberOfSides(part); i++)
1177 {
1178 if (tex.FaceTextures[i] != null)
1179 {
1180 tex.FaceTextures[i].Glow = glow;
1181 }
1182 tex.DefaultTexture.Glow = glow;
1183 }
1184 part.UpdateTexture(tex);
1185 return;
1186 }
1187 }
1188
1189 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1190 {
1191
1192 Shininess sval = new Shininess();
1193
1194 switch (shiny)
1195 {
1196 case 0:
1197 sval = Shininess.None;
1198 break;
1199 case 1:
1200 sval = Shininess.Low;
1201 break;
1202 case 2:
1203 sval = Shininess.Medium;
1204 break;
1205 case 3:
1206 sval = Shininess.High;
1207 break;
1208 default:
1209 sval = Shininess.None;
1210 break;
1211 }
1212
1213 Primitive.TextureEntry tex = part.Shape.Textures;
1214 if (face >= 0 && face < GetNumberOfSides(part))
1215 {
1216 tex.CreateFace((uint) face);
1217 tex.FaceTextures[face].Shiny = sval;
1218 tex.FaceTextures[face].Bump = bump;
1219 part.UpdateTexture(tex);
1220 return;
1221 }
1222 else if (face == ScriptBaseClass.ALL_SIDES)
1223 {
1224 for (uint i = 0; i < GetNumberOfSides(part); i++)
1225 {
1226 if (tex.FaceTextures[i] != null)
1227 {
1228 tex.FaceTextures[i].Shiny = sval;
1229 tex.FaceTextures[i].Bump = bump;;
1230 }
1231 tex.DefaultTexture.Shiny = sval;
1232 tex.DefaultTexture.Bump = bump;
1233 }
1234 part.UpdateTexture(tex);
1235 return;
1236 }
1237 }
1238
1239 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1240 {
1241 Primitive.TextureEntry tex = part.Shape.Textures;
1242 if (face >= 0 && face < GetNumberOfSides(part))
1243 {
1244 tex.CreateFace((uint) face);
1245 tex.FaceTextures[face].Fullbright = bright;
1246 part.UpdateTexture(tex);
1247 return;
1248 }
1249 else if (face == ScriptBaseClass.ALL_SIDES)
1250 {
1251 for (uint i = 0; i < GetNumberOfSides(part); i++)
1252 {
1253 if (tex.FaceTextures[i] != null)
1254 {
1255 tex.FaceTextures[i].Fullbright = bright;
1256 }
1257 }
1258 tex.DefaultTexture.Fullbright = bright;
1259 part.UpdateTexture(tex);
1260 return;
1261 }
1262 }
1263
1264 public LSL_Float llGetAlpha(int face)
1265 {
1266 m_host.AddScriptLPS(1);
1267 return GetAlpha(m_host, face);
1268 }
1269
1270 private LSL_Float GetAlpha(SceneObjectPart part, int face)
1271 {
1272 Primitive.TextureEntry tex = part.Shape.Textures;
1273 if (face == ScriptBaseClass.ALL_SIDES)
1274 {
1275 int i;
1276 double sum = 0.0;
1277 for (i = 0 ; i < GetNumberOfSides(part) ; i++)
1278 sum += (double)tex.GetFace((uint)i).RGBA.A;
1279 return sum;
1280 }
1281 if (face >= 0 && face < GetNumberOfSides(part))
1282 {
1283 return (double)tex.GetFace((uint)face).RGBA.A;
1284 }
1285 return 0.0;
1286 }
1287
1288 public void llSetAlpha(double alpha, int face)
1289 {
1290 m_host.AddScriptLPS(1);
1291
1292 SetAlpha(m_host, alpha, face);
1293 }
1294
1295 private void SetAlpha(SceneObjectPart part, double alpha, int face)
1296 {
1297 Primitive.TextureEntry tex = part.Shape.Textures;
1298 Color4 texcolor;
1299 if (face >= 0 && face < GetNumberOfSides(part))
1300 {
1301 texcolor = tex.CreateFace((uint)face).RGBA;
1302 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
1303 tex.FaceTextures[face].RGBA = texcolor;
1304 part.UpdateTexture(tex);
1305 return;
1306 }
1307 else if (face == ScriptBaseClass.ALL_SIDES)
1308 {
1309 for (int i = 0; i < GetNumberOfSides(part); i++)
1310 {
1311 if (tex.FaceTextures[i] != null)
1312 {
1313 texcolor = tex.FaceTextures[i].RGBA;
1314 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
1315 tex.FaceTextures[i].RGBA = texcolor;
1316 }
1317 }
1318 texcolor = tex.DefaultTexture.RGBA;
1319 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
1320 tex.DefaultTexture.RGBA = texcolor;
1321 part.UpdateTexture(tex);
1322 return;
1323 }
1324 }
1325
1326 /// <summary>
1327 /// Set flexi parameters of a part.
1328 ///
1329 /// FIXME: Much of this code should probably be within the part itself.
1330 /// </summary>
1331 /// <param name="part"></param>
1332 /// <param name="flexi"></param>
1333 /// <param name="softness"></param>
1334 /// <param name="gravity"></param>
1335 /// <param name="friction"></param>
1336 /// <param name="wind"></param>
1337 /// <param name="tension"></param>
1338 /// <param name="Force"></param>
1339 private void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1340 float wind, float tension, LSL_Vector Force)
1341 {
1342 if (part == null)
1343 return;
1344
1345 bool needs_fakedelete = false;
1346 if (flexi)
1347 {
1348 if (!part.Shape.FlexiEntry)
1349 {
1350 needs_fakedelete = true;
1351 }
1352 part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do
1353 // work once the prim is already flexi
1354 part.Shape.FlexiSoftness = softness;
1355 part.Shape.FlexiGravity = gravity;
1356 part.Shape.FlexiDrag = friction;
1357 part.Shape.FlexiWind = wind;
1358 part.Shape.FlexiTension = tension;
1359 part.Shape.FlexiForceX = (float)Force.x;
1360 part.Shape.FlexiForceY = (float)Force.y;
1361 part.Shape.FlexiForceZ = (float)Force.z;
1362 part.Shape.PathCurve = 0x80;
1363
1364 }
1365 else
1366 {
1367 if (part.Shape.FlexiEntry)
1368 {
1369 needs_fakedelete = true;
1370 }
1371 part.Shape.FlexiEntry = false;
1372 }
1373
1374 needs_fakedelete = false;
1375 if (needs_fakedelete)
1376 {
1377 if (part.ParentGroup != null)
1378 {
1379 part.ParentGroup.FakeDeleteGroup();
1380 }
1381 }
1382
1383 part.ParentGroup.HasGroupChanged = true;
1384 part.ScheduleFullUpdate();
1385 }
1386
1387 /// <summary>
1388 /// Set a light point on a part
1389 ///
1390 /// FIXME: Much of this code should probably be in SceneObjectGroup
1391 /// </summary>
1392 /// <param name="part"></param>
1393 /// <param name="light"></param>
1394 /// <param name="color"></param>
1395 /// <param name="intensity"></param>
1396 /// <param name="radius"></param>
1397 /// <param name="falloff"></param>
1398 private void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1399 {
1400 if (part == null)
1401 return;
1402
1403 if (light)
1404 {
1405 part.Shape.LightEntry = true;
1406 part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f);
1407 part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f);
1408 part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f);
1409 part.Shape.LightIntensity = intensity;
1410 part.Shape.LightRadius = radius;
1411 part.Shape.LightFalloff = falloff;
1412 }
1413 else
1414 {
1415 part.Shape.LightEntry = false;
1416 }
1417
1418 part.ParentGroup.HasGroupChanged = true;
1419 part.ScheduleFullUpdate();
1420 }
1421
1422 public LSL_Vector llGetColor(int face)
1423 {
1424 m_host.AddScriptLPS(1);
1425 return GetColor(m_host, face);
1426 }
1427
1428 private LSL_Vector GetColor(SceneObjectPart part, int face)
1429 {
1430 Primitive.TextureEntry tex = part.Shape.Textures;
1431 Color4 texcolor;
1432 LSL_Vector rgb = new LSL_Vector();
1433 if (face == ScriptBaseClass.ALL_SIDES)
1434 {
1435 int i;
1436
1437 for (i = 0 ; i < GetNumberOfSides(part) ; i++)
1438 {
1439 texcolor = tex.GetFace((uint)i).RGBA;
1440 rgb.x += texcolor.R;
1441 rgb.y += texcolor.G;
1442 rgb.z += texcolor.B;
1443 }
1444
1445 rgb.x /= (float)GetNumberOfSides(part);
1446 rgb.y /= (float)GetNumberOfSides(part);
1447 rgb.z /= (float)GetNumberOfSides(part);
1448
1449 return rgb;
1450 }
1451 if (face >= 0 && face < GetNumberOfSides(part))
1452 {
1453 texcolor = tex.GetFace((uint)face).RGBA;
1454 rgb.x = texcolor.R;
1455 rgb.y = texcolor.G;
1456 rgb.z = texcolor.B;
1457 return rgb;
1458 }
1459 else
1460 {
1461 return new LSL_Vector();
1462 }
1463 }
1464
1465 public void llSetTexture(string texture, int face)
1466 {
1467 m_host.AddScriptLPS(1);
1468 SetTexture(m_host, texture, face);
1469 // ScriptSleep(200);
1470 }
1471
1472 private void SetTexture(SceneObjectPart part, string texture, int face)
1473 {
1474 UUID textureID=new UUID();
1475
1476 if (!UUID.TryParse(texture, out textureID))
1477 {
1478 textureID=InventoryKey(texture, (int)AssetType.Texture);
1479 }
1480
1481 if (textureID == UUID.Zero)
1482 return;
1483
1484 Primitive.TextureEntry tex = part.Shape.Textures;
1485
1486 if (face >= 0 && face < GetNumberOfSides(part))
1487 {
1488 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
1489 texface.TextureID = textureID;
1490 tex.FaceTextures[face] = texface;
1491 part.UpdateTexture(tex);
1492 return;
1493 }
1494 else if (face == ScriptBaseClass.ALL_SIDES)
1495 {
1496 for (uint i = 0; i < GetNumberOfSides(part); i++)
1497 {
1498 if (tex.FaceTextures[i] != null)
1499 {
1500 tex.FaceTextures[i].TextureID = textureID;
1501 }
1502 }
1503 tex.DefaultTexture.TextureID = textureID;
1504 part.UpdateTexture(tex);
1505 return;
1506 }
1507 }
1508
1509 public void llScaleTexture(double u, double v, int face)
1510 {
1511 m_host.AddScriptLPS(1);
1512
1513 ScaleTexture(m_host, u, v, face);
1514 // ScriptSleep(200);
1515 }
1516
1517 private void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1518 {
1519 Primitive.TextureEntry tex = part.Shape.Textures;
1520 if (face >= 0 && face < GetNumberOfSides(part))
1521 {
1522 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
1523 texface.RepeatU = (float)u;
1524 texface.RepeatV = (float)v;
1525 tex.FaceTextures[face] = texface;
1526 part.UpdateTexture(tex);
1527 return;
1528 }
1529 if (face == ScriptBaseClass.ALL_SIDES)
1530 {
1531 for (int i = 0; i < GetNumberOfSides(part); i++)
1532 {
1533 if (tex.FaceTextures[i] != null)
1534 {
1535 tex.FaceTextures[i].RepeatU = (float)u;
1536 tex.FaceTextures[i].RepeatV = (float)v;
1537 }
1538 }
1539 tex.DefaultTexture.RepeatU = (float)u;
1540 tex.DefaultTexture.RepeatV = (float)v;
1541 part.UpdateTexture(tex);
1542 return;
1543 }
1544 }
1545
1546 public void llOffsetTexture(double u, double v, int face)
1547 {
1548 m_host.AddScriptLPS(1);
1549 OffsetTexture(m_host, u, v, face);
1550 // ScriptSleep(200);
1551 }
1552
1553 private void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1554 {
1555 Primitive.TextureEntry tex = part.Shape.Textures;
1556 if (face >= 0 && face < GetNumberOfSides(part))
1557 {
1558 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
1559 texface.OffsetU = (float)u;
1560 texface.OffsetV = (float)v;
1561 tex.FaceTextures[face] = texface;
1562 part.UpdateTexture(tex);
1563 return;
1564 }
1565 if (face == ScriptBaseClass.ALL_SIDES)
1566 {
1567 for (int i = 0; i < GetNumberOfSides(part); i++)
1568 {
1569 if (tex.FaceTextures[i] != null)
1570 {
1571 tex.FaceTextures[i].OffsetU = (float)u;
1572 tex.FaceTextures[i].OffsetV = (float)v;
1573 }
1574 }
1575 tex.DefaultTexture.OffsetU = (float)u;
1576 tex.DefaultTexture.OffsetV = (float)v;
1577 part.UpdateTexture(tex);
1578 return;
1579 }
1580 }
1581
1582 public void llRotateTexture(double rotation, int face)
1583 {
1584 m_host.AddScriptLPS(1);
1585 RotateTexture(m_host, rotation, face);
1586 // ScriptSleep(200);
1587 }
1588
1589 private void RotateTexture(SceneObjectPart part, double rotation, int face)
1590 {
1591 Primitive.TextureEntry tex = part.Shape.Textures;
1592 if (face >= 0 && face < GetNumberOfSides(part))
1593 {
1594 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
1595 texface.Rotation = (float)rotation;
1596 tex.FaceTextures[face] = texface;
1597 part.UpdateTexture(tex);
1598 return;
1599 }
1600 if (face == ScriptBaseClass.ALL_SIDES)
1601 {
1602 for (int i = 0; i < GetNumberOfSides(part); i++)
1603 {
1604 if (tex.FaceTextures[i] != null)
1605 {
1606 tex.FaceTextures[i].Rotation = (float)rotation;
1607 }
1608 }
1609 tex.DefaultTexture.Rotation = (float)rotation;
1610 part.UpdateTexture(tex);
1611 return;
1612 }
1613 }
1614
1615 public LSL_String llGetTexture(int face)
1616 {
1617 m_host.AddScriptLPS(1);
1618 return GetTexture(m_host, face);
1619 }
1620
1621 private LSL_String GetTexture(SceneObjectPart part, int face)
1622 {
1623 Primitive.TextureEntry tex = part.Shape.Textures;
1624 if (face == ScriptBaseClass.ALL_SIDES)
1625 {
1626 face = 0;
1627 }
1628 if (face >= 0 && face < GetNumberOfSides(part))
1629 {
1630 Primitive.TextureEntryFace texface;
1631 texface = tex.GetFace((uint)face);
1632 return texface.TextureID.ToString();
1633 }
1634 else
1635 {
1636 return String.Empty;
1637 }
1638 }
1639
1640 public void llSetPos(LSL_Vector pos)
1641 {
1642 m_host.AddScriptLPS(1);
1643
1644 SetPos(m_host, pos);
1645
1646 ScriptSleep(200);
1647 }
1648
1649 private void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1650 {
1651 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
1652 LSL_Vector currentPos = llGetLocalPos();
1653 if (llVecDist(currentPos, targetPos) > 10.0f * m_ScriptDistanceFactor)
1654 {
1655 targetPos = currentPos + m_ScriptDistanceFactor * 10.0f * llVecNorm(targetPos - currentPos);
1656 }
1657
1658 if (part.ParentID != 0)
1659 {
1660 part.UpdateOffSet(new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z));
1661 }
1662 else
1663 {
1664 part.UpdateGroupPosition(new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z));
1665 }
1666 }
1667
1668 public LSL_Vector llGetPos()
1669 {
1670 m_host.AddScriptLPS(1);
1671 return new LSL_Vector(m_host.AbsolutePosition.X,
1672 m_host.AbsolutePosition.Y,
1673 m_host.AbsolutePosition.Z);
1674 }
1675
1676 public LSL_Vector llGetLocalPos()
1677 {
1678 m_host.AddScriptLPS(1);
1679 if (m_host.ParentID != 0)
1680 {
1681 return new LSL_Vector(m_host.OffsetPosition.X,
1682 m_host.OffsetPosition.Y,
1683 m_host.OffsetPosition.Z);
1684 }
1685 else
1686 {
1687 return new LSL_Vector(m_host.AbsolutePosition.X,
1688 m_host.AbsolutePosition.Y,
1689 m_host.AbsolutePosition.Z);
1690 }
1691 }
1692
1693 public void llSetRot(LSL_Rotation rot)
1694 {
1695 m_host.AddScriptLPS(1);
1696
1697 SetRot(m_host, rot);
1698
1699 ScriptSleep(200);
1700 }
1701
1702 private void SetRot(SceneObjectPart part, LSL_Rotation rot)
1703 {
1704 part.UpdateRotation(new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s));
1705 // Update rotation does not move the object in the physics scene if it's a linkset.
1706 part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition;
1707 }
1708
1709 public LSL_Rotation llGetRot()
1710 {
1711 m_host.AddScriptLPS(1);
1712 Quaternion q = m_host.RotationOffset;
1713 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
1714 }
1715
1716 public LSL_Rotation llGetLocalRot()
1717 {
1718 m_host.AddScriptLPS(1);
1719 return new LSL_Rotation(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W);
1720 }
1721
1722 public void llSetForce(LSL_Vector force, int local)
1723 {
1724 m_host.AddScriptLPS(1);
1725
1726 if (m_host.ParentGroup != null)
1727 {
1728 if (m_host.ParentGroup.RootPart != null)
1729 {
1730 if (local != 0)
1731 force *= llGetRot();
1732
1733 m_host.ParentGroup.RootPart.SetForce(new PhysicsVector((float)force.x, (float)force.y, (float)force.z));
1734 }
1735 }
1736 }
1737
1738 public LSL_Vector llGetForce()
1739 {
1740 LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0);
1741
1742 m_host.AddScriptLPS(1);
1743
1744 if (m_host.ParentGroup != null)
1745 {
1746 if (m_host.ParentGroup.RootPart != null)
1747 {
1748 PhysicsVector tmpForce = m_host.ParentGroup.RootPart.GetForce();
1749 force.x = tmpForce.X;
1750 force.y = tmpForce.Y;
1751 force.z = tmpForce.Z;
1752 }
1753 }
1754
1755 return force;
1756 }
1757
1758 public LSL_Integer llTarget(LSL_Vector position, double range)
1759 {
1760 m_host.AddScriptLPS(1);
1761 return m_host.registerTargetWaypoint(new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range);
1762 }
1763
1764 public void llTargetRemove(int number)
1765 {
1766 m_host.AddScriptLPS(1);
1767 m_host.unregisterTargetWaypoint(number);
1768 }
1769
1770 public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
1771 {
1772 m_host.AddScriptLPS(1);
1773 NotImplemented("llRotTarget");
1774 return 0;
1775 }
1776
1777 public void llRotTargetRemove(int number)
1778 {
1779 m_host.AddScriptLPS(1);
1780 NotImplemented("llRotTargetRemove");
1781 }
1782
1783 public void llMoveToTarget(LSL_Vector target, double tau)
1784 {
1785 m_host.AddScriptLPS(1);
1786 m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau);
1787 }
1788
1789 public void llStopMoveToTarget()
1790 {
1791 m_host.AddScriptLPS(1);
1792 m_host.StopMoveToTarget();
1793 }
1794
1795 public void llApplyImpulse(LSL_Vector force, int local)
1796 {
1797 m_host.AddScriptLPS(1);
1798 //No energy force yet
1799
1800 if (force.x > 20000)
1801 force.x = 20000;
1802 if (force.y > 20000)
1803 force.y = 20000;
1804 if (force.z > 20000)
1805 force.z = 20000;
1806
1807 m_host.ApplyImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
1808 }
1809
1810 public void llApplyRotationalImpulse(LSL_Vector force, int local)
1811 {
1812 m_host.AddScriptLPS(1);
1813 NotImplemented("llApplyRotationalImpulse");
1814 }
1815
1816 public void llSetTorque(LSL_Vector torque, int local)
1817 {
1818 m_host.AddScriptLPS(1);
1819 NotImplemented("llSetTorque");
1820 }
1821
1822 public LSL_Vector llGetTorque()
1823 {
1824 m_host.AddScriptLPS(1);
1825 NotImplemented("llGetTorque");
1826 return new LSL_Vector();
1827 }
1828
1829 public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local)
1830 {
1831 m_host.AddScriptLPS(1);
1832 NotImplemented("llSetForceAndTorque");
1833 }
1834
1835 public LSL_Vector llGetVel()
1836 {
1837 m_host.AddScriptLPS(1);
1838 return new LSL_Vector(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z);
1839 }
1840
1841 public LSL_Vector llGetAccel()
1842 {
1843 m_host.AddScriptLPS(1);
1844 return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z);
1845 }
1846
1847 public LSL_Vector llGetOmega()
1848 {
1849 m_host.AddScriptLPS(1);
1850 return new LSL_Vector(m_host.RotationalVelocity.X, m_host.RotationalVelocity.Y, m_host.RotationalVelocity.Z);
1851 }
1852
1853 public LSL_Float llGetTimeOfDay()
1854 {
1855 m_host.AddScriptLPS(1);
1856 return (double)(((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4)) * World.TimeDilation);
1857 }
1858
1859 public LSL_Float llGetWallclock()
1860 {
1861 m_host.AddScriptLPS(1);
1862 return DateTime.Now.TimeOfDay.TotalSeconds;
1863 }
1864
1865 public LSL_Float llGetTime()
1866 {
1867 m_host.AddScriptLPS(1);
1868 TimeSpan ScriptTime = DateTime.Now - m_timer;
1869 return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation);
1870 }
1871
1872 public void llResetTime()
1873 {
1874 m_host.AddScriptLPS(1);
1875 m_timer = DateTime.Now;
1876 }
1877
1878 public LSL_Float llGetAndResetTime()
1879 {
1880 m_host.AddScriptLPS(1);
1881 TimeSpan ScriptTime = DateTime.Now - m_timer;
1882 m_timer = DateTime.Now;
1883 return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation);
1884 }
1885
1886 public void llSound()
1887 {
1888 m_host.AddScriptLPS(1);
1889 // This function has been deprecated
1890 // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound
1891 Deprecated("llSound");
1892 }
1893
1894 // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
1895 // 20080530 Updated to remove code duplication
1896 public void llPlaySound(string sound, double volume)
1897 {
1898 m_host.AddScriptLPS(1);
1899
1900 // send the sound, once, to all clients in range
1901 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0);
1902 }
1903
1904 // Xantor 20080528 we should do this differently.
1905 // 1) apply the sound to the object
1906 // 2) schedule full update
1907 // just sending the sound out once doesn't work so well when other avatars come in view later on
1908 // or when the prim gets moved, changed, sat on, whatever
1909 // see large number of mantises (mantes?)
1910 // 20080530 Updated to remove code duplication
1911 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
1912 public void llLoopSound(string sound, double volume)
1913 {
1914 m_host.AddScriptLPS(1);
1915
1916 if (m_host.Sound != UUID.Zero)
1917 llStopSound();
1918
1919 m_host.Sound = KeyOrName(sound);
1920 m_host.SoundGain = volume;
1921 m_host.SoundFlags = 1; // looping
1922 m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
1923
1924 m_host.ScheduleFullUpdate();
1925 m_host.SendFullUpdateToAllClients();
1926 }
1927
1928 public void llLoopSoundMaster(string sound, double volume)
1929 {
1930 m_host.AddScriptLPS(1);
1931 NotImplemented("llLoopSoundMaster");
1932 }
1933
1934 public void llLoopSoundSlave(string sound, double volume)
1935 {
1936 m_host.AddScriptLPS(1);
1937 NotImplemented("llLoopSoundSlave");
1938 }
1939
1940 public void llPlaySoundSlave(string sound, double volume)
1941 {
1942 m_host.AddScriptLPS(1);
1943 NotImplemented("llPlaySoundSlave");
1944 }
1945
1946 public void llTriggerSound(string sound, double volume)
1947 {
1948 m_host.AddScriptLPS(1);
1949 // send the sound, once, to all clients in range
1950 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0);
1951 }
1952
1953 // Xantor 20080528: Clear prim data of sound instead
1954 public void llStopSound()
1955 {
1956 m_host.AddScriptLPS(1);
1957
1958 m_host.Sound = UUID.Zero;
1959 m_host.SoundGain = 0;
1960 m_host.SoundFlags = 0;
1961 m_host.SoundRadius = 0;
1962
1963 m_host.ScheduleFullUpdate();
1964 m_host.SendFullUpdateToAllClients();
1965
1966 // m_host.SendSound(UUID.Zero.ToString(), 1.0, false, 2);
1967 }
1968
1969 public void llPreloadSound(string sound)
1970 {
1971 m_host.AddScriptLPS(1);
1972 m_host.PreloadSound(sound);
1973 // ScriptSleep(1000);
1974 }
1975
1976 /// <summary>
1977 /// Return a portion of the designated string bounded by
1978 /// inclusive indices (start and end). As usual, the negative
1979 /// indices, and the tolerance for out-of-bound values, makes
1980 /// this more complicated than it might otherwise seem.
1981 /// </summary>
1982
1983 public LSL_String llGetSubString(string src, int start, int end)
1984 {
1985
1986 m_host.AddScriptLPS(1);
1987
1988 // Normalize indices (if negative).
1989 // After normlaization they may still be
1990 // negative, but that is now relative to
1991 // the start, rather than the end, of the
1992 // sequence.
1993
1994 if (start < 0)
1995 {
1996 start = src.Length+start;
1997 }
1998 if (end < 0)
1999 {
2000 end = src.Length+end;
2001 }
2002
2003 // Conventional substring
2004 if (start <= end)
2005 {
2006 // Implies both bounds are out-of-range.
2007 if (end < 0 || start >= src.Length)
2008 {
2009 return String.Empty;
2010 }
2011 // If end is positive, then it directly
2012 // corresponds to the lengt of the substring
2013 // needed (plus one of course). BUT, it
2014 // must be within bounds.
2015 if (end >= src.Length)
2016 {
2017 end = src.Length-1;
2018 }
2019
2020 if (start < 0)
2021 {
2022 return src.Substring(0,end+1);
2023 }
2024 // Both indices are positive
2025 return src.Substring(start, (end+1) - start);
2026 }
2027
2028 // Inverted substring (end < start)
2029 else
2030 {
2031 // Implies both indices are below the
2032 // lower bound. In the inverted case, that
2033 // means the entire string will be returned
2034 // unchanged.
2035 if (start < 0)
2036 {
2037 return src;
2038 }
2039 // If both indices are greater than the upper
2040 // bound the result may seem initially counter
2041 // intuitive.
2042 if (end >= src.Length)
2043 {
2044 return src;
2045 }
2046
2047 if (end < 0)
2048 {
2049 if (start < src.Length)
2050 {
2051 return src.Substring(start);
2052 }
2053 else
2054 {
2055 return String.Empty;
2056 }
2057 }
2058 else
2059 {
2060 if (start < src.Length)
2061 {
2062 return src.Substring(0,end+1) + src.Substring(start);
2063 }
2064 else
2065 {
2066 return src.Substring(0,end+1);
2067 }
2068 }
2069 }
2070 }
2071
2072 /// <summary>
2073 /// Delete substring removes the specified substring bounded
2074 /// by the inclusive indices start and end. Indices may be
2075 /// negative (indicating end-relative) and may be inverted,
2076 /// i.e. end < start.
2077 /// </summary>
2078
2079 public LSL_String llDeleteSubString(string src, int start, int end)
2080 {
2081
2082 m_host.AddScriptLPS(1);
2083
2084 // Normalize indices (if negative).
2085 // After normlaization they may still be
2086 // negative, but that is now relative to
2087 // the start, rather than the end, of the
2088 // sequence.
2089 if (start < 0)
2090 {
2091 start = src.Length+start;
2092 }
2093 if (end < 0)
2094 {
2095 end = src.Length+end;
2096 }
2097 // Conventionally delimited substring
2098 if (start <= end)
2099 {
2100 // If both bounds are outside of the existing
2101 // string, then return unchanges.
2102 if (end < 0 || start >= src.Length)
2103 {
2104 return src;
2105 }
2106 // At least one bound is in-range, so we
2107 // need to clip the out-of-bound argument.
2108 if (start < 0)
2109 {
2110 start = 0;
2111 }
2112
2113 if (end >= src.Length)
2114 {
2115 end = src.Length-1;
2116 }
2117
2118 return src.Remove(start,end-start+1);
2119 }
2120 // Inverted substring
2121 else
2122 {
2123 // In this case, out of bounds means that
2124 // the existing string is part of the cut.
2125 if (start < 0 || end >= src.Length)
2126 {
2127 return String.Empty;
2128 }
2129
2130 if (end > 0)
2131 {
2132 if (start < src.Length)
2133 {
2134 return src.Remove(start).Remove(0,end+1);
2135 }
2136 else
2137 {
2138 return src.Remove(0,end+1);
2139 }
2140 }
2141 else
2142 {
2143 if (start < src.Length)
2144 {
2145 return src.Remove(start);
2146 }
2147 else
2148 {
2149 return src;
2150 }
2151 }
2152 }
2153 }
2154
2155 /// <summary>
2156 /// Insert string inserts the specified string identified by src
2157 /// at the index indicated by index. Index may be negative, in
2158 /// which case it is end-relative. The index may exceed either
2159 /// string bound, with the result being a concatenation.
2160 /// </summary>
2161
2162 public LSL_String llInsertString(string dest, int index, string src)
2163 {
2164
2165 m_host.AddScriptLPS(1);
2166
2167 // Normalize indices (if negative).
2168 // After normlaization they may still be
2169 // negative, but that is now relative to
2170 // the start, rather than the end, of the
2171 // sequence.
2172 if (index < 0)
2173 {
2174 index = dest.Length+index;
2175
2176 // Negative now means it is less than the lower
2177 // bound of the string.
2178
2179 if (index < 0)
2180 {
2181 return src+dest;
2182 }
2183
2184 }
2185
2186 if (index >= dest.Length)
2187 {
2188 return dest+src;
2189 }
2190
2191 // The index is in bounds.
2192 // In this case the index refers to the index that will
2193 // be assigned to the first character of the inserted string.
2194 // So unlike the other string operations, we do not add one
2195 // to get the correct string length.
2196 return dest.Substring(0,index)+src+dest.Substring(index);
2197
2198 }
2199
2200 public LSL_String llToUpper(string src)
2201 {
2202 m_host.AddScriptLPS(1);
2203 return src.ToUpper();
2204 }
2205
2206 public LSL_String llToLower(string src)
2207 {
2208 m_host.AddScriptLPS(1);
2209 return src.ToLower();
2210 }
2211
2212 public LSL_Integer llGiveMoney(string destination, int amount)
2213 {
2214 UUID invItemID=InventorySelf();
2215 if (invItemID == UUID.Zero)
2216 return 0;
2217
2218 m_host.AddScriptLPS(1);
2219
2220 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
2221 return 0;
2222
2223 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
2224 {
2225 LSLError("No permissions to give money");
2226 return 0;
2227 }
2228
2229 UUID toID=new UUID();
2230
2231 if (!UUID.TryParse(destination, out toID))
2232 {
2233 LSLError("Bad key in llGiveMoney");
2234 return 0;
2235 }
2236
2237 IMoneyModule money=World.RequestModuleInterface<IMoneyModule>();
2238
2239 if (money == null)
2240 {
2241 NotImplemented("llGiveMoney");
2242 return 0;
2243 }
2244
2245 bool result=money.ObjectGiveMoney(m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
2246
2247 if (result)
2248 return 1;
2249
2250 return 0;
2251 }
2252
2253 public void llMakeExplosion()
2254 {
2255 m_host.AddScriptLPS(1);
2256 Deprecated("llMakeExplosion");
2257 // ScriptSleep(100);
2258 }
2259
2260 public void llMakeFountain()
2261 {
2262 m_host.AddScriptLPS(1);
2263 Deprecated("llMakeFountain");
2264 // ScriptSleep(100);
2265 }
2266
2267 public void llMakeSmoke()
2268 {
2269 m_host.AddScriptLPS(1);
2270 Deprecated("llMakeSmoke");
2271 // ScriptSleep(100);
2272 }
2273
2274 public void llMakeFire()
2275 {
2276 m_host.AddScriptLPS(1);
2277 Deprecated("llMakeFire");
2278 // ScriptSleep(100);
2279 }
2280
2281 public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
2282 {
2283 m_host.AddScriptLPS(1);
2284
2285 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
2286 return;
2287 float dist = (float)llVecDist(llGetPos(), pos);
2288
2289 if (dist > m_ScriptDistanceFactor * 10.0f)
2290 return;
2291
2292 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
2293 {
2294 if (inv.Value.Name == inventory)
2295 {
2296 // make sure we're an object.
2297 if (inv.Value.InvType != (int)InventoryType.Object)
2298 {
2299 llSay(0, "Unable to create requested object. Object is missing from database.");
2300 return;
2301 }
2302
2303 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
2304
2305 // test if we're further away then 10m
2306 if (Util.GetDistanceTo(llpos, m_host.AbsolutePosition) > 10)
2307 return; // wiki says, if it's further away then 10m, silently fail.
2308
2309 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z);
2310
2311 // need the magnitude later
2312 float velmag = (float)Util.GetMagnitude(llvel);
2313
2314 SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), llvel, param);
2315
2316 // If either of these are null, then there was an unknown error.
2317 if (new_group == null)
2318 continue;
2319 if (new_group.RootPart == null)
2320 continue;
2321
2322 // objects rezzed with this method are die_at_edge by default.
2323 new_group.RootPart.SetDieAtEdge(true);
2324
2325 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2326 "object_rez", new Object[] {
2327 new LSL_String(
2328 new_group.RootPart.UUID.ToString()) },
2329 new DetectParams[0]));
2330
2331 float groupmass = new_group.GetMass();
2332
2333 //Recoil.
2334 llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0);
2335 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
2336 ScriptSleep((int)((groupmass * velmag) / 10));
2337 // ScriptSleep(100);
2338 return;
2339 }
2340 }
2341 llSay(0, "Could not find object " + inventory);
2342 }
2343
2344 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
2345 {
2346 llRezAtRoot(inventory, pos, vel, rot, param);
2347 }
2348
2349 public void llLookAt(LSL_Vector target, double strength, double damping)
2350 {
2351 m_host.AddScriptLPS(1);
2352 NotImplemented("llLookAt");
2353 }
2354
2355 public void llStopLookAt()
2356 {
2357 m_host.AddScriptLPS(1);
2358 NotImplemented("llStopLookAt");
2359 }
2360
2361 public void llSetTimerEvent(double sec)
2362 {
2363 m_host.AddScriptLPS(1);
2364 // Setting timer repeat
2365 AsyncCommands.TimerPlugin.SetTimerEvent(m_localID, m_itemID, sec);
2366 }
2367
2368 public void llSleep(double sec)
2369 {
2370 m_host.AddScriptLPS(1);
2371 Thread.Sleep((int)(sec * 1000));
2372 }
2373
2374 public LSL_Float llGetMass()
2375 {
2376 m_host.AddScriptLPS(1);
2377 return m_host.GetMass();
2378 }
2379
2380 public void llCollisionFilter(string name, string id, int accept)
2381 {
2382 m_host.AddScriptLPS(1);
2383 NotImplemented("llCollisionFilter");
2384 }
2385
2386 public void llTakeControls(int controls, int accept, int pass_on)
2387 {
2388 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2389 {
2390 return;
2391 }
2392
2393 if (m_host.TaskInventory[InventorySelf()].PermsGranter != UUID.Zero)
2394 {
2395 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter);
2396
2397 if (presence != null)
2398 {
2399 if ((m_host.TaskInventory[InventorySelf()].PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
2400 {
2401 presence.RegisterControlEventsToScript(controls, accept, pass_on, m_localID, m_itemID);
2402
2403 }
2404 }
2405 }
2406
2407 m_host.AddScriptLPS(1);
2408 }
2409
2410 public void llReleaseControls()
2411 {
2412 m_host.AddScriptLPS(1);
2413
2414 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2415 {
2416 return;
2417 }
2418
2419 if (m_host.TaskInventory[InventorySelf()].PermsGranter != UUID.Zero)
2420 {
2421 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter);
2422
2423 if (presence != null)
2424 {
2425 if ((m_host.TaskInventory[InventorySelf()].PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
2426 {
2427 // Unregister controls from Presence
2428 presence.UnRegisterControlEventsToScript(m_localID, m_itemID);
2429 // Remove Take Control permission.
2430 m_host.TaskInventory[InventorySelf()].PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
2431 }
2432 }
2433 }
2434 }
2435
2436 public void llAttachToAvatar(int attachment)
2437 {
2438 m_host.AddScriptLPS(1);
2439 NotImplemented("llAttachToAvatar");
2440 }
2441
2442 public void llDetachFromAvatar()
2443 {
2444 m_host.AddScriptLPS(1);
2445 NotImplemented("llDetachFromAvatar");
2446 }
2447
2448 public void llTakeCamera(string avatar)
2449 {
2450 m_host.AddScriptLPS(1);
2451 Deprecated("llTakeCamera");
2452 }
2453
2454 public void llReleaseCamera(string avatar)
2455 {
2456 m_host.AddScriptLPS(1);
2457 Deprecated("llReleaseCamera");
2458 }
2459
2460 public LSL_String llGetOwner()
2461 {
2462 m_host.AddScriptLPS(1);
2463
2464 return m_host.ObjectOwner.ToString();
2465 }
2466
2467 public void llInstantMessage(string user, string message)
2468 {
2469 m_host.AddScriptLPS(1);
2470
2471 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
2472 // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
2473 // but I don't think we have a list of scenes available from here.
2474 // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
2475
2476 // user is a UUID
2477
2478 // TODO: figure out values for client, fromSession, and imSessionID
2479 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
2480 UUID friendTransactionID = UUID.Random();
2481
2482 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
2483
2484 GridInstantMessage msg = new GridInstantMessage();
2485 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
2486 msg.fromAgentSession = new Guid(friendTransactionID.ToString());// fromAgentSession.UUID;
2487 msg.toAgentID = new Guid(user); // toAgentID.Guid;
2488 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
2489// Console.WriteLine("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
2490// Console.WriteLine("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
2491 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp;
2492 //if (client != null)
2493 //{
2494 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
2495 //}
2496 //else
2497 //{
2498 // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it
2499 //}
2500 msg.message = message;
2501 msg.dialog = (byte)19; // messgage from script ??? // dialog;
2502 msg.fromGroup = false;// fromGroup;
2503 msg.offline = (byte)0; //offline;
2504 msg.ParentEstateID = 0; //ParentEstateID;
2505 msg.Position = Vector3.Zero;// new Vector3(m_host.AbsolutePosition);
2506 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
2507 msg.binaryBucket = new byte[0];// binaryBucket;
2508 World.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
2509 // ScriptSleep(2000);
2510 }
2511
2512 public void llEmail(string address, string subject, string message)
2513 {
2514 m_host.AddScriptLPS(1);
2515 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
2516 if (emailModule == null)
2517 return;
2518
2519 emailModule.SendEmail(m_host.UUID, address, subject, message);
2520 // ScriptSleep(20000);
2521 }
2522
2523 public void llGetNextEmail(string address, string subject)
2524 {
2525 m_host.AddScriptLPS(1);
2526 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
2527 if (emailModule == null)
2528 return;
2529 Email email;
2530
2531 email = emailModule.GetNextEmail(m_host.UUID, address, subject);
2532
2533 if (email == null)
2534 return;
2535
2536 m_ScriptEngine.PostObjectEvent(m_host.LocalId,
2537 new EventParams("email",
2538 new Object[] {
2539 new LSL_String(email.time),
2540 new LSL_String(email.sender),
2541 new LSL_String(email.subject),
2542 new LSL_String(email.message),
2543 new LSL_Integer(email.numLeft)},
2544 new DetectParams[0]));
2545
2546 }
2547
2548 public LSL_String llGetKey()
2549 {
2550 m_host.AddScriptLPS(1);
2551 return m_host.UUID.ToString();
2552 }
2553
2554 public void llSetBuoyancy(double buoyancy)
2555 {
2556 m_host.AddScriptLPS(1);
2557 if (m_host.ParentGroup != null)
2558 {
2559 if (m_host.ParentGroup.RootPart != null)
2560 {
2561 m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy);
2562 }
2563 }
2564 }
2565
2566
2567
2568 public void llSetHoverHeight(double height, int water, double tau)
2569 {
2570 m_host.AddScriptLPS(1);
2571 NotImplemented("llSetHoverHeight");
2572 }
2573
2574 public void llStopHover()
2575 {
2576 m_host.AddScriptLPS(1);
2577 NotImplemented("llStopHover");
2578 }
2579
2580 public void llMinEventDelay(double delay)
2581 {
2582 m_host.AddScriptLPS(1);
2583 NotImplemented("llMinEventDelay");
2584 }
2585
2586 public void llSoundPreload()
2587 {
2588 m_host.AddScriptLPS(1);
2589 Deprecated("llSoundPreload");
2590 }
2591
2592 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
2593 {
2594 m_host.AddScriptLPS(1);
2595 NotImplemented("llRotLookAt");
2596 }
2597
2598 public LSL_Integer llStringLength(string str)
2599 {
2600 m_host.AddScriptLPS(1);
2601 if (str.Length > 0)
2602 {
2603 return str.Length;
2604 }
2605 else
2606 {
2607 return 0;
2608 }
2609 }
2610
2611 public void llStartAnimation(string anim)
2612 {
2613 m_host.AddScriptLPS(1);
2614
2615 UUID invItemID=InventorySelf();
2616 if (invItemID == UUID.Zero)
2617 return;
2618
2619 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
2620 return;
2621
2622 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
2623 {
2624 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter);
2625
2626 if (presence != null)
2627 {
2628 // Do NOT try to parse UUID, animations cannot be triggered by ID
2629 UUID animID=InventoryKey(anim, (int)AssetType.Animation);
2630 if (animID == UUID.Zero)
2631 presence.AddAnimation(anim);
2632 else
2633 presence.AddAnimation(animID);
2634 }
2635 }
2636 }
2637
2638 public void llStopAnimation(string anim)
2639 {
2640 m_host.AddScriptLPS(1);
2641
2642 UUID invItemID=InventorySelf();
2643 if (invItemID == UUID.Zero)
2644 return;
2645
2646 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
2647 return;
2648
2649 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
2650 {
2651 UUID animID = new UUID();
2652
2653 if (!UUID.TryParse(anim, out animID))
2654 {
2655 animID=InventoryKey(anim);
2656 }
2657
2658 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter);
2659
2660 if (presence != null)
2661 {
2662 if (animID == UUID.Zero)
2663 presence.RemoveAnimation(anim);
2664 else
2665 presence.RemoveAnimation(animID);
2666 }
2667 }
2668 }
2669
2670 public void llPointAt()
2671 {
2672 m_host.AddScriptLPS(1);
2673 NotImplemented("llPointAt");
2674 }
2675
2676 public void llStopPointAt()
2677 {
2678 m_host.AddScriptLPS(1);
2679 NotImplemented("llStopPointAt");
2680 }
2681
2682 public void llTargetOmega(LSL_Vector axis, double spinrate, double gain)
2683 {
2684 m_host.AddScriptLPS(1);
2685 m_host.RotationalVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
2686 m_host.AngularVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
2687 m_host.ScheduleTerseUpdate();
2688 m_host.SendTerseUpdateToAllClients();
2689 m_host.ParentGroup.HasGroupChanged = true;
2690 }
2691
2692 public LSL_Integer llGetStartParameter()
2693 {
2694 // This is not handled here
2695 return 0;
2696 }
2697
2698 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
2699 {
2700 m_host.AddScriptLPS(1);
2701 NotImplemented("llGodLikeRezObject");
2702 }
2703
2704 public void llRequestPermissions(string agent, int perm)
2705 {
2706 UUID agentID=new UUID();
2707
2708 if (!UUID.TryParse(agent, out agentID))
2709 return;
2710
2711 UUID invItemID=InventorySelf();
2712
2713 if (invItemID == UUID.Zero)
2714 return; // Not in a prim? How??
2715
2716 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
2717 {
2718 llReleaseControls();
2719
2720 m_host.TaskInventory[invItemID].PermsGranter=UUID.Zero;
2721 m_host.TaskInventory[invItemID].PermsMask=0;
2722
2723 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2724 "run_time_permissions", new Object[] {
2725 new LSL_Integer(0) },
2726 new DetectParams[0]));
2727
2728 return;
2729 }
2730
2731 if ( m_host.TaskInventory[invItemID].PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
2732 llReleaseControls();
2733
2734 m_host.AddScriptLPS(1);
2735
2736 if (m_host.ParentGroup.RootPart.IsAttachment && agent == m_host.ParentGroup.RootPart.AttachedAvatar)
2737 {
2738 // When attached, certain permissions are implicit if requested from owner
2739 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
2740 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
2741 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
2742 ScriptBaseClass.PERMISSION_ATTACH;
2743
2744 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
2745 {
2746 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2747 m_host.TaskInventory[invItemID].PermsMask=perm;
2748
2749 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2750 "run_time_permissions", new Object[] {
2751 new LSL_Integer(perm) },
2752 new DetectParams[0]));
2753
2754 return;
2755 }
2756 }
2757 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar
2758 {
2759 // When agent is sitting, certain permissions are implicit if requested from sitting agent
2760 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
2761 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
2762 ScriptBaseClass.PERMISSION_TRACK_CAMERA;
2763
2764 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
2765 {
2766 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2767 m_host.TaskInventory[invItemID].PermsMask=perm;
2768
2769 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2770 "run_time_permissions", new Object[] {
2771 new LSL_Integer(perm) },
2772 new DetectParams[0]));
2773
2774 return;
2775 }
2776 }
2777
2778 ScenePresence presence = World.GetScenePresence(agentID);
2779
2780 if (presence != null)
2781 {
2782 string ownerName=resolveName(m_host.ParentGroup.RootPart.OwnerID);
2783 if (ownerName == String.Empty)
2784 ownerName="(hippos)";
2785
2786 if (!m_waitingForScriptAnswer)
2787 {
2788 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2789 m_host.TaskInventory[invItemID].PermsMask=0;
2790 presence.ControllingClient.OnScriptAnswer+=handleScriptAnswer;
2791 m_waitingForScriptAnswer=true;
2792 }
2793
2794 presence.ControllingClient.SendScriptQuestion(m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, invItemID, perm);
2795 return;
2796 }
2797
2798 // Requested agent is not in range, refuse perms
2799 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2800 "run_time_permissions", new Object[] {
2801 new LSL_Integer(0) },
2802 new DetectParams[0]));
2803 }
2804
2805 void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer)
2806 {
2807 if (taskID != m_host.UUID)
2808 return;
2809
2810 UUID invItemID=InventorySelf();
2811
2812 if (invItemID == UUID.Zero)
2813 return;
2814
2815 client.OnScriptAnswer-=handleScriptAnswer;
2816 m_waitingForScriptAnswer=false;
2817
2818 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
2819 llReleaseControls();
2820
2821 m_host.TaskInventory[invItemID].PermsMask=answer;
2822 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2823 "run_time_permissions", new Object[] {
2824 new LSL_Integer(answer) },
2825 new DetectParams[0]));
2826 }
2827
2828 public LSL_String llGetPermissionsKey()
2829 {
2830 m_host.AddScriptLPS(1);
2831
2832 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2833 {
2834 if (item.Type == 10 && item.ItemID == m_itemID)
2835 {
2836 return item.PermsGranter.ToString();
2837 }
2838 }
2839
2840 return UUID.Zero.ToString();
2841 }
2842
2843 public LSL_Integer llGetPermissions()
2844 {
2845 m_host.AddScriptLPS(1);
2846
2847 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2848 {
2849 if (item.Type == 10 && item.ItemID == m_itemID)
2850 {
2851 return item.PermsMask;
2852 }
2853 }
2854
2855 return 0;
2856 }
2857
2858 public LSL_Integer llGetLinkNumber()
2859 {
2860 m_host.AddScriptLPS(1);
2861
2862 if (m_host.ParentGroup.Children.Count > 1)
2863 {
2864 return m_host.LinkNum;
2865 }
2866 else
2867 {
2868 return 0;
2869 }
2870 }
2871
2872 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
2873 {
2874 List<SceneObjectPart> parts = GetLinkParts(linknumber);
2875
2876 foreach (SceneObjectPart part in parts)
2877 SetColor(part, color, face);
2878 }
2879
2880 public void llCreateLink(string target, int parent)
2881 {
2882 m_host.AddScriptLPS(1);
2883 UUID invItemID = InventorySelf();
2884 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0) {
2885 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
2886 return;
2887 }
2888 IClientAPI client = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter).ControllingClient;
2889 SceneObjectPart targetPart = World.GetSceneObjectPart(target);
2890 SceneObjectGroup parentPrim = null, childPrim = null;
2891 if (targetPart != null)
2892 {
2893 if (parent != 0) {
2894 parentPrim = m_host.ParentGroup;
2895 childPrim = targetPart.ParentGroup;
2896 }
2897 else
2898 {
2899 parentPrim = targetPart.ParentGroup;
2900 childPrim = m_host.ParentGroup;
2901 }
2902// byte uf = childPrim.RootPart.UpdateFlag;
2903 childPrim.RootPart.UpdateFlag = 0;
2904 parentPrim.LinkToGroup(childPrim);
2905// if (uf != (Byte)0)
2906// parent.RootPart.UpdateFlag = uf;
2907 }
2908 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
2909 parentPrim.RootPart.AddFlag(PrimFlags.CreateSelected);
2910 parentPrim.HasGroupChanged = true;
2911 parentPrim.ScheduleGroupForFullUpdate();
2912 parentPrim.GetProperties(client);
2913
2914 ScriptSleep(1000);
2915 }
2916
2917 public void llBreakLink(int linknum)
2918 {
2919 m_host.AddScriptLPS(1);
2920 UUID invItemID = InventorySelf();
2921 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0)
2922 {
2923 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
2924 return;
2925 }
2926 if (linknum < ScriptBaseClass.LINK_THIS)
2927 return;
2928 SceneObjectGroup parentPrim = m_host.ParentGroup;
2929 SceneObjectPart childPrim = null;
2930 switch (linknum)
2931 {
2932 case ScriptBaseClass.LINK_ROOT:
2933 break;
2934 case ScriptBaseClass.LINK_SET:
2935 case ScriptBaseClass.LINK_ALL_OTHERS:
2936 case ScriptBaseClass.LINK_ALL_CHILDREN:
2937 case ScriptBaseClass.LINK_THIS:
2938 foreach (SceneObjectPart part in parentPrim.Children.Values)
2939 {
2940 if (part.UUID != m_host.UUID)
2941 {
2942 childPrim = part;
2943 break;
2944 }
2945 }
2946 break;
2947 default:
2948 childPrim = parentPrim.GetLinkNumPart(linknum);
2949 if (childPrim.UUID == m_host.UUID)
2950 childPrim = null;
2951 break;
2952 }
2953 if (linknum == ScriptBaseClass.LINK_ROOT)
2954 {
2955 // Restructuring Multiple Prims.
2956 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
2957 parts.Remove(parentPrim.RootPart);
2958 foreach (SceneObjectPart part in parts)
2959 {
2960 parentPrim.DelinkFromGroup(part.LocalId, true);
2961 }
2962 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
2963 if (parts.Count > 0) {
2964 SceneObjectPart newRoot = parts[0];
2965 parts.Remove(newRoot);
2966 foreach (SceneObjectPart part in parts)
2967 {
2968 part.UpdateFlag = 0;
2969 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
2970 }
2971 }
2972 }
2973 else
2974 {
2975 if (childPrim == null)
2976 return;
2977 parentPrim.DelinkFromGroup(childPrim.LocalId, true);
2978 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
2979 }
2980 }
2981
2982 public void llBreakAllLinks()
2983 {
2984 m_host.AddScriptLPS(1);
2985 SceneObjectGroup parentPrim = m_host.ParentGroup;
2986 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
2987 parts.Remove(parentPrim.RootPart);
2988 foreach (SceneObjectPart part in parts)
2989 {
2990 parentPrim.DelinkFromGroup(part.LocalId, true);
2991 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
2992 }
2993 }
2994
2995 public LSL_String llGetLinkKey(int linknum)
2996 {
2997 m_host.AddScriptLPS(1);
2998 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
2999 if (part != null)
3000 {
3001 return part.UUID.ToString();
3002 }
3003 else
3004 {
3005 return UUID.Zero.ToString();
3006 }
3007 }
3008
3009 public LSL_String llGetLinkName(int linknum)
3010 {
3011 m_host.AddScriptLPS(1);
3012 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3013 if (part != null)
3014 {
3015 return part.Name;
3016 }
3017 else
3018 {
3019 return "";
3020 }
3021 }
3022
3023 public LSL_Integer llGetInventoryNumber(int type)
3024 {
3025 m_host.AddScriptLPS(1);
3026 int count = 0;
3027 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3028 {
3029 if (inv.Value.Type == type || type == -1)
3030 {
3031 count = count + 1;
3032 }
3033 }
3034 return count;
3035 }
3036
3037 public LSL_String llGetInventoryName(int type, int number)
3038 {
3039 m_host.AddScriptLPS(1);
3040 ArrayList keys = new ArrayList();
3041 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3042 {
3043 if (inv.Value.Type == type || type == -1)
3044 {
3045 keys.Add(inv.Value.Name);
3046 }
3047 }
3048 if (keys.Count == 0)
3049 {
3050 return String.Empty;
3051 }
3052 keys.Sort();
3053 if (keys.Count > number)
3054 {
3055 return (string)keys[number];
3056 }
3057 return String.Empty;
3058 }
3059
3060 public void llSetScriptState(string name, int run)
3061 { 151 {
3062 UUID item; 152 UUID item;
3063 ScriptManager sm; 153 ScriptManager sm;
@@ -3070,14 +160,11 @@ namespace OpenSim.Region.ScriptEngine.Common
3070 160
3071 if ((item = ScriptByName(name)) != UUID.Zero) 161 if ((item = ScriptByName(name)) != UUID.Zero)
3072 { 162 {
3073 if ((sm = m_ScriptEngine.m_ScriptManager) != null) 163 if ((sm = m_ScriptEngineDirect.m_ScriptManager) != null)
3074 { 164 {
3075 if (sm.Scripts.ContainsKey(m_localID)) 165 if ((script = sm.GetScript(m_localID, item)) != null)
3076 { 166 {
3077 if ((script = sm.GetScript(m_localID, item)) != null) 167 return script.Exec.Running?1:0;
3078 {
3079 script.Exec.Running = (run==0) ? false : true;
3080 }
3081 } 168 }
3082 } 169 }
3083 } 170 }
@@ -3085,2204 +172,14 @@ namespace OpenSim.Region.ScriptEngine.Common
3085 // Required by SL 172 // Required by SL
3086 173
3087 if (script == null) 174 if (script == null)
3088 ShoutError("llSetScriptState: script "+name+" not found"); 175 ShoutError("llGetScriptState: script "+name+" not found");
3089 176
3090 // If we didn't find it, then it's safe to 177 // If we didn't find it, then it's safe to
3091 // assume it is not running. 178 // assume it is not running.
3092 }
3093
3094 public LSL_Float llGetEnergy()
3095 {
3096 m_host.AddScriptLPS(1);
3097 // TODO: figure out real energy value
3098 return 1.0f;
3099 }
3100
3101 public void llGiveInventory(string destination, string inventory)
3102 {
3103 m_host.AddScriptLPS(1);
3104 bool found = false;
3105 UUID destId = UUID.Zero;
3106 UUID objId = UUID.Zero;
3107
3108 if (!UUID.TryParse(destination, out destId))
3109 {
3110 llSay(0, "Could not parse key " + destination);
3111 return;
3112 }
3113
3114 // move the first object found with this inventory name
3115 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3116 {
3117 if (inv.Value.Name == inventory)
3118 {
3119 found = true;
3120 objId = inv.Key;
3121 break;
3122 }
3123 }
3124
3125 if (!found)
3126 {
3127 llSay(0, String.Format("Could not find object '{0}'", inventory));
3128 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3129 }
3130
3131 // check if destination is an avatar
3132 if (World.GetScenePresence(destId) != null)
3133 {
3134 // destination is an avatar
3135 World.MoveTaskInventoryItem(destId, null, m_host, objId);
3136 }
3137 else
3138 {
3139 // destination is an object
3140 World.MoveTaskInventoryItem(destId, m_host, objId);
3141 }
3142 // ScriptSleep(3000);
3143 }
3144
3145 public void llRemoveInventory(string name)
3146 {
3147 m_host.AddScriptLPS(1);
3148 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3149 {
3150 if (item.Name == name)
3151 {
3152 m_host.RemoveInventoryItem(item.ItemID);
3153 return;
3154 }
3155 }
3156 }
3157
3158 public void llSetText(string text, LSL_Vector color, double alpha)
3159 {
3160 m_host.AddScriptLPS(1);
3161 Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f),
3162 Util.Clip((float)color.y, 0.0f, 1.0f),
3163 Util.Clip((float)color.z, 0.0f, 1.0f));
3164 m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
3165 m_host.ParentGroup.HasGroupChanged = true;
3166 }
3167
3168 public LSL_Float llWater(LSL_Vector offset)
3169 {
3170 m_host.AddScriptLPS(1);
3171 return World.RegionInfo.RegionSettings.WaterHeight;
3172 }
3173
3174 public void llPassTouches(int pass)
3175 {
3176 m_host.AddScriptLPS(1);
3177 NotImplemented("llPassTouches");
3178 }
3179
3180 public LSL_String llRequestAgentData(string id, int data)
3181 {
3182 m_host.AddScriptLPS(1);
3183
3184 UserProfileData userProfile =
3185 World.CommsManager.UserService.GetUserProfile(id);
3186
3187 UserAgentData userAgent =
3188 World.CommsManager.UserService.GetAgentByUUID(id);
3189
3190 if (userProfile == null || userAgent == null)
3191 return UUID.Zero.ToString();
3192
3193 string reply = String.Empty;
3194
3195 switch (data)
3196 {
3197 case 1: // DATA_ONLINE (0|1)
3198 // TODO: implement fetching of this information
3199 if (userProfile.CurrentAgent.AgentOnline)
3200 reply = "1";
3201 else
3202 reply = "0";
3203 break;
3204 case 2: // DATA_NAME (First Last)
3205 reply = userProfile.FirstName + " " + userProfile.SurName;
3206 break;
3207 case 3: // DATA_BORN (YYYY-MM-DD)
3208 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
3209 born = born.AddSeconds(userProfile.Created);
3210 reply = born.ToString("yyyy-MM-dd");
3211 break;
3212 case 4: // DATA_RATING (0,0,0,0,0,0)
3213 reply = "0,0,0,0,0,0";
3214 break;
3215 case 8: // DATA_PAYINFO (0|1|2|3)
3216 reply = "0";
3217 break;
3218 default:
3219 return UUID.Zero.ToString(); // Raise no event
3220 }
3221
3222 UUID rq = UUID.Random();
3223
3224 UUID tid = AsyncCommands.
3225 DataserverPlugin.RegisterRequest(m_localID,
3226 m_itemID, rq.ToString());
3227
3228 AsyncCommands.
3229 DataserverPlugin.DataserverReply(rq.ToString(), reply);
3230
3231 // ScriptSleep(100);
3232 return tid.ToString();
3233 }
3234
3235 public LSL_String llRequestInventoryData(string name)
3236 {
3237 m_host.AddScriptLPS(1);
3238
3239 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3240 {
3241 if (item.Type == 3 && item.Name == name)
3242 {
3243 UUID tid = AsyncCommands.
3244 DataserverPlugin.RegisterRequest(m_localID,
3245 m_itemID, item.AssetID.ToString());
3246
3247 Vector3 region = new Vector3(
3248 World.RegionInfo.RegionLocX * Constants.RegionSize,
3249 World.RegionInfo.RegionLocY * Constants.RegionSize,
3250 0);
3251
3252 World.AssetCache.GetAsset(item.AssetID,
3253 delegate(UUID i, AssetBase a)
3254 {
3255 AssetLandmark lm = new AssetLandmark(a);
3256
3257 float rx = (uint)(lm.RegionHandle >> 32);
3258 float ry = (uint)lm.RegionHandle;
3259 region = lm.Position + new Vector3(rx, ry, 0) - region;
3260
3261 string reply = region.ToString();
3262 AsyncCommands.
3263 DataserverPlugin.DataserverReply(i.ToString(),
3264 reply);
3265 }, false);
3266
3267 // ScriptSleep(1000);
3268 return tid.ToString();
3269 }
3270 }
3271 // ScriptSleep(1000);
3272 return String.Empty;
3273 }
3274
3275 public void llSetDamage(double damage)
3276 {
3277 m_host.AddScriptLPS(1);
3278 NotImplemented("llSetDamage");
3279 }
3280
3281 public void llTeleportAgentHome(string agent)
3282 {
3283 m_host.AddScriptLPS(1);
3284 UUID agentId = new UUID();
3285 if (UUID.TryParse(agent, out agentId))
3286 {
3287 ScenePresence presence = World.GetScenePresence(agentId);
3288 if (presence != null)
3289 {
3290 // agent must be over the owners land
3291 if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y))
3292 World.TeleportClientHome(agentId, presence.ControllingClient);
3293 }
3294 }
3295 // ScriptSleep(5000);
3296 }
3297
3298 public void llTextBox(string avatar, string message, int chat_channel)
3299 {
3300 m_host.AddScriptLPS(1);
3301 NotImplemented("llTextBox");
3302 }
3303
3304 public void llModifyLand(int action, int brush)
3305 {
3306 m_host.AddScriptLPS(1);
3307 World.ExternalChecks.ExternalChecksCanTerraformLand(m_host.OwnerID, new Vector3(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, 0));
3308 }
3309
3310 public void llCollisionSound(string impact_sound, double impact_volume)
3311 {
3312 m_host.AddScriptLPS(1);
3313 NotImplemented("llCollisionSound");
3314 }
3315
3316 public void llCollisionSprite(string impact_sprite)
3317 {
3318 m_host.AddScriptLPS(1);
3319 NotImplemented("llCollisionSprite");
3320 }
3321
3322 public LSL_String llGetAnimation(string id)
3323 {
3324 m_host.AddScriptLPS(1);
3325 NotImplemented("llGetAnimation");
3326 return String.Empty;
3327 }
3328
3329 public void llResetScript()
3330 {
3331 m_host.AddScriptLPS(800);
3332 m_ScriptEngine.m_ScriptManager.ResetScript(m_localID, m_itemID);
3333 }
3334
3335 public void llMessageLinked(int linknum, int num, string msg, string id)
3336 {
3337
3338 m_host.AddScriptLPS(1);
3339
3340 // uint partLocalID;
3341 UUID partItemID;
3342
3343 switch ((int)linknum)
3344 {
3345
3346 case (int)ScriptBaseClass.LINK_ROOT:
3347
3348 SceneObjectPart part = m_host.ParentGroup.RootPart;
3349
3350 foreach (TaskInventoryItem item in part.TaskInventory.Values)
3351 {
3352 if (item.Type == 10)
3353 {
3354 // partLocalID = part.LocalId;
3355 partItemID = item.ItemID;
3356
3357 object[] resobj = new object[]
3358 {
3359 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3360 };
3361
3362 m_ScriptEngine.PostScriptEvent(partItemID,
3363 new EventParams("link_message",
3364 resobj, new DetectParams[0]));
3365 }
3366 }
3367
3368 break;
3369
3370 case (int)ScriptBaseClass.LINK_SET:
3371
3372 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
3373 {
3374
3375 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
3376 {
3377 if (item.Type == 10)
3378 {
3379 // partLocalID = partInst.LocalId;
3380 partItemID = item.ItemID;
3381 Object[] resobj = new object[]
3382 {
3383 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3384 };
3385
3386 m_ScriptEngine.PostScriptEvent(partItemID,
3387 new EventParams("link_message",
3388 resobj, new DetectParams[0]));
3389 }
3390 }
3391 }
3392
3393 break;
3394
3395 case (int)ScriptBaseClass.LINK_ALL_OTHERS:
3396
3397 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
3398 {
3399
3400 if (partInst.LocalId != m_host.LocalId)
3401 {
3402
3403 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
3404 {
3405 if (item.Type == 10)
3406 {
3407 // partLocalID = partInst.LocalId;
3408 partItemID = item.ItemID;
3409 Object[] resobj = new object[]
3410 {
3411 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3412 };
3413
3414 m_ScriptEngine.PostScriptEvent(partItemID,
3415 new EventParams("link_message",
3416 resobj, new DetectParams[0]));
3417 }
3418 }
3419
3420 }
3421 }
3422
3423 break;
3424
3425 case (int)ScriptBaseClass.LINK_ALL_CHILDREN:
3426
3427 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
3428 {
3429
3430 if (partInst.LocalId != m_host.ParentGroup.RootPart.LocalId)
3431 {
3432
3433 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
3434 {
3435 if (item.Type == 10)
3436 {
3437 // partLocalID = partInst.LocalId;
3438 partItemID = item.ItemID;
3439 Object[] resobj = new object[]
3440 {
3441 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3442 };
3443
3444 m_ScriptEngine.PostScriptEvent(partItemID,
3445 new EventParams("link_message",
3446 resobj, new DetectParams[0]));
3447 }
3448 }
3449
3450 }
3451 }
3452
3453 break;
3454
3455 case (int)ScriptBaseClass.LINK_THIS:
3456
3457 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3458 {
3459 if (item.Type == 10)
3460 {
3461 partItemID = item.ItemID;
3462
3463 object[] resobj = new object[]
3464 {
3465 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3466 };
3467
3468 m_ScriptEngine.PostScriptEvent(partItemID,
3469 new EventParams("link_message",
3470 resobj, new DetectParams[0]));
3471 }
3472 }
3473
3474 break;
3475
3476 default:
3477
3478 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
3479 {
3480
3481 if ((partInst.LinkNum) == linknum)
3482 {
3483
3484 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
3485 {
3486 if (item.Type == 10)
3487 {
3488 // partLocalID = partInst.LocalId;
3489 partItemID = item.ItemID;
3490 Object[] resObjDef = new object[]
3491 {
3492 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3493 };
3494
3495 m_ScriptEngine.PostScriptEvent(partItemID,
3496 new EventParams("link_message",
3497 resObjDef, new DetectParams[0]));
3498 }
3499 }
3500
3501 }
3502 }
3503
3504 break;
3505
3506 }
3507
3508 }
3509
3510 public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local)
3511 {
3512 m_host.AddScriptLPS(1);
3513 SceneObjectPart targ = World.GetSceneObjectPart(target);
3514 if (targ == null)
3515 return;
3516 targ.ApplyImpulse(new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z), local != 0);
3517 }
3518
3519 public void llPassCollisions(int pass)
3520 {
3521 m_host.AddScriptLPS(1);
3522 NotImplemented("llPassCollisions");
3523 }
3524
3525 public LSL_String llGetScriptName()
3526 {
3527
3528 string result = String.Empty;
3529
3530 m_host.AddScriptLPS(1);
3531
3532 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3533 {
3534 if (item.Type == 10 && item.ItemID == m_itemID)
3535 {
3536 result = item.Name!=null?item.Name:String.Empty;
3537 break;
3538 }
3539 }
3540
3541 return result;
3542
3543 }
3544
3545 // this function to understand which shape it is (taken from meshmerizer)
3546 // quite useful can be used by meshmerizer to have a centralized point of understanding the shape
3547 // except that it refers to scripting constants
3548 private int getScriptPrimType(PrimitiveBaseShape primShape)
3549 {
3550 if (primShape.SculptEntry)
3551 return ScriptBaseClass.PRIM_TYPE_SCULPT;
3552 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
3553 {
3554 if (primShape.PathCurve == (byte)Extrusion.Straight)
3555 return ScriptBaseClass.PRIM_TYPE_BOX;
3556 else if (primShape.PathCurve == (byte)Extrusion.Curve1)
3557 return ScriptBaseClass.PRIM_TYPE_TUBE;
3558 }
3559 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
3560 {
3561 if (primShape.PathCurve == (byte)Extrusion.Straight)
3562 return ScriptBaseClass.PRIM_TYPE_CYLINDER;
3563 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
3564 else if (primShape.PathCurve == (byte)Extrusion.Curve1)
3565 return ScriptBaseClass.PRIM_TYPE_TORUS;
3566 }
3567 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
3568 {
3569 if (primShape.PathCurve == (byte)Extrusion.Curve1 || primShape.PathCurve == (byte)Extrusion.Curve2)
3570 return ScriptBaseClass.PRIM_TYPE_SPHERE;
3571 }
3572 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
3573 {
3574 if (primShape.PathCurve == (byte)Extrusion.Straight)
3575 return ScriptBaseClass.PRIM_TYPE_PRISM;
3576 else if (primShape.PathCurve == (byte)Extrusion.Curve1)
3577 return ScriptBaseClass.PRIM_TYPE_RING;
3578 }
3579 return ScriptBaseClass.PRIM_TYPE_BOX;
3580 }
3581
3582 // Helper functions to understand if object has cut, hollow, dimple, and other affecting number of faces
3583 private void hasCutHollowDimpleProfileCut(int primType, PrimitiveBaseShape shape, out bool hasCut, out bool hasHollow,
3584 out bool hasDimple, out bool hasProfileCut)
3585 {
3586 if (primType == ScriptBaseClass.PRIM_TYPE_BOX
3587 ||
3588 primType == ScriptBaseClass.PRIM_TYPE_CYLINDER
3589 ||
3590 primType == ScriptBaseClass.PRIM_TYPE_PRISM)
3591
3592 hasCut = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0);
3593 else
3594 hasCut = (shape.PathBegin > 0) || (shape.PathEnd > 0);
3595
3596 hasHollow = shape.ProfileHollow > 0;
3597 hasDimple = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); // taken from llSetPrimitiveParms
3598 hasProfileCut = hasDimple; // is it the same thing?
3599
3600 }
3601
3602 public LSL_Integer llGetNumberOfSides()
3603 {
3604 m_host.AddScriptLPS(1);
3605 return GetNumberOfSides(m_host);
3606 }
3607
3608 private int GetNumberOfSides(SceneObjectPart part)
3609 {
3610 int ret = 0;
3611 bool hasCut;
3612 bool hasHollow;
3613 bool hasDimple;
3614 bool hasProfileCut;
3615
3616 int primType = getScriptPrimType(part.Shape);
3617 hasCutHollowDimpleProfileCut(primType, part.Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut);
3618
3619 switch (primType)
3620 {
3621 case ScriptBaseClass.PRIM_TYPE_BOX:
3622 ret = 6;
3623 if (hasCut) ret += 2;
3624 if (hasHollow) ret += 1;
3625 break;
3626 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
3627 ret = 3;
3628 if (hasCut) ret += 2;
3629 if (hasHollow) ret += 1;
3630 break;
3631 case ScriptBaseClass.PRIM_TYPE_PRISM:
3632 ret = 5;
3633 if (hasCut) ret += 2;
3634 if (hasHollow) ret += 1;
3635 break;
3636 case ScriptBaseClass.PRIM_TYPE_SPHERE:
3637 ret = 1;
3638 if (hasCut) ret += 2;
3639 if (hasDimple) ret += 2;
3640 if (hasHollow) ret += 3; // Emulate lsl on secondlife (according to documentation it should have added only +1)
3641 break;
3642 case ScriptBaseClass.PRIM_TYPE_TORUS:
3643 ret = 1;
3644 if (hasCut) ret += 2;
3645 if (hasProfileCut) ret += 2;
3646 if (hasHollow) ret += 1;
3647 break;
3648 case ScriptBaseClass.PRIM_TYPE_TUBE:
3649 ret = 4;
3650 if (hasCut) ret += 2;
3651 if (hasProfileCut) ret += 2;
3652 if (hasHollow) ret += 1;
3653 break;
3654 case ScriptBaseClass.PRIM_TYPE_RING:
3655 ret = 3;
3656 if (hasCut) ret += 2;
3657 if (hasProfileCut) ret += 2;
3658 if (hasHollow) ret += 1;
3659 break;
3660 case ScriptBaseClass.PRIM_TYPE_SCULPT:
3661 ret = 1;
3662 break;
3663 }
3664 return ret;
3665 }
3666
3667
3668 /* The new / changed functions were tested with the following LSL script:
3669
3670 default
3671 {
3672 state_entry()
3673 {
3674 rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD);
3675
3676 llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot));
3677 llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG));
3678
3679 // convert back and forth between quaternion <-> vector and angle
3680
3681 rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot));
3682
3683 llOwnerSay("Old rotation was: "+(string) rot);
3684 llOwnerSay("re-converted rotation is: "+(string) newrot);
3685
3686 llSetRot(rot); // to check the parameters in the prim
3687 }
3688 }
3689 */
3690
3691
3692
3693 // Xantor 29/apr/2008
3694 // Returns rotation described by rotating angle radians about axis.
3695 // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
3696 public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle)
3697 {
3698 m_host.AddScriptLPS(1);
3699
3700 double x, y, z, s, t;
3701
3702 s = Math.Cos(angle / 2);
3703 t = Math.Sin(angle / 2); // temp value to avoid 2 more sin() calcs
3704 x = axis.x * t;
3705 y = axis.y * t;
3706 z = axis.z * t;
3707
3708 return new LSL_Rotation(x,y,z,s);
3709 }
3710
3711
3712 // Xantor 29/apr/2008
3713 // converts a Quaternion to X,Y,Z axis rotations
3714 public LSL_Vector llRot2Axis(LSL_Rotation rot)
3715 {
3716 m_host.AddScriptLPS(1);
3717 double x,y,z;
3718
3719 if (rot.s > 1) // normalization needed
3720 {
3721 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
3722 rot.z * rot.z + rot.s * rot.s);
3723
3724 rot.x /= length;
3725 rot.y /= length;
3726 rot.z /= length;
3727 rot.s /= length;
3728
3729 }
3730
3731 // double angle = 2 * Math.Acos(rot.s);
3732 double s = Math.Sqrt(1 - rot.s * rot.s);
3733 if (s < 0.001)
3734 {
3735 x = 1;
3736 y = z = 0;
3737 }
3738 else
3739 {
3740 x = rot.x / s; // normalise axis
3741 y = rot.y / s;
3742 z = rot.z / s;
3743 }
3744
3745
3746 return new LSL_Vector(x,y,z);
3747
3748 }
3749
3750
3751 // Returns the angle of a quaternion (see llRot2Axis for the axis)
3752 public LSL_Float llRot2Angle(LSL_Rotation rot)
3753 {
3754 m_host.AddScriptLPS(1);
3755
3756 if (rot.s > 1) // normalization needed
3757 {
3758 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
3759 rot.z * rot.z + rot.s * rot.s);
3760
3761 rot.x /= length;
3762 rot.y /= length;
3763 rot.z /= length;
3764 rot.s /= length;
3765
3766 }
3767
3768 double angle = 2 * Math.Acos(rot.s);
3769
3770 return angle;
3771
3772 }
3773
3774 public LSL_Float llAcos(double val)
3775 {
3776 m_host.AddScriptLPS(1);
3777 return (double)Math.Acos(val);
3778 }
3779
3780 public LSL_Float llAsin(double val)
3781 {
3782 m_host.AddScriptLPS(1);
3783 return (double)Math.Asin(val);
3784 }
3785
3786 // Xantor 30/apr/2008
3787 public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b)
3788 {
3789 m_host.AddScriptLPS(1);
3790
3791 return (double) Math.Acos(a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s) * 2;
3792 }
3793
3794 public LSL_String llGetInventoryKey(string name)
3795 {
3796 m_host.AddScriptLPS(1);
3797 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3798 {
3799 if (inv.Value.Name == name)
3800 {
3801 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
3802 {
3803 return inv.Value.AssetID.ToString();
3804 }
3805 else
3806 {
3807 return UUID.Zero.ToString();
3808 }
3809 }
3810 }
3811 return UUID.Zero.ToString();
3812 }
3813
3814 public void llAllowInventoryDrop(int add)
3815 {
3816 m_host.AddScriptLPS(1);
3817
3818 if (add != 0)
3819 m_host.ParentGroup.RootPart.AllowedDrop = true;
3820 else
3821 m_host.ParentGroup.RootPart.AllowedDrop = false;
3822 }
3823
3824 public LSL_Vector llGetSunDirection()
3825 {
3826 m_host.AddScriptLPS(1);
3827
3828 LSL_Vector SunDoubleVector3;
3829 Vector3 SunFloatVector3;
3830
3831 // sunPosition estate setting is set in OpenSim.Region.Environment.Modules.SunModule
3832 // have to convert from Vector3 (float) to LSL_Vector (double)
3833 SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector;
3834 SunDoubleVector3.x = (double)SunFloatVector3.X;
3835 SunDoubleVector3.y = (double)SunFloatVector3.Y;
3836 SunDoubleVector3.z = (double)SunFloatVector3.Z;
3837
3838 return SunDoubleVector3;
3839 }
3840
3841 public LSL_Vector llGetTextureOffset(int face)
3842 {
3843 m_host.AddScriptLPS(1);
3844 return GetTextureOffset(m_host, face);
3845 }
3846
3847 private LSL_Vector GetTextureOffset(SceneObjectPart part, int face)
3848 {
3849 Primitive.TextureEntry tex = part.Shape.Textures;
3850 LSL_Vector offset = new LSL_Vector();
3851 if (face == ScriptBaseClass.ALL_SIDES)
3852 {
3853 face = 0;
3854 }
3855 if (face >= 0 && face < GetNumberOfSides(part))
3856 {
3857 offset.x = tex.GetFace((uint)face).OffsetU;
3858 offset.y = tex.GetFace((uint)face).OffsetV;
3859 offset.z = 0.0;
3860 return offset;
3861 }
3862 else
3863 {
3864 return offset;
3865 }
3866 }
3867
3868 public LSL_Vector llGetTextureScale(int side)
3869 {
3870 m_host.AddScriptLPS(1);
3871 Primitive.TextureEntry tex = m_host.Shape.Textures;
3872 LSL_Vector scale;
3873 if (side == -1)
3874 {
3875 side = 0;
3876 }
3877 scale.x = tex.GetFace((uint)side).RepeatU;
3878 scale.y = tex.GetFace((uint)side).RepeatV;
3879 scale.z = 0.0;
3880 return scale;
3881 }
3882
3883 public LSL_Float llGetTextureRot(int face)
3884 {
3885 m_host.AddScriptLPS(1);
3886 return GetTextureRot(m_host, face);
3887 }
3888
3889 private LSL_Float GetTextureRot(SceneObjectPart part, int face)
3890 {
3891 Primitive.TextureEntry tex = part.Shape.Textures;
3892 if (face == -1)
3893 {
3894 face = 0;
3895 }
3896 if (face >= 0 && face < GetNumberOfSides(part))
3897 {
3898 return tex.GetFace((uint)face).Rotation;
3899 }
3900 else
3901 {
3902 return 0.0;
3903 }
3904 }
3905
3906 public LSL_Integer llSubStringIndex(string source, string pattern)
3907 {
3908 m_host.AddScriptLPS(1);
3909 return source.IndexOf(pattern);
3910 }
3911
3912 public LSL_String llGetOwnerKey(string id)
3913 {
3914 m_host.AddScriptLPS(1);
3915 UUID key = new UUID();
3916 if (UUID.TryParse(id, out key))
3917 {
3918 try
3919 {
3920 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
3921 if (obj == null)
3922 return id; // the key is for an agent so just return the key
3923 else
3924 return obj.OwnerID.ToString();
3925 }
3926 catch (KeyNotFoundException)
3927 {
3928 return id; // The Object/Agent not in the region so just return the key
3929 }
3930 }
3931 else
3932 {
3933 return UUID.Zero.ToString();
3934 }
3935 }
3936
3937 public LSL_Vector llGetCenterOfMass()
3938 {
3939 m_host.AddScriptLPS(1);
3940 NotImplemented("llGetCenterOfMass");
3941 return new LSL_Vector();
3942 }
3943
3944 public LSL_List llListSort(LSL_List src, int stride, int ascending)
3945 {
3946 m_host.AddScriptLPS(1);
3947
3948 if (stride <= 0)
3949 {
3950 stride = 1;
3951 }
3952 return src.Sort(stride, ascending);
3953 }
3954
3955 public LSL_Integer llGetListLength(LSL_List src)
3956 {
3957 m_host.AddScriptLPS(1);
3958
3959 if (src == null)
3960 {
3961 return 0;
3962 }
3963 else
3964 {
3965 return src.Length;
3966 }
3967 }
3968
3969 public LSL_Integer llList2Integer(LSL_List src, int index)
3970 {
3971 m_host.AddScriptLPS(1);
3972 if (index < 0)
3973 {
3974 index = src.Length + index;
3975 }
3976 if (index >= src.Length)
3977 {
3978 return 0;
3979 }
3980 try
3981 {
3982 if (src.Data[index] is LSL_Integer)
3983 return Convert.ToInt32(((LSL_Integer) src.Data[index]).value);
3984 else if (src.Data[index] is LSL_Float)
3985 return Convert.ToInt32(((LSL_Float) src.Data[index]).value);
3986 else if (src.Data[index] is LSL_String)
3987 return Convert.ToInt32(((LSL_String) src.Data[index]).m_string);
3988 return Convert.ToInt32(src.Data[index]);
3989 }
3990 catch (FormatException)
3991 {
3992 return 0;
3993 }
3994 }
3995
3996 public LSL_Float llList2Float(LSL_List src, int index)
3997 {
3998 m_host.AddScriptLPS(1);
3999 if (index < 0)
4000 {
4001 index = src.Length + index;
4002 }
4003 if (index >= src.Length)
4004 {
4005 return 0.0;
4006 }
4007 try
4008 {
4009 if (src.Data[index] is LSL_Integer)
4010 return Convert.ToDouble(((LSL_Integer) src.Data[index]).value);
4011 else if (src.Data[index] is LSL_Float)
4012 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4013 else if (src.Data[index] is LSL_String)
4014 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string);
4015 return Convert.ToDouble(src.Data[index]);
4016 }
4017 catch (FormatException)
4018 {
4019 return 0.0;
4020 }
4021 }
4022
4023 public LSL_String llList2String(LSL_List src, int index)
4024 {
4025 m_host.AddScriptLPS(1);
4026 if (index < 0)
4027 {
4028 index = src.Length + index;
4029 }
4030 if (index >= src.Length)
4031 {
4032 return String.Empty;
4033 }
4034 return src.Data[index].ToString();
4035 }
4036
4037 public LSL_String llList2Key(LSL_List src, int index)
4038 {
4039 m_host.AddScriptLPS(1);
4040 if (index < 0)
4041 {
4042 index = src.Length + index;
4043 }
4044 if (index >= src.Length)
4045 {
4046 return "";
4047 }
4048 return src.Data[index].ToString();
4049 }
4050
4051 public LSL_Vector llList2Vector(LSL_List src, int index)
4052 {
4053 m_host.AddScriptLPS(1);
4054 if (index < 0)
4055 {
4056 index = src.Length + index;
4057 }
4058 if (index >= src.Length)
4059 {
4060 return new LSL_Vector(0, 0, 0);
4061 }
4062 if (src.Data[index].GetType() == typeof(LSL_Vector))
4063 {
4064 return (LSL_Vector)src.Data[index];
4065 }
4066 else
4067 {
4068 return new LSL_Vector(src.Data[index].ToString());
4069 }
4070 }
4071
4072 public LSL_Rotation llList2Rot(LSL_List src, int index)
4073 {
4074 m_host.AddScriptLPS(1);
4075 if (index < 0)
4076 {
4077 index = src.Length + index;
4078 }
4079 if (index >= src.Length)
4080 {
4081 return new LSL_Rotation(0, 0, 0, 1);
4082 }
4083 if (src.Data[index].GetType() == typeof(LSL_Rotation))
4084 {
4085 return (LSL_Rotation)src.Data[index];
4086 }
4087 else
4088 {
4089 return new LSL_Rotation(src.Data[index].ToString());
4090 }
4091 }
4092
4093 public LSL_List llList2List(LSL_List src, int start, int end)
4094 {
4095 m_host.AddScriptLPS(1);
4096 return src.GetSublist(start, end);
4097 }
4098
4099 public LSL_List llDeleteSubList(LSL_List src, int start, int end)
4100 {
4101 return src.DeleteSublist(end, start);
4102 }
4103
4104 public LSL_Integer llGetListEntryType(LSL_List src, int index)
4105 {
4106 m_host.AddScriptLPS(1);
4107 if (index < 0)
4108 {
4109 index = src.Length + index;
4110 }
4111 if (index >= src.Length)
4112 {
4113 return 0;
4114 }
4115
4116 if (src.Data[index] is LSL_Integer || src.Data[index] is Int32)
4117 return 1;
4118 if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double)
4119 return 2;
4120 if (src.Data[index] is LSL_String || src.Data[index] is String)
4121 {
4122 UUID tuuid;
4123 if (UUID.TryParse(src.Data[index].ToString(), out tuuid))
4124 {
4125 return 4;
4126 }
4127 else
4128 {
4129 return 3;
4130 }
4131 }
4132 if (src.Data[index] is LSL_Vector)
4133 return 5;
4134 if (src.Data[index] is LSL_Rotation)
4135 return 6;
4136 if (src.Data[index] is LSL_List)
4137 return 7;
4138 return 0;
4139
4140 }
4141
4142 /// <summary>
4143 /// Process the supplied list and return the
4144 /// content of the list formatted as a comma
4145 /// separated list. There is a space after
4146 /// each comma.
4147 /// </summary>
4148
4149 public LSL_String llList2CSV(LSL_List src)
4150 {
4151
4152 string ret = String.Empty;
4153 int x = 0;
4154
4155 m_host.AddScriptLPS(1);
4156
4157 if (src.Data.Length > 0)
4158 {
4159 ret = src.Data[x++].ToString();
4160 for (; x < src.Data.Length; x++)
4161 {
4162 ret += ", "+src.Data[x].ToString();
4163 }
4164 }
4165
4166 return ret;
4167 }
4168
4169 /// <summary>
4170 /// The supplied string is scanned for commas
4171 /// and converted into a list. Commas are only
4172 /// effective if they are encountered outside
4173 /// of '<' '>' delimiters. Any whitespace
4174 /// before or after an element is trimmed.
4175 /// </summary>
4176
4177 public LSL_List llCSV2List(string src)
4178 {
4179
4180 LSL_List result = new LSL_List();
4181 int parens = 0;
4182 int start = 0;
4183 int length = 0;
4184
4185 m_host.AddScriptLPS(1);
4186
4187 for (int i = 0; i < src.Length; i++)
4188 {
4189 switch (src[i])
4190 {
4191 case '<':
4192 parens++;
4193 length++;
4194 break;
4195 case '>':
4196 if (parens > 0)
4197 parens--;
4198 length++;
4199 break;
4200 case ',':
4201 if (parens == 0)
4202 {
4203 result.Add(src.Substring(start,length).Trim());
4204 start += length+1;
4205 length = 0;
4206 }
4207 else
4208 {
4209 length++;
4210 }
4211 break;
4212 default:
4213 length++;
4214 break;
4215 }
4216 }
4217
4218 result.Add(src.Substring(start,length).Trim());
4219
4220 return result;
4221 }
4222
4223 /// <summary>
4224 /// Randomizes the list, be arbitrarily reordering
4225 /// sublists of stride elements. As the stride approaches
4226 /// the size of the list, the options become very
4227 /// limited.
4228 /// </summary>
4229 /// <remarks>
4230 /// This could take a while for very large list
4231 /// sizes.
4232 /// </remarks>
4233
4234 public LSL_List llListRandomize(LSL_List src, int stride)
4235 {
4236 LSL_List result;
4237 Random rand = new Random();
4238
4239 int chunkk;
4240 int[] chunks;
4241
4242 m_host.AddScriptLPS(1);
4243
4244 if (stride <= 0)
4245 {
4246 stride = 1;
4247 }
4248
4249 // Stride MUST be a factor of the list length
4250 // If not, then return the src list. This also
4251 // traps those cases where stride > length.
4252
4253 if (src.Length != stride && src.Length%stride == 0)
4254 {
4255 chunkk = src.Length/stride;
4256
4257 chunks = new int[chunkk];
4258
4259 for (int i = 0; i < chunkk; i++)
4260 chunks[i] = i;
4261
4262 // Knuth shuffle the chunkk index
4263 for (int i = chunkk - 1; i >= 1; i--)
4264 {
4265 // Elect an unrandomized chunk to swap
4266 int index = rand.Next(i + 1);
4267 int tmp;
4268
4269 // and swap position with first unrandomized chunk
4270 tmp = chunks[i];
4271 chunks[i] = chunks[index];
4272 chunks[index] = tmp;
4273 }
4274
4275 // Construct the randomized list
4276
4277 result = new LSL_List();
4278
4279 for (int i = 0; i < chunkk; i++)
4280 {
4281 for (int j = 0; j < stride; j++)
4282 {
4283 result.Add(src.Data[chunks[i]*stride+j]);
4284 }
4285 }
4286 }
4287 else {
4288 object[] array = new object[src.Length];
4289 Array.Copy(src.Data, 0, array, 0, src.Length);
4290 result = new LSL_List(array);
4291 }
4292
4293 return result;
4294 }
4295
4296 /// <summary>
4297 /// Elements in the source list starting with 0 and then
4298 /// every i+stride. If the stride is negative then the scan
4299 /// is backwards producing an inverted result.
4300 /// Only those elements that are also in the specified
4301 /// range are included in the result.
4302 /// </summary>
4303
4304 public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride)
4305 {
4306
4307 LSL_List result = new LSL_List();
4308 int[] si = new int[2];
4309 int[] ei = new int[2];
4310 bool twopass = false;
4311
4312 m_host.AddScriptLPS(1);
4313
4314 // First step is always to deal with negative indices
4315
4316 if (start < 0)
4317 start = src.Length+start;
4318 if (end < 0)
4319 end = src.Length+end;
4320
4321 // Out of bounds indices are OK, just trim them
4322 // accordingly
4323
4324 if (start > src.Length)
4325 start = src.Length;
4326
4327 if (end > src.Length)
4328 end = src.Length;
4329
4330 // There may be one or two ranges to be considered
4331
4332 if (start != end)
4333 {
4334
4335 if (start <= end)
4336 {
4337 si[0] = start;
4338 ei[0] = end;
4339 }
4340 else
4341 {
4342 si[1] = start;
4343 ei[1] = src.Length;
4344 si[0] = 0;
4345 ei[0] = end;
4346 twopass = true;
4347 }
4348
4349 // The scan always starts from the beginning of the
4350 // source list, but members are only selected if they
4351 // fall within the specified sub-range. The specified
4352 // range values are inclusive.
4353 // A negative stride reverses the direction of the
4354 // scan producing an inverted list as a result.
4355
4356 if (stride == 0)
4357 stride = 1;
4358
4359 if (stride > 0)
4360 {
4361 for (int i = 0; i < src.Length; i += stride)
4362 {
4363 if (i<=ei[0] && i>=si[0])
4364 result.Add(src.Data[i]);
4365 if (twopass && i>=si[1] && i<=ei[1])
4366 result.Add(src.Data[i]);
4367 }
4368 }
4369 else if (stride < 0)
4370 {
4371 for (int i = src.Length - 1; i >= 0; i += stride)
4372 {
4373 if (i <= ei[0] && i >= si[0])
4374 result.Add(src.Data[i]);
4375 if (twopass && i >= si[1] && i <= ei[1])
4376 result.Add(src.Data[i]);
4377 }
4378 }
4379 }
4380
4381 return result;
4382 }
4383
4384 public LSL_Integer llGetRegionAgentCount()
4385 {
4386 m_host.AddScriptLPS(1);
4387 NotImplemented("llGetRegionAgentCount");
4388 return new LSL_Integer(0);
4389 }
4390
4391 public LSL_Vector llGetRegionCorner()
4392 {
4393 m_host.AddScriptLPS(1);
4394 return new LSL_Vector(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
4395 }
4396
4397 /// <summary>
4398 /// Insert the list identified by <src> into the
4399 /// list designated by <dest> such that the first
4400 /// new element has the index specified by <index>
4401 /// </summary>
4402
4403 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
4404 {
4405
4406 LSL_List pref = null;
4407 LSL_List suff = null;
4408
4409 m_host.AddScriptLPS(1);
4410
4411 if (index < 0)
4412 {
4413 index = index+dest.Length;
4414 if (index < 0)
4415 {
4416 index = 0;
4417 }
4418 }
4419
4420 if (index != 0)
4421 {
4422 pref = dest.GetSublist(0,index-1);
4423 if (index < dest.Length)
4424 {
4425 suff = dest.GetSublist(index,-1);
4426 return pref + src + suff;
4427 }
4428 else
4429 {
4430 return pref + src;
4431 }
4432 }
4433 else
4434 {
4435 if (index < dest.Length)
4436 {
4437 suff = dest.GetSublist(index,-1);
4438 return src + suff;
4439 }
4440 else
4441 {
4442 return src;
4443 }
4444 }
4445
4446 }
4447
4448 /// <summary>
4449 /// Returns the index of the first occurrence of test
4450 /// in src.
4451 /// </summary>
4452
4453 public LSL_Integer llListFindList(LSL_List src, LSL_List test)
4454 {
4455
4456 int index = -1;
4457 int length = src.Length - test.Length + 1;
4458
4459 m_host.AddScriptLPS(1);
4460 179
4461 // If either list is empty, do not match
4462
4463 if (src.Length != 0 && test.Length != 0)
4464 {
4465 for (int i = 0; i < length; i++)
4466 {
4467 if (src.Data[i].Equals(test.Data[0]))
4468 {
4469 int j;
4470 for (j = 1; j < test.Length; j++)
4471 if (!src.Data[i+j].Equals(test.Data[j]))
4472 break;
4473 if (j == test.Length)
4474 {
4475 index = i;
4476 break;
4477 }
4478 }
4479 }
4480 }
4481
4482 return index;
4483
4484 }
4485
4486 public LSL_String llGetObjectName()
4487 {
4488 m_host.AddScriptLPS(1);
4489 return m_host.Name!=null?m_host.Name:String.Empty;
4490 }
4491
4492 public void llSetObjectName(string name)
4493 {
4494 m_host.AddScriptLPS(1);
4495 m_host.Name = name!=null?name:String.Empty;
4496 }
4497
4498 public LSL_String llGetDate()
4499 {
4500 m_host.AddScriptLPS(1);
4501 DateTime date = DateTime.Now.ToUniversalTime();
4502 string result = date.ToString("yyyy-MM-dd");
4503 return result;
4504 }
4505
4506 public LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir)
4507 {
4508 m_host.AddScriptLPS(1);
4509 NotImplemented("llEdgeOfWorld");
4510 return 0; 180 return 0;
4511 } 181 }
4512 182
4513 public LSL_Integer llGetAgentInfo(string id)
4514 {
4515 m_host.AddScriptLPS(1);
4516 NotImplemented("llGetAgentInfo");
4517 return 0;
4518 }
4519
4520 public void llAdjustSoundVolume(double volume)
4521 {
4522 m_host.AddScriptLPS(1);
4523 m_host.AdjustSoundGain(volume);
4524 // ScriptSleep(100);
4525 }
4526
4527 public void llSetSoundQueueing(int queue)
4528 {
4529 m_host.AddScriptLPS(1);
4530 NotImplemented("llSetSoundQueueing");
4531 }
4532
4533 public void llSetSoundRadius(double radius)
4534 {
4535 m_host.AddScriptLPS(1);
4536 m_host.SoundRadius = radius;
4537 }
4538
4539 public LSL_String llKey2Name(string id)
4540 {
4541 m_host.AddScriptLPS(1);
4542 UUID key = new UUID();
4543 if (UUID.TryParse(id,out key))
4544 {
4545 ScenePresence presence = World.GetScenePresence(key);
4546
4547 if (presence != null)
4548 {
4549 return presence.ControllingClient.Name;
4550 //return presence.Name;
4551 }
4552
4553 if (World.GetSceneObjectPart(key) != null)
4554 {
4555 return World.GetSceneObjectPart(key).Name;
4556 }
4557 }
4558 return String.Empty;
4559 }
4560
4561
4562
4563 public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate)
4564 {
4565 m_host.AddScriptLPS(1);
4566 Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation();
4567 pTexAnim.Flags = (Primitive.TextureAnimMode)mode;
4568
4569 //ALL_SIDES
4570 if (face == ScriptBaseClass.ALL_SIDES)
4571 face = 255;
4572
4573 pTexAnim.Face = (uint)face;
4574 pTexAnim.Length = (float)length;
4575 pTexAnim.Rate = (float)rate;
4576 pTexAnim.SizeX = (uint)sizex;
4577 pTexAnim.SizeY = (uint)sizey;
4578 pTexAnim.Start = (float)start;
4579
4580 m_host.AddTextureAnimation(pTexAnim);
4581 m_host.SendFullUpdateToAllClients();
4582 m_host.ParentGroup.HasGroupChanged = true;
4583 }
4584
4585 public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east,
4586 LSL_Vector bottom_south_west)
4587 {
4588 m_host.AddScriptLPS(1);
4589 NotImplemented("llTriggerSoundLimited");
4590 }
4591
4592 public void llEjectFromLand(string pest)
4593 {
4594 m_host.AddScriptLPS(1);
4595 UUID agentId = new UUID();
4596 if (UUID.TryParse(pest, out agentId))
4597 {
4598 ScenePresence presence = World.GetScenePresence(agentId);
4599 if (presence != null)
4600 {
4601 // agent must be over the owners land
4602 if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y))
4603 World.TeleportClientHome(agentId, presence.ControllingClient);
4604 }
4605 }
4606 // ScriptSleep(5000);
4607 }
4608
4609 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List spacers)
4610 {
4611 m_host.AddScriptLPS(1);
4612 LSL_List ret = new LSL_List();
4613 object[] delimiters = new object[separators.Length + spacers.Length];
4614 separators.Data.CopyTo(delimiters, 0);
4615 spacers.Data.CopyTo(delimiters, separators.Length);
4616 bool dfound = false;
4617 do
4618 {
4619 dfound = false;
4620 int cindex = -1;
4621 string cdeli = "";
4622 for (int i = 0; i < delimiters.Length; i++)
4623 {
4624 int index = str.IndexOf(delimiters[i].ToString());
4625 bool found = index != -1;
4626 if (found && String.Empty != delimiters[i].ToString())
4627 {
4628 if ((cindex > index) || (cindex == -1))
4629 {
4630 cindex = index;
4631 cdeli = delimiters[i].ToString();
4632 }
4633 dfound = dfound || found;
4634 }
4635 }
4636 if (cindex != -1)
4637 {
4638 if (cindex > 0)
4639 {
4640 ret.Add(str.Substring(0, cindex));
4641 // Cannot use spacers.Contains() because spacers may be either type String or LSLString
4642 for (int j = 0; j < spacers.Length; j++)
4643 {
4644 if (spacers.Data[j].ToString() == cdeli)
4645 {
4646 ret.Add(cdeli);
4647 break;
4648 }
4649 }
4650 }
4651 if (cindex == 0 && spacers.Contains(cdeli))
4652 {
4653 ret.Add(cdeli);
4654 }
4655 str = str.Substring(cindex + cdeli.Length);
4656 }
4657 } while (dfound);
4658 if (str != "")
4659 {
4660 ret.Add(str);
4661 }
4662 return ret;
4663 }
4664
4665 public LSL_Integer llOverMyLand(string id)
4666 {
4667 m_host.AddScriptLPS(1);
4668 UUID key = new UUID();
4669 if (UUID.TryParse(id,out key))
4670 {
4671 ScenePresence presence = World.GetScenePresence(key);
4672 if (presence != null) // object is an avatar
4673 {
4674 if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y))
4675 return 1;
4676 }
4677 else // object is not an avatar
4678 {
4679 SceneObjectPart obj = World.GetSceneObjectPart(key);
4680 if (obj != null)
4681 if (m_host.OwnerID == World.GetLandOwner(obj.AbsolutePosition.X, obj.AbsolutePosition.Y))
4682 return 1;
4683 }
4684 }
4685 return 0;
4686 }
4687
4688 public LSL_String llGetLandOwnerAt(LSL_Vector pos)
4689 {
4690 m_host.AddScriptLPS(1);
4691 return World.GetLandOwner((float)pos.x, (float)pos.y).ToString();
4692 }
4693
4694 public LSL_Vector llGetAgentSize(string id)
4695 {
4696 m_host.AddScriptLPS(1);
4697 ScenePresence avatar = World.GetScenePresence(id);
4698 LSL_Vector agentSize;
4699 if (avatar == null)
4700 {
4701 agentSize = ScriptBaseClass.ZERO_VECTOR;
4702 }
4703 else
4704 {
4705 PhysicsVector size = avatar.PhysicsActor.Size;
4706 agentSize = new LSL_Vector(size.X, size.Y, size.Z);
4707 }
4708 return agentSize;
4709 }
4710
4711 public LSL_Integer llSameGroup(string agent)
4712 {
4713 m_host.AddScriptLPS(1);
4714 UUID agentId = new UUID();
4715 if (!UUID.TryParse(agent, out agentId))
4716 return new LSL_Integer(0);
4717 ScenePresence presence = World.GetScenePresence(agentId);
4718 if (presence == null)
4719 return new LSL_Integer(0);
4720 IClientAPI client = presence.ControllingClient;
4721 if (m_host.GroupID == client.ActiveGroupId)
4722 return new LSL_Integer(1);
4723 else
4724 return new LSL_Integer(0);
4725 }
4726
4727 public void llUnSit(string id)
4728 {
4729 m_host.AddScriptLPS(1);
4730
4731 UUID key = new UUID();
4732 if (UUID.TryParse(id, out key))
4733 {
4734 ScenePresence av = World.GetScenePresence(key);
4735
4736 if (av != null)
4737 {
4738 if (llAvatarOnSitTarget() == id)
4739 {
4740 // if the avatar is sitting on this object, then
4741 // we can unsit them. We don't want random scripts unsitting random people
4742 // Lets avoid the popcorn avatar scenario.
4743 av.StandUp();
4744 }
4745 else
4746 {
4747 // If the object owner also owns the parcel
4748 // or
4749 // if the land is group owned and the object is group owned by the same group
4750 // or
4751 // if the object is owned by a person with estate access.
4752
4753 ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y);
4754 if (parcel != null)
4755 {
4756 if (m_host.ObjectOwner == parcel.landData.OwnerID ||
4757 (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.landData.GroupID
4758 && parcel.landData.IsGroupOwned) || World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID))
4759 {
4760 av.StandUp();
4761 }
4762 }
4763 }
4764 }
4765
4766 }
4767
4768 }
4769
4770 public LSL_Vector llGroundSlope(LSL_Vector offset)
4771 {
4772 m_host.AddScriptLPS(1);
4773
4774 Vector3 pos = m_host.AbsolutePosition + new Vector3((float)offset.x,
4775 (float)offset.y,
4776 (float)offset.z);
4777
4778 Vector3 p0 = new Vector3(pos.X, pos.Y,
4779 (float)llGround(
4780 new LSL_Vector(pos.X, pos.Y, pos.Z)
4781 ));
4782 Vector3 p1 = new Vector3(pos.X + 1, pos.Y,
4783 (float)llGround(
4784 new LSL_Vector(pos.X + 1, pos.Y, pos.Z)
4785 ));
4786 Vector3 p2 = new Vector3(pos.X, pos.Y + 1,
4787 (float)llGround(
4788 new LSL_Vector(pos.X, pos.Y + 1, pos.Z)
4789 ));
4790
4791 Vector3 v0 = new Vector3(
4792 p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
4793 Vector3 v1 = new Vector3(
4794 p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z);
4795
4796 v0.Normalize();
4797 v1.Normalize();
4798
4799 Vector3 tv = new Vector3();
4800 tv.X = (v0.Y * v1.Z) - (v0.Z * v1.Y);
4801 tv.Y = (v0.Z * v1.X) - (v0.X * v1.Z);
4802 tv.Z = (v0.X * v1.Y) - (v0.Y * v1.X);
4803
4804 return new LSL_Vector(tv.X, tv.Y, tv.Z);
4805 }
4806
4807 public LSL_Vector llGroundNormal(LSL_Vector offset)
4808 {
4809 m_host.AddScriptLPS(1);
4810 LSL_Vector x = llGroundSlope(offset);
4811 return new LSL_Vector(x.x, x.y, 1.0);
4812 }
4813
4814 public LSL_Vector llGroundContour(LSL_Vector offset)
4815 {
4816 m_host.AddScriptLPS(1);
4817 LSL_Vector x = llGroundSlope(offset);
4818 return new LSL_Vector(-x.y, x.x, 0.0);
4819 }
4820
4821 public LSL_Integer llGetAttached()
4822 {
4823 m_host.AddScriptLPS(1);
4824 NotImplemented("llGetAttached");
4825 return 0;
4826 }
4827
4828 public LSL_Integer llGetFreeMemory()
4829 {
4830 m_host.AddScriptLPS(1);
4831 // Make scripts designed for LSO happy
4832 return 16384;
4833 }
4834
4835 public LSL_String llGetRegionName()
4836 {
4837 m_host.AddScriptLPS(1);
4838 return World.RegionInfo.RegionName;
4839 }
4840
4841 public LSL_Float llGetRegionTimeDilation()
4842 {
4843 m_host.AddScriptLPS(1);
4844 return (double)World.TimeDilation;
4845 }
4846
4847 public LSL_Float llGetRegionFPS()
4848 {
4849 m_host.AddScriptLPS(1);
4850 //TODO: return actual FPS
4851 return 10.0f;
4852 }
4853
4854 /* particle system rules should be coming into this routine as doubles, that is
4855 rule[0] should be an integer from this list and rule[1] should be the arg
4856 for the same integer. wiki.secondlife.com has most of this mapping, but some
4857 came from http://www.caligari-designs.com/p4u2
4858
4859 We iterate through the list for 'Count' elements, incrementing by two for each
4860 iteration and set the members of Primitive.ParticleSystem, one at a time.
4861 */
4862
4863 public enum PrimitiveRule : int
4864 {
4865 PSYS_PART_FLAGS = 0,
4866 PSYS_PART_START_COLOR = 1,
4867 PSYS_PART_START_ALPHA = 2,
4868 PSYS_PART_END_COLOR = 3,
4869 PSYS_PART_END_ALPHA = 4,
4870 PSYS_PART_START_SCALE = 5,
4871 PSYS_PART_END_SCALE = 6,
4872 PSYS_PART_MAX_AGE = 7,
4873 PSYS_SRC_ACCEL = 8,
4874 PSYS_SRC_PATTERN = 9,
4875 PSYS_SRC_TEXTURE = 12,
4876 PSYS_SRC_BURST_RATE = 13,
4877 PSYS_SRC_BURST_PART_COUNT = 15,
4878 PSYS_SRC_BURST_RADIUS = 16,
4879 PSYS_SRC_BURST_SPEED_MIN = 17,
4880 PSYS_SRC_BURST_SPEED_MAX = 18,
4881 PSYS_SRC_MAX_AGE = 19,
4882 PSYS_SRC_TARGET_KEY = 20,
4883 PSYS_SRC_OMEGA = 21,
4884 PSYS_SRC_ANGLE_BEGIN = 22,
4885 PSYS_SRC_ANGLE_END = 23
4886 }
4887
4888 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
4889 {
4890 Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None;
4891
4892 return returnval;
4893 }
4894
4895 private Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues()
4896 {
4897 Primitive.ParticleSystem ps = new Primitive.ParticleSystem();
4898
4899 // TODO find out about the other defaults and add them here
4900 ps.PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
4901 ps.PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
4902 ps.PartStartScaleX = 1.0f;
4903 ps.PartStartScaleY = 1.0f;
4904 ps.PartEndScaleX = 1.0f;
4905 ps.PartEndScaleY = 1.0f;
4906 ps.BurstSpeedMin = 1.0f;
4907 ps.BurstSpeedMax = 1.0f;
4908 ps.BurstRate = 0.1f;
4909 ps.PartMaxAge = 10.0f;
4910 return ps;
4911 }
4912
4913 public void llParticleSystem(LSL_List rules)
4914 {
4915 m_host.AddScriptLPS(1);
4916 if (rules.Length == 0)
4917 {
4918 m_host.RemoveParticleSystem();
4919 m_host.ParentGroup.HasGroupChanged = true;
4920 }
4921 else
4922 {
4923 Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues();
4924 LSL_Vector tempv = new LSL_Vector();
4925
4926 float tempf = 0;
4927
4928 for (int i = 0; i < rules.Length; i += 2)
4929 {
4930 switch ((int)rules.Data[i])
4931 {
4932 case (int)ScriptBaseClass.PSYS_PART_FLAGS:
4933 prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1);
4934 break;
4935
4936 case (int)ScriptBaseClass.PSYS_PART_START_COLOR:
4937 tempv = rules.GetVector3Item(i + 1);
4938 prules.PartStartColor.R = (float)tempv.x;
4939 prules.PartStartColor.G = (float)tempv.y;
4940 prules.PartStartColor.B = (float)tempv.z;
4941 break;
4942
4943 case (int)ScriptBaseClass.PSYS_PART_START_ALPHA:
4944 tempf = (float)rules.GetLSLFloatItem(i + 1);
4945 prules.PartStartColor.A = tempf;
4946 break;
4947
4948 case (int)ScriptBaseClass.PSYS_PART_END_COLOR:
4949 tempv = rules.GetVector3Item(i + 1);
4950 prules.PartEndColor.R = (float)tempv.x;
4951 prules.PartEndColor.G = (float)tempv.y;
4952 prules.PartEndColor.B = (float)tempv.z;
4953 break;
4954
4955 case (int)ScriptBaseClass.PSYS_PART_END_ALPHA:
4956 tempf = (float)rules.GetLSLFloatItem(i + 1);
4957 prules.PartEndColor.A = tempf;
4958 break;
4959
4960 case (int)ScriptBaseClass.PSYS_PART_START_SCALE:
4961 tempv = rules.GetVector3Item(i + 1);
4962 prules.PartStartScaleX = (float)tempv.x;
4963 prules.PartStartScaleY = (float)tempv.y;
4964 break;
4965
4966 case (int)ScriptBaseClass.PSYS_PART_END_SCALE:
4967 tempv = rules.GetVector3Item(i + 1);
4968 prules.PartEndScaleX = (float)tempv.x;
4969 prules.PartEndScaleY = (float)tempv.y;
4970 break;
4971
4972 case (int)ScriptBaseClass.PSYS_PART_MAX_AGE:
4973 tempf = (float)rules.GetLSLFloatItem(i + 1);
4974 prules.PartMaxAge = tempf;
4975 break;
4976
4977 case (int)ScriptBaseClass.PSYS_SRC_ACCEL:
4978 tempv = rules.GetVector3Item(i + 1);
4979 prules.PartAcceleration.X = (float)tempv.x;
4980 prules.PartAcceleration.Y = (float)tempv.y;
4981 prules.PartAcceleration.Z = (float)tempv.z;
4982 break;
4983
4984 case (int)ScriptBaseClass.PSYS_SRC_PATTERN:
4985 int tmpi = (int)rules.GetLSLIntegerItem(i + 1);
4986 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
4987 break;
4988
4989 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE:
4990 prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1));
4991 break;
4992
4993 case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE:
4994 tempf = (float)rules.GetLSLFloatItem(i + 1);
4995 prules.BurstRate = (float)tempf;
4996 break;
4997
4998 case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT:
4999 prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1);
5000 break;
5001
5002 case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS:
5003 tempf = (float)rules.GetLSLFloatItem(i + 1);
5004 prules.BurstRadius = (float)tempf;
5005 break;
5006
5007 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN:
5008 tempf = (float)rules.GetLSLFloatItem(i + 1);
5009 prules.BurstSpeedMin = (float)tempf;
5010 break;
5011
5012 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX:
5013 tempf = (float)rules.GetLSLFloatItem(i + 1);
5014 prules.BurstSpeedMax = (float)tempf;
5015 break;
5016
5017 case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE:
5018 tempf = (float)rules.GetLSLFloatItem(i + 1);
5019 prules.MaxAge = (float)tempf;
5020 break;
5021
5022 case (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY:
5023 UUID key = UUID.Zero;
5024 if (UUID.TryParse(rules.Data[i + 1].ToString(), out key))
5025 {
5026 prules.Target = key;
5027 }
5028 else
5029 {
5030 prules.Target = m_host.UUID;
5031 }
5032 break;
5033
5034 case (int)ScriptBaseClass.PSYS_SRC_OMEGA:
5035 // AL: This is an assumption, since it is the only thing that would match.
5036 tempv = rules.GetVector3Item(i + 1);
5037 prules.AngularVelocity.X = (float)tempv.x;
5038 prules.AngularVelocity.Y = (float)tempv.y;
5039 prules.AngularVelocity.Z = (float)tempv.z;
5040 break;
5041
5042 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN:
5043 tempf = (float)rules.GetLSLFloatItem(i + 1);
5044 prules.InnerAngle = (float)tempf;
5045 break;
5046
5047 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END:
5048 tempf = (float)rules.GetLSLFloatItem(i + 1);
5049 prules.OuterAngle = (float)tempf;
5050 break;
5051 }
5052
5053 }
5054 prules.CRC = 1;
5055
5056 m_host.AddNewParticleSystem(prules);
5057 m_host.ParentGroup.HasGroupChanged = true;
5058 }
5059 m_host.SendFullUpdateToAllClients();
5060 }
5061
5062 public void llGroundRepel(double height, int water, double tau)
5063 {
5064 m_host.AddScriptLPS(1);
5065 NotImplemented("llGroundRepel");
5066 }
5067
5068 private UUID GetTaskInventoryItem(string name)
5069 {
5070 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
5071 {
5072 if (inv.Value.Name == name)
5073 return inv.Key;
5074 }
5075 return UUID.Zero;
5076 }
5077
5078 public void llGiveInventoryList(string destination, string category, LSL_List inventory)
5079 {
5080 m_host.AddScriptLPS(1);
5081
5082 UUID destID;
5083 if (!UUID.TryParse(destination, out destID))
5084 return;
5085
5086 List<UUID> itemList = new List<UUID>();
5087
5088 foreach (Object item in inventory.Data)
5089 {
5090 UUID itemID;
5091 if (UUID.TryParse(item.ToString(), out itemID))
5092 {
5093 itemList.Add(itemID);
5094 }
5095 else
5096 {
5097 itemID = GetTaskInventoryItem(item.ToString());
5098 if (itemID != UUID.Zero)
5099 itemList.Add(itemID);
5100 }
5101 }
5102
5103 if (itemList.Count == 0)
5104 return;
5105
5106 m_ScriptEngine.World.MoveTaskInventoryItems(destID, category, m_host, itemList);
5107 }
5108
5109 public void llSetVehicleType(int type)
5110 {
5111 m_host.AddScriptLPS(1);
5112 NotImplemented("llSetVehicleType");
5113 }
5114
5115 public void llSetVehicledoubleParam(int param, double value)
5116 {
5117 m_host.AddScriptLPS(1);
5118 NotImplemented("llSetVehicledoubleParam");
5119 }
5120
5121 public void llSetVehicleFloatParam(int param, float value)
5122 {
5123 m_host.AddScriptLPS(1);
5124 NotImplemented("llSetVehicleFloatParam");
5125 }
5126
5127 public void llSetVehicleVectorParam(int param, LSL_Vector vec)
5128 {
5129 m_host.AddScriptLPS(1);
5130 NotImplemented("llSetVehicleVectorParam");
5131 }
5132
5133 public void llSetVehicleRotationParam(int param, LSL_Rotation rot)
5134 {
5135 m_host.AddScriptLPS(1);
5136 NotImplemented("llSetVehicleRotationParam");
5137 }
5138
5139 public void llSetVehicleFlags(int flags)
5140 {
5141 m_host.AddScriptLPS(1);
5142 NotImplemented("llSetVehicleFlags");
5143 }
5144
5145 public void llRemoveVehicleFlags(int flags)
5146 {
5147 m_host.AddScriptLPS(1);
5148 NotImplemented("llRemoveVehicleFlags");
5149 }
5150
5151 public void llSitTarget(LSL_Vector offset, LSL_Rotation rot)
5152 {
5153 m_host.AddScriptLPS(1);
5154 // LSL quaternions can normalize to 0, normal Quaternions can't.
5155 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
5156 rot.z = 1; // ZERO_ROTATION = 0,0,0,1
5157
5158 m_host.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z);
5159 m_host.SitTargetOrientation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
5160 }
5161
5162 public LSL_String llAvatarOnSitTarget()
5163 {
5164 m_host.AddScriptLPS(1);
5165 return m_host.GetAvatarOnSitTarget().ToString();
5166 }
5167
5168 public void llAddToLandPassList(string avatar, double hours)
5169 {
5170 m_host.AddScriptLPS(1);
5171 UUID key;
5172 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
5173 if (land.OwnerID == m_host.OwnerID)
5174 {
5175 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
5176 if (UUID.TryParse(avatar, out key))
5177 {
5178 entry.AgentID = key;
5179 entry.Flags = ParcelManager.AccessList.Access;
5180 entry.Time = DateTime.Now.AddHours(hours);
5181 land.ParcelAccessList.Add(entry);
5182 }
5183 }
5184 // ScriptSleep(100);
5185 }
5186
5187 public void llSetTouchText(string text)
5188 {
5189 m_host.AddScriptLPS(1);
5190 m_host.TouchName = text;
5191 }
5192
5193 public void llSetSitText(string text)
5194 {
5195 m_host.AddScriptLPS(1);
5196 m_host.SitName = text;
5197 }
5198
5199 public void llSetCameraEyeOffset(LSL_Vector offset)
5200 {
5201 m_host.AddScriptLPS(1);
5202 m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z));
5203 }
5204
5205 public void llSetCameraAtOffset(LSL_Vector offset)
5206 {
5207 m_host.AddScriptLPS(1);
5208 m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z));
5209 }
5210
5211 public LSL_String llDumpList2String(LSL_List src, string seperator)
5212 {
5213 m_host.AddScriptLPS(1);
5214 if (src.Length == 0)
5215 {
5216 return String.Empty;
5217 }
5218 string ret = String.Empty;
5219 foreach (object o in src.Data)
5220 {
5221 ret = ret + o.ToString() + seperator;
5222 }
5223 ret = ret.Substring(0, ret.Length - seperator.Length);
5224 return ret;
5225 }
5226
5227 public LSL_Integer llScriptDanger(LSL_Vector pos)
5228 {
5229 m_host.AddScriptLPS(1);
5230 bool result = World.scriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z));
5231 if (result)
5232 {
5233 return 1;
5234 }
5235 else
5236 {
5237 return 0;
5238 }
5239
5240 }
5241
5242 public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel)
5243 {
5244 m_host.AddScriptLPS(1);
5245 UUID av = new UUID();
5246 if (!UUID.TryParse(avatar,out av))
5247 {
5248 LSLError("First parameter to llDialog needs to be a key");
5249 return;
5250 }
5251 if (buttons.Length > 12)
5252 {
5253 LSLError("No more than 12 buttons can be shown");
5254 return;
5255 }
5256 string[] buts = new string[buttons.Length];
5257 for (int i = 0; i < buttons.Length; i++)
5258 {
5259 if (buttons.Data[i].ToString() == String.Empty)
5260 {
5261 LSLError("button label cannot be blank");
5262 return;
5263 }
5264 if (buttons.Data[i].ToString().Length > 24)
5265 {
5266 LSLError("button label cannot be longer than 24 characters");
5267 return;
5268 }
5269 buts[i] = buttons.Data[i].ToString();
5270 }
5271 World.SendDialogToUser(av, m_host.Name, m_host.UUID, m_host.OwnerID, message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
5272 // ScriptSleep(1000);
5273 }
5274
5275 public void llVolumeDetect(int detect)
5276 {
5277 m_host.AddScriptLPS(1);
5278 NotImplemented("llVolumeDetect");
5279 }
5280
5281 /// <summary>
5282 /// Reset the named script. The script must be present
5283 /// in the same prim.
5284 /// </summary>
5285
5286 public void llResetOtherScript(string name) 183 public void llResetOtherScript(string name)
5287 { 184 {
5288 UUID item; 185 UUID item;
@@ -5295,7 +192,7 @@ namespace OpenSim.Region.ScriptEngine.Common
5295 // so get the state one step at a time. 192 // so get the state one step at a time.
5296 193
5297 if ((item = ScriptByName(name)) != UUID.Zero) 194 if ((item = ScriptByName(name)) != UUID.Zero)
5298 if ((sm = m_ScriptEngine.m_ScriptManager) != null) 195 if ((sm = m_ScriptEngineDirect.m_ScriptManager) != null)
5299 sm.ResetScript(m_localID, item); 196 sm.ResetScript(m_localID, item);
5300 197
5301 // Required by SL 198 // Required by SL
@@ -5307,7 +204,13 @@ namespace OpenSim.Region.ScriptEngine.Common
5307 // assume it is not running. 204 // assume it is not running.
5308 } 205 }
5309 206
5310 public LSL_Integer llGetScriptState(string name) 207 public void llResetScript()
208 {
209 m_host.AddScriptLPS(800);
210 m_ScriptEngineDirect.m_ScriptManager.ResetScript(m_localID, m_itemID);
211 }
212
213 public void llSetScriptState(string name, int run)
5311 { 214 {
5312 UUID item; 215 UUID item;
5313 ScriptManager sm; 216 ScriptManager sm;
@@ -5320,11 +223,14 @@ namespace OpenSim.Region.ScriptEngine.Common
5320 223
5321 if ((item = ScriptByName(name)) != UUID.Zero) 224 if ((item = ScriptByName(name)) != UUID.Zero)
5322 { 225 {
5323 if ((sm = m_ScriptEngine.m_ScriptManager) != null) 226 if ((sm = m_ScriptEngineDirect.m_ScriptManager) != null)
5324 { 227 {
5325 if ((script = sm.GetScript(m_localID, item)) != null) 228 if (sm.Scripts.ContainsKey(m_localID))
5326 { 229 {
5327 return script.Exec.Running?1:0; 230 if ((script = sm.GetScript(m_localID, item)) != null)
231 {
232 script.Exec.Running = (run==0) ? false : true;
233 }
5328 } 234 }
5329 } 235 }
5330 } 236 }
@@ -5332,2831 +238,12 @@ namespace OpenSim.Region.ScriptEngine.Common
5332 // Required by SL 238 // Required by SL
5333 239
5334 if (script == null) 240 if (script == null)
5335 ShoutError("llGetScriptState: script "+name+" not found"); 241 ShoutError("llSetScriptState: script "+name+" not found");
5336 242
5337 // If we didn't find it, then it's safe to 243 // If we didn't find it, then it's safe to
5338 // assume it is not running. 244 // assume it is not running.
5339
5340 return 0;
5341 }
5342
5343 public void llRemoteLoadScript()
5344 {
5345 m_host.AddScriptLPS(1);
5346 Deprecated("llRemoteLoadScript");
5347 // ScriptSleep(3000);
5348 }
5349
5350 public void llSetRemoteScriptAccessPin(int pin)
5351 {
5352 m_host.AddScriptLPS(1);
5353 m_host.ScriptAccessPin = pin;
5354 }
5355
5356 public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
5357 {
5358 m_host.AddScriptLPS(1);
5359 bool found = false;
5360 UUID destId = UUID.Zero;
5361 UUID srcId = UUID.Zero;
5362
5363 if (!UUID.TryParse(target, out destId))
5364 {
5365 llSay(0, "Could not parse key " + target);
5366 return;
5367 }
5368
5369 // target must be a different prim than the one containing the script
5370 if (m_host.UUID == destId)
5371 {
5372 return;
5373 }
5374
5375 // copy the first script found with this inventory name
5376 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
5377 {
5378 if (inv.Value.Name == name)
5379 {
5380 // make sure the object is a script
5381 if (10 == inv.Value.Type)
5382 {
5383 found = true;
5384 srcId = inv.Key;
5385 break;
5386 }
5387 }
5388 }
5389
5390 if (!found)
5391 {
5392 llSay(0, "Could not find script " + name);
5393 return;
5394 }
5395
5396 // the rest of the permission checks are done in RezScript, so check the pin there as well
5397 World.RezScript(srcId, m_host, destId, pin, running, start_param);
5398 // this will cause the delay even if the script pin or permissions were wrong - seems ok
5399 ScriptSleep(3000);
5400 } 245 }
5401 246
5402 public void llOpenRemoteDataChannel()
5403 {
5404 m_host.AddScriptLPS(1);
5405 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
5406 if (xmlrpcMod.IsEnabled())
5407 {
5408 UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, UUID.Zero);
5409 object[] resobj = new object[] { new LSL_Integer(1), new LSL_String(channelID.ToString()), new LSL_String(UUID.Zero.ToString()), new LSL_String(String.Empty), new LSL_Integer(0), new LSL_String(String.Empty) };
5410 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
5411 "remote_data", resobj,
5412 new DetectParams[0]));
5413 }
5414 // ScriptSleep(1000);
5415 }
5416
5417 public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata)
5418 {
5419 m_host.AddScriptLPS(1);
5420 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
5421 // ScriptSleep(3000);
5422 return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString();
5423 }
5424
5425 public void llRemoteDataReply(string channel, string message_id, string sdata, int idata)
5426 {
5427 m_host.AddScriptLPS(1);
5428 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
5429 xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
5430 // ScriptSleep(3000);
5431 }
5432
5433 public void llCloseRemoteDataChannel(string channel)
5434 {
5435 m_host.AddScriptLPS(1);
5436 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
5437 xmlrpcMod.CloseXMLRPCChannel(channel);
5438 // ScriptSleep(1000);
5439 }
5440
5441 public LSL_String llMD5String(string src, int nonce)
5442 {
5443 m_host.AddScriptLPS(1);
5444 return Util.Md5Hash(src + ":" + nonce.ToString());
5445 }
5446
5447 private ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist)
5448 {
5449 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
5450
5451 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
5452 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
5453 holeshape != (int)ScriptBaseClass.PRIM_HOLE_SQUARE &&
5454 holeshape != (int)ScriptBaseClass.PRIM_HOLE_TRIANGLE)
5455 {
5456 holeshape = (int)ScriptBaseClass.PRIM_HOLE_DEFAULT;
5457 }
5458 shapeBlock.ProfileCurve = (byte)holeshape;
5459 if (cut.x < 0f)
5460 {
5461 cut.x = 0f;
5462 }
5463 if (cut.x > 1f)
5464 {
5465 cut.x = 1f;
5466 }
5467 if (cut.y < 0f)
5468 {
5469 cut.y = 0f;
5470 }
5471 if (cut.y > 1f)
5472 {
5473 cut.y = 1f;
5474 }
5475 if (cut.y - cut.x < 0.05f)
5476 {
5477 cut.x = cut.y - 0.05f;
5478 }
5479 shapeBlock.ProfileBegin = (ushort)(50000 * cut.x);
5480 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y));
5481 if (hollow < 0f)
5482 {
5483 hollow = 0f;
5484 }
5485 if (hollow > 0.95)
5486 {
5487 hollow = 0.95f;
5488 }
5489 shapeBlock.ProfileHollow = (ushort)(50000 * hollow);
5490 if (twist.x < -1.0f)
5491 {
5492 twist.x = -1.0f;
5493 }
5494 if (twist.x > 1.0f)
5495 {
5496 twist.x = 1.0f;
5497 }
5498 if (twist.y < -1.0f)
5499 {
5500 twist.y = -1.0f;
5501 }
5502 if (twist.y > 1.0f)
5503 {
5504 twist.y = 1.0f;
5505 }
5506 shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x);
5507 shapeBlock.PathTwist = (sbyte)(100 * twist.y);
5508
5509 shapeBlock.ObjectLocalID = part.LocalId;
5510
5511 // retain pathcurve
5512 shapeBlock.PathCurve = part.Shape.PathCurve;
5513
5514 return shapeBlock;
5515 }
5516
5517 private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge)
5518 {
5519 ObjectShapePacket.ObjectDataBlock shapeBlock;
5520
5521 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
5522
5523 shapeBlock.ProfileCurve += fudge;
5524
5525 if (taper_b.x < 0f)
5526 {
5527 taper_b.x = 0f;
5528 }
5529 if (taper_b.x > 2f)
5530 {
5531 taper_b.x = 2f;
5532 }
5533 if (taper_b.y < 0f)
5534 {
5535 taper_b.y = 0f;
5536 }
5537 if (taper_b.y > 2f)
5538 {
5539 taper_b.y = 2f;
5540 }
5541 shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x));
5542 shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y));
5543 if (topshear.x < -0.5f)
5544 {
5545 topshear.x = -0.5f;
5546 }
5547 if (topshear.x > 0.5f)
5548 {
5549 topshear.x = 0.5f;
5550 }
5551 if (topshear.y < -0.5f)
5552 {
5553 topshear.y = -0.5f;
5554 }
5555 if (topshear.y > 0.5f)
5556 {
5557 topshear.y = 0.5f;
5558 }
5559 shapeBlock.PathShearX = (byte)(100 * topshear.x);
5560 shapeBlock.PathShearY = (byte)(100 * topshear.y);
5561
5562 part.UpdateShape(shapeBlock);
5563 }
5564
5565 private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge)
5566 {
5567 ObjectShapePacket.ObjectDataBlock shapeBlock;
5568
5569 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
5570
5571 // profile/path swapped for a sphere
5572 shapeBlock.PathBegin = shapeBlock.ProfileBegin;
5573 shapeBlock.PathEnd = shapeBlock.ProfileEnd;
5574
5575 shapeBlock.ProfileCurve += fudge;
5576
5577 shapeBlock.PathScaleX = 100;
5578 shapeBlock.PathScaleY = 100;
5579
5580 if (dimple.x < 0f)
5581 {
5582 dimple.x = 0f;
5583 }
5584 if (dimple.x > 1f)
5585 {
5586 dimple.x = 1f;
5587 }
5588 if (dimple.y < 0f)
5589 {
5590 dimple.y = 0f;
5591 }
5592 if (dimple.y > 1f)
5593 {
5594 dimple.y = 1f;
5595 }
5596 if (dimple.y - cut.x < 0.05f)
5597 {
5598 dimple.x = cut.y - 0.05f;
5599 }
5600 shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x);
5601 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y));
5602
5603 part.UpdateShape(shapeBlock);
5604 }
5605
5606 private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte fudge)
5607 {
5608 ObjectShapePacket.ObjectDataBlock shapeBlock;
5609
5610 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
5611
5612 shapeBlock.ProfileCurve += fudge;
5613
5614 // profile/path swapped for a torrus, tube, ring
5615 shapeBlock.PathBegin = shapeBlock.ProfileBegin;
5616 shapeBlock.PathEnd = shapeBlock.ProfileEnd;
5617
5618 if (holesize.x < 0.05f)
5619 {
5620 holesize.x = 0.05f;
5621 }
5622 if (holesize.x > 1f)
5623 {
5624 holesize.x = 1f;
5625 }
5626 if (holesize.y < 0.05f)
5627 {
5628 holesize.y = 0.05f;
5629 }
5630 if (holesize.y > 0.5f)
5631 {
5632 holesize.y = 0.5f;
5633 }
5634 shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x));
5635 shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y));
5636 if (topshear.x < -0.5f)
5637 {
5638 topshear.x = -0.5f;
5639 }
5640 if (topshear.x > 0.5f)
5641 {
5642 topshear.x = 0.5f;
5643 }
5644 if (topshear.y < -0.5f)
5645 {
5646 topshear.y = -0.5f;
5647 }
5648 if (topshear.y > 0.5f)
5649 {
5650 topshear.y = 0.5f;
5651 }
5652 shapeBlock.PathShearX = (byte)(100 * topshear.x);
5653 shapeBlock.PathShearY = (byte)(100 * topshear.y);
5654 if (profilecut.x < 0f)
5655 {
5656 profilecut.x = 0f;
5657 }
5658 if (profilecut.x > 1f)
5659 {
5660 profilecut.x = 1f;
5661 }
5662 if (profilecut.y < 0f)
5663 {
5664 profilecut.y = 0f;
5665 }
5666 if (profilecut.y > 1f)
5667 {
5668 profilecut.y = 1f;
5669 }
5670 if (profilecut.y - cut.x < 0.05f)
5671 {
5672 profilecut.x = cut.y - 0.05f;
5673 }
5674 shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x);
5675 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y));
5676 if (taper_a.x < -1f)
5677 {
5678 taper_a.x = -1f;
5679 }
5680 if (taper_a.x > 1f)
5681 {
5682 taper_a.x = 1f;
5683 }
5684 if (taper_a.y < -1f)
5685 {
5686 taper_a.y = -1f;
5687 }
5688 if (taper_a.y > 1f)
5689 {
5690 taper_a.y = 1f;
5691 }
5692 shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x);
5693 shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y);
5694 if (revolutions < 1f)
5695 {
5696 revolutions = 1f;
5697 }
5698 if (revolutions > 4f)
5699 {
5700 revolutions = 4f;
5701 }
5702 shapeBlock.PathRevolutions = (byte)(66.666667 * (revolutions - 1.0));
5703 // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
5704 if (radiusoffset < 0f)
5705 {
5706 radiusoffset = 0f;
5707 }
5708 if (radiusoffset > 1f)
5709 {
5710 radiusoffset = 1f;
5711 }
5712 shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset);
5713 if (skew < -0.95f)
5714 {
5715 skew = -0.95f;
5716 }
5717 if (skew > 0.95f)
5718 {
5719 skew = 0.95f;
5720 }
5721 shapeBlock.PathSkew = (sbyte)(100 * skew);
5722
5723 part.UpdateShape(shapeBlock);
5724 }
5725
5726 private void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type)
5727 {
5728 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
5729 UUID sculptId;
5730
5731 if (!UUID.TryParse(map, out sculptId))
5732 {
5733 llSay(0, "Could not parse key " + map);
5734 return;
5735 }
5736
5737 shapeBlock.ObjectLocalID = part.LocalId;
5738 shapeBlock.PathScaleX = 100;
5739 shapeBlock.PathScaleY = 150;
5740
5741 if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER &&
5742 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE &&
5743 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE &&
5744 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS)
5745 {
5746 // default
5747 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
5748 }
5749
5750 // retain pathcurve
5751 shapeBlock.PathCurve = part.Shape.PathCurve;
5752
5753 part.Shape.SetSculptData((byte)type, sculptId);
5754 part.Shape.SculptEntry = true;
5755 part.UpdateShape(shapeBlock);
5756 }
5757
5758 public void llSetPrimitiveParams(LSL_List rules)
5759 {
5760 SetPrimParams(m_host, rules);
5761 }
5762
5763 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
5764 {
5765 m_host.AddScriptLPS(1);
5766
5767 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5768
5769 foreach (SceneObjectPart part in parts)
5770 SetPrimParams(part, rules);
5771 }
5772
5773 private void SetPrimParams(SceneObjectPart part, LSL_List rules)
5774 {
5775 int idx = 0;
5776
5777 while (idx < rules.Length)
5778 {
5779 int code = rules.GetLSLIntegerItem(idx++);
5780
5781 int remain = rules.Length - idx;
5782
5783 int face;
5784 LSL_Vector v;
5785
5786 switch (code)
5787 {
5788 case (int)ScriptBaseClass.PRIM_POSITION:
5789 if (remain < 1)
5790 return;
5791
5792 v=rules.GetVector3Item(idx++);
5793 SetPos(part, v);
5794
5795 break;
5796 case (int)ScriptBaseClass.PRIM_SIZE:
5797 if (remain < 1)
5798 return;
5799
5800 v=rules.GetVector3Item(idx++);
5801 SetScale(part, v);
5802
5803 break;
5804 case (int)ScriptBaseClass.PRIM_ROTATION:
5805 if (remain < 1)
5806 return;
5807
5808 LSL_Rotation q = rules.GetQuaternionItem(idx++);
5809 SetRot(part, q);
5810
5811 break;
5812
5813 case (int)ScriptBaseClass.PRIM_TYPE:
5814 if (remain < 3)
5815 return;
5816
5817 code = (int)rules.GetLSLIntegerItem(idx++);
5818
5819 remain = rules.Length - idx;
5820 float hollow;
5821 LSL_Vector twist;
5822 LSL_Vector taper_b;
5823 LSL_Vector topshear;
5824 float revolutions;
5825 float radiusoffset;
5826 float skew;
5827 LSL_Vector holesize;
5828 LSL_Vector profilecut;
5829
5830 switch (code)
5831 {
5832 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
5833 if (remain < 6)
5834 return;
5835
5836 face = (int)rules.GetLSLIntegerItem(idx++);
5837 v = rules.GetVector3Item(idx++); // cut
5838 hollow = (float)rules.GetLSLFloatItem(idx++);
5839 twist = rules.GetVector3Item(idx++);
5840 taper_b = rules.GetVector3Item(idx++);
5841 topshear = rules.GetVector3Item(idx++);
5842 part.Shape.PathCurve = (byte)Extrusion.Straight;
5843 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 1);
5844 break;
5845
5846 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
5847 if (remain < 6)
5848 return;
5849
5850 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5851 v = rules.GetVector3Item(idx++); // cut
5852 hollow = (float)rules.GetLSLFloatItem(idx++);
5853 twist = rules.GetVector3Item(idx++);
5854 taper_b = rules.GetVector3Item(idx++);
5855 topshear = rules.GetVector3Item(idx++);
5856 part.Shape.ProfileShape = ProfileShape.Circle;
5857 part.Shape.PathCurve = (byte)Extrusion.Straight;
5858 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 0);
5859 break;
5860
5861 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
5862 if (remain < 6)
5863 return;
5864
5865 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5866 v = rules.GetVector3Item(idx++); //cut
5867 hollow = (float)rules.GetLSLFloatItem(idx++);
5868 twist = rules.GetVector3Item(idx++);
5869 taper_b = rules.GetVector3Item(idx++);
5870 topshear = rules.GetVector3Item(idx++);
5871 part.Shape.PathCurve = (byte)Extrusion.Straight;
5872 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 3);
5873 break;
5874
5875 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
5876 if (remain < 5)
5877 return;
5878
5879 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5880 v = rules.GetVector3Item(idx++); // cut
5881 hollow = (float)rules.GetLSLFloatItem(idx++);
5882 twist = rules.GetVector3Item(idx++);
5883 taper_b = rules.GetVector3Item(idx++); // dimple
5884 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5885 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, 5);
5886 break;
5887
5888 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
5889 if (remain < 11)
5890 return;
5891
5892 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5893 v = rules.GetVector3Item(idx++); //cut
5894 hollow = (float)rules.GetLSLFloatItem(idx++);
5895 twist = rules.GetVector3Item(idx++);
5896 holesize = rules.GetVector3Item(idx++);
5897 topshear = rules.GetVector3Item(idx++);
5898 profilecut = rules.GetVector3Item(idx++);
5899 taper_b = rules.GetVector3Item(idx++); // taper_a
5900 revolutions = (float)rules.GetLSLFloatItem(idx++);
5901 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
5902 skew = (float)rules.GetLSLFloatItem(idx++);
5903 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5904 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 0);
5905 break;
5906
5907 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
5908 if (remain < 11)
5909 return;
5910
5911 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5912 v = rules.GetVector3Item(idx++); //cut
5913 hollow = (float)rules.GetLSLFloatItem(idx++);
5914 twist = rules.GetVector3Item(idx++);
5915 holesize = rules.GetVector3Item(idx++);
5916 topshear = rules.GetVector3Item(idx++);
5917 profilecut = rules.GetVector3Item(idx++);
5918 taper_b = rules.GetVector3Item(idx++); // taper_a
5919 revolutions = (float)rules.GetLSLFloatItem(idx++);
5920 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
5921 skew = (float)rules.GetLSLFloatItem(idx++);
5922 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5923 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 1);
5924 break;
5925
5926 case (int)ScriptBaseClass.PRIM_TYPE_RING:
5927 if (remain < 11)
5928 return;
5929
5930 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5931 v = rules.GetVector3Item(idx++); //cut
5932 hollow = (float)rules.GetLSLFloatItem(idx++);
5933 twist = rules.GetVector3Item(idx++);
5934 holesize = rules.GetVector3Item(idx++);
5935 topshear = rules.GetVector3Item(idx++);
5936 profilecut = rules.GetVector3Item(idx++);
5937 taper_b = rules.GetVector3Item(idx++); // taper_a
5938 revolutions = (float)rules.GetLSLFloatItem(idx++);
5939 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
5940 skew = (float)rules.GetLSLFloatItem(idx++);
5941 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5942 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 3);
5943 break;
5944
5945 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
5946 if (remain < 2)
5947 return;
5948
5949 string map = rules.Data[idx++].ToString();
5950 face = (int)rules.GetLSLIntegerItem(idx++); // type
5951 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5952 SetPrimitiveShapeParams(part, map, face);
5953 break;
5954 }
5955
5956 break;
5957
5958 case (int)ScriptBaseClass.PRIM_TEXTURE:
5959 if (remain < 5)
5960 return;
5961
5962 face=(int)rules.GetLSLIntegerItem(idx++);
5963 string tex=rules.Data[idx++].ToString();
5964 LSL_Vector repeats=rules.GetVector3Item(idx++);
5965 LSL_Vector offsets=rules.GetVector3Item(idx++);
5966 double rotation=(double)rules.GetLSLFloatItem(idx++);
5967
5968 SetTexture(part, tex, face);
5969 ScaleTexture(part, repeats.x, repeats.y, face);
5970 OffsetTexture(part, offsets.x, offsets.y, face);
5971 RotateTexture(part, rotation, face);
5972
5973 break;
5974
5975 case (int)ScriptBaseClass.PRIM_COLOR:
5976 if (remain < 3)
5977 return;
5978
5979 face=(int)rules.GetLSLIntegerItem(idx++);
5980 LSL_Vector color=rules.GetVector3Item(idx++);
5981 double alpha=(double)rules.GetLSLFloatItem(idx++);
5982
5983 SetColor(part, color, face);
5984 SetAlpha(part, alpha, face);
5985
5986 break;
5987 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
5988 if (remain < 7)
5989 return;
5990
5991 bool flexi = rules.GetLSLIntegerItem(idx++);
5992 int softness = rules.GetLSLIntegerItem(idx++);
5993 float gravity = (float)rules.GetLSLFloatItem(idx++);
5994 float friction = (float)rules.GetLSLFloatItem(idx++);
5995 float wind = (float)rules.GetLSLFloatItem(idx++);
5996 float tension = (float)rules.GetLSLFloatItem(idx++);
5997 LSL_Vector force = rules.GetVector3Item(idx++);
5998
5999 SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force);
6000
6001 break;
6002 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
6003 if (remain < 5)
6004 return;
6005 bool light = rules.GetLSLIntegerItem(idx++);
6006 LSL_Vector lightcolor = rules.GetVector3Item(idx++);
6007 float intensity = (float)rules.GetLSLFloatItem(idx++);
6008 float radius = (float)rules.GetLSLFloatItem(idx++);
6009 float falloff = (float)rules.GetLSLFloatItem(idx++);
6010
6011 SetPointLight(part, light, lightcolor, intensity, radius, falloff);
6012
6013 break;
6014 case (int)ScriptBaseClass.PRIM_GLOW:
6015 if (remain < 2)
6016 return;
6017 face = rules.GetLSLIntegerItem(idx++);
6018 float glow = (float)rules.GetLSLFloatItem(idx++);
6019
6020 SetGlow(part, face, glow);
6021
6022 break;
6023 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
6024 if (remain < 3)
6025 return;
6026 face = (int)rules.GetLSLIntegerItem(idx++);
6027 int shiny = (int)rules.GetLSLIntegerItem(idx++);
6028 Bumpiness bump = (Bumpiness)Convert.ToByte((int)rules.GetLSLIntegerItem(idx++));
6029
6030 SetShiny(part, face, shiny, bump);
6031
6032 break;
6033 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
6034 if (remain < 2)
6035 return;
6036 face = rules.GetLSLIntegerItem(idx++);
6037 bool st = rules.GetLSLIntegerItem(idx++);
6038 SetFullBright(part, face , st);
6039 break;
6040 case (int)ScriptBaseClass.PRIM_MATERIAL:
6041 if (remain < 1)
6042 return;
6043 if (part != null)
6044 {
6045 /* Unhandled at this time - sends "Unhandled" message
6046 will enable when available
6047 byte material = Convert.ToByte((int)rules.GetLSLIntegerItem(idx++));
6048 part.Material = material;
6049 */
6050 return;
6051 }
6052 break;
6053 case (int)ScriptBaseClass.PRIM_PHANTOM:
6054 if (remain < 1)
6055 return;
6056
6057 string ph = rules.Data[idx++].ToString();
6058 bool phantom;
6059
6060 if (ph.Equals("1"))
6061 phantom = true;
6062 else
6063 phantom = false;
6064
6065 part.ScriptSetPhantomStatus(phantom);
6066 part.ScheduleFullUpdate();
6067 break;
6068 case (int)ScriptBaseClass.PRIM_PHYSICS:
6069 if (remain < 1)
6070 return;
6071 string phy = rules.Data[idx++].ToString();
6072 bool physics;
6073
6074 if (phy.Equals("1"))
6075 physics = true;
6076 else
6077 physics = false;
6078
6079 m_host.ScriptSetPhysicsStatus(physics);
6080 part.ScheduleFullUpdate();
6081 break;
6082 }
6083 }
6084 }
6085
6086 public LSL_String llStringToBase64(string str)
6087 {
6088 m_host.AddScriptLPS(1);
6089 try
6090 {
6091 byte[] encData_byte = new byte[str.Length];
6092 encData_byte = Encoding.UTF8.GetBytes(str);
6093 string encodedData = Convert.ToBase64String(encData_byte);
6094 return encodedData;
6095 }
6096 catch (Exception e)
6097 {
6098 throw new Exception("Error in base64Encode" + e.Message);
6099 }
6100 }
6101
6102 public LSL_String llBase64ToString(string str)
6103 {
6104 m_host.AddScriptLPS(1);
6105 UTF8Encoding encoder = new UTF8Encoding();
6106 Decoder utf8Decode = encoder.GetDecoder();
6107 try
6108 {
6109 byte[] todecode_byte = Convert.FromBase64String(str);
6110 int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
6111 char[] decoded_char = new char[charCount];
6112 utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
6113 string result = new String(decoded_char);
6114 return result;
6115 }
6116 catch (Exception e)
6117 {
6118 throw new Exception("Error in base64Decode" + e.Message);
6119 }
6120 }
6121
6122 public void llXorBase64Strings()
6123 {
6124 m_host.AddScriptLPS(1);
6125 Deprecated("llXorBase64Strings");
6126 // ScriptSleep(300);
6127 }
6128
6129 public void llRemoteDataSetRegion()
6130 {
6131 m_host.AddScriptLPS(1);
6132 NotImplemented("llRemoteDataSetRegion");
6133 }
6134
6135 public LSL_Float llLog10(double val)
6136 {
6137 m_host.AddScriptLPS(1);
6138 return (double)Math.Log10(val);
6139 }
6140
6141 public LSL_Float llLog(double val)
6142 {
6143 m_host.AddScriptLPS(1);
6144 return (double)Math.Log(val);
6145 }
6146
6147 public LSL_List llGetAnimationList( string id )
6148 {
6149 m_host.AddScriptLPS(1);
6150
6151 LSL_List l = new LSL_List();
6152 ScenePresence av = World.GetScenePresence(id);
6153 if (av == null)
6154 return l;
6155 UUID[] anims;
6156 anims = av.GetAnimationArray();
6157 foreach (UUID foo in anims)
6158 l.Add(foo.ToString());
6159 return l;
6160 }
6161
6162 public void llSetParcelMusicURL(string url)
6163 {
6164 m_host.AddScriptLPS(1);
6165 UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
6166 if (landowner == UUID.Zero)
6167 {
6168 return;
6169 }
6170 if (landowner != m_host.ObjectOwner)
6171 {
6172 return;
6173 }
6174 World.SetLandMusicURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url);
6175 // ScriptSleep(2000);
6176 }
6177
6178 public LSL_Vector llGetRootPosition()
6179 {
6180 m_host.AddScriptLPS(1);
6181 return new LSL_Vector(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, m_host.ParentGroup.AbsolutePosition.Z);
6182 }
6183
6184 public LSL_Rotation llGetRootRotation()
6185 {
6186 m_host.AddScriptLPS(1);
6187 return new LSL_Rotation(m_host.ParentGroup.GroupRotation.X, m_host.ParentGroup.GroupRotation.Y, m_host.ParentGroup.GroupRotation.Z, m_host.ParentGroup.GroupRotation.W);
6188 }
6189
6190 public LSL_String llGetObjectDesc()
6191 {
6192 return m_host.Description!=null?m_host.Description:String.Empty;
6193 }
6194
6195 public void llSetObjectDesc(string desc)
6196 {
6197 m_host.AddScriptLPS(1);
6198 m_host.Description = desc!=null?desc:String.Empty;
6199 }
6200
6201 public LSL_String llGetCreator()
6202 {
6203 m_host.AddScriptLPS(1);
6204 return m_host.ObjectCreator.ToString();
6205 }
6206
6207 public LSL_String llGetTimestamp()
6208 {
6209 m_host.AddScriptLPS(1);
6210 return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
6211 }
6212
6213 public void llSetLinkAlpha(int linknumber, double alpha, int face)
6214 {
6215 m_host.AddScriptLPS(1);
6216 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber);
6217 if (linknumber > -1)
6218 {
6219 Primitive.TextureEntry tex = part.Shape.Textures;
6220 Color4 texcolor;
6221 if (face >= 0 && face < GetNumberOfSides(m_host))
6222 {
6223 texcolor = tex.CreateFace((uint)face).RGBA;
6224 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6225 tex.FaceTextures[face].RGBA = texcolor;
6226 part.UpdateTexture(tex);
6227 return;
6228 }
6229 else if (face == ScriptBaseClass.ALL_SIDES)
6230 {
6231 texcolor = tex.DefaultTexture.RGBA;
6232 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6233 tex.DefaultTexture.RGBA = texcolor;
6234 for (uint i = 0; i < GetNumberOfSides(m_host); i++)
6235 {
6236 if (tex.FaceTextures[i] != null)
6237 {
6238 texcolor = tex.FaceTextures[i].RGBA;
6239 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6240 tex.FaceTextures[i].RGBA = texcolor;
6241 }
6242 }
6243 texcolor = tex.DefaultTexture.RGBA;
6244 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6245 tex.DefaultTexture.RGBA = texcolor;
6246 part.UpdateTexture(tex);
6247 return;
6248 }
6249 return;
6250 }
6251 else if (linknumber == -1)
6252 {
6253 int num = m_host.ParentGroup.PrimCount;
6254 for (int w = 0; w < num; w++)
6255 {
6256 linknumber = w;
6257 part = m_host.ParentGroup.GetLinkNumPart(linknumber);
6258 Primitive.TextureEntry tex = part.Shape.Textures;
6259 Color4 texcolor;
6260 if (face > -1)
6261 {
6262 texcolor = tex.CreateFace((uint)face).RGBA;
6263 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6264 tex.FaceTextures[face].RGBA = texcolor;
6265 part.UpdateTexture(tex);
6266 }
6267 else if (face == -1)
6268 {
6269 texcolor = tex.DefaultTexture.RGBA;
6270 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6271 tex.DefaultTexture.RGBA = texcolor;
6272 for (uint i = 0; i < 32; i++)
6273 {
6274 if (tex.FaceTextures[i] != null)
6275 {
6276 texcolor = tex.FaceTextures[i].RGBA;
6277 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6278 tex.FaceTextures[i].RGBA = texcolor;
6279 }
6280 }
6281 texcolor = tex.DefaultTexture.RGBA;
6282 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6283 tex.DefaultTexture.RGBA = texcolor;
6284 part.UpdateTexture(tex);
6285 }
6286 }
6287 return;
6288 }
6289 }
6290
6291 public LSL_Integer llGetNumberOfPrims()
6292 {
6293 m_host.AddScriptLPS(1);
6294 return m_host.ParentGroup.PrimCount;
6295 }
6296
6297 public LSL_List llGetBoundingBox(string obj)
6298 {
6299 m_host.AddScriptLPS(1);
6300 NotImplemented("llGetBoundingBox");
6301 return new LSL_List();
6302 }
6303
6304 public LSL_Vector llGetGeometricCenter()
6305 {
6306 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z);
6307 }
6308
6309 public LSL_List llGetPrimitiveParams(LSL_List rules)
6310 {
6311 m_host.AddScriptLPS(1);
6312
6313 LSL_List res = new LSL_List();
6314 int idx=0;
6315 while (idx < rules.Length)
6316 {
6317 int code=(int)rules.GetLSLIntegerItem(idx++);
6318 int remain=rules.Length-idx;
6319
6320 switch (code)
6321 {
6322 case (int)ScriptBaseClass.PRIM_MATERIAL:
6323 res.Add(new LSL_Integer(m_host.Material));
6324 break;
6325
6326 case (int)ScriptBaseClass.PRIM_PHYSICS:
6327 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0)
6328 res.Add(new LSL_Integer(1));
6329 else
6330 res.Add(new LSL_Integer(0));
6331 break;
6332
6333 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
6334 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0)
6335 res.Add(new LSL_Integer(1));
6336 else
6337 res.Add(new LSL_Integer(0));
6338 break;
6339
6340 case (int)ScriptBaseClass.PRIM_PHANTOM:
6341 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
6342 res.Add(new LSL_Integer(1));
6343 else
6344 res.Add(new LSL_Integer(0));
6345 break;
6346
6347 case (int)ScriptBaseClass.PRIM_POSITION:
6348 res.Add(new LSL_Vector(m_host.AbsolutePosition.X,
6349 m_host.AbsolutePosition.Y,
6350 m_host.AbsolutePosition.Z));
6351 break;
6352
6353 case (int)ScriptBaseClass.PRIM_SIZE:
6354 res.Add(new LSL_Vector(m_host.Scale.X,
6355 m_host.Scale.Y,
6356 m_host.Scale.Z));
6357 break;
6358
6359 case (int)ScriptBaseClass.PRIM_ROTATION:
6360 res.Add(new LSL_Rotation(m_host.RotationOffset.X,
6361 m_host.RotationOffset.Y,
6362 m_host.RotationOffset.Z,
6363 m_host.RotationOffset.W));
6364 break;
6365
6366 case (int)ScriptBaseClass.PRIM_TYPE:
6367 // implementing box
6368 PrimitiveBaseShape Shape = m_host.Shape;
6369 int primType = getScriptPrimType(m_host.Shape);
6370 res.Add(new LSL_Integer(primType));
6371 switch (primType)
6372 {
6373 case ScriptBaseClass.PRIM_TYPE_BOX:
6374 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
6375 case ScriptBaseClass.PRIM_TYPE_PRISM:
6376 res.Add(new LSL_Integer(Shape.ProfileCurve));
6377 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
6378 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
6379 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
6380 res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
6381 res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0));
6382 break;
6383
6384 case ScriptBaseClass.PRIM_TYPE_SPHERE:
6385 res.Add(new LSL_Integer(Shape.ProfileCurve));
6386 res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
6387 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
6388 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
6389 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
6390 break;
6391
6392 case ScriptBaseClass.PRIM_TYPE_SCULPT:
6393 res.Add(Shape.SculptTexture.ToString());
6394 res.Add(new LSL_Integer(Shape.SculptType));
6395 break;
6396
6397 case ScriptBaseClass.PRIM_TYPE_RING:
6398 case ScriptBaseClass.PRIM_TYPE_TUBE:
6399 case ScriptBaseClass.PRIM_TYPE_TORUS:
6400 // holeshape
6401 res.Add(new LSL_Integer(Shape.ProfileCurve));
6402
6403 // cut
6404 res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
6405
6406 // hollow
6407 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
6408
6409 // twist
6410 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
6411
6412 // vector holesize
6413 res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
6414
6415 // vector topshear
6416 res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0));
6417
6418 // vector profilecut
6419 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
6420
6421
6422 // vector tapera
6423 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
6424
6425 // float revolutions,
6426 res.Add(new LSL_Float(Shape.PathRevolutions / 50.0)); // needs fixing :(
6427
6428 // float radiusoffset,
6429 res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));
6430
6431 // float skew
6432 res.Add(new LSL_Float(Shape.PathSkew / 100.0));
6433 break;
6434
6435 }
6436 break;
6437
6438 case (int)ScriptBaseClass.PRIM_TEXTURE:
6439 if (remain < 1)
6440 return res;
6441
6442 int face = (int)rules.GetLSLIntegerItem(idx++);
6443 Primitive.TextureEntry tex = m_host.Shape.Textures;
6444 if (face == ScriptBaseClass.ALL_SIDES)
6445 {
6446 for (face = 0 ; face < GetNumberOfSides(m_host) ; face++)
6447 {
6448 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
6449
6450 res.Add(new LSL_String(texface.TextureID.ToString()));
6451 res.Add(new LSL_Vector(texface.RepeatU,
6452 texface.RepeatV,
6453 0));
6454 res.Add(new LSL_Vector(texface.OffsetU,
6455 texface.OffsetV,
6456 0));
6457 res.Add(new LSL_Float(texface.Rotation));
6458 }
6459 }
6460 else
6461 {
6462 if (face >= 0 && face < GetNumberOfSides(m_host))
6463 {
6464 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
6465
6466 res.Add(new LSL_String(texface.TextureID.ToString()));
6467 res.Add(new LSL_Vector(texface.RepeatU,
6468 texface.RepeatV,
6469 0));
6470 res.Add(new LSL_Vector(texface.OffsetU,
6471 texface.OffsetV,
6472 0));
6473 res.Add(new LSL_Float(texface.Rotation));
6474 }
6475 }
6476 break;
6477
6478 case (int)ScriptBaseClass.PRIM_COLOR:
6479 if (remain < 1)
6480 return res;
6481
6482 face=(int)rules.GetLSLIntegerItem(idx++);
6483
6484 tex = m_host.Shape.Textures;
6485 Color4 texcolor;
6486 if (face == ScriptBaseClass.ALL_SIDES)
6487 {
6488 for (face = 0 ; face < GetNumberOfSides(m_host) ; face++)
6489 {
6490 texcolor = tex.GetFace((uint)face).RGBA;
6491 res.Add(new LSL_Vector(texcolor.R,
6492 texcolor.G,
6493 texcolor.B));
6494 res.Add(new LSL_Float(texcolor.A));
6495 }
6496 }
6497 else
6498 {
6499 texcolor = tex.GetFace((uint)face).RGBA;
6500 res.Add(new LSL_Vector(texcolor.R,
6501 texcolor.G,
6502 texcolor.B));
6503 res.Add(new LSL_Float(texcolor.A));
6504 }
6505 break;
6506
6507 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
6508 // TODO--------------
6509 if (remain < 1)
6510 return res;
6511
6512 face=(int)rules.GetLSLIntegerItem(idx++);
6513
6514 res.Add(new LSL_Integer(0));
6515 res.Add(new LSL_Integer(0));
6516 break;
6517
6518 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
6519 // TODO--------------
6520 if (remain < 1)
6521 return res;
6522
6523 face=(int)rules.GetLSLIntegerItem(idx++);
6524
6525 res.Add(new LSL_Integer(0));
6526 break;
6527
6528 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
6529 PrimitiveBaseShape shape = m_host.Shape;
6530
6531 if (shape.FlexiEntry)
6532 res.Add(new LSL_Integer(1)); // active
6533 else
6534 res.Add(new LSL_Integer(0));
6535 res.Add(new LSL_Integer(shape.FlexiSoftness));// softness
6536 res.Add(new LSL_Float(shape.FlexiGravity)); // gravity
6537 res.Add(new LSL_Float(shape.FlexiDrag)); // friction
6538 res.Add(new LSL_Float(shape.FlexiWind)); // wind
6539 res.Add(new LSL_Float(shape.FlexiTension)); // tension
6540 res.Add(new LSL_Vector(shape.FlexiForceX, // force
6541 shape.FlexiForceY,
6542 shape.FlexiForceZ));
6543 break;
6544
6545 case (int)ScriptBaseClass.PRIM_TEXGEN:
6546 // TODO--------------
6547 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
6548 if (remain < 1)
6549 return res;
6550
6551 face=(int)rules.GetLSLIntegerItem(idx++);
6552
6553 res.Add(new LSL_Integer(0));
6554 break;
6555
6556 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
6557 shape = m_host.Shape;
6558
6559 if (shape.LightEntry)
6560 res.Add(new LSL_Integer(1)); // active
6561 else
6562 res.Add(new LSL_Integer(0));
6563 res.Add(new LSL_Vector(shape.LightColorR, // color
6564 shape.LightColorG,
6565 shape.LightColorB));
6566 res.Add(new LSL_Float(shape.LightIntensity)); // intensity
6567 res.Add(new LSL_Float(shape.LightRadius)); // radius
6568 res.Add(new LSL_Float(shape.LightFalloff)); // falloff
6569 break;
6570
6571 case (int)ScriptBaseClass.PRIM_GLOW:
6572 // TODO--------------
6573 if (remain < 1)
6574 return res;
6575
6576 face=(int)rules.GetLSLIntegerItem(idx++);
6577
6578 res.Add(new LSL_Float(0));
6579 break;
6580 }
6581 }
6582 return res;
6583 }
6584
6585 // <remarks>
6586 // <para>
6587 // The .NET definition of base 64 is:
6588 // <list>
6589 // <item>
6590 // Significant: A-Z a-z 0-9 + -
6591 // </item>
6592 // <item>
6593 // Whitespace: \t \n \r ' '
6594 // </item>
6595 // <item>
6596 // Valueless: =
6597 // </item>
6598 // <item>
6599 // End-of-string: \0 or '=='
6600 // </item>
6601 // </list>
6602 // </para>
6603 // <para>
6604 // Each point in a base-64 string represents
6605 // a 6 bit value. A 32-bit integer can be
6606 // represented using 6 characters (with some
6607 // redundancy).
6608 // </para>
6609 // <para>
6610 // LSL requires a base64 string to be 8
6611 // characters in length. LSL also uses '/'
6612 // rather than '-' (MIME compliant).
6613 // </para>
6614 // <para>
6615 // RFC 1341 used as a reference (as specified
6616 // by the SecondLife Wiki).
6617 // </para>
6618 // <para>
6619 // SL do not record any kind of exception for
6620 // these functions, so the string to integer
6621 // conversion returns '0' if an invalid
6622 // character is encountered during conversion.
6623 // </para>
6624 // <para>
6625 // References
6626 // <list>
6627 // <item>
6628 // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64
6629 // </item>
6630 // <item>
6631 // </item>
6632 // </list>
6633 // </para>
6634 // </remarks>
6635
6636 // <summary>
6637 // Table for converting 6-bit integers into
6638 // base-64 characters
6639 // </summary>
6640
6641 private static readonly char[] i2ctable =
6642 {
6643 'A','B','C','D','E','F','G','H',
6644 'I','J','K','L','M','N','O','P',
6645 'Q','R','S','T','U','V','W','X',
6646 'Y','Z',
6647 'a','b','c','d','e','f','g','h',
6648 'i','j','k','l','m','n','o','p',
6649 'q','r','s','t','u','v','w','x',
6650 'y','z',
6651 '0','1','2','3','4','5','6','7',
6652 '8','9',
6653 '+','/'
6654 };
6655
6656 // <summary>
6657 // Table for converting base-64 characters
6658 // into 6-bit integers.
6659 // </summary>
6660
6661 private static readonly int[] c2itable =
6662 {
6663 -1,-1,-1,-1,-1,-1,-1,-1, // 0x
6664 -1,-1,-1,-1,-1,-1,-1,-1,
6665 -1,-1,-1,-1,-1,-1,-1,-1, // 1x
6666 -1,-1,-1,-1,-1,-1,-1,-1,
6667 -1,-1,-1,-1,-1,-1,-1,-1, // 2x
6668 -1,-1,-1,63,-1,-1,-1,64,
6669 53,54,55,56,57,58,59,60, // 3x
6670 61,62,-1,-1,-1,0,-1,-1,
6671 -1,1,2,3,4,5,6,7, // 4x
6672 8,9,10,11,12,13,14,15,
6673 16,17,18,19,20,21,22,23, // 5x
6674 24,25,26,-1,-1,-1,-1,-1,
6675 -1,27,28,29,30,31,32,33, // 6x
6676 34,35,36,37,38,39,40,41,
6677 42,43,44,45,46,47,48,49, // 7x
6678 50,51,52,-1,-1,-1,-1,-1,
6679 -1,-1,-1,-1,-1,-1,-1,-1, // 8x
6680 -1,-1,-1,-1,-1,-1,-1,-1,
6681 -1,-1,-1,-1,-1,-1,-1,-1, // 9x
6682 -1,-1,-1,-1,-1,-1,-1,-1,
6683 -1,-1,-1,-1,-1,-1,-1,-1, // Ax
6684 -1,-1,-1,-1,-1,-1,-1,-1,
6685 -1,-1,-1,-1,-1,-1,-1,-1, // Bx
6686 -1,-1,-1,-1,-1,-1,-1,-1,
6687 -1,-1,-1,-1,-1,-1,-1,-1, // Cx
6688 -1,-1,-1,-1,-1,-1,-1,-1,
6689 -1,-1,-1,-1,-1,-1,-1,-1, // Dx
6690 -1,-1,-1,-1,-1,-1,-1,-1,
6691 -1,-1,-1,-1,-1,-1,-1,-1, // Ex
6692 -1,-1,-1,-1,-1,-1,-1,-1,
6693 -1,-1,-1,-1,-1,-1,-1,-1, // Fx
6694 -1,-1,-1,-1,-1,-1,-1,-1
6695 };
6696
6697 // <summary>
6698 // Converts a 32-bit integer into a Base64
6699 // character string. Base64 character strings
6700 // are always 8 characters long. All iinteger
6701 // values are acceptable.
6702 // </summary>
6703 // <param name="number">
6704 // 32-bit integer to be converted.
6705 // </param>
6706 // <returns>
6707 // 8 character string. The 1st six characters
6708 // contain the encoded number, the last two
6709 // characters are padded with "=".
6710 // </returns>
6711
6712 public LSL_String llIntegerToBase64(int number)
6713 {
6714 // uninitialized string
6715
6716 char[] imdt = new char[8];
6717
6718 m_host.AddScriptLPS(1);
6719
6720 // Manually unroll the loop
6721
6722 imdt[7] = '=';
6723 imdt[6] = '=';
6724 imdt[5] = i2ctable[number<<4 & 0x3F];
6725 imdt[4] = i2ctable[number>>2 & 0x3F];
6726 imdt[3] = i2ctable[number>>8 & 0x3F];
6727 imdt[2] = i2ctable[number>>14 & 0x3F];
6728 imdt[1] = i2ctable[number>>20 & 0x3F];
6729 imdt[0] = i2ctable[number>>26 & 0x3F];
6730
6731 return new string(imdt);
6732 }
6733
6734 // <summary>
6735 // Converts an eight character base-64 string
6736 // into a 32-bit integer.
6737 // </summary>
6738 // <param name="str">
6739 // 8 characters string to be converted. Other
6740 // length strings return zero.
6741 // </param>
6742 // <returns>
6743 // Returns an integer representing the
6744 // encoded value providedint he 1st 6
6745 // characters of the string.
6746 // </returns>
6747 // <remarks>
6748 // This is coded to behave like LSL's
6749 // implementation (I think), based upon the
6750 // information available at the Wiki.
6751 // If more than 8 characters are supplied,
6752 // zero is returned.
6753 // If a NULL string is supplied, zero will
6754 // be returned.
6755 // If fewer than 6 characters are supplied, then
6756 // the answer will reflect a partial
6757 // accumulation.
6758 // <para>
6759 // The 6-bit segments are
6760 // extracted left-to-right in big-endian mode,
6761 // which means that segment 6 only contains the
6762 // two low-order bits of the 32 bit integer as
6763 // its high order 2 bits. A short string therefore
6764 // means loss of low-order information. E.g.
6765 //
6766 // |<---------------------- 32-bit integer ----------------------->|<-Pad->|
6767 // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->|
6768 // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P|
6769 // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P|
6770 // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] |
6771 //
6772 // </para>
6773 // </remarks>
6774
6775 public LSL_Integer llBase64ToInteger(string str)
6776 {
6777 int number = 0;
6778 int digit;
6779
6780 m_host.AddScriptLPS(1);
6781
6782 // Require a well-fromed base64 string
6783
6784 if (str.Length > 8)
6785 return 0;
6786
6787 // The loop is unrolled in the interests
6788 // of performance and simple necessity.
6789 //
6790 // MUST find 6 digits to be well formed
6791 // -1 == invalid
6792 // 0 == padding
6793
6794 if ((digit=c2itable[str[0]])<=0)
6795 {
6796 return digit<0?(int)0:number;
6797 }
6798 number += --digit<<26;
6799
6800 if ((digit=c2itable[str[1]])<=0)
6801 {
6802 return digit<0?(int)0:number;
6803 }
6804 number += --digit<<20;
6805
6806 if ((digit=c2itable[str[2]])<=0)
6807 {
6808 return digit<0?(int)0:number;
6809 }
6810 number += --digit<<14;
6811
6812 if ((digit=c2itable[str[3]])<=0)
6813 {
6814 return digit<0?(int)0:number;
6815 }
6816 number += --digit<<8;
6817
6818 if ((digit=c2itable[str[4]])<=0)
6819 {
6820 return digit<0?(int)0:number;
6821 }
6822 number += --digit<<2;
6823
6824 if ((digit=c2itable[str[5]])<=0)
6825 {
6826 return digit<0?(int)0:number;
6827 }
6828 number += --digit>>4;
6829
6830 // ignore trailing padding
6831
6832 return number;
6833 }
6834
6835 public LSL_Float llGetGMTclock()
6836 {
6837 m_host.AddScriptLPS(1);
6838 return DateTime.UtcNow.TimeOfDay.TotalSeconds;
6839 }
6840
6841 public LSL_String llGetSimulatorHostname()
6842 {
6843 m_host.AddScriptLPS(1);
6844 return System.Environment.MachineName;
6845 }
6846
6847 public void llSetLocalRot(LSL_Rotation rot)
6848 {
6849 m_host.AddScriptLPS(1);
6850 m_host.RotationOffset = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
6851 // ScriptSleep(200);
6852 }
6853
6854 // <summary>
6855 // Scan the string supplied in 'src' and
6856 // tokenize it based upon two sets of
6857 // tokenizers provided in two lists,
6858 // separators and spacers.
6859 // </summary>
6860 //
6861 // <remarks>
6862 // Separators demarcate tokens and are
6863 // elided as they are encountered. Spacers
6864 // also demarcate tokens, but are themselves
6865 // retained as tokens.
6866 //
6867 // Both separators and spacers may be arbitrarily
6868 // long strings. i.e. ":::".
6869 //
6870 // The function returns an ordered list
6871 // representing the tokens found in the supplied
6872 // sources string. If two successive tokenizers
6873 // are encountered, then a NULL entry is added
6874 // to the list.
6875 //
6876 // It is a precondition that the source and
6877 // toekizer lisst are non-null. If they are null,
6878 // then a null pointer exception will be thrown
6879 // while their lengths are being determined.
6880 //
6881 // A small amount of working memoryis required
6882 // of approximately 8*#tokenizers.
6883 //
6884 // There are many ways in which this function
6885 // can be implemented, this implementation is
6886 // fairly naive and assumes that when the
6887 // function is invooked with a short source
6888 // string and/or short lists of tokenizers, then
6889 // performance will not be an issue.
6890 //
6891 // In order to minimize the perofrmance
6892 // effects of long strings, or large numbers
6893 // of tokeizers, the function skips as far as
6894 // possible whenever a toekenizer is found,
6895 // and eliminates redundant tokenizers as soon
6896 // as is possible.
6897 //
6898 // The implementation tries to avoid any copying
6899 // of arrays or other objects.
6900 // </remarks>
6901
6902 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
6903 {
6904 int beginning = 0;
6905 int srclen = src.Length;
6906 int seplen = separators.Length;
6907 object[] separray = separators.Data;
6908 int spclen = spacers.Length;
6909 object[] spcarray = spacers.Data;
6910 int mlen = seplen+spclen;
6911
6912 int[] offset = new int[mlen+1];
6913 bool[] active = new bool[mlen];
6914
6915 int best;
6916 int j;
6917
6918 // Initial capacity reduces resize cost
6919
6920 LSL_List tokens = new LSL_List();
6921
6922 m_host.AddScriptLPS(1);
6923
6924 // All entries are initially valid
6925
6926 for (int i = 0; i < mlen; i++)
6927 active[i] = true;
6928
6929 offset[mlen] = srclen;
6930
6931 while (beginning < srclen)
6932 {
6933
6934 best = mlen; // as bad as it gets
6935
6936 // Scan for separators
6937
6938 for (j = 0; j < seplen; j++)
6939 {
6940 if (active[j])
6941 {
6942 // scan all of the markers
6943 if ((offset[j] = src.IndexOf(separray[j].ToString(),beginning)) == -1)
6944 {
6945 // not present at all
6946 active[j] = false;
6947 }
6948 else
6949 {
6950 // present and correct
6951 if (offset[j] < offset[best])
6952 {
6953 // closest so far
6954 best = j;
6955 if (offset[best] == beginning)
6956 break;
6957 }
6958 }
6959 }
6960 }
6961
6962 // Scan for spacers
6963
6964 if (offset[best] != beginning)
6965 {
6966 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++)
6967 {
6968 if (active[j])
6969 {
6970 // scan all of the markers
6971 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
6972 {
6973 // not present at all
6974 active[j] = false;
6975 }
6976 else
6977 {
6978 // present and correct
6979 if (offset[j] < offset[best])
6980 {
6981 // closest so far
6982 best = j;
6983 }
6984 }
6985 }
6986 }
6987 }
6988
6989 // This is the normal exit from the scanning loop
6990
6991 if (best == mlen)
6992 {
6993 // no markers were found on this pass
6994 // so we're pretty much done
6995 tokens.Add(src.Substring(beginning, srclen - beginning));
6996 break;
6997 }
6998
6999 // Otherwise we just add the newly delimited token
7000 // and recalculate where the search should continue.
7001
7002 tokens.Add(src.Substring(beginning,offset[best]-beginning));
7003
7004 if (best < seplen)
7005 {
7006 beginning = offset[best] + (separray[best].ToString()).Length;
7007 }
7008 else
7009 {
7010 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
7011 tokens.Add(spcarray[best - seplen]);
7012 }
7013 }
7014
7015 // This an awkward an not very intuitive boundary case. If the
7016 // last substring is a tokenizer, then there is an implied trailing
7017 // null list entry. Hopefully the single comparison will not be too
7018 // arduous. Alternatively the 'break' could be replced with a return
7019 // but that's shabby programming.
7020
7021 if (beginning == srclen)
7022 {
7023 if (srclen != 0)
7024 tokens.Add("");
7025 }
7026
7027 return tokens;
7028 }
7029
7030 public LSL_Integer llGetObjectPermMask(int mask)
7031 {
7032 m_host.AddScriptLPS(1);
7033
7034 int permmask = 0;
7035
7036 if (mask == ScriptBaseClass.MASK_BASE)//0
7037 {
7038 permmask = (int)m_host.BaseMask;
7039 }
7040
7041 else if (mask == ScriptBaseClass.MASK_OWNER)//1
7042 {
7043 permmask = (int)m_host.OwnerMask;
7044 }
7045
7046 else if (mask == ScriptBaseClass.MASK_GROUP)//2
7047 {
7048 permmask = (int)m_host.GroupMask;
7049 }
7050
7051 else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
7052 {
7053 permmask = (int)m_host.EveryoneMask;
7054 }
7055
7056 else if (mask == ScriptBaseClass.MASK_NEXT)//4
7057 {
7058 permmask = (int)m_host.NextOwnerMask;
7059 }
7060
7061 return permmask;
7062 }
7063
7064 public void llSetObjectPermMask(int mask, int value)
7065 {
7066 m_host.AddScriptLPS(1);
7067 IConfigSource config = new IniConfigSource(Application.iniFilePath);
7068 if (config.Configs["XEngine"] == null)
7069 config.AddConfig("XEngine");
7070
7071 if (config.Configs["XEngine"].GetBoolean("AllowGodFunctions", false))
7072 {
7073 if (World.ExternalChecks.ExternalChecksCanRunConsoleCommand(m_host.OwnerID))
7074 {
7075 if (mask == ScriptBaseClass.MASK_BASE)//0
7076 {
7077 m_host.BaseMask = (uint)value;
7078 }
7079
7080 else if (mask == ScriptBaseClass.MASK_OWNER)//1
7081 {
7082 m_host.OwnerMask = (uint)value;
7083 }
7084
7085 else if (mask == ScriptBaseClass.MASK_GROUP)//2
7086 {
7087 m_host.GroupMask = (uint)value;
7088 }
7089
7090 else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
7091 {
7092 m_host.EveryoneMask = (uint)value;
7093 }
7094
7095 else if (mask == ScriptBaseClass.MASK_NEXT)//4
7096 {
7097 m_host.NextOwnerMask = (uint)value;
7098 }
7099 }
7100 }
7101 }
7102
7103 public LSL_Integer llGetInventoryPermMask(string item, int mask)
7104 {
7105 m_host.AddScriptLPS(1);
7106 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
7107 {
7108 if (inv.Value.Name == item)
7109 {
7110 switch (mask)
7111 {
7112 case 0:
7113 return (int)inv.Value.BasePermissions;
7114 case 1:
7115 return (int)inv.Value.CurrentPermissions;
7116 case 2:
7117 return (int)inv.Value.GroupPermissions;
7118 case 3:
7119 return (int)inv.Value.EveryonePermissions;
7120 case 4:
7121 return (int)inv.Value.NextPermissions;
7122 }
7123 }
7124 }
7125 return -1;
7126 }
7127
7128 public void llSetInventoryPermMask(string item, int mask, int value)
7129 {
7130 m_host.AddScriptLPS(1);
7131 NotImplemented("llSetInventoryPermMask");
7132 }
7133
7134 public LSL_String llGetInventoryCreator(string item)
7135 {
7136 m_host.AddScriptLPS(1);
7137 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
7138 {
7139 if (inv.Value.Name == item)
7140 {
7141 return inv.Value.CreatorID.ToString();
7142 }
7143 }
7144 llSay(0, "No item name '" + item + "'");
7145 return String.Empty;
7146 }
7147
7148 public void llOwnerSay(string msg)
7149 {
7150 m_host.AddScriptLPS(1);
7151
7152 World.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
7153// IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
7154// wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg);
7155 }
7156
7157 public LSL_String llRequestSimulatorData(string simulator, int data)
7158 {
7159 try
7160 {
7161 m_host.AddScriptLPS(1);
7162
7163 string reply = String.Empty;
7164
7165 RegionInfo info = m_ScriptEngine.World.RequestClosestRegion(simulator);
7166
7167 switch (data)
7168 {
7169 case 5: // DATA_SIM_POS
7170 if (info == null)
7171 {
7172 // ScriptSleep(1000);
7173 return UUID.Zero.ToString();
7174 }
7175 reply = new LSL_Vector(
7176 info.RegionLocX * Constants.RegionSize,
7177 info.RegionLocY * Constants.RegionSize,
7178 0).ToString();
7179 break;
7180 case 6: // DATA_SIM_STATUS
7181 if (info != null)
7182 reply = "up"; // Duh!
7183 else
7184 reply = "unknown";
7185 break;
7186 case 7: // DATA_SIM_RATING
7187 if (info == null)
7188 {
7189 // ScriptSleep(1000);
7190 return UUID.Zero.ToString();
7191 }
7192 int access = info.RegionSettings.Maturity;
7193 if (access == 0)
7194 reply = "PG";
7195 else if (access == 1)
7196 reply = "MATURE";
7197 else
7198 reply = "UNKNOWN";
7199 break;
7200 case 128: // SIM_RELEASE
7201 reply = m_ScriptEngine.World.GetSimulatorVersion();
7202 break;
7203 default:
7204 // ScriptSleep(1000);
7205 return UUID.Zero.ToString(); // Raise no event
7206 }
7207 UUID rq = UUID.Random();
7208
7209 UUID tid = AsyncCommands.
7210 DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString());
7211
7212 AsyncCommands.
7213 DataserverPlugin.DataserverReply(rq.ToString(), reply);
7214
7215 // ScriptSleep(1000);
7216 return tid.ToString();
7217 }
7218 catch(Exception e)
7219 {
7220 Console.WriteLine(e.ToString());
7221 return UUID.Zero.ToString();
7222 }
7223 }
7224
7225 public void llForceMouselook(int mouselook)
7226 {
7227 m_host.AddScriptLPS(1);
7228 m_host.SetForceMouselook(mouselook != 0);
7229 }
7230
7231 public LSL_Float llGetObjectMass(string id)
7232 {
7233 m_host.AddScriptLPS(1);
7234 UUID key = new UUID();
7235 if (UUID.TryParse(id, out key))
7236 {
7237 try
7238 {
7239 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
7240 if (obj != null)
7241 return (double)obj.GetMass();
7242 // the object is null so the key is for an avatar
7243 ScenePresence avatar = World.GetScenePresence(key);
7244 if (avatar != null)
7245 if (avatar.IsChildAgent)
7246 // ref http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
7247 // child agents have a mass of 1.0
7248 return 1;
7249 else
7250 return (double)avatar.PhysicsActor.Mass;
7251 }
7252 catch (KeyNotFoundException)
7253 {
7254 return 0; // The Object/Agent not in the region so just return zero
7255 }
7256 }
7257 return 0;
7258 }
7259
7260 /// <summary>
7261 /// illListReplaceList removes the sub-list defined by the inclusive indices
7262 /// start and end and inserts the src list in its place. The inclusive
7263 /// nature of the indices means that at least one element must be deleted
7264 /// if the indices are within the bounds of the existing list. I.e. 2,2
7265 /// will remove the element at index 2 and replace it with the source
7266 /// list. Both indices may be negative, with the usual interpretation. An
7267 /// interesting case is where end is lower than start. As these indices
7268 /// bound the list to be removed, then 0->end, and start->lim are removed
7269 /// and the source list is added as a suffix.
7270 /// </summary>
7271
7272 public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end)
7273 {
7274 LSL_List pref = null;
7275
7276 m_host.AddScriptLPS(1);
7277
7278 // Note that although we have normalized, both
7279 // indices could still be negative.
7280 if (start < 0)
7281 {
7282 start = start+dest.Length;
7283 }
7284
7285 if (end < 0)
7286 {
7287 end = end+dest.Length;
7288 }
7289 // The comventional case, remove a sequence starting with
7290 // start and ending with end. And then insert the source
7291 // list.
7292 if (start <= end)
7293 {
7294 // If greater than zero, then there is going to be a
7295 // surviving prefix. Otherwise the inclusive nature
7296 // of the indices mean that we're going to add the
7297 // source list as a prefix.
7298 if (start > 0)
7299 {
7300 pref = dest.GetSublist(0,start-1);
7301 // Only add a suffix if there is something
7302 // beyond the end index (it's inclusive too).
7303 if (end + 1 < dest.Length)
7304 {
7305 return pref + src + dest.GetSublist(end + 1, -1);
7306 }
7307 else
7308 {
7309 return pref + src;
7310 }
7311 }
7312 // If start is less than or equal to zero, then
7313 // the new list is simply a prefix. We still need to
7314 // figure out any necessary surgery to the destination
7315 // based upon end. Note that if end exceeds the upper
7316 // bound in this case, the entire destination list
7317 // is removed.
7318 else
7319 {
7320 if (end + 1 < dest.Length)
7321 {
7322 return src + dest.GetSublist(end + 1, -1);
7323 }
7324 else
7325 {
7326 return src;
7327 }
7328 }
7329 }
7330 // Finally, if start > end, we strip away a prefix and
7331 // a suffix, to leave the list that sits <between> ens
7332 // and start, and then tag on the src list. AT least
7333 // that's my interpretation. We can get sublist to do
7334 // this for us. Note that one, or both of the indices
7335 // might have been negative.
7336 else
7337 {
7338 return dest.GetSublist(end + 1, start - 1) + src;
7339 }
7340 }
7341
7342 public void llLoadURL(string avatar_id, string message, string url)
7343 {
7344 m_host.AddScriptLPS(1);
7345 UUID avatarId = new UUID(avatar_id);
7346 m_ScriptEngine.World.SendUrlToUser(avatarId, m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message,
7347 url);
7348 // ScriptSleep(10000);
7349 }
7350
7351 public void llParcelMediaCommandList(LSL_List commandList)
7352 {
7353 //TO DO: Implement the missing commands
7354 //PARCEL_MEDIA_COMMAND_STOP Stop the media stream and go back to the first frame.
7355 //PARCEL_MEDIA_COMMAND_PAUSE Pause the media stream (stop playing but stay on current frame).
7356 //PARCEL_MEDIA_COMMAND_PLAY Start the media stream playing from the current frame and stop when the end is reached.
7357 //PARCEL_MEDIA_COMMAND_LOOP Start the media stream playing from the current frame. When the end is reached, loop to the beginning and continue.
7358 //PARCEL_MEDIA_COMMAND_TEXTURE key uuid Use this to get or set the parcel's media texture.
7359 //PARCEL_MEDIA_COMMAND_URL string url Used to get or set the parcel's media url.
7360 //PARCEL_MEDIA_COMMAND_TIME float time Move a media stream to a specific time.
7361 //PARCEL_MEDIA_COMMAND_AGENT key uuid Applies the media command to the specified agent only.
7362 //PARCEL_MEDIA_COMMAND_UNLOAD Completely unloads the movie and restores the original texture.
7363 //PARCEL_MEDIA_COMMAND_AUTO_ALIGN integer boolean Sets the parcel option 'Auto scale content'.
7364 //PARCEL_MEDIA_COMMAND_TYPE string mime_type Use this to get or set the parcel media MIME type (e.g. "text/html"). (1.19.1 RC0 or later)
7365 //PARCEL_MEDIA_COMMAND_SIZE integer x, integer y Use this to get or set the parcel media pixel resolution. (1.19.1 RC0 or later)
7366 //PARCEL_MEDIA_COMMAND_DESC string desc Use this to get or set the parcel media description. (1.19.1 RC0 or later)
7367 //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
7368 m_host.AddScriptLPS(1);
7369 for (int i = 0; i < commandList.Data.Length; i++)
7370 {
7371 switch ((ParcelMediaCommandEnum)commandList.Data[i])
7372 {
7373 case ParcelMediaCommandEnum.Play:
7374 List<ScenePresence> scenePresencePlayList = World.GetScenePresences();
7375 foreach (ScenePresence agent in scenePresencePlayList)
7376 {
7377 if (!agent.IsChildAgent)
7378 {
7379 agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Play, 0);
7380 }
7381 }
7382 break;
7383 case ParcelMediaCommandEnum.Stop:
7384 List<ScenePresence> scenePresenceStopList = World.GetScenePresences();
7385 foreach (ScenePresence agent in scenePresenceStopList)
7386 {
7387 if (!agent.IsChildAgent)
7388 {
7389 agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Stop, 0);
7390 }
7391 }
7392 break;
7393 case ParcelMediaCommandEnum.Pause:
7394 List<ScenePresence> scenePresencePauseList = World.GetScenePresences();
7395 foreach (ScenePresence agent in scenePresencePauseList)
7396 {
7397 if (!agent.IsChildAgent)
7398 {
7399 agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Pause, 0);
7400 }
7401 }
7402 break;
7403
7404 case ParcelMediaCommandEnum.Url:
7405 if ((i + 1) < commandList.Length)
7406 {
7407 if (commandList.Data[i + 1] is string)
7408 {
7409 UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
7410
7411 if (landowner == UUID.Zero)
7412 {
7413 return;
7414 }
7415
7416 if (landowner != m_host.ObjectOwner)
7417 {
7418 return;
7419 }
7420
7421 World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, (string)commandList.GetLSLStringItem(i + 1));
7422
7423 List<ScenePresence> scenePresenceList = World.GetScenePresences();
7424 LandData landData = World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
7425 //Send an update of the mediaURL to all the clients that are in the parcel
7426 foreach (ScenePresence agent in scenePresenceList)
7427 {
7428 if (!agent.IsChildAgent)
7429 {
7430 //Send parcel media update to the client
7431 agent.ControllingClient.SendParcelMediaUpdate(landData.MediaURL, landData.MediaID, landData.MediaAutoScale, "", landData.Description, 0, 0, 1);
7432 }
7433 }
7434
7435 }
7436 i++;
7437 }
7438 break;
7439 default:
7440 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
7441 NotImplemented("llParcelMediaCommandList parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType(), commandList.Data[i].ToString()).ToString());
7442 break;
7443 }//end switch
7444
7445 }
7446 // ScriptSleep(2000);
7447 }
7448
7449 public LSL_List llParcelMediaQuery(LSL_List aList)
7450 {
7451 m_host.AddScriptLPS(1);
7452 LSL_List list = new LSL_List();
7453 //TO DO: make the implementation for the missing commands
7454 //PARCEL_MEDIA_COMMAND_TEXTURE key uuid Use this to get or set the parcel's media texture.
7455 //PARCEL_MEDIA_COMMAND_URL string url Used to get or set the parcel's media url.
7456 //PARCEL_MEDIA_COMMAND_TYPE string mime_type Use this to get or set the parcel media MIME type (e.g. "text/html"). (1.19.1 RC0 or later)
7457 //PARCEL_MEDIA_COMMAND_SIZE integer x, integer y Use this to get or set the parcel media pixel resolution. (1.19.1 RC0 or later)
7458 //PARCEL_MEDIA_COMMAND_DESC string desc Use this to get or set the parcel media description. (1.19.1 RC0 or later)
7459 //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
7460 for (int i = 0; i < aList.Data.Length; i++)
7461 {
7462
7463 if (aList.Data[i] != null)
7464 {
7465 switch ((ParcelMediaCommandEnum) aList.Data[i])
7466 {
7467 case ParcelMediaCommandEnum.Url:
7468 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
7469 break;
7470 case ParcelMediaCommandEnum.Desc:
7471 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description));
7472 break;
7473 case ParcelMediaCommandEnum.Texture:
7474 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString()));
7475 break;
7476 default:
7477 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
7478 NotImplemented("llParcelMediaQuery parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString());
7479 break;
7480 }
7481
7482 }
7483 }
7484 // ScriptSleep(2000);
7485 return list;
7486 }
7487
7488 public LSL_Integer llModPow(int a, int b, int c)
7489 {
7490 m_host.AddScriptLPS(1);
7491 Int64 tmp = 0;
7492 Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp);
7493 // ScriptSleep(1000);
7494 return Convert.ToInt32(tmp);
7495 }
7496
7497 public LSL_Integer llGetInventoryType(string name)
7498 {
7499 m_host.AddScriptLPS(1);
7500 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
7501 {
7502 if (inv.Value.Name == name)
7503 {
7504 return inv.Value.InvType;
7505 }
7506 }
7507 return -1;
7508 }
7509
7510 public void llSetPayPrice(int price, LSL_List quick_pay_buttons)
7511 {
7512 m_host.AddScriptLPS(1);
7513
7514 if (quick_pay_buttons.Data.Length < 4)
7515 {
7516 LSLError("List must have at least 4 elements");
7517 return;
7518 }
7519 m_host.ParentGroup.RootPart.PayPrice[0]=price;
7520
7521 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0];
7522 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1];
7523 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2];
7524 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3];
7525 m_host.ParentGroup.HasGroupChanged = true;
7526 }
7527
7528 public LSL_Vector llGetCameraPos()
7529 {
7530 m_host.AddScriptLPS(1);
7531 UUID invItemID=InventorySelf();
7532 if (invItemID == UUID.Zero)
7533 return new LSL_Vector();
7534 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
7535 return new LSL_Vector();
7536 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
7537 {
7538 ShoutError("No permissions to track the camera");
7539 return new LSL_Vector();
7540 }
7541 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
7542 if (presence != null)
7543 {
7544 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
7545 return pos;
7546 }
7547 return new LSL_Vector();
7548 }
7549
7550 public LSL_Rotation llGetCameraRot()
7551 {
7552 m_host.AddScriptLPS(1);
7553 NotImplemented("llGetCameraRot");
7554 return new LSL_Rotation();
7555 }
7556
7557 public void llSetPrimURL()
7558 {
7559 m_host.AddScriptLPS(1);
7560 NotImplemented("llSetPrimURL");
7561 // ScriptSleep(2000);
7562 }
7563
7564 public void llRefreshPrimURL()
7565 {
7566 m_host.AddScriptLPS(1);
7567 NotImplemented("llRefreshPrimURL");
7568 // ScriptSleep(20000);
7569 }
7570
7571 public LSL_String llEscapeURL(string url)
7572 {
7573 m_host.AddScriptLPS(1);
7574 try
7575 {
7576 return Uri.EscapeUriString(url);
7577 }
7578 catch (Exception ex)
7579 {
7580 return "llEscapeURL: " + ex.ToString();
7581 }
7582 }
7583
7584 public LSL_String llUnescapeURL(string url)
7585 {
7586 m_host.AddScriptLPS(1);
7587 try
7588 {
7589 return Uri.UnescapeDataString(url);
7590 }
7591 catch (Exception ex)
7592 {
7593 return "llUnescapeURL: " + ex.ToString();
7594 }
7595 }
7596
7597 public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector look_at)
7598 {
7599 m_host.AddScriptLPS(1);
7600 NotImplemented("llMapDestination");
7601 // ScriptSleep(1000);
7602 }
7603
7604 public void llAddToLandBanList(string avatar, double hours)
7605 {
7606 m_host.AddScriptLPS(1);
7607 UUID key;
7608 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7609 if (land.OwnerID == m_host.OwnerID)
7610 {
7611 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
7612 if (UUID.TryParse(avatar, out key))
7613 {
7614 entry.AgentID = key;
7615 entry.Flags = ParcelManager.AccessList.Ban;
7616 entry.Time = DateTime.Now.AddHours(hours);
7617 land.ParcelAccessList.Add(entry);
7618 }
7619 }
7620 // ScriptSleep(100);
7621 }
7622
7623 public void llRemoveFromLandPassList(string avatar)
7624 {
7625 m_host.AddScriptLPS(1);
7626 UUID key;
7627 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7628 if (land.OwnerID == m_host.OwnerID)
7629 {
7630 if (UUID.TryParse(avatar, out key))
7631 {
7632 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
7633 {
7634 if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Access)
7635 {
7636 land.ParcelAccessList.Remove(entry);
7637 break;
7638 }
7639 }
7640 }
7641 }
7642 // ScriptSleep(100);
7643 }
7644
7645 public void llRemoveFromLandBanList(string avatar)
7646 {
7647 m_host.AddScriptLPS(1);
7648 UUID key;
7649 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7650 if (land.OwnerID == m_host.OwnerID)
7651 {
7652 if (UUID.TryParse(avatar, out key))
7653 {
7654 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
7655 {
7656 if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Ban)
7657 {
7658 land.ParcelAccessList.Remove(entry);
7659 break;
7660 }
7661 }
7662 }
7663 }
7664 // ScriptSleep(100);
7665 }
7666
7667 public void llSetCameraParams(LSL_List rules)
7668 {
7669 m_host.AddScriptLPS(1);
7670
7671 // our key in the object we are in
7672 UUID invItemID=InventorySelf();
7673 if (invItemID == UUID.Zero) return;
7674
7675 // the object we are in
7676 UUID objectID = m_host.ParentUUID;
7677 if (objectID == UUID.Zero) return;
7678
7679 // we need the permission first, to know which avatar we want to set the camera for
7680 UUID agentID = m_host.TaskInventory[invItemID].PermsGranter;
7681 if (agentID == UUID.Zero) return;
7682 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
7683
7684 ScenePresence presence = World.GetScenePresence(agentID);
7685
7686 // we are not interested in child-agents
7687 if (presence.IsChildAgent) return;
7688
7689 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
7690 object[] data = rules.Data;
7691 for (int i = 0; i < data.Length; ++i) {
7692 int type = Convert.ToInt32(data[i++].ToString());
7693 if (i >= data.Length) break; // odd number of entries => ignore the last
7694
7695 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
7696 switch (type) {
7697 case ScriptBaseClass.CAMERA_FOCUS:
7698 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
7699 case ScriptBaseClass.CAMERA_POSITION:
7700 LSL_Vector v = (LSL_Vector)data[i];
7701 parameters.Add(type + 1, (float)v.x);
7702 parameters.Add(type + 2, (float)v.y);
7703 parameters.Add(type + 3, (float)v.z);
7704 break;
7705 default:
7706 // TODO: clean that up as soon as the implicit casts are in
7707 if (data[i] is LSL_Float)
7708 parameters.Add(type, (float)((LSL_Float)data[i]).value);
7709 else if (data[i] is LSL_Integer)
7710 parameters.Add(type, (float)((LSL_Integer)data[i]).value);
7711 else parameters.Add(type, Convert.ToSingle(data[i]));
7712 break;
7713 }
7714 }
7715 if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters);
7716 }
7717
7718 public void llClearCameraParams()
7719 {
7720 m_host.AddScriptLPS(1);
7721
7722 // our key in the object we are in
7723 UUID invItemID=InventorySelf();
7724 if (invItemID == UUID.Zero) return;
7725
7726 // the object we are in
7727 UUID objectID = m_host.ParentUUID;
7728 if (objectID == UUID.Zero) return;
7729
7730 // we need the permission first, to know which avatar we want to clear the camera for
7731 UUID agentID = m_host.TaskInventory[invItemID].PermsGranter;
7732 if (agentID == UUID.Zero) return;
7733 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
7734
7735 ScenePresence presence = World.GetScenePresence(agentID);
7736
7737 // we are not interested in child-agents
7738 if (presence.IsChildAgent) return;
7739
7740 presence.ControllingClient.SendClearFollowCamProperties(objectID);
7741 }
7742
7743 public LSL_Float llListStatistics(int operation, LSL_List src)
7744 {
7745 m_host.AddScriptLPS(1);
7746 LSL_List nums = LSL_List.ToDoubleList(src);
7747 switch (operation)
7748 {
7749 case ScriptBaseClass.LIST_STAT_RANGE:
7750 return nums.Range();
7751 case ScriptBaseClass.LIST_STAT_MIN:
7752 return nums.Min();
7753 case ScriptBaseClass.LIST_STAT_MAX:
7754 return nums.Max();
7755 case ScriptBaseClass.LIST_STAT_MEAN:
7756 return nums.Mean();
7757 case ScriptBaseClass.LIST_STAT_MEDIAN:
7758 return nums.Median();
7759 case ScriptBaseClass.LIST_STAT_NUM_COUNT:
7760 return nums.NumericLength();
7761 case ScriptBaseClass.LIST_STAT_STD_DEV:
7762 return nums.StdDev();
7763 case ScriptBaseClass.LIST_STAT_SUM:
7764 return nums.Sum();
7765 case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
7766 return nums.SumSqrs();
7767 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
7768 return nums.GeometricMean();
7769 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
7770 return nums.HarmonicMean();
7771 default:
7772 return 0.0;
7773 }
7774 }
7775
7776 public LSL_Integer llGetUnixTime()
7777 {
7778 m_host.AddScriptLPS(1);
7779 return Util.UnixTimeSinceEpoch();
7780 }
7781
7782 public LSL_Integer llGetParcelFlags(LSL_Vector pos)
7783 {
7784 m_host.AddScriptLPS(1);
7785 return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).landData.Flags;
7786 }
7787
7788 public LSL_Integer llGetRegionFlags()
7789 {
7790 m_host.AddScriptLPS(1);
7791 IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
7792 if (estate == null)
7793 return 67108864;
7794 return (int)estate.GetRegionFlags();
7795 }
7796
7797 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
7798 {
7799 m_host.AddScriptLPS(1);
7800 string ret = String.Empty;
7801 string src1 = llBase64ToString(str1);
7802 string src2 = llBase64ToString(str2);
7803 int c = 0;
7804 for (int i = 0; i < src1.Length; i++)
7805 {
7806 ret += src1[i] ^ src2[c];
7807
7808 c++;
7809 if (c >= src2.Length)
7810 c = 0;
7811 }
7812 return llStringToBase64(ret);
7813 }
7814
7815 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
7816 {
7817 // Partial implementation: support for parameter flags needed
7818 // see http://wiki.secondlife.com/wiki/LlHTTPRequest
7819 // parameter flags support are implemented in ScriptsHttpRequests.cs
7820 // in StartHttpRequest
7821
7822 m_host.AddScriptLPS(1);
7823 IHttpRequests httpScriptMod =
7824 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
7825 List<string> param = new List<string>();
7826 foreach (object o in parameters.Data)
7827 {
7828 param.Add(o.ToString());
7829 }
7830
7831 Vector3 position = m_host.AbsolutePosition;
7832 Vector3 velocity = m_host.Velocity;
7833 Quaternion rotation = m_host.RotationOffset;
7834 ScenePresence scenePresence = World.GetScenePresence(m_host.ObjectOwner);
7835 RegionInfo regionInfo = World.RegionInfo;
7836
7837 Dictionary<string, string> httpHeaders = new Dictionary<string, string>();
7838
7839 httpHeaders["X-SecondLife-Shard"] = "OpenSim";
7840 httpHeaders["X-SecondLife-Object-Name"] = m_host.Name;
7841 httpHeaders["X-SecondLife-Object-Key"] = m_itemID.ToString();
7842 httpHeaders["X-SecondLife-Region"] = string.Format("{0} ({1}, {2})", regionInfo.RegionName, regionInfo.RegionLocX, regionInfo.RegionLocY);
7843 httpHeaders["X-SecondLife-Local-Position"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", position.X, position.Y, position.Z);
7844 httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z);
7845 httpHeaders["X-SecondLife-Local-Rotation"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})", rotation.X, rotation.Y, rotation.Z, rotation.W);
7846 httpHeaders["X-SecondLife-Owner-Name"] = scenePresence == null ? string.Empty : scenePresence.ControllingClient.Name;
7847 httpHeaders["X-SecondLife-Owner-Key"] = m_host.ObjectOwner.ToString();
7848
7849 UUID reqID = httpScriptMod.
7850 StartHttpRequest(m_localID, m_itemID, url, param, httpHeaders, body);
7851
7852 if (reqID != UUID.Zero)
7853 return reqID.ToString();
7854 else
7855 return null;
7856 }
7857
7858 public void llResetLandBanList()
7859 {
7860 m_host.AddScriptLPS(1);
7861 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7862 if (land.OwnerID == m_host.OwnerID)
7863 {
7864 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
7865 {
7866 if (entry.Flags == ParcelManager.AccessList.Ban)
7867 {
7868 land.ParcelAccessList.Remove(entry);
7869 }
7870 }
7871 }
7872 // ScriptSleep(100);
7873 }
7874
7875 public void llResetLandPassList()
7876 {
7877 m_host.AddScriptLPS(1);
7878 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7879 if (land.OwnerID == m_host.OwnerID)
7880 {
7881 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
7882 {
7883 if (entry.Flags == ParcelManager.AccessList.Access)
7884 {
7885 land.ParcelAccessList.Remove(entry);
7886 }
7887 }
7888 }
7889 // ScriptSleep(100);
7890 }
7891
7892 public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide)
7893 {
7894 m_host.AddScriptLPS(1);
7895
7896 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
7897
7898 if (land == null)
7899 {
7900 return 0;
7901 }
7902
7903 else
7904 {
7905 if (sim_wide == 1)
7906 {
7907 if (category == 0)
7908 {
7909 return land.SimwidePrims;
7910 }
7911
7912 else
7913 {
7914 //public int simwideArea = 0;
7915 return 0;
7916 }
7917 }
7918
7919 else
7920 {
7921 if (category == 0)//Total Prims
7922 {
7923 return 0;//land.
7924 }
7925
7926 else if (category == 1)//Owner Prims
7927 {
7928 return land.OwnerPrims;
7929 }
7930
7931 else if (category == 2)//Group Prims
7932 {
7933 return land.GroupPrims;
7934 }
7935
7936 else if (category == 3)//Other Prims
7937 {
7938 return land.OtherPrims;
7939 }
7940
7941 else if (category == 4)//Selected
7942 {
7943 return land.SelectedPrims;
7944 }
7945
7946 else if (category == 5)//Temp
7947 {
7948 return 0;//land.
7949 }
7950 }
7951 }
7952 return 0;
7953 }
7954
7955 public LSL_List llGetParcelPrimOwners(LSL_Vector pos)
7956 {
7957 m_host.AddScriptLPS(1);
7958 LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
7959 LSL_List ret = new LSL_List();
7960 if (land != null)
7961 {
7962 foreach (KeyValuePair<UUID, int> d in land.getLandObjectOwners())
7963 {
7964 ret.Add(d.Key.ToString());
7965 ret.Add(d.Value);
7966 }
7967 }
7968 // ScriptSleep(2000);
7969 return ret;
7970 }
7971
7972 public LSL_Integer llGetObjectPrimCount(string object_id)
7973 {
7974 m_host.AddScriptLPS(1);
7975 SceneObjectPart part = World.GetSceneObjectPart(new UUID(object_id));
7976 if (part == null)
7977 {
7978 return 0;
7979 }
7980 else
7981 {
7982 return part.ParentGroup.Children.Count;
7983 }
7984 }
7985
7986 public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide)
7987 {
7988 m_host.AddScriptLPS(1);
7989 // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation
7990 // Which probably will be irrelevent in OpenSim....
7991 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
7992
7993 float bonusfactor = (float)World.RegionInfo.RegionSettings.ObjectBonus;
7994
7995 if (land == null)
7996 {
7997 return 0;
7998 }
7999
8000 if (sim_wide == 1)
8001 {
8002 decimal v = land.SimwideArea * (decimal)(0.22) * (decimal)bonusfactor;
8003
8004 return (int)v;
8005 }
8006
8007 else
8008 {
8009 decimal v = land.Area * (decimal)(0.22) * (decimal)bonusfactor;
8010
8011 return (int)v;
8012 }
8013
8014 }
8015
8016 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param)
8017 {
8018 m_host.AddScriptLPS(1);
8019 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
8020 if (land == null)
8021 {
8022 return new LSL_List(0);
8023 }
8024 LSL_List ret = new LSL_List();
8025 foreach (object o in param.Data)
8026 {
8027 switch (o.ToString())
8028 {
8029 case "0":
8030 ret = ret + new LSL_List(land.Name);
8031 break;
8032 case "1":
8033 ret = ret + new LSL_List(land.Description);
8034 break;
8035 case "2":
8036 ret = ret + new LSL_List(land.OwnerID.ToString());
8037 break;
8038 case "3":
8039 ret = ret + new LSL_List(land.GroupID.ToString());
8040 break;
8041 case "4":
8042 ret = ret + new LSL_List(land.Area);
8043 break;
8044 default:
8045 ret = ret + new LSL_List(0);
8046 break;
8047 }
8048 }
8049 return ret;
8050 }
8051
8052 public void llSetLinkTexture(int linknumber, string texture, int face)
8053 {
8054 m_host.AddScriptLPS(1);
8055
8056 if (m_host.ParentGroup == null)
8057 return;
8058
8059 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber);
8060
8061 if (part == null)
8062 return;
8063
8064 SetTexture(part, texture, face);
8065 // ScriptSleep(200);
8066 }
8067
8068 public LSL_String llStringTrim(string src, int type)
8069 {
8070 m_host.AddScriptLPS(1);
8071 if (type == (int)ScriptBaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); }
8072 if (type == (int)ScriptBaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); }
8073 if (type == (int)ScriptBaseClass.STRING_TRIM) { return src.Trim(); }
8074 return src;
8075 }
8076
8077 public LSL_List llGetObjectDetails(string id, LSL_List args)
8078 {
8079 m_host.AddScriptLPS(1);
8080 LSL_List ret = new LSL_List();
8081 UUID key = new UUID();
8082 if (UUID.TryParse(id, out key))
8083 {
8084 ScenePresence av = World.GetScenePresence(key);
8085
8086 if (av != null)
8087 {
8088 foreach (object o in args.Data)
8089 {
8090 switch (o.ToString())
8091 {
8092 case "1":
8093 ret.Add(av.Firstname + " " + av.Lastname);
8094 break;
8095 case "2":
8096 ret.Add("");
8097 break;
8098 case "3":
8099 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z));
8100 break;
8101 case "4":
8102 ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W));
8103 break;
8104 case "5":
8105 ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z));
8106 break;
8107 case "6":
8108 ret.Add(id);
8109 break;
8110 case "7":
8111 ret.Add(UUID.Zero.ToString());
8112 break;
8113 case "8":
8114 ret.Add(UUID.Zero.ToString());
8115 break;
8116 }
8117 }
8118 return ret;
8119 }
8120 SceneObjectPart obj = World.GetSceneObjectPart(key);
8121 if (obj != null)
8122 {
8123 foreach (object o in args.Data)
8124 {
8125 switch (o.ToString())
8126 {
8127 case "1":
8128 ret.Add(obj.Name);
8129 break;
8130 case "2":
8131 ret.Add(obj.Description);
8132 break;
8133 case "3":
8134 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z));
8135 break;
8136 case "4":
8137 ret.Add(new LSL_Rotation(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W));
8138 break;
8139 case "5":
8140 ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z));
8141 break;
8142 case "6":
8143 ret.Add(obj.OwnerID.ToString());
8144 break;
8145 case "7":
8146 ret.Add(obj.GroupID.ToString());
8147 break;
8148 case "8":
8149 ret.Add(obj.CreatorID.ToString());
8150 break;
8151 }
8152 }
8153 return ret;
8154 }
8155 }
8156 return new LSL_List();
8157 }
8158
8159
8160 internal UUID ScriptByName(string name) 247 internal UUID ScriptByName(string name)
8161 { 248 {
8162 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 249 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
@@ -8171,280 +258,5 @@ namespace OpenSim.Region.ScriptEngine.Common
8171 { 258 {
8172 llShout(ScriptBaseClass.DEBUG_CHANNEL, msg); 259 llShout(ScriptBaseClass.DEBUG_CHANNEL, msg);
8173 } 260 }
8174
8175
8176
8177 internal void NotImplemented(string command)
8178 {
8179 if (throwErrorOnNotImplemented)
8180 throw new NotImplementedException("Command not implemented: " + command);
8181 }
8182
8183 internal void Deprecated(string command)
8184 {
8185 throw new Exception("Command deprecated: " + command);
8186 }
8187
8188 internal void LSLError(string msg)
8189 {
8190 throw new Exception("LSL Runtime Error: " + msg);
8191 }
8192
8193 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset);
8194 private void WithNotecard(UUID assetID, AssetRequestCallback cb)
8195 {
8196 World.AssetCache.GetAsset(assetID, delegate(UUID i, AssetBase a) { cb(i, a); }, false);
8197 }
8198
8199 public LSL_String llGetNumberOfNotecardLines(string name)
8200 {
8201 m_host.AddScriptLPS(1);
8202
8203 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
8204 {
8205 if (item.Type == 7 && item.Name == name)
8206 {
8207 UUID tid = AsyncCommands.
8208 DataserverPlugin.RegisterRequest(m_localID,
8209 m_itemID, item.AssetID.ToString());
8210 if (NotecardCache.IsCached(item.AssetID))
8211 {
8212 AsyncCommands.
8213 DataserverPlugin.DataserverReply(item.AssetID.ToString(),
8214 NotecardCache.GetLines(item.AssetID).ToString());
8215 // ScriptSleep(100);
8216 return tid.ToString();
8217 }
8218 WithNotecard(item.AssetID, delegate (UUID id, AssetBase a)
8219 {
8220 System.Text.ASCIIEncoding enc =
8221 new System.Text.ASCIIEncoding();
8222 string data = enc.GetString(a.Data);
8223 //Console.WriteLine(data);
8224 NotecardCache.Cache(id, data);
8225 AsyncCommands.
8226 DataserverPlugin.DataserverReply(id.ToString(),
8227 NotecardCache.GetLines(id).ToString());
8228 });
8229 // ScriptSleep(100);
8230 return tid.ToString();
8231 }
8232 }
8233 // if we got to here, we didn't find the notecard the script was asking for
8234 // => complain loudly, as specified by the LSL docs
8235 ShoutError("Notecard '" + name + "' could not be found.");
8236
8237 // ScriptSleep(100);
8238 return UUID.Zero.ToString();
8239 }
8240
8241 public LSL_String llGetNotecardLine(string name, int line)
8242 {
8243 m_host.AddScriptLPS(1);
8244
8245 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
8246 {
8247 if (item.Type == 7 && item.Name == name)
8248 {
8249 UUID tid = AsyncCommands.
8250 DataserverPlugin.RegisterRequest(m_localID,
8251 m_itemID, item.AssetID.ToString());
8252
8253 if (NotecardCache.IsCached(item.AssetID))
8254 {
8255 AsyncCommands.
8256 DataserverPlugin.DataserverReply(item.AssetID.ToString(),
8257 NotecardCache.GetLine(item.AssetID, line));
8258 // ScriptSleep(100);
8259 return tid.ToString();
8260 }
8261
8262 WithNotecard(item.AssetID, delegate (UUID id, AssetBase a)
8263 {
8264 System.Text.ASCIIEncoding enc =
8265 new System.Text.ASCIIEncoding();
8266 string data = enc.GetString(a.Data);
8267 //Console.WriteLine(data);
8268 NotecardCache.Cache(id, data);
8269 AsyncCommands.
8270 DataserverPlugin.DataserverReply(id.ToString(),
8271 NotecardCache.GetLine(id, line));
8272 });
8273
8274 // ScriptSleep(100);
8275 return tid.ToString();
8276 }
8277 }
8278
8279 // if we got to here, we didn't find the notecard the script was asking for
8280 // => complain loudly, as specified by the LSL docs
8281 ShoutError("Notecard '" + name + "' could not be found.");
8282
8283 // ScriptSleep(100);
8284 return UUID.Zero.ToString();
8285 }
8286
8287 }
8288
8289 public class NotecardCache
8290 {
8291 private class Notecard
8292 {
8293 public string[] text;
8294 public DateTime lastRef;
8295 }
8296
8297 private static Dictionary<UUID, Notecard> m_Notecards =
8298 new Dictionary<UUID, Notecard>();
8299
8300 public static void Cache(UUID assetID, string text)
8301 {
8302 CacheCheck();
8303
8304 lock (m_Notecards)
8305 {
8306 if (m_Notecards.ContainsKey(assetID))
8307 return;
8308
8309 Notecard nc = new Notecard();
8310 nc.lastRef = DateTime.Now;
8311 nc.text = ParseText(text.Replace("\r", "").Split('\n'));
8312 m_Notecards[assetID] = nc;
8313 }
8314 }
8315
8316 private static string[] ParseText(string[] input)
8317 {
8318 int idx = 0;
8319 int level = 0;
8320 List<string> output = new List<string>();
8321 string[] words;
8322
8323 while (idx < input.Length)
8324 {
8325 if (input[idx] == "{")
8326 {
8327 level++;
8328 idx++;
8329 continue;
8330 }
8331
8332 if (input[idx]== "}")
8333 {
8334 level--;
8335 idx++;
8336 continue;
8337 }
8338
8339 switch (level)
8340 {
8341 case 0:
8342 words = input[idx].Split(' '); // Linden text ver
8343 // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard)
8344 if (words.Length < 3)
8345 return new String[0];
8346
8347 int version = int.Parse(words[3]);
8348 if (version != 2)
8349 return new String[0];
8350 break;
8351 case 1:
8352 words = input[idx].Split(' ');
8353 if (words[0] == "LLEmbeddedItems")
8354 break;
8355 if (words[0] == "Text")
8356 {
8357 int len = int.Parse(words[2]);
8358 idx++;
8359
8360 int count = -1;
8361
8362 while (count < len)
8363 {
8364 // int l = input[idx].Length;
8365 string ln = input[idx];
8366
8367 int need = len-count-1;
8368 if (ln.Length > need)
8369 ln = ln.Substring(0, need);
8370
8371 output.Add(ln);
8372 count += ln.Length + 1;
8373 idx++;
8374 }
8375
8376 return output.ToArray();
8377 }
8378 break;
8379 case 2:
8380 words = input[idx].Split(' '); // count
8381 if (words[0] == "count")
8382 {
8383 int c = int.Parse(words[1]);
8384 if (c > 0)
8385 return new String[0];
8386 break;
8387 }
8388 break;
8389 }
8390 idx++;
8391 }
8392 return output.ToArray();
8393 }
8394
8395 public static bool IsCached(UUID assetID)
8396 {
8397 lock (m_Notecards)
8398 {
8399 return m_Notecards.ContainsKey(assetID);
8400 }
8401 }
8402
8403 public static int GetLines(UUID assetID)
8404 {
8405 if (!IsCached(assetID))
8406 return -1;
8407
8408 lock (m_Notecards)
8409 {
8410 m_Notecards[assetID].lastRef = DateTime.Now;
8411 return m_Notecards[assetID].text.Length;
8412 }
8413 }
8414
8415 public static string GetLine(UUID assetID, int line)
8416 {
8417 if (line < 0)
8418 return "";
8419
8420 string data;
8421
8422 if (!IsCached(assetID))
8423 return "";
8424
8425 lock (m_Notecards)
8426 {
8427 m_Notecards[assetID].lastRef = DateTime.Now;
8428
8429 if (line >= m_Notecards[assetID].text.Length)
8430 return "\n\n\n";
8431
8432 data = m_Notecards[assetID].text[line];
8433 if (data.Length > 255)
8434 data = data.Substring(0, 255);
8435
8436 return data;
8437 }
8438 }
8439
8440 public static void CacheCheck()
8441 {
8442 foreach (UUID key in new List<UUID>(m_Notecards.Keys))
8443 {
8444 Notecard nc = m_Notecards[key];
8445 if (nc.lastRef.AddSeconds(30) < DateTime.Now)
8446 m_Notecards.Remove(key);
8447 }
8448 }
8449 } 261 }
8450} 262}
diff --git a/OpenSim/Region/ScriptEngine/Common/OSSL_BuilIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/OSSL_BuilIn_Commands.cs
index 0ef909f..7b2d229 100644
--- a/OpenSim/Region/ScriptEngine/Common/OSSL_BuilIn_Commands.cs
+++ b/OpenSim/Region/ScriptEngine/Common/OSSL_BuilIn_Commands.cs
@@ -40,10 +40,13 @@ namespace OpenSim.Region.ScriptEngine.Common
40{ 40{
41 public class OSSL_BuilIn_Commands : LSL_BuiltIn_Commands, OSSL_BuilIn_Commands_Interface 41 public class OSSL_BuilIn_Commands : LSL_BuiltIn_Commands, OSSL_BuilIn_Commands_Interface
42 { 42 {
43 internal ScriptEngineBase.ScriptEngine m_ScriptEngineDirect;
44
43 public OSSL_BuilIn_Commands(ScriptEngineBase.ScriptEngine scriptEngine, SceneObjectPart host, uint localID, 45 public OSSL_BuilIn_Commands(ScriptEngineBase.ScriptEngine scriptEngine, SceneObjectPart host, uint localID,
44 UUID itemID) 46 UUID itemID)
45 : base(scriptEngine, host, localID, itemID) 47 : base(scriptEngine, host, localID, itemID)
46 { 48 {
49 m_ScriptEngineDirect = scriptEngine;
47 Prim = new OSSLPrim(this); 50 Prim = new OSSLPrim(this);
48 } 51 }
49 52
@@ -577,7 +580,7 @@ namespace OpenSim.Region.ScriptEngine.Common
577 { 580 {
578 UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, new UUID(channel)); 581 UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, new UUID(channel));
579 object[] resobj = new object[] { new LSL_Types.LSLInteger(1), new LSL_Types.LSLString(channelID.ToString()), new LSL_Types.LSLString(UUID.Zero.ToString()), new LSL_Types.LSLString(String.Empty), new LSL_Types.LSLInteger(0), new LSL_Types.LSLString(String.Empty) }; 582 object[] resobj = new object[] { new LSL_Types.LSLInteger(1), new LSL_Types.LSLString(channelID.ToString()), new LSL_Types.LSLString(UUID.Zero.ToString()), new LSL_Types.LSLString(String.Empty), new LSL_Types.LSLInteger(0), new LSL_Types.LSLString(String.Empty) };
580 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(m_localID, m_itemID, "remote_data", new DetectParams[0], resobj); 583 m_ScriptEngineDirect.m_EventQueueManager.AddToScriptQueue(m_localID, m_itemID, "remote_data", new DetectParams[0], resobj);
581 } 584 }
582 } 585 }
583 586
@@ -605,16 +608,16 @@ namespace OpenSim.Region.ScriptEngine.Common
605 608
606 int scriptEngineNameIndex = 0; 609 int scriptEngineNameIndex = 0;
607 610
608 if (!String.IsNullOrEmpty(m_ScriptEngine.ScriptEngineName)) 611 if (!String.IsNullOrEmpty(m_ScriptEngineDirect.ScriptEngineName))
609 { 612 {
610 // parse off the "ScriptEngine." 613 // parse off the "ScriptEngine."
611 scriptEngineNameIndex = m_ScriptEngine.ScriptEngineName.IndexOf(".", scriptEngineNameIndex); 614 scriptEngineNameIndex = m_ScriptEngineDirect.ScriptEngineName.IndexOf(".", scriptEngineNameIndex);
612 scriptEngineNameIndex++; // get past delimiter 615 scriptEngineNameIndex++; // get past delimiter
613 616
614 int scriptEngineNameLength = m_ScriptEngine.ScriptEngineName.Length - scriptEngineNameIndex; 617 int scriptEngineNameLength = m_ScriptEngineDirect.ScriptEngineName.Length - scriptEngineNameIndex;
615 618
616 // create char array then a string that is only the script engine name 619 // create char array then a string that is only the script engine name
617 Char[] scriptEngineNameCharArray = m_ScriptEngine.ScriptEngineName.ToCharArray(scriptEngineNameIndex, scriptEngineNameLength); 620 Char[] scriptEngineNameCharArray = m_ScriptEngineDirect.ScriptEngineName.ToCharArray(scriptEngineNameIndex, scriptEngineNameLength);
618 String scriptEngineName = new String(scriptEngineNameCharArray); 621 String scriptEngineName = new String(scriptEngineNameCharArray);
619 622
620 return scriptEngineName; 623 return scriptEngineName;
@@ -805,5 +808,10 @@ namespace OpenSim.Region.ScriptEngine.Common
805 808
806 return jsondata; 809 return jsondata;
807 } 810 }
811
812 internal void LSLError(string msg)
813 {
814 throw new Exception("LSL Runtime Error: " + msg);
815 }
808 } 816 }
809} 817}
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
index b09a30b..d423311 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
@@ -220,6 +220,11 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
220 220
221 return det[number]; 221 return det[number];
222 } 222 }
223
224 public int GetStartParameter(UUID itemID)
225 {
226 return 0;
227 }
223 #endregion 228 #endregion
224 } 229 }
225} 230}
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IEventReceiver.cs b/OpenSim/Region/ScriptEngine/Interfaces/IEventReceiver.cs
index d315800..4be6a77 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IEventReceiver.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IEventReceiver.cs
@@ -54,5 +54,8 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
54 /// Post event to an entire prim 54 /// Post event to an entire prim
55 /// </summary> 55 /// </summary>
56 bool PostObjectEvent(uint localID, EventParams parms); 56 bool PostObjectEvent(uint localID, EventParams parms);
57
58 DetectParams GetDetectParams(UUID item, int number);
59 int GetStartParameter(UUID itemID);
57 } 60 }
58} 61}
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
index e0e9e82..389af00 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
@@ -51,7 +51,6 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
51 void SetScriptState(UUID itemID, bool state); 51 void SetScriptState(UUID itemID, bool state);
52 bool GetScriptState(UUID itemID); 52 bool GetScriptState(UUID itemID);
53 void SetState(UUID itemID, string newState); 53 void SetState(UUID itemID, string newState);
54 int GetStartParameter(UUID itemID);
55 54
56 /// <summary> 55 /// <summary>
57 /// Queue an event for execution 56 /// Queue an event for execution
@@ -59,7 +58,5 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
59 IScriptWorkItem QueueEventHandler(object parms); 58 IScriptWorkItem QueueEventHandler(object parms);
60 59
61 IScriptApi GetApi(UUID itemID, string name); 60 IScriptApi GetApi(UUID itemID, string name);
62
63 DetectParams GetDetectParams(UUID item, int number);
64 } 61 }
65} 62}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index ced5452..d782c56 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -63,22 +63,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
63 /// <summary> 63 /// <summary>
64 /// Contains all LSL ll-functions. This class will be in Default AppDomain. 64 /// Contains all LSL ll-functions. This class will be in Default AppDomain.
65 /// </summary> 65 /// </summary>
66 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi 66 public class LSL_Api : LSL_Api_Base, ILSL_Api, IScriptApi
67 { 67 {
68 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 68 private IScriptEngine m_ScriptEngineDirect;
69 69
70 internal IScriptEngine m_ScriptEngine; 70 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
71 internal SceneObjectPart m_host;
72 internal uint m_localID;
73 internal UUID m_itemID;
74 internal bool throwErrorOnNotImplemented = true;
75 internal AsyncCommandManager AsyncCommands = null;
76 internal float m_ScriptDelayFactor = 1.0f;
77 internal float m_ScriptDistanceFactor = 1.0f;
78 71
79 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 72 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
80 { 73 {
81 m_ScriptEngine = ScriptEngine; 74 m_ScriptEngine = ScriptEngine;
75 m_ScriptEngineDirect = ScriptEngine;
82 m_host = host; 76 m_host = host;
83 m_localID = localID; 77 m_localID = localID;
84 m_itemID = itemID; 78 m_itemID = itemID;
@@ -105,8 +99,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
105 System.Threading.Thread.Sleep(delay); 99 System.Threading.Thread.Sleep(delay);
106 } 100 }
107 101
108
109
110 // Object never expires 102 // Object never expires
111 public override Object InitializeLifetimeService() 103 public override Object InitializeLifetimeService()
112 { 104 {
@@ -119,14 +111,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
119 return lease; 111 return lease;
120 } 112 }
121 113
122 public Scene World
123 {
124 get { return m_ScriptEngine.World; }
125 }
126
127 public void state(string newState) 114 public void state(string newState)
128 { 115 {
129 m_ScriptEngine.SetState(m_itemID, newState); 116 m_ScriptEngineDirect.SetState(m_itemID, newState);
130 throw new EventAbortException(); 117 throw new EventAbortException();
131 } 118 }
132 119
@@ -136,5125 +123,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
136 return World.GetCommander(name); 123 return World.GetCommander(name);
137 } 124 }
138 125
139 private List<SceneObjectPart> GetLinkParts(int linkType)
140 {
141 List<SceneObjectPart> ret = new List<SceneObjectPart>();
142 ret.Add(m_host);
143
144 switch (linkType)
145 {
146 case ScriptBaseClass.LINK_SET:
147 if (m_host.ParentGroup != null)
148 return new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
149 return ret;
150
151 case ScriptBaseClass.LINK_ROOT:
152 if (m_host.ParentGroup != null)
153 {
154 ret = new List<SceneObjectPart>();
155 ret.Add(m_host.ParentGroup.RootPart);
156 return ret;
157 }
158 return ret;
159
160 case ScriptBaseClass.LINK_ALL_OTHERS:
161 if (m_host.ParentGroup == null)
162 return new List<SceneObjectPart>();
163 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
164 if (ret.Contains(m_host))
165 ret.Remove(m_host);
166 return ret;
167
168 case ScriptBaseClass.LINK_ALL_CHILDREN:
169 if (m_host.ParentGroup == null)
170 return new List<SceneObjectPart>();
171 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
172 if (ret.Contains(m_host.ParentGroup.RootPart))
173 ret.Remove(m_host.ParentGroup.RootPart);
174 return ret;
175
176 case ScriptBaseClass.LINK_THIS:
177 return ret;
178
179 default:
180 if (linkType < 0 || m_host.ParentGroup == null)
181 return new List<SceneObjectPart>();
182 SceneObjectPart target = m_host.ParentGroup.GetLinkNumPart(linkType);
183 if (target == null)
184 return new List<SceneObjectPart>();
185 ret = new List<SceneObjectPart>();
186 ret.Add(target);
187 return ret;
188
189 }
190 }
191
192 private UUID InventorySelf()
193 {
194 UUID invItemID = new UUID();
195
196 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
197 {
198 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
199 {
200 invItemID = inv.Key;
201 break;
202 }
203 }
204
205 return invItemID;
206 }
207
208 private UUID InventoryKey(string name, int type)
209 {
210 m_host.AddScriptLPS(1);
211 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
212 {
213 if (inv.Value.Name == name)
214 {
215 if (inv.Value.Type != type)
216 return UUID.Zero;
217
218 return inv.Value.AssetID.ToString();
219 }
220 }
221 return UUID.Zero;
222 }
223
224 private UUID InventoryKey(string name)
225 {
226 m_host.AddScriptLPS(1);
227 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
228 {
229 if (inv.Value.Name == name)
230 {
231 return inv.Value.AssetID.ToString();
232 }
233 }
234 return UUID.Zero;
235 }
236
237
238 /// <summary>
239 /// accepts a valid UUID, -or- a name of an inventory item.
240 /// Returns a valid UUID or UUID.Zero if key invalid and item not found
241 /// in prim inventory.
242 /// </summary>
243 /// <param name="k"></param>
244 /// <returns></returns>
245 private UUID KeyOrName(string k)
246 {
247 UUID key = UUID.Zero;
248
249 // if we can parse the string as a key, use it.
250 if (UUID.TryParse(k, out key))
251 {
252 return key;
253 }
254 // else try to locate the name in inventory of object. found returns key,
255 // not found returns UUID.Zero which will translate to the default particle texture
256 else
257 {
258 return InventoryKey(k);
259 }
260 }
261
262 //These are the implementations of the various ll-functions used by the LSL scripts.
263 public LSL_Float llSin(double f)
264 {
265 m_host.AddScriptLPS(1);
266 return (double)Math.Sin(f);
267 }
268
269 public LSL_Float llCos(double f)
270 {
271 m_host.AddScriptLPS(1);
272 return (double)Math.Cos(f);
273 }
274
275 public LSL_Float llTan(double f)
276 {
277 m_host.AddScriptLPS(1);
278 return (double)Math.Tan(f);
279 }
280
281 public LSL_Float llAtan2(double x, double y)
282 {
283 m_host.AddScriptLPS(1);
284 return (double)Math.Atan2(y, x);
285 }
286
287 public LSL_Float llSqrt(double f)
288 {
289 m_host.AddScriptLPS(1);
290 return (double)Math.Sqrt(f);
291 }
292
293 public LSL_Float llPow(double fbase, double fexponent)
294 {
295 m_host.AddScriptLPS(1);
296 return (double)Math.Pow(fbase, fexponent);
297 }
298
299 public LSL_Integer llAbs(int i)
300 {
301 m_host.AddScriptLPS(1);
302 return (int)Math.Abs(i);
303 }
304
305 public LSL_Float llFabs(double f)
306 {
307 m_host.AddScriptLPS(1);
308 return (double)Math.Abs(f);
309 }
310
311 public LSL_Float llFrand(double mag)
312 {
313 m_host.AddScriptLPS(1);
314 lock (Util.RandomClass)
315 {
316 return Util.RandomClass.NextDouble() * mag;
317 }
318 }
319
320 public LSL_Integer llFloor(double f)
321 {
322 m_host.AddScriptLPS(1);
323 return (int)Math.Floor(f);
324 }
325
326 public LSL_Integer llCeil(double f)
327 {
328 m_host.AddScriptLPS(1);
329 return (int)Math.Ceiling(f);
330 }
331
332 // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
333 public LSL_Integer llRound(double f)
334 {
335 m_host.AddScriptLPS(1);
336 return (int)Math.Round(f, MidpointRounding.AwayFromZero);
337 }
338
339 //This next group are vector operations involving squaring and square root. ckrinke
340 public LSL_Float llVecMag(LSL_Vector v)
341 {
342 m_host.AddScriptLPS(1);
343 return LSL_Vector.Mag(v);
344 }
345
346 public LSL_Vector llVecNorm(LSL_Vector v)
347 {
348 m_host.AddScriptLPS(1);
349 double mag = LSL_Vector.Mag(v);
350 LSL_Vector nor = new LSL_Vector();
351 nor.x = v.x / mag;
352 nor.y = v.y / mag;
353 nor.z = v.z / mag;
354 return nor;
355 }
356
357 public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
358 {
359 m_host.AddScriptLPS(1);
360 double dx = a.x - b.x;
361 double dy = a.y - b.y;
362 double dz = a.z - b.z;
363 return Math.Sqrt(dx * dx + dy * dy + dz * dz);
364 }
365
366 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
367
368 // Utility function for llRot2Euler
369
370 // normalize an angle between 0 - 2*PI (0 and 360 degrees)
371 private double NormalizeAngle(double angle)
372 {
373 angle = angle % (Math.PI * 2);
374 if (angle < 0) angle = angle + Math.PI * 2;
375 return angle;
376 }
377
378 // Old implementation of llRot2Euler, now normalized
379
380 public LSL_Vector llRot2Euler(LSL_Rotation r)
381 {
382 m_host.AddScriptLPS(1);
383 //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke
384 LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s);
385 double m = (t.x + t.y + t.z + t.s);
386 if (m == 0) return new LSL_Vector();
387 double n = 2 * (r.y * r.s + r.x * r.z);
388 double p = m * m - n * n;
389 if (p > 0)
390 return new LSL_Vector(NormalizeAngle(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s))),
391 NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))),
392 NormalizeAngle(Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))));
393 else if (n > 0)
394 return new LSL_Vector(0.0, Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
395 else
396 return new LSL_Vector(0.0, -Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
397 }
398
399 /* From wiki:
400 The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
401 in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
402 a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
403 vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
404 */
405
406 /* How we arrived at this llEuler2Rot
407 *
408 * Experiment in SL to determine conventions:
409 * llEuler2Rot(<PI,0,0>)=<1,0,0,0>
410 * llEuler2Rot(<0,PI,0>)=<0,1,0,0>
411 * llEuler2Rot(<0,0,PI>)=<0,0,1,0>
412 *
413 * Important facts about Quaternions
414 * - multiplication is non-commutative (a*b != b*a)
415 * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
416 *
417 * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
418 * Qx = c1+i*s1
419 * Qy = c2+j*s2;
420 * Qz = c3+k*s3;
421 *
422 * Rotations applied in order (from above) Z, Y, X
423 * Q = (Qz * Qy) * Qx
424 * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
425 * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
426 * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
427 * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3
428 * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3 -s1*s2*s3
429 * regroup: x=i*(s1*c2*c3+c1*s2*s3)
430 * y=j*(c1*s2*c3-s1*c2*s3)
431 * z=k*(s1*s2*c3+c1*c2*s3)
432 * s= c1*c2*c3-s1*s2*s3
433 *
434 * This implementation agrees with the functions found here:
435 * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
436 * And with the results in SL.
437 *
438 * It's also possible to calculate llEuler2Rot by direct multiplication of
439 * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
440 * from the wiki).
441 * Apparently in some cases this is better from a numerical precision perspective?
442 */
443
444 public LSL_Rotation llEuler2Rot(LSL_Vector v)
445 {
446 m_host.AddScriptLPS(1);
447
448 double x,y,z,s;
449
450 double c1 = Math.Cos(v.x/2.0);
451 double c2 = Math.Cos(v.y/2.0);
452 double c3 = Math.Cos(v.z/2.0);
453 double s1 = Math.Sin(v.x/2.0);
454 double s2 = Math.Sin(v.y/2.0);
455 double s3 = Math.Sin(v.z/2.0);
456
457 x = s1*c2*c3+c1*s2*s3;
458 y = c1*s2*c3-s1*c2*s3;
459 z = s1*s2*c3+c1*c2*s3;
460 s = c1*c2*c3-s1*s2*s3;
461
462 return new LSL_Rotation(x, y, z, s);
463 }
464
465 public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
466 {
467 m_host.AddScriptLPS(1);
468 double x, y, z, s;
469 int f = 0;
470 // Important Note: q1=<x,y,z,s> is equal to q2=<-x,-y,-z,-s>
471 // Computing quaternion x,y,z,s values
472 x = ((fwd.x - left.y - up.z + 1) / 4);
473 x *= x;
474 x = Math.Sqrt(Math.Sqrt(x));
475 y = ((1 - up.z) / 2 - x * x);
476 y *= y;
477 y = Math.Sqrt(Math.Sqrt(y));
478 z = ((1 - left.y) / 2 - x * x);
479 z *= z;
480 z = Math.Sqrt(Math.Sqrt(z));
481 s = (1 - x * x - y * y - z * z);
482 s *= s;
483 s = Math.Sqrt(Math.Sqrt(s));
484
485 // Set f for signs detection
486 if (fwd.y + left.x >= 0) { f += 1; }
487 if (fwd.z + up.x >= 0) { f += 2; }
488 if (left.z - up.y >= 0) { f += 4; }
489 // Set correct quaternion signs based on f value
490 if (f == 0) { x = -x; }
491 if (f == 1) { x = -x; y = -y; }
492 if (f == 2) { x = -x; z = -z; }
493 if (f == 3) { s = -s; }
494 if (f == 4) { x = -x; s = -s; }
495 if (f == 5) { z = -z; }
496 if (f == 6) { y = -y; }
497
498 LSL_Rotation result = new LSL_Rotation(x, y, z, s);
499
500 // a hack to correct a few questionable angles :(
501 if (llVecDist(llRot2Fwd(result), fwd) > 0.001 || llVecDist(llRot2Left(result), left) > 0.001)
502 result.s = -s;
503
504 return result;
505 }
506
507 public LSL_Vector llRot2Fwd(LSL_Rotation r)
508 {
509 m_host.AddScriptLPS(1);
510
511 double x, y, z, m;
512
513 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
514 // m is always greater than zero
515 // if m is not equal to 1 then Rotation needs to be normalized
516 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
517 {
518 m = 1.0 / Math.Sqrt(m);
519 r.x *= m;
520 r.y *= m;
521 r.z *= m;
522 r.s *= m;
523 }
524
525 // Fast Algebric Calculations instead of Vectors & Quaternions Product
526 x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s;
527 y = 2 * (r.x * r.y + r.z * r.s);
528 z = 2 * (r.x * r.z - r.y * r.s);
529 return (new LSL_Vector(x, y, z));
530 }
531
532 public LSL_Vector llRot2Left(LSL_Rotation r)
533 {
534 m_host.AddScriptLPS(1);
535
536 double x, y, z, m;
537
538 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
539 // m is always greater than zero
540 // if m is not equal to 1 then Rotation needs to be normalized
541 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
542 {
543 m = 1.0 / Math.Sqrt(m);
544 r.x *= m;
545 r.y *= m;
546 r.z *= m;
547 r.s *= m;
548 }
549
550 // Fast Algebric Calculations instead of Vectors & Quaternions Product
551 x = 2 * (r.x * r.y - r.z * r.s);
552 y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s;
553 z = 2 * (r.x * r.s + r.y * r.z);
554 return (new LSL_Vector(x, y, z));
555 }
556
557 public LSL_Vector llRot2Up(LSL_Rotation r)
558 {
559 m_host.AddScriptLPS(1);
560 double x, y, z, m;
561
562 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
563 // m is always greater than zero
564 // if m is not equal to 1 then Rotation needs to be normalized
565 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
566 {
567 m = 1.0 / Math.Sqrt(m);
568 r.x *= m;
569 r.y *= m;
570 r.z *= m;
571 r.s *= m;
572 }
573
574 // Fast Algebric Calculations instead of Vectors & Quaternions Product
575 x = 2 * (r.x * r.z + r.y * r.s);
576 y = 2 * (-r.x * r.s + r.y * r.z);
577 z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s;
578 return (new LSL_Vector(x, y, z));
579 }
580
581 public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
582 {
583 //A and B should both be normalized
584 m_host.AddScriptLPS(1);
585 double dotProduct = LSL_Vector.Dot(a, b);
586 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
587 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
588 double angle = Math.Acos(dotProduct / magProduct);
589 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
590 double s = Math.Sin(angle / 2);
591
592 double x = axis.x * s;
593 double y = axis.y * s;
594 double z = axis.z * s;
595 double w = Math.Cos(angle / 2);
596
597 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
598 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
599
600 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
601 }
602
603 public void llWhisper(int channelID, string text)
604 {
605 m_host.AddScriptLPS(1);
606
607 if (text.Length > 1023)
608 text = text.Substring(0, 1023);
609
610 World.SimChat(Utils.StringToBytes(text),
611 ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
612
613 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
614 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
615 }
616
617 public void llSay(int channelID, string text)
618 {
619 m_host.AddScriptLPS(1);
620
621 if (text.Length > 1023)
622 text = text.Substring(0, 1023);
623
624 World.SimChat(Utils.StringToBytes(text),
625 ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
626
627 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
628 wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
629 }
630
631 public void llShout(int channelID, string text)
632 {
633 m_host.AddScriptLPS(1);
634
635 if (text.Length > 1023)
636 text = text.Substring(0, 1023);
637
638 World.SimChat(Utils.StringToBytes(text),
639 ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, true);
640
641 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
642 wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
643 }
644
645 public void llRegionSay(int channelID, string text)
646 {
647 if (channelID == 0)
648 {
649 LSLError("Cannot use llRegionSay() on channel 0");
650 return;
651 }
652
653 if (text.Length > 1023)
654 text = text.Substring(0, 1023);
655
656 m_host.AddScriptLPS(1);
657
658 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
659 wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
660 }
661
662 public LSL_Integer llListen(int channelID, string name, string ID, string msg)
663 {
664 m_host.AddScriptLPS(1);
665 UUID keyID;
666 UUID.TryParse(ID, out keyID);
667 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
668 return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, keyID, msg);
669 }
670
671 public void llListenControl(int number, int active)
672 {
673 m_host.AddScriptLPS(1);
674 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
675 wComm.ListenControl(m_itemID, number, active);
676 }
677
678 public void llListenRemove(int number)
679 {
680 m_host.AddScriptLPS(1);
681 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
682 wComm.ListenRemove(m_itemID, number);
683 }
684
685 public void llSensor(string name, string id, int type, double range, double arc)
686 {
687 m_host.AddScriptLPS(1);
688 UUID keyID = UUID.Zero;
689 UUID.TryParse(id, out keyID);
690
691 AsyncCommands.SensorRepeatPlugin.SenseOnce(m_localID, m_itemID, name, keyID, type, range, arc, m_host);
692 }
693
694 public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
695 {
696 m_host.AddScriptLPS(1);
697 UUID keyID = UUID.Zero;
698 UUID.TryParse(id, out keyID);
699
700 AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_localID, m_itemID, name, keyID, type, range, arc, rate, m_host);
701 }
702
703 public void llSensorRemove()
704 {
705 m_host.AddScriptLPS(1);
706 AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_localID, m_itemID);
707 }
708
709 public string resolveName(UUID objecUUID)
710 {
711 // try avatar username surname
712 CachedUserInfo profile = World.CommsManager.UserProfileCacheService.GetUserDetails(objecUUID);
713 if (profile != null && profile.UserProfile != null)
714 {
715 string avatarname = profile.UserProfile.FirstName + " " + profile.UserProfile.SurName;
716 return avatarname;
717 }
718 // try an scene object
719 SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID);
720 if (SOP != null)
721 {
722 string objectname = SOP.Name;
723 return objectname;
724 }
725
726 EntityBase SensedObject;
727 lock (World.Entities)
728 {
729 World.Entities.TryGetValue(objecUUID, out SensedObject);
730 }
731
732 if (SensedObject == null)
733 return String.Empty;
734 return SensedObject.Name;
735 }
736
737 public LSL_String llDetectedName(int number)
738 {
739 m_host.AddScriptLPS(1);
740 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
741 if (d == null)
742 return String.Empty;
743 return d.Name;
744 }
745
746 public LSL_String llDetectedKey(int number)
747 {
748 m_host.AddScriptLPS(1);
749 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
750 if (d == null)
751 return String.Empty;
752 return d.Key.ToString();
753 }
754
755 public LSL_String llDetectedOwner(int number)
756 {
757 m_host.AddScriptLPS(1);
758 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
759 if (d == null)
760 return String.Empty;
761 return d.Owner.ToString();
762 }
763
764 public LSL_Integer llDetectedType(int number)
765 {
766 m_host.AddScriptLPS(1);
767 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
768 if (d == null)
769 return 0;
770 return new LSL_Integer(d.Type);
771 }
772
773 public LSL_Vector llDetectedPos(int number)
774 {
775 m_host.AddScriptLPS(1);
776 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
777 if (d == null)
778 return new LSL_Vector();
779 return d.Position;
780 }
781
782 public LSL_Vector llDetectedVel(int number)
783 {
784 m_host.AddScriptLPS(1);
785 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
786 if (d == null)
787 return new LSL_Vector();
788 return d.Velocity;
789 }
790
791 public LSL_Vector llDetectedGrab(int number)
792 {
793 m_host.AddScriptLPS(1);
794 DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number);
795 if (parms == null)
796 return new LSL_Vector(0, 0, 0);
797
798 return parms.OffsetPos;
799 }
800
801 public LSL_Rotation llDetectedRot(int number)
802 {
803 m_host.AddScriptLPS(1);
804 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
805 if (d == null)
806 return new LSL_Rotation();
807 return d.Rotation;
808 }
809
810 public LSL_Integer llDetectedGroup(int number)
811 {
812 m_host.AddScriptLPS(1);
813 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
814 if (d == null)
815 return new LSL_Integer(0);
816 if (m_host.GroupID == d.Group)
817 return new LSL_Integer(1);
818 return new LSL_Integer(0);
819 }
820
821 public LSL_Integer llDetectedLinkNumber(int number)
822 {
823 m_host.AddScriptLPS(1);
824 DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number);
825 if (parms == null)
826 return new LSL_Integer(0);
827
828 return new LSL_Integer(parms.LinkNum);
829 }
830
831 public LSL_Vector llDetectedTouchBinormal(int index)
832 {
833 m_host.AddScriptLPS(1);
834 NotImplemented("llDetectedTouchBinormal");
835 return new LSL_Vector();
836 }
837
838 public LSL_Integer llDetectedTouchFace(int index)
839 {
840 m_host.AddScriptLPS(1);
841 NotImplemented("llDetectedTouchFace");
842 return new LSL_Integer(0);
843 }
844
845 public LSL_Vector llDetectedTouchNormal(int index)
846 {
847 m_host.AddScriptLPS(1);
848 NotImplemented("llDetectedTouchNormal");
849 return new LSL_Vector();
850 }
851
852 public LSL_Vector llDetectedTouchPos(int index)
853 {
854 m_host.AddScriptLPS(1);
855 NotImplemented("llDetectedTouchPos");
856 return new LSL_Vector();
857 }
858
859 public LSL_Vector llDetectedTouchST(int index)
860 {
861 m_host.AddScriptLPS(1);
862 NotImplemented("llDetectedTouchST");
863 return new LSL_Vector();
864 }
865
866 public LSL_Vector llDetectedTouchUV(int index)
867 {
868 m_host.AddScriptLPS(1);
869 NotImplemented("llDetectedTouchUV");
870 return new LSL_Vector();
871 }
872
873 public void llDie()
874 {
875 m_host.AddScriptLPS(1);
876 throw new SelfDeleteException();
877 }
878
879 public LSL_Float llGround(LSL_Vector offset)
880 {
881 m_host.AddScriptLPS(1);
882 int x = (int)(m_host.OffsetPosition.X + offset.x);
883 int y = (int)(m_host.OffsetPosition.Y + offset.y);
884 return World.GetLandHeight(x, y);
885 }
886
887 public LSL_Float llCloud(LSL_Vector offset)
888 {
889 m_host.AddScriptLPS(1);
890 return 0;
891 }
892
893 public LSL_Vector llWind(LSL_Vector offset)
894 {
895 m_host.AddScriptLPS(1);
896 return new LSL_Vector();
897 }
898
899 public void llSetStatus(int status, int value)
900 {
901 m_host.AddScriptLPS(1);
902
903 int statusrotationaxis = 0;
904
905 if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS)
906 {
907 if (value == 1)
908 {
909 SceneObjectGroup group = m_host.ParentGroup;
910 if (group == null)
911 return;
912 bool allow = true;
913 foreach (SceneObjectPart part in group.Children.Values)
914 {
915 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
916 {
917 allow = false;
918 break;
919 }
920 }
921
922 if (!allow)
923 return;
924 m_host.ScriptSetPhysicsStatus(true);
925 }
926 else
927 m_host.ScriptSetPhysicsStatus(false);
928 }
929
930 if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM)
931 {
932 if (value == 1)
933 m_host.ScriptSetPhantomStatus(true);
934 else
935 m_host.ScriptSetPhantomStatus(false);
936 }
937
938 if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS)
939 {
940 m_host.AddFlag(PrimFlags.CastShadows);
941 }
942
943 if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X)
944 {
945 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X;
946 }
947
948 if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y)
949 {
950 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y;
951 }
952
953 if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z)
954 {
955 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z;
956 }
957
958 if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB)
959 {
960 NotImplemented("llSetStatus - STATUS_BLOCK_GRAB");
961 }
962
963 if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE)
964 {
965 if (value == 1)
966 m_host.SetDieAtEdge(true);
967 else
968 m_host.SetDieAtEdge(false);
969 }
970
971 if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
972 {
973 NotImplemented("llSetStatus - STATUS_RETURN_AT_EDGE");
974 }
975
976 if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX)
977 {
978 NotImplemented("llSetStatus - STATUS_SANDBOX");
979 }
980
981 if (statusrotationaxis != 0)
982 {
983 m_host.SetAxisRotation(statusrotationaxis, value);
984 }
985 }
986
987 public LSL_Integer llGetStatus(int status)
988 {
989 m_host.AddScriptLPS(1);
990 // Console.WriteLine(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString());
991 switch (status)
992 {
993 case ScriptBaseClass.STATUS_PHYSICS:
994 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics)
995 {
996 return 1;
997 }
998 return 0;
999
1000 case ScriptBaseClass.STATUS_PHANTOM:
1001 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom)
1002 {
1003 return 1;
1004 }
1005 return 0;
1006
1007 case ScriptBaseClass.STATUS_CAST_SHADOWS:
1008 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows)
1009 {
1010 return 1;
1011 }
1012 return 0;
1013
1014 case ScriptBaseClass.STATUS_BLOCK_GRAB:
1015 NotImplemented("llGetStatus - STATUS_BLOCK_GRAB");
1016 return 0;
1017
1018 case ScriptBaseClass.STATUS_DIE_AT_EDGE:
1019 if (m_host.GetDieAtEdge())
1020 return 1;
1021 else
1022 return 0;
1023
1024 case ScriptBaseClass.STATUS_RETURN_AT_EDGE:
1025 NotImplemented("llGetStatus - STATUS_RETURN_AT_EDGE");
1026 return 0;
1027
1028 case ScriptBaseClass.STATUS_ROTATE_X:
1029 NotImplemented("llGetStatus - STATUS_ROTATE_X");
1030 return 0;
1031
1032 case ScriptBaseClass.STATUS_ROTATE_Y:
1033 NotImplemented("llGetStatus - STATUS_ROTATE_Y");
1034 return 0;
1035
1036 case ScriptBaseClass.STATUS_ROTATE_Z:
1037 NotImplemented("llGetStatus - STATUS_ROTATE_Z");
1038 return 0;
1039
1040 case ScriptBaseClass.STATUS_SANDBOX:
1041 NotImplemented("llGetStatus - STATUS_SANDBOX");
1042 return 0;
1043 }
1044 return 0;
1045 }
1046
1047 public void llSetScale(LSL_Vector scale)
1048 {
1049 m_host.AddScriptLPS(1);
1050 SetScale(m_host, scale);
1051 }
1052
1053 private void SetScale(SceneObjectPart part, LSL_Vector scale)
1054 {
1055 // TODO: this needs to trigger a persistance save as well
1056
1057 if (part == null || part.ParentGroup == null || part.ParentGroup.RootPart == null)
1058 return;
1059
1060 if (part.ParentGroup.RootPart.PhysActor != null && part.ParentGroup.RootPart.PhysActor.IsPhysical)
1061 {
1062 if (scale.x > World.m_maxPhys)
1063 scale.x = World.m_maxPhys;
1064 if (scale.y > World.m_maxPhys)
1065 scale.y = World.m_maxPhys;
1066 if (scale.z > World.m_maxPhys)
1067 scale.z = World.m_maxPhys;
1068 }
1069 if (scale.x > World.m_maxNonphys)
1070 scale.x = World.m_maxNonphys;
1071 if (scale.y > World.m_maxNonphys)
1072 scale.y = World.m_maxNonphys;
1073 if (scale.z > World.m_maxNonphys)
1074 scale.z = World.m_maxNonphys;
1075 Vector3 tmp = part.Scale;
1076 tmp.X = (float)scale.x;
1077 tmp.Y = (float)scale.y;
1078 tmp.Z = (float)scale.z;
1079 part.Scale = tmp;
1080 part.SendFullUpdateToAllClients();
1081 }
1082
1083 public LSL_Vector llGetScale()
1084 {
1085 m_host.AddScriptLPS(1);
1086 return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z);
1087 }
1088
1089 public void llSetClickAction(int action)
1090 {
1091 m_host.AddScriptLPS(1);
1092 NotImplemented("llSetClickAction");
1093 return;
1094 }
1095
1096 public void llSetColor(LSL_Vector color, int face)
1097 {
1098 m_host.AddScriptLPS(1);
1099
1100 SetColor(m_host, color, face);
1101 }
1102
1103 private void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1104 {
1105 Primitive.TextureEntry tex = part.Shape.Textures;
1106 Color4 texcolor;
1107 if (face >= 0 && face < GetNumberOfSides(part))
1108 {
1109 texcolor = tex.CreateFace((uint)face).RGBA;
1110 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1111 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1112 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1113 tex.FaceTextures[face].RGBA = texcolor;
1114 part.UpdateTexture(tex);
1115 return;
1116 }
1117 else if (face == ScriptBaseClass.ALL_SIDES)
1118 {
1119 for (uint i = 0; i < GetNumberOfSides(part); i++)
1120 {
1121 if (tex.FaceTextures[i] != null)
1122 {
1123 texcolor = tex.FaceTextures[i].RGBA;
1124 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1125 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1126 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1127 tex.FaceTextures[i].RGBA = texcolor;
1128 }
1129 texcolor = tex.DefaultTexture.RGBA;
1130 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1131 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1132 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1133 tex.DefaultTexture.RGBA = texcolor;
1134 }
1135 part.UpdateTexture(tex);
1136 return;
1137 }
1138 }
1139
1140 public void SetGlow(SceneObjectPart part, int face, float glow)
1141 {
1142 Primitive.TextureEntry tex = part.Shape.Textures;
1143 if (face >= 0 && face < GetNumberOfSides(part))
1144 {
1145 tex.CreateFace((uint) face);
1146 tex.FaceTextures[face].Glow = glow;
1147 part.UpdateTexture(tex);
1148 return;
1149 }
1150 else if (face == ScriptBaseClass.ALL_SIDES)
1151 {
1152 for (uint i = 0; i < GetNumberOfSides(part); i++)
1153 {
1154 if (tex.FaceTextures[i] != null)
1155 {
1156 tex.FaceTextures[i].Glow = glow;
1157 }
1158 tex.DefaultTexture.Glow = glow;
1159 }
1160 part.UpdateTexture(tex);
1161 return;
1162 }
1163 }
1164
1165 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1166 {
1167
1168 Shininess sval = new Shininess();
1169
1170 switch (shiny)
1171 {
1172 case 0:
1173 sval = Shininess.None;
1174 break;
1175 case 1:
1176 sval = Shininess.Low;
1177 break;
1178 case 2:
1179 sval = Shininess.Medium;
1180 break;
1181 case 3:
1182 sval = Shininess.High;
1183 break;
1184 default:
1185 sval = Shininess.None;
1186 break;
1187 }
1188
1189 Primitive.TextureEntry tex = part.Shape.Textures;
1190 if (face >= 0 && face < GetNumberOfSides(part))
1191 {
1192 tex.CreateFace((uint) face);
1193 tex.FaceTextures[face].Shiny = sval;
1194 tex.FaceTextures[face].Bump = bump;
1195 part.UpdateTexture(tex);
1196 return;
1197 }
1198 else if (face == ScriptBaseClass.ALL_SIDES)
1199 {
1200 for (uint i = 0; i < GetNumberOfSides(part); i++)
1201 {
1202 if (tex.FaceTextures[i] != null)
1203 {
1204 tex.FaceTextures[i].Shiny = sval;
1205 tex.FaceTextures[i].Bump = bump;;
1206 }
1207 tex.DefaultTexture.Shiny = sval;
1208 tex.DefaultTexture.Bump = bump;
1209 }
1210 part.UpdateTexture(tex);
1211 return;
1212 }
1213 }
1214
1215 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1216 {
1217 Primitive.TextureEntry tex = part.Shape.Textures;
1218 if (face >= 0 && face < GetNumberOfSides(part))
1219 {
1220 tex.CreateFace((uint) face);
1221 tex.FaceTextures[face].Fullbright = bright;
1222 part.UpdateTexture(tex);
1223 return;
1224 }
1225 else if (face == ScriptBaseClass.ALL_SIDES)
1226 {
1227 for (uint i = 0; i < GetNumberOfSides(part); i++)
1228 {
1229 if (tex.FaceTextures[i] != null)
1230 {
1231 tex.FaceTextures[i].Fullbright = bright;
1232 }
1233 }
1234 tex.DefaultTexture.Fullbright = bright;
1235 part.UpdateTexture(tex);
1236 return;
1237 }
1238 }
1239
1240 public LSL_Float llGetAlpha(int face)
1241 {
1242 m_host.AddScriptLPS(1);
1243
1244 return GetAlpha(m_host, face);
1245 }
1246
1247 private LSL_Float GetAlpha(SceneObjectPart part, int face)
1248 {
1249 Primitive.TextureEntry tex = part.Shape.Textures;
1250 if (face == ScriptBaseClass.ALL_SIDES)
1251 {
1252 int i;
1253 double sum = 0.0;
1254 for (i = 0 ; i < GetNumberOfSides(part) ; i++)
1255 sum += (double)tex.GetFace((uint)i).RGBA.A;
1256 return sum;
1257 }
1258 if (face >= 0 && face < GetNumberOfSides(part))
1259 {
1260 return (double)tex.GetFace((uint)face).RGBA.A;
1261 }
1262 return 0.0;
1263 }
1264
1265 public void llSetAlpha(double alpha, int face)
1266 {
1267 m_host.AddScriptLPS(1);
1268
1269 SetAlpha(m_host, alpha, face);
1270 }
1271
1272 private void SetAlpha(SceneObjectPart part, double alpha, int face)
1273 {
1274 Primitive.TextureEntry tex = part.Shape.Textures;
1275 Color4 texcolor;
1276 if (face >= 0 && face < GetNumberOfSides(part))
1277 {
1278 texcolor = tex.CreateFace((uint)face).RGBA;
1279 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
1280 tex.FaceTextures[face].RGBA = texcolor;
1281 part.UpdateTexture(tex);
1282 return;
1283 }
1284 else if (face == ScriptBaseClass.ALL_SIDES)
1285 {
1286 for (int i = 0; i < GetNumberOfSides(part); i++)
1287 {
1288 if (tex.FaceTextures[i] != null)
1289 {
1290 texcolor = tex.FaceTextures[i].RGBA;
1291 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
1292 tex.FaceTextures[i].RGBA = texcolor;
1293 }
1294 }
1295 texcolor = tex.DefaultTexture.RGBA;
1296 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
1297 tex.DefaultTexture.RGBA = texcolor;
1298 part.UpdateTexture(tex);
1299 return;
1300 }
1301 }
1302
1303 /// <summary>
1304 /// Set flexi parameters of a part.
1305 ///
1306 /// FIXME: Much of this code should probably be within the part itself.
1307 /// </summary>
1308 /// <param name="part"></param>
1309 /// <param name="flexi"></param>
1310 /// <param name="softness"></param>
1311 /// <param name="gravity"></param>
1312 /// <param name="friction"></param>
1313 /// <param name="wind"></param>
1314 /// <param name="tension"></param>
1315 /// <param name="Force"></param>
1316 private void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1317 float wind, float tension, LSL_Vector Force)
1318 {
1319 if (part == null)
1320 return;
1321
1322 bool needs_fakedelete = false;
1323 if (flexi)
1324 {
1325 if (!part.Shape.FlexiEntry)
1326 {
1327 needs_fakedelete = true;
1328 }
1329 part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do
1330 // work once the prim is already flexi
1331 part.Shape.FlexiSoftness = softness;
1332 part.Shape.FlexiGravity = gravity;
1333 part.Shape.FlexiDrag = friction;
1334 part.Shape.FlexiWind = wind;
1335 part.Shape.FlexiTension = tension;
1336 part.Shape.FlexiForceX = (float)Force.x;
1337 part.Shape.FlexiForceY = (float)Force.y;
1338 part.Shape.FlexiForceZ = (float)Force.z;
1339 part.Shape.PathCurve = 0x80;
1340
1341 }
1342 else
1343 {
1344 if (part.Shape.FlexiEntry)
1345 {
1346 needs_fakedelete = true;
1347 }
1348 part.Shape.FlexiEntry = false;
1349 }
1350
1351 needs_fakedelete = false;
1352 if (needs_fakedelete)
1353 {
1354 if (part.ParentGroup != null)
1355 {
1356 part.ParentGroup.FakeDeleteGroup();
1357 }
1358 }
1359
1360 part.ParentGroup.HasGroupChanged = true;
1361 part.ScheduleFullUpdate();
1362 }
1363
1364 /// <summary>
1365 /// Set a light point on a part
1366 ///
1367 /// FIXME: Much of this code should probably be in SceneObjectGroup
1368 /// </summary>
1369 /// <param name="part"></param>
1370 /// <param name="light"></param>
1371 /// <param name="color"></param>
1372 /// <param name="intensity"></param>
1373 /// <param name="radius"></param>
1374 /// <param name="falloff"></param>
1375 private void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1376 {
1377 if (part == null)
1378 return;
1379
1380 if (light)
1381 {
1382 part.Shape.LightEntry = true;
1383 part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f);
1384 part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f);
1385 part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f);
1386 part.Shape.LightIntensity = intensity;
1387 part.Shape.LightRadius = radius;
1388 part.Shape.LightFalloff = falloff;
1389 }
1390 else
1391 {
1392 part.Shape.LightEntry = false;
1393 }
1394
1395 part.ParentGroup.HasGroupChanged = true;
1396 part.ScheduleFullUpdate();
1397 }
1398
1399 public LSL_Vector llGetColor(int face)
1400 {
1401 m_host.AddScriptLPS(1);
1402 return GetColor(m_host, face);
1403 }
1404
1405 private LSL_Vector GetColor(SceneObjectPart part, int face)
1406 {
1407 Primitive.TextureEntry tex = part.Shape.Textures;
1408 Color4 texcolor;
1409 LSL_Vector rgb = new LSL_Vector();
1410 if (face == ScriptBaseClass.ALL_SIDES)
1411 {
1412 int i;
1413
1414 for (i = 0 ; i < GetNumberOfSides(part) ; i++)
1415 {
1416 texcolor = tex.GetFace((uint)i).RGBA;
1417 rgb.x += texcolor.R;
1418 rgb.y += texcolor.G;
1419 rgb.z += texcolor.B;
1420 }
1421
1422 rgb.x /= (float)GetNumberOfSides(part);
1423 rgb.y /= (float)GetNumberOfSides(part);
1424 rgb.z /= (float)GetNumberOfSides(part);
1425
1426 return rgb;
1427 }
1428 if (face >= 0 && face < GetNumberOfSides(part))
1429 {
1430 texcolor = tex.GetFace((uint)face).RGBA;
1431 rgb.x = texcolor.R;
1432 rgb.y = texcolor.G;
1433 rgb.z = texcolor.B;
1434 return rgb;
1435 }
1436 else
1437 {
1438 return new LSL_Vector();
1439 }
1440 }
1441
1442 public void llSetTexture(string texture, int face)
1443 {
1444 m_host.AddScriptLPS(1);
1445 SetTexture(m_host, texture, face);
1446 // ScriptSleep(200);
1447 }
1448
1449 private void SetTexture(SceneObjectPart part, string texture, int face)
1450 {
1451 UUID textureID=new UUID();
1452
1453 if (!UUID.TryParse(texture, out textureID))
1454 {
1455 textureID=InventoryKey(texture, (int)AssetType.Texture);
1456 }
1457
1458 if (textureID == UUID.Zero)
1459 return;
1460
1461 Primitive.TextureEntry tex = part.Shape.Textures;
1462
1463 if (face >= 0 && face < GetNumberOfSides(part))
1464 {
1465 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
1466 texface.TextureID = textureID;
1467 tex.FaceTextures[face] = texface;
1468 part.UpdateTexture(tex);
1469 return;
1470 }
1471 else if (face == ScriptBaseClass.ALL_SIDES)
1472 {
1473 for (uint i = 0; i < GetNumberOfSides(part); i++)
1474 {
1475 if (tex.FaceTextures[i] != null)
1476 {
1477 tex.FaceTextures[i].TextureID = textureID;
1478 }
1479 }
1480 tex.DefaultTexture.TextureID = textureID;
1481 part.UpdateTexture(tex);
1482 return;
1483 }
1484 }
1485
1486 public void llScaleTexture(double u, double v, int face)
1487 {
1488 m_host.AddScriptLPS(1);
1489
1490 ScaleTexture(m_host, u, v, face);
1491 // ScriptSleep(200);
1492 }
1493
1494 private void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1495 {
1496 Primitive.TextureEntry tex = part.Shape.Textures;
1497 if (face >= 0 && face < GetNumberOfSides(part))
1498 {
1499 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
1500 texface.RepeatU = (float)u;
1501 texface.RepeatV = (float)v;
1502 tex.FaceTextures[face] = texface;
1503 part.UpdateTexture(tex);
1504 return;
1505 }
1506 if (face == ScriptBaseClass.ALL_SIDES)
1507 {
1508 for (int i = 0; i < GetNumberOfSides(part); i++)
1509 {
1510 if (tex.FaceTextures[i] != null)
1511 {
1512 tex.FaceTextures[i].RepeatU = (float)u;
1513 tex.FaceTextures[i].RepeatV = (float)v;
1514 }
1515 }
1516 tex.DefaultTexture.RepeatU = (float)u;
1517 tex.DefaultTexture.RepeatV = (float)v;
1518 part.UpdateTexture(tex);
1519 return;
1520 }
1521 }
1522
1523 public void llOffsetTexture(double u, double v, int face)
1524 {
1525 m_host.AddScriptLPS(1);
1526 OffsetTexture(m_host, u, v, face);
1527 // ScriptSleep(200);
1528 }
1529
1530 private void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1531 {
1532 Primitive.TextureEntry tex = part.Shape.Textures;
1533 if (face >= 0 && face < GetNumberOfSides(part))
1534 {
1535 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
1536 texface.OffsetU = (float)u;
1537 texface.OffsetV = (float)v;
1538 tex.FaceTextures[face] = texface;
1539 part.UpdateTexture(tex);
1540 return;
1541 }
1542 if (face == ScriptBaseClass.ALL_SIDES)
1543 {
1544 for (int i = 0; i < GetNumberOfSides(part); i++)
1545 {
1546 if (tex.FaceTextures[i] != null)
1547 {
1548 tex.FaceTextures[i].OffsetU = (float)u;
1549 tex.FaceTextures[i].OffsetV = (float)v;
1550 }
1551 }
1552 tex.DefaultTexture.OffsetU = (float)u;
1553 tex.DefaultTexture.OffsetV = (float)v;
1554 part.UpdateTexture(tex);
1555 return;
1556 }
1557 }
1558
1559 public void llRotateTexture(double rotation, int face)
1560 {
1561 m_host.AddScriptLPS(1);
1562 RotateTexture(m_host, rotation, face);
1563 // ScriptSleep(200);
1564 }
1565
1566 private void RotateTexture(SceneObjectPart part, double rotation, int face)
1567 {
1568 Primitive.TextureEntry tex = part.Shape.Textures;
1569 if (face >= 0 && face < GetNumberOfSides(part))
1570 {
1571 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
1572 texface.Rotation = (float)rotation;
1573 tex.FaceTextures[face] = texface;
1574 part.UpdateTexture(tex);
1575 return;
1576 }
1577 if (face == ScriptBaseClass.ALL_SIDES)
1578 {
1579 for (int i = 0; i < GetNumberOfSides(part); i++)
1580 {
1581 if (tex.FaceTextures[i] != null)
1582 {
1583 tex.FaceTextures[i].Rotation = (float)rotation;
1584 }
1585 }
1586 tex.DefaultTexture.Rotation = (float)rotation;
1587 part.UpdateTexture(tex);
1588 return;
1589 }
1590 }
1591
1592 public LSL_String llGetTexture(int face)
1593 {
1594 m_host.AddScriptLPS(1);
1595 return GetTexture(m_host, face);
1596 }
1597
1598 private LSL_String GetTexture(SceneObjectPart part, int face)
1599 {
1600 Primitive.TextureEntry tex = part.Shape.Textures;
1601 if (face == ScriptBaseClass.ALL_SIDES)
1602 {
1603 face = 0;
1604 }
1605 if (face >= 0 && face < GetNumberOfSides(part))
1606 {
1607 Primitive.TextureEntryFace texface;
1608 texface = tex.GetFace((uint)face);
1609 return texface.TextureID.ToString();
1610 }
1611 else
1612 {
1613 return String.Empty;
1614 }
1615 }
1616
1617 public void llSetPos(LSL_Vector pos)
1618 {
1619 m_host.AddScriptLPS(1);
1620
1621 SetPos(m_host, pos);
1622
1623 ScriptSleep(200);
1624 }
1625
1626 private void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1627 {
1628 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
1629 LSL_Vector currentPos = llGetLocalPos();
1630 if (llVecDist(currentPos, targetPos) > 10.0f * m_ScriptDistanceFactor)
1631 {
1632 targetPos = currentPos + m_ScriptDistanceFactor * 10.0f * llVecNorm(targetPos - currentPos);
1633 }
1634
1635 if (part.ParentID != 0)
1636 {
1637 part.UpdateOffSet(new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z));
1638 }
1639 else
1640 {
1641 part.UpdateGroupPosition(new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z));
1642 }
1643 }
1644
1645 public LSL_Vector llGetPos()
1646 {
1647 m_host.AddScriptLPS(1);
1648 return new LSL_Vector(m_host.AbsolutePosition.X,
1649 m_host.AbsolutePosition.Y,
1650 m_host.AbsolutePosition.Z);
1651 }
1652
1653 public LSL_Vector llGetLocalPos()
1654 {
1655 m_host.AddScriptLPS(1);
1656 if (m_host.ParentID != 0)
1657 {
1658 return new LSL_Vector(m_host.OffsetPosition.X,
1659 m_host.OffsetPosition.Y,
1660 m_host.OffsetPosition.Z);
1661 }
1662 else
1663 {
1664 return new LSL_Vector(m_host.AbsolutePosition.X,
1665 m_host.AbsolutePosition.Y,
1666 m_host.AbsolutePosition.Z);
1667 }
1668 }
1669
1670 public void llSetRot(LSL_Rotation rot)
1671 {
1672 m_host.AddScriptLPS(1);
1673
1674 SetRot(m_host, rot);
1675
1676 ScriptSleep(200);
1677 }
1678
1679 private void SetRot(SceneObjectPart part, LSL_Rotation rot)
1680 {
1681 part.UpdateRotation(new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s));
1682 // Update rotation does not move the object in the physics scene if it's a linkset.
1683 part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition;
1684 }
1685
1686 public LSL_Rotation llGetRot()
1687 {
1688 m_host.AddScriptLPS(1);
1689 Quaternion q = m_host.RotationOffset;
1690 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
1691 }
1692
1693 public LSL_Rotation llGetLocalRot()
1694 {
1695 m_host.AddScriptLPS(1);
1696 return new LSL_Rotation(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W);
1697 }
1698
1699 public void llSetForce(LSL_Vector force, int local)
1700 {
1701 m_host.AddScriptLPS(1);
1702
1703 if (m_host.ParentGroup != null)
1704 {
1705 if (m_host.ParentGroup.RootPart != null)
1706 {
1707 if (local != 0)
1708 force *= llGetRot();
1709
1710 m_host.ParentGroup.RootPart.SetForce(new PhysicsVector((float)force.x, (float)force.y, (float)force.z));
1711 }
1712 }
1713 }
1714
1715 public LSL_Vector llGetForce()
1716 {
1717 LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0);
1718
1719 m_host.AddScriptLPS(1);
1720
1721 if (m_host.ParentGroup != null)
1722 {
1723 if (m_host.ParentGroup.RootPart != null)
1724 {
1725 PhysicsVector tmpForce = m_host.ParentGroup.RootPart.GetForce();
1726 force.x = tmpForce.X;
1727 force.y = tmpForce.Y;
1728 force.z = tmpForce.Z;
1729 }
1730 }
1731
1732 return force;
1733 }
1734
1735 public LSL_Integer llTarget(LSL_Vector position, double range)
1736 {
1737 m_host.AddScriptLPS(1);
1738 return m_host.registerTargetWaypoint(new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range);
1739 }
1740
1741 public void llTargetRemove(int number)
1742 {
1743 m_host.AddScriptLPS(1);
1744 m_host.unregisterTargetWaypoint(number);
1745 }
1746
1747 public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
1748 {
1749 m_host.AddScriptLPS(1);
1750 NotImplemented("llRotTarget");
1751 return 0;
1752 }
1753
1754 public void llRotTargetRemove(int number)
1755 {
1756 m_host.AddScriptLPS(1);
1757 NotImplemented("llRotTargetRemove");
1758 }
1759
1760 public void llMoveToTarget(LSL_Vector target, double tau)
1761 {
1762 m_host.AddScriptLPS(1);
1763 m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau);
1764 }
1765
1766 public void llStopMoveToTarget()
1767 {
1768 m_host.AddScriptLPS(1);
1769 m_host.StopMoveToTarget();
1770 }
1771
1772 public void llApplyImpulse(LSL_Vector force, int local)
1773 {
1774 m_host.AddScriptLPS(1);
1775 //No energy force yet
1776
1777 if (force.x > 20000)
1778 force.x = 20000;
1779 if (force.y > 20000)
1780 force.y = 20000;
1781 if (force.z > 20000)
1782 force.z = 20000;
1783
1784 m_host.ApplyImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
1785 }
1786
1787 public void llApplyRotationalImpulse(LSL_Vector force, int local)
1788 {
1789 m_host.AddScriptLPS(1);
1790 NotImplemented("llApplyRotationalImpulse");
1791 }
1792
1793 public void llSetTorque(LSL_Vector torque, int local)
1794 {
1795 m_host.AddScriptLPS(1);
1796 NotImplemented("llSetTorque");
1797 }
1798
1799 public LSL_Vector llGetTorque()
1800 {
1801 m_host.AddScriptLPS(1);
1802 NotImplemented("llGetTorque");
1803 return new LSL_Vector();
1804 }
1805
1806 public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local)
1807 {
1808 m_host.AddScriptLPS(1);
1809 NotImplemented("llSetForceAndTorque");
1810 }
1811
1812 public LSL_Vector llGetVel()
1813 {
1814 m_host.AddScriptLPS(1);
1815 return new LSL_Vector(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z);
1816 }
1817
1818 public LSL_Vector llGetAccel()
1819 {
1820 m_host.AddScriptLPS(1);
1821 return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z);
1822 }
1823
1824 public LSL_Vector llGetOmega()
1825 {
1826 m_host.AddScriptLPS(1);
1827 return new LSL_Vector(m_host.RotationalVelocity.X, m_host.RotationalVelocity.Y, m_host.RotationalVelocity.Z);
1828 }
1829
1830 public LSL_Float llGetTimeOfDay()
1831 {
1832 m_host.AddScriptLPS(1);
1833 return (double)(((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4)) * World.TimeDilation);
1834 }
1835
1836 public LSL_Float llGetWallclock()
1837 {
1838 m_host.AddScriptLPS(1);
1839 return DateTime.Now.TimeOfDay.TotalSeconds;
1840 }
1841
1842 public LSL_Float llGetTime()
1843 {
1844 m_host.AddScriptLPS(1);
1845 TimeSpan ScriptTime = DateTime.Now - m_timer;
1846 return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation);
1847 }
1848
1849 public void llResetTime()
1850 {
1851 m_host.AddScriptLPS(1);
1852 m_timer = DateTime.Now;
1853 }
1854
1855 public LSL_Float llGetAndResetTime()
1856 {
1857 m_host.AddScriptLPS(1);
1858 TimeSpan ScriptTime = DateTime.Now - m_timer;
1859 m_timer = DateTime.Now;
1860 return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation);
1861 }
1862
1863 public void llSound()
1864 {
1865 m_host.AddScriptLPS(1);
1866 // This function has been deprecated
1867 // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound
1868 Deprecated("llSound");
1869 }
1870
1871 // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
1872 // 20080530 Updated to remove code duplication
1873 public void llPlaySound(string sound, double volume)
1874 {
1875 m_host.AddScriptLPS(1);
1876
1877 // send the sound, once, to all clients in range
1878 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0);
1879 }
1880
1881 // Xantor 20080528 we should do this differently.
1882 // 1) apply the sound to the object
1883 // 2) schedule full update
1884 // just sending the sound out once doesn't work so well when other avatars come in view later on
1885 // or when the prim gets moved, changed, sat on, whatever
1886 // see large number of mantises (mantes?)
1887 // 20080530 Updated to remove code duplication
1888 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
1889 public void llLoopSound(string sound, double volume)
1890 {
1891 m_host.AddScriptLPS(1);
1892
1893 if (m_host.Sound != UUID.Zero)
1894 llStopSound();
1895
1896 m_host.Sound = KeyOrName(sound);
1897 m_host.SoundGain = volume;
1898 m_host.SoundFlags = 1; // looping
1899 m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
1900
1901 m_host.ScheduleFullUpdate();
1902 m_host.SendFullUpdateToAllClients();
1903 }
1904
1905 public void llLoopSoundMaster(string sound, double volume)
1906 {
1907 m_host.AddScriptLPS(1);
1908 NotImplemented("llLoopSoundMaster");
1909 }
1910
1911 public void llLoopSoundSlave(string sound, double volume)
1912 {
1913 m_host.AddScriptLPS(1);
1914 NotImplemented("llLoopSoundSlave");
1915 }
1916
1917 public void llPlaySoundSlave(string sound, double volume)
1918 {
1919 m_host.AddScriptLPS(1);
1920 NotImplemented("llPlaySoundSlave");
1921 }
1922
1923 public void llTriggerSound(string sound, double volume)
1924 {
1925 m_host.AddScriptLPS(1);
1926 // send the sound, once, to all clients in range
1927 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0);
1928 }
1929
1930 // Xantor 20080528: Clear prim data of sound instead
1931 public void llStopSound()
1932 {
1933 m_host.AddScriptLPS(1);
1934
1935 m_host.Sound = UUID.Zero;
1936 m_host.SoundGain = 0;
1937 m_host.SoundFlags = 0;
1938 m_host.SoundRadius = 0;
1939
1940 m_host.ScheduleFullUpdate();
1941 m_host.SendFullUpdateToAllClients();
1942
1943 // m_host.SendSound(UUID.Zero.ToString(), 1.0, false, 2);
1944 }
1945
1946 public void llPreloadSound(string sound)
1947 {
1948 m_host.AddScriptLPS(1);
1949 m_host.PreloadSound(sound);
1950 // ScriptSleep(1000);
1951 }
1952
1953 /// <summary>
1954 /// Return a portion of the designated string bounded by
1955 /// inclusive indices (start and end). As usual, the negative
1956 /// indices, and the tolerance for out-of-bound values, makes
1957 /// this more complicated than it might otherwise seem.
1958 /// </summary>
1959
1960 public LSL_String llGetSubString(string src, int start, int end)
1961 {
1962
1963 m_host.AddScriptLPS(1);
1964
1965 // Normalize indices (if negative).
1966 // After normlaization they may still be
1967 // negative, but that is now relative to
1968 // the start, rather than the end, of the
1969 // sequence.
1970
1971 if (start < 0)
1972 {
1973 start = src.Length+start;
1974 }
1975 if (end < 0)
1976 {
1977 end = src.Length+end;
1978 }
1979
1980 // Conventional substring
1981 if (start <= end)
1982 {
1983 // Implies both bounds are out-of-range.
1984 if (end < 0 || start >= src.Length)
1985 {
1986 return String.Empty;
1987 }
1988 // If end is positive, then it directly
1989 // corresponds to the lengt of the substring
1990 // needed (plus one of course). BUT, it
1991 // must be within bounds.
1992 if (end >= src.Length)
1993 {
1994 end = src.Length-1;
1995 }
1996
1997 if (start < 0)
1998 {
1999 return src.Substring(0,end+1);
2000 }
2001 // Both indices are positive
2002 return src.Substring(start, (end+1) - start);
2003 }
2004
2005 // Inverted substring (end < start)
2006 else
2007 {
2008 // Implies both indices are below the
2009 // lower bound. In the inverted case, that
2010 // means the entire string will be returned
2011 // unchanged.
2012 if (start < 0)
2013 {
2014 return src;
2015 }
2016 // If both indices are greater than the upper
2017 // bound the result may seem initially counter
2018 // intuitive.
2019 if (end >= src.Length)
2020 {
2021 return src;
2022 }
2023
2024 if (end < 0)
2025 {
2026 if (start < src.Length)
2027 {
2028 return src.Substring(start);
2029 }
2030 else
2031 {
2032 return String.Empty;
2033 }
2034 }
2035 else
2036 {
2037 if (start < src.Length)
2038 {
2039 return src.Substring(0,end+1) + src.Substring(start);
2040 }
2041 else
2042 {
2043 return src.Substring(0,end+1);
2044 }
2045 }
2046 }
2047 }
2048
2049 /// <summary>
2050 /// Delete substring removes the specified substring bounded
2051 /// by the inclusive indices start and end. Indices may be
2052 /// negative (indicating end-relative) and may be inverted,
2053 /// i.e. end < start.
2054 /// </summary>
2055
2056 public LSL_String llDeleteSubString(string src, int start, int end)
2057 {
2058
2059 m_host.AddScriptLPS(1);
2060
2061 // Normalize indices (if negative).
2062 // After normlaization they may still be
2063 // negative, but that is now relative to
2064 // the start, rather than the end, of the
2065 // sequence.
2066 if (start < 0)
2067 {
2068 start = src.Length+start;
2069 }
2070 if (end < 0)
2071 {
2072 end = src.Length+end;
2073 }
2074 // Conventionally delimited substring
2075 if (start <= end)
2076 {
2077 // If both bounds are outside of the existing
2078 // string, then return unchanges.
2079 if (end < 0 || start >= src.Length)
2080 {
2081 return src;
2082 }
2083 // At least one bound is in-range, so we
2084 // need to clip the out-of-bound argument.
2085 if (start < 0)
2086 {
2087 start = 0;
2088 }
2089
2090 if (end >= src.Length)
2091 {
2092 end = src.Length-1;
2093 }
2094
2095 return src.Remove(start,end-start+1);
2096 }
2097 // Inverted substring
2098 else
2099 {
2100 // In this case, out of bounds means that
2101 // the existing string is part of the cut.
2102 if (start < 0 || end >= src.Length)
2103 {
2104 return String.Empty;
2105 }
2106
2107 if (end > 0)
2108 {
2109 if (start < src.Length)
2110 {
2111 return src.Remove(start).Remove(0,end+1);
2112 }
2113 else
2114 {
2115 return src.Remove(0,end+1);
2116 }
2117 }
2118 else
2119 {
2120 if (start < src.Length)
2121 {
2122 return src.Remove(start);
2123 }
2124 else
2125 {
2126 return src;
2127 }
2128 }
2129 }
2130 }
2131
2132 /// <summary>
2133 /// Insert string inserts the specified string identified by src
2134 /// at the index indicated by index. Index may be negative, in
2135 /// which case it is end-relative. The index may exceed either
2136 /// string bound, with the result being a concatenation.
2137 /// </summary>
2138
2139 public LSL_String llInsertString(string dest, int index, string src)
2140 {
2141
2142 m_host.AddScriptLPS(1);
2143
2144 // Normalize indices (if negative).
2145 // After normlaization they may still be
2146 // negative, but that is now relative to
2147 // the start, rather than the end, of the
2148 // sequence.
2149 if (index < 0)
2150 {
2151 index = dest.Length+index;
2152
2153 // Negative now means it is less than the lower
2154 // bound of the string.
2155
2156 if (index < 0)
2157 {
2158 return src+dest;
2159 }
2160
2161 }
2162
2163 if (index >= dest.Length)
2164 {
2165 return dest+src;
2166 }
2167
2168 // The index is in bounds.
2169 // In this case the index refers to the index that will
2170 // be assigned to the first character of the inserted string.
2171 // So unlike the other string operations, we do not add one
2172 // to get the correct string length.
2173 return dest.Substring(0,index)+src+dest.Substring(index);
2174
2175 }
2176
2177 public LSL_String llToUpper(string src)
2178 {
2179 m_host.AddScriptLPS(1);
2180 return src.ToUpper();
2181 }
2182
2183 public LSL_String llToLower(string src)
2184 {
2185 m_host.AddScriptLPS(1);
2186 return src.ToLower();
2187 }
2188
2189 public LSL_Integer llGiveMoney(string destination, int amount)
2190 {
2191 UUID invItemID=InventorySelf();
2192 if (invItemID == UUID.Zero)
2193 return 0;
2194
2195 m_host.AddScriptLPS(1);
2196
2197 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
2198 return 0;
2199
2200 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
2201 {
2202 LSLError("No permissions to give money");
2203 return 0;
2204 }
2205
2206 UUID toID=new UUID();
2207
2208 if (!UUID.TryParse(destination, out toID))
2209 {
2210 LSLError("Bad key in llGiveMoney");
2211 return 0;
2212 }
2213
2214 IMoneyModule money=World.RequestModuleInterface<IMoneyModule>();
2215
2216 if (money == null)
2217 {
2218 NotImplemented("llGiveMoney");
2219 return 0;
2220 }
2221
2222 bool result=money.ObjectGiveMoney(m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
2223
2224 if (result)
2225 return 1;
2226
2227 return 0;
2228 }
2229
2230 public void llMakeExplosion()
2231 {
2232 m_host.AddScriptLPS(1);
2233 Deprecated("llMakeExplosion");
2234 // ScriptSleep(100);
2235 }
2236
2237 public void llMakeFountain()
2238 {
2239 m_host.AddScriptLPS(1);
2240 Deprecated("llMakeFountain");
2241 // ScriptSleep(100);
2242 }
2243
2244 public void llMakeSmoke()
2245 {
2246 m_host.AddScriptLPS(1);
2247 Deprecated("llMakeSmoke");
2248 // ScriptSleep(100);
2249 }
2250
2251 public void llMakeFire()
2252 {
2253 m_host.AddScriptLPS(1);
2254 Deprecated("llMakeFire");
2255 // ScriptSleep(100);
2256 }
2257
2258 public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
2259 {
2260 m_host.AddScriptLPS(1);
2261
2262 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
2263 return;
2264 float dist = (float)llVecDist(llGetPos(), pos);
2265
2266 if (dist > m_ScriptDistanceFactor * 10.0f)
2267 return;
2268
2269 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
2270 {
2271 if (inv.Value.Name == inventory)
2272 {
2273 // make sure we're an object.
2274 if (inv.Value.InvType != (int)InventoryType.Object)
2275 {
2276 llSay(0, "Unable to create requested object. Object is missing from database.");
2277 return;
2278 }
2279
2280 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
2281
2282 // test if we're further away then 10m
2283 if (Util.GetDistanceTo(llpos, m_host.AbsolutePosition) > 10)
2284 return; // wiki says, if it's further away then 10m, silently fail.
2285
2286 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z);
2287
2288 // need the magnitude later
2289 float velmag = (float)Util.GetMagnitude(llvel);
2290
2291 SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), llvel, param);
2292
2293 // If either of these are null, then there was an unknown error.
2294 if (new_group == null)
2295 continue;
2296 if (new_group.RootPart == null)
2297 continue;
2298
2299 // objects rezzed with this method are die_at_edge by default.
2300 new_group.RootPart.SetDieAtEdge(true);
2301
2302 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2303 "object_rez", new Object[] {
2304 new LSL_String(
2305 new_group.RootPart.UUID.ToString()) },
2306 new DetectParams[0]));
2307
2308 float groupmass = new_group.GetMass();
2309
2310 //Recoil.
2311 llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0);
2312 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
2313 ScriptSleep((int)((groupmass * velmag) / 10));
2314 // ScriptSleep(100);
2315 return;
2316 }
2317 }
2318 llSay(0, "Could not find object " + inventory);
2319 }
2320
2321 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
2322 {
2323 llRezAtRoot(inventory, pos, vel, rot, param);
2324 }
2325
2326 public void llLookAt(LSL_Vector target, double strength, double damping)
2327 {
2328 m_host.AddScriptLPS(1);
2329 NotImplemented("llLookAt");
2330 }
2331
2332 public void llStopLookAt()
2333 {
2334 m_host.AddScriptLPS(1);
2335 NotImplemented("llStopLookAt");
2336 }
2337
2338 public void llSetTimerEvent(double sec)
2339 {
2340 m_host.AddScriptLPS(1);
2341 // Setting timer repeat
2342 AsyncCommands.TimerPlugin.SetTimerEvent(m_localID, m_itemID, sec);
2343 }
2344
2345 public void llSleep(double sec)
2346 {
2347 m_host.AddScriptLPS(1);
2348 Thread.Sleep((int)(sec * 1000));
2349 }
2350
2351 public LSL_Float llGetMass()
2352 {
2353 m_host.AddScriptLPS(1);
2354 return m_host.GetMass();
2355 }
2356
2357 public void llCollisionFilter(string name, string id, int accept)
2358 {
2359 m_host.AddScriptLPS(1);
2360 NotImplemented("llCollisionFilter");
2361 }
2362
2363 public void llTakeControls(int controls, int accept, int pass_on)
2364 {
2365 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2366 {
2367 return;
2368 }
2369
2370 if (m_host.TaskInventory[InventorySelf()].PermsGranter != UUID.Zero)
2371 {
2372 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter);
2373
2374 if (presence != null)
2375 {
2376 if ((m_host.TaskInventory[InventorySelf()].PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
2377 {
2378 presence.RegisterControlEventsToScript(controls, accept, pass_on, m_localID, m_itemID);
2379
2380 }
2381 }
2382 }
2383
2384 m_host.AddScriptLPS(1);
2385 }
2386
2387 public void llReleaseControls()
2388 {
2389 m_host.AddScriptLPS(1);
2390
2391 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2392 {
2393 return;
2394 }
2395
2396 if (m_host.TaskInventory[InventorySelf()].PermsGranter != UUID.Zero)
2397 {
2398 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter);
2399
2400 if (presence != null)
2401 {
2402 if ((m_host.TaskInventory[InventorySelf()].PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
2403 {
2404 // Unregister controls from Presence
2405 presence.UnRegisterControlEventsToScript(m_localID, m_itemID);
2406 // Remove Take Control permission.
2407 m_host.TaskInventory[InventorySelf()].PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
2408 }
2409 }
2410 }
2411 }
2412
2413 public void llAttachToAvatar(int attachment)
2414 {
2415 m_host.AddScriptLPS(1);
2416 NotImplemented("llAttachToAvatar");
2417 }
2418
2419 public void llDetachFromAvatar()
2420 {
2421 m_host.AddScriptLPS(1);
2422 NotImplemented("llDetachFromAvatar");
2423 }
2424
2425 public void llTakeCamera(string avatar)
2426 {
2427 m_host.AddScriptLPS(1);
2428 Deprecated("llTakeCamera");
2429 }
2430
2431 public void llReleaseCamera(string avatar)
2432 {
2433 m_host.AddScriptLPS(1);
2434 Deprecated("llReleaseCamera");
2435 }
2436
2437 public LSL_String llGetOwner()
2438 {
2439 m_host.AddScriptLPS(1);
2440
2441 return m_host.ObjectOwner.ToString();
2442 }
2443
2444 public void llInstantMessage(string user, string message)
2445 {
2446 m_host.AddScriptLPS(1);
2447
2448 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
2449 // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
2450 // but I don't think we have a list of scenes available from here.
2451 // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
2452
2453 // user is a UUID
2454
2455 // TODO: figure out values for client, fromSession, and imSessionID
2456 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
2457 UUID friendTransactionID = UUID.Random();
2458
2459 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
2460
2461 GridInstantMessage msg = new GridInstantMessage();
2462 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
2463 msg.fromAgentSession = new Guid(friendTransactionID.ToString());// fromAgentSession.UUID;
2464 msg.toAgentID = new Guid(user); // toAgentID.Guid;
2465 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
2466// Console.WriteLine("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
2467// Console.WriteLine("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
2468 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp;
2469 //if (client != null)
2470 //{
2471 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
2472 //}
2473 //else
2474 //{
2475 // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it
2476 //}
2477 msg.message = message;
2478 msg.dialog = (byte)19; // messgage from script ??? // dialog;
2479 msg.fromGroup = false;// fromGroup;
2480 msg.offline = (byte)0; //offline;
2481 msg.ParentEstateID = 0; //ParentEstateID;
2482 msg.Position = Vector3.Zero;// new Vector3(m_host.AbsolutePosition);
2483 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
2484 msg.binaryBucket = new byte[0];// binaryBucket;
2485 World.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
2486 // ScriptSleep(2000);
2487 }
2488
2489 public void llEmail(string address, string subject, string message)
2490 {
2491 m_host.AddScriptLPS(1);
2492 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
2493 if (emailModule == null)
2494 return;
2495
2496 emailModule.SendEmail(m_host.UUID, address, subject, message);
2497 // ScriptSleep(20000);
2498 }
2499
2500 public void llGetNextEmail(string address, string subject)
2501 {
2502 m_host.AddScriptLPS(1);
2503 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
2504 if (emailModule == null)
2505 return;
2506 Email email;
2507
2508 email = emailModule.GetNextEmail(m_host.UUID, address, subject);
2509
2510 if (email == null)
2511 return;
2512
2513 m_ScriptEngine.PostObjectEvent(m_host.LocalId,
2514 new EventParams("email",
2515 new Object[] {
2516 new LSL_String(email.time),
2517 new LSL_String(email.sender),
2518 new LSL_String(email.subject),
2519 new LSL_String(email.message),
2520 new LSL_Integer(email.numLeft)},
2521 new DetectParams[0]));
2522
2523 }
2524
2525 public LSL_String llGetKey()
2526 {
2527 m_host.AddScriptLPS(1);
2528 return m_host.UUID.ToString();
2529 }
2530
2531 public void llSetBuoyancy(double buoyancy)
2532 {
2533 m_host.AddScriptLPS(1);
2534 if (m_host.ParentGroup != null)
2535 {
2536 if (m_host.ParentGroup.RootPart != null)
2537 {
2538 m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy);
2539 }
2540 }
2541 }
2542
2543
2544
2545 public void llSetHoverHeight(double height, int water, double tau)
2546 {
2547 m_host.AddScriptLPS(1);
2548 NotImplemented("llSetHoverHeight");
2549 }
2550
2551 public void llStopHover()
2552 {
2553 m_host.AddScriptLPS(1);
2554 NotImplemented("llStopHover");
2555 }
2556
2557 public void llMinEventDelay(double delay)
2558 {
2559 m_host.AddScriptLPS(1);
2560 NotImplemented("llMinEventDelay");
2561 }
2562
2563 public void llSoundPreload()
2564 {
2565 m_host.AddScriptLPS(1);
2566 Deprecated("llSoundPreload");
2567 }
2568
2569 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
2570 {
2571 m_host.AddScriptLPS(1);
2572 NotImplemented("llRotLookAt");
2573 }
2574
2575 public LSL_Integer llStringLength(string str)
2576 {
2577 m_host.AddScriptLPS(1);
2578 if (str.Length > 0)
2579 {
2580 return str.Length;
2581 }
2582 else
2583 {
2584 return 0;
2585 }
2586 }
2587
2588 public void llStartAnimation(string anim)
2589 {
2590 m_host.AddScriptLPS(1);
2591
2592 UUID invItemID=InventorySelf();
2593 if (invItemID == UUID.Zero)
2594 return;
2595
2596 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
2597 return;
2598
2599 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
2600 {
2601 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter);
2602
2603 if (presence != null)
2604 {
2605 // Do NOT try to parse UUID, animations cannot be triggered by ID
2606 UUID animID=InventoryKey(anim, (int)AssetType.Animation);
2607 if (animID == UUID.Zero)
2608 presence.AddAnimation(anim);
2609 else
2610 presence.AddAnimation(animID);
2611 }
2612 }
2613 }
2614
2615 public void llStopAnimation(string anim)
2616 {
2617 m_host.AddScriptLPS(1);
2618
2619 UUID invItemID=InventorySelf();
2620 if (invItemID == UUID.Zero)
2621 return;
2622
2623 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
2624 return;
2625
2626 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
2627 {
2628 UUID animID = new UUID();
2629
2630 if (!UUID.TryParse(anim, out animID))
2631 {
2632 animID=InventoryKey(anim);
2633 }
2634
2635 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter);
2636
2637 if (presence != null)
2638 {
2639 if (animID == UUID.Zero)
2640 presence.RemoveAnimation(anim);
2641 else
2642 presence.RemoveAnimation(animID);
2643 }
2644 }
2645 }
2646
2647 public void llPointAt()
2648 {
2649 m_host.AddScriptLPS(1);
2650 NotImplemented("llPointAt");
2651 }
2652
2653 public void llStopPointAt()
2654 {
2655 m_host.AddScriptLPS(1);
2656 NotImplemented("llStopPointAt");
2657 }
2658
2659 public void llTargetOmega(LSL_Vector axis, double spinrate, double gain)
2660 {
2661 m_host.AddScriptLPS(1);
2662 m_host.RotationalVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
2663 m_host.AngularVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
2664 m_host.ScheduleTerseUpdate();
2665 m_host.SendTerseUpdateToAllClients();
2666 m_host.ParentGroup.HasGroupChanged = true;
2667 }
2668
2669 public LSL_Integer llGetStartParameter()
2670 {
2671 m_host.AddScriptLPS(1);
2672 return m_ScriptEngine.GetStartParameter(m_itemID);
2673 }
2674
2675 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
2676 {
2677 m_host.AddScriptLPS(1);
2678 NotImplemented("llGodLikeRezObject");
2679 }
2680
2681 public void llRequestPermissions(string agent, int perm)
2682 {
2683 UUID agentID=new UUID();
2684
2685 if (!UUID.TryParse(agent, out agentID))
2686 return;
2687
2688 UUID invItemID=InventorySelf();
2689
2690 if (invItemID == UUID.Zero)
2691 return; // Not in a prim? How??
2692
2693 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
2694 {
2695 llReleaseControls();
2696
2697 m_host.TaskInventory[invItemID].PermsGranter=UUID.Zero;
2698 m_host.TaskInventory[invItemID].PermsMask=0;
2699
2700 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2701 "run_time_permissions", new Object[] {
2702 new LSL_Integer(0) },
2703 new DetectParams[0]));
2704
2705 return;
2706 }
2707
2708 if ( m_host.TaskInventory[invItemID].PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
2709 llReleaseControls();
2710
2711 m_host.AddScriptLPS(1);
2712
2713 if (m_host.ParentGroup.RootPart.IsAttachment && agent == m_host.ParentGroup.RootPart.AttachedAvatar)
2714 {
2715 // When attached, certain permissions are implicit if requested from owner
2716 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
2717 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
2718 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
2719 ScriptBaseClass.PERMISSION_ATTACH;
2720
2721 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
2722 {
2723 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2724 m_host.TaskInventory[invItemID].PermsMask=perm;
2725
2726 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2727 "run_time_permissions", new Object[] {
2728 new LSL_Integer(perm) },
2729 new DetectParams[0]));
2730
2731 return;
2732 }
2733 }
2734 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar
2735 {
2736 // When agent is sitting, certain permissions are implicit if requested from sitting agent
2737 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
2738 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
2739 ScriptBaseClass.PERMISSION_TRACK_CAMERA;
2740
2741 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
2742 {
2743 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2744 m_host.TaskInventory[invItemID].PermsMask=perm;
2745
2746 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2747 "run_time_permissions", new Object[] {
2748 new LSL_Integer(perm) },
2749 new DetectParams[0]));
2750
2751 return;
2752 }
2753 }
2754
2755 ScenePresence presence = World.GetScenePresence(agentID);
2756
2757 if (presence != null)
2758 {
2759 string ownerName=resolveName(m_host.ParentGroup.RootPart.OwnerID);
2760 if (ownerName == String.Empty)
2761 ownerName="(hippos)";
2762
2763 if (!m_waitingForScriptAnswer)
2764 {
2765 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2766 m_host.TaskInventory[invItemID].PermsMask=0;
2767 presence.ControllingClient.OnScriptAnswer+=handleScriptAnswer;
2768 m_waitingForScriptAnswer=true;
2769 }
2770
2771 presence.ControllingClient.SendScriptQuestion(m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, invItemID, perm);
2772 return;
2773 }
2774
2775 // Requested agent is not in range, refuse perms
2776 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2777 "run_time_permissions", new Object[] {
2778 new LSL_Integer(0) },
2779 new DetectParams[0]));
2780 }
2781
2782 void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer)
2783 {
2784 if (taskID != m_host.UUID)
2785 return;
2786
2787 UUID invItemID=InventorySelf();
2788
2789 if (invItemID == UUID.Zero)
2790 return;
2791
2792 client.OnScriptAnswer-=handleScriptAnswer;
2793 m_waitingForScriptAnswer=false;
2794
2795 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
2796 llReleaseControls();
2797
2798 m_host.TaskInventory[invItemID].PermsMask=answer;
2799 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2800 "run_time_permissions", new Object[] {
2801 new LSL_Integer(answer) },
2802 new DetectParams[0]));
2803 }
2804
2805 public LSL_String llGetPermissionsKey()
2806 {
2807 m_host.AddScriptLPS(1);
2808
2809 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2810 {
2811 if (item.Type == 10 && item.ItemID == m_itemID)
2812 {
2813 return item.PermsGranter.ToString();
2814 }
2815 }
2816
2817 return UUID.Zero.ToString();
2818 }
2819
2820 public LSL_Integer llGetPermissions()
2821 {
2822 m_host.AddScriptLPS(1);
2823
2824 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2825 {
2826 if (item.Type == 10 && item.ItemID == m_itemID)
2827 {
2828 return item.PermsMask;
2829 }
2830 }
2831
2832 return 0;
2833 }
2834
2835 public LSL_Integer llGetLinkNumber()
2836 {
2837 m_host.AddScriptLPS(1);
2838
2839 if (m_host.ParentGroup.Children.Count > 1)
2840 {
2841 return m_host.LinkNum;
2842 }
2843 else
2844 {
2845 return 0;
2846 }
2847 }
2848
2849 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
2850 {
2851 List<SceneObjectPart> parts = GetLinkParts(linknumber);
2852
2853 foreach (SceneObjectPart part in parts)
2854 SetColor(part, color, face);
2855 }
2856
2857 public void llCreateLink(string target, int parent)
2858 {
2859 m_host.AddScriptLPS(1);
2860 UUID invItemID = InventorySelf();
2861 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0) {
2862 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
2863 return;
2864 }
2865 IClientAPI client = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter).ControllingClient;
2866 SceneObjectPart targetPart = World.GetSceneObjectPart(target);
2867 SceneObjectGroup parentPrim = null, childPrim = null;
2868 if (targetPart != null)
2869 {
2870 if (parent != 0) {
2871 parentPrim = m_host.ParentGroup;
2872 childPrim = targetPart.ParentGroup;
2873 }
2874 else
2875 {
2876 parentPrim = targetPart.ParentGroup;
2877 childPrim = m_host.ParentGroup;
2878 }
2879// byte uf = childPrim.RootPart.UpdateFlag;
2880 childPrim.RootPart.UpdateFlag = 0;
2881 parentPrim.LinkToGroup(childPrim);
2882// if (uf != (Byte)0)
2883// parent.RootPart.UpdateFlag = uf;
2884 }
2885 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
2886 parentPrim.RootPart.AddFlag(PrimFlags.CreateSelected);
2887 parentPrim.HasGroupChanged = true;
2888 parentPrim.ScheduleGroupForFullUpdate();
2889 parentPrim.GetProperties(client);
2890
2891 ScriptSleep(1000);
2892 }
2893
2894 public void llBreakLink(int linknum)
2895 {
2896 m_host.AddScriptLPS(1);
2897 UUID invItemID = InventorySelf();
2898 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0)
2899 {
2900 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
2901 return;
2902 }
2903 if (linknum < ScriptBaseClass.LINK_THIS)
2904 return;
2905 SceneObjectGroup parentPrim = m_host.ParentGroup;
2906 SceneObjectPart childPrim = null;
2907 switch (linknum)
2908 {
2909 case ScriptBaseClass.LINK_ROOT:
2910 break;
2911 case ScriptBaseClass.LINK_SET:
2912 case ScriptBaseClass.LINK_ALL_OTHERS:
2913 case ScriptBaseClass.LINK_ALL_CHILDREN:
2914 case ScriptBaseClass.LINK_THIS:
2915 foreach (SceneObjectPart part in parentPrim.Children.Values)
2916 {
2917 if (part.UUID != m_host.UUID)
2918 {
2919 childPrim = part;
2920 break;
2921 }
2922 }
2923 break;
2924 default:
2925 childPrim = parentPrim.GetLinkNumPart(linknum);
2926 if (childPrim.UUID == m_host.UUID)
2927 childPrim = null;
2928 break;
2929 }
2930 if (linknum == ScriptBaseClass.LINK_ROOT)
2931 {
2932 // Restructuring Multiple Prims.
2933 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
2934 parts.Remove(parentPrim.RootPart);
2935 foreach (SceneObjectPart part in parts)
2936 {
2937 parentPrim.DelinkFromGroup(part.LocalId, true);
2938 }
2939 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
2940 if (parts.Count > 0) {
2941 SceneObjectPart newRoot = parts[0];
2942 parts.Remove(newRoot);
2943 foreach (SceneObjectPart part in parts)
2944 {
2945 part.UpdateFlag = 0;
2946 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
2947 }
2948 }
2949 }
2950 else
2951 {
2952 if (childPrim == null)
2953 return;
2954 parentPrim.DelinkFromGroup(childPrim.LocalId, true);
2955 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
2956 }
2957 }
2958
2959 public void llBreakAllLinks()
2960 {
2961 m_host.AddScriptLPS(1);
2962 SceneObjectGroup parentPrim = m_host.ParentGroup;
2963 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
2964 parts.Remove(parentPrim.RootPart);
2965 foreach (SceneObjectPart part in parts)
2966 {
2967 parentPrim.DelinkFromGroup(part.LocalId, true);
2968 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
2969 }
2970 }
2971
2972 public LSL_String llGetLinkKey(int linknum)
2973 {
2974 m_host.AddScriptLPS(1);
2975 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
2976 if (part != null)
2977 {
2978 return part.UUID.ToString();
2979 }
2980 else
2981 {
2982 return UUID.Zero.ToString();
2983 }
2984 }
2985
2986 public LSL_String llGetLinkName(int linknum)
2987 {
2988 m_host.AddScriptLPS(1);
2989 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
2990 if (part != null)
2991 {
2992 return part.Name;
2993 }
2994 else
2995 {
2996 return "";
2997 }
2998 }
2999
3000 public LSL_Integer llGetInventoryNumber(int type)
3001 {
3002 m_host.AddScriptLPS(1);
3003 int count = 0;
3004 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3005 {
3006 if (inv.Value.Type == type || type == -1)
3007 {
3008 count = count + 1;
3009 }
3010 }
3011 return count;
3012 }
3013
3014 public LSL_String llGetInventoryName(int type, int number)
3015 {
3016 m_host.AddScriptLPS(1);
3017 ArrayList keys = new ArrayList();
3018 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3019 {
3020 if (inv.Value.Type == type || type == -1)
3021 {
3022 keys.Add(inv.Value.Name);
3023 }
3024 }
3025 if (keys.Count == 0)
3026 {
3027 return String.Empty;
3028 }
3029 keys.Sort();
3030 if (keys.Count > number)
3031 {
3032 return (string)keys[number];
3033 }
3034 return String.Empty;
3035 }
3036
3037 public void llSetScriptState(string name, int run)
3038 {
3039 UUID item;
3040
3041 m_host.AddScriptLPS(1);
3042
3043 // These functions are supposed to be robust,
3044 // so get the state one step at a time.
3045
3046 if ((item = ScriptByName(name)) != UUID.Zero)
3047 {
3048 m_ScriptEngine.SetScriptState(item, run == 0 ? false : true);
3049 }
3050 else
3051 {
3052 ShoutError("llSetScriptState: script "+name+" not found");
3053 }
3054 }
3055
3056 public LSL_Float llGetEnergy()
3057 {
3058 m_host.AddScriptLPS(1);
3059 // TODO: figure out real energy value
3060 return 1.0f;
3061 }
3062
3063 public void llGiveInventory(string destination, string inventory)
3064 {
3065 m_host.AddScriptLPS(1);
3066 bool found = false;
3067 UUID destId = UUID.Zero;
3068 UUID objId = UUID.Zero;
3069
3070 if (!UUID.TryParse(destination, out destId))
3071 {
3072 llSay(0, "Could not parse key " + destination);
3073 return;
3074 }
3075
3076 // move the first object found with this inventory name
3077 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3078 {
3079 if (inv.Value.Name == inventory)
3080 {
3081 found = true;
3082 objId = inv.Key;
3083 break;
3084 }
3085 }
3086
3087 if (!found)
3088 {
3089 llSay(0, String.Format("Could not find object '{0}'", inventory));
3090 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3091 }
3092
3093 // check if destination is an avatar
3094 if (World.GetScenePresence(destId) != null)
3095 {
3096 // destination is an avatar
3097 World.MoveTaskInventoryItem(destId, null, m_host, objId);
3098 }
3099 else
3100 {
3101 // destination is an object
3102 World.MoveTaskInventoryItem(destId, m_host, objId);
3103 }
3104 // ScriptSleep(3000);
3105 }
3106
3107 public void llRemoveInventory(string name)
3108 {
3109 m_host.AddScriptLPS(1);
3110 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3111 {
3112 if (item.Name == name)
3113 {
3114 m_host.RemoveInventoryItem(item.ItemID);
3115 return;
3116 }
3117 }
3118 }
3119
3120 public void llSetText(string text, LSL_Vector color, double alpha)
3121 {
3122 m_host.AddScriptLPS(1);
3123 Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f),
3124 Util.Clip((float)color.y, 0.0f, 1.0f),
3125 Util.Clip((float)color.z, 0.0f, 1.0f));
3126 m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
3127 m_host.ParentGroup.HasGroupChanged = true;
3128 }
3129
3130 public LSL_Float llWater(LSL_Vector offset)
3131 {
3132 m_host.AddScriptLPS(1);
3133 return World.RegionInfo.RegionSettings.WaterHeight;
3134 }
3135
3136 public void llPassTouches(int pass)
3137 {
3138 m_host.AddScriptLPS(1);
3139 NotImplemented("llPassTouches");
3140 }
3141
3142 public LSL_String llRequestAgentData(string id, int data)
3143 {
3144 m_host.AddScriptLPS(1);
3145
3146 UserProfileData userProfile =
3147 World.CommsManager.UserService.GetUserProfile(id);
3148
3149 UserAgentData userAgent =
3150 World.CommsManager.UserService.GetAgentByUUID(id);
3151
3152 if (userProfile == null || userAgent == null)
3153 return UUID.Zero.ToString();
3154
3155 string reply = String.Empty;
3156
3157 switch (data)
3158 {
3159 case 1: // DATA_ONLINE (0|1)
3160 // TODO: implement fetching of this information
3161 if (userProfile.CurrentAgent.AgentOnline)
3162 reply = "1";
3163 else
3164 reply = "0";
3165 break;
3166 case 2: // DATA_NAME (First Last)
3167 reply = userProfile.FirstName + " " + userProfile.SurName;
3168 break;
3169 case 3: // DATA_BORN (YYYY-MM-DD)
3170 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
3171 born = born.AddSeconds(userProfile.Created);
3172 reply = born.ToString("yyyy-MM-dd");
3173 break;
3174 case 4: // DATA_RATING (0,0,0,0,0,0)
3175 reply = "0,0,0,0,0,0";
3176 break;
3177 case 8: // DATA_PAYINFO (0|1|2|3)
3178 reply = "0";
3179 break;
3180 default:
3181 return UUID.Zero.ToString(); // Raise no event
3182 }
3183
3184 UUID rq = UUID.Random();
3185
3186 UUID tid = AsyncCommands.
3187 DataserverPlugin.RegisterRequest(m_localID,
3188 m_itemID, rq.ToString());
3189
3190 AsyncCommands.
3191 DataserverPlugin.DataserverReply(rq.ToString(), reply);
3192
3193 // ScriptSleep(100);
3194 return tid.ToString();
3195 }
3196
3197 public LSL_String llRequestInventoryData(string name)
3198 {
3199 m_host.AddScriptLPS(1);
3200
3201 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3202 {
3203 if (item.Type == 3 && item.Name == name)
3204 {
3205 UUID tid = AsyncCommands.
3206 DataserverPlugin.RegisterRequest(m_localID,
3207 m_itemID, item.AssetID.ToString());
3208
3209 Vector3 region = new Vector3(
3210 World.RegionInfo.RegionLocX * Constants.RegionSize,
3211 World.RegionInfo.RegionLocY * Constants.RegionSize,
3212 0);
3213
3214 World.AssetCache.GetAsset(item.AssetID,
3215 delegate(UUID i, AssetBase a)
3216 {
3217 AssetLandmark lm = new AssetLandmark(a);
3218
3219 float rx = (uint)(lm.RegionHandle >> 32);
3220 float ry = (uint)lm.RegionHandle;
3221 region = lm.Position + new Vector3(rx, ry, 0) - region;
3222
3223 string reply = region.ToString();
3224 AsyncCommands.
3225 DataserverPlugin.DataserverReply(i.ToString(),
3226 reply);
3227 }, false);
3228
3229 // ScriptSleep(1000);
3230 return tid.ToString();
3231 }
3232 }
3233 // ScriptSleep(1000);
3234 return String.Empty;
3235 }
3236
3237 public void llSetDamage(double damage)
3238 {
3239 m_host.AddScriptLPS(1);
3240 NotImplemented("llSetDamage");
3241 }
3242
3243 public void llTeleportAgentHome(string agent)
3244 {
3245 m_host.AddScriptLPS(1);
3246 UUID agentId = new UUID();
3247 if (UUID.TryParse(agent, out agentId))
3248 {
3249 ScenePresence presence = World.GetScenePresence(agentId);
3250 if (presence != null)
3251 {
3252 // agent must be over the owners land
3253 if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y))
3254 World.TeleportClientHome(agentId, presence.ControllingClient);
3255 }
3256 }
3257 // ScriptSleep(5000);
3258 }
3259
3260 public void llTextBox(string avatar, string message, int chat_channel)
3261 {
3262 m_host.AddScriptLPS(1);
3263 NotImplemented("llTextBox");
3264 }
3265
3266 public void llModifyLand(int action, int brush)
3267 {
3268 m_host.AddScriptLPS(1);
3269 World.ExternalChecks.ExternalChecksCanTerraformLand(m_host.OwnerID, new Vector3(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, 0));
3270 }
3271
3272 public void llCollisionSound(string impact_sound, double impact_volume)
3273 {
3274 m_host.AddScriptLPS(1);
3275 NotImplemented("llCollisionSound");
3276 }
3277
3278 public void llCollisionSprite(string impact_sprite)
3279 {
3280 m_host.AddScriptLPS(1);
3281 NotImplemented("llCollisionSprite");
3282 }
3283
3284 public LSL_String llGetAnimation(string id)
3285 {
3286 m_host.AddScriptLPS(1);
3287 NotImplemented("llGetAnimation");
3288 return String.Empty;
3289 }
3290
3291 public void llResetScript()
3292 {
3293 m_host.AddScriptLPS(1);
3294 m_ScriptEngine.ApiResetScript(m_itemID);
3295 throw new EventAbortException();
3296 }
3297
3298 public void llMessageLinked(int linknum, int num, string msg, string id)
3299 {
3300
3301 m_host.AddScriptLPS(1);
3302
3303 // uint partLocalID;
3304 UUID partItemID;
3305
3306 switch ((int)linknum)
3307 {
3308
3309 case (int)ScriptBaseClass.LINK_ROOT:
3310
3311 SceneObjectPart part = m_host.ParentGroup.RootPart;
3312
3313 foreach (TaskInventoryItem item in part.TaskInventory.Values)
3314 {
3315 if (item.Type == 10)
3316 {
3317 // partLocalID = part.LocalId;
3318 partItemID = item.ItemID;
3319
3320 object[] resobj = new object[]
3321 {
3322 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3323 };
3324
3325 m_ScriptEngine.PostScriptEvent(partItemID,
3326 new EventParams("link_message",
3327 resobj, new DetectParams[0]));
3328 }
3329 }
3330
3331 break;
3332
3333 case (int)ScriptBaseClass.LINK_SET:
3334
3335 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
3336 {
3337
3338 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
3339 {
3340 if (item.Type == 10)
3341 {
3342 // partLocalID = partInst.LocalId;
3343 partItemID = item.ItemID;
3344 Object[] resobj = new object[]
3345 {
3346 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3347 };
3348
3349 m_ScriptEngine.PostScriptEvent(partItemID,
3350 new EventParams("link_message",
3351 resobj, new DetectParams[0]));
3352 }
3353 }
3354 }
3355
3356 break;
3357
3358 case (int)ScriptBaseClass.LINK_ALL_OTHERS:
3359
3360 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
3361 {
3362
3363 if (partInst.LocalId != m_host.LocalId)
3364 {
3365
3366 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
3367 {
3368 if (item.Type == 10)
3369 {
3370 // partLocalID = partInst.LocalId;
3371 partItemID = item.ItemID;
3372 Object[] resobj = new object[]
3373 {
3374 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3375 };
3376
3377 m_ScriptEngine.PostScriptEvent(partItemID,
3378 new EventParams("link_message",
3379 resobj, new DetectParams[0]));
3380 }
3381 }
3382
3383 }
3384 }
3385
3386 break;
3387
3388 case (int)ScriptBaseClass.LINK_ALL_CHILDREN:
3389
3390 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
3391 {
3392
3393 if (partInst.LocalId != m_host.ParentGroup.RootPart.LocalId)
3394 {
3395
3396 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
3397 {
3398 if (item.Type == 10)
3399 {
3400 // partLocalID = partInst.LocalId;
3401 partItemID = item.ItemID;
3402 Object[] resobj = new object[]
3403 {
3404 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3405 };
3406
3407 m_ScriptEngine.PostScriptEvent(partItemID,
3408 new EventParams("link_message",
3409 resobj, new DetectParams[0]));
3410 }
3411 }
3412
3413 }
3414 }
3415
3416 break;
3417
3418 case (int)ScriptBaseClass.LINK_THIS:
3419
3420 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3421 {
3422 if (item.Type == 10)
3423 {
3424 partItemID = item.ItemID;
3425
3426 object[] resobj = new object[]
3427 {
3428 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3429 };
3430
3431 m_ScriptEngine.PostScriptEvent(partItemID,
3432 new EventParams("link_message",
3433 resobj, new DetectParams[0]));
3434 }
3435 }
3436
3437 break;
3438
3439 default:
3440
3441 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
3442 {
3443
3444 if ((partInst.LinkNum) == linknum)
3445 {
3446
3447 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
3448 {
3449 if (item.Type == 10)
3450 {
3451 // partLocalID = partInst.LocalId;
3452 partItemID = item.ItemID;
3453 Object[] resObjDef = new object[]
3454 {
3455 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3456 };
3457
3458 m_ScriptEngine.PostScriptEvent(partItemID,
3459 new EventParams("link_message",
3460 resObjDef, new DetectParams[0]));
3461 }
3462 }
3463
3464 }
3465 }
3466
3467 break;
3468
3469 }
3470
3471 }
3472
3473 public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local)
3474 {
3475 m_host.AddScriptLPS(1);
3476 SceneObjectPart targ = World.GetSceneObjectPart(target);
3477 if (targ == null)
3478 return;
3479 targ.ApplyImpulse(new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z), local != 0);
3480 }
3481
3482 public void llPassCollisions(int pass)
3483 {
3484 m_host.AddScriptLPS(1);
3485 NotImplemented("llPassCollisions");
3486 }
3487
3488 public LSL_String llGetScriptName()
3489 {
3490
3491 string result = String.Empty;
3492
3493 m_host.AddScriptLPS(1);
3494
3495 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3496 {
3497 if (item.Type == 10 && item.ItemID == m_itemID)
3498 {
3499 result = item.Name!=null?item.Name:String.Empty;
3500 break;
3501 }
3502 }
3503
3504 return result;
3505
3506 }
3507
3508 // this function to understand which shape it is (taken from meshmerizer)
3509 // quite useful can be used by meshmerizer to have a centralized point of understanding the shape
3510 // except that it refers to scripting constants
3511 private int getScriptPrimType(PrimitiveBaseShape primShape)
3512 {
3513 if (primShape.SculptEntry)
3514 return ScriptBaseClass.PRIM_TYPE_SCULPT;
3515 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
3516 {
3517 if (primShape.PathCurve == (byte)Extrusion.Straight)
3518 return ScriptBaseClass.PRIM_TYPE_BOX;
3519 else if (primShape.PathCurve == (byte)Extrusion.Curve1)
3520 return ScriptBaseClass.PRIM_TYPE_TUBE;
3521 }
3522 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
3523 {
3524 if (primShape.PathCurve == (byte)Extrusion.Straight)
3525 return ScriptBaseClass.PRIM_TYPE_CYLINDER;
3526 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
3527 else if (primShape.PathCurve == (byte)Extrusion.Curve1)
3528 return ScriptBaseClass.PRIM_TYPE_TORUS;
3529 }
3530 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
3531 {
3532 if (primShape.PathCurve == (byte)Extrusion.Curve1 || primShape.PathCurve == (byte)Extrusion.Curve2)
3533 return ScriptBaseClass.PRIM_TYPE_SPHERE;
3534 }
3535 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
3536 {
3537 if (primShape.PathCurve == (byte)Extrusion.Straight)
3538 return ScriptBaseClass.PRIM_TYPE_PRISM;
3539 else if (primShape.PathCurve == (byte)Extrusion.Curve1)
3540 return ScriptBaseClass.PRIM_TYPE_RING;
3541 }
3542 return ScriptBaseClass.PRIM_TYPE_BOX;
3543 }
3544
3545 // Helper functions to understand if object has cut, hollow, dimple, and other affecting number of faces
3546 private void hasCutHollowDimpleProfileCut(int primType, PrimitiveBaseShape shape, out bool hasCut, out bool hasHollow,
3547 out bool hasDimple, out bool hasProfileCut)
3548 {
3549 if (primType == ScriptBaseClass.PRIM_TYPE_BOX
3550 ||
3551 primType == ScriptBaseClass.PRIM_TYPE_CYLINDER
3552 ||
3553 primType == ScriptBaseClass.PRIM_TYPE_PRISM)
3554
3555 hasCut = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0);
3556 else
3557 hasCut = (shape.PathBegin > 0) || (shape.PathEnd > 0);
3558
3559 hasHollow = shape.ProfileHollow > 0;
3560 hasDimple = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); // taken from llSetPrimitiveParms
3561 hasProfileCut = hasDimple; // is it the same thing?
3562
3563 }
3564
3565 public LSL_Integer llGetNumberOfSides()
3566 {
3567 m_host.AddScriptLPS(1);
3568
3569 return GetNumberOfSides(m_host);
3570 }
3571
3572 private int GetNumberOfSides(SceneObjectPart part)
3573 {
3574 int ret = 0;
3575 bool hasCut;
3576 bool hasHollow;
3577 bool hasDimple;
3578 bool hasProfileCut;
3579
3580 int primType = getScriptPrimType(part.Shape);
3581 hasCutHollowDimpleProfileCut(primType, part.Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut);
3582
3583 switch (primType)
3584 {
3585 case ScriptBaseClass.PRIM_TYPE_BOX:
3586 ret = 6;
3587 if (hasCut) ret += 2;
3588 if (hasHollow) ret += 1;
3589 break;
3590 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
3591 ret = 3;
3592 if (hasCut) ret += 2;
3593 if (hasHollow) ret += 1;
3594 break;
3595 case ScriptBaseClass.PRIM_TYPE_PRISM:
3596 ret = 5;
3597 if (hasCut) ret += 2;
3598 if (hasHollow) ret += 1;
3599 break;
3600 case ScriptBaseClass.PRIM_TYPE_SPHERE:
3601 ret = 1;
3602 if (hasCut) ret += 2;
3603 if (hasDimple) ret += 2;
3604 if (hasHollow) ret += 3; // Emulate lsl on secondlife (according to documentation it should have added only +1)
3605 break;
3606 case ScriptBaseClass.PRIM_TYPE_TORUS:
3607 ret = 1;
3608 if (hasCut) ret += 2;
3609 if (hasProfileCut) ret += 2;
3610 if (hasHollow) ret += 1;
3611 break;
3612 case ScriptBaseClass.PRIM_TYPE_TUBE:
3613 ret = 4;
3614 if (hasCut) ret += 2;
3615 if (hasProfileCut) ret += 2;
3616 if (hasHollow) ret += 1;
3617 break;
3618 case ScriptBaseClass.PRIM_TYPE_RING:
3619 ret = 3;
3620 if (hasCut) ret += 2;
3621 if (hasProfileCut) ret += 2;
3622 if (hasHollow) ret += 1;
3623 break;
3624 case ScriptBaseClass.PRIM_TYPE_SCULPT:
3625 ret = 1;
3626 break;
3627 }
3628 return ret;
3629 }
3630
3631
3632 /* The new / changed functions were tested with the following LSL script:
3633
3634 default
3635 {
3636 state_entry()
3637 {
3638 rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD);
3639
3640 llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot));
3641 llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG));
3642
3643 // convert back and forth between quaternion <-> vector and angle
3644
3645 rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot));
3646
3647 llOwnerSay("Old rotation was: "+(string) rot);
3648 llOwnerSay("re-converted rotation is: "+(string) newrot);
3649
3650 llSetRot(rot); // to check the parameters in the prim
3651 }
3652 }
3653 */
3654
3655
3656
3657 // Xantor 29/apr/2008
3658 // Returns rotation described by rotating angle radians about axis.
3659 // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
3660 public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle)
3661 {
3662 m_host.AddScriptLPS(1);
3663
3664 double x, y, z, s, t;
3665
3666 s = Math.Cos(angle / 2);
3667 t = Math.Sin(angle / 2); // temp value to avoid 2 more sin() calcs
3668 x = axis.x * t;
3669 y = axis.y * t;
3670 z = axis.z * t;
3671
3672 return new LSL_Rotation(x,y,z,s);
3673 }
3674
3675
3676 // Xantor 29/apr/2008
3677 // converts a Quaternion to X,Y,Z axis rotations
3678 public LSL_Vector llRot2Axis(LSL_Rotation rot)
3679 {
3680 m_host.AddScriptLPS(1);
3681 double x,y,z;
3682
3683 if (rot.s > 1) // normalization needed
3684 {
3685 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
3686 rot.z * rot.z + rot.s * rot.s);
3687
3688 rot.x /= length;
3689 rot.y /= length;
3690 rot.z /= length;
3691 rot.s /= length;
3692
3693 }
3694
3695 // double angle = 2 * Math.Acos(rot.s);
3696 double s = Math.Sqrt(1 - rot.s * rot.s);
3697 if (s < 0.001)
3698 {
3699 x = 1;
3700 y = z = 0;
3701 }
3702 else
3703 {
3704 x = rot.x / s; // normalise axis
3705 y = rot.y / s;
3706 z = rot.z / s;
3707 }
3708
3709 return new LSL_Vector(x,y,z);
3710 }
3711
3712
3713 // Returns the angle of a quaternion (see llRot2Axis for the axis)
3714 public LSL_Float llRot2Angle(LSL_Rotation rot)
3715 {
3716 m_host.AddScriptLPS(1);
3717
3718 if (rot.s > 1) // normalization needed
3719 {
3720 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
3721 rot.z * rot.z + rot.s * rot.s);
3722
3723 rot.x /= length;
3724 rot.y /= length;
3725 rot.z /= length;
3726 rot.s /= length;
3727 }
3728
3729 double angle = 2 * Math.Acos(rot.s);
3730
3731 return angle;
3732 }
3733
3734 public LSL_Float llAcos(double val)
3735 {
3736 m_host.AddScriptLPS(1);
3737 return (double)Math.Acos(val);
3738 }
3739
3740 public LSL_Float llAsin(double val)
3741 {
3742 m_host.AddScriptLPS(1);
3743 return (double)Math.Asin(val);
3744 }
3745
3746 // Xantor 30/apr/2008
3747 public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b)
3748 {
3749 m_host.AddScriptLPS(1);
3750
3751 return (double) Math.Acos(a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s) * 2;
3752 }
3753
3754 public LSL_String llGetInventoryKey(string name)
3755 {
3756 m_host.AddScriptLPS(1);
3757 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3758 {
3759 if (inv.Value.Name == name)
3760 {
3761 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
3762 {
3763 return inv.Value.AssetID.ToString();
3764 }
3765 else
3766 {
3767 return UUID.Zero.ToString();
3768 }
3769 }
3770 }
3771 return UUID.Zero.ToString();
3772 }
3773
3774 public void llAllowInventoryDrop(int add)
3775 {
3776 m_host.AddScriptLPS(1);
3777
3778 if (add != 0)
3779 m_host.ParentGroup.RootPart.AllowedDrop = true;
3780 else
3781 m_host.ParentGroup.RootPart.AllowedDrop = false;
3782 }
3783
3784 public LSL_Vector llGetSunDirection()
3785 {
3786 m_host.AddScriptLPS(1);
3787
3788 LSL_Vector SunDoubleVector3;
3789 Vector3 SunFloatVector3;
3790
3791 // sunPosition estate setting is set in OpenSim.Region.Environment.Modules.SunModule
3792 // have to convert from Vector3 (float) to LSL_Vector (double)
3793 SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector;
3794 SunDoubleVector3.x = (double)SunFloatVector3.X;
3795 SunDoubleVector3.y = (double)SunFloatVector3.Y;
3796 SunDoubleVector3.z = (double)SunFloatVector3.Z;
3797
3798 return SunDoubleVector3;
3799 }
3800
3801 public LSL_Vector llGetTextureOffset(int face)
3802 {
3803 m_host.AddScriptLPS(1);
3804 return GetTextureOffset(m_host, face);
3805 }
3806
3807 private LSL_Vector GetTextureOffset(SceneObjectPart part, int face)
3808 {
3809 Primitive.TextureEntry tex = part.Shape.Textures;
3810 LSL_Vector offset = new LSL_Vector();
3811 if (face == ScriptBaseClass.ALL_SIDES)
3812 {
3813 face = 0;
3814 }
3815 if (face >= 0 && face < GetNumberOfSides(part))
3816 {
3817 offset.x = tex.GetFace((uint)face).OffsetU;
3818 offset.y = tex.GetFace((uint)face).OffsetV;
3819 offset.z = 0.0;
3820 return offset;
3821 }
3822 else
3823 {
3824 return offset;
3825 }
3826 }
3827
3828 public LSL_Vector llGetTextureScale(int side)
3829 {
3830 m_host.AddScriptLPS(1);
3831 Primitive.TextureEntry tex = m_host.Shape.Textures;
3832 LSL_Vector scale;
3833 if (side == -1)
3834 {
3835 side = 0;
3836 }
3837 scale.x = tex.GetFace((uint)side).RepeatU;
3838 scale.y = tex.GetFace((uint)side).RepeatV;
3839 scale.z = 0.0;
3840 return scale;
3841 }
3842
3843 public LSL_Float llGetTextureRot(int face)
3844 {
3845 m_host.AddScriptLPS(1);
3846 return GetTextureRot(m_host, face);
3847 }
3848
3849 private LSL_Float GetTextureRot(SceneObjectPart part, int face)
3850 {
3851 Primitive.TextureEntry tex = part.Shape.Textures;
3852 if (face == -1)
3853 {
3854 face = 0;
3855 }
3856 if (face >= 0 && face < GetNumberOfSides(part))
3857 {
3858 return tex.GetFace((uint)face).Rotation;
3859 }
3860 else
3861 {
3862 return 0.0;
3863 }
3864 }
3865
3866 public LSL_Integer llSubStringIndex(string source, string pattern)
3867 {
3868 m_host.AddScriptLPS(1);
3869 return source.IndexOf(pattern);
3870 }
3871
3872 public LSL_String llGetOwnerKey(string id)
3873 {
3874 m_host.AddScriptLPS(1);
3875 UUID key = new UUID();
3876 if (UUID.TryParse(id, out key))
3877 {
3878 try
3879 {
3880 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
3881 if (obj == null)
3882 return id; // the key is for an agent so just return the key
3883 else
3884 return obj.OwnerID.ToString();
3885 }
3886 catch (KeyNotFoundException)
3887 {
3888 return id; // The Object/Agent not in the region so just return the key
3889 }
3890 }
3891 else
3892 {
3893 return UUID.Zero.ToString();
3894 }
3895 }
3896
3897 public LSL_Vector llGetCenterOfMass()
3898 {
3899 m_host.AddScriptLPS(1);
3900 NotImplemented("llGetCenterOfMass");
3901 return new LSL_Vector();
3902 }
3903
3904 public LSL_List llListSort(LSL_List src, int stride, int ascending)
3905 {
3906 m_host.AddScriptLPS(1);
3907
3908 if (stride <= 0)
3909 {
3910 stride = 1;
3911 }
3912 return src.Sort(stride, ascending);
3913 }
3914
3915 public LSL_Integer llGetListLength(LSL_List src)
3916 {
3917 m_host.AddScriptLPS(1);
3918
3919 if (src == null)
3920 {
3921 return 0;
3922 }
3923 else
3924 {
3925 return src.Length;
3926 }
3927 }
3928
3929 public LSL_Integer llList2Integer(LSL_List src, int index)
3930 {
3931 m_host.AddScriptLPS(1);
3932 if (index < 0)
3933 {
3934 index = src.Length + index;
3935 }
3936 if (index >= src.Length)
3937 {
3938 return 0;
3939 }
3940 try
3941 {
3942 if (src.Data[index] is LSL_Integer)
3943 return Convert.ToInt32(((LSL_Integer) src.Data[index]).value);
3944 else if (src.Data[index] is LSL_Float)
3945 return Convert.ToInt32(((LSL_Float) src.Data[index]).value);
3946 else if (src.Data[index] is LSL_String)
3947 return Convert.ToInt32(((LSL_String) src.Data[index]).m_string);
3948 return Convert.ToInt32(src.Data[index]);
3949 }
3950 catch (FormatException)
3951 {
3952 return 0;
3953 }
3954 }
3955
3956 public LSL_Float llList2Float(LSL_List src, int index)
3957 {
3958 m_host.AddScriptLPS(1);
3959 if (index < 0)
3960 {
3961 index = src.Length + index;
3962 }
3963 if (index >= src.Length)
3964 {
3965 return 0.0;
3966 }
3967 try
3968 {
3969 if (src.Data[index] is LSL_Integer)
3970 return Convert.ToDouble(((LSL_Integer) src.Data[index]).value);
3971 else if (src.Data[index] is LSL_Float)
3972 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
3973 else if (src.Data[index] is LSL_String)
3974 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string);
3975 return Convert.ToDouble(src.Data[index]);
3976 }
3977 catch (FormatException)
3978 {
3979 return 0.0;
3980 }
3981 }
3982
3983 public LSL_String llList2String(LSL_List src, int index)
3984 {
3985 m_host.AddScriptLPS(1);
3986 if (index < 0)
3987 {
3988 index = src.Length + index;
3989 }
3990 if (index >= src.Length)
3991 {
3992 return String.Empty;
3993 }
3994 return src.Data[index].ToString();
3995 }
3996
3997 public LSL_String llList2Key(LSL_List src, int index)
3998 {
3999 m_host.AddScriptLPS(1);
4000 if (index < 0)
4001 {
4002 index = src.Length + index;
4003 }
4004 if (index >= src.Length)
4005 {
4006 return "";
4007 }
4008 return src.Data[index].ToString();
4009 }
4010
4011 public LSL_Vector llList2Vector(LSL_List src, int index)
4012 {
4013 m_host.AddScriptLPS(1);
4014 if (index < 0)
4015 {
4016 index = src.Length + index;
4017 }
4018 if (index >= src.Length)
4019 {
4020 return new LSL_Vector(0, 0, 0);
4021 }
4022 if (src.Data[index].GetType() == typeof(LSL_Vector))
4023 {
4024 return (LSL_Vector)src.Data[index];
4025 }
4026 else
4027 {
4028 return new LSL_Vector(src.Data[index].ToString());
4029 }
4030 }
4031
4032 public LSL_Rotation llList2Rot(LSL_List src, int index)
4033 {
4034 m_host.AddScriptLPS(1);
4035 if (index < 0)
4036 {
4037 index = src.Length + index;
4038 }
4039 if (index >= src.Length)
4040 {
4041 return new LSL_Rotation(0, 0, 0, 1);
4042 }
4043 if (src.Data[index].GetType() == typeof(LSL_Rotation))
4044 {
4045 return (LSL_Rotation)src.Data[index];
4046 }
4047 else
4048 {
4049 return new LSL_Rotation(src.Data[index].ToString());
4050 }
4051 }
4052
4053 public LSL_List llList2List(LSL_List src, int start, int end)
4054 {
4055 m_host.AddScriptLPS(1);
4056 return src.GetSublist(start, end);
4057 }
4058
4059 public LSL_List llDeleteSubList(LSL_List src, int start, int end)
4060 {
4061 return src.DeleteSublist(end, start);
4062 }
4063
4064 public LSL_Integer llGetListEntryType(LSL_List src, int index)
4065 {
4066 m_host.AddScriptLPS(1);
4067 if (index < 0)
4068 {
4069 index = src.Length + index;
4070 }
4071 if (index >= src.Length)
4072 {
4073 return 0;
4074 }
4075
4076 if (src.Data[index] is LSL_Integer || src.Data[index] is Int32)
4077 return 1;
4078 if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double)
4079 return 2;
4080 if (src.Data[index] is LSL_String || src.Data[index] is String)
4081 {
4082 UUID tuuid;
4083 if (UUID.TryParse(src.Data[index].ToString(), out tuuid))
4084 {
4085 return 4;
4086 }
4087 else
4088 {
4089 return 3;
4090 }
4091 }
4092 if (src.Data[index] is LSL_Vector)
4093 return 5;
4094 if (src.Data[index] is LSL_Rotation)
4095 return 6;
4096 if (src.Data[index] is LSL_List)
4097 return 7;
4098 return 0;
4099
4100 }
4101
4102 /// <summary>
4103 /// Process the supplied list and return the
4104 /// content of the list formatted as a comma
4105 /// separated list. There is a space after
4106 /// each comma.
4107 /// </summary>
4108
4109 public LSL_String llList2CSV(LSL_List src)
4110 {
4111
4112 string ret = String.Empty;
4113 int x = 0;
4114
4115 m_host.AddScriptLPS(1);
4116
4117 if (src.Data.Length > 0)
4118 {
4119 ret = src.Data[x++].ToString();
4120 for (; x < src.Data.Length; x++)
4121 {
4122 ret += ", "+src.Data[x].ToString();
4123 }
4124 }
4125
4126 return ret;
4127 }
4128
4129 /// <summary>
4130 /// The supplied string is scanned for commas
4131 /// and converted into a list. Commas are only
4132 /// effective if they are encountered outside
4133 /// of '<' '>' delimiters. Any whitespace
4134 /// before or after an element is trimmed.
4135 /// </summary>
4136
4137 public LSL_List llCSV2List(string src)
4138 {
4139
4140 LSL_List result = new LSL_List();
4141 int parens = 0;
4142 int start = 0;
4143 int length = 0;
4144
4145 m_host.AddScriptLPS(1);
4146
4147 for (int i = 0; i < src.Length; i++)
4148 {
4149 switch (src[i])
4150 {
4151 case '<':
4152 parens++;
4153 length++;
4154 break;
4155 case '>':
4156 if (parens > 0)
4157 parens--;
4158 length++;
4159 break;
4160 case ',':
4161 if (parens == 0)
4162 {
4163 result.Add(src.Substring(start,length).Trim());
4164 start += length+1;
4165 length = 0;
4166 }
4167 else
4168 {
4169 length++;
4170 }
4171 break;
4172 default:
4173 length++;
4174 break;
4175 }
4176 }
4177
4178 result.Add(src.Substring(start,length).Trim());
4179
4180 return result;
4181 }
4182
4183 /// <summary>
4184 /// Randomizes the list, be arbitrarily reordering
4185 /// sublists of stride elements. As the stride approaches
4186 /// the size of the list, the options become very
4187 /// limited.
4188 /// </summary>
4189 /// <remarks>
4190 /// This could take a while for very large list
4191 /// sizes.
4192 /// </remarks>
4193
4194 public LSL_List llListRandomize(LSL_List src, int stride)
4195 {
4196 LSL_List result;
4197 Random rand = new Random();
4198
4199 int chunkk;
4200 int[] chunks;
4201
4202 m_host.AddScriptLPS(1);
4203
4204 if (stride <= 0)
4205 {
4206 stride = 1;
4207 }
4208
4209 // Stride MUST be a factor of the list length
4210 // If not, then return the src list. This also
4211 // traps those cases where stride > length.
4212
4213 if (src.Length != stride && src.Length%stride == 0)
4214 {
4215 chunkk = src.Length/stride;
4216
4217 chunks = new int[chunkk];
4218
4219 for (int i = 0; i < chunkk; i++)
4220 chunks[i] = i;
4221
4222 // Knuth shuffle the chunkk index
4223 for (int i = chunkk - 1; i >= 1; i--)
4224 {
4225 // Elect an unrandomized chunk to swap
4226 int index = rand.Next(i + 1);
4227 int tmp;
4228
4229 // and swap position with first unrandomized chunk
4230 tmp = chunks[i];
4231 chunks[i] = chunks[index];
4232 chunks[index] = tmp;
4233 }
4234
4235 // Construct the randomized list
4236
4237 result = new LSL_List();
4238
4239 for (int i = 0; i < chunkk; i++)
4240 {
4241 for (int j = 0; j < stride; j++)
4242 {
4243 result.Add(src.Data[chunks[i]*stride+j]);
4244 }
4245 }
4246 }
4247 else {
4248 object[] array = new object[src.Length];
4249 Array.Copy(src.Data, 0, array, 0, src.Length);
4250 result = new LSL_List(array);
4251 }
4252
4253 return result;
4254 }
4255
4256 /// <summary>
4257 /// Elements in the source list starting with 0 and then
4258 /// every i+stride. If the stride is negative then the scan
4259 /// is backwards producing an inverted result.
4260 /// Only those elements that are also in the specified
4261 /// range are included in the result.
4262 /// </summary>
4263
4264 public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride)
4265 {
4266
4267 LSL_List result = new LSL_List();
4268 int[] si = new int[2];
4269 int[] ei = new int[2];
4270 bool twopass = false;
4271
4272 m_host.AddScriptLPS(1);
4273
4274 // First step is always to deal with negative indices
4275
4276 if (start < 0)
4277 start = src.Length+start;
4278 if (end < 0)
4279 end = src.Length+end;
4280
4281 // Out of bounds indices are OK, just trim them
4282 // accordingly
4283
4284 if (start > src.Length)
4285 start = src.Length;
4286
4287 if (end > src.Length)
4288 end = src.Length;
4289
4290 // There may be one or two ranges to be considered
4291
4292 if (start != end)
4293 {
4294
4295 if (start <= end)
4296 {
4297 si[0] = start;
4298 ei[0] = end;
4299 }
4300 else
4301 {
4302 si[1] = start;
4303 ei[1] = src.Length;
4304 si[0] = 0;
4305 ei[0] = end;
4306 twopass = true;
4307 }
4308
4309 // The scan always starts from the beginning of the
4310 // source list, but members are only selected if they
4311 // fall within the specified sub-range. The specified
4312 // range values are inclusive.
4313 // A negative stride reverses the direction of the
4314 // scan producing an inverted list as a result.
4315
4316 if (stride == 0)
4317 stride = 1;
4318
4319 if (stride > 0)
4320 {
4321 for (int i = 0; i < src.Length; i += stride)
4322 {
4323 if (i<=ei[0] && i>=si[0])
4324 result.Add(src.Data[i]);
4325 if (twopass && i>=si[1] && i<=ei[1])
4326 result.Add(src.Data[i]);
4327 }
4328 }
4329 else if (stride < 0)
4330 {
4331 for (int i = src.Length - 1; i >= 0; i += stride)
4332 {
4333 if (i <= ei[0] && i >= si[0])
4334 result.Add(src.Data[i]);
4335 if (twopass && i >= si[1] && i <= ei[1])
4336 result.Add(src.Data[i]);
4337 }
4338 }
4339 }
4340
4341 return result;
4342 }
4343
4344 public LSL_Integer llGetRegionAgentCount()
4345 {
4346 m_host.AddScriptLPS(1);
4347 NotImplemented("llGetRegionAgentCount");
4348 return new LSL_Integer(0);
4349 }
4350
4351 public LSL_Vector llGetRegionCorner()
4352 {
4353 m_host.AddScriptLPS(1);
4354 return new LSL_Vector(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
4355 }
4356
4357 /// <summary>
4358 /// Insert the list identified by <src> into the
4359 /// list designated by <dest> such that the first
4360 /// new element has the index specified by <index>
4361 /// </summary>
4362
4363 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
4364 {
4365
4366 LSL_List pref = null;
4367 LSL_List suff = null;
4368
4369 m_host.AddScriptLPS(1);
4370
4371 if (index < 0)
4372 {
4373 index = index+dest.Length;
4374 if (index < 0)
4375 {
4376 index = 0;
4377 }
4378 }
4379
4380 if (index != 0)
4381 {
4382 pref = dest.GetSublist(0,index-1);
4383 if (index < dest.Length)
4384 {
4385 suff = dest.GetSublist(index,-1);
4386 return pref + src + suff;
4387 }
4388 else
4389 {
4390 return pref + src;
4391 }
4392 }
4393 else
4394 {
4395 if (index < dest.Length)
4396 {
4397 suff = dest.GetSublist(index,-1);
4398 return src + suff;
4399 }
4400 else
4401 {
4402 return src;
4403 }
4404 }
4405
4406 }
4407
4408 /// <summary>
4409 /// Returns the index of the first occurrence of test
4410 /// in src.
4411 /// </summary>
4412
4413 public LSL_Integer llListFindList(LSL_List src, LSL_List test)
4414 {
4415
4416 int index = -1;
4417 int length = src.Length - test.Length + 1;
4418
4419 m_host.AddScriptLPS(1);
4420
4421 // If either list is empty, do not match
4422
4423 if (src.Length != 0 && test.Length != 0)
4424 {
4425 for (int i = 0; i < length; i++)
4426 {
4427 if (src.Data[i].Equals(test.Data[0]))
4428 {
4429 int j;
4430 for (j = 1; j < test.Length; j++)
4431 if (!src.Data[i+j].Equals(test.Data[j]))
4432 break;
4433 if (j == test.Length)
4434 {
4435 index = i;
4436 break;
4437 }
4438 }
4439 }
4440 }
4441
4442 return index;
4443
4444 }
4445
4446 public LSL_String llGetObjectName()
4447 {
4448 m_host.AddScriptLPS(1);
4449 return m_host.Name!=null?m_host.Name:String.Empty;
4450 }
4451
4452 public void llSetObjectName(string name)
4453 {
4454 m_host.AddScriptLPS(1);
4455 m_host.Name = name!=null?name:String.Empty;
4456 }
4457
4458 public LSL_String llGetDate()
4459 {
4460 m_host.AddScriptLPS(1);
4461 DateTime date = DateTime.Now.ToUniversalTime();
4462 string result = date.ToString("yyyy-MM-dd");
4463 return result;
4464 }
4465
4466 public LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir)
4467 {
4468 m_host.AddScriptLPS(1);
4469 NotImplemented("llEdgeOfWorld");
4470 return 0;
4471 }
4472
4473 public LSL_Integer llGetAgentInfo(string id)
4474 {
4475 m_host.AddScriptLPS(1);
4476 NotImplemented("llGetAgentInfo");
4477 return 0;
4478 }
4479
4480 public void llAdjustSoundVolume(double volume)
4481 {
4482 m_host.AddScriptLPS(1);
4483 m_host.AdjustSoundGain(volume);
4484 // ScriptSleep(100);
4485 }
4486
4487 public void llSetSoundQueueing(int queue)
4488 {
4489 m_host.AddScriptLPS(1);
4490 NotImplemented("llSetSoundQueueing");
4491 }
4492
4493 public void llSetSoundRadius(double radius)
4494 {
4495 m_host.AddScriptLPS(1);
4496 m_host.SoundRadius = radius;
4497 }
4498
4499 public LSL_String llKey2Name(string id)
4500 {
4501 m_host.AddScriptLPS(1);
4502 UUID key = new UUID();
4503 if (UUID.TryParse(id,out key))
4504 {
4505 ScenePresence presence = World.GetScenePresence(key);
4506
4507 if (presence != null)
4508 {
4509 return presence.ControllingClient.Name;
4510 //return presence.Name;
4511 }
4512
4513 if (World.GetSceneObjectPart(key) != null)
4514 {
4515 return World.GetSceneObjectPart(key).Name;
4516 }
4517 }
4518 return String.Empty;
4519 }
4520
4521
4522
4523 public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate)
4524 {
4525 m_host.AddScriptLPS(1);
4526 Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation();
4527 pTexAnim.Flags = (Primitive.TextureAnimMode)mode;
4528
4529 //ALL_SIDES
4530 if (face == ScriptBaseClass.ALL_SIDES)
4531 face = 255;
4532
4533 pTexAnim.Face = (uint)face;
4534 pTexAnim.Length = (float)length;
4535 pTexAnim.Rate = (float)rate;
4536 pTexAnim.SizeX = (uint)sizex;
4537 pTexAnim.SizeY = (uint)sizey;
4538 pTexAnim.Start = (float)start;
4539
4540 m_host.AddTextureAnimation(pTexAnim);
4541 m_host.SendFullUpdateToAllClients();
4542 m_host.ParentGroup.HasGroupChanged = true;
4543 }
4544
4545 public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east,
4546 LSL_Vector bottom_south_west)
4547 {
4548 m_host.AddScriptLPS(1);
4549 NotImplemented("llTriggerSoundLimited");
4550 }
4551
4552 public void llEjectFromLand(string pest)
4553 {
4554 m_host.AddScriptLPS(1);
4555 UUID agentId = new UUID();
4556 if (UUID.TryParse(pest, out agentId))
4557 {
4558 ScenePresence presence = World.GetScenePresence(agentId);
4559 if (presence != null)
4560 {
4561 // agent must be over the owners land
4562 if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y))
4563 World.TeleportClientHome(agentId, presence.ControllingClient);
4564 }
4565 }
4566 // ScriptSleep(5000);
4567 }
4568
4569 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List spacers)
4570 {
4571 m_host.AddScriptLPS(1);
4572 LSL_List ret = new LSL_List();
4573 object[] delimiters = new object[separators.Length + spacers.Length];
4574 separators.Data.CopyTo(delimiters, 0);
4575 spacers.Data.CopyTo(delimiters, separators.Length);
4576 bool dfound = false;
4577 do
4578 {
4579 dfound = false;
4580 int cindex = -1;
4581 string cdeli = "";
4582 for (int i = 0; i < delimiters.Length; i++)
4583 {
4584 int index = str.IndexOf(delimiters[i].ToString());
4585 bool found = index != -1;
4586 if (found && String.Empty != delimiters[i].ToString())
4587 {
4588 if ((cindex > index) || (cindex == -1))
4589 {
4590 cindex = index;
4591 cdeli = delimiters[i].ToString();
4592 }
4593 dfound = dfound || found;
4594 }
4595 }
4596 if (cindex != -1)
4597 {
4598 if (cindex > 0)
4599 {
4600 ret.Add(str.Substring(0, cindex));
4601 // Cannot use spacers.Contains() because spacers may be either type String or LSLString
4602 for (int j = 0; j < spacers.Length; j++)
4603 {
4604 if (spacers.Data[j].ToString() == cdeli)
4605 {
4606 ret.Add(cdeli);
4607 break;
4608 }
4609 }
4610 }
4611 if (cindex == 0 && spacers.Contains(cdeli))
4612 {
4613 ret.Add(cdeli);
4614 }
4615 str = str.Substring(cindex + cdeli.Length);
4616 }
4617 } while (dfound);
4618 if (str != "")
4619 {
4620 ret.Add(str);
4621 }
4622 return ret;
4623 }
4624
4625 public LSL_Integer llOverMyLand(string id)
4626 {
4627 m_host.AddScriptLPS(1);
4628 UUID key = new UUID();
4629 if (UUID.TryParse(id,out key))
4630 {
4631 ScenePresence presence = World.GetScenePresence(key);
4632 if (presence != null) // object is an avatar
4633 {
4634 if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y))
4635 return 1;
4636 }
4637 else // object is not an avatar
4638 {
4639 SceneObjectPart obj = World.GetSceneObjectPart(key);
4640 if (obj != null)
4641 if (m_host.OwnerID == World.GetLandOwner(obj.AbsolutePosition.X, obj.AbsolutePosition.Y))
4642 return 1;
4643 }
4644 }
4645 return 0;
4646 }
4647
4648 public LSL_String llGetLandOwnerAt(LSL_Vector pos)
4649 {
4650 m_host.AddScriptLPS(1);
4651 return World.GetLandOwner((float)pos.x, (float)pos.y).ToString();
4652 }
4653
4654 public LSL_Vector llGetAgentSize(string id)
4655 {
4656 m_host.AddScriptLPS(1);
4657 ScenePresence avatar = World.GetScenePresence(id);
4658 LSL_Vector agentSize;
4659 if (avatar == null)
4660 {
4661 agentSize = ScriptBaseClass.ZERO_VECTOR;
4662 }
4663 else
4664 {
4665 PhysicsVector size = avatar.PhysicsActor.Size;
4666 agentSize = new LSL_Vector(size.X, size.Y, size.Z);
4667 }
4668 return agentSize;
4669 }
4670
4671 public LSL_Integer llSameGroup(string agent)
4672 {
4673 m_host.AddScriptLPS(1);
4674 UUID agentId = new UUID();
4675 if (!UUID.TryParse(agent, out agentId))
4676 return new LSL_Integer(0);
4677 ScenePresence presence = World.GetScenePresence(agentId);
4678 if (presence == null)
4679 return new LSL_Integer(0);
4680 IClientAPI client = presence.ControllingClient;
4681 if (m_host.GroupID == client.ActiveGroupId)
4682 return new LSL_Integer(1);
4683 else
4684 return new LSL_Integer(0);
4685 }
4686
4687 public void llUnSit(string id)
4688 {
4689 m_host.AddScriptLPS(1);
4690
4691 UUID key = new UUID();
4692 if (UUID.TryParse(id, out key))
4693 {
4694 ScenePresence av = World.GetScenePresence(key);
4695
4696 if (av != null)
4697 {
4698 if (llAvatarOnSitTarget() == id)
4699 {
4700 // if the avatar is sitting on this object, then
4701 // we can unsit them. We don't want random scripts unsitting random people
4702 // Lets avoid the popcorn avatar scenario.
4703 av.StandUp();
4704 }
4705 else
4706 {
4707 // If the object owner also owns the parcel
4708 // or
4709 // if the land is group owned and the object is group owned by the same group
4710 // or
4711 // if the object is owned by a person with estate access.
4712
4713 ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y);
4714 if (parcel != null)
4715 {
4716 if (m_host.ObjectOwner == parcel.landData.OwnerID ||
4717 (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.landData.GroupID
4718 && parcel.landData.IsGroupOwned) || World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID))
4719 {
4720 av.StandUp();
4721 }
4722 }
4723 }
4724 }
4725
4726 }
4727
4728 }
4729
4730 public LSL_Vector llGroundSlope(LSL_Vector offset)
4731 {
4732 m_host.AddScriptLPS(1);
4733
4734 Vector3 pos = m_host.AbsolutePosition + new Vector3((float)offset.x,
4735 (float)offset.y,
4736 (float)offset.z);
4737
4738 Vector3 p0 = new Vector3(pos.X, pos.Y,
4739 (float)llGround(
4740 new LSL_Vector(pos.X, pos.Y, pos.Z)
4741 ));
4742 Vector3 p1 = new Vector3(pos.X + 1, pos.Y,
4743 (float)llGround(
4744 new LSL_Vector(pos.X + 1, pos.Y, pos.Z)
4745 ));
4746 Vector3 p2 = new Vector3(pos.X, pos.Y + 1,
4747 (float)llGround(
4748 new LSL_Vector(pos.X, pos.Y + 1, pos.Z)
4749 ));
4750
4751 Vector3 v0 = new Vector3(
4752 p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
4753 Vector3 v1 = new Vector3(
4754 p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z);
4755
4756 v0.Normalize();
4757 v1.Normalize();
4758
4759 Vector3 tv = new Vector3();
4760 tv.X = (v0.Y * v1.Z) - (v0.Z * v1.Y);
4761 tv.Y = (v0.Z * v1.X) - (v0.X * v1.Z);
4762 tv.Z = (v0.X * v1.Y) - (v0.Y * v1.X);
4763
4764 return new LSL_Vector(tv.X, tv.Y, tv.Z);
4765 }
4766
4767 public LSL_Vector llGroundNormal(LSL_Vector offset)
4768 {
4769 m_host.AddScriptLPS(1);
4770 LSL_Vector x = llGroundSlope(offset);
4771 return new LSL_Vector(x.x, x.y, 1.0);
4772 }
4773
4774 public LSL_Vector llGroundContour(LSL_Vector offset)
4775 {
4776 m_host.AddScriptLPS(1);
4777 LSL_Vector x = llGroundSlope(offset);
4778 return new LSL_Vector(-x.y, x.x, 0.0);
4779 }
4780
4781 public LSL_Integer llGetAttached()
4782 {
4783 m_host.AddScriptLPS(1);
4784 NotImplemented("llGetAttached");
4785 return 0;
4786 }
4787
4788 public LSL_Integer llGetFreeMemory()
4789 {
4790 m_host.AddScriptLPS(1);
4791 // Make scripts designed for LSO happy
4792 return 16384;
4793 }
4794
4795 public LSL_String llGetRegionName()
4796 {
4797 m_host.AddScriptLPS(1);
4798 return World.RegionInfo.RegionName;
4799 }
4800
4801 public LSL_Float llGetRegionTimeDilation()
4802 {
4803 m_host.AddScriptLPS(1);
4804 return (double)World.TimeDilation;
4805 }
4806
4807 public LSL_Float llGetRegionFPS()
4808 {
4809 m_host.AddScriptLPS(1);
4810 //TODO: return actual FPS
4811 return 10.0f;
4812 }
4813
4814 /* particle system rules should be coming into this routine as doubles, that is
4815 rule[0] should be an integer from this list and rule[1] should be the arg
4816 for the same integer. wiki.secondlife.com has most of this mapping, but some
4817 came from http://www.caligari-designs.com/p4u2
4818
4819 We iterate through the list for 'Count' elements, incrementing by two for each
4820 iteration and set the members of Primitive.ParticleSystem, one at a time.
4821 */
4822
4823 public enum PrimitiveRule : int
4824 {
4825 PSYS_PART_FLAGS = 0,
4826 PSYS_PART_START_COLOR = 1,
4827 PSYS_PART_START_ALPHA = 2,
4828 PSYS_PART_END_COLOR = 3,
4829 PSYS_PART_END_ALPHA = 4,
4830 PSYS_PART_START_SCALE = 5,
4831 PSYS_PART_END_SCALE = 6,
4832 PSYS_PART_MAX_AGE = 7,
4833 PSYS_SRC_ACCEL = 8,
4834 PSYS_SRC_PATTERN = 9,
4835 PSYS_SRC_TEXTURE = 12,
4836 PSYS_SRC_BURST_RATE = 13,
4837 PSYS_SRC_BURST_PART_COUNT = 15,
4838 PSYS_SRC_BURST_RADIUS = 16,
4839 PSYS_SRC_BURST_SPEED_MIN = 17,
4840 PSYS_SRC_BURST_SPEED_MAX = 18,
4841 PSYS_SRC_MAX_AGE = 19,
4842 PSYS_SRC_TARGET_KEY = 20,
4843 PSYS_SRC_OMEGA = 21,
4844 PSYS_SRC_ANGLE_BEGIN = 22,
4845 PSYS_SRC_ANGLE_END = 23
4846 }
4847
4848 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
4849 {
4850 Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None;
4851
4852 return returnval;
4853 }
4854
4855 private Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues()
4856 {
4857 Primitive.ParticleSystem ps = new Primitive.ParticleSystem();
4858
4859 // TODO find out about the other defaults and add them here
4860 ps.PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
4861 ps.PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
4862 ps.PartStartScaleX = 1.0f;
4863 ps.PartStartScaleY = 1.0f;
4864 ps.PartEndScaleX = 1.0f;
4865 ps.PartEndScaleY = 1.0f;
4866 ps.BurstSpeedMin = 1.0f;
4867 ps.BurstSpeedMax = 1.0f;
4868 ps.BurstRate = 0.1f;
4869 ps.PartMaxAge = 10.0f;
4870 return ps;
4871 }
4872
4873 public void llParticleSystem(LSL_List rules)
4874 {
4875 m_host.AddScriptLPS(1);
4876 if (rules.Length == 0)
4877 {
4878 m_host.RemoveParticleSystem();
4879 m_host.ParentGroup.HasGroupChanged = true;
4880 }
4881 else
4882 {
4883 Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues();
4884 LSL_Vector tempv = new LSL_Vector();
4885
4886 float tempf = 0;
4887
4888 for (int i = 0; i < rules.Length; i += 2)
4889 {
4890 switch ((int)rules.Data[i])
4891 {
4892 case (int)ScriptBaseClass.PSYS_PART_FLAGS:
4893 prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1);
4894 break;
4895
4896 case (int)ScriptBaseClass.PSYS_PART_START_COLOR:
4897 tempv = rules.GetVector3Item(i + 1);
4898 prules.PartStartColor.R = (float)tempv.x;
4899 prules.PartStartColor.G = (float)tempv.y;
4900 prules.PartStartColor.B = (float)tempv.z;
4901 break;
4902
4903 case (int)ScriptBaseClass.PSYS_PART_START_ALPHA:
4904 tempf = (float)rules.GetLSLFloatItem(i + 1);
4905 prules.PartStartColor.A = tempf;
4906 break;
4907
4908 case (int)ScriptBaseClass.PSYS_PART_END_COLOR:
4909 tempv = rules.GetVector3Item(i + 1);
4910 prules.PartEndColor.R = (float)tempv.x;
4911 prules.PartEndColor.G = (float)tempv.y;
4912 prules.PartEndColor.B = (float)tempv.z;
4913 break;
4914
4915 case (int)ScriptBaseClass.PSYS_PART_END_ALPHA:
4916 tempf = (float)rules.GetLSLFloatItem(i + 1);
4917 prules.PartEndColor.A = tempf;
4918 break;
4919
4920 case (int)ScriptBaseClass.PSYS_PART_START_SCALE:
4921 tempv = rules.GetVector3Item(i + 1);
4922 prules.PartStartScaleX = (float)tempv.x;
4923 prules.PartStartScaleY = (float)tempv.y;
4924 break;
4925
4926 case (int)ScriptBaseClass.PSYS_PART_END_SCALE:
4927 tempv = rules.GetVector3Item(i + 1);
4928 prules.PartEndScaleX = (float)tempv.x;
4929 prules.PartEndScaleY = (float)tempv.y;
4930 break;
4931
4932 case (int)ScriptBaseClass.PSYS_PART_MAX_AGE:
4933 tempf = (float)rules.GetLSLFloatItem(i + 1);
4934 prules.PartMaxAge = tempf;
4935 break;
4936
4937 case (int)ScriptBaseClass.PSYS_SRC_ACCEL:
4938 tempv = rules.GetVector3Item(i + 1);
4939 prules.PartAcceleration.X = (float)tempv.x;
4940 prules.PartAcceleration.Y = (float)tempv.y;
4941 prules.PartAcceleration.Z = (float)tempv.z;
4942 break;
4943
4944 case (int)ScriptBaseClass.PSYS_SRC_PATTERN:
4945 int tmpi = (int)rules.GetLSLIntegerItem(i + 1);
4946 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
4947 break;
4948
4949 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE:
4950 prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1));
4951 break;
4952
4953 case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE:
4954 tempf = (float)rules.GetLSLFloatItem(i + 1);
4955 prules.BurstRate = (float)tempf;
4956 break;
4957
4958 case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT:
4959 prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1);
4960 break;
4961
4962 case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS:
4963 tempf = (float)rules.GetLSLFloatItem(i + 1);
4964 prules.BurstRadius = (float)tempf;
4965 break;
4966
4967 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN:
4968 tempf = (float)rules.GetLSLFloatItem(i + 1);
4969 prules.BurstSpeedMin = (float)tempf;
4970 break;
4971
4972 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX:
4973 tempf = (float)rules.GetLSLFloatItem(i + 1);
4974 prules.BurstSpeedMax = (float)tempf;
4975 break;
4976
4977 case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE:
4978 tempf = (float)rules.GetLSLFloatItem(i + 1);
4979 prules.MaxAge = (float)tempf;
4980 break;
4981
4982 case (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY:
4983 UUID key = UUID.Zero;
4984 if (UUID.TryParse(rules.Data[i + 1].ToString(), out key))
4985 {
4986 prules.Target = key;
4987 }
4988 else
4989 {
4990 prules.Target = m_host.UUID;
4991 }
4992 break;
4993
4994 case (int)ScriptBaseClass.PSYS_SRC_OMEGA:
4995 // AL: This is an assumption, since it is the only thing that would match.
4996 tempv = rules.GetVector3Item(i + 1);
4997 prules.AngularVelocity.X = (float)tempv.x;
4998 prules.AngularVelocity.Y = (float)tempv.y;
4999 prules.AngularVelocity.Z = (float)tempv.z;
5000 break;
5001
5002 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN:
5003 tempf = (float)rules.GetLSLFloatItem(i + 1);
5004 prules.InnerAngle = (float)tempf;
5005 break;
5006
5007 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END:
5008 tempf = (float)rules.GetLSLFloatItem(i + 1);
5009 prules.OuterAngle = (float)tempf;
5010 break;
5011 }
5012
5013 }
5014 prules.CRC = 1;
5015
5016 m_host.AddNewParticleSystem(prules);
5017 m_host.ParentGroup.HasGroupChanged = true;
5018 }
5019 m_host.SendFullUpdateToAllClients();
5020 }
5021
5022 public void llGroundRepel(double height, int water, double tau)
5023 {
5024 m_host.AddScriptLPS(1);
5025 NotImplemented("llGroundRepel");
5026 }
5027
5028 private UUID GetTaskInventoryItem(string name)
5029 {
5030 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
5031 {
5032 if (inv.Value.Name == name)
5033 return inv.Key;
5034 }
5035 return UUID.Zero;
5036 }
5037
5038 public void llGiveInventoryList(string destination, string category, LSL_List inventory)
5039 {
5040 m_host.AddScriptLPS(1);
5041
5042 UUID destID;
5043 if (!UUID.TryParse(destination, out destID))
5044 return;
5045
5046 List<UUID> itemList = new List<UUID>();
5047
5048 foreach (Object item in inventory.Data)
5049 {
5050 UUID itemID;
5051 if (UUID.TryParse(item.ToString(), out itemID))
5052 {
5053 itemList.Add(itemID);
5054 }
5055 else
5056 {
5057 itemID = GetTaskInventoryItem(item.ToString());
5058 if (itemID != UUID.Zero)
5059 itemList.Add(itemID);
5060 }
5061 }
5062
5063 if (itemList.Count == 0)
5064 return;
5065
5066 m_ScriptEngine.World.MoveTaskInventoryItems(destID, category, m_host, itemList);
5067 }
5068
5069 public void llSetVehicleType(int type)
5070 {
5071 m_host.AddScriptLPS(1);
5072 NotImplemented("llSetVehicleType");
5073 }
5074
5075 public void llSetVehicledoubleParam(int param, double value)
5076 {
5077 m_host.AddScriptLPS(1);
5078 NotImplemented("llSetVehicledoubleParam");
5079 }
5080
5081 public void llSetVehicleFloatParam(int param, float value)
5082 {
5083 m_host.AddScriptLPS(1);
5084 NotImplemented("llSetVehicleFloatParam");
5085 }
5086
5087 public void llSetVehicleVectorParam(int param, LSL_Vector vec)
5088 {
5089 m_host.AddScriptLPS(1);
5090 NotImplemented("llSetVehicleVectorParam");
5091 }
5092
5093 public void llSetVehicleRotationParam(int param, LSL_Rotation rot)
5094 {
5095 m_host.AddScriptLPS(1);
5096 NotImplemented("llSetVehicleRotationParam");
5097 }
5098
5099 public void llSetVehicleFlags(int flags)
5100 {
5101 m_host.AddScriptLPS(1);
5102 NotImplemented("llSetVehicleFlags");
5103 }
5104
5105 public void llRemoveVehicleFlags(int flags)
5106 {
5107 m_host.AddScriptLPS(1);
5108 NotImplemented("llRemoveVehicleFlags");
5109 }
5110
5111 public void llSitTarget(LSL_Vector offset, LSL_Rotation rot)
5112 {
5113 m_host.AddScriptLPS(1);
5114 // LSL quaternions can normalize to 0, normal Quaternions can't.
5115 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
5116 rot.z = 1; // ZERO_ROTATION = 0,0,0,1
5117
5118 m_host.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z);
5119 m_host.SitTargetOrientation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
5120 }
5121
5122 public LSL_String llAvatarOnSitTarget()
5123 {
5124 m_host.AddScriptLPS(1);
5125 return m_host.GetAvatarOnSitTarget().ToString();
5126 }
5127
5128 public void llAddToLandPassList(string avatar, double hours)
5129 {
5130 m_host.AddScriptLPS(1);
5131 UUID key;
5132 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
5133 if (land.OwnerID == m_host.OwnerID)
5134 {
5135 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
5136 if (UUID.TryParse(avatar, out key))
5137 {
5138 entry.AgentID = key;
5139 entry.Flags = ParcelManager.AccessList.Access;
5140 entry.Time = DateTime.Now.AddHours(hours);
5141 land.ParcelAccessList.Add(entry);
5142 }
5143 }
5144 // ScriptSleep(100);
5145 }
5146
5147 public void llSetTouchText(string text)
5148 {
5149 m_host.AddScriptLPS(1);
5150 m_host.TouchName = text;
5151 }
5152
5153 public void llSetSitText(string text)
5154 {
5155 m_host.AddScriptLPS(1);
5156 m_host.SitName = text;
5157 }
5158
5159 public void llSetCameraEyeOffset(LSL_Vector offset)
5160 {
5161 m_host.AddScriptLPS(1);
5162 m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z));
5163 }
5164
5165 public void llSetCameraAtOffset(LSL_Vector offset)
5166 {
5167 m_host.AddScriptLPS(1);
5168 m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z));
5169 }
5170
5171 public LSL_String llDumpList2String(LSL_List src, string seperator)
5172 {
5173 m_host.AddScriptLPS(1);
5174 if (src.Length == 0)
5175 {
5176 return String.Empty;
5177 }
5178 string ret = String.Empty;
5179 foreach (object o in src.Data)
5180 {
5181 ret = ret + o.ToString() + seperator;
5182 }
5183 ret = ret.Substring(0, ret.Length - seperator.Length);
5184 return ret;
5185 }
5186
5187 public LSL_Integer llScriptDanger(LSL_Vector pos)
5188 {
5189 m_host.AddScriptLPS(1);
5190 bool result = World.scriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z));
5191 if (result)
5192 {
5193 return 1;
5194 }
5195 else
5196 {
5197 return 0;
5198 }
5199
5200 }
5201
5202 public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel)
5203 {
5204 m_host.AddScriptLPS(1);
5205 UUID av = new UUID();
5206 if (!UUID.TryParse(avatar,out av))
5207 {
5208 LSLError("First parameter to llDialog needs to be a key");
5209 return;
5210 }
5211 if (buttons.Length > 12)
5212 {
5213 LSLError("No more than 12 buttons can be shown");
5214 return;
5215 }
5216 string[] buts = new string[buttons.Length];
5217 for (int i = 0; i < buttons.Length; i++)
5218 {
5219 if (buttons.Data[i].ToString() == String.Empty)
5220 {
5221 LSLError("button label cannot be blank");
5222 return;
5223 }
5224 if (buttons.Data[i].ToString().Length > 24)
5225 {
5226 LSLError("button label cannot be longer than 24 characters");
5227 return;
5228 }
5229 buts[i] = buttons.Data[i].ToString();
5230 }
5231 World.SendDialogToUser(av, m_host.Name, m_host.UUID, m_host.OwnerID, message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
5232 // ScriptSleep(1000);
5233 }
5234
5235 public void llVolumeDetect(int detect)
5236 {
5237 m_host.AddScriptLPS(1);
5238 NotImplemented("llVolumeDetect");
5239 }
5240
5241 /// <summary>
5242 /// Reset the named script. The script must be present
5243 /// in the same prim.
5244 /// </summary>
5245
5246 public void llResetOtherScript(string name)
5247 {
5248 UUID item;
5249
5250 m_host.AddScriptLPS(1);
5251
5252 if ((item = ScriptByName(name)) != UUID.Zero)
5253 m_ScriptEngine.ResetScript(item);
5254 else
5255 ShoutError("llResetOtherScript: script "+name+" not found");
5256 }
5257
5258 public LSL_Integer llGetScriptState(string name) 126 public LSL_Integer llGetScriptState(string name)
5259 { 127 {
5260 UUID item; 128 UUID item;
@@ -5263,7 +131,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5263 131
5264 if ((item = ScriptByName(name)) != UUID.Zero) 132 if ((item = ScriptByName(name)) != UUID.Zero)
5265 { 133 {
5266 return m_ScriptEngine.GetScriptState(item) ?1:0; 134 return m_ScriptEngineDirect.GetScriptState(item) ?1:0;
5267 } 135 }
5268 136
5269 ShoutError("llGetScriptState: script "+name+" not found"); 137 ShoutError("llGetScriptState: script "+name+" not found");
@@ -5274,3109 +142,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5274 return 0; 142 return 0;
5275 } 143 }
5276 144
5277 public void llRemoteLoadScript() 145 public void llResetOtherScript(string name)
5278 {
5279 m_host.AddScriptLPS(1);
5280 Deprecated("llRemoteLoadScript");
5281 // ScriptSleep(3000);
5282 }
5283
5284 public void llSetRemoteScriptAccessPin(int pin)
5285 {
5286 m_host.AddScriptLPS(1);
5287 m_host.ScriptAccessPin = pin;
5288 }
5289
5290 public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
5291 {
5292 m_host.AddScriptLPS(1);
5293 bool found = false;
5294 UUID destId = UUID.Zero;
5295 UUID srcId = UUID.Zero;
5296
5297 if (!UUID.TryParse(target, out destId))
5298 {
5299 llSay(0, "Could not parse key " + target);
5300 return;
5301 }
5302
5303 // target must be a different prim than the one containing the script
5304 if (m_host.UUID == destId)
5305 {
5306 return;
5307 }
5308
5309 // copy the first script found with this inventory name
5310 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
5311 {
5312 if (inv.Value.Name == name)
5313 {
5314 // make sure the object is a script
5315 if (10 == inv.Value.Type)
5316 {
5317 found = true;
5318 srcId = inv.Key;
5319 break;
5320 }
5321 }
5322 }
5323
5324 if (!found)
5325 {
5326 llSay(0, "Could not find script " + name);
5327 return;
5328 }
5329
5330 // the rest of the permission checks are done in RezScript, so check the pin there as well
5331 World.RezScript(srcId, m_host, destId, pin, running, start_param);
5332 // this will cause the delay even if the script pin or permissions were wrong - seems ok
5333 ScriptSleep(3000);
5334 }
5335
5336 public void llOpenRemoteDataChannel()
5337 {
5338 m_host.AddScriptLPS(1);
5339 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
5340 if (xmlrpcMod.IsEnabled())
5341 {
5342 UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, UUID.Zero);
5343 object[] resobj = new object[] { new LSL_Integer(1), new LSL_String(channelID.ToString()), new LSL_String(UUID.Zero.ToString()), new LSL_String(String.Empty), new LSL_Integer(0), new LSL_String(String.Empty) };
5344 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
5345 "remote_data", resobj,
5346 new DetectParams[0]));
5347 }
5348 // ScriptSleep(1000);
5349 }
5350
5351 public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata)
5352 {
5353 m_host.AddScriptLPS(1);
5354 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
5355 // ScriptSleep(3000);
5356 return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString();
5357 }
5358
5359 public void llRemoteDataReply(string channel, string message_id, string sdata, int idata)
5360 {
5361 m_host.AddScriptLPS(1);
5362 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
5363 xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
5364 // ScriptSleep(3000);
5365 }
5366
5367 public void llCloseRemoteDataChannel(string channel)
5368 {
5369 m_host.AddScriptLPS(1);
5370 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
5371 xmlrpcMod.CloseXMLRPCChannel(channel);
5372 // ScriptSleep(1000);
5373 }
5374
5375 public LSL_String llMD5String(string src, int nonce)
5376 {
5377 m_host.AddScriptLPS(1);
5378 return Util.Md5Hash(src + ":" + nonce.ToString());
5379 }
5380
5381 private ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist)
5382 {
5383 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
5384
5385 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
5386 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
5387 holeshape != (int)ScriptBaseClass.PRIM_HOLE_SQUARE &&
5388 holeshape != (int)ScriptBaseClass.PRIM_HOLE_TRIANGLE)
5389 {
5390 holeshape = (int)ScriptBaseClass.PRIM_HOLE_DEFAULT;
5391 }
5392 shapeBlock.ProfileCurve = (byte)holeshape;
5393 if (cut.x < 0f)
5394 {
5395 cut.x = 0f;
5396 }
5397 if (cut.x > 1f)
5398 {
5399 cut.x = 1f;
5400 }
5401 if (cut.y < 0f)
5402 {
5403 cut.y = 0f;
5404 }
5405 if (cut.y > 1f)
5406 {
5407 cut.y = 1f;
5408 }
5409 if (cut.y - cut.x < 0.05f)
5410 {
5411 cut.x = cut.y - 0.05f;
5412 }
5413 shapeBlock.ProfileBegin = (ushort)(50000 * cut.x);
5414 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y));
5415 if (hollow < 0f)
5416 {
5417 hollow = 0f;
5418 }
5419 if (hollow > 0.95)
5420 {
5421 hollow = 0.95f;
5422 }
5423 shapeBlock.ProfileHollow = (ushort)(50000 * hollow);
5424 if (twist.x < -1.0f)
5425 {
5426 twist.x = -1.0f;
5427 }
5428 if (twist.x > 1.0f)
5429 {
5430 twist.x = 1.0f;
5431 }
5432 if (twist.y < -1.0f)
5433 {
5434 twist.y = -1.0f;
5435 }
5436 if (twist.y > 1.0f)
5437 {
5438 twist.y = 1.0f;
5439 }
5440 shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x);
5441 shapeBlock.PathTwist = (sbyte)(100 * twist.y);
5442
5443 shapeBlock.ObjectLocalID = part.LocalId;
5444
5445 // retain pathcurve
5446 shapeBlock.PathCurve = part.Shape.PathCurve;
5447
5448 return shapeBlock;
5449 }
5450
5451 private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge)
5452 {
5453 ObjectShapePacket.ObjectDataBlock shapeBlock;
5454
5455 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
5456
5457 shapeBlock.ProfileCurve += fudge;
5458
5459 if (taper_b.x < 0f)
5460 {
5461 taper_b.x = 0f;
5462 }
5463 if (taper_b.x > 2f)
5464 {
5465 taper_b.x = 2f;
5466 }
5467 if (taper_b.y < 0f)
5468 {
5469 taper_b.y = 0f;
5470 }
5471 if (taper_b.y > 2f)
5472 {
5473 taper_b.y = 2f;
5474 }
5475 shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x));
5476 shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y));
5477 if (topshear.x < -0.5f)
5478 {
5479 topshear.x = -0.5f;
5480 }
5481 if (topshear.x > 0.5f)
5482 {
5483 topshear.x = 0.5f;
5484 }
5485 if (topshear.y < -0.5f)
5486 {
5487 topshear.y = -0.5f;
5488 }
5489 if (topshear.y > 0.5f)
5490 {
5491 topshear.y = 0.5f;
5492 }
5493 shapeBlock.PathShearX = (byte)(100 * topshear.x);
5494 shapeBlock.PathShearY = (byte)(100 * topshear.y);
5495
5496 part.UpdateShape(shapeBlock);
5497 }
5498
5499 private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge)
5500 {
5501 ObjectShapePacket.ObjectDataBlock shapeBlock;
5502
5503 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
5504
5505 // profile/path swapped for a sphere
5506 shapeBlock.PathBegin = shapeBlock.ProfileBegin;
5507 shapeBlock.PathEnd = shapeBlock.ProfileEnd;
5508
5509 shapeBlock.ProfileCurve += fudge;
5510
5511 shapeBlock.PathScaleX = 100;
5512 shapeBlock.PathScaleY = 100;
5513
5514 if (dimple.x < 0f)
5515 {
5516 dimple.x = 0f;
5517 }
5518 if (dimple.x > 1f)
5519 {
5520 dimple.x = 1f;
5521 }
5522 if (dimple.y < 0f)
5523 {
5524 dimple.y = 0f;
5525 }
5526 if (dimple.y > 1f)
5527 {
5528 dimple.y = 1f;
5529 }
5530 if (dimple.y - cut.x < 0.05f)
5531 {
5532 dimple.x = cut.y - 0.05f;
5533 }
5534 shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x);
5535 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y));
5536
5537 part.UpdateShape(shapeBlock);
5538 }
5539
5540 private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte fudge)
5541 {
5542 ObjectShapePacket.ObjectDataBlock shapeBlock;
5543
5544 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
5545
5546 shapeBlock.ProfileCurve += fudge;
5547
5548 // profile/path swapped for a torrus, tube, ring
5549 shapeBlock.PathBegin = shapeBlock.ProfileBegin;
5550 shapeBlock.PathEnd = shapeBlock.ProfileEnd;
5551
5552 if (holesize.x < 0.05f)
5553 {
5554 holesize.x = 0.05f;
5555 }
5556 if (holesize.x > 1f)
5557 {
5558 holesize.x = 1f;
5559 }
5560 if (holesize.y < 0.05f)
5561 {
5562 holesize.y = 0.05f;
5563 }
5564 if (holesize.y > 0.5f)
5565 {
5566 holesize.y = 0.5f;
5567 }
5568 shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x));
5569 shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y));
5570 if (topshear.x < -0.5f)
5571 {
5572 topshear.x = -0.5f;
5573 }
5574 if (topshear.x > 0.5f)
5575 {
5576 topshear.x = 0.5f;
5577 }
5578 if (topshear.y < -0.5f)
5579 {
5580 topshear.y = -0.5f;
5581 }
5582 if (topshear.y > 0.5f)
5583 {
5584 topshear.y = 0.5f;
5585 }
5586 shapeBlock.PathShearX = (byte)(100 * topshear.x);
5587 shapeBlock.PathShearY = (byte)(100 * topshear.y);
5588 if (profilecut.x < 0f)
5589 {
5590 profilecut.x = 0f;
5591 }
5592 if (profilecut.x > 1f)
5593 {
5594 profilecut.x = 1f;
5595 }
5596 if (profilecut.y < 0f)
5597 {
5598 profilecut.y = 0f;
5599 }
5600 if (profilecut.y > 1f)
5601 {
5602 profilecut.y = 1f;
5603 }
5604 if (profilecut.y - cut.x < 0.05f)
5605 {
5606 profilecut.x = cut.y - 0.05f;
5607 }
5608 shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x);
5609 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y));
5610 if (taper_a.x < -1f)
5611 {
5612 taper_a.x = -1f;
5613 }
5614 if (taper_a.x > 1f)
5615 {
5616 taper_a.x = 1f;
5617 }
5618 if (taper_a.y < -1f)
5619 {
5620 taper_a.y = -1f;
5621 }
5622 if (taper_a.y > 1f)
5623 {
5624 taper_a.y = 1f;
5625 }
5626 shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x);
5627 shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y);
5628 if (revolutions < 1f)
5629 {
5630 revolutions = 1f;
5631 }
5632 if (revolutions > 4f)
5633 {
5634 revolutions = 4f;
5635 }
5636 shapeBlock.PathRevolutions = (byte)(66.666667 * (revolutions - 1.0));
5637 // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
5638 if (radiusoffset < 0f)
5639 {
5640 radiusoffset = 0f;
5641 }
5642 if (radiusoffset > 1f)
5643 {
5644 radiusoffset = 1f;
5645 }
5646 shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset);
5647 if (skew < -0.95f)
5648 {
5649 skew = -0.95f;
5650 }
5651 if (skew > 0.95f)
5652 {
5653 skew = 0.95f;
5654 }
5655 shapeBlock.PathSkew = (sbyte)(100 * skew);
5656
5657 part.UpdateShape(shapeBlock);
5658 }
5659
5660 private void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type)
5661 {
5662 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
5663 UUID sculptId;
5664
5665 if (!UUID.TryParse(map, out sculptId))
5666 {
5667 llSay(0, "Could not parse key " + map);
5668 return;
5669 }
5670
5671 shapeBlock.ObjectLocalID = part.LocalId;
5672 shapeBlock.PathScaleX = 100;
5673 shapeBlock.PathScaleY = 150;
5674
5675 if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER &&
5676 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE &&
5677 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE &&
5678 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS)
5679 {
5680 // default
5681 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
5682 }
5683
5684 // retain pathcurve
5685 shapeBlock.PathCurve = part.Shape.PathCurve;
5686
5687 part.Shape.SetSculptData((byte)type, sculptId);
5688 part.Shape.SculptEntry = true;
5689 part.UpdateShape(shapeBlock);
5690 }
5691
5692 public void llSetPrimitiveParams(LSL_List rules)
5693 {
5694 SetPrimParams(m_host, rules);
5695 }
5696
5697 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
5698 {
5699 m_host.AddScriptLPS(1);
5700
5701 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5702
5703 foreach (SceneObjectPart part in parts)
5704 SetPrimParams(part, rules);
5705 }
5706
5707 private void SetPrimParams(SceneObjectPart part, LSL_List rules)
5708 {
5709 int idx = 0;
5710
5711 while (idx < rules.Length)
5712 {
5713 int code = rules.GetLSLIntegerItem(idx++);
5714
5715 int remain = rules.Length - idx;
5716
5717 int face;
5718 LSL_Vector v;
5719
5720 switch (code)
5721 {
5722 case (int)ScriptBaseClass.PRIM_POSITION:
5723 if (remain < 1)
5724 return;
5725
5726 v=rules.GetVector3Item(idx++);
5727 SetPos(part, v);
5728
5729 break;
5730 case (int)ScriptBaseClass.PRIM_SIZE:
5731 if (remain < 1)
5732 return;
5733
5734 v=rules.GetVector3Item(idx++);
5735 SetScale(part, v);
5736
5737 break;
5738 case (int)ScriptBaseClass.PRIM_ROTATION:
5739 if (remain < 1)
5740 return;
5741
5742 LSL_Rotation q = rules.GetQuaternionItem(idx++);
5743 SetRot(part, q);
5744
5745 break;
5746
5747 case (int)ScriptBaseClass.PRIM_TYPE:
5748 if (remain < 3)
5749 return;
5750
5751 code = (int)rules.GetLSLIntegerItem(idx++);
5752
5753 remain = rules.Length - idx;
5754 float hollow;
5755 LSL_Vector twist;
5756 LSL_Vector taper_b;
5757 LSL_Vector topshear;
5758 float revolutions;
5759 float radiusoffset;
5760 float skew;
5761 LSL_Vector holesize;
5762 LSL_Vector profilecut;
5763
5764 switch (code)
5765 {
5766 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
5767 if (remain < 6)
5768 return;
5769
5770 face = (int)rules.GetLSLIntegerItem(idx++);
5771 v = rules.GetVector3Item(idx++); // cut
5772 hollow = (float)rules.GetLSLFloatItem(idx++);
5773 twist = rules.GetVector3Item(idx++);
5774 taper_b = rules.GetVector3Item(idx++);
5775 topshear = rules.GetVector3Item(idx++);
5776
5777 part.Shape.PathCurve = (byte)Extrusion.Straight;
5778 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 1);
5779 break;
5780
5781 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
5782 if (remain < 6)
5783 return;
5784
5785 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5786 v = rules.GetVector3Item(idx++); // cut
5787 hollow = (float)rules.GetLSLFloatItem(idx++);
5788 twist = rules.GetVector3Item(idx++);
5789 taper_b = rules.GetVector3Item(idx++);
5790 topshear = rules.GetVector3Item(idx++);
5791 part.Shape.ProfileShape = ProfileShape.Circle;
5792 part.Shape.PathCurve = (byte)Extrusion.Straight;
5793 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 0);
5794 break;
5795
5796 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
5797 if (remain < 6)
5798 return;
5799
5800 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5801 v = rules.GetVector3Item(idx++); //cut
5802 hollow = (float)rules.GetLSLFloatItem(idx++);
5803 twist = rules.GetVector3Item(idx++);
5804 taper_b = rules.GetVector3Item(idx++);
5805 topshear = rules.GetVector3Item(idx++);
5806 part.Shape.PathCurve = (byte)Extrusion.Straight;
5807 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 3);
5808 break;
5809
5810 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
5811 if (remain < 5)
5812 return;
5813
5814 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5815 v = rules.GetVector3Item(idx++); // cut
5816 hollow = (float)rules.GetLSLFloatItem(idx++);
5817 twist = rules.GetVector3Item(idx++);
5818 taper_b = rules.GetVector3Item(idx++); // dimple
5819 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5820 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, 5);
5821 break;
5822
5823 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
5824 if (remain < 11)
5825 return;
5826
5827 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5828 v = rules.GetVector3Item(idx++); //cut
5829 hollow = (float)rules.GetLSLFloatItem(idx++);
5830 twist = rules.GetVector3Item(idx++);
5831 holesize = rules.GetVector3Item(idx++);
5832 topshear = rules.GetVector3Item(idx++);
5833 profilecut = rules.GetVector3Item(idx++);
5834 taper_b = rules.GetVector3Item(idx++); // taper_a
5835 revolutions = (float)rules.GetLSLFloatItem(idx++);
5836 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
5837 skew = (float)rules.GetLSLFloatItem(idx++);
5838 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5839 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 0);
5840 break;
5841
5842 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
5843 if (remain < 11)
5844 return;
5845
5846 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5847 v = rules.GetVector3Item(idx++); //cut
5848 hollow = (float)rules.GetLSLFloatItem(idx++);
5849 twist = rules.GetVector3Item(idx++);
5850 holesize = rules.GetVector3Item(idx++);
5851 topshear = rules.GetVector3Item(idx++);
5852 profilecut = rules.GetVector3Item(idx++);
5853 taper_b = rules.GetVector3Item(idx++); // taper_a
5854 revolutions = (float)rules.GetLSLFloatItem(idx++);
5855 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
5856 skew = (float)rules.GetLSLFloatItem(idx++);
5857 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5858 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 1);
5859 break;
5860
5861 case (int)ScriptBaseClass.PRIM_TYPE_RING:
5862 if (remain < 11)
5863 return;
5864
5865 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5866 v = rules.GetVector3Item(idx++); //cut
5867 hollow = (float)rules.GetLSLFloatItem(idx++);
5868 twist = rules.GetVector3Item(idx++);
5869 holesize = rules.GetVector3Item(idx++);
5870 topshear = rules.GetVector3Item(idx++);
5871 profilecut = rules.GetVector3Item(idx++);
5872 taper_b = rules.GetVector3Item(idx++); // taper_a
5873 revolutions = (float)rules.GetLSLFloatItem(idx++);
5874 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
5875 skew = (float)rules.GetLSLFloatItem(idx++);
5876 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5877 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 3);
5878 break;
5879
5880 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
5881 if (remain < 2)
5882 return;
5883
5884 string map = rules.Data[idx++].ToString();
5885 face = (int)rules.GetLSLIntegerItem(idx++); // type
5886 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5887 SetPrimitiveShapeParams(part, map, face);
5888 break;
5889 }
5890
5891 break;
5892
5893 case (int)ScriptBaseClass.PRIM_TEXTURE:
5894 if (remain < 5)
5895 return;
5896
5897 face=(int)rules.GetLSLIntegerItem(idx++);
5898 string tex=rules.Data[idx++].ToString();
5899 LSL_Vector repeats=rules.GetVector3Item(idx++);
5900 LSL_Vector offsets=rules.GetVector3Item(idx++);
5901 double rotation=(double)rules.GetLSLFloatItem(idx++);
5902
5903 SetTexture(part, tex, face);
5904 ScaleTexture(part, repeats.x, repeats.y, face);
5905 OffsetTexture(part, offsets.x, offsets.y, face);
5906 RotateTexture(part, rotation, face);
5907
5908 break;
5909
5910 case (int)ScriptBaseClass.PRIM_COLOR:
5911 if (remain < 3)
5912 return;
5913
5914 face=(int)rules.GetLSLIntegerItem(idx++);
5915 LSL_Vector color=rules.GetVector3Item(idx++);
5916 double alpha=(double)rules.GetLSLFloatItem(idx++);
5917
5918 SetColor(part, color, face);
5919 SetAlpha(part, alpha, face);
5920
5921 break;
5922 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
5923 if (remain < 7)
5924 return;
5925
5926 bool flexi = rules.GetLSLIntegerItem(idx++);
5927 int softness = rules.GetLSLIntegerItem(idx++);
5928 float gravity = (float)rules.GetLSLFloatItem(idx++);
5929 float friction = (float)rules.GetLSLFloatItem(idx++);
5930 float wind = (float)rules.GetLSLFloatItem(idx++);
5931 float tension = (float)rules.GetLSLFloatItem(idx++);
5932 LSL_Vector force = rules.GetVector3Item(idx++);
5933
5934 SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force);
5935
5936 break;
5937 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
5938 if (remain < 5)
5939 return;
5940 bool light = rules.GetLSLIntegerItem(idx++);
5941 LSL_Vector lightcolor = rules.GetVector3Item(idx++);
5942 float intensity = (float)rules.GetLSLFloatItem(idx++);
5943 float radius = (float)rules.GetLSLFloatItem(idx++);
5944 float falloff = (float)rules.GetLSLFloatItem(idx++);
5945
5946 SetPointLight(part, light, lightcolor, intensity, radius, falloff);
5947
5948 break;
5949 case (int)ScriptBaseClass.PRIM_GLOW:
5950 if (remain < 2)
5951 return;
5952 face = rules.GetLSLIntegerItem(idx++);
5953 float glow = (float)rules.GetLSLFloatItem(idx++);
5954
5955 SetGlow(part, face, glow);
5956
5957 break;
5958 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
5959 if (remain < 3)
5960 return;
5961 face = (int)rules.GetLSLIntegerItem(idx++);
5962 int shiny = (int)rules.GetLSLIntegerItem(idx++);
5963 Bumpiness bump = (Bumpiness)Convert.ToByte((int)rules.GetLSLIntegerItem(idx++));
5964
5965 SetShiny(part, face, shiny, bump);
5966
5967 break;
5968 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
5969 if (remain < 2)
5970 return;
5971 face = rules.GetLSLIntegerItem(idx++);
5972 bool st = rules.GetLSLIntegerItem(idx++);
5973 SetFullBright(part, face , st);
5974 break;
5975 case (int)ScriptBaseClass.PRIM_MATERIAL:
5976 if (remain < 1)
5977 return;
5978 if (part != null)
5979 {
5980 /* Unhandled at this time - sends "Unhandled" message
5981 will enable when available
5982 byte material = Convert.ToByte((int)rules.GetLSLIntegerItem(idx++));
5983 part.Material = material;
5984 */
5985 return;
5986 }
5987 break;
5988 case (int)ScriptBaseClass.PRIM_PHANTOM:
5989 if (remain < 1)
5990 return;
5991
5992 string ph = rules.Data[idx++].ToString();
5993 bool phantom;
5994
5995 if (ph.Equals("1"))
5996 phantom = true;
5997 else
5998 phantom = false;
5999
6000 part.ScriptSetPhantomStatus(phantom);
6001 part.ScheduleFullUpdate();
6002 break;
6003 case (int)ScriptBaseClass.PRIM_PHYSICS:
6004 if (remain < 1)
6005 return;
6006 string phy = rules.Data[idx++].ToString();
6007 bool physics;
6008
6009 if (phy.Equals("1"))
6010 physics = true;
6011 else
6012 physics = false;
6013
6014 m_host.ScriptSetPhysicsStatus(physics);
6015 part.ScheduleFullUpdate();
6016 break;
6017 }
6018 }
6019 }
6020
6021 public LSL_String llStringToBase64(string str)
6022 {
6023 m_host.AddScriptLPS(1);
6024 try
6025 {
6026 byte[] encData_byte = new byte[str.Length];
6027 encData_byte = Encoding.UTF8.GetBytes(str);
6028 string encodedData = Convert.ToBase64String(encData_byte);
6029 return encodedData;
6030 }
6031 catch (Exception e)
6032 {
6033 throw new Exception("Error in base64Encode" + e.Message);
6034 }
6035 }
6036
6037 public LSL_String llBase64ToString(string str)
6038 {
6039 m_host.AddScriptLPS(1);
6040 UTF8Encoding encoder = new UTF8Encoding();
6041 Decoder utf8Decode = encoder.GetDecoder();
6042 try
6043 {
6044 byte[] todecode_byte = Convert.FromBase64String(str);
6045 int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
6046 char[] decoded_char = new char[charCount];
6047 utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
6048 string result = new String(decoded_char);
6049 return result;
6050 }
6051 catch (Exception e)
6052 {
6053 throw new Exception("Error in base64Decode" + e.Message);
6054 }
6055 }
6056
6057 public void llXorBase64Strings()
6058 {
6059 m_host.AddScriptLPS(1);
6060 Deprecated("llXorBase64Strings");
6061 // ScriptSleep(300);
6062 }
6063
6064 public void llRemoteDataSetRegion()
6065 {
6066 m_host.AddScriptLPS(1);
6067 NotImplemented("llRemoteDataSetRegion");
6068 }
6069
6070 public LSL_Float llLog10(double val)
6071 {
6072 m_host.AddScriptLPS(1);
6073 return (double)Math.Log10(val);
6074 }
6075
6076 public LSL_Float llLog(double val)
6077 {
6078 m_host.AddScriptLPS(1);
6079 return (double)Math.Log(val);
6080 }
6081
6082 public LSL_List llGetAnimationList( string id )
6083 {
6084 m_host.AddScriptLPS(1);
6085
6086 LSL_List l = new LSL_List();
6087 ScenePresence av = World.GetScenePresence(id);
6088 if (av == null)
6089 return l;
6090 UUID[] anims;
6091 anims = av.GetAnimationArray();
6092 foreach (UUID foo in anims)
6093 l.Add(foo.ToString());
6094 return l;
6095 }
6096
6097 public void llSetParcelMusicURL(string url)
6098 {
6099 m_host.AddScriptLPS(1);
6100 UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
6101 if (landowner == UUID.Zero)
6102 {
6103 return;
6104 }
6105 if (landowner != m_host.ObjectOwner)
6106 {
6107 return;
6108 }
6109 World.SetLandMusicURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url);
6110 // ScriptSleep(2000);
6111 }
6112
6113 public LSL_Vector llGetRootPosition()
6114 {
6115 m_host.AddScriptLPS(1);
6116 return new LSL_Vector(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, m_host.ParentGroup.AbsolutePosition.Z);
6117 }
6118
6119 public LSL_Rotation llGetRootRotation()
6120 {
6121 m_host.AddScriptLPS(1);
6122 return new LSL_Rotation(m_host.ParentGroup.GroupRotation.X, m_host.ParentGroup.GroupRotation.Y, m_host.ParentGroup.GroupRotation.Z, m_host.ParentGroup.GroupRotation.W);
6123 }
6124
6125 public LSL_String llGetObjectDesc()
6126 {
6127 return m_host.Description!=null?m_host.Description:String.Empty;
6128 }
6129
6130 public void llSetObjectDesc(string desc)
6131 {
6132 m_host.AddScriptLPS(1);
6133 m_host.Description = desc!=null?desc:String.Empty;
6134 }
6135
6136 public LSL_String llGetCreator()
6137 {
6138 m_host.AddScriptLPS(1);
6139 return m_host.ObjectCreator.ToString();
6140 }
6141
6142 public LSL_String llGetTimestamp()
6143 {
6144 m_host.AddScriptLPS(1);
6145 return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
6146 }
6147
6148 public void llSetLinkAlpha(int linknumber, double alpha, int face)
6149 {
6150 m_host.AddScriptLPS(1);
6151 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber);
6152 if (linknumber > -1)
6153 {
6154 Primitive.TextureEntry tex = part.Shape.Textures;
6155 Color4 texcolor;
6156 if (face >= 0 && face < GetNumberOfSides(m_host))
6157 {
6158 texcolor = tex.CreateFace((uint)face).RGBA;
6159 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6160 tex.FaceTextures[face].RGBA = texcolor;
6161 part.UpdateTexture(tex);
6162 return;
6163 }
6164 else if (face == ScriptBaseClass.ALL_SIDES)
6165 {
6166 texcolor = tex.DefaultTexture.RGBA;
6167 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6168 tex.DefaultTexture.RGBA = texcolor;
6169 for (uint i = 0; i < GetNumberOfSides(m_host); i++)
6170 {
6171 if (tex.FaceTextures[i] != null)
6172 {
6173 texcolor = tex.FaceTextures[i].RGBA;
6174 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6175 tex.FaceTextures[i].RGBA = texcolor;
6176 }
6177 }
6178 texcolor = tex.DefaultTexture.RGBA;
6179 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6180 tex.DefaultTexture.RGBA = texcolor;
6181 part.UpdateTexture(tex);
6182 return;
6183 }
6184 return;
6185 }
6186 else if (linknumber == -1)
6187 {
6188 int num = m_host.ParentGroup.PrimCount;
6189 for (int w = 0; w < num; w++)
6190 {
6191 linknumber = w;
6192 part = m_host.ParentGroup.GetLinkNumPart(linknumber);
6193 Primitive.TextureEntry tex = part.Shape.Textures;
6194 Color4 texcolor;
6195 if (face > -1)
6196 {
6197 texcolor = tex.CreateFace((uint)face).RGBA;
6198 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6199 tex.FaceTextures[face].RGBA = texcolor;
6200 part.UpdateTexture(tex);
6201 }
6202 else if (face == -1)
6203 {
6204 texcolor = tex.DefaultTexture.RGBA;
6205 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6206 tex.DefaultTexture.RGBA = texcolor;
6207 for (uint i = 0; i < 32; i++)
6208 {
6209 if (tex.FaceTextures[i] != null)
6210 {
6211 texcolor = tex.FaceTextures[i].RGBA;
6212 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6213 tex.FaceTextures[i].RGBA = texcolor;
6214 }
6215 }
6216 texcolor = tex.DefaultTexture.RGBA;
6217 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6218 tex.DefaultTexture.RGBA = texcolor;
6219 part.UpdateTexture(tex);
6220 }
6221 }
6222 return;
6223 }
6224 }
6225
6226 public LSL_Integer llGetNumberOfPrims()
6227 {
6228 m_host.AddScriptLPS(1);
6229 return m_host.ParentGroup.PrimCount;
6230 }
6231
6232 public LSL_List llGetBoundingBox(string obj)
6233 {
6234 m_host.AddScriptLPS(1);
6235 NotImplemented("llGetBoundingBox");
6236 return new LSL_List();
6237 }
6238
6239 public LSL_Vector llGetGeometricCenter()
6240 {
6241 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z);
6242 }
6243
6244 public LSL_List llGetPrimitiveParams(LSL_List rules)
6245 {
6246 m_host.AddScriptLPS(1);
6247
6248 LSL_List res = new LSL_List();
6249 int idx=0;
6250 while (idx < rules.Length)
6251 {
6252 int code=(int)rules.GetLSLIntegerItem(idx++);
6253 int remain=rules.Length-idx;
6254
6255 switch (code)
6256 {
6257 case (int)ScriptBaseClass.PRIM_MATERIAL:
6258 res.Add(new LSL_Integer(m_host.Material));
6259 break;
6260
6261 case (int)ScriptBaseClass.PRIM_PHYSICS:
6262 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0)
6263 res.Add(new LSL_Integer(1));
6264 else
6265 res.Add(new LSL_Integer(0));
6266 break;
6267
6268 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
6269 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0)
6270 res.Add(new LSL_Integer(1));
6271 else
6272 res.Add(new LSL_Integer(0));
6273 break;
6274
6275 case (int)ScriptBaseClass.PRIM_PHANTOM:
6276 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
6277 res.Add(new LSL_Integer(1));
6278 else
6279 res.Add(new LSL_Integer(0));
6280 break;
6281
6282 case (int)ScriptBaseClass.PRIM_POSITION:
6283 res.Add(new LSL_Vector(m_host.AbsolutePosition.X,
6284 m_host.AbsolutePosition.Y,
6285 m_host.AbsolutePosition.Z));
6286 break;
6287
6288 case (int)ScriptBaseClass.PRIM_SIZE:
6289 res.Add(new LSL_Vector(m_host.Scale.X,
6290 m_host.Scale.Y,
6291 m_host.Scale.Z));
6292 break;
6293
6294 case (int)ScriptBaseClass.PRIM_ROTATION:
6295 res.Add(new LSL_Rotation(m_host.RotationOffset.X,
6296 m_host.RotationOffset.Y,
6297 m_host.RotationOffset.Z,
6298 m_host.RotationOffset.W));
6299 break;
6300
6301 case (int)ScriptBaseClass.PRIM_TYPE:
6302 // implementing box
6303 PrimitiveBaseShape Shape = m_host.Shape;
6304 int primType = getScriptPrimType(m_host.Shape);
6305 res.Add(new LSL_Integer(primType));
6306 switch (primType)
6307 {
6308 case ScriptBaseClass.PRIM_TYPE_BOX:
6309 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
6310 case ScriptBaseClass.PRIM_TYPE_PRISM:
6311 res.Add(new LSL_Integer(Shape.ProfileCurve));
6312 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
6313 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
6314 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
6315 res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
6316 res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0));
6317 break;
6318
6319 case ScriptBaseClass.PRIM_TYPE_SPHERE:
6320 res.Add(new LSL_Integer(Shape.ProfileCurve));
6321 res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
6322 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
6323 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
6324 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
6325 break;
6326
6327 case ScriptBaseClass.PRIM_TYPE_SCULPT:
6328 res.Add(Shape.SculptTexture.ToString());
6329 res.Add(new LSL_Integer(Shape.SculptType));
6330 break;
6331
6332 case ScriptBaseClass.PRIM_TYPE_RING:
6333 case ScriptBaseClass.PRIM_TYPE_TUBE:
6334 case ScriptBaseClass.PRIM_TYPE_TORUS:
6335 // holeshape
6336 res.Add(new LSL_Integer(Shape.ProfileCurve));
6337
6338 // cut
6339 res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
6340
6341 // hollow
6342 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
6343
6344 // twist
6345 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
6346
6347 // vector holesize
6348 res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
6349
6350 // vector topshear
6351 res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0));
6352
6353 // vector profilecut
6354 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
6355
6356
6357 // vector tapera
6358 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
6359
6360 // float revolutions,
6361 res.Add(new LSL_Float(Shape.PathRevolutions / 50.0)); // needs fixing :(
6362
6363 // float radiusoffset,
6364 res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));
6365
6366 // float skew
6367 res.Add(new LSL_Float(Shape.PathSkew / 100.0));
6368 break;
6369
6370 }
6371 break;
6372
6373 case (int)ScriptBaseClass.PRIM_TEXTURE:
6374 if (remain < 1)
6375 return res;
6376
6377 int face = (int)rules.GetLSLIntegerItem(idx++);
6378 Primitive.TextureEntry tex = m_host.Shape.Textures;
6379 if (face == ScriptBaseClass.ALL_SIDES)
6380 {
6381 for (face = 0 ; face < GetNumberOfSides(m_host) ; face++)
6382 {
6383 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
6384
6385 res.Add(new LSL_String(texface.TextureID.ToString()));
6386 res.Add(new LSL_Vector(texface.RepeatU,
6387 texface.RepeatV,
6388 0));
6389 res.Add(new LSL_Vector(texface.OffsetU,
6390 texface.OffsetV,
6391 0));
6392 res.Add(new LSL_Float(texface.Rotation));
6393 }
6394 }
6395 else
6396 {
6397 if (face >= 0 && face < GetNumberOfSides(m_host))
6398 {
6399 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
6400
6401 res.Add(new LSL_String(texface.TextureID.ToString()));
6402 res.Add(new LSL_Vector(texface.RepeatU,
6403 texface.RepeatV,
6404 0));
6405 res.Add(new LSL_Vector(texface.OffsetU,
6406 texface.OffsetV,
6407 0));
6408 res.Add(new LSL_Float(texface.Rotation));
6409 }
6410 }
6411 break;
6412
6413 case (int)ScriptBaseClass.PRIM_COLOR:
6414 if (remain < 1)
6415 return res;
6416
6417 face=(int)rules.GetLSLIntegerItem(idx++);
6418
6419 tex = m_host.Shape.Textures;
6420 Color4 texcolor;
6421 if (face == ScriptBaseClass.ALL_SIDES)
6422 {
6423 for (face = 0 ; face < GetNumberOfSides(m_host) ; face++)
6424 {
6425 texcolor = tex.GetFace((uint)face).RGBA;
6426 res.Add(new LSL_Vector(texcolor.R,
6427 texcolor.G,
6428 texcolor.B));
6429 res.Add(new LSL_Float(texcolor.A));
6430 }
6431 }
6432 else
6433 {
6434 texcolor = tex.GetFace((uint)face).RGBA;
6435 res.Add(new LSL_Vector(texcolor.R,
6436 texcolor.G,
6437 texcolor.B));
6438 res.Add(new LSL_Float(texcolor.A));
6439 }
6440 break;
6441
6442 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
6443 // TODO--------------
6444 if (remain < 1)
6445 return res;
6446
6447 face=(int)rules.GetLSLIntegerItem(idx++);
6448
6449 res.Add(new LSL_Integer(0));
6450 res.Add(new LSL_Integer(0));
6451 break;
6452
6453 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
6454 // TODO--------------
6455 if (remain < 1)
6456 return res;
6457
6458 face=(int)rules.GetLSLIntegerItem(idx++);
6459
6460 res.Add(new LSL_Integer(0));
6461 break;
6462
6463 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
6464 PrimitiveBaseShape shape = m_host.Shape;
6465
6466 if (shape.FlexiEntry)
6467 res.Add(new LSL_Integer(1)); // active
6468 else
6469 res.Add(new LSL_Integer(0));
6470 res.Add(new LSL_Integer(shape.FlexiSoftness));// softness
6471 res.Add(new LSL_Float(shape.FlexiGravity)); // gravity
6472 res.Add(new LSL_Float(shape.FlexiDrag)); // friction
6473 res.Add(new LSL_Float(shape.FlexiWind)); // wind
6474 res.Add(new LSL_Float(shape.FlexiTension)); // tension
6475 res.Add(new LSL_Vector(shape.FlexiForceX, // force
6476 shape.FlexiForceY,
6477 shape.FlexiForceZ));
6478 break;
6479
6480 case (int)ScriptBaseClass.PRIM_TEXGEN:
6481 // TODO--------------
6482 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
6483 if (remain < 1)
6484 return res;
6485
6486 face=(int)rules.GetLSLIntegerItem(idx++);
6487
6488 res.Add(new LSL_Integer(0));
6489 break;
6490
6491 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
6492 shape = m_host.Shape;
6493
6494 if (shape.LightEntry)
6495 res.Add(new LSL_Integer(1)); // active
6496 else
6497 res.Add(new LSL_Integer(0));
6498 res.Add(new LSL_Vector(shape.LightColorR, // color
6499 shape.LightColorG,
6500 shape.LightColorB));
6501 res.Add(new LSL_Float(shape.LightIntensity)); // intensity
6502 res.Add(new LSL_Float(shape.LightRadius)); // radius
6503 res.Add(new LSL_Float(shape.LightFalloff)); // falloff
6504 break;
6505
6506 case (int)ScriptBaseClass.PRIM_GLOW:
6507 // TODO--------------
6508 if (remain < 1)
6509 return res;
6510
6511 face=(int)rules.GetLSLIntegerItem(idx++);
6512
6513 res.Add(new LSL_Float(0));
6514 break;
6515 }
6516 }
6517 return res;
6518 }
6519
6520 // <remarks>
6521 // <para>
6522 // The .NET definition of base 64 is:
6523 // <list>
6524 // <item>
6525 // Significant: A-Z a-z 0-9 + -
6526 // </item>
6527 // <item>
6528 // Whitespace: \t \n \r ' '
6529 // </item>
6530 // <item>
6531 // Valueless: =
6532 // </item>
6533 // <item>
6534 // End-of-string: \0 or '=='
6535 // </item>
6536 // </list>
6537 // </para>
6538 // <para>
6539 // Each point in a base-64 string represents
6540 // a 6 bit value. A 32-bit integer can be
6541 // represented using 6 characters (with some
6542 // redundancy).
6543 // </para>
6544 // <para>
6545 // LSL requires a base64 string to be 8
6546 // characters in length. LSL also uses '/'
6547 // rather than '-' (MIME compliant).
6548 // </para>
6549 // <para>
6550 // RFC 1341 used as a reference (as specified
6551 // by the SecondLife Wiki).
6552 // </para>
6553 // <para>
6554 // SL do not record any kind of exception for
6555 // these functions, so the string to integer
6556 // conversion returns '0' if an invalid
6557 // character is encountered during conversion.
6558 // </para>
6559 // <para>
6560 // References
6561 // <list>
6562 // <item>
6563 // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64
6564 // </item>
6565 // <item>
6566 // </item>
6567 // </list>
6568 // </para>
6569 // </remarks>
6570
6571 // <summary>
6572 // Table for converting 6-bit integers into
6573 // base-64 characters
6574 // </summary>
6575
6576 private static readonly char[] i2ctable =
6577 {
6578 'A','B','C','D','E','F','G','H',
6579 'I','J','K','L','M','N','O','P',
6580 'Q','R','S','T','U','V','W','X',
6581 'Y','Z',
6582 'a','b','c','d','e','f','g','h',
6583 'i','j','k','l','m','n','o','p',
6584 'q','r','s','t','u','v','w','x',
6585 'y','z',
6586 '0','1','2','3','4','5','6','7',
6587 '8','9',
6588 '+','/'
6589 };
6590
6591 // <summary>
6592 // Table for converting base-64 characters
6593 // into 6-bit integers.
6594 // </summary>
6595
6596 private static readonly int[] c2itable =
6597 {
6598 -1,-1,-1,-1,-1,-1,-1,-1, // 0x
6599 -1,-1,-1,-1,-1,-1,-1,-1,
6600 -1,-1,-1,-1,-1,-1,-1,-1, // 1x
6601 -1,-1,-1,-1,-1,-1,-1,-1,
6602 -1,-1,-1,-1,-1,-1,-1,-1, // 2x
6603 -1,-1,-1,63,-1,-1,-1,64,
6604 53,54,55,56,57,58,59,60, // 3x
6605 61,62,-1,-1,-1,0,-1,-1,
6606 -1,1,2,3,4,5,6,7, // 4x
6607 8,9,10,11,12,13,14,15,
6608 16,17,18,19,20,21,22,23, // 5x
6609 24,25,26,-1,-1,-1,-1,-1,
6610 -1,27,28,29,30,31,32,33, // 6x
6611 34,35,36,37,38,39,40,41,
6612 42,43,44,45,46,47,48,49, // 7x
6613 50,51,52,-1,-1,-1,-1,-1,
6614 -1,-1,-1,-1,-1,-1,-1,-1, // 8x
6615 -1,-1,-1,-1,-1,-1,-1,-1,
6616 -1,-1,-1,-1,-1,-1,-1,-1, // 9x
6617 -1,-1,-1,-1,-1,-1,-1,-1,
6618 -1,-1,-1,-1,-1,-1,-1,-1, // Ax
6619 -1,-1,-1,-1,-1,-1,-1,-1,
6620 -1,-1,-1,-1,-1,-1,-1,-1, // Bx
6621 -1,-1,-1,-1,-1,-1,-1,-1,
6622 -1,-1,-1,-1,-1,-1,-1,-1, // Cx
6623 -1,-1,-1,-1,-1,-1,-1,-1,
6624 -1,-1,-1,-1,-1,-1,-1,-1, // Dx
6625 -1,-1,-1,-1,-1,-1,-1,-1,
6626 -1,-1,-1,-1,-1,-1,-1,-1, // Ex
6627 -1,-1,-1,-1,-1,-1,-1,-1,
6628 -1,-1,-1,-1,-1,-1,-1,-1, // Fx
6629 -1,-1,-1,-1,-1,-1,-1,-1
6630 };
6631
6632 // <summary>
6633 // Converts a 32-bit integer into a Base64
6634 // character string. Base64 character strings
6635 // are always 8 characters long. All iinteger
6636 // values are acceptable.
6637 // </summary>
6638 // <param name="number">
6639 // 32-bit integer to be converted.
6640 // </param>
6641 // <returns>
6642 // 8 character string. The 1st six characters
6643 // contain the encoded number, the last two
6644 // characters are padded with "=".
6645 // </returns>
6646
6647 public LSL_String llIntegerToBase64(int number)
6648 {
6649 // uninitialized string
6650
6651 char[] imdt = new char[8];
6652
6653 m_host.AddScriptLPS(1);
6654
6655 // Manually unroll the loop
6656
6657 imdt[7] = '=';
6658 imdt[6] = '=';
6659 imdt[5] = i2ctable[number<<4 & 0x3F];
6660 imdt[4] = i2ctable[number>>2 & 0x3F];
6661 imdt[3] = i2ctable[number>>8 & 0x3F];
6662 imdt[2] = i2ctable[number>>14 & 0x3F];
6663 imdt[1] = i2ctable[number>>20 & 0x3F];
6664 imdt[0] = i2ctable[number>>26 & 0x3F];
6665
6666 return new string(imdt);
6667 }
6668
6669 // <summary>
6670 // Converts an eight character base-64 string
6671 // into a 32-bit integer.
6672 // </summary>
6673 // <param name="str">
6674 // 8 characters string to be converted. Other
6675 // length strings return zero.
6676 // </param>
6677 // <returns>
6678 // Returns an integer representing the
6679 // encoded value providedint he 1st 6
6680 // characters of the string.
6681 // </returns>
6682 // <remarks>
6683 // This is coded to behave like LSL's
6684 // implementation (I think), based upon the
6685 // information available at the Wiki.
6686 // If more than 8 characters are supplied,
6687 // zero is returned.
6688 // If a NULL string is supplied, zero will
6689 // be returned.
6690 // If fewer than 6 characters are supplied, then
6691 // the answer will reflect a partial
6692 // accumulation.
6693 // <para>
6694 // The 6-bit segments are
6695 // extracted left-to-right in big-endian mode,
6696 // which means that segment 6 only contains the
6697 // two low-order bits of the 32 bit integer as
6698 // its high order 2 bits. A short string therefore
6699 // means loss of low-order information. E.g.
6700 //
6701 // |<---------------------- 32-bit integer ----------------------->|<-Pad->|
6702 // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->|
6703 // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P|
6704 // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P|
6705 // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] |
6706 //
6707 // </para>
6708 // </remarks>
6709
6710 public LSL_Integer llBase64ToInteger(string str)
6711 {
6712 int number = 0;
6713 int digit;
6714
6715 m_host.AddScriptLPS(1);
6716
6717 // Require a well-fromed base64 string
6718
6719 if (str.Length > 8)
6720 return 0;
6721
6722 // The loop is unrolled in the interests
6723 // of performance and simple necessity.
6724 //
6725 // MUST find 6 digits to be well formed
6726 // -1 == invalid
6727 // 0 == padding
6728
6729 if ((digit=c2itable[str[0]])<=0)
6730 {
6731 return digit<0?(int)0:number;
6732 }
6733 number += --digit<<26;
6734
6735 if ((digit=c2itable[str[1]])<=0)
6736 {
6737 return digit<0?(int)0:number;
6738 }
6739 number += --digit<<20;
6740
6741 if ((digit=c2itable[str[2]])<=0)
6742 {
6743 return digit<0?(int)0:number;
6744 }
6745 number += --digit<<14;
6746
6747 if ((digit=c2itable[str[3]])<=0)
6748 {
6749 return digit<0?(int)0:number;
6750 }
6751 number += --digit<<8;
6752
6753 if ((digit=c2itable[str[4]])<=0)
6754 {
6755 return digit<0?(int)0:number;
6756 }
6757 number += --digit<<2;
6758
6759 if ((digit=c2itable[str[5]])<=0)
6760 {
6761 return digit<0?(int)0:number;
6762 }
6763 number += --digit>>4;
6764
6765 // ignore trailing padding
6766
6767 return number;
6768 }
6769
6770 public LSL_Float llGetGMTclock()
6771 {
6772 m_host.AddScriptLPS(1);
6773 return DateTime.UtcNow.TimeOfDay.TotalSeconds;
6774 }
6775
6776 public LSL_String llGetSimulatorHostname()
6777 {
6778 m_host.AddScriptLPS(1);
6779 return System.Environment.MachineName;
6780 }
6781
6782 public void llSetLocalRot(LSL_Rotation rot)
6783 {
6784 m_host.AddScriptLPS(1);
6785 m_host.RotationOffset = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
6786 // ScriptSleep(200);
6787 }
6788
6789 // <summary>
6790 // Scan the string supplied in 'src' and
6791 // tokenize it based upon two sets of
6792 // tokenizers provided in two lists,
6793 // separators and spacers.
6794 // </summary>
6795 //
6796 // <remarks>
6797 // Separators demarcate tokens and are
6798 // elided as they are encountered. Spacers
6799 // also demarcate tokens, but are themselves
6800 // retained as tokens.
6801 //
6802 // Both separators and spacers may be arbitrarily
6803 // long strings. i.e. ":::".
6804 //
6805 // The function returns an ordered list
6806 // representing the tokens found in the supplied
6807 // sources string. If two successive tokenizers
6808 // are encountered, then a NULL entry is added
6809 // to the list.
6810 //
6811 // It is a precondition that the source and
6812 // toekizer lisst are non-null. If they are null,
6813 // then a null pointer exception will be thrown
6814 // while their lengths are being determined.
6815 //
6816 // A small amount of working memoryis required
6817 // of approximately 8*#tokenizers.
6818 //
6819 // There are many ways in which this function
6820 // can be implemented, this implementation is
6821 // fairly naive and assumes that when the
6822 // function is invooked with a short source
6823 // string and/or short lists of tokenizers, then
6824 // performance will not be an issue.
6825 //
6826 // In order to minimize the perofrmance
6827 // effects of long strings, or large numbers
6828 // of tokeizers, the function skips as far as
6829 // possible whenever a toekenizer is found,
6830 // and eliminates redundant tokenizers as soon
6831 // as is possible.
6832 //
6833 // The implementation tries to avoid any copying
6834 // of arrays or other objects.
6835 // </remarks>
6836
6837 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
6838 {
6839 int beginning = 0;
6840 int srclen = src.Length;
6841 int seplen = separators.Length;
6842 object[] separray = separators.Data;
6843 int spclen = spacers.Length;
6844 object[] spcarray = spacers.Data;
6845 int mlen = seplen+spclen;
6846
6847 int[] offset = new int[mlen+1];
6848 bool[] active = new bool[mlen];
6849
6850 int best;
6851 int j;
6852
6853 // Initial capacity reduces resize cost
6854
6855 LSL_List tokens = new LSL_List();
6856
6857 m_host.AddScriptLPS(1);
6858
6859 // All entries are initially valid
6860
6861 for (int i = 0; i < mlen; i++)
6862 active[i] = true;
6863
6864 offset[mlen] = srclen;
6865
6866 while (beginning < srclen)
6867 {
6868
6869 best = mlen; // as bad as it gets
6870
6871 // Scan for separators
6872
6873 for (j = 0; j < seplen; j++)
6874 {
6875 if (active[j])
6876 {
6877 // scan all of the markers
6878 if ((offset[j] = src.IndexOf(separray[j].ToString(),beginning)) == -1)
6879 {
6880 // not present at all
6881 active[j] = false;
6882 }
6883 else
6884 {
6885 // present and correct
6886 if (offset[j] < offset[best])
6887 {
6888 // closest so far
6889 best = j;
6890 if (offset[best] == beginning)
6891 break;
6892 }
6893 }
6894 }
6895 }
6896
6897 // Scan for spacers
6898
6899 if (offset[best] != beginning)
6900 {
6901 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++)
6902 {
6903 if (active[j])
6904 {
6905 // scan all of the markers
6906 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
6907 {
6908 // not present at all
6909 active[j] = false;
6910 }
6911 else
6912 {
6913 // present and correct
6914 if (offset[j] < offset[best])
6915 {
6916 // closest so far
6917 best = j;
6918 }
6919 }
6920 }
6921 }
6922 }
6923
6924 // This is the normal exit from the scanning loop
6925
6926 if (best == mlen)
6927 {
6928 // no markers were found on this pass
6929 // so we're pretty much done
6930 tokens.Add(src.Substring(beginning, srclen - beginning));
6931 break;
6932 }
6933
6934 // Otherwise we just add the newly delimited token
6935 // and recalculate where the search should continue.
6936
6937 tokens.Add(src.Substring(beginning,offset[best]-beginning));
6938
6939 if (best < seplen)
6940 {
6941 beginning = offset[best] + (separray[best].ToString()).Length;
6942 }
6943 else
6944 {
6945 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
6946 tokens.Add(spcarray[best - seplen]);
6947 }
6948 }
6949
6950 // This an awkward an not very intuitive boundary case. If the
6951 // last substring is a tokenizer, then there is an implied trailing
6952 // null list entry. Hopefully the single comparison will not be too
6953 // arduous. Alternatively the 'break' could be replced with a return
6954 // but that's shabby programming.
6955
6956 if (beginning == srclen)
6957 {
6958 if (srclen != 0)
6959 tokens.Add("");
6960 }
6961
6962 return tokens;
6963 }
6964
6965 public LSL_Integer llGetObjectPermMask(int mask)
6966 {
6967 m_host.AddScriptLPS(1);
6968
6969 int permmask = 0;
6970
6971 if (mask == ScriptBaseClass.MASK_BASE)//0
6972 {
6973 permmask = (int)m_host.BaseMask;
6974 }
6975
6976 else if (mask == ScriptBaseClass.MASK_OWNER)//1
6977 {
6978 permmask = (int)m_host.OwnerMask;
6979 }
6980
6981 else if (mask == ScriptBaseClass.MASK_GROUP)//2
6982 {
6983 permmask = (int)m_host.GroupMask;
6984 }
6985
6986 else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
6987 {
6988 permmask = (int)m_host.EveryoneMask;
6989 }
6990
6991 else if (mask == ScriptBaseClass.MASK_NEXT)//4
6992 {
6993 permmask = (int)m_host.NextOwnerMask;
6994 }
6995
6996 return permmask;
6997 }
6998
6999 public void llSetObjectPermMask(int mask, int value)
7000 {
7001 m_host.AddScriptLPS(1);
7002 IConfigSource config = new IniConfigSource(Application.iniFilePath);
7003 if (config.Configs["XEngine"] == null)
7004 config.AddConfig("XEngine");
7005
7006 if (config.Configs["XEngine"].GetBoolean("AllowGodFunctions", false))
7007 {
7008 if (World.ExternalChecks.ExternalChecksCanRunConsoleCommand(m_host.OwnerID))
7009 {
7010 if (mask == ScriptBaseClass.MASK_BASE)//0
7011 {
7012 m_host.BaseMask = (uint)value;
7013 }
7014
7015 else if (mask == ScriptBaseClass.MASK_OWNER)//1
7016 {
7017 m_host.OwnerMask = (uint)value;
7018 }
7019
7020 else if (mask == ScriptBaseClass.MASK_GROUP)//2
7021 {
7022 m_host.GroupMask = (uint)value;
7023 }
7024
7025 else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
7026 {
7027 m_host.EveryoneMask = (uint)value;
7028 }
7029
7030 else if (mask == ScriptBaseClass.MASK_NEXT)//4
7031 {
7032 m_host.NextOwnerMask = (uint)value;
7033 }
7034 }
7035 }
7036 }
7037
7038 public LSL_Integer llGetInventoryPermMask(string item, int mask)
7039 {
7040 m_host.AddScriptLPS(1);
7041 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
7042 {
7043 if (inv.Value.Name == item)
7044 {
7045 switch (mask)
7046 {
7047 case 0:
7048 return (int)inv.Value.BasePermissions;
7049 case 1:
7050 return (int)inv.Value.CurrentPermissions;
7051 case 2:
7052 return (int)inv.Value.GroupPermissions;
7053 case 3:
7054 return (int)inv.Value.EveryonePermissions;
7055 case 4:
7056 return (int)inv.Value.NextPermissions;
7057 }
7058 }
7059 }
7060 return -1;
7061 }
7062
7063 public void llSetInventoryPermMask(string item, int mask, int value)
7064 {
7065 m_host.AddScriptLPS(1);
7066 NotImplemented("llSetInventoryPermMask");
7067 }
7068
7069 public LSL_String llGetInventoryCreator(string item)
7070 {
7071 m_host.AddScriptLPS(1);
7072 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
7073 {
7074 if (inv.Value.Name == item)
7075 {
7076 return inv.Value.CreatorID.ToString();
7077 }
7078 }
7079 llSay(0, "No item name '" + item + "'");
7080 return String.Empty;
7081 }
7082
7083 public void llOwnerSay(string msg)
7084 {
7085 m_host.AddScriptLPS(1);
7086
7087 World.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
7088// IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
7089// wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg);
7090 }
7091
7092 public LSL_String llRequestSimulatorData(string simulator, int data)
7093 {
7094 try
7095 {
7096 m_host.AddScriptLPS(1);
7097
7098 string reply = String.Empty;
7099
7100 RegionInfo info = m_ScriptEngine.World.RequestClosestRegion(simulator);
7101
7102 switch (data)
7103 {
7104 case 5: // DATA_SIM_POS
7105 if (info == null)
7106 {
7107 // ScriptSleep(1000);
7108 return UUID.Zero.ToString();
7109 }
7110 reply = new LSL_Vector(
7111 info.RegionLocX * Constants.RegionSize,
7112 info.RegionLocY * Constants.RegionSize,
7113 0).ToString();
7114 break;
7115 case 6: // DATA_SIM_STATUS
7116 if (info != null)
7117 reply = "up"; // Duh!
7118 else
7119 reply = "unknown";
7120 break;
7121 case 7: // DATA_SIM_RATING
7122 if (info == null)
7123 {
7124 // ScriptSleep(1000);
7125 return UUID.Zero.ToString();
7126 }
7127 int access = info.RegionSettings.Maturity;
7128 if (access == 0)
7129 reply = "PG";
7130 else if (access == 1)
7131 reply = "MATURE";
7132 else
7133 reply = "UNKNOWN";
7134 break;
7135 case 128: // SIM_RELEASE
7136 reply = m_ScriptEngine.World.GetSimulatorVersion();
7137 break;
7138 default:
7139 // ScriptSleep(1000);
7140 return UUID.Zero.ToString(); // Raise no event
7141 }
7142 UUID rq = UUID.Random();
7143
7144 UUID tid = AsyncCommands.
7145 DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString());
7146
7147 AsyncCommands.
7148 DataserverPlugin.DataserverReply(rq.ToString(), reply);
7149
7150 // ScriptSleep(1000);
7151 return tid.ToString();
7152 }
7153 catch(Exception e)
7154 {
7155 Console.WriteLine(e.ToString());
7156 return UUID.Zero.ToString();
7157 }
7158 }
7159
7160 public void llForceMouselook(int mouselook)
7161 {
7162 m_host.AddScriptLPS(1);
7163 m_host.SetForceMouselook(mouselook != 0);
7164 }
7165
7166 public LSL_Float llGetObjectMass(string id)
7167 {
7168 m_host.AddScriptLPS(1);
7169 UUID key = new UUID();
7170 if (UUID.TryParse(id, out key))
7171 {
7172 try
7173 {
7174 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
7175 if (obj != null)
7176 return (double)obj.GetMass();
7177 // the object is null so the key is for an avatar
7178 ScenePresence avatar = World.GetScenePresence(key);
7179 if (avatar != null)
7180 if (avatar.IsChildAgent)
7181 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
7182 // child agents have a mass of 1.0
7183 return 1;
7184 else
7185 return (double)avatar.PhysicsActor.Mass;
7186 }
7187 catch (KeyNotFoundException)
7188 {
7189 return 0; // The Object/Agent not in the region so just return zero
7190 }
7191 }
7192 return 0;
7193 }
7194
7195 /// <summary>
7196 /// illListReplaceList removes the sub-list defined by the inclusive indices
7197 /// start and end and inserts the src list in its place. The inclusive
7198 /// nature of the indices means that at least one element must be deleted
7199 /// if the indices are within the bounds of the existing list. I.e. 2,2
7200 /// will remove the element at index 2 and replace it with the source
7201 /// list. Both indices may be negative, with the usual interpretation. An
7202 /// interesting case is where end is lower than start. As these indices
7203 /// bound the list to be removed, then 0->end, and start->lim are removed
7204 /// and the source list is added as a suffix.
7205 /// </summary>
7206
7207 public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end)
7208 {
7209 LSL_List pref = null;
7210
7211 m_host.AddScriptLPS(1);
7212
7213 // Note that although we have normalized, both
7214 // indices could still be negative.
7215 if (start < 0)
7216 {
7217 start = start+dest.Length;
7218 }
7219
7220 if (end < 0)
7221 {
7222 end = end+dest.Length;
7223 }
7224 // The comventional case, remove a sequence starting with
7225 // start and ending with end. And then insert the source
7226 // list.
7227 if (start <= end)
7228 {
7229 // If greater than zero, then there is going to be a
7230 // surviving prefix. Otherwise the inclusive nature
7231 // of the indices mean that we're going to add the
7232 // source list as a prefix.
7233 if (start > 0)
7234 {
7235 pref = dest.GetSublist(0,start-1);
7236 // Only add a suffix if there is something
7237 // beyond the end index (it's inclusive too).
7238 if (end + 1 < dest.Length)
7239 {
7240 return pref + src + dest.GetSublist(end + 1, -1);
7241 }
7242 else
7243 {
7244 return pref + src;
7245 }
7246 }
7247 // If start is less than or equal to zero, then
7248 // the new list is simply a prefix. We still need to
7249 // figure out any necessary surgery to the destination
7250 // based upon end. Note that if end exceeds the upper
7251 // bound in this case, the entire destination list
7252 // is removed.
7253 else
7254 {
7255 if (end + 1 < dest.Length)
7256 {
7257 return src + dest.GetSublist(end + 1, -1);
7258 }
7259 else
7260 {
7261 return src;
7262 }
7263 }
7264 }
7265 // Finally, if start > end, we strip away a prefix and
7266 // a suffix, to leave the list that sits <between> ens
7267 // and start, and then tag on the src list. AT least
7268 // that's my interpretation. We can get sublist to do
7269 // this for us. Note that one, or both of the indices
7270 // might have been negative.
7271 else
7272 {
7273 return dest.GetSublist(end + 1, start - 1) + src;
7274 }
7275 }
7276
7277 public void llLoadURL(string avatar_id, string message, string url)
7278 {
7279 m_host.AddScriptLPS(1);
7280 UUID avatarId = new UUID(avatar_id);
7281 m_ScriptEngine.World.SendUrlToUser(avatarId, m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message,
7282 url);
7283 // ScriptSleep(10000);
7284 }
7285
7286 public void llParcelMediaCommandList(LSL_List commandList)
7287 {
7288 //TO DO: Implement the missing commands
7289 //PARCEL_MEDIA_COMMAND_STOP Stop the media stream and go back to the first frame.
7290 //PARCEL_MEDIA_COMMAND_PAUSE Pause the media stream (stop playing but stay on current frame).
7291 //PARCEL_MEDIA_COMMAND_PLAY Start the media stream playing from the current frame and stop when the end is reached.
7292 //PARCEL_MEDIA_COMMAND_LOOP Start the media stream playing from the current frame. When the end is reached, loop to the beginning and continue.
7293 //PARCEL_MEDIA_COMMAND_TEXTURE key uuid Use this to get or set the parcel's media texture.
7294 //PARCEL_MEDIA_COMMAND_URL string url Used to get or set the parcel's media url.
7295 //PARCEL_MEDIA_COMMAND_TIME float time Move a media stream to a specific time.
7296 //PARCEL_MEDIA_COMMAND_AGENT key uuid Applies the media command to the specified agent only.
7297 //PARCEL_MEDIA_COMMAND_UNLOAD Completely unloads the movie and restores the original texture.
7298 //PARCEL_MEDIA_COMMAND_AUTO_ALIGN integer boolean Sets the parcel option 'Auto scale content'.
7299 //PARCEL_MEDIA_COMMAND_TYPE string mime_type Use this to get or set the parcel media MIME type (e.g. "text/html"). (1.19.1 RC0 or later)
7300 //PARCEL_MEDIA_COMMAND_SIZE integer x, integer y Use this to get or set the parcel media pixel resolution. (1.19.1 RC0 or later)
7301 //PARCEL_MEDIA_COMMAND_DESC string desc Use this to get or set the parcel media description. (1.19.1 RC0 or later)
7302 //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
7303 m_host.AddScriptLPS(1);
7304 for (int i = 0; i < commandList.Data.Length; i++)
7305 {
7306 switch ((ParcelMediaCommandEnum)commandList.Data[i])
7307 {
7308 case ParcelMediaCommandEnum.Play:
7309 List<ScenePresence> scenePresencePlayList = World.GetScenePresences();
7310 foreach (ScenePresence agent in scenePresencePlayList)
7311 {
7312 if (!agent.IsChildAgent)
7313 {
7314 agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Play, 0);
7315 }
7316 }
7317 break;
7318 case ParcelMediaCommandEnum.Stop:
7319 List<ScenePresence> scenePresenceStopList = World.GetScenePresences();
7320 foreach (ScenePresence agent in scenePresenceStopList)
7321 {
7322 if (!agent.IsChildAgent)
7323 {
7324 agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Stop, 0);
7325 }
7326 }
7327 break;
7328 case ParcelMediaCommandEnum.Pause:
7329 List<ScenePresence> scenePresencePauseList = World.GetScenePresences();
7330 foreach (ScenePresence agent in scenePresencePauseList)
7331 {
7332 if (!agent.IsChildAgent)
7333 {
7334 agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Pause, 0);
7335 }
7336 }
7337 break;
7338
7339 case ParcelMediaCommandEnum.Url:
7340 if ((i + 1) < commandList.Length)
7341 {
7342 if (commandList.Data[i + 1] is string)
7343 {
7344 UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
7345
7346 if (landowner == UUID.Zero)
7347 {
7348 return;
7349 }
7350
7351 if (landowner != m_host.ObjectOwner)
7352 {
7353 return;
7354 }
7355
7356 World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, (string)commandList.GetLSLStringItem(i + 1));
7357
7358 List<ScenePresence> scenePresenceList = World.GetScenePresences();
7359 LandData landData = World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
7360 //Send an update of the mediaURL to all the clients that are in the parcel
7361 foreach (ScenePresence agent in scenePresenceList)
7362 {
7363 if (!agent.IsChildAgent)
7364 {
7365 //Send parcel media update to the client
7366 agent.ControllingClient.SendParcelMediaUpdate(landData.MediaURL, landData.MediaID, landData.MediaAutoScale, "", landData.Description, 0, 0, 1);
7367 }
7368 }
7369
7370 }
7371 i++;
7372 }
7373 break;
7374 default:
7375 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
7376 NotImplemented("llParcelMediaCommandList parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType(), commandList.Data[i].ToString()).ToString());
7377 break;
7378 }//end switch
7379
7380 }
7381 // ScriptSleep(2000);
7382 }
7383
7384 public LSL_List llParcelMediaQuery(LSL_List aList)
7385 {
7386 m_host.AddScriptLPS(1);
7387 LSL_List list = new LSL_List();
7388 //TO DO: make the implementation for the missing commands
7389 //PARCEL_MEDIA_COMMAND_TEXTURE key uuid Use this to get or set the parcel's media texture.
7390 //PARCEL_MEDIA_COMMAND_URL string url Used to get or set the parcel's media url.
7391 //PARCEL_MEDIA_COMMAND_TYPE string mime_type Use this to get or set the parcel media MIME type (e.g. "text/html"). (1.19.1 RC0 or later)
7392 //PARCEL_MEDIA_COMMAND_SIZE integer x, integer y Use this to get or set the parcel media pixel resolution. (1.19.1 RC0 or later)
7393 //PARCEL_MEDIA_COMMAND_DESC string desc Use this to get or set the parcel media description. (1.19.1 RC0 or later)
7394 //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
7395 for (int i = 0; i < aList.Data.Length; i++)
7396 {
7397
7398 if (aList.Data[i] != null)
7399 {
7400 switch ((ParcelMediaCommandEnum) aList.Data[i])
7401 {
7402 case ParcelMediaCommandEnum.Url:
7403 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
7404 break;
7405 case ParcelMediaCommandEnum.Desc:
7406 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description));
7407 break;
7408 case ParcelMediaCommandEnum.Texture:
7409 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString()));
7410 break;
7411 default:
7412 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
7413 NotImplemented("llParcelMediaQuery parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString());
7414 break;
7415 }
7416
7417 }
7418 }
7419 // ScriptSleep(2000);
7420 return list;
7421 }
7422
7423 public LSL_Integer llModPow(int a, int b, int c)
7424 {
7425 m_host.AddScriptLPS(1);
7426 Int64 tmp = 0;
7427 Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp);
7428 // ScriptSleep(1000);
7429 return Convert.ToInt32(tmp);
7430 }
7431
7432 public LSL_Integer llGetInventoryType(string name)
7433 {
7434 m_host.AddScriptLPS(1);
7435 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
7436 {
7437 if (inv.Value.Name == name)
7438 {
7439 return inv.Value.InvType;
7440 }
7441 }
7442 return -1;
7443 }
7444
7445 public void llSetPayPrice(int price, LSL_List quick_pay_buttons)
7446 {
7447 m_host.AddScriptLPS(1);
7448
7449 if (quick_pay_buttons.Data.Length < 4)
7450 {
7451 LSLError("List must have at least 4 elements");
7452 return;
7453 }
7454 m_host.ParentGroup.RootPart.PayPrice[0]=price;
7455
7456 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0];
7457 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1];
7458 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2];
7459 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3];
7460 m_host.ParentGroup.HasGroupChanged = true;
7461 }
7462
7463 public LSL_Vector llGetCameraPos()
7464 {
7465 m_host.AddScriptLPS(1);
7466 UUID invItemID=InventorySelf();
7467 if (invItemID == UUID.Zero)
7468 return new LSL_Vector();
7469 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
7470 return new LSL_Vector();
7471 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
7472 {
7473 ShoutError("No permissions to track the camera");
7474 return new LSL_Vector();
7475 }
7476 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
7477 if (presence != null)
7478 {
7479 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
7480 return pos;
7481 }
7482 return new LSL_Vector();
7483 }
7484
7485 public LSL_Rotation llGetCameraRot()
7486 {
7487 m_host.AddScriptLPS(1);
7488 NotImplemented("llGetCameraRot");
7489 return new LSL_Rotation();
7490 }
7491
7492 public void llSetPrimURL()
7493 {
7494 m_host.AddScriptLPS(1);
7495 NotImplemented("llSetPrimURL");
7496 // ScriptSleep(2000);
7497 }
7498
7499 public void llRefreshPrimURL()
7500 {
7501 m_host.AddScriptLPS(1);
7502 NotImplemented("llRefreshPrimURL");
7503 // ScriptSleep(20000);
7504 }
7505
7506 public LSL_String llEscapeURL(string url)
7507 {
7508 m_host.AddScriptLPS(1);
7509 try
7510 {
7511 return Uri.EscapeUriString(url);
7512 }
7513 catch (Exception ex)
7514 {
7515 return "llEscapeURL: " + ex.ToString();
7516 }
7517 }
7518
7519 public LSL_String llUnescapeURL(string url)
7520 {
7521 m_host.AddScriptLPS(1);
7522 try
7523 {
7524 return Uri.UnescapeDataString(url);
7525 }
7526 catch (Exception ex)
7527 {
7528 return "llUnescapeURL: " + ex.ToString();
7529 }
7530 }
7531
7532 public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector look_at)
7533 {
7534 m_host.AddScriptLPS(1);
7535 NotImplemented("llMapDestination");
7536 // ScriptSleep(1000);
7537 }
7538
7539 public void llAddToLandBanList(string avatar, double hours)
7540 {
7541 m_host.AddScriptLPS(1);
7542 UUID key;
7543 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7544 if (land.OwnerID == m_host.OwnerID)
7545 {
7546 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
7547 if (UUID.TryParse(avatar, out key))
7548 {
7549 entry.AgentID = key;
7550 entry.Flags = ParcelManager.AccessList.Ban;
7551 entry.Time = DateTime.Now.AddHours(hours);
7552 land.ParcelAccessList.Add(entry);
7553 }
7554 }
7555 // ScriptSleep(100);
7556 }
7557
7558 public void llRemoveFromLandPassList(string avatar)
7559 {
7560 m_host.AddScriptLPS(1);
7561 UUID key;
7562 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7563 if (land.OwnerID == m_host.OwnerID)
7564 {
7565 if (UUID.TryParse(avatar, out key))
7566 {
7567 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
7568 {
7569 if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Access)
7570 {
7571 land.ParcelAccessList.Remove(entry);
7572 break;
7573 }
7574 }
7575 }
7576 }
7577 // ScriptSleep(100);
7578 }
7579
7580 public void llRemoveFromLandBanList(string avatar)
7581 {
7582 m_host.AddScriptLPS(1);
7583 UUID key;
7584 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7585 if (land.OwnerID == m_host.OwnerID)
7586 {
7587 if (UUID.TryParse(avatar, out key))
7588 {
7589 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
7590 {
7591 if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Ban)
7592 {
7593 land.ParcelAccessList.Remove(entry);
7594 break;
7595 }
7596 }
7597 }
7598 }
7599 // ScriptSleep(100);
7600 }
7601
7602 public void llSetCameraParams(LSL_List rules)
7603 {
7604 m_host.AddScriptLPS(1);
7605
7606 // our key in the object we are in
7607 UUID invItemID=InventorySelf();
7608 if (invItemID == UUID.Zero) return;
7609
7610 // the object we are in
7611 UUID objectID = m_host.ParentUUID;
7612 if (objectID == UUID.Zero) return;
7613
7614 // we need the permission first, to know which avatar we want to set the camera for
7615 UUID agentID = m_host.TaskInventory[invItemID].PermsGranter;
7616 if (agentID == UUID.Zero) return;
7617 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
7618
7619 ScenePresence presence = World.GetScenePresence(agentID);
7620
7621 // we are not interested in child-agents
7622 if (presence.IsChildAgent) return;
7623
7624 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
7625 object[] data = rules.Data;
7626 for (int i = 0; i < data.Length; ++i) {
7627 int type = Convert.ToInt32(data[i++].ToString());
7628 if (i >= data.Length) break; // odd number of entries => ignore the last
7629
7630 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
7631 switch (type) {
7632 case ScriptBaseClass.CAMERA_FOCUS:
7633 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
7634 case ScriptBaseClass.CAMERA_POSITION:
7635 LSL_Vector v = (LSL_Vector)data[i];
7636 parameters.Add(type + 1, (float)v.x);
7637 parameters.Add(type + 2, (float)v.y);
7638 parameters.Add(type + 3, (float)v.z);
7639 break;
7640 default:
7641 // TODO: clean that up as soon as the implicit casts are in
7642 if (data[i] is LSL_Float)
7643 parameters.Add(type, (float)((LSL_Float)data[i]).value);
7644 else if (data[i] is LSL_Integer)
7645 parameters.Add(type, (float)((LSL_Integer)data[i]).value);
7646 else parameters.Add(type, Convert.ToSingle(data[i]));
7647 break;
7648 }
7649 }
7650 if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters);
7651 }
7652
7653 public void llClearCameraParams()
7654 {
7655 m_host.AddScriptLPS(1);
7656
7657 // our key in the object we are in
7658 UUID invItemID=InventorySelf();
7659 if (invItemID == UUID.Zero) return;
7660
7661 // the object we are in
7662 UUID objectID = m_host.ParentUUID;
7663 if (objectID == UUID.Zero) return;
7664
7665 // we need the permission first, to know which avatar we want to clear the camera for
7666 UUID agentID = m_host.TaskInventory[invItemID].PermsGranter;
7667 if (agentID == UUID.Zero) return;
7668 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
7669
7670 ScenePresence presence = World.GetScenePresence(agentID);
7671
7672 // we are not interested in child-agents
7673 if (presence.IsChildAgent) return;
7674
7675 presence.ControllingClient.SendClearFollowCamProperties(objectID);
7676 }
7677
7678 public LSL_Float llListStatistics(int operation, LSL_List src)
7679 {
7680 m_host.AddScriptLPS(1);
7681 LSL_List nums = LSL_List.ToDoubleList(src);
7682 switch (operation)
7683 {
7684 case ScriptBaseClass.LIST_STAT_RANGE:
7685 return nums.Range();
7686 case ScriptBaseClass.LIST_STAT_MIN:
7687 return nums.Min();
7688 case ScriptBaseClass.LIST_STAT_MAX:
7689 return nums.Max();
7690 case ScriptBaseClass.LIST_STAT_MEAN:
7691 return nums.Mean();
7692 case ScriptBaseClass.LIST_STAT_MEDIAN:
7693 return nums.Median();
7694 case ScriptBaseClass.LIST_STAT_NUM_COUNT:
7695 return nums.NumericLength();
7696 case ScriptBaseClass.LIST_STAT_STD_DEV:
7697 return nums.StdDev();
7698 case ScriptBaseClass.LIST_STAT_SUM:
7699 return nums.Sum();
7700 case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
7701 return nums.SumSqrs();
7702 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
7703 return nums.GeometricMean();
7704 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
7705 return nums.HarmonicMean();
7706 default:
7707 return 0.0;
7708 }
7709 }
7710
7711 public LSL_Integer llGetUnixTime()
7712 {
7713 m_host.AddScriptLPS(1);
7714 return Util.UnixTimeSinceEpoch();
7715 }
7716
7717 public LSL_Integer llGetParcelFlags(LSL_Vector pos)
7718 {
7719 m_host.AddScriptLPS(1);
7720 return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).landData.Flags;
7721 }
7722
7723 public LSL_Integer llGetRegionFlags()
7724 {
7725 m_host.AddScriptLPS(1);
7726 IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
7727 if (estate == null)
7728 return 67108864;
7729 return (int)estate.GetRegionFlags();
7730 }
7731
7732 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
7733 {
7734 m_host.AddScriptLPS(1);
7735 string ret = String.Empty;
7736 string src1 = llBase64ToString(str1);
7737 string src2 = llBase64ToString(str2);
7738 int c = 0;
7739 for (int i = 0; i < src1.Length; i++)
7740 {
7741 ret += src1[i] ^ src2[c];
7742
7743 c++;
7744 if (c >= src2.Length)
7745 c = 0;
7746 }
7747 return llStringToBase64(ret);
7748 }
7749
7750 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
7751 {
7752 // Partial implementation: support for parameter flags needed
7753 // see http://wiki.secondlife.com/wiki/LlHTTPRequest
7754 // parameter flags support are implemented in ScriptsHttpRequests.cs
7755 // in StartHttpRequest
7756
7757 m_host.AddScriptLPS(1);
7758 IHttpRequests httpScriptMod =
7759 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
7760 List<string> param = new List<string>();
7761 foreach (object o in parameters.Data)
7762 {
7763 param.Add(o.ToString());
7764 }
7765
7766 Vector3 position = m_host.AbsolutePosition;
7767 Vector3 velocity = m_host.Velocity;
7768 Quaternion rotation = m_host.RotationOffset;
7769 ScenePresence scenePresence = World.GetScenePresence(m_host.ObjectOwner);
7770 RegionInfo regionInfo = World.RegionInfo;
7771
7772 Dictionary<string, string> httpHeaders = new Dictionary<string, string>();
7773
7774 httpHeaders["X-SecondLife-Shard"] = "OpenSim";
7775 httpHeaders["X-SecondLife-Object-Name"] = m_host.Name;
7776 httpHeaders["X-SecondLife-Object-Key"] = m_itemID.ToString();
7777 httpHeaders["X-SecondLife-Region"] = string.Format("{0} ({1}, {2})", regionInfo.RegionName, regionInfo.RegionLocX, regionInfo.RegionLocY);
7778 httpHeaders["X-SecondLife-Local-Position"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", position.X, position.Y, position.Z);
7779 httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z);
7780 httpHeaders["X-SecondLife-Local-Rotation"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})", rotation.X, rotation.Y, rotation.Z, rotation.W);
7781 httpHeaders["X-SecondLife-Owner-Name"] = scenePresence == null ? string.Empty : scenePresence.ControllingClient.Name;
7782 httpHeaders["X-SecondLife-Owner-Key"] = m_host.ObjectOwner.ToString();
7783
7784 UUID reqID = httpScriptMod.
7785 StartHttpRequest(m_localID, m_itemID, url, param, httpHeaders, body);
7786
7787 if (reqID != UUID.Zero)
7788 return reqID.ToString();
7789 else
7790 return null;
7791 }
7792
7793 public void llResetLandBanList()
7794 { 146 {
7795 m_host.AddScriptLPS(1); 147 UUID item;
7796 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7797 if (land.OwnerID == m_host.OwnerID)
7798 {
7799 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
7800 {
7801 if (entry.Flags == ParcelManager.AccessList.Ban)
7802 {
7803 land.ParcelAccessList.Remove(entry);
7804 }
7805 }
7806 }
7807 // ScriptSleep(100);
7808 }
7809 148
7810 public void llResetLandPassList()
7811 {
7812 m_host.AddScriptLPS(1); 149 m_host.AddScriptLPS(1);
7813 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7814 if (land.OwnerID == m_host.OwnerID)
7815 {
7816 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
7817 {
7818 if (entry.Flags == ParcelManager.AccessList.Access)
7819 {
7820 land.ParcelAccessList.Remove(entry);
7821 }
7822 }
7823 }
7824 // ScriptSleep(100);
7825 }
7826
7827 public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide)
7828 {
7829 m_host.AddScriptLPS(1);
7830
7831 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
7832
7833 if (land == null)
7834 {
7835 return 0;
7836 }
7837 150
151 if ((item = ScriptByName(name)) != UUID.Zero)
152 m_ScriptEngineDirect.ResetScript(item);
7838 else 153 else
7839 { 154 ShoutError("llResetOtherScript: script "+name+" not found");
7840 if (sim_wide == 1)
7841 {
7842 if (category == 0)
7843 {
7844 return land.SimwidePrims;
7845 }
7846
7847 else
7848 {
7849 //public int simwideArea = 0;
7850 return 0;
7851 }
7852 }
7853
7854 else
7855 {
7856 if (category == 0)//Total Prims
7857 {
7858 return 0;//land.
7859 }
7860
7861 else if (category == 1)//Owner Prims
7862 {
7863 return land.OwnerPrims;
7864 }
7865
7866 else if (category == 2)//Group Prims
7867 {
7868 return land.GroupPrims;
7869 }
7870
7871 else if (category == 3)//Other Prims
7872 {
7873 return land.OtherPrims;
7874 }
7875
7876 else if (category == 4)//Selected
7877 {
7878 return land.SelectedPrims;
7879 }
7880
7881 else if (category == 5)//Temp
7882 {
7883 return 0;//land.
7884 }
7885 }
7886 }
7887 return 0;
7888 } 155 }
7889 156
7890 public LSL_List llGetParcelPrimOwners(LSL_Vector pos) 157 public void llResetScript()
7891 { 158 {
7892 m_host.AddScriptLPS(1); 159 m_host.AddScriptLPS(1);
7893 LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); 160 m_ScriptEngineDirect.ApiResetScript(m_itemID);
7894 LSL_List ret = new LSL_List(); 161 throw new EventAbortException();
7895 if (land != null)
7896 {
7897 foreach (KeyValuePair<UUID, int> d in land.getLandObjectOwners())
7898 {
7899 ret.Add(d.Key.ToString());
7900 ret.Add(d.Value);
7901 }
7902 }
7903 // ScriptSleep(2000);
7904 return ret;
7905 } 162 }
7906 163
7907 public LSL_Integer llGetObjectPrimCount(string object_id) 164 public void llSetScriptState(string name, int run)
7908 { 165 {
7909 m_host.AddScriptLPS(1); 166 UUID item;
7910 SceneObjectPart part = World.GetSceneObjectPart(new UUID(object_id));
7911 if (part == null)
7912 {
7913 return 0;
7914 }
7915 else
7916 {
7917 return part.ParentGroup.Children.Count;
7918 }
7919 }
7920 167
7921 public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide)
7922 {
7923 m_host.AddScriptLPS(1); 168 m_host.AddScriptLPS(1);
7924 // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation
7925 // Which probably will be irrelevent in OpenSim....
7926 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
7927
7928 float bonusfactor = (float)World.RegionInfo.RegionSettings.ObjectBonus;
7929 169
7930 if (land == null) 170 // These functions are supposed to be robust,
7931 { 171 // so get the state one step at a time.
7932 return 0;
7933 }
7934 172
7935 if (sim_wide == 1) 173 if ((item = ScriptByName(name)) != UUID.Zero)
7936 { 174 {
7937 decimal v = land.SimwideArea * (decimal)(0.22) * (decimal)bonusfactor; 175 m_ScriptEngineDirect.SetScriptState(item, run == 0 ? false : true);
7938
7939 return (int)v;
7940 } 176 }
7941
7942 else 177 else
7943 { 178 {
7944 decimal v = land.Area * (decimal)(0.22) * (decimal)bonusfactor; 179 ShoutError("llSetScriptState: script "+name+" not found");
7945
7946 return (int)v;
7947 }
7948
7949 }
7950
7951 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param)
7952 {
7953 m_host.AddScriptLPS(1);
7954 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
7955 if (land == null)
7956 {
7957 return new LSL_List(0);
7958 }
7959 LSL_List ret = new LSL_List();
7960 foreach (object o in param.Data)
7961 {
7962 switch (o.ToString())
7963 {
7964 case "0":
7965 ret = ret + new LSL_List(land.Name);
7966 break;
7967 case "1":
7968 ret = ret + new LSL_List(land.Description);
7969 break;
7970 case "2":
7971 ret = ret + new LSL_List(land.OwnerID.ToString());
7972 break;
7973 case "3":
7974 ret = ret + new LSL_List(land.GroupID.ToString());
7975 break;
7976 case "4":
7977 ret = ret + new LSL_List(land.Area);
7978 break;
7979 default:
7980 ret = ret + new LSL_List(0);
7981 break;
7982 }
7983 }
7984 return ret;
7985 }
7986
7987 public void llSetLinkTexture(int linknumber, string texture, int face)
7988 {
7989 m_host.AddScriptLPS(1);
7990
7991 if (m_host.ParentGroup == null)
7992 return;
7993
7994 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber);
7995
7996 if (part == null)
7997 return;
7998
7999 SetTexture(part, texture, face);
8000 // ScriptSleep(200);
8001 }
8002
8003 public LSL_String llStringTrim(string src, int type)
8004 {
8005 m_host.AddScriptLPS(1);
8006 if (type == (int)ScriptBaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); }
8007 if (type == (int)ScriptBaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); }
8008 if (type == (int)ScriptBaseClass.STRING_TRIM) { return src.Trim(); }
8009 return src;
8010 }
8011
8012 public LSL_List llGetObjectDetails(string id, LSL_List args)
8013 {
8014 m_host.AddScriptLPS(1);
8015 LSL_List ret = new LSL_List();
8016 UUID key = new UUID();
8017 if (UUID.TryParse(id, out key))
8018 {
8019 ScenePresence av = World.GetScenePresence(key);
8020
8021 if (av != null)
8022 {
8023 foreach (object o in args.Data)
8024 {
8025 switch (o.ToString())
8026 {
8027 case "1":
8028 ret.Add(av.Firstname + " " + av.Lastname);
8029 break;
8030 case "2":
8031 ret.Add("");
8032 break;
8033 case "3":
8034 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z));
8035 break;
8036 case "4":
8037 ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W));
8038 break;
8039 case "5":
8040 ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z));
8041 break;
8042 case "6":
8043 ret.Add(id);
8044 break;
8045 case "7":
8046 ret.Add(UUID.Zero.ToString());
8047 break;
8048 case "8":
8049 ret.Add(UUID.Zero.ToString());
8050 break;
8051 }
8052 }
8053 return ret;
8054 }
8055 SceneObjectPart obj = World.GetSceneObjectPart(key);
8056 if (obj != null)
8057 {
8058 foreach (object o in args.Data)
8059 {
8060 switch (o.ToString())
8061 {
8062 case "1":
8063 ret.Add(obj.Name);
8064 break;
8065 case "2":
8066 ret.Add(obj.Description);
8067 break;
8068 case "3":
8069 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z));
8070 break;
8071 case "4":
8072 ret.Add(new LSL_Rotation(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W));
8073 break;
8074 case "5":
8075 ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z));
8076 break;
8077 case "6":
8078 ret.Add(obj.OwnerID.ToString());
8079 break;
8080 case "7":
8081 ret.Add(obj.GroupID.ToString());
8082 break;
8083 case "8":
8084 ret.Add(obj.CreatorID.ToString());
8085 break;
8086 }
8087 }
8088 return ret;
8089 }
8090 }
8091 return new LSL_List();
8092 }
8093
8094
8095 internal UUID ScriptByName(string name)
8096 {
8097 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
8098 {
8099 if (item.Type == 10 && item.Name == name)
8100 return item.ItemID;
8101 }
8102 return UUID.Zero;
8103 }
8104
8105 internal void ShoutError(string msg)
8106 {
8107 llShout(ScriptBaseClass.DEBUG_CHANNEL, msg);
8108 }
8109
8110 internal void NotImplemented(string command)
8111 {
8112 if (throwErrorOnNotImplemented)
8113 throw new NotImplementedException("Command not implemented: " + command);
8114 }
8115
8116 internal void Deprecated(string command)
8117 {
8118 throw new Exception("Command deprecated: " + command);
8119 }
8120
8121 internal void LSLError(string msg)
8122 {
8123 throw new Exception("LSL Runtime Error: " + msg);
8124 }
8125
8126 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset);
8127 private void WithNotecard(UUID assetID, AssetRequestCallback cb)
8128 {
8129 World.AssetCache.GetAsset(assetID, delegate(UUID i, AssetBase a) { cb(i, a); }, false);
8130 }
8131
8132 public LSL_String llGetNumberOfNotecardLines(string name)
8133 {
8134 m_host.AddScriptLPS(1);
8135
8136 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
8137 {
8138 if (item.Type == 7 && item.Name == name)
8139 {
8140 UUID tid = AsyncCommands.
8141 DataserverPlugin.RegisterRequest(m_localID,
8142 m_itemID, item.AssetID.ToString());
8143 if (NotecardCache.IsCached(item.AssetID))
8144 {
8145 AsyncCommands.
8146 DataserverPlugin.DataserverReply(item.AssetID.ToString(),
8147 NotecardCache.GetLines(item.AssetID).ToString());
8148 // ScriptSleep(100);
8149 return tid.ToString();
8150 }
8151 WithNotecard(item.AssetID, delegate (UUID id, AssetBase a)
8152 {
8153 System.Text.ASCIIEncoding enc =
8154 new System.Text.ASCIIEncoding();
8155 string data = enc.GetString(a.Data);
8156 //Console.WriteLine(data);
8157 NotecardCache.Cache(id, data);
8158 AsyncCommands.
8159 DataserverPlugin.DataserverReply(id.ToString(),
8160 NotecardCache.GetLines(id).ToString());
8161 });
8162 // ScriptSleep(100);
8163 return tid.ToString();
8164 }
8165 }
8166 // if we got to here, we didn't find the notecard the script was asking for
8167 // => complain loudly, as specified by the LSL docs
8168 ShoutError("Notecard '" + name + "' could not be found.");
8169
8170 // ScriptSleep(100);
8171 return UUID.Zero.ToString();
8172 }
8173
8174 public LSL_String llGetNotecardLine(string name, int line)
8175 {
8176 m_host.AddScriptLPS(1);
8177
8178 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
8179 {
8180 if (item.Type == 7 && item.Name == name)
8181 {
8182 UUID tid = AsyncCommands.
8183 DataserverPlugin.RegisterRequest(m_localID,
8184 m_itemID, item.AssetID.ToString());
8185
8186 if (NotecardCache.IsCached(item.AssetID))
8187 {
8188 AsyncCommands.
8189 DataserverPlugin.DataserverReply(item.AssetID.ToString(),
8190 NotecardCache.GetLine(item.AssetID, line));
8191 // ScriptSleep(100);
8192 return tid.ToString();
8193 }
8194
8195 WithNotecard(item.AssetID, delegate (UUID id, AssetBase a)
8196 {
8197 System.Text.ASCIIEncoding enc =
8198 new System.Text.ASCIIEncoding();
8199 string data = enc.GetString(a.Data);
8200 //Console.WriteLine(data);
8201 NotecardCache.Cache(id, data);
8202 AsyncCommands.
8203 DataserverPlugin.DataserverReply(id.ToString(),
8204 NotecardCache.GetLine(id, line));
8205 });
8206
8207 // ScriptSleep(100);
8208 return tid.ToString();
8209 }
8210 }
8211
8212 // if we got to here, we didn't find the notecard the script was asking for
8213 // => complain loudly, as specified by the LSL docs
8214 ShoutError("Notecard '" + name + "' could not be found.");
8215
8216 // ScriptSleep(100);
8217 return UUID.Zero.ToString();
8218 }
8219
8220 }
8221
8222 public class NotecardCache
8223 {
8224 private class Notecard
8225 {
8226 public string[] text;
8227 public DateTime lastRef;
8228 }
8229
8230 private static Dictionary<UUID, Notecard> m_Notecards =
8231 new Dictionary<UUID, Notecard>();
8232
8233 public static void Cache(UUID assetID, string text)
8234 {
8235 CacheCheck();
8236
8237 lock (m_Notecards)
8238 {
8239 if (m_Notecards.ContainsKey(assetID))
8240 return;
8241
8242 Notecard nc = new Notecard();
8243 nc.lastRef = DateTime.Now;
8244 nc.text = ParseText(text.Replace("\r", "").Split('\n'));
8245 m_Notecards[assetID] = nc;
8246 }
8247 }
8248
8249 private static string[] ParseText(string[] input)
8250 {
8251 int idx = 0;
8252 int level = 0;
8253 List<string> output = new List<string>();
8254 string[] words;
8255
8256 while (idx < input.Length)
8257 {
8258 if (input[idx] == "{")
8259 {
8260 level++;
8261 idx++;
8262 continue;
8263 }
8264
8265 if (input[idx]== "}")
8266 {
8267 level--;
8268 idx++;
8269 continue;
8270 }
8271
8272 switch (level)
8273 {
8274 case 0:
8275 words = input[idx].Split(' '); // Linden text ver
8276 // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard)
8277 if (words.Length < 3)
8278 return new String[0];
8279
8280 int version = int.Parse(words[3]);
8281 if (version != 2)
8282 return new String[0];
8283 break;
8284 case 1:
8285 words = input[idx].Split(' ');
8286 if (words[0] == "LLEmbeddedItems")
8287 break;
8288 if (words[0] == "Text")
8289 {
8290 int len = int.Parse(words[2]);
8291 idx++;
8292
8293 int count = -1;
8294
8295 while (count < len)
8296 {
8297 // int l = input[idx].Length;
8298 string ln = input[idx];
8299
8300 int need = len-count-1;
8301 if (ln.Length > need)
8302 ln = ln.Substring(0, need);
8303
8304 output.Add(ln);
8305 count += ln.Length + 1;
8306 idx++;
8307 }
8308
8309 return output.ToArray();
8310 }
8311 break;
8312 case 2:
8313 words = input[idx].Split(' '); // count
8314 if (words[0] == "count")
8315 {
8316 int c = int.Parse(words[1]);
8317 if (c > 0)
8318 return new String[0];
8319 break;
8320 }
8321 break;
8322 }
8323 idx++;
8324 }
8325 return output.ToArray();
8326 }
8327
8328 public static bool IsCached(UUID assetID)
8329 {
8330 lock (m_Notecards)
8331 {
8332 return m_Notecards.ContainsKey(assetID);
8333 }
8334 }
8335
8336 public static int GetLines(UUID assetID)
8337 {
8338 if (!IsCached(assetID))
8339 return -1;
8340
8341 lock (m_Notecards)
8342 {
8343 m_Notecards[assetID].lastRef = DateTime.Now;
8344 return m_Notecards[assetID].text.Length;
8345 }
8346 }
8347
8348 public static string GetLine(UUID assetID, int line)
8349 {
8350 if (line < 0)
8351 return "";
8352
8353 string data;
8354
8355 if (!IsCached(assetID))
8356 return "";
8357
8358 lock (m_Notecards)
8359 {
8360 m_Notecards[assetID].lastRef = DateTime.Now;
8361
8362 if (line >= m_Notecards[assetID].text.Length)
8363 return "\n\n\n";
8364
8365 data = m_Notecards[assetID].text[line];
8366 if (data.Length > 255)
8367 data = data.Substring(0, 255);
8368
8369 return data;
8370 }
8371 }
8372
8373 public static void CacheCheck()
8374 {
8375 foreach (UUID key in new List<UUID>(m_Notecards.Keys))
8376 {
8377 Notecard nc = m_Notecards[key];
8378 if (nc.lastRef.AddSeconds(30) < DateTime.Now)
8379 m_Notecards.Remove(key);
8380 } 180 }
8381 } 181 }
8382 } 182 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api_Base.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api_Base.cs
new file mode 100644
index 0000000..16b4c50
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api_Base.cs
@@ -0,0 +1,8279 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Runtime.Remoting.Lifetime;
32using System.Text;
33using System.Threading;
34using Nini.Config;
35using OpenMetaverse;
36using OpenMetaverse.Packets;
37using OpenSim;
38using OpenSim.Framework;
39using OpenSim.Framework.Communications.Cache;
40using OpenSim.Region.Environment;
41using OpenSim.Region.Interfaces;
42using OpenSim.Region.Environment.Interfaces;
43using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney;
44using OpenSim.Region.Environment.Modules.World.Land;
45using OpenSim.Region.Environment.Scenes;
46using OpenSim.Region.Physics.Manager;
47using OpenSim.Region.ScriptEngine.Shared;
48using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
49using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
50using OpenSim.Region.ScriptEngine.Interfaces;
51using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
52
53using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
54using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
55using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
56using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
57using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
58using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
59using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
60
61namespace OpenSim.Region.ScriptEngine.Shared.Api
62{
63 /// <summary>
64 /// Contains all LSL ll-functions. This class will be in Default AppDomain.
65 /// </summary>
66 public class LSL_Api_Base : MarshalByRefObject
67 {
68 protected IEventReceiver m_ScriptEngine;
69 protected SceneObjectPart m_host;
70 protected uint m_localID;
71 protected UUID m_itemID;
72 protected bool throwErrorOnNotImplemented = true;
73 protected AsyncCommandManager AsyncCommands = null;
74 protected float m_ScriptDelayFactor = 1.0f;
75 protected float m_ScriptDistanceFactor = 1.0f;
76
77 private DateTime m_timer = DateTime.Now;
78 private bool m_waitingForScriptAnswer=false;
79 protected void ScriptSleep(int delay)
80 {
81 delay = (int)((float)delay * m_ScriptDelayFactor);
82 if (delay == 0)
83 return;
84 System.Threading.Thread.Sleep(delay);
85 }
86
87 public Scene World
88 {
89 get { return m_ScriptEngine.World; }
90 }
91
92 private List<SceneObjectPart> GetLinkParts(int linkType)
93 {
94 List<SceneObjectPart> ret = new List<SceneObjectPart>();
95 ret.Add(m_host);
96
97 switch (linkType)
98 {
99 case ScriptBaseClass.LINK_SET:
100 if (m_host.ParentGroup != null)
101 return new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
102 return ret;
103
104 case ScriptBaseClass.LINK_ROOT:
105 if (m_host.ParentGroup != null)
106 {
107 ret = new List<SceneObjectPart>();
108 ret.Add(m_host.ParentGroup.RootPart);
109 return ret;
110 }
111 return ret;
112
113 case ScriptBaseClass.LINK_ALL_OTHERS:
114 if (m_host.ParentGroup == null)
115 return new List<SceneObjectPart>();
116 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
117 if (ret.Contains(m_host))
118 ret.Remove(m_host);
119 return ret;
120
121 case ScriptBaseClass.LINK_ALL_CHILDREN:
122 if (m_host.ParentGroup == null)
123 return new List<SceneObjectPart>();
124 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
125 if (ret.Contains(m_host.ParentGroup.RootPart))
126 ret.Remove(m_host.ParentGroup.RootPart);
127 return ret;
128
129 case ScriptBaseClass.LINK_THIS:
130 return ret;
131
132 default:
133 if (linkType < 0 || m_host.ParentGroup == null)
134 return new List<SceneObjectPart>();
135 SceneObjectPart target = m_host.ParentGroup.GetLinkNumPart(linkType);
136 if (target == null)
137 return new List<SceneObjectPart>();
138 ret = new List<SceneObjectPart>();
139 ret.Add(target);
140 return ret;
141
142 }
143 }
144
145 private UUID InventorySelf()
146 {
147 UUID invItemID = new UUID();
148
149 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
150 {
151 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
152 {
153 invItemID = inv.Key;
154 break;
155 }
156 }
157
158 return invItemID;
159 }
160
161 private UUID InventoryKey(string name, int type)
162 {
163 m_host.AddScriptLPS(1);
164 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
165 {
166 if (inv.Value.Name == name)
167 {
168 if (inv.Value.Type != type)
169 return UUID.Zero;
170
171 return inv.Value.AssetID.ToString();
172 }
173 }
174 return UUID.Zero;
175 }
176
177 private UUID InventoryKey(string name)
178 {
179 m_host.AddScriptLPS(1);
180 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
181 {
182 if (inv.Value.Name == name)
183 {
184 return inv.Value.AssetID.ToString();
185 }
186 }
187 return UUID.Zero;
188 }
189
190
191 /// <summary>
192 /// accepts a valid UUID, -or- a name of an inventory item.
193 /// Returns a valid UUID or UUID.Zero if key invalid and item not found
194 /// in prim inventory.
195 /// </summary>
196 /// <param name="k"></param>
197 /// <returns></returns>
198 private UUID KeyOrName(string k)
199 {
200 UUID key = UUID.Zero;
201
202 // if we can parse the string as a key, use it.
203 if (UUID.TryParse(k, out key))
204 {
205 return key;
206 }
207 // else try to locate the name in inventory of object. found returns key,
208 // not found returns UUID.Zero which will translate to the default particle texture
209 else
210 {
211 return InventoryKey(k);
212 }
213 }
214
215 //These are the implementations of the various ll-functions used by the LSL scripts.
216 public LSL_Float llSin(double f)
217 {
218 m_host.AddScriptLPS(1);
219 return (double)Math.Sin(f);
220 }
221
222 public LSL_Float llCos(double f)
223 {
224 m_host.AddScriptLPS(1);
225 return (double)Math.Cos(f);
226 }
227
228 public LSL_Float llTan(double f)
229 {
230 m_host.AddScriptLPS(1);
231 return (double)Math.Tan(f);
232 }
233
234 public LSL_Float llAtan2(double x, double y)
235 {
236 m_host.AddScriptLPS(1);
237 return (double)Math.Atan2(y, x);
238 }
239
240 public LSL_Float llSqrt(double f)
241 {
242 m_host.AddScriptLPS(1);
243 return (double)Math.Sqrt(f);
244 }
245
246 public LSL_Float llPow(double fbase, double fexponent)
247 {
248 m_host.AddScriptLPS(1);
249 return (double)Math.Pow(fbase, fexponent);
250 }
251
252 public LSL_Integer llAbs(int i)
253 {
254 m_host.AddScriptLPS(1);
255 return (int)Math.Abs(i);
256 }
257
258 public LSL_Float llFabs(double f)
259 {
260 m_host.AddScriptLPS(1);
261 return (double)Math.Abs(f);
262 }
263
264 public LSL_Float llFrand(double mag)
265 {
266 m_host.AddScriptLPS(1);
267 lock (Util.RandomClass)
268 {
269 return Util.RandomClass.NextDouble() * mag;
270 }
271 }
272
273 public LSL_Integer llFloor(double f)
274 {
275 m_host.AddScriptLPS(1);
276 return (int)Math.Floor(f);
277 }
278
279 public LSL_Integer llCeil(double f)
280 {
281 m_host.AddScriptLPS(1);
282 return (int)Math.Ceiling(f);
283 }
284
285 // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
286 public LSL_Integer llRound(double f)
287 {
288 m_host.AddScriptLPS(1);
289 return (int)Math.Round(f, MidpointRounding.AwayFromZero);
290 }
291
292 //This next group are vector operations involving squaring and square root. ckrinke
293 public LSL_Float llVecMag(LSL_Vector v)
294 {
295 m_host.AddScriptLPS(1);
296 return LSL_Vector.Mag(v);
297 }
298
299 public LSL_Vector llVecNorm(LSL_Vector v)
300 {
301 m_host.AddScriptLPS(1);
302 double mag = LSL_Vector.Mag(v);
303 LSL_Vector nor = new LSL_Vector();
304 nor.x = v.x / mag;
305 nor.y = v.y / mag;
306 nor.z = v.z / mag;
307 return nor;
308 }
309
310 public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
311 {
312 m_host.AddScriptLPS(1);
313 double dx = a.x - b.x;
314 double dy = a.y - b.y;
315 double dz = a.z - b.z;
316 return Math.Sqrt(dx * dx + dy * dy + dz * dz);
317 }
318
319 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
320
321 // Utility function for llRot2Euler
322
323 // normalize an angle between 0 - 2*PI (0 and 360 degrees)
324 private double NormalizeAngle(double angle)
325 {
326 angle = angle % (Math.PI * 2);
327 if (angle < 0) angle = angle + Math.PI * 2;
328 return angle;
329 }
330
331 // Old implementation of llRot2Euler, now normalized
332
333 public LSL_Vector llRot2Euler(LSL_Rotation r)
334 {
335 m_host.AddScriptLPS(1);
336 //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke
337 LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s);
338 double m = (t.x + t.y + t.z + t.s);
339 if (m == 0) return new LSL_Vector();
340 double n = 2 * (r.y * r.s + r.x * r.z);
341 double p = m * m - n * n;
342 if (p > 0)
343 return new LSL_Vector(NormalizeAngle(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s))),
344 NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))),
345 NormalizeAngle(Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))));
346 else if (n > 0)
347 return new LSL_Vector(0.0, Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
348 else
349 return new LSL_Vector(0.0, -Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
350 }
351
352 /* From wiki:
353 The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
354 in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
355 a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
356 vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
357 */
358
359 /* How we arrived at this llEuler2Rot
360 *
361 * Experiment in SL to determine conventions:
362 * llEuler2Rot(<PI,0,0>)=<1,0,0,0>
363 * llEuler2Rot(<0,PI,0>)=<0,1,0,0>
364 * llEuler2Rot(<0,0,PI>)=<0,0,1,0>
365 *
366 * Important facts about Quaternions
367 * - multiplication is non-commutative (a*b != b*a)
368 * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
369 *
370 * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
371 * Qx = c1+i*s1
372 * Qy = c2+j*s2;
373 * Qz = c3+k*s3;
374 *
375 * Rotations applied in order (from above) Z, Y, X
376 * Q = (Qz * Qy) * Qx
377 * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
378 * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
379 * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
380 * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3
381 * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3 -s1*s2*s3
382 * regroup: x=i*(s1*c2*c3+c1*s2*s3)
383 * y=j*(c1*s2*c3-s1*c2*s3)
384 * z=k*(s1*s2*c3+c1*c2*s3)
385 * s= c1*c2*c3-s1*s2*s3
386 *
387 * This implementation agrees with the functions found here:
388 * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
389 * And with the results in SL.
390 *
391 * It's also possible to calculate llEuler2Rot by direct multiplication of
392 * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
393 * from the wiki).
394 * Apparently in some cases this is better from a numerical precision perspective?
395 */
396
397 public LSL_Rotation llEuler2Rot(LSL_Vector v)
398 {
399 m_host.AddScriptLPS(1);
400
401 double x,y,z,s;
402
403 double c1 = Math.Cos(v.x/2.0);
404 double c2 = Math.Cos(v.y/2.0);
405 double c3 = Math.Cos(v.z/2.0);
406 double s1 = Math.Sin(v.x/2.0);
407 double s2 = Math.Sin(v.y/2.0);
408 double s3 = Math.Sin(v.z/2.0);
409
410 x = s1*c2*c3+c1*s2*s3;
411 y = c1*s2*c3-s1*c2*s3;
412 z = s1*s2*c3+c1*c2*s3;
413 s = c1*c2*c3-s1*s2*s3;
414
415 return new LSL_Rotation(x, y, z, s);
416 }
417
418 public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
419 {
420 m_host.AddScriptLPS(1);
421 double x, y, z, s;
422 int f = 0;
423 // Important Note: q1=<x,y,z,s> is equal to q2=<-x,-y,-z,-s>
424 // Computing quaternion x,y,z,s values
425 x = ((fwd.x - left.y - up.z + 1) / 4);
426 x *= x;
427 x = Math.Sqrt(Math.Sqrt(x));
428 y = ((1 - up.z) / 2 - x * x);
429 y *= y;
430 y = Math.Sqrt(Math.Sqrt(y));
431 z = ((1 - left.y) / 2 - x * x);
432 z *= z;
433 z = Math.Sqrt(Math.Sqrt(z));
434 s = (1 - x * x - y * y - z * z);
435 s *= s;
436 s = Math.Sqrt(Math.Sqrt(s));
437
438 // Set f for signs detection
439 if (fwd.y + left.x >= 0) { f += 1; }
440 if (fwd.z + up.x >= 0) { f += 2; }
441 if (left.z - up.y >= 0) { f += 4; }
442 // Set correct quaternion signs based on f value
443 if (f == 0) { x = -x; }
444 if (f == 1) { x = -x; y = -y; }
445 if (f == 2) { x = -x; z = -z; }
446 if (f == 3) { s = -s; }
447 if (f == 4) { x = -x; s = -s; }
448 if (f == 5) { z = -z; }
449 if (f == 6) { y = -y; }
450
451 LSL_Rotation result = new LSL_Rotation(x, y, z, s);
452
453 // a hack to correct a few questionable angles :(
454 if (llVecDist(llRot2Fwd(result), fwd) > 0.001 || llVecDist(llRot2Left(result), left) > 0.001)
455 result.s = -s;
456
457 return result;
458 }
459
460 public LSL_Vector llRot2Fwd(LSL_Rotation r)
461 {
462 m_host.AddScriptLPS(1);
463
464 double x, y, z, m;
465
466 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
467 // m is always greater than zero
468 // if m is not equal to 1 then Rotation needs to be normalized
469 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
470 {
471 m = 1.0 / Math.Sqrt(m);
472 r.x *= m;
473 r.y *= m;
474 r.z *= m;
475 r.s *= m;
476 }
477
478 // Fast Algebric Calculations instead of Vectors & Quaternions Product
479 x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s;
480 y = 2 * (r.x * r.y + r.z * r.s);
481 z = 2 * (r.x * r.z - r.y * r.s);
482 return (new LSL_Vector(x, y, z));
483 }
484
485 public LSL_Vector llRot2Left(LSL_Rotation r)
486 {
487 m_host.AddScriptLPS(1);
488
489 double x, y, z, m;
490
491 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
492 // m is always greater than zero
493 // if m is not equal to 1 then Rotation needs to be normalized
494 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
495 {
496 m = 1.0 / Math.Sqrt(m);
497 r.x *= m;
498 r.y *= m;
499 r.z *= m;
500 r.s *= m;
501 }
502
503 // Fast Algebric Calculations instead of Vectors & Quaternions Product
504 x = 2 * (r.x * r.y - r.z * r.s);
505 y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s;
506 z = 2 * (r.x * r.s + r.y * r.z);
507 return (new LSL_Vector(x, y, z));
508 }
509
510 public LSL_Vector llRot2Up(LSL_Rotation r)
511 {
512 m_host.AddScriptLPS(1);
513 double x, y, z, m;
514
515 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
516 // m is always greater than zero
517 // if m is not equal to 1 then Rotation needs to be normalized
518 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
519 {
520 m = 1.0 / Math.Sqrt(m);
521 r.x *= m;
522 r.y *= m;
523 r.z *= m;
524 r.s *= m;
525 }
526
527 // Fast Algebric Calculations instead of Vectors & Quaternions Product
528 x = 2 * (r.x * r.z + r.y * r.s);
529 y = 2 * (-r.x * r.s + r.y * r.z);
530 z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s;
531 return (new LSL_Vector(x, y, z));
532 }
533
534 public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
535 {
536 //A and B should both be normalized
537 m_host.AddScriptLPS(1);
538 double dotProduct = LSL_Vector.Dot(a, b);
539 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
540 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
541 double angle = Math.Acos(dotProduct / magProduct);
542 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
543 double s = Math.Sin(angle / 2);
544
545 double x = axis.x * s;
546 double y = axis.y * s;
547 double z = axis.z * s;
548 double w = Math.Cos(angle / 2);
549
550 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
551 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
552
553 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
554 }
555
556 public void llWhisper(int channelID, string text)
557 {
558 m_host.AddScriptLPS(1);
559
560 if (text.Length > 1023)
561 text = text.Substring(0, 1023);
562
563 World.SimChat(Utils.StringToBytes(text),
564 ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
565
566 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
567 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
568 }
569
570 public void llSay(int channelID, string text)
571 {
572 m_host.AddScriptLPS(1);
573
574 if (text.Length > 1023)
575 text = text.Substring(0, 1023);
576
577 World.SimChat(Utils.StringToBytes(text),
578 ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
579
580 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
581 wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
582 }
583
584 public void llShout(int channelID, string text)
585 {
586 m_host.AddScriptLPS(1);
587
588 if (text.Length > 1023)
589 text = text.Substring(0, 1023);
590
591 World.SimChat(Utils.StringToBytes(text),
592 ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, true);
593
594 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
595 wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
596 }
597
598 public void llRegionSay(int channelID, string text)
599 {
600 if (channelID == 0)
601 {
602 LSLError("Cannot use llRegionSay() on channel 0");
603 return;
604 }
605
606 if (text.Length > 1023)
607 text = text.Substring(0, 1023);
608
609 m_host.AddScriptLPS(1);
610
611 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
612 wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
613 }
614
615 public LSL_Integer llListen(int channelID, string name, string ID, string msg)
616 {
617 m_host.AddScriptLPS(1);
618 UUID keyID;
619 UUID.TryParse(ID, out keyID);
620 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
621 return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, keyID, msg);
622 }
623
624 public void llListenControl(int number, int active)
625 {
626 m_host.AddScriptLPS(1);
627 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
628 wComm.ListenControl(m_itemID, number, active);
629 }
630
631 public void llListenRemove(int number)
632 {
633 m_host.AddScriptLPS(1);
634 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
635 wComm.ListenRemove(m_itemID, number);
636 }
637
638 public void llSensor(string name, string id, int type, double range, double arc)
639 {
640 m_host.AddScriptLPS(1);
641 UUID keyID = UUID.Zero;
642 UUID.TryParse(id, out keyID);
643
644 AsyncCommands.SensorRepeatPlugin.SenseOnce(m_localID, m_itemID, name, keyID, type, range, arc, m_host);
645 }
646
647 public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
648 {
649 m_host.AddScriptLPS(1);
650 UUID keyID = UUID.Zero;
651 UUID.TryParse(id, out keyID);
652
653 AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_localID, m_itemID, name, keyID, type, range, arc, rate, m_host);
654 }
655
656 public void llSensorRemove()
657 {
658 m_host.AddScriptLPS(1);
659 AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_localID, m_itemID);
660 }
661
662 public string resolveName(UUID objecUUID)
663 {
664 // try avatar username surname
665 CachedUserInfo profile = World.CommsManager.UserProfileCacheService.GetUserDetails(objecUUID);
666 if (profile != null && profile.UserProfile != null)
667 {
668 string avatarname = profile.UserProfile.FirstName + " " + profile.UserProfile.SurName;
669 return avatarname;
670 }
671 // try an scene object
672 SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID);
673 if (SOP != null)
674 {
675 string objectname = SOP.Name;
676 return objectname;
677 }
678
679 EntityBase SensedObject;
680 lock (World.Entities)
681 {
682 World.Entities.TryGetValue(objecUUID, out SensedObject);
683 }
684
685 if (SensedObject == null)
686 return String.Empty;
687 return SensedObject.Name;
688 }
689
690 public LSL_String llDetectedName(int number)
691 {
692 m_host.AddScriptLPS(1);
693 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
694 if (d == null)
695 return String.Empty;
696 return d.Name;
697 }
698
699 public LSL_String llDetectedKey(int number)
700 {
701 m_host.AddScriptLPS(1);
702 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
703 if (d == null)
704 return String.Empty;
705 return d.Key.ToString();
706 }
707
708 public LSL_String llDetectedOwner(int number)
709 {
710 m_host.AddScriptLPS(1);
711 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
712 if (d == null)
713 return String.Empty;
714 return d.Owner.ToString();
715 }
716
717 public LSL_Integer llDetectedType(int number)
718 {
719 m_host.AddScriptLPS(1);
720 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
721 if (d == null)
722 return 0;
723 return new LSL_Integer(d.Type);
724 }
725
726 public LSL_Vector llDetectedPos(int number)
727 {
728 m_host.AddScriptLPS(1);
729 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
730 if (d == null)
731 return new LSL_Vector();
732 return d.Position;
733 }
734
735 public LSL_Vector llDetectedVel(int number)
736 {
737 m_host.AddScriptLPS(1);
738 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
739 if (d == null)
740 return new LSL_Vector();
741 return d.Velocity;
742 }
743
744 public LSL_Vector llDetectedGrab(int number)
745 {
746 m_host.AddScriptLPS(1);
747 DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number);
748 if (parms == null)
749 return new LSL_Vector(0, 0, 0);
750
751 return parms.OffsetPos;
752 }
753
754 public LSL_Rotation llDetectedRot(int number)
755 {
756 m_host.AddScriptLPS(1);
757 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
758 if (d == null)
759 return new LSL_Rotation();
760 return d.Rotation;
761 }
762
763 public LSL_Integer llDetectedGroup(int number)
764 {
765 m_host.AddScriptLPS(1);
766 DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
767 if (d == null)
768 return new LSL_Integer(0);
769 if (m_host.GroupID == d.Group)
770 return new LSL_Integer(1);
771 return new LSL_Integer(0);
772 }
773
774 public LSL_Integer llDetectedLinkNumber(int number)
775 {
776 m_host.AddScriptLPS(1);
777 DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number);
778 if (parms == null)
779 return new LSL_Integer(0);
780
781 return new LSL_Integer(parms.LinkNum);
782 }
783
784 public LSL_Vector llDetectedTouchBinormal(int index)
785 {
786 m_host.AddScriptLPS(1);
787 NotImplemented("llDetectedTouchBinormal");
788 return new LSL_Vector();
789 }
790
791 public LSL_Integer llDetectedTouchFace(int index)
792 {
793 m_host.AddScriptLPS(1);
794 NotImplemented("llDetectedTouchFace");
795 return new LSL_Integer(0);
796 }
797
798 public LSL_Vector llDetectedTouchNormal(int index)
799 {
800 m_host.AddScriptLPS(1);
801 NotImplemented("llDetectedTouchNormal");
802 return new LSL_Vector();
803 }
804
805 public LSL_Vector llDetectedTouchPos(int index)
806 {
807 m_host.AddScriptLPS(1);
808 NotImplemented("llDetectedTouchPos");
809 return new LSL_Vector();
810 }
811
812 public LSL_Vector llDetectedTouchST(int index)
813 {
814 m_host.AddScriptLPS(1);
815 NotImplemented("llDetectedTouchST");
816 return new LSL_Vector();
817 }
818
819 public LSL_Vector llDetectedTouchUV(int index)
820 {
821 m_host.AddScriptLPS(1);
822 NotImplemented("llDetectedTouchUV");
823 return new LSL_Vector();
824 }
825
826 public void llDie()
827 {
828 m_host.AddScriptLPS(1);
829 throw new SelfDeleteException();
830 }
831
832 public LSL_Float llGround(LSL_Vector offset)
833 {
834 m_host.AddScriptLPS(1);
835 int x = (int)(m_host.OffsetPosition.X + offset.x);
836 int y = (int)(m_host.OffsetPosition.Y + offset.y);
837 return World.GetLandHeight(x, y);
838 }
839
840 public LSL_Float llCloud(LSL_Vector offset)
841 {
842 m_host.AddScriptLPS(1);
843 return 0;
844 }
845
846 public LSL_Vector llWind(LSL_Vector offset)
847 {
848 m_host.AddScriptLPS(1);
849 return new LSL_Vector();
850 }
851
852 public void llSetStatus(int status, int value)
853 {
854 m_host.AddScriptLPS(1);
855
856 int statusrotationaxis = 0;
857
858 if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS)
859 {
860 if (value == 1)
861 {
862 SceneObjectGroup group = m_host.ParentGroup;
863 if (group == null)
864 return;
865 bool allow = true;
866 foreach (SceneObjectPart part in group.Children.Values)
867 {
868 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
869 {
870 allow = false;
871 break;
872 }
873 }
874
875 if (!allow)
876 return;
877 m_host.ScriptSetPhysicsStatus(true);
878 }
879 else
880 m_host.ScriptSetPhysicsStatus(false);
881 }
882
883 if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM)
884 {
885 if (value == 1)
886 m_host.ScriptSetPhantomStatus(true);
887 else
888 m_host.ScriptSetPhantomStatus(false);
889 }
890
891 if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS)
892 {
893 m_host.AddFlag(PrimFlags.CastShadows);
894 }
895
896 if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X)
897 {
898 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X;
899 }
900
901 if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y)
902 {
903 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y;
904 }
905
906 if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z)
907 {
908 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z;
909 }
910
911 if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB)
912 {
913 NotImplemented("llSetStatus - STATUS_BLOCK_GRAB");
914 }
915
916 if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE)
917 {
918 if (value == 1)
919 m_host.SetDieAtEdge(true);
920 else
921 m_host.SetDieAtEdge(false);
922 }
923
924 if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
925 {
926 NotImplemented("llSetStatus - STATUS_RETURN_AT_EDGE");
927 }
928
929 if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX)
930 {
931 NotImplemented("llSetStatus - STATUS_SANDBOX");
932 }
933
934 if (statusrotationaxis != 0)
935 {
936 m_host.SetAxisRotation(statusrotationaxis, value);
937 }
938 }
939
940 public LSL_Integer llGetStatus(int status)
941 {
942 m_host.AddScriptLPS(1);
943 // Console.WriteLine(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString());
944 switch (status)
945 {
946 case ScriptBaseClass.STATUS_PHYSICS:
947 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics)
948 {
949 return 1;
950 }
951 return 0;
952
953 case ScriptBaseClass.STATUS_PHANTOM:
954 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom)
955 {
956 return 1;
957 }
958 return 0;
959
960 case ScriptBaseClass.STATUS_CAST_SHADOWS:
961 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows)
962 {
963 return 1;
964 }
965 return 0;
966
967 case ScriptBaseClass.STATUS_BLOCK_GRAB:
968 NotImplemented("llGetStatus - STATUS_BLOCK_GRAB");
969 return 0;
970
971 case ScriptBaseClass.STATUS_DIE_AT_EDGE:
972 if (m_host.GetDieAtEdge())
973 return 1;
974 else
975 return 0;
976
977 case ScriptBaseClass.STATUS_RETURN_AT_EDGE:
978 NotImplemented("llGetStatus - STATUS_RETURN_AT_EDGE");
979 return 0;
980
981 case ScriptBaseClass.STATUS_ROTATE_X:
982 NotImplemented("llGetStatus - STATUS_ROTATE_X");
983 return 0;
984
985 case ScriptBaseClass.STATUS_ROTATE_Y:
986 NotImplemented("llGetStatus - STATUS_ROTATE_Y");
987 return 0;
988
989 case ScriptBaseClass.STATUS_ROTATE_Z:
990 NotImplemented("llGetStatus - STATUS_ROTATE_Z");
991 return 0;
992
993 case ScriptBaseClass.STATUS_SANDBOX:
994 NotImplemented("llGetStatus - STATUS_SANDBOX");
995 return 0;
996 }
997 return 0;
998 }
999
1000 public void llSetScale(LSL_Vector scale)
1001 {
1002 m_host.AddScriptLPS(1);
1003 SetScale(m_host, scale);
1004 }
1005
1006 private void SetScale(SceneObjectPart part, LSL_Vector scale)
1007 {
1008 // TODO: this needs to trigger a persistance save as well
1009
1010 if (part == null || part.ParentGroup == null || part.ParentGroup.RootPart == null)
1011 return;
1012
1013 if (part.ParentGroup.RootPart.PhysActor != null && part.ParentGroup.RootPart.PhysActor.IsPhysical)
1014 {
1015 if (scale.x > World.m_maxPhys)
1016 scale.x = World.m_maxPhys;
1017 if (scale.y > World.m_maxPhys)
1018 scale.y = World.m_maxPhys;
1019 if (scale.z > World.m_maxPhys)
1020 scale.z = World.m_maxPhys;
1021 }
1022 if (scale.x > World.m_maxNonphys)
1023 scale.x = World.m_maxNonphys;
1024 if (scale.y > World.m_maxNonphys)
1025 scale.y = World.m_maxNonphys;
1026 if (scale.z > World.m_maxNonphys)
1027 scale.z = World.m_maxNonphys;
1028 Vector3 tmp = part.Scale;
1029 tmp.X = (float)scale.x;
1030 tmp.Y = (float)scale.y;
1031 tmp.Z = (float)scale.z;
1032 part.Scale = tmp;
1033 part.SendFullUpdateToAllClients();
1034 }
1035
1036 public LSL_Vector llGetScale()
1037 {
1038 m_host.AddScriptLPS(1);
1039 return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z);
1040 }
1041
1042 public void llSetClickAction(int action)
1043 {
1044 m_host.AddScriptLPS(1);
1045 NotImplemented("llSetClickAction");
1046 return;
1047 }
1048
1049 public void llSetColor(LSL_Vector color, int face)
1050 {
1051 m_host.AddScriptLPS(1);
1052
1053 SetColor(m_host, color, face);
1054 }
1055
1056 private void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1057 {
1058 Primitive.TextureEntry tex = part.Shape.Textures;
1059 Color4 texcolor;
1060 if (face >= 0 && face < GetNumberOfSides(part))
1061 {
1062 texcolor = tex.CreateFace((uint)face).RGBA;
1063 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1064 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1065 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1066 tex.FaceTextures[face].RGBA = texcolor;
1067 part.UpdateTexture(tex);
1068 return;
1069 }
1070 else if (face == ScriptBaseClass.ALL_SIDES)
1071 {
1072 for (uint i = 0; i < GetNumberOfSides(part); i++)
1073 {
1074 if (tex.FaceTextures[i] != null)
1075 {
1076 texcolor = tex.FaceTextures[i].RGBA;
1077 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1078 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1079 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1080 tex.FaceTextures[i].RGBA = texcolor;
1081 }
1082 texcolor = tex.DefaultTexture.RGBA;
1083 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1084 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1085 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1086 tex.DefaultTexture.RGBA = texcolor;
1087 }
1088 part.UpdateTexture(tex);
1089 return;
1090 }
1091 }
1092
1093 public void SetGlow(SceneObjectPart part, int face, float glow)
1094 {
1095 Primitive.TextureEntry tex = part.Shape.Textures;
1096 if (face >= 0 && face < GetNumberOfSides(part))
1097 {
1098 tex.CreateFace((uint) face);
1099 tex.FaceTextures[face].Glow = glow;
1100 part.UpdateTexture(tex);
1101 return;
1102 }
1103 else if (face == ScriptBaseClass.ALL_SIDES)
1104 {
1105 for (uint i = 0; i < GetNumberOfSides(part); i++)
1106 {
1107 if (tex.FaceTextures[i] != null)
1108 {
1109 tex.FaceTextures[i].Glow = glow;
1110 }
1111 tex.DefaultTexture.Glow = glow;
1112 }
1113 part.UpdateTexture(tex);
1114 return;
1115 }
1116 }
1117
1118 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1119 {
1120
1121 Shininess sval = new Shininess();
1122
1123 switch (shiny)
1124 {
1125 case 0:
1126 sval = Shininess.None;
1127 break;
1128 case 1:
1129 sval = Shininess.Low;
1130 break;
1131 case 2:
1132 sval = Shininess.Medium;
1133 break;
1134 case 3:
1135 sval = Shininess.High;
1136 break;
1137 default:
1138 sval = Shininess.None;
1139 break;
1140 }
1141
1142 Primitive.TextureEntry tex = part.Shape.Textures;
1143 if (face >= 0 && face < GetNumberOfSides(part))
1144 {
1145 tex.CreateFace((uint) face);
1146 tex.FaceTextures[face].Shiny = sval;
1147 tex.FaceTextures[face].Bump = bump;
1148 part.UpdateTexture(tex);
1149 return;
1150 }
1151 else if (face == ScriptBaseClass.ALL_SIDES)
1152 {
1153 for (uint i = 0; i < GetNumberOfSides(part); i++)
1154 {
1155 if (tex.FaceTextures[i] != null)
1156 {
1157 tex.FaceTextures[i].Shiny = sval;
1158 tex.FaceTextures[i].Bump = bump;;
1159 }
1160 tex.DefaultTexture.Shiny = sval;
1161 tex.DefaultTexture.Bump = bump;
1162 }
1163 part.UpdateTexture(tex);
1164 return;
1165 }
1166 }
1167
1168 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1169 {
1170 Primitive.TextureEntry tex = part.Shape.Textures;
1171 if (face >= 0 && face < GetNumberOfSides(part))
1172 {
1173 tex.CreateFace((uint) face);
1174 tex.FaceTextures[face].Fullbright = bright;
1175 part.UpdateTexture(tex);
1176 return;
1177 }
1178 else if (face == ScriptBaseClass.ALL_SIDES)
1179 {
1180 for (uint i = 0; i < GetNumberOfSides(part); i++)
1181 {
1182 if (tex.FaceTextures[i] != null)
1183 {
1184 tex.FaceTextures[i].Fullbright = bright;
1185 }
1186 }
1187 tex.DefaultTexture.Fullbright = bright;
1188 part.UpdateTexture(tex);
1189 return;
1190 }
1191 }
1192
1193 public LSL_Float llGetAlpha(int face)
1194 {
1195 m_host.AddScriptLPS(1);
1196
1197 return GetAlpha(m_host, face);
1198 }
1199
1200 private LSL_Float GetAlpha(SceneObjectPart part, int face)
1201 {
1202 Primitive.TextureEntry tex = part.Shape.Textures;
1203 if (face == ScriptBaseClass.ALL_SIDES)
1204 {
1205 int i;
1206 double sum = 0.0;
1207 for (i = 0 ; i < GetNumberOfSides(part) ; i++)
1208 sum += (double)tex.GetFace((uint)i).RGBA.A;
1209 return sum;
1210 }
1211 if (face >= 0 && face < GetNumberOfSides(part))
1212 {
1213 return (double)tex.GetFace((uint)face).RGBA.A;
1214 }
1215 return 0.0;
1216 }
1217
1218 public void llSetAlpha(double alpha, int face)
1219 {
1220 m_host.AddScriptLPS(1);
1221
1222 SetAlpha(m_host, alpha, face);
1223 }
1224
1225 private void SetAlpha(SceneObjectPart part, double alpha, int face)
1226 {
1227 Primitive.TextureEntry tex = part.Shape.Textures;
1228 Color4 texcolor;
1229 if (face >= 0 && face < GetNumberOfSides(part))
1230 {
1231 texcolor = tex.CreateFace((uint)face).RGBA;
1232 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
1233 tex.FaceTextures[face].RGBA = texcolor;
1234 part.UpdateTexture(tex);
1235 return;
1236 }
1237 else if (face == ScriptBaseClass.ALL_SIDES)
1238 {
1239 for (int i = 0; i < GetNumberOfSides(part); i++)
1240 {
1241 if (tex.FaceTextures[i] != null)
1242 {
1243 texcolor = tex.FaceTextures[i].RGBA;
1244 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
1245 tex.FaceTextures[i].RGBA = texcolor;
1246 }
1247 }
1248 texcolor = tex.DefaultTexture.RGBA;
1249 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
1250 tex.DefaultTexture.RGBA = texcolor;
1251 part.UpdateTexture(tex);
1252 return;
1253 }
1254 }
1255
1256 /// <summary>
1257 /// Set flexi parameters of a part.
1258 ///
1259 /// FIXME: Much of this code should probably be within the part itself.
1260 /// </summary>
1261 /// <param name="part"></param>
1262 /// <param name="flexi"></param>
1263 /// <param name="softness"></param>
1264 /// <param name="gravity"></param>
1265 /// <param name="friction"></param>
1266 /// <param name="wind"></param>
1267 /// <param name="tension"></param>
1268 /// <param name="Force"></param>
1269 private void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1270 float wind, float tension, LSL_Vector Force)
1271 {
1272 if (part == null)
1273 return;
1274
1275 bool needs_fakedelete = false;
1276 if (flexi)
1277 {
1278 if (!part.Shape.FlexiEntry)
1279 {
1280 needs_fakedelete = true;
1281 }
1282 part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do
1283 // work once the prim is already flexi
1284 part.Shape.FlexiSoftness = softness;
1285 part.Shape.FlexiGravity = gravity;
1286 part.Shape.FlexiDrag = friction;
1287 part.Shape.FlexiWind = wind;
1288 part.Shape.FlexiTension = tension;
1289 part.Shape.FlexiForceX = (float)Force.x;
1290 part.Shape.FlexiForceY = (float)Force.y;
1291 part.Shape.FlexiForceZ = (float)Force.z;
1292 part.Shape.PathCurve = 0x80;
1293
1294 }
1295 else
1296 {
1297 if (part.Shape.FlexiEntry)
1298 {
1299 needs_fakedelete = true;
1300 }
1301 part.Shape.FlexiEntry = false;
1302 }
1303
1304 needs_fakedelete = false;
1305 if (needs_fakedelete)
1306 {
1307 if (part.ParentGroup != null)
1308 {
1309 part.ParentGroup.FakeDeleteGroup();
1310 }
1311 }
1312
1313 part.ParentGroup.HasGroupChanged = true;
1314 part.ScheduleFullUpdate();
1315 }
1316
1317 /// <summary>
1318 /// Set a light point on a part
1319 ///
1320 /// FIXME: Much of this code should probably be in SceneObjectGroup
1321 /// </summary>
1322 /// <param name="part"></param>
1323 /// <param name="light"></param>
1324 /// <param name="color"></param>
1325 /// <param name="intensity"></param>
1326 /// <param name="radius"></param>
1327 /// <param name="falloff"></param>
1328 private void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1329 {
1330 if (part == null)
1331 return;
1332
1333 if (light)
1334 {
1335 part.Shape.LightEntry = true;
1336 part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f);
1337 part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f);
1338 part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f);
1339 part.Shape.LightIntensity = intensity;
1340 part.Shape.LightRadius = radius;
1341 part.Shape.LightFalloff = falloff;
1342 }
1343 else
1344 {
1345 part.Shape.LightEntry = false;
1346 }
1347
1348 part.ParentGroup.HasGroupChanged = true;
1349 part.ScheduleFullUpdate();
1350 }
1351
1352 public LSL_Vector llGetColor(int face)
1353 {
1354 m_host.AddScriptLPS(1);
1355 return GetColor(m_host, face);
1356 }
1357
1358 private LSL_Vector GetColor(SceneObjectPart part, int face)
1359 {
1360 Primitive.TextureEntry tex = part.Shape.Textures;
1361 Color4 texcolor;
1362 LSL_Vector rgb = new LSL_Vector();
1363 if (face == ScriptBaseClass.ALL_SIDES)
1364 {
1365 int i;
1366
1367 for (i = 0 ; i < GetNumberOfSides(part) ; i++)
1368 {
1369 texcolor = tex.GetFace((uint)i).RGBA;
1370 rgb.x += texcolor.R;
1371 rgb.y += texcolor.G;
1372 rgb.z += texcolor.B;
1373 }
1374
1375 rgb.x /= (float)GetNumberOfSides(part);
1376 rgb.y /= (float)GetNumberOfSides(part);
1377 rgb.z /= (float)GetNumberOfSides(part);
1378
1379 return rgb;
1380 }
1381 if (face >= 0 && face < GetNumberOfSides(part))
1382 {
1383 texcolor = tex.GetFace((uint)face).RGBA;
1384 rgb.x = texcolor.R;
1385 rgb.y = texcolor.G;
1386 rgb.z = texcolor.B;
1387 return rgb;
1388 }
1389 else
1390 {
1391 return new LSL_Vector();
1392 }
1393 }
1394
1395 public void llSetTexture(string texture, int face)
1396 {
1397 m_host.AddScriptLPS(1);
1398 SetTexture(m_host, texture, face);
1399 // ScriptSleep(200);
1400 }
1401
1402 private void SetTexture(SceneObjectPart part, string texture, int face)
1403 {
1404 UUID textureID=new UUID();
1405
1406 if (!UUID.TryParse(texture, out textureID))
1407 {
1408 textureID=InventoryKey(texture, (int)AssetType.Texture);
1409 }
1410
1411 if (textureID == UUID.Zero)
1412 return;
1413
1414 Primitive.TextureEntry tex = part.Shape.Textures;
1415
1416 if (face >= 0 && face < GetNumberOfSides(part))
1417 {
1418 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
1419 texface.TextureID = textureID;
1420 tex.FaceTextures[face] = texface;
1421 part.UpdateTexture(tex);
1422 return;
1423 }
1424 else if (face == ScriptBaseClass.ALL_SIDES)
1425 {
1426 for (uint i = 0; i < GetNumberOfSides(part); i++)
1427 {
1428 if (tex.FaceTextures[i] != null)
1429 {
1430 tex.FaceTextures[i].TextureID = textureID;
1431 }
1432 }
1433 tex.DefaultTexture.TextureID = textureID;
1434 part.UpdateTexture(tex);
1435 return;
1436 }
1437 }
1438
1439 public void llScaleTexture(double u, double v, int face)
1440 {
1441 m_host.AddScriptLPS(1);
1442
1443 ScaleTexture(m_host, u, v, face);
1444 // ScriptSleep(200);
1445 }
1446
1447 private void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1448 {
1449 Primitive.TextureEntry tex = part.Shape.Textures;
1450 if (face >= 0 && face < GetNumberOfSides(part))
1451 {
1452 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
1453 texface.RepeatU = (float)u;
1454 texface.RepeatV = (float)v;
1455 tex.FaceTextures[face] = texface;
1456 part.UpdateTexture(tex);
1457 return;
1458 }
1459 if (face == ScriptBaseClass.ALL_SIDES)
1460 {
1461 for (int i = 0; i < GetNumberOfSides(part); i++)
1462 {
1463 if (tex.FaceTextures[i] != null)
1464 {
1465 tex.FaceTextures[i].RepeatU = (float)u;
1466 tex.FaceTextures[i].RepeatV = (float)v;
1467 }
1468 }
1469 tex.DefaultTexture.RepeatU = (float)u;
1470 tex.DefaultTexture.RepeatV = (float)v;
1471 part.UpdateTexture(tex);
1472 return;
1473 }
1474 }
1475
1476 public void llOffsetTexture(double u, double v, int face)
1477 {
1478 m_host.AddScriptLPS(1);
1479 OffsetTexture(m_host, u, v, face);
1480 // ScriptSleep(200);
1481 }
1482
1483 private void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1484 {
1485 Primitive.TextureEntry tex = part.Shape.Textures;
1486 if (face >= 0 && face < GetNumberOfSides(part))
1487 {
1488 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
1489 texface.OffsetU = (float)u;
1490 texface.OffsetV = (float)v;
1491 tex.FaceTextures[face] = texface;
1492 part.UpdateTexture(tex);
1493 return;
1494 }
1495 if (face == ScriptBaseClass.ALL_SIDES)
1496 {
1497 for (int i = 0; i < GetNumberOfSides(part); i++)
1498 {
1499 if (tex.FaceTextures[i] != null)
1500 {
1501 tex.FaceTextures[i].OffsetU = (float)u;
1502 tex.FaceTextures[i].OffsetV = (float)v;
1503 }
1504 }
1505 tex.DefaultTexture.OffsetU = (float)u;
1506 tex.DefaultTexture.OffsetV = (float)v;
1507 part.UpdateTexture(tex);
1508 return;
1509 }
1510 }
1511
1512 public void llRotateTexture(double rotation, int face)
1513 {
1514 m_host.AddScriptLPS(1);
1515 RotateTexture(m_host, rotation, face);
1516 // ScriptSleep(200);
1517 }
1518
1519 private void RotateTexture(SceneObjectPart part, double rotation, int face)
1520 {
1521 Primitive.TextureEntry tex = part.Shape.Textures;
1522 if (face >= 0 && face < GetNumberOfSides(part))
1523 {
1524 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
1525 texface.Rotation = (float)rotation;
1526 tex.FaceTextures[face] = texface;
1527 part.UpdateTexture(tex);
1528 return;
1529 }
1530 if (face == ScriptBaseClass.ALL_SIDES)
1531 {
1532 for (int i = 0; i < GetNumberOfSides(part); i++)
1533 {
1534 if (tex.FaceTextures[i] != null)
1535 {
1536 tex.FaceTextures[i].Rotation = (float)rotation;
1537 }
1538 }
1539 tex.DefaultTexture.Rotation = (float)rotation;
1540 part.UpdateTexture(tex);
1541 return;
1542 }
1543 }
1544
1545 public LSL_String llGetTexture(int face)
1546 {
1547 m_host.AddScriptLPS(1);
1548 return GetTexture(m_host, face);
1549 }
1550
1551 private LSL_String GetTexture(SceneObjectPart part, int face)
1552 {
1553 Primitive.TextureEntry tex = part.Shape.Textures;
1554 if (face == ScriptBaseClass.ALL_SIDES)
1555 {
1556 face = 0;
1557 }
1558 if (face >= 0 && face < GetNumberOfSides(part))
1559 {
1560 Primitive.TextureEntryFace texface;
1561 texface = tex.GetFace((uint)face);
1562 return texface.TextureID.ToString();
1563 }
1564 else
1565 {
1566 return String.Empty;
1567 }
1568 }
1569
1570 public void llSetPos(LSL_Vector pos)
1571 {
1572 m_host.AddScriptLPS(1);
1573
1574 SetPos(m_host, pos);
1575
1576 ScriptSleep(200);
1577 }
1578
1579 private void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1580 {
1581 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
1582 LSL_Vector currentPos = llGetLocalPos();
1583 if (llVecDist(currentPos, targetPos) > 10.0f * m_ScriptDistanceFactor)
1584 {
1585 targetPos = currentPos + m_ScriptDistanceFactor * 10.0f * llVecNorm(targetPos - currentPos);
1586 }
1587
1588 if (part.ParentID != 0)
1589 {
1590 part.UpdateOffSet(new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z));
1591 }
1592 else
1593 {
1594 part.UpdateGroupPosition(new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z));
1595 }
1596 }
1597
1598 public LSL_Vector llGetPos()
1599 {
1600 m_host.AddScriptLPS(1);
1601 return new LSL_Vector(m_host.AbsolutePosition.X,
1602 m_host.AbsolutePosition.Y,
1603 m_host.AbsolutePosition.Z);
1604 }
1605
1606 public LSL_Vector llGetLocalPos()
1607 {
1608 m_host.AddScriptLPS(1);
1609 if (m_host.ParentID != 0)
1610 {
1611 return new LSL_Vector(m_host.OffsetPosition.X,
1612 m_host.OffsetPosition.Y,
1613 m_host.OffsetPosition.Z);
1614 }
1615 else
1616 {
1617 return new LSL_Vector(m_host.AbsolutePosition.X,
1618 m_host.AbsolutePosition.Y,
1619 m_host.AbsolutePosition.Z);
1620 }
1621 }
1622
1623 public void llSetRot(LSL_Rotation rot)
1624 {
1625 m_host.AddScriptLPS(1);
1626
1627 SetRot(m_host, rot);
1628
1629 ScriptSleep(200);
1630 }
1631
1632 private void SetRot(SceneObjectPart part, LSL_Rotation rot)
1633 {
1634 part.UpdateRotation(new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s));
1635 // Update rotation does not move the object in the physics scene if it's a linkset.
1636 part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition;
1637 }
1638
1639 public LSL_Rotation llGetRot()
1640 {
1641 m_host.AddScriptLPS(1);
1642 Quaternion q = m_host.RotationOffset;
1643 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
1644 }
1645
1646 public LSL_Rotation llGetLocalRot()
1647 {
1648 m_host.AddScriptLPS(1);
1649 return new LSL_Rotation(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W);
1650 }
1651
1652 public void llSetForce(LSL_Vector force, int local)
1653 {
1654 m_host.AddScriptLPS(1);
1655
1656 if (m_host.ParentGroup != null)
1657 {
1658 if (m_host.ParentGroup.RootPart != null)
1659 {
1660 if (local != 0)
1661 force *= llGetRot();
1662
1663 m_host.ParentGroup.RootPart.SetForce(new PhysicsVector((float)force.x, (float)force.y, (float)force.z));
1664 }
1665 }
1666 }
1667
1668 public LSL_Vector llGetForce()
1669 {
1670 LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0);
1671
1672 m_host.AddScriptLPS(1);
1673
1674 if (m_host.ParentGroup != null)
1675 {
1676 if (m_host.ParentGroup.RootPart != null)
1677 {
1678 PhysicsVector tmpForce = m_host.ParentGroup.RootPart.GetForce();
1679 force.x = tmpForce.X;
1680 force.y = tmpForce.Y;
1681 force.z = tmpForce.Z;
1682 }
1683 }
1684
1685 return force;
1686 }
1687
1688 public LSL_Integer llTarget(LSL_Vector position, double range)
1689 {
1690 m_host.AddScriptLPS(1);
1691 return m_host.registerTargetWaypoint(new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range);
1692 }
1693
1694 public void llTargetRemove(int number)
1695 {
1696 m_host.AddScriptLPS(1);
1697 m_host.unregisterTargetWaypoint(number);
1698 }
1699
1700 public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
1701 {
1702 m_host.AddScriptLPS(1);
1703 NotImplemented("llRotTarget");
1704 return 0;
1705 }
1706
1707 public void llRotTargetRemove(int number)
1708 {
1709 m_host.AddScriptLPS(1);
1710 NotImplemented("llRotTargetRemove");
1711 }
1712
1713 public void llMoveToTarget(LSL_Vector target, double tau)
1714 {
1715 m_host.AddScriptLPS(1);
1716 m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau);
1717 }
1718
1719 public void llStopMoveToTarget()
1720 {
1721 m_host.AddScriptLPS(1);
1722 m_host.StopMoveToTarget();
1723 }
1724
1725 public void llApplyImpulse(LSL_Vector force, int local)
1726 {
1727 m_host.AddScriptLPS(1);
1728 //No energy force yet
1729
1730 if (force.x > 20000)
1731 force.x = 20000;
1732 if (force.y > 20000)
1733 force.y = 20000;
1734 if (force.z > 20000)
1735 force.z = 20000;
1736
1737 m_host.ApplyImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
1738 }
1739
1740 public void llApplyRotationalImpulse(LSL_Vector force, int local)
1741 {
1742 m_host.AddScriptLPS(1);
1743 NotImplemented("llApplyRotationalImpulse");
1744 }
1745
1746 public void llSetTorque(LSL_Vector torque, int local)
1747 {
1748 m_host.AddScriptLPS(1);
1749 NotImplemented("llSetTorque");
1750 }
1751
1752 public LSL_Vector llGetTorque()
1753 {
1754 m_host.AddScriptLPS(1);
1755 NotImplemented("llGetTorque");
1756 return new LSL_Vector();
1757 }
1758
1759 public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local)
1760 {
1761 m_host.AddScriptLPS(1);
1762 NotImplemented("llSetForceAndTorque");
1763 }
1764
1765 public LSL_Vector llGetVel()
1766 {
1767 m_host.AddScriptLPS(1);
1768 return new LSL_Vector(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z);
1769 }
1770
1771 public LSL_Vector llGetAccel()
1772 {
1773 m_host.AddScriptLPS(1);
1774 return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z);
1775 }
1776
1777 public LSL_Vector llGetOmega()
1778 {
1779 m_host.AddScriptLPS(1);
1780 return new LSL_Vector(m_host.RotationalVelocity.X, m_host.RotationalVelocity.Y, m_host.RotationalVelocity.Z);
1781 }
1782
1783 public LSL_Float llGetTimeOfDay()
1784 {
1785 m_host.AddScriptLPS(1);
1786 return (double)(((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4)) * World.TimeDilation);
1787 }
1788
1789 public LSL_Float llGetWallclock()
1790 {
1791 m_host.AddScriptLPS(1);
1792 return DateTime.Now.TimeOfDay.TotalSeconds;
1793 }
1794
1795 public LSL_Float llGetTime()
1796 {
1797 m_host.AddScriptLPS(1);
1798 TimeSpan ScriptTime = DateTime.Now - m_timer;
1799 return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation);
1800 }
1801
1802 public void llResetTime()
1803 {
1804 m_host.AddScriptLPS(1);
1805 m_timer = DateTime.Now;
1806 }
1807
1808 public LSL_Float llGetAndResetTime()
1809 {
1810 m_host.AddScriptLPS(1);
1811 TimeSpan ScriptTime = DateTime.Now - m_timer;
1812 m_timer = DateTime.Now;
1813 return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation);
1814 }
1815
1816 public void llSound()
1817 {
1818 m_host.AddScriptLPS(1);
1819 // This function has been deprecated
1820 // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound
1821 Deprecated("llSound");
1822 }
1823
1824 // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
1825 // 20080530 Updated to remove code duplication
1826 public void llPlaySound(string sound, double volume)
1827 {
1828 m_host.AddScriptLPS(1);
1829
1830 // send the sound, once, to all clients in range
1831 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0);
1832 }
1833
1834 // Xantor 20080528 we should do this differently.
1835 // 1) apply the sound to the object
1836 // 2) schedule full update
1837 // just sending the sound out once doesn't work so well when other avatars come in view later on
1838 // or when the prim gets moved, changed, sat on, whatever
1839 // see large number of mantises (mantes?)
1840 // 20080530 Updated to remove code duplication
1841 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
1842 public void llLoopSound(string sound, double volume)
1843 {
1844 m_host.AddScriptLPS(1);
1845
1846 if (m_host.Sound != UUID.Zero)
1847 llStopSound();
1848
1849 m_host.Sound = KeyOrName(sound);
1850 m_host.SoundGain = volume;
1851 m_host.SoundFlags = 1; // looping
1852 m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
1853
1854 m_host.ScheduleFullUpdate();
1855 m_host.SendFullUpdateToAllClients();
1856 }
1857
1858 public void llLoopSoundMaster(string sound, double volume)
1859 {
1860 m_host.AddScriptLPS(1);
1861 NotImplemented("llLoopSoundMaster");
1862 }
1863
1864 public void llLoopSoundSlave(string sound, double volume)
1865 {
1866 m_host.AddScriptLPS(1);
1867 NotImplemented("llLoopSoundSlave");
1868 }
1869
1870 public void llPlaySoundSlave(string sound, double volume)
1871 {
1872 m_host.AddScriptLPS(1);
1873 NotImplemented("llPlaySoundSlave");
1874 }
1875
1876 public void llTriggerSound(string sound, double volume)
1877 {
1878 m_host.AddScriptLPS(1);
1879 // send the sound, once, to all clients in range
1880 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0);
1881 }
1882
1883 // Xantor 20080528: Clear prim data of sound instead
1884 public void llStopSound()
1885 {
1886 m_host.AddScriptLPS(1);
1887
1888 m_host.Sound = UUID.Zero;
1889 m_host.SoundGain = 0;
1890 m_host.SoundFlags = 0;
1891 m_host.SoundRadius = 0;
1892
1893 m_host.ScheduleFullUpdate();
1894 m_host.SendFullUpdateToAllClients();
1895
1896 // m_host.SendSound(UUID.Zero.ToString(), 1.0, false, 2);
1897 }
1898
1899 public void llPreloadSound(string sound)
1900 {
1901 m_host.AddScriptLPS(1);
1902 m_host.PreloadSound(sound);
1903 // ScriptSleep(1000);
1904 }
1905
1906 /// <summary>
1907 /// Return a portion of the designated string bounded by
1908 /// inclusive indices (start and end). As usual, the negative
1909 /// indices, and the tolerance for out-of-bound values, makes
1910 /// this more complicated than it might otherwise seem.
1911 /// </summary>
1912
1913 public LSL_String llGetSubString(string src, int start, int end)
1914 {
1915
1916 m_host.AddScriptLPS(1);
1917
1918 // Normalize indices (if negative).
1919 // After normlaization they may still be
1920 // negative, but that is now relative to
1921 // the start, rather than the end, of the
1922 // sequence.
1923
1924 if (start < 0)
1925 {
1926 start = src.Length+start;
1927 }
1928 if (end < 0)
1929 {
1930 end = src.Length+end;
1931 }
1932
1933 // Conventional substring
1934 if (start <= end)
1935 {
1936 // Implies both bounds are out-of-range.
1937 if (end < 0 || start >= src.Length)
1938 {
1939 return String.Empty;
1940 }
1941 // If end is positive, then it directly
1942 // corresponds to the lengt of the substring
1943 // needed (plus one of course). BUT, it
1944 // must be within bounds.
1945 if (end >= src.Length)
1946 {
1947 end = src.Length-1;
1948 }
1949
1950 if (start < 0)
1951 {
1952 return src.Substring(0,end+1);
1953 }
1954 // Both indices are positive
1955 return src.Substring(start, (end+1) - start);
1956 }
1957
1958 // Inverted substring (end < start)
1959 else
1960 {
1961 // Implies both indices are below the
1962 // lower bound. In the inverted case, that
1963 // means the entire string will be returned
1964 // unchanged.
1965 if (start < 0)
1966 {
1967 return src;
1968 }
1969 // If both indices are greater than the upper
1970 // bound the result may seem initially counter
1971 // intuitive.
1972 if (end >= src.Length)
1973 {
1974 return src;
1975 }
1976
1977 if (end < 0)
1978 {
1979 if (start < src.Length)
1980 {
1981 return src.Substring(start);
1982 }
1983 else
1984 {
1985 return String.Empty;
1986 }
1987 }
1988 else
1989 {
1990 if (start < src.Length)
1991 {
1992 return src.Substring(0,end+1) + src.Substring(start);
1993 }
1994 else
1995 {
1996 return src.Substring(0,end+1);
1997 }
1998 }
1999 }
2000 }
2001
2002 /// <summary>
2003 /// Delete substring removes the specified substring bounded
2004 /// by the inclusive indices start and end. Indices may be
2005 /// negative (indicating end-relative) and may be inverted,
2006 /// i.e. end < start.
2007 /// </summary>
2008
2009 public LSL_String llDeleteSubString(string src, int start, int end)
2010 {
2011
2012 m_host.AddScriptLPS(1);
2013
2014 // Normalize indices (if negative).
2015 // After normlaization they may still be
2016 // negative, but that is now relative to
2017 // the start, rather than the end, of the
2018 // sequence.
2019 if (start < 0)
2020 {
2021 start = src.Length+start;
2022 }
2023 if (end < 0)
2024 {
2025 end = src.Length+end;
2026 }
2027 // Conventionally delimited substring
2028 if (start <= end)
2029 {
2030 // If both bounds are outside of the existing
2031 // string, then return unchanges.
2032 if (end < 0 || start >= src.Length)
2033 {
2034 return src;
2035 }
2036 // At least one bound is in-range, so we
2037 // need to clip the out-of-bound argument.
2038 if (start < 0)
2039 {
2040 start = 0;
2041 }
2042
2043 if (end >= src.Length)
2044 {
2045 end = src.Length-1;
2046 }
2047
2048 return src.Remove(start,end-start+1);
2049 }
2050 // Inverted substring
2051 else
2052 {
2053 // In this case, out of bounds means that
2054 // the existing string is part of the cut.
2055 if (start < 0 || end >= src.Length)
2056 {
2057 return String.Empty;
2058 }
2059
2060 if (end > 0)
2061 {
2062 if (start < src.Length)
2063 {
2064 return src.Remove(start).Remove(0,end+1);
2065 }
2066 else
2067 {
2068 return src.Remove(0,end+1);
2069 }
2070 }
2071 else
2072 {
2073 if (start < src.Length)
2074 {
2075 return src.Remove(start);
2076 }
2077 else
2078 {
2079 return src;
2080 }
2081 }
2082 }
2083 }
2084
2085 /// <summary>
2086 /// Insert string inserts the specified string identified by src
2087 /// at the index indicated by index. Index may be negative, in
2088 /// which case it is end-relative. The index may exceed either
2089 /// string bound, with the result being a concatenation.
2090 /// </summary>
2091
2092 public LSL_String llInsertString(string dest, int index, string src)
2093 {
2094
2095 m_host.AddScriptLPS(1);
2096
2097 // Normalize indices (if negative).
2098 // After normlaization they may still be
2099 // negative, but that is now relative to
2100 // the start, rather than the end, of the
2101 // sequence.
2102 if (index < 0)
2103 {
2104 index = dest.Length+index;
2105
2106 // Negative now means it is less than the lower
2107 // bound of the string.
2108
2109 if (index < 0)
2110 {
2111 return src+dest;
2112 }
2113
2114 }
2115
2116 if (index >= dest.Length)
2117 {
2118 return dest+src;
2119 }
2120
2121 // The index is in bounds.
2122 // In this case the index refers to the index that will
2123 // be assigned to the first character of the inserted string.
2124 // So unlike the other string operations, we do not add one
2125 // to get the correct string length.
2126 return dest.Substring(0,index)+src+dest.Substring(index);
2127
2128 }
2129
2130 public LSL_String llToUpper(string src)
2131 {
2132 m_host.AddScriptLPS(1);
2133 return src.ToUpper();
2134 }
2135
2136 public LSL_String llToLower(string src)
2137 {
2138 m_host.AddScriptLPS(1);
2139 return src.ToLower();
2140 }
2141
2142 public LSL_Integer llGiveMoney(string destination, int amount)
2143 {
2144 UUID invItemID=InventorySelf();
2145 if (invItemID == UUID.Zero)
2146 return 0;
2147
2148 m_host.AddScriptLPS(1);
2149
2150 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
2151 return 0;
2152
2153 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
2154 {
2155 LSLError("No permissions to give money");
2156 return 0;
2157 }
2158
2159 UUID toID=new UUID();
2160
2161 if (!UUID.TryParse(destination, out toID))
2162 {
2163 LSLError("Bad key in llGiveMoney");
2164 return 0;
2165 }
2166
2167 IMoneyModule money=World.RequestModuleInterface<IMoneyModule>();
2168
2169 if (money == null)
2170 {
2171 NotImplemented("llGiveMoney");
2172 return 0;
2173 }
2174
2175 bool result=money.ObjectGiveMoney(m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
2176
2177 if (result)
2178 return 1;
2179
2180 return 0;
2181 }
2182
2183 public void llMakeExplosion()
2184 {
2185 m_host.AddScriptLPS(1);
2186 Deprecated("llMakeExplosion");
2187 // ScriptSleep(100);
2188 }
2189
2190 public void llMakeFountain()
2191 {
2192 m_host.AddScriptLPS(1);
2193 Deprecated("llMakeFountain");
2194 // ScriptSleep(100);
2195 }
2196
2197 public void llMakeSmoke()
2198 {
2199 m_host.AddScriptLPS(1);
2200 Deprecated("llMakeSmoke");
2201 // ScriptSleep(100);
2202 }
2203
2204 public void llMakeFire()
2205 {
2206 m_host.AddScriptLPS(1);
2207 Deprecated("llMakeFire");
2208 // ScriptSleep(100);
2209 }
2210
2211 public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
2212 {
2213 m_host.AddScriptLPS(1);
2214
2215 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
2216 return;
2217 float dist = (float)llVecDist(llGetPos(), pos);
2218
2219 if (dist > m_ScriptDistanceFactor * 10.0f)
2220 return;
2221
2222 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
2223 {
2224 if (inv.Value.Name == inventory)
2225 {
2226 // make sure we're an object.
2227 if (inv.Value.InvType != (int)InventoryType.Object)
2228 {
2229 llSay(0, "Unable to create requested object. Object is missing from database.");
2230 return;
2231 }
2232
2233 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
2234
2235 // test if we're further away then 10m
2236 if (Util.GetDistanceTo(llpos, m_host.AbsolutePosition) > 10)
2237 return; // wiki says, if it's further away then 10m, silently fail.
2238
2239 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z);
2240
2241 // need the magnitude later
2242 float velmag = (float)Util.GetMagnitude(llvel);
2243
2244 SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), llvel, param);
2245
2246 // If either of these are null, then there was an unknown error.
2247 if (new_group == null)
2248 continue;
2249 if (new_group.RootPart == null)
2250 continue;
2251
2252 // objects rezzed with this method are die_at_edge by default.
2253 new_group.RootPart.SetDieAtEdge(true);
2254
2255 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2256 "object_rez", new Object[] {
2257 new LSL_String(
2258 new_group.RootPart.UUID.ToString()) },
2259 new DetectParams[0]));
2260
2261 float groupmass = new_group.GetMass();
2262
2263 //Recoil.
2264 llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0);
2265 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
2266 ScriptSleep((int)((groupmass * velmag) / 10));
2267 // ScriptSleep(100);
2268 return;
2269 }
2270 }
2271 llSay(0, "Could not find object " + inventory);
2272 }
2273
2274 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
2275 {
2276 llRezAtRoot(inventory, pos, vel, rot, param);
2277 }
2278
2279 public void llLookAt(LSL_Vector target, double strength, double damping)
2280 {
2281 m_host.AddScriptLPS(1);
2282 NotImplemented("llLookAt");
2283 }
2284
2285 public void llStopLookAt()
2286 {
2287 m_host.AddScriptLPS(1);
2288 NotImplemented("llStopLookAt");
2289 }
2290
2291 public void llSetTimerEvent(double sec)
2292 {
2293 m_host.AddScriptLPS(1);
2294 // Setting timer repeat
2295 AsyncCommands.TimerPlugin.SetTimerEvent(m_localID, m_itemID, sec);
2296 }
2297
2298 public void llSleep(double sec)
2299 {
2300 m_host.AddScriptLPS(1);
2301 Thread.Sleep((int)(sec * 1000));
2302 }
2303
2304 public LSL_Float llGetMass()
2305 {
2306 m_host.AddScriptLPS(1);
2307 return m_host.GetMass();
2308 }
2309
2310 public void llCollisionFilter(string name, string id, int accept)
2311 {
2312 m_host.AddScriptLPS(1);
2313 NotImplemented("llCollisionFilter");
2314 }
2315
2316 public void llTakeControls(int controls, int accept, int pass_on)
2317 {
2318 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2319 {
2320 return;
2321 }
2322
2323 if (m_host.TaskInventory[InventorySelf()].PermsGranter != UUID.Zero)
2324 {
2325 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter);
2326
2327 if (presence != null)
2328 {
2329 if ((m_host.TaskInventory[InventorySelf()].PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
2330 {
2331 presence.RegisterControlEventsToScript(controls, accept, pass_on, m_localID, m_itemID);
2332
2333 }
2334 }
2335 }
2336
2337 m_host.AddScriptLPS(1);
2338 }
2339
2340 public void llReleaseControls()
2341 {
2342 m_host.AddScriptLPS(1);
2343
2344 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2345 {
2346 return;
2347 }
2348
2349 if (m_host.TaskInventory[InventorySelf()].PermsGranter != UUID.Zero)
2350 {
2351 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter);
2352
2353 if (presence != null)
2354 {
2355 if ((m_host.TaskInventory[InventorySelf()].PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
2356 {
2357 // Unregister controls from Presence
2358 presence.UnRegisterControlEventsToScript(m_localID, m_itemID);
2359 // Remove Take Control permission.
2360 m_host.TaskInventory[InventorySelf()].PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
2361 }
2362 }
2363 }
2364 }
2365
2366 public void llAttachToAvatar(int attachment)
2367 {
2368 m_host.AddScriptLPS(1);
2369 NotImplemented("llAttachToAvatar");
2370 }
2371
2372 public void llDetachFromAvatar()
2373 {
2374 m_host.AddScriptLPS(1);
2375 NotImplemented("llDetachFromAvatar");
2376 }
2377
2378 public void llTakeCamera(string avatar)
2379 {
2380 m_host.AddScriptLPS(1);
2381 Deprecated("llTakeCamera");
2382 }
2383
2384 public void llReleaseCamera(string avatar)
2385 {
2386 m_host.AddScriptLPS(1);
2387 Deprecated("llReleaseCamera");
2388 }
2389
2390 public LSL_String llGetOwner()
2391 {
2392 m_host.AddScriptLPS(1);
2393
2394 return m_host.ObjectOwner.ToString();
2395 }
2396
2397 public void llInstantMessage(string user, string message)
2398 {
2399 m_host.AddScriptLPS(1);
2400
2401 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
2402 // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
2403 // but I don't think we have a list of scenes available from here.
2404 // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
2405
2406 // user is a UUID
2407
2408 // TODO: figure out values for client, fromSession, and imSessionID
2409 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
2410 UUID friendTransactionID = UUID.Random();
2411
2412 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
2413
2414 GridInstantMessage msg = new GridInstantMessage();
2415 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
2416 msg.fromAgentSession = new Guid(friendTransactionID.ToString());// fromAgentSession.UUID;
2417 msg.toAgentID = new Guid(user); // toAgentID.Guid;
2418 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
2419// Console.WriteLine("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
2420// Console.WriteLine("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
2421 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp;
2422 //if (client != null)
2423 //{
2424 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
2425 //}
2426 //else
2427 //{
2428 // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it
2429 //}
2430 msg.message = message;
2431 msg.dialog = (byte)19; // messgage from script ??? // dialog;
2432 msg.fromGroup = false;// fromGroup;
2433 msg.offline = (byte)0; //offline;
2434 msg.ParentEstateID = 0; //ParentEstateID;
2435 msg.Position = Vector3.Zero;// new Vector3(m_host.AbsolutePosition);
2436 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
2437 msg.binaryBucket = new byte[0];// binaryBucket;
2438 World.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
2439 // ScriptSleep(2000);
2440 }
2441
2442 public void llEmail(string address, string subject, string message)
2443 {
2444 m_host.AddScriptLPS(1);
2445 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
2446 if (emailModule == null)
2447 return;
2448
2449 emailModule.SendEmail(m_host.UUID, address, subject, message);
2450 // ScriptSleep(20000);
2451 }
2452
2453 public void llGetNextEmail(string address, string subject)
2454 {
2455 m_host.AddScriptLPS(1);
2456 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
2457 if (emailModule == null)
2458 return;
2459 Email email;
2460
2461 email = emailModule.GetNextEmail(m_host.UUID, address, subject);
2462
2463 if (email == null)
2464 return;
2465
2466 m_ScriptEngine.PostObjectEvent(m_host.LocalId,
2467 new EventParams("email",
2468 new Object[] {
2469 new LSL_String(email.time),
2470 new LSL_String(email.sender),
2471 new LSL_String(email.subject),
2472 new LSL_String(email.message),
2473 new LSL_Integer(email.numLeft)},
2474 new DetectParams[0]));
2475
2476 }
2477
2478 public LSL_String llGetKey()
2479 {
2480 m_host.AddScriptLPS(1);
2481 return m_host.UUID.ToString();
2482 }
2483
2484 public void llSetBuoyancy(double buoyancy)
2485 {
2486 m_host.AddScriptLPS(1);
2487 if (m_host.ParentGroup != null)
2488 {
2489 if (m_host.ParentGroup.RootPart != null)
2490 {
2491 m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy);
2492 }
2493 }
2494 }
2495
2496
2497
2498 public void llSetHoverHeight(double height, int water, double tau)
2499 {
2500 m_host.AddScriptLPS(1);
2501 NotImplemented("llSetHoverHeight");
2502 }
2503
2504 public void llStopHover()
2505 {
2506 m_host.AddScriptLPS(1);
2507 NotImplemented("llStopHover");
2508 }
2509
2510 public void llMinEventDelay(double delay)
2511 {
2512 m_host.AddScriptLPS(1);
2513 NotImplemented("llMinEventDelay");
2514 }
2515
2516 public void llSoundPreload()
2517 {
2518 m_host.AddScriptLPS(1);
2519 Deprecated("llSoundPreload");
2520 }
2521
2522 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
2523 {
2524 m_host.AddScriptLPS(1);
2525 NotImplemented("llRotLookAt");
2526 }
2527
2528 public LSL_Integer llStringLength(string str)
2529 {
2530 m_host.AddScriptLPS(1);
2531 if (str.Length > 0)
2532 {
2533 return str.Length;
2534 }
2535 else
2536 {
2537 return 0;
2538 }
2539 }
2540
2541 public void llStartAnimation(string anim)
2542 {
2543 m_host.AddScriptLPS(1);
2544
2545 UUID invItemID=InventorySelf();
2546 if (invItemID == UUID.Zero)
2547 return;
2548
2549 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
2550 return;
2551
2552 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
2553 {
2554 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter);
2555
2556 if (presence != null)
2557 {
2558 // Do NOT try to parse UUID, animations cannot be triggered by ID
2559 UUID animID=InventoryKey(anim, (int)AssetType.Animation);
2560 if (animID == UUID.Zero)
2561 presence.AddAnimation(anim);
2562 else
2563 presence.AddAnimation(animID);
2564 }
2565 }
2566 }
2567
2568 public void llStopAnimation(string anim)
2569 {
2570 m_host.AddScriptLPS(1);
2571
2572 UUID invItemID=InventorySelf();
2573 if (invItemID == UUID.Zero)
2574 return;
2575
2576 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
2577 return;
2578
2579 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
2580 {
2581 UUID animID = new UUID();
2582
2583 if (!UUID.TryParse(anim, out animID))
2584 {
2585 animID=InventoryKey(anim);
2586 }
2587
2588 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter);
2589
2590 if (presence != null)
2591 {
2592 if (animID == UUID.Zero)
2593 presence.RemoveAnimation(anim);
2594 else
2595 presence.RemoveAnimation(animID);
2596 }
2597 }
2598 }
2599
2600 public void llPointAt()
2601 {
2602 m_host.AddScriptLPS(1);
2603 NotImplemented("llPointAt");
2604 }
2605
2606 public void llStopPointAt()
2607 {
2608 m_host.AddScriptLPS(1);
2609 NotImplemented("llStopPointAt");
2610 }
2611
2612 public void llTargetOmega(LSL_Vector axis, double spinrate, double gain)
2613 {
2614 m_host.AddScriptLPS(1);
2615 m_host.RotationalVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
2616 m_host.AngularVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
2617 m_host.ScheduleTerseUpdate();
2618 m_host.SendTerseUpdateToAllClients();
2619 m_host.ParentGroup.HasGroupChanged = true;
2620 }
2621
2622 public LSL_Integer llGetStartParameter()
2623 {
2624 m_host.AddScriptLPS(1);
2625 return m_ScriptEngine.GetStartParameter(m_itemID);
2626 }
2627
2628 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
2629 {
2630 m_host.AddScriptLPS(1);
2631 NotImplemented("llGodLikeRezObject");
2632 }
2633
2634 public void llRequestPermissions(string agent, int perm)
2635 {
2636 UUID agentID=new UUID();
2637
2638 if (!UUID.TryParse(agent, out agentID))
2639 return;
2640
2641 UUID invItemID=InventorySelf();
2642
2643 if (invItemID == UUID.Zero)
2644 return; // Not in a prim? How??
2645
2646 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
2647 {
2648 llReleaseControls();
2649
2650 m_host.TaskInventory[invItemID].PermsGranter=UUID.Zero;
2651 m_host.TaskInventory[invItemID].PermsMask=0;
2652
2653 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2654 "run_time_permissions", new Object[] {
2655 new LSL_Integer(0) },
2656 new DetectParams[0]));
2657
2658 return;
2659 }
2660
2661 if ( m_host.TaskInventory[invItemID].PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
2662 llReleaseControls();
2663
2664 m_host.AddScriptLPS(1);
2665
2666 if (m_host.ParentGroup.RootPart.IsAttachment && agent == m_host.ParentGroup.RootPart.AttachedAvatar)
2667 {
2668 // When attached, certain permissions are implicit if requested from owner
2669 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
2670 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
2671 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
2672 ScriptBaseClass.PERMISSION_ATTACH;
2673
2674 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
2675 {
2676 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2677 m_host.TaskInventory[invItemID].PermsMask=perm;
2678
2679 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2680 "run_time_permissions", new Object[] {
2681 new LSL_Integer(perm) },
2682 new DetectParams[0]));
2683
2684 return;
2685 }
2686 }
2687 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar
2688 {
2689 // When agent is sitting, certain permissions are implicit if requested from sitting agent
2690 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
2691 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
2692 ScriptBaseClass.PERMISSION_TRACK_CAMERA;
2693
2694 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
2695 {
2696 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2697 m_host.TaskInventory[invItemID].PermsMask=perm;
2698
2699 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2700 "run_time_permissions", new Object[] {
2701 new LSL_Integer(perm) },
2702 new DetectParams[0]));
2703
2704 return;
2705 }
2706 }
2707
2708 ScenePresence presence = World.GetScenePresence(agentID);
2709
2710 if (presence != null)
2711 {
2712 string ownerName=resolveName(m_host.ParentGroup.RootPart.OwnerID);
2713 if (ownerName == String.Empty)
2714 ownerName="(hippos)";
2715
2716 if (!m_waitingForScriptAnswer)
2717 {
2718 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2719 m_host.TaskInventory[invItemID].PermsMask=0;
2720 presence.ControllingClient.OnScriptAnswer+=handleScriptAnswer;
2721 m_waitingForScriptAnswer=true;
2722 }
2723
2724 presence.ControllingClient.SendScriptQuestion(m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, invItemID, perm);
2725 return;
2726 }
2727
2728 // Requested agent is not in range, refuse perms
2729 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2730 "run_time_permissions", new Object[] {
2731 new LSL_Integer(0) },
2732 new DetectParams[0]));
2733 }
2734
2735 void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer)
2736 {
2737 if (taskID != m_host.UUID)
2738 return;
2739
2740 UUID invItemID=InventorySelf();
2741
2742 if (invItemID == UUID.Zero)
2743 return;
2744
2745 client.OnScriptAnswer-=handleScriptAnswer;
2746 m_waitingForScriptAnswer=false;
2747
2748 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
2749 llReleaseControls();
2750
2751 m_host.TaskInventory[invItemID].PermsMask=answer;
2752 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
2753 "run_time_permissions", new Object[] {
2754 new LSL_Integer(answer) },
2755 new DetectParams[0]));
2756 }
2757
2758 public LSL_String llGetPermissionsKey()
2759 {
2760 m_host.AddScriptLPS(1);
2761
2762 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2763 {
2764 if (item.Type == 10 && item.ItemID == m_itemID)
2765 {
2766 return item.PermsGranter.ToString();
2767 }
2768 }
2769
2770 return UUID.Zero.ToString();
2771 }
2772
2773 public LSL_Integer llGetPermissions()
2774 {
2775 m_host.AddScriptLPS(1);
2776
2777 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2778 {
2779 if (item.Type == 10 && item.ItemID == m_itemID)
2780 {
2781 return item.PermsMask;
2782 }
2783 }
2784
2785 return 0;
2786 }
2787
2788 public LSL_Integer llGetLinkNumber()
2789 {
2790 m_host.AddScriptLPS(1);
2791
2792 if (m_host.ParentGroup.Children.Count > 1)
2793 {
2794 return m_host.LinkNum;
2795 }
2796 else
2797 {
2798 return 0;
2799 }
2800 }
2801
2802 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
2803 {
2804 List<SceneObjectPart> parts = GetLinkParts(linknumber);
2805
2806 foreach (SceneObjectPart part in parts)
2807 SetColor(part, color, face);
2808 }
2809
2810 public void llCreateLink(string target, int parent)
2811 {
2812 m_host.AddScriptLPS(1);
2813 UUID invItemID = InventorySelf();
2814 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0) {
2815 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
2816 return;
2817 }
2818 IClientAPI client = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter).ControllingClient;
2819 SceneObjectPart targetPart = World.GetSceneObjectPart(target);
2820 SceneObjectGroup parentPrim = null, childPrim = null;
2821 if (targetPart != null)
2822 {
2823 if (parent != 0) {
2824 parentPrim = m_host.ParentGroup;
2825 childPrim = targetPart.ParentGroup;
2826 }
2827 else
2828 {
2829 parentPrim = targetPart.ParentGroup;
2830 childPrim = m_host.ParentGroup;
2831 }
2832// byte uf = childPrim.RootPart.UpdateFlag;
2833 childPrim.RootPart.UpdateFlag = 0;
2834 parentPrim.LinkToGroup(childPrim);
2835// if (uf != (Byte)0)
2836// parent.RootPart.UpdateFlag = uf;
2837 }
2838 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
2839 parentPrim.RootPart.AddFlag(PrimFlags.CreateSelected);
2840 parentPrim.HasGroupChanged = true;
2841 parentPrim.ScheduleGroupForFullUpdate();
2842 parentPrim.GetProperties(client);
2843
2844 ScriptSleep(1000);
2845 }
2846
2847 public void llBreakLink(int linknum)
2848 {
2849 m_host.AddScriptLPS(1);
2850 UUID invItemID = InventorySelf();
2851 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0)
2852 {
2853 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
2854 return;
2855 }
2856 if (linknum < ScriptBaseClass.LINK_THIS)
2857 return;
2858 SceneObjectGroup parentPrim = m_host.ParentGroup;
2859 SceneObjectPart childPrim = null;
2860 switch (linknum)
2861 {
2862 case ScriptBaseClass.LINK_ROOT:
2863 break;
2864 case ScriptBaseClass.LINK_SET:
2865 case ScriptBaseClass.LINK_ALL_OTHERS:
2866 case ScriptBaseClass.LINK_ALL_CHILDREN:
2867 case ScriptBaseClass.LINK_THIS:
2868 foreach (SceneObjectPart part in parentPrim.Children.Values)
2869 {
2870 if (part.UUID != m_host.UUID)
2871 {
2872 childPrim = part;
2873 break;
2874 }
2875 }
2876 break;
2877 default:
2878 childPrim = parentPrim.GetLinkNumPart(linknum);
2879 if (childPrim.UUID == m_host.UUID)
2880 childPrim = null;
2881 break;
2882 }
2883 if (linknum == ScriptBaseClass.LINK_ROOT)
2884 {
2885 // Restructuring Multiple Prims.
2886 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
2887 parts.Remove(parentPrim.RootPart);
2888 foreach (SceneObjectPart part in parts)
2889 {
2890 parentPrim.DelinkFromGroup(part.LocalId, true);
2891 }
2892 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
2893 if (parts.Count > 0) {
2894 SceneObjectPart newRoot = parts[0];
2895 parts.Remove(newRoot);
2896 foreach (SceneObjectPart part in parts)
2897 {
2898 part.UpdateFlag = 0;
2899 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
2900 }
2901 }
2902 }
2903 else
2904 {
2905 if (childPrim == null)
2906 return;
2907 parentPrim.DelinkFromGroup(childPrim.LocalId, true);
2908 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
2909 }
2910 }
2911
2912 public void llBreakAllLinks()
2913 {
2914 m_host.AddScriptLPS(1);
2915 SceneObjectGroup parentPrim = m_host.ParentGroup;
2916 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
2917 parts.Remove(parentPrim.RootPart);
2918 foreach (SceneObjectPart part in parts)
2919 {
2920 parentPrim.DelinkFromGroup(part.LocalId, true);
2921 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
2922 }
2923 }
2924
2925 public LSL_String llGetLinkKey(int linknum)
2926 {
2927 m_host.AddScriptLPS(1);
2928 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
2929 if (part != null)
2930 {
2931 return part.UUID.ToString();
2932 }
2933 else
2934 {
2935 return UUID.Zero.ToString();
2936 }
2937 }
2938
2939 public LSL_String llGetLinkName(int linknum)
2940 {
2941 m_host.AddScriptLPS(1);
2942 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
2943 if (part != null)
2944 {
2945 return part.Name;
2946 }
2947 else
2948 {
2949 return "";
2950 }
2951 }
2952
2953 public LSL_Integer llGetInventoryNumber(int type)
2954 {
2955 m_host.AddScriptLPS(1);
2956 int count = 0;
2957 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
2958 {
2959 if (inv.Value.Type == type || type == -1)
2960 {
2961 count = count + 1;
2962 }
2963 }
2964 return count;
2965 }
2966
2967 public LSL_String llGetInventoryName(int type, int number)
2968 {
2969 m_host.AddScriptLPS(1);
2970 ArrayList keys = new ArrayList();
2971 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
2972 {
2973 if (inv.Value.Type == type || type == -1)
2974 {
2975 keys.Add(inv.Value.Name);
2976 }
2977 }
2978 if (keys.Count == 0)
2979 {
2980 return String.Empty;
2981 }
2982 keys.Sort();
2983 if (keys.Count > number)
2984 {
2985 return (string)keys[number];
2986 }
2987 return String.Empty;
2988 }
2989
2990 public LSL_Float llGetEnergy()
2991 {
2992 m_host.AddScriptLPS(1);
2993 // TODO: figure out real energy value
2994 return 1.0f;
2995 }
2996
2997 public void llGiveInventory(string destination, string inventory)
2998 {
2999 m_host.AddScriptLPS(1);
3000 bool found = false;
3001 UUID destId = UUID.Zero;
3002 UUID objId = UUID.Zero;
3003
3004 if (!UUID.TryParse(destination, out destId))
3005 {
3006 llSay(0, "Could not parse key " + destination);
3007 return;
3008 }
3009
3010 // move the first object found with this inventory name
3011 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3012 {
3013 if (inv.Value.Name == inventory)
3014 {
3015 found = true;
3016 objId = inv.Key;
3017 break;
3018 }
3019 }
3020
3021 if (!found)
3022 {
3023 llSay(0, String.Format("Could not find object '{0}'", inventory));
3024 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3025 }
3026
3027 // check if destination is an avatar
3028 if (World.GetScenePresence(destId) != null)
3029 {
3030 // destination is an avatar
3031 World.MoveTaskInventoryItem(destId, null, m_host, objId);
3032 }
3033 else
3034 {
3035 // destination is an object
3036 World.MoveTaskInventoryItem(destId, m_host, objId);
3037 }
3038 // ScriptSleep(3000);
3039 }
3040
3041 public void llRemoveInventory(string name)
3042 {
3043 m_host.AddScriptLPS(1);
3044 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3045 {
3046 if (item.Name == name)
3047 {
3048 m_host.RemoveInventoryItem(item.ItemID);
3049 return;
3050 }
3051 }
3052 }
3053
3054 public void llSetText(string text, LSL_Vector color, double alpha)
3055 {
3056 m_host.AddScriptLPS(1);
3057 Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f),
3058 Util.Clip((float)color.y, 0.0f, 1.0f),
3059 Util.Clip((float)color.z, 0.0f, 1.0f));
3060 m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
3061 m_host.ParentGroup.HasGroupChanged = true;
3062 }
3063
3064 public LSL_Float llWater(LSL_Vector offset)
3065 {
3066 m_host.AddScriptLPS(1);
3067 return World.RegionInfo.RegionSettings.WaterHeight;
3068 }
3069
3070 public void llPassTouches(int pass)
3071 {
3072 m_host.AddScriptLPS(1);
3073 NotImplemented("llPassTouches");
3074 }
3075
3076 public LSL_String llRequestAgentData(string id, int data)
3077 {
3078 m_host.AddScriptLPS(1);
3079
3080 UserProfileData userProfile =
3081 World.CommsManager.UserService.GetUserProfile(id);
3082
3083 UserAgentData userAgent =
3084 World.CommsManager.UserService.GetAgentByUUID(id);
3085
3086 if (userProfile == null || userAgent == null)
3087 return UUID.Zero.ToString();
3088
3089 string reply = String.Empty;
3090
3091 switch (data)
3092 {
3093 case 1: // DATA_ONLINE (0|1)
3094 // TODO: implement fetching of this information
3095 if (userProfile.CurrentAgent.AgentOnline)
3096 reply = "1";
3097 else
3098 reply = "0";
3099 break;
3100 case 2: // DATA_NAME (First Last)
3101 reply = userProfile.FirstName + " " + userProfile.SurName;
3102 break;
3103 case 3: // DATA_BORN (YYYY-MM-DD)
3104 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
3105 born = born.AddSeconds(userProfile.Created);
3106 reply = born.ToString("yyyy-MM-dd");
3107 break;
3108 case 4: // DATA_RATING (0,0,0,0,0,0)
3109 reply = "0,0,0,0,0,0";
3110 break;
3111 case 8: // DATA_PAYINFO (0|1|2|3)
3112 reply = "0";
3113 break;
3114 default:
3115 return UUID.Zero.ToString(); // Raise no event
3116 }
3117
3118 UUID rq = UUID.Random();
3119
3120 UUID tid = AsyncCommands.
3121 DataserverPlugin.RegisterRequest(m_localID,
3122 m_itemID, rq.ToString());
3123
3124 AsyncCommands.
3125 DataserverPlugin.DataserverReply(rq.ToString(), reply);
3126
3127 // ScriptSleep(100);
3128 return tid.ToString();
3129 }
3130
3131 public LSL_String llRequestInventoryData(string name)
3132 {
3133 m_host.AddScriptLPS(1);
3134
3135 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3136 {
3137 if (item.Type == 3 && item.Name == name)
3138 {
3139 UUID tid = AsyncCommands.
3140 DataserverPlugin.RegisterRequest(m_localID,
3141 m_itemID, item.AssetID.ToString());
3142
3143 Vector3 region = new Vector3(
3144 World.RegionInfo.RegionLocX * Constants.RegionSize,
3145 World.RegionInfo.RegionLocY * Constants.RegionSize,
3146 0);
3147
3148 World.AssetCache.GetAsset(item.AssetID,
3149 delegate(UUID i, AssetBase a)
3150 {
3151 AssetLandmark lm = new AssetLandmark(a);
3152
3153 float rx = (uint)(lm.RegionHandle >> 32);
3154 float ry = (uint)lm.RegionHandle;
3155 region = lm.Position + new Vector3(rx, ry, 0) - region;
3156
3157 string reply = region.ToString();
3158 AsyncCommands.
3159 DataserverPlugin.DataserverReply(i.ToString(),
3160 reply);
3161 }, false);
3162
3163 // ScriptSleep(1000);
3164 return tid.ToString();
3165 }
3166 }
3167 // ScriptSleep(1000);
3168 return String.Empty;
3169 }
3170
3171 public void llSetDamage(double damage)
3172 {
3173 m_host.AddScriptLPS(1);
3174 NotImplemented("llSetDamage");
3175 }
3176
3177 public void llTeleportAgentHome(string agent)
3178 {
3179 m_host.AddScriptLPS(1);
3180 UUID agentId = new UUID();
3181 if (UUID.TryParse(agent, out agentId))
3182 {
3183 ScenePresence presence = World.GetScenePresence(agentId);
3184 if (presence != null)
3185 {
3186 // agent must be over the owners land
3187 if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y))
3188 World.TeleportClientHome(agentId, presence.ControllingClient);
3189 }
3190 }
3191 // ScriptSleep(5000);
3192 }
3193
3194 public void llTextBox(string avatar, string message, int chat_channel)
3195 {
3196 m_host.AddScriptLPS(1);
3197 NotImplemented("llTextBox");
3198 }
3199
3200 public void llModifyLand(int action, int brush)
3201 {
3202 m_host.AddScriptLPS(1);
3203 World.ExternalChecks.ExternalChecksCanTerraformLand(m_host.OwnerID, new Vector3(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, 0));
3204 }
3205
3206 public void llCollisionSound(string impact_sound, double impact_volume)
3207 {
3208 m_host.AddScriptLPS(1);
3209 NotImplemented("llCollisionSound");
3210 }
3211
3212 public void llCollisionSprite(string impact_sprite)
3213 {
3214 m_host.AddScriptLPS(1);
3215 NotImplemented("llCollisionSprite");
3216 }
3217
3218 public LSL_String llGetAnimation(string id)
3219 {
3220 m_host.AddScriptLPS(1);
3221 NotImplemented("llGetAnimation");
3222 return String.Empty;
3223 }
3224
3225 public void llMessageLinked(int linknum, int num, string msg, string id)
3226 {
3227
3228 m_host.AddScriptLPS(1);
3229
3230 // uint partLocalID;
3231 UUID partItemID;
3232
3233 switch ((int)linknum)
3234 {
3235
3236 case (int)ScriptBaseClass.LINK_ROOT:
3237
3238 SceneObjectPart part = m_host.ParentGroup.RootPart;
3239
3240 foreach (TaskInventoryItem item in part.TaskInventory.Values)
3241 {
3242 if (item.Type == 10)
3243 {
3244 // partLocalID = part.LocalId;
3245 partItemID = item.ItemID;
3246
3247 object[] resobj = new object[]
3248 {
3249 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3250 };
3251
3252 m_ScriptEngine.PostScriptEvent(partItemID,
3253 new EventParams("link_message",
3254 resobj, new DetectParams[0]));
3255 }
3256 }
3257
3258 break;
3259
3260 case (int)ScriptBaseClass.LINK_SET:
3261
3262 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
3263 {
3264
3265 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
3266 {
3267 if (item.Type == 10)
3268 {
3269 // partLocalID = partInst.LocalId;
3270 partItemID = item.ItemID;
3271 Object[] resobj = new object[]
3272 {
3273 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3274 };
3275
3276 m_ScriptEngine.PostScriptEvent(partItemID,
3277 new EventParams("link_message",
3278 resobj, new DetectParams[0]));
3279 }
3280 }
3281 }
3282
3283 break;
3284
3285 case (int)ScriptBaseClass.LINK_ALL_OTHERS:
3286
3287 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
3288 {
3289
3290 if (partInst.LocalId != m_host.LocalId)
3291 {
3292
3293 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
3294 {
3295 if (item.Type == 10)
3296 {
3297 // partLocalID = partInst.LocalId;
3298 partItemID = item.ItemID;
3299 Object[] resobj = new object[]
3300 {
3301 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3302 };
3303
3304 m_ScriptEngine.PostScriptEvent(partItemID,
3305 new EventParams("link_message",
3306 resobj, new DetectParams[0]));
3307 }
3308 }
3309
3310 }
3311 }
3312
3313 break;
3314
3315 case (int)ScriptBaseClass.LINK_ALL_CHILDREN:
3316
3317 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
3318 {
3319
3320 if (partInst.LocalId != m_host.ParentGroup.RootPart.LocalId)
3321 {
3322
3323 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
3324 {
3325 if (item.Type == 10)
3326 {
3327 // partLocalID = partInst.LocalId;
3328 partItemID = item.ItemID;
3329 Object[] resobj = new object[]
3330 {
3331 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3332 };
3333
3334 m_ScriptEngine.PostScriptEvent(partItemID,
3335 new EventParams("link_message",
3336 resobj, new DetectParams[0]));
3337 }
3338 }
3339
3340 }
3341 }
3342
3343 break;
3344
3345 case (int)ScriptBaseClass.LINK_THIS:
3346
3347 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3348 {
3349 if (item.Type == 10)
3350 {
3351 partItemID = item.ItemID;
3352
3353 object[] resobj = new object[]
3354 {
3355 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3356 };
3357
3358 m_ScriptEngine.PostScriptEvent(partItemID,
3359 new EventParams("link_message",
3360 resobj, new DetectParams[0]));
3361 }
3362 }
3363
3364 break;
3365
3366 default:
3367
3368 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
3369 {
3370
3371 if ((partInst.LinkNum) == linknum)
3372 {
3373
3374 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
3375 {
3376 if (item.Type == 10)
3377 {
3378 // partLocalID = partInst.LocalId;
3379 partItemID = item.ItemID;
3380 Object[] resObjDef = new object[]
3381 {
3382 new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
3383 };
3384
3385 m_ScriptEngine.PostScriptEvent(partItemID,
3386 new EventParams("link_message",
3387 resObjDef, new DetectParams[0]));
3388 }
3389 }
3390
3391 }
3392 }
3393
3394 break;
3395
3396 }
3397
3398 }
3399
3400 public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local)
3401 {
3402 m_host.AddScriptLPS(1);
3403 SceneObjectPart targ = World.GetSceneObjectPart(target);
3404 if (targ == null)
3405 return;
3406 targ.ApplyImpulse(new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z), local != 0);
3407 }
3408
3409 public void llPassCollisions(int pass)
3410 {
3411 m_host.AddScriptLPS(1);
3412 NotImplemented("llPassCollisions");
3413 }
3414
3415 public LSL_String llGetScriptName()
3416 {
3417
3418 string result = String.Empty;
3419
3420 m_host.AddScriptLPS(1);
3421
3422 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3423 {
3424 if (item.Type == 10 && item.ItemID == m_itemID)
3425 {
3426 result = item.Name!=null?item.Name:String.Empty;
3427 break;
3428 }
3429 }
3430
3431 return result;
3432
3433 }
3434
3435 // this function to understand which shape it is (taken from meshmerizer)
3436 // quite useful can be used by meshmerizer to have a centralized point of understanding the shape
3437 // except that it refers to scripting constants
3438 private int getScriptPrimType(PrimitiveBaseShape primShape)
3439 {
3440 if (primShape.SculptEntry)
3441 return ScriptBaseClass.PRIM_TYPE_SCULPT;
3442 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
3443 {
3444 if (primShape.PathCurve == (byte)Extrusion.Straight)
3445 return ScriptBaseClass.PRIM_TYPE_BOX;
3446 else if (primShape.PathCurve == (byte)Extrusion.Curve1)
3447 return ScriptBaseClass.PRIM_TYPE_TUBE;
3448 }
3449 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
3450 {
3451 if (primShape.PathCurve == (byte)Extrusion.Straight)
3452 return ScriptBaseClass.PRIM_TYPE_CYLINDER;
3453 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
3454 else if (primShape.PathCurve == (byte)Extrusion.Curve1)
3455 return ScriptBaseClass.PRIM_TYPE_TORUS;
3456 }
3457 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
3458 {
3459 if (primShape.PathCurve == (byte)Extrusion.Curve1 || primShape.PathCurve == (byte)Extrusion.Curve2)
3460 return ScriptBaseClass.PRIM_TYPE_SPHERE;
3461 }
3462 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
3463 {
3464 if (primShape.PathCurve == (byte)Extrusion.Straight)
3465 return ScriptBaseClass.PRIM_TYPE_PRISM;
3466 else if (primShape.PathCurve == (byte)Extrusion.Curve1)
3467 return ScriptBaseClass.PRIM_TYPE_RING;
3468 }
3469 return ScriptBaseClass.PRIM_TYPE_BOX;
3470 }
3471
3472 // Helper functions to understand if object has cut, hollow, dimple, and other affecting number of faces
3473 private void hasCutHollowDimpleProfileCut(int primType, PrimitiveBaseShape shape, out bool hasCut, out bool hasHollow,
3474 out bool hasDimple, out bool hasProfileCut)
3475 {
3476 if (primType == ScriptBaseClass.PRIM_TYPE_BOX
3477 ||
3478 primType == ScriptBaseClass.PRIM_TYPE_CYLINDER
3479 ||
3480 primType == ScriptBaseClass.PRIM_TYPE_PRISM)
3481
3482 hasCut = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0);
3483 else
3484 hasCut = (shape.PathBegin > 0) || (shape.PathEnd > 0);
3485
3486 hasHollow = shape.ProfileHollow > 0;
3487 hasDimple = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); // taken from llSetPrimitiveParms
3488 hasProfileCut = hasDimple; // is it the same thing?
3489
3490 }
3491
3492 public LSL_Integer llGetNumberOfSides()
3493 {
3494 m_host.AddScriptLPS(1);
3495
3496 return GetNumberOfSides(m_host);
3497 }
3498
3499 private int GetNumberOfSides(SceneObjectPart part)
3500 {
3501 int ret = 0;
3502 bool hasCut;
3503 bool hasHollow;
3504 bool hasDimple;
3505 bool hasProfileCut;
3506
3507 int primType = getScriptPrimType(part.Shape);
3508 hasCutHollowDimpleProfileCut(primType, part.Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut);
3509
3510 switch (primType)
3511 {
3512 case ScriptBaseClass.PRIM_TYPE_BOX:
3513 ret = 6;
3514 if (hasCut) ret += 2;
3515 if (hasHollow) ret += 1;
3516 break;
3517 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
3518 ret = 3;
3519 if (hasCut) ret += 2;
3520 if (hasHollow) ret += 1;
3521 break;
3522 case ScriptBaseClass.PRIM_TYPE_PRISM:
3523 ret = 5;
3524 if (hasCut) ret += 2;
3525 if (hasHollow) ret += 1;
3526 break;
3527 case ScriptBaseClass.PRIM_TYPE_SPHERE:
3528 ret = 1;
3529 if (hasCut) ret += 2;
3530 if (hasDimple) ret += 2;
3531 if (hasHollow) ret += 3; // Emulate lsl on secondlife (according to documentation it should have added only +1)
3532 break;
3533 case ScriptBaseClass.PRIM_TYPE_TORUS:
3534 ret = 1;
3535 if (hasCut) ret += 2;
3536 if (hasProfileCut) ret += 2;
3537 if (hasHollow) ret += 1;
3538 break;
3539 case ScriptBaseClass.PRIM_TYPE_TUBE:
3540 ret = 4;
3541 if (hasCut) ret += 2;
3542 if (hasProfileCut) ret += 2;
3543 if (hasHollow) ret += 1;
3544 break;
3545 case ScriptBaseClass.PRIM_TYPE_RING:
3546 ret = 3;
3547 if (hasCut) ret += 2;
3548 if (hasProfileCut) ret += 2;
3549 if (hasHollow) ret += 1;
3550 break;
3551 case ScriptBaseClass.PRIM_TYPE_SCULPT:
3552 ret = 1;
3553 break;
3554 }
3555 return ret;
3556 }
3557
3558
3559 /* The new / changed functions were tested with the following LSL script:
3560
3561 default
3562 {
3563 state_entry()
3564 {
3565 rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD);
3566
3567 llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot));
3568 llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG));
3569
3570 // convert back and forth between quaternion <-> vector and angle
3571
3572 rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot));
3573
3574 llOwnerSay("Old rotation was: "+(string) rot);
3575 llOwnerSay("re-converted rotation is: "+(string) newrot);
3576
3577 llSetRot(rot); // to check the parameters in the prim
3578 }
3579 }
3580 */
3581
3582
3583
3584 // Xantor 29/apr/2008
3585 // Returns rotation described by rotating angle radians about axis.
3586 // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
3587 public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle)
3588 {
3589 m_host.AddScriptLPS(1);
3590
3591 double x, y, z, s, t;
3592
3593 s = Math.Cos(angle / 2);
3594 t = Math.Sin(angle / 2); // temp value to avoid 2 more sin() calcs
3595 x = axis.x * t;
3596 y = axis.y * t;
3597 z = axis.z * t;
3598
3599 return new LSL_Rotation(x,y,z,s);
3600 }
3601
3602
3603 // Xantor 29/apr/2008
3604 // converts a Quaternion to X,Y,Z axis rotations
3605 public LSL_Vector llRot2Axis(LSL_Rotation rot)
3606 {
3607 m_host.AddScriptLPS(1);
3608 double x,y,z;
3609
3610 if (rot.s > 1) // normalization needed
3611 {
3612 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
3613 rot.z * rot.z + rot.s * rot.s);
3614
3615 rot.x /= length;
3616 rot.y /= length;
3617 rot.z /= length;
3618 rot.s /= length;
3619
3620 }
3621
3622 // double angle = 2 * Math.Acos(rot.s);
3623 double s = Math.Sqrt(1 - rot.s * rot.s);
3624 if (s < 0.001)
3625 {
3626 x = 1;
3627 y = z = 0;
3628 }
3629 else
3630 {
3631 x = rot.x / s; // normalise axis
3632 y = rot.y / s;
3633 z = rot.z / s;
3634 }
3635
3636 return new LSL_Vector(x,y,z);
3637 }
3638
3639
3640 // Returns the angle of a quaternion (see llRot2Axis for the axis)
3641 public LSL_Float llRot2Angle(LSL_Rotation rot)
3642 {
3643 m_host.AddScriptLPS(1);
3644
3645 if (rot.s > 1) // normalization needed
3646 {
3647 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
3648 rot.z * rot.z + rot.s * rot.s);
3649
3650 rot.x /= length;
3651 rot.y /= length;
3652 rot.z /= length;
3653 rot.s /= length;
3654 }
3655
3656 double angle = 2 * Math.Acos(rot.s);
3657
3658 return angle;
3659 }
3660
3661 public LSL_Float llAcos(double val)
3662 {
3663 m_host.AddScriptLPS(1);
3664 return (double)Math.Acos(val);
3665 }
3666
3667 public LSL_Float llAsin(double val)
3668 {
3669 m_host.AddScriptLPS(1);
3670 return (double)Math.Asin(val);
3671 }
3672
3673 // Xantor 30/apr/2008
3674 public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b)
3675 {
3676 m_host.AddScriptLPS(1);
3677
3678 return (double) Math.Acos(a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s) * 2;
3679 }
3680
3681 public LSL_String llGetInventoryKey(string name)
3682 {
3683 m_host.AddScriptLPS(1);
3684 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3685 {
3686 if (inv.Value.Name == name)
3687 {
3688 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
3689 {
3690 return inv.Value.AssetID.ToString();
3691 }
3692 else
3693 {
3694 return UUID.Zero.ToString();
3695 }
3696 }
3697 }
3698 return UUID.Zero.ToString();
3699 }
3700
3701 public void llAllowInventoryDrop(int add)
3702 {
3703 m_host.AddScriptLPS(1);
3704
3705 if (add != 0)
3706 m_host.ParentGroup.RootPart.AllowedDrop = true;
3707 else
3708 m_host.ParentGroup.RootPart.AllowedDrop = false;
3709 }
3710
3711 public LSL_Vector llGetSunDirection()
3712 {
3713 m_host.AddScriptLPS(1);
3714
3715 LSL_Vector SunDoubleVector3;
3716 Vector3 SunFloatVector3;
3717
3718 // sunPosition estate setting is set in OpenSim.Region.Environment.Modules.SunModule
3719 // have to convert from Vector3 (float) to LSL_Vector (double)
3720 SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector;
3721 SunDoubleVector3.x = (double)SunFloatVector3.X;
3722 SunDoubleVector3.y = (double)SunFloatVector3.Y;
3723 SunDoubleVector3.z = (double)SunFloatVector3.Z;
3724
3725 return SunDoubleVector3;
3726 }
3727
3728 public LSL_Vector llGetTextureOffset(int face)
3729 {
3730 m_host.AddScriptLPS(1);
3731 return GetTextureOffset(m_host, face);
3732 }
3733
3734 private LSL_Vector GetTextureOffset(SceneObjectPart part, int face)
3735 {
3736 Primitive.TextureEntry tex = part.Shape.Textures;
3737 LSL_Vector offset = new LSL_Vector();
3738 if (face == ScriptBaseClass.ALL_SIDES)
3739 {
3740 face = 0;
3741 }
3742 if (face >= 0 && face < GetNumberOfSides(part))
3743 {
3744 offset.x = tex.GetFace((uint)face).OffsetU;
3745 offset.y = tex.GetFace((uint)face).OffsetV;
3746 offset.z = 0.0;
3747 return offset;
3748 }
3749 else
3750 {
3751 return offset;
3752 }
3753 }
3754
3755 public LSL_Vector llGetTextureScale(int side)
3756 {
3757 m_host.AddScriptLPS(1);
3758 Primitive.TextureEntry tex = m_host.Shape.Textures;
3759 LSL_Vector scale;
3760 if (side == -1)
3761 {
3762 side = 0;
3763 }
3764 scale.x = tex.GetFace((uint)side).RepeatU;
3765 scale.y = tex.GetFace((uint)side).RepeatV;
3766 scale.z = 0.0;
3767 return scale;
3768 }
3769
3770 public LSL_Float llGetTextureRot(int face)
3771 {
3772 m_host.AddScriptLPS(1);
3773 return GetTextureRot(m_host, face);
3774 }
3775
3776 private LSL_Float GetTextureRot(SceneObjectPart part, int face)
3777 {
3778 Primitive.TextureEntry tex = part.Shape.Textures;
3779 if (face == -1)
3780 {
3781 face = 0;
3782 }
3783 if (face >= 0 && face < GetNumberOfSides(part))
3784 {
3785 return tex.GetFace((uint)face).Rotation;
3786 }
3787 else
3788 {
3789 return 0.0;
3790 }
3791 }
3792
3793 public LSL_Integer llSubStringIndex(string source, string pattern)
3794 {
3795 m_host.AddScriptLPS(1);
3796 return source.IndexOf(pattern);
3797 }
3798
3799 public LSL_String llGetOwnerKey(string id)
3800 {
3801 m_host.AddScriptLPS(1);
3802 UUID key = new UUID();
3803 if (UUID.TryParse(id, out key))
3804 {
3805 try
3806 {
3807 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
3808 if (obj == null)
3809 return id; // the key is for an agent so just return the key
3810 else
3811 return obj.OwnerID.ToString();
3812 }
3813 catch (KeyNotFoundException)
3814 {
3815 return id; // The Object/Agent not in the region so just return the key
3816 }
3817 }
3818 else
3819 {
3820 return UUID.Zero.ToString();
3821 }
3822 }
3823
3824 public LSL_Vector llGetCenterOfMass()
3825 {
3826 m_host.AddScriptLPS(1);
3827 NotImplemented("llGetCenterOfMass");
3828 return new LSL_Vector();
3829 }
3830
3831 public LSL_List llListSort(LSL_List src, int stride, int ascending)
3832 {
3833 m_host.AddScriptLPS(1);
3834
3835 if (stride <= 0)
3836 {
3837 stride = 1;
3838 }
3839 return src.Sort(stride, ascending);
3840 }
3841
3842 public LSL_Integer llGetListLength(LSL_List src)
3843 {
3844 m_host.AddScriptLPS(1);
3845
3846 if (src == null)
3847 {
3848 return 0;
3849 }
3850 else
3851 {
3852 return src.Length;
3853 }
3854 }
3855
3856 public LSL_Integer llList2Integer(LSL_List src, int index)
3857 {
3858 m_host.AddScriptLPS(1);
3859 if (index < 0)
3860 {
3861 index = src.Length + index;
3862 }
3863 if (index >= src.Length)
3864 {
3865 return 0;
3866 }
3867 try
3868 {
3869 if (src.Data[index] is LSL_Integer)
3870 return Convert.ToInt32(((LSL_Integer) src.Data[index]).value);
3871 else if (src.Data[index] is LSL_Float)
3872 return Convert.ToInt32(((LSL_Float) src.Data[index]).value);
3873 else if (src.Data[index] is LSL_String)
3874 return Convert.ToInt32(((LSL_String) src.Data[index]).m_string);
3875 return Convert.ToInt32(src.Data[index]);
3876 }
3877 catch (FormatException)
3878 {
3879 return 0;
3880 }
3881 }
3882
3883 public LSL_Float llList2Float(LSL_List src, int index)
3884 {
3885 m_host.AddScriptLPS(1);
3886 if (index < 0)
3887 {
3888 index = src.Length + index;
3889 }
3890 if (index >= src.Length)
3891 {
3892 return 0.0;
3893 }
3894 try
3895 {
3896 if (src.Data[index] is LSL_Integer)
3897 return Convert.ToDouble(((LSL_Integer) src.Data[index]).value);
3898 else if (src.Data[index] is LSL_Float)
3899 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
3900 else if (src.Data[index] is LSL_String)
3901 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string);
3902 return Convert.ToDouble(src.Data[index]);
3903 }
3904 catch (FormatException)
3905 {
3906 return 0.0;
3907 }
3908 }
3909
3910 public LSL_String llList2String(LSL_List src, int index)
3911 {
3912 m_host.AddScriptLPS(1);
3913 if (index < 0)
3914 {
3915 index = src.Length + index;
3916 }
3917 if (index >= src.Length)
3918 {
3919 return String.Empty;
3920 }
3921 return src.Data[index].ToString();
3922 }
3923
3924 public LSL_String llList2Key(LSL_List src, int index)
3925 {
3926 m_host.AddScriptLPS(1);
3927 if (index < 0)
3928 {
3929 index = src.Length + index;
3930 }
3931 if (index >= src.Length)
3932 {
3933 return "";
3934 }
3935 return src.Data[index].ToString();
3936 }
3937
3938 public LSL_Vector llList2Vector(LSL_List src, int index)
3939 {
3940 m_host.AddScriptLPS(1);
3941 if (index < 0)
3942 {
3943 index = src.Length + index;
3944 }
3945 if (index >= src.Length)
3946 {
3947 return new LSL_Vector(0, 0, 0);
3948 }
3949 if (src.Data[index].GetType() == typeof(LSL_Vector))
3950 {
3951 return (LSL_Vector)src.Data[index];
3952 }
3953 else
3954 {
3955 return new LSL_Vector(src.Data[index].ToString());
3956 }
3957 }
3958
3959 public LSL_Rotation llList2Rot(LSL_List src, int index)
3960 {
3961 m_host.AddScriptLPS(1);
3962 if (index < 0)
3963 {
3964 index = src.Length + index;
3965 }
3966 if (index >= src.Length)
3967 {
3968 return new LSL_Rotation(0, 0, 0, 1);
3969 }
3970 if (src.Data[index].GetType() == typeof(LSL_Rotation))
3971 {
3972 return (LSL_Rotation)src.Data[index];
3973 }
3974 else
3975 {
3976 return new LSL_Rotation(src.Data[index].ToString());
3977 }
3978 }
3979
3980 public LSL_List llList2List(LSL_List src, int start, int end)
3981 {
3982 m_host.AddScriptLPS(1);
3983 return src.GetSublist(start, end);
3984 }
3985
3986 public LSL_List llDeleteSubList(LSL_List src, int start, int end)
3987 {
3988 return src.DeleteSublist(end, start);
3989 }
3990
3991 public LSL_Integer llGetListEntryType(LSL_List src, int index)
3992 {
3993 m_host.AddScriptLPS(1);
3994 if (index < 0)
3995 {
3996 index = src.Length + index;
3997 }
3998 if (index >= src.Length)
3999 {
4000 return 0;
4001 }
4002
4003 if (src.Data[index] is LSL_Integer || src.Data[index] is Int32)
4004 return 1;
4005 if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double)
4006 return 2;
4007 if (src.Data[index] is LSL_String || src.Data[index] is String)
4008 {
4009 UUID tuuid;
4010 if (UUID.TryParse(src.Data[index].ToString(), out tuuid))
4011 {
4012 return 4;
4013 }
4014 else
4015 {
4016 return 3;
4017 }
4018 }
4019 if (src.Data[index] is LSL_Vector)
4020 return 5;
4021 if (src.Data[index] is LSL_Rotation)
4022 return 6;
4023 if (src.Data[index] is LSL_List)
4024 return 7;
4025 return 0;
4026
4027 }
4028
4029 /// <summary>
4030 /// Process the supplied list and return the
4031 /// content of the list formatted as a comma
4032 /// separated list. There is a space after
4033 /// each comma.
4034 /// </summary>
4035
4036 public LSL_String llList2CSV(LSL_List src)
4037 {
4038
4039 string ret = String.Empty;
4040 int x = 0;
4041
4042 m_host.AddScriptLPS(1);
4043
4044 if (src.Data.Length > 0)
4045 {
4046 ret = src.Data[x++].ToString();
4047 for (; x < src.Data.Length; x++)
4048 {
4049 ret += ", "+src.Data[x].ToString();
4050 }
4051 }
4052
4053 return ret;
4054 }
4055
4056 /// <summary>
4057 /// The supplied string is scanned for commas
4058 /// and converted into a list. Commas are only
4059 /// effective if they are encountered outside
4060 /// of '<' '>' delimiters. Any whitespace
4061 /// before or after an element is trimmed.
4062 /// </summary>
4063
4064 public LSL_List llCSV2List(string src)
4065 {
4066
4067 LSL_List result = new LSL_List();
4068 int parens = 0;
4069 int start = 0;
4070 int length = 0;
4071
4072 m_host.AddScriptLPS(1);
4073
4074 for (int i = 0; i < src.Length; i++)
4075 {
4076 switch (src[i])
4077 {
4078 case '<':
4079 parens++;
4080 length++;
4081 break;
4082 case '>':
4083 if (parens > 0)
4084 parens--;
4085 length++;
4086 break;
4087 case ',':
4088 if (parens == 0)
4089 {
4090 result.Add(src.Substring(start,length).Trim());
4091 start += length+1;
4092 length = 0;
4093 }
4094 else
4095 {
4096 length++;
4097 }
4098 break;
4099 default:
4100 length++;
4101 break;
4102 }
4103 }
4104
4105 result.Add(src.Substring(start,length).Trim());
4106
4107 return result;
4108 }
4109
4110 /// <summary>
4111 /// Randomizes the list, be arbitrarily reordering
4112 /// sublists of stride elements. As the stride approaches
4113 /// the size of the list, the options become very
4114 /// limited.
4115 /// </summary>
4116 /// <remarks>
4117 /// This could take a while for very large list
4118 /// sizes.
4119 /// </remarks>
4120
4121 public LSL_List llListRandomize(LSL_List src, int stride)
4122 {
4123 LSL_List result;
4124 Random rand = new Random();
4125
4126 int chunkk;
4127 int[] chunks;
4128
4129 m_host.AddScriptLPS(1);
4130
4131 if (stride <= 0)
4132 {
4133 stride = 1;
4134 }
4135
4136 // Stride MUST be a factor of the list length
4137 // If not, then return the src list. This also
4138 // traps those cases where stride > length.
4139
4140 if (src.Length != stride && src.Length%stride == 0)
4141 {
4142 chunkk = src.Length/stride;
4143
4144 chunks = new int[chunkk];
4145
4146 for (int i = 0; i < chunkk; i++)
4147 chunks[i] = i;
4148
4149 // Knuth shuffle the chunkk index
4150 for (int i = chunkk - 1; i >= 1; i--)
4151 {
4152 // Elect an unrandomized chunk to swap
4153 int index = rand.Next(i + 1);
4154 int tmp;
4155
4156 // and swap position with first unrandomized chunk
4157 tmp = chunks[i];
4158 chunks[i] = chunks[index];
4159 chunks[index] = tmp;
4160 }
4161
4162 // Construct the randomized list
4163
4164 result = new LSL_List();
4165
4166 for (int i = 0; i < chunkk; i++)
4167 {
4168 for (int j = 0; j < stride; j++)
4169 {
4170 result.Add(src.Data[chunks[i]*stride+j]);
4171 }
4172 }
4173 }
4174 else {
4175 object[] array = new object[src.Length];
4176 Array.Copy(src.Data, 0, array, 0, src.Length);
4177 result = new LSL_List(array);
4178 }
4179
4180 return result;
4181 }
4182
4183 /// <summary>
4184 /// Elements in the source list starting with 0 and then
4185 /// every i+stride. If the stride is negative then the scan
4186 /// is backwards producing an inverted result.
4187 /// Only those elements that are also in the specified
4188 /// range are included in the result.
4189 /// </summary>
4190
4191 public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride)
4192 {
4193
4194 LSL_List result = new LSL_List();
4195 int[] si = new int[2];
4196 int[] ei = new int[2];
4197 bool twopass = false;
4198
4199 m_host.AddScriptLPS(1);
4200
4201 // First step is always to deal with negative indices
4202
4203 if (start < 0)
4204 start = src.Length+start;
4205 if (end < 0)
4206 end = src.Length+end;
4207
4208 // Out of bounds indices are OK, just trim them
4209 // accordingly
4210
4211 if (start > src.Length)
4212 start = src.Length;
4213
4214 if (end > src.Length)
4215 end = src.Length;
4216
4217 // There may be one or two ranges to be considered
4218
4219 if (start != end)
4220 {
4221
4222 if (start <= end)
4223 {
4224 si[0] = start;
4225 ei[0] = end;
4226 }
4227 else
4228 {
4229 si[1] = start;
4230 ei[1] = src.Length;
4231 si[0] = 0;
4232 ei[0] = end;
4233 twopass = true;
4234 }
4235
4236 // The scan always starts from the beginning of the
4237 // source list, but members are only selected if they
4238 // fall within the specified sub-range. The specified
4239 // range values are inclusive.
4240 // A negative stride reverses the direction of the
4241 // scan producing an inverted list as a result.
4242
4243 if (stride == 0)
4244 stride = 1;
4245
4246 if (stride > 0)
4247 {
4248 for (int i = 0; i < src.Length; i += stride)
4249 {
4250 if (i<=ei[0] && i>=si[0])
4251 result.Add(src.Data[i]);
4252 if (twopass && i>=si[1] && i<=ei[1])
4253 result.Add(src.Data[i]);
4254 }
4255 }
4256 else if (stride < 0)
4257 {
4258 for (int i = src.Length - 1; i >= 0; i += stride)
4259 {
4260 if (i <= ei[0] && i >= si[0])
4261 result.Add(src.Data[i]);
4262 if (twopass && i >= si[1] && i <= ei[1])
4263 result.Add(src.Data[i]);
4264 }
4265 }
4266 }
4267
4268 return result;
4269 }
4270
4271 public LSL_Integer llGetRegionAgentCount()
4272 {
4273 m_host.AddScriptLPS(1);
4274 NotImplemented("llGetRegionAgentCount");
4275 return new LSL_Integer(0);
4276 }
4277
4278 public LSL_Vector llGetRegionCorner()
4279 {
4280 m_host.AddScriptLPS(1);
4281 return new LSL_Vector(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
4282 }
4283
4284 /// <summary>
4285 /// Insert the list identified by <src> into the
4286 /// list designated by <dest> such that the first
4287 /// new element has the index specified by <index>
4288 /// </summary>
4289
4290 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
4291 {
4292
4293 LSL_List pref = null;
4294 LSL_List suff = null;
4295
4296 m_host.AddScriptLPS(1);
4297
4298 if (index < 0)
4299 {
4300 index = index+dest.Length;
4301 if (index < 0)
4302 {
4303 index = 0;
4304 }
4305 }
4306
4307 if (index != 0)
4308 {
4309 pref = dest.GetSublist(0,index-1);
4310 if (index < dest.Length)
4311 {
4312 suff = dest.GetSublist(index,-1);
4313 return pref + src + suff;
4314 }
4315 else
4316 {
4317 return pref + src;
4318 }
4319 }
4320 else
4321 {
4322 if (index < dest.Length)
4323 {
4324 suff = dest.GetSublist(index,-1);
4325 return src + suff;
4326 }
4327 else
4328 {
4329 return src;
4330 }
4331 }
4332
4333 }
4334
4335 /// <summary>
4336 /// Returns the index of the first occurrence of test
4337 /// in src.
4338 /// </summary>
4339
4340 public LSL_Integer llListFindList(LSL_List src, LSL_List test)
4341 {
4342
4343 int index = -1;
4344 int length = src.Length - test.Length + 1;
4345
4346 m_host.AddScriptLPS(1);
4347
4348 // If either list is empty, do not match
4349
4350 if (src.Length != 0 && test.Length != 0)
4351 {
4352 for (int i = 0; i < length; i++)
4353 {
4354 if (src.Data[i].Equals(test.Data[0]))
4355 {
4356 int j;
4357 for (j = 1; j < test.Length; j++)
4358 if (!src.Data[i+j].Equals(test.Data[j]))
4359 break;
4360 if (j == test.Length)
4361 {
4362 index = i;
4363 break;
4364 }
4365 }
4366 }
4367 }
4368
4369 return index;
4370
4371 }
4372
4373 public LSL_String llGetObjectName()
4374 {
4375 m_host.AddScriptLPS(1);
4376 return m_host.Name!=null?m_host.Name:String.Empty;
4377 }
4378
4379 public void llSetObjectName(string name)
4380 {
4381 m_host.AddScriptLPS(1);
4382 m_host.Name = name!=null?name:String.Empty;
4383 }
4384
4385 public LSL_String llGetDate()
4386 {
4387 m_host.AddScriptLPS(1);
4388 DateTime date = DateTime.Now.ToUniversalTime();
4389 string result = date.ToString("yyyy-MM-dd");
4390 return result;
4391 }
4392
4393 public LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir)
4394 {
4395 m_host.AddScriptLPS(1);
4396 NotImplemented("llEdgeOfWorld");
4397 return 0;
4398 }
4399
4400 public LSL_Integer llGetAgentInfo(string id)
4401 {
4402 m_host.AddScriptLPS(1);
4403 NotImplemented("llGetAgentInfo");
4404 return 0;
4405 }
4406
4407 public void llAdjustSoundVolume(double volume)
4408 {
4409 m_host.AddScriptLPS(1);
4410 m_host.AdjustSoundGain(volume);
4411 // ScriptSleep(100);
4412 }
4413
4414 public void llSetSoundQueueing(int queue)
4415 {
4416 m_host.AddScriptLPS(1);
4417 NotImplemented("llSetSoundQueueing");
4418 }
4419
4420 public void llSetSoundRadius(double radius)
4421 {
4422 m_host.AddScriptLPS(1);
4423 m_host.SoundRadius = radius;
4424 }
4425
4426 public LSL_String llKey2Name(string id)
4427 {
4428 m_host.AddScriptLPS(1);
4429 UUID key = new UUID();
4430 if (UUID.TryParse(id,out key))
4431 {
4432 ScenePresence presence = World.GetScenePresence(key);
4433
4434 if (presence != null)
4435 {
4436 return presence.ControllingClient.Name;
4437 //return presence.Name;
4438 }
4439
4440 if (World.GetSceneObjectPart(key) != null)
4441 {
4442 return World.GetSceneObjectPart(key).Name;
4443 }
4444 }
4445 return String.Empty;
4446 }
4447
4448
4449
4450 public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate)
4451 {
4452 m_host.AddScriptLPS(1);
4453 Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation();
4454 pTexAnim.Flags = (Primitive.TextureAnimMode)mode;
4455
4456 //ALL_SIDES
4457 if (face == ScriptBaseClass.ALL_SIDES)
4458 face = 255;
4459
4460 pTexAnim.Face = (uint)face;
4461 pTexAnim.Length = (float)length;
4462 pTexAnim.Rate = (float)rate;
4463 pTexAnim.SizeX = (uint)sizex;
4464 pTexAnim.SizeY = (uint)sizey;
4465 pTexAnim.Start = (float)start;
4466
4467 m_host.AddTextureAnimation(pTexAnim);
4468 m_host.SendFullUpdateToAllClients();
4469 m_host.ParentGroup.HasGroupChanged = true;
4470 }
4471
4472 public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east,
4473 LSL_Vector bottom_south_west)
4474 {
4475 m_host.AddScriptLPS(1);
4476 NotImplemented("llTriggerSoundLimited");
4477 }
4478
4479 public void llEjectFromLand(string pest)
4480 {
4481 m_host.AddScriptLPS(1);
4482 UUID agentId = new UUID();
4483 if (UUID.TryParse(pest, out agentId))
4484 {
4485 ScenePresence presence = World.GetScenePresence(agentId);
4486 if (presence != null)
4487 {
4488 // agent must be over the owners land
4489 if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y))
4490 World.TeleportClientHome(agentId, presence.ControllingClient);
4491 }
4492 }
4493 // ScriptSleep(5000);
4494 }
4495
4496 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List spacers)
4497 {
4498 m_host.AddScriptLPS(1);
4499 LSL_List ret = new LSL_List();
4500 object[] delimiters = new object[separators.Length + spacers.Length];
4501 separators.Data.CopyTo(delimiters, 0);
4502 spacers.Data.CopyTo(delimiters, separators.Length);
4503 bool dfound = false;
4504 do
4505 {
4506 dfound = false;
4507 int cindex = -1;
4508 string cdeli = "";
4509 for (int i = 0; i < delimiters.Length; i++)
4510 {
4511 int index = str.IndexOf(delimiters[i].ToString());
4512 bool found = index != -1;
4513 if (found && String.Empty != delimiters[i].ToString())
4514 {
4515 if ((cindex > index) || (cindex == -1))
4516 {
4517 cindex = index;
4518 cdeli = delimiters[i].ToString();
4519 }
4520 dfound = dfound || found;
4521 }
4522 }
4523 if (cindex != -1)
4524 {
4525 if (cindex > 0)
4526 {
4527 ret.Add(str.Substring(0, cindex));
4528 // Cannot use spacers.Contains() because spacers may be either type String or LSLString
4529 for (int j = 0; j < spacers.Length; j++)
4530 {
4531 if (spacers.Data[j].ToString() == cdeli)
4532 {
4533 ret.Add(cdeli);
4534 break;
4535 }
4536 }
4537 }
4538 if (cindex == 0 && spacers.Contains(cdeli))
4539 {
4540 ret.Add(cdeli);
4541 }
4542 str = str.Substring(cindex + cdeli.Length);
4543 }
4544 } while (dfound);
4545 if (str != "")
4546 {
4547 ret.Add(str);
4548 }
4549 return ret;
4550 }
4551
4552 public LSL_Integer llOverMyLand(string id)
4553 {
4554 m_host.AddScriptLPS(1);
4555 UUID key = new UUID();
4556 if (UUID.TryParse(id,out key))
4557 {
4558 ScenePresence presence = World.GetScenePresence(key);
4559 if (presence != null) // object is an avatar
4560 {
4561 if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y))
4562 return 1;
4563 }
4564 else // object is not an avatar
4565 {
4566 SceneObjectPart obj = World.GetSceneObjectPart(key);
4567 if (obj != null)
4568 if (m_host.OwnerID == World.GetLandOwner(obj.AbsolutePosition.X, obj.AbsolutePosition.Y))
4569 return 1;
4570 }
4571 }
4572 return 0;
4573 }
4574
4575 public LSL_String llGetLandOwnerAt(LSL_Vector pos)
4576 {
4577 m_host.AddScriptLPS(1);
4578 return World.GetLandOwner((float)pos.x, (float)pos.y).ToString();
4579 }
4580
4581 public LSL_Vector llGetAgentSize(string id)
4582 {
4583 m_host.AddScriptLPS(1);
4584 ScenePresence avatar = World.GetScenePresence(id);
4585 LSL_Vector agentSize;
4586 if (avatar == null)
4587 {
4588 agentSize = ScriptBaseClass.ZERO_VECTOR;
4589 }
4590 else
4591 {
4592 PhysicsVector size = avatar.PhysicsActor.Size;
4593 agentSize = new LSL_Vector(size.X, size.Y, size.Z);
4594 }
4595 return agentSize;
4596 }
4597
4598 public LSL_Integer llSameGroup(string agent)
4599 {
4600 m_host.AddScriptLPS(1);
4601 UUID agentId = new UUID();
4602 if (!UUID.TryParse(agent, out agentId))
4603 return new LSL_Integer(0);
4604 ScenePresence presence = World.GetScenePresence(agentId);
4605 if (presence == null)
4606 return new LSL_Integer(0);
4607 IClientAPI client = presence.ControllingClient;
4608 if (m_host.GroupID == client.ActiveGroupId)
4609 return new LSL_Integer(1);
4610 else
4611 return new LSL_Integer(0);
4612 }
4613
4614 public void llUnSit(string id)
4615 {
4616 m_host.AddScriptLPS(1);
4617
4618 UUID key = new UUID();
4619 if (UUID.TryParse(id, out key))
4620 {
4621 ScenePresence av = World.GetScenePresence(key);
4622
4623 if (av != null)
4624 {
4625 if (llAvatarOnSitTarget() == id)
4626 {
4627 // if the avatar is sitting on this object, then
4628 // we can unsit them. We don't want random scripts unsitting random people
4629 // Lets avoid the popcorn avatar scenario.
4630 av.StandUp();
4631 }
4632 else
4633 {
4634 // If the object owner also owns the parcel
4635 // or
4636 // if the land is group owned and the object is group owned by the same group
4637 // or
4638 // if the object is owned by a person with estate access.
4639
4640 ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y);
4641 if (parcel != null)
4642 {
4643 if (m_host.ObjectOwner == parcel.landData.OwnerID ||
4644 (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.landData.GroupID
4645 && parcel.landData.IsGroupOwned) || World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID))
4646 {
4647 av.StandUp();
4648 }
4649 }
4650 }
4651 }
4652
4653 }
4654
4655 }
4656
4657 public LSL_Vector llGroundSlope(LSL_Vector offset)
4658 {
4659 m_host.AddScriptLPS(1);
4660
4661 Vector3 pos = m_host.AbsolutePosition + new Vector3((float)offset.x,
4662 (float)offset.y,
4663 (float)offset.z);
4664
4665 Vector3 p0 = new Vector3(pos.X, pos.Y,
4666 (float)llGround(
4667 new LSL_Vector(pos.X, pos.Y, pos.Z)
4668 ));
4669 Vector3 p1 = new Vector3(pos.X + 1, pos.Y,
4670 (float)llGround(
4671 new LSL_Vector(pos.X + 1, pos.Y, pos.Z)
4672 ));
4673 Vector3 p2 = new Vector3(pos.X, pos.Y + 1,
4674 (float)llGround(
4675 new LSL_Vector(pos.X, pos.Y + 1, pos.Z)
4676 ));
4677
4678 Vector3 v0 = new Vector3(
4679 p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
4680 Vector3 v1 = new Vector3(
4681 p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z);
4682
4683 v0.Normalize();
4684 v1.Normalize();
4685
4686 Vector3 tv = new Vector3();
4687 tv.X = (v0.Y * v1.Z) - (v0.Z * v1.Y);
4688 tv.Y = (v0.Z * v1.X) - (v0.X * v1.Z);
4689 tv.Z = (v0.X * v1.Y) - (v0.Y * v1.X);
4690
4691 return new LSL_Vector(tv.X, tv.Y, tv.Z);
4692 }
4693
4694 public LSL_Vector llGroundNormal(LSL_Vector offset)
4695 {
4696 m_host.AddScriptLPS(1);
4697 LSL_Vector x = llGroundSlope(offset);
4698 return new LSL_Vector(x.x, x.y, 1.0);
4699 }
4700
4701 public LSL_Vector llGroundContour(LSL_Vector offset)
4702 {
4703 m_host.AddScriptLPS(1);
4704 LSL_Vector x = llGroundSlope(offset);
4705 return new LSL_Vector(-x.y, x.x, 0.0);
4706 }
4707
4708 public LSL_Integer llGetAttached()
4709 {
4710 m_host.AddScriptLPS(1);
4711 NotImplemented("llGetAttached");
4712 return 0;
4713 }
4714
4715 public LSL_Integer llGetFreeMemory()
4716 {
4717 m_host.AddScriptLPS(1);
4718 // Make scripts designed for LSO happy
4719 return 16384;
4720 }
4721
4722 public LSL_String llGetRegionName()
4723 {
4724 m_host.AddScriptLPS(1);
4725 return World.RegionInfo.RegionName;
4726 }
4727
4728 public LSL_Float llGetRegionTimeDilation()
4729 {
4730 m_host.AddScriptLPS(1);
4731 return (double)World.TimeDilation;
4732 }
4733
4734 public LSL_Float llGetRegionFPS()
4735 {
4736 m_host.AddScriptLPS(1);
4737 //TODO: return actual FPS
4738 return 10.0f;
4739 }
4740
4741 /* particle system rules should be coming into this routine as doubles, that is
4742 rule[0] should be an integer from this list and rule[1] should be the arg
4743 for the same integer. wiki.secondlife.com has most of this mapping, but some
4744 came from http://www.caligari-designs.com/p4u2
4745
4746 We iterate through the list for 'Count' elements, incrementing by two for each
4747 iteration and set the members of Primitive.ParticleSystem, one at a time.
4748 */
4749
4750 public enum PrimitiveRule : int
4751 {
4752 PSYS_PART_FLAGS = 0,
4753 PSYS_PART_START_COLOR = 1,
4754 PSYS_PART_START_ALPHA = 2,
4755 PSYS_PART_END_COLOR = 3,
4756 PSYS_PART_END_ALPHA = 4,
4757 PSYS_PART_START_SCALE = 5,
4758 PSYS_PART_END_SCALE = 6,
4759 PSYS_PART_MAX_AGE = 7,
4760 PSYS_SRC_ACCEL = 8,
4761 PSYS_SRC_PATTERN = 9,
4762 PSYS_SRC_TEXTURE = 12,
4763 PSYS_SRC_BURST_RATE = 13,
4764 PSYS_SRC_BURST_PART_COUNT = 15,
4765 PSYS_SRC_BURST_RADIUS = 16,
4766 PSYS_SRC_BURST_SPEED_MIN = 17,
4767 PSYS_SRC_BURST_SPEED_MAX = 18,
4768 PSYS_SRC_MAX_AGE = 19,
4769 PSYS_SRC_TARGET_KEY = 20,
4770 PSYS_SRC_OMEGA = 21,
4771 PSYS_SRC_ANGLE_BEGIN = 22,
4772 PSYS_SRC_ANGLE_END = 23
4773 }
4774
4775 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
4776 {
4777 Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None;
4778
4779 return returnval;
4780 }
4781
4782 private Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues()
4783 {
4784 Primitive.ParticleSystem ps = new Primitive.ParticleSystem();
4785
4786 // TODO find out about the other defaults and add them here
4787 ps.PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
4788 ps.PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
4789 ps.PartStartScaleX = 1.0f;
4790 ps.PartStartScaleY = 1.0f;
4791 ps.PartEndScaleX = 1.0f;
4792 ps.PartEndScaleY = 1.0f;
4793 ps.BurstSpeedMin = 1.0f;
4794 ps.BurstSpeedMax = 1.0f;
4795 ps.BurstRate = 0.1f;
4796 ps.PartMaxAge = 10.0f;
4797 return ps;
4798 }
4799
4800 public void llParticleSystem(LSL_List rules)
4801 {
4802 m_host.AddScriptLPS(1);
4803 if (rules.Length == 0)
4804 {
4805 m_host.RemoveParticleSystem();
4806 m_host.ParentGroup.HasGroupChanged = true;
4807 }
4808 else
4809 {
4810 Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues();
4811 LSL_Vector tempv = new LSL_Vector();
4812
4813 float tempf = 0;
4814
4815 for (int i = 0; i < rules.Length; i += 2)
4816 {
4817 switch ((int)rules.Data[i])
4818 {
4819 case (int)ScriptBaseClass.PSYS_PART_FLAGS:
4820 prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1);
4821 break;
4822
4823 case (int)ScriptBaseClass.PSYS_PART_START_COLOR:
4824 tempv = rules.GetVector3Item(i + 1);
4825 prules.PartStartColor.R = (float)tempv.x;
4826 prules.PartStartColor.G = (float)tempv.y;
4827 prules.PartStartColor.B = (float)tempv.z;
4828 break;
4829
4830 case (int)ScriptBaseClass.PSYS_PART_START_ALPHA:
4831 tempf = (float)rules.GetLSLFloatItem(i + 1);
4832 prules.PartStartColor.A = tempf;
4833 break;
4834
4835 case (int)ScriptBaseClass.PSYS_PART_END_COLOR:
4836 tempv = rules.GetVector3Item(i + 1);
4837 prules.PartEndColor.R = (float)tempv.x;
4838 prules.PartEndColor.G = (float)tempv.y;
4839 prules.PartEndColor.B = (float)tempv.z;
4840 break;
4841
4842 case (int)ScriptBaseClass.PSYS_PART_END_ALPHA:
4843 tempf = (float)rules.GetLSLFloatItem(i + 1);
4844 prules.PartEndColor.A = tempf;
4845 break;
4846
4847 case (int)ScriptBaseClass.PSYS_PART_START_SCALE:
4848 tempv = rules.GetVector3Item(i + 1);
4849 prules.PartStartScaleX = (float)tempv.x;
4850 prules.PartStartScaleY = (float)tempv.y;
4851 break;
4852
4853 case (int)ScriptBaseClass.PSYS_PART_END_SCALE:
4854 tempv = rules.GetVector3Item(i + 1);
4855 prules.PartEndScaleX = (float)tempv.x;
4856 prules.PartEndScaleY = (float)tempv.y;
4857 break;
4858
4859 case (int)ScriptBaseClass.PSYS_PART_MAX_AGE:
4860 tempf = (float)rules.GetLSLFloatItem(i + 1);
4861 prules.PartMaxAge = tempf;
4862 break;
4863
4864 case (int)ScriptBaseClass.PSYS_SRC_ACCEL:
4865 tempv = rules.GetVector3Item(i + 1);
4866 prules.PartAcceleration.X = (float)tempv.x;
4867 prules.PartAcceleration.Y = (float)tempv.y;
4868 prules.PartAcceleration.Z = (float)tempv.z;
4869 break;
4870
4871 case (int)ScriptBaseClass.PSYS_SRC_PATTERN:
4872 int tmpi = (int)rules.GetLSLIntegerItem(i + 1);
4873 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
4874 break;
4875
4876 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE:
4877 prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1));
4878 break;
4879
4880 case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE:
4881 tempf = (float)rules.GetLSLFloatItem(i + 1);
4882 prules.BurstRate = (float)tempf;
4883 break;
4884
4885 case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT:
4886 prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1);
4887 break;
4888
4889 case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS:
4890 tempf = (float)rules.GetLSLFloatItem(i + 1);
4891 prules.BurstRadius = (float)tempf;
4892 break;
4893
4894 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN:
4895 tempf = (float)rules.GetLSLFloatItem(i + 1);
4896 prules.BurstSpeedMin = (float)tempf;
4897 break;
4898
4899 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX:
4900 tempf = (float)rules.GetLSLFloatItem(i + 1);
4901 prules.BurstSpeedMax = (float)tempf;
4902 break;
4903
4904 case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE:
4905 tempf = (float)rules.GetLSLFloatItem(i + 1);
4906 prules.MaxAge = (float)tempf;
4907 break;
4908
4909 case (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY:
4910 UUID key = UUID.Zero;
4911 if (UUID.TryParse(rules.Data[i + 1].ToString(), out key))
4912 {
4913 prules.Target = key;
4914 }
4915 else
4916 {
4917 prules.Target = m_host.UUID;
4918 }
4919 break;
4920
4921 case (int)ScriptBaseClass.PSYS_SRC_OMEGA:
4922 // AL: This is an assumption, since it is the only thing that would match.
4923 tempv = rules.GetVector3Item(i + 1);
4924 prules.AngularVelocity.X = (float)tempv.x;
4925 prules.AngularVelocity.Y = (float)tempv.y;
4926 prules.AngularVelocity.Z = (float)tempv.z;
4927 break;
4928
4929 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN:
4930 tempf = (float)rules.GetLSLFloatItem(i + 1);
4931 prules.InnerAngle = (float)tempf;
4932 break;
4933
4934 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END:
4935 tempf = (float)rules.GetLSLFloatItem(i + 1);
4936 prules.OuterAngle = (float)tempf;
4937 break;
4938 }
4939
4940 }
4941 prules.CRC = 1;
4942
4943 m_host.AddNewParticleSystem(prules);
4944 m_host.ParentGroup.HasGroupChanged = true;
4945 }
4946 m_host.SendFullUpdateToAllClients();
4947 }
4948
4949 public void llGroundRepel(double height, int water, double tau)
4950 {
4951 m_host.AddScriptLPS(1);
4952 NotImplemented("llGroundRepel");
4953 }
4954
4955 private UUID GetTaskInventoryItem(string name)
4956 {
4957 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4958 {
4959 if (inv.Value.Name == name)
4960 return inv.Key;
4961 }
4962 return UUID.Zero;
4963 }
4964
4965 public void llGiveInventoryList(string destination, string category, LSL_List inventory)
4966 {
4967 m_host.AddScriptLPS(1);
4968
4969 UUID destID;
4970 if (!UUID.TryParse(destination, out destID))
4971 return;
4972
4973 List<UUID> itemList = new List<UUID>();
4974
4975 foreach (Object item in inventory.Data)
4976 {
4977 UUID itemID;
4978 if (UUID.TryParse(item.ToString(), out itemID))
4979 {
4980 itemList.Add(itemID);
4981 }
4982 else
4983 {
4984 itemID = GetTaskInventoryItem(item.ToString());
4985 if (itemID != UUID.Zero)
4986 itemList.Add(itemID);
4987 }
4988 }
4989
4990 if (itemList.Count == 0)
4991 return;
4992
4993 m_ScriptEngine.World.MoveTaskInventoryItems(destID, category, m_host, itemList);
4994 }
4995
4996 public void llSetVehicleType(int type)
4997 {
4998 m_host.AddScriptLPS(1);
4999 NotImplemented("llSetVehicleType");
5000 }
5001
5002 public void llSetVehicledoubleParam(int param, double value)
5003 {
5004 m_host.AddScriptLPS(1);
5005 NotImplemented("llSetVehicledoubleParam");
5006 }
5007
5008 public void llSetVehicleFloatParam(int param, float value)
5009 {
5010 m_host.AddScriptLPS(1);
5011 NotImplemented("llSetVehicleFloatParam");
5012 }
5013
5014 public void llSetVehicleVectorParam(int param, LSL_Vector vec)
5015 {
5016 m_host.AddScriptLPS(1);
5017 NotImplemented("llSetVehicleVectorParam");
5018 }
5019
5020 public void llSetVehicleRotationParam(int param, LSL_Rotation rot)
5021 {
5022 m_host.AddScriptLPS(1);
5023 NotImplemented("llSetVehicleRotationParam");
5024 }
5025
5026 public void llSetVehicleFlags(int flags)
5027 {
5028 m_host.AddScriptLPS(1);
5029 NotImplemented("llSetVehicleFlags");
5030 }
5031
5032 public void llRemoveVehicleFlags(int flags)
5033 {
5034 m_host.AddScriptLPS(1);
5035 NotImplemented("llRemoveVehicleFlags");
5036 }
5037
5038 public void llSitTarget(LSL_Vector offset, LSL_Rotation rot)
5039 {
5040 m_host.AddScriptLPS(1);
5041 // LSL quaternions can normalize to 0, normal Quaternions can't.
5042 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
5043 rot.z = 1; // ZERO_ROTATION = 0,0,0,1
5044
5045 m_host.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z);
5046 m_host.SitTargetOrientation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
5047 }
5048
5049 public LSL_String llAvatarOnSitTarget()
5050 {
5051 m_host.AddScriptLPS(1);
5052 return m_host.GetAvatarOnSitTarget().ToString();
5053 }
5054
5055 public void llAddToLandPassList(string avatar, double hours)
5056 {
5057 m_host.AddScriptLPS(1);
5058 UUID key;
5059 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
5060 if (land.OwnerID == m_host.OwnerID)
5061 {
5062 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
5063 if (UUID.TryParse(avatar, out key))
5064 {
5065 entry.AgentID = key;
5066 entry.Flags = ParcelManager.AccessList.Access;
5067 entry.Time = DateTime.Now.AddHours(hours);
5068 land.ParcelAccessList.Add(entry);
5069 }
5070 }
5071 // ScriptSleep(100);
5072 }
5073
5074 public void llSetTouchText(string text)
5075 {
5076 m_host.AddScriptLPS(1);
5077 m_host.TouchName = text;
5078 }
5079
5080 public void llSetSitText(string text)
5081 {
5082 m_host.AddScriptLPS(1);
5083 m_host.SitName = text;
5084 }
5085
5086 public void llSetCameraEyeOffset(LSL_Vector offset)
5087 {
5088 m_host.AddScriptLPS(1);
5089 m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z));
5090 }
5091
5092 public void llSetCameraAtOffset(LSL_Vector offset)
5093 {
5094 m_host.AddScriptLPS(1);
5095 m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z));
5096 }
5097
5098 public LSL_String llDumpList2String(LSL_List src, string seperator)
5099 {
5100 m_host.AddScriptLPS(1);
5101 if (src.Length == 0)
5102 {
5103 return String.Empty;
5104 }
5105 string ret = String.Empty;
5106 foreach (object o in src.Data)
5107 {
5108 ret = ret + o.ToString() + seperator;
5109 }
5110 ret = ret.Substring(0, ret.Length - seperator.Length);
5111 return ret;
5112 }
5113
5114 public LSL_Integer llScriptDanger(LSL_Vector pos)
5115 {
5116 m_host.AddScriptLPS(1);
5117 bool result = World.scriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z));
5118 if (result)
5119 {
5120 return 1;
5121 }
5122 else
5123 {
5124 return 0;
5125 }
5126
5127 }
5128
5129 public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel)
5130 {
5131 m_host.AddScriptLPS(1);
5132 UUID av = new UUID();
5133 if (!UUID.TryParse(avatar,out av))
5134 {
5135 LSLError("First parameter to llDialog needs to be a key");
5136 return;
5137 }
5138 if (buttons.Length > 12)
5139 {
5140 LSLError("No more than 12 buttons can be shown");
5141 return;
5142 }
5143 string[] buts = new string[buttons.Length];
5144 for (int i = 0; i < buttons.Length; i++)
5145 {
5146 if (buttons.Data[i].ToString() == String.Empty)
5147 {
5148 LSLError("button label cannot be blank");
5149 return;
5150 }
5151 if (buttons.Data[i].ToString().Length > 24)
5152 {
5153 LSLError("button label cannot be longer than 24 characters");
5154 return;
5155 }
5156 buts[i] = buttons.Data[i].ToString();
5157 }
5158 World.SendDialogToUser(av, m_host.Name, m_host.UUID, m_host.OwnerID, message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
5159 // ScriptSleep(1000);
5160 }
5161
5162 public void llVolumeDetect(int detect)
5163 {
5164 m_host.AddScriptLPS(1);
5165 NotImplemented("llVolumeDetect");
5166 }
5167
5168 /// <summary>
5169 /// Reset the named script. The script must be present
5170 /// in the same prim.
5171 /// </summary>
5172
5173 public void llRemoteLoadScript()
5174 {
5175 m_host.AddScriptLPS(1);
5176 Deprecated("llRemoteLoadScript");
5177 // ScriptSleep(3000);
5178 }
5179
5180 public void llSetRemoteScriptAccessPin(int pin)
5181 {
5182 m_host.AddScriptLPS(1);
5183 m_host.ScriptAccessPin = pin;
5184 }
5185
5186 public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
5187 {
5188 m_host.AddScriptLPS(1);
5189 bool found = false;
5190 UUID destId = UUID.Zero;
5191 UUID srcId = UUID.Zero;
5192
5193 if (!UUID.TryParse(target, out destId))
5194 {
5195 llSay(0, "Could not parse key " + target);
5196 return;
5197 }
5198
5199 // target must be a different prim than the one containing the script
5200 if (m_host.UUID == destId)
5201 {
5202 return;
5203 }
5204
5205 // copy the first script found with this inventory name
5206 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
5207 {
5208 if (inv.Value.Name == name)
5209 {
5210 // make sure the object is a script
5211 if (10 == inv.Value.Type)
5212 {
5213 found = true;
5214 srcId = inv.Key;
5215 break;
5216 }
5217 }
5218 }
5219
5220 if (!found)
5221 {
5222 llSay(0, "Could not find script " + name);
5223 return;
5224 }
5225
5226 // the rest of the permission checks are done in RezScript, so check the pin there as well
5227 World.RezScript(srcId, m_host, destId, pin, running, start_param);
5228 // this will cause the delay even if the script pin or permissions were wrong - seems ok
5229 ScriptSleep(3000);
5230 }
5231
5232 public void llOpenRemoteDataChannel()
5233 {
5234 m_host.AddScriptLPS(1);
5235 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
5236 if (xmlrpcMod.IsEnabled())
5237 {
5238 UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, UUID.Zero);
5239 object[] resobj = new object[] { new LSL_Integer(1), new LSL_String(channelID.ToString()), new LSL_String(UUID.Zero.ToString()), new LSL_String(String.Empty), new LSL_Integer(0), new LSL_String(String.Empty) };
5240 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
5241 "remote_data", resobj,
5242 new DetectParams[0]));
5243 }
5244 // ScriptSleep(1000);
5245 }
5246
5247 public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata)
5248 {
5249 m_host.AddScriptLPS(1);
5250 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
5251 // ScriptSleep(3000);
5252 return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString();
5253 }
5254
5255 public void llRemoteDataReply(string channel, string message_id, string sdata, int idata)
5256 {
5257 m_host.AddScriptLPS(1);
5258 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
5259 xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
5260 // ScriptSleep(3000);
5261 }
5262
5263 public void llCloseRemoteDataChannel(string channel)
5264 {
5265 m_host.AddScriptLPS(1);
5266 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
5267 xmlrpcMod.CloseXMLRPCChannel(channel);
5268 // ScriptSleep(1000);
5269 }
5270
5271 public LSL_String llMD5String(string src, int nonce)
5272 {
5273 m_host.AddScriptLPS(1);
5274 return Util.Md5Hash(src + ":" + nonce.ToString());
5275 }
5276
5277 private ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist)
5278 {
5279 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
5280
5281 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
5282 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
5283 holeshape != (int)ScriptBaseClass.PRIM_HOLE_SQUARE &&
5284 holeshape != (int)ScriptBaseClass.PRIM_HOLE_TRIANGLE)
5285 {
5286 holeshape = (int)ScriptBaseClass.PRIM_HOLE_DEFAULT;
5287 }
5288 shapeBlock.ProfileCurve = (byte)holeshape;
5289 if (cut.x < 0f)
5290 {
5291 cut.x = 0f;
5292 }
5293 if (cut.x > 1f)
5294 {
5295 cut.x = 1f;
5296 }
5297 if (cut.y < 0f)
5298 {
5299 cut.y = 0f;
5300 }
5301 if (cut.y > 1f)
5302 {
5303 cut.y = 1f;
5304 }
5305 if (cut.y - cut.x < 0.05f)
5306 {
5307 cut.x = cut.y - 0.05f;
5308 }
5309 shapeBlock.ProfileBegin = (ushort)(50000 * cut.x);
5310 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y));
5311 if (hollow < 0f)
5312 {
5313 hollow = 0f;
5314 }
5315 if (hollow > 0.95)
5316 {
5317 hollow = 0.95f;
5318 }
5319 shapeBlock.ProfileHollow = (ushort)(50000 * hollow);
5320 if (twist.x < -1.0f)
5321 {
5322 twist.x = -1.0f;
5323 }
5324 if (twist.x > 1.0f)
5325 {
5326 twist.x = 1.0f;
5327 }
5328 if (twist.y < -1.0f)
5329 {
5330 twist.y = -1.0f;
5331 }
5332 if (twist.y > 1.0f)
5333 {
5334 twist.y = 1.0f;
5335 }
5336 shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x);
5337 shapeBlock.PathTwist = (sbyte)(100 * twist.y);
5338
5339 shapeBlock.ObjectLocalID = part.LocalId;
5340
5341 // retain pathcurve
5342 shapeBlock.PathCurve = part.Shape.PathCurve;
5343
5344 return shapeBlock;
5345 }
5346
5347 private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge)
5348 {
5349 ObjectShapePacket.ObjectDataBlock shapeBlock;
5350
5351 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
5352
5353 shapeBlock.ProfileCurve += fudge;
5354
5355 if (taper_b.x < 0f)
5356 {
5357 taper_b.x = 0f;
5358 }
5359 if (taper_b.x > 2f)
5360 {
5361 taper_b.x = 2f;
5362 }
5363 if (taper_b.y < 0f)
5364 {
5365 taper_b.y = 0f;
5366 }
5367 if (taper_b.y > 2f)
5368 {
5369 taper_b.y = 2f;
5370 }
5371 shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x));
5372 shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y));
5373 if (topshear.x < -0.5f)
5374 {
5375 topshear.x = -0.5f;
5376 }
5377 if (topshear.x > 0.5f)
5378 {
5379 topshear.x = 0.5f;
5380 }
5381 if (topshear.y < -0.5f)
5382 {
5383 topshear.y = -0.5f;
5384 }
5385 if (topshear.y > 0.5f)
5386 {
5387 topshear.y = 0.5f;
5388 }
5389 shapeBlock.PathShearX = (byte)(100 * topshear.x);
5390 shapeBlock.PathShearY = (byte)(100 * topshear.y);
5391
5392 part.UpdateShape(shapeBlock);
5393 }
5394
5395 private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge)
5396 {
5397 ObjectShapePacket.ObjectDataBlock shapeBlock;
5398
5399 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
5400
5401 // profile/path swapped for a sphere
5402 shapeBlock.PathBegin = shapeBlock.ProfileBegin;
5403 shapeBlock.PathEnd = shapeBlock.ProfileEnd;
5404
5405 shapeBlock.ProfileCurve += fudge;
5406
5407 shapeBlock.PathScaleX = 100;
5408 shapeBlock.PathScaleY = 100;
5409
5410 if (dimple.x < 0f)
5411 {
5412 dimple.x = 0f;
5413 }
5414 if (dimple.x > 1f)
5415 {
5416 dimple.x = 1f;
5417 }
5418 if (dimple.y < 0f)
5419 {
5420 dimple.y = 0f;
5421 }
5422 if (dimple.y > 1f)
5423 {
5424 dimple.y = 1f;
5425 }
5426 if (dimple.y - cut.x < 0.05f)
5427 {
5428 dimple.x = cut.y - 0.05f;
5429 }
5430 shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x);
5431 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y));
5432
5433 part.UpdateShape(shapeBlock);
5434 }
5435
5436 private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte fudge)
5437 {
5438 ObjectShapePacket.ObjectDataBlock shapeBlock;
5439
5440 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
5441
5442 shapeBlock.ProfileCurve += fudge;
5443
5444 // profile/path swapped for a torrus, tube, ring
5445 shapeBlock.PathBegin = shapeBlock.ProfileBegin;
5446 shapeBlock.PathEnd = shapeBlock.ProfileEnd;
5447
5448 if (holesize.x < 0.05f)
5449 {
5450 holesize.x = 0.05f;
5451 }
5452 if (holesize.x > 1f)
5453 {
5454 holesize.x = 1f;
5455 }
5456 if (holesize.y < 0.05f)
5457 {
5458 holesize.y = 0.05f;
5459 }
5460 if (holesize.y > 0.5f)
5461 {
5462 holesize.y = 0.5f;
5463 }
5464 shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x));
5465 shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y));
5466 if (topshear.x < -0.5f)
5467 {
5468 topshear.x = -0.5f;
5469 }
5470 if (topshear.x > 0.5f)
5471 {
5472 topshear.x = 0.5f;
5473 }
5474 if (topshear.y < -0.5f)
5475 {
5476 topshear.y = -0.5f;
5477 }
5478 if (topshear.y > 0.5f)
5479 {
5480 topshear.y = 0.5f;
5481 }
5482 shapeBlock.PathShearX = (byte)(100 * topshear.x);
5483 shapeBlock.PathShearY = (byte)(100 * topshear.y);
5484 if (profilecut.x < 0f)
5485 {
5486 profilecut.x = 0f;
5487 }
5488 if (profilecut.x > 1f)
5489 {
5490 profilecut.x = 1f;
5491 }
5492 if (profilecut.y < 0f)
5493 {
5494 profilecut.y = 0f;
5495 }
5496 if (profilecut.y > 1f)
5497 {
5498 profilecut.y = 1f;
5499 }
5500 if (profilecut.y - cut.x < 0.05f)
5501 {
5502 profilecut.x = cut.y - 0.05f;
5503 }
5504 shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x);
5505 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y));
5506 if (taper_a.x < -1f)
5507 {
5508 taper_a.x = -1f;
5509 }
5510 if (taper_a.x > 1f)
5511 {
5512 taper_a.x = 1f;
5513 }
5514 if (taper_a.y < -1f)
5515 {
5516 taper_a.y = -1f;
5517 }
5518 if (taper_a.y > 1f)
5519 {
5520 taper_a.y = 1f;
5521 }
5522 shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x);
5523 shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y);
5524 if (revolutions < 1f)
5525 {
5526 revolutions = 1f;
5527 }
5528 if (revolutions > 4f)
5529 {
5530 revolutions = 4f;
5531 }
5532 shapeBlock.PathRevolutions = (byte)(66.666667 * (revolutions - 1.0));
5533 // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
5534 if (radiusoffset < 0f)
5535 {
5536 radiusoffset = 0f;
5537 }
5538 if (radiusoffset > 1f)
5539 {
5540 radiusoffset = 1f;
5541 }
5542 shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset);
5543 if (skew < -0.95f)
5544 {
5545 skew = -0.95f;
5546 }
5547 if (skew > 0.95f)
5548 {
5549 skew = 0.95f;
5550 }
5551 shapeBlock.PathSkew = (sbyte)(100 * skew);
5552
5553 part.UpdateShape(shapeBlock);
5554 }
5555
5556 private void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type)
5557 {
5558 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
5559 UUID sculptId;
5560
5561 if (!UUID.TryParse(map, out sculptId))
5562 {
5563 llSay(0, "Could not parse key " + map);
5564 return;
5565 }
5566
5567 shapeBlock.ObjectLocalID = part.LocalId;
5568 shapeBlock.PathScaleX = 100;
5569 shapeBlock.PathScaleY = 150;
5570
5571 if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER &&
5572 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE &&
5573 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE &&
5574 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS)
5575 {
5576 // default
5577 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
5578 }
5579
5580 // retain pathcurve
5581 shapeBlock.PathCurve = part.Shape.PathCurve;
5582
5583 part.Shape.SetSculptData((byte)type, sculptId);
5584 part.Shape.SculptEntry = true;
5585 part.UpdateShape(shapeBlock);
5586 }
5587
5588 public void llSetPrimitiveParams(LSL_List rules)
5589 {
5590 SetPrimParams(m_host, rules);
5591 }
5592
5593 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
5594 {
5595 m_host.AddScriptLPS(1);
5596
5597 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5598
5599 foreach (SceneObjectPart part in parts)
5600 SetPrimParams(part, rules);
5601 }
5602
5603 private void SetPrimParams(SceneObjectPart part, LSL_List rules)
5604 {
5605 int idx = 0;
5606
5607 while (idx < rules.Length)
5608 {
5609 int code = rules.GetLSLIntegerItem(idx++);
5610
5611 int remain = rules.Length - idx;
5612
5613 int face;
5614 LSL_Vector v;
5615
5616 switch (code)
5617 {
5618 case (int)ScriptBaseClass.PRIM_POSITION:
5619 if (remain < 1)
5620 return;
5621
5622 v=rules.GetVector3Item(idx++);
5623 SetPos(part, v);
5624
5625 break;
5626 case (int)ScriptBaseClass.PRIM_SIZE:
5627 if (remain < 1)
5628 return;
5629
5630 v=rules.GetVector3Item(idx++);
5631 SetScale(part, v);
5632
5633 break;
5634 case (int)ScriptBaseClass.PRIM_ROTATION:
5635 if (remain < 1)
5636 return;
5637
5638 LSL_Rotation q = rules.GetQuaternionItem(idx++);
5639 SetRot(part, q);
5640
5641 break;
5642
5643 case (int)ScriptBaseClass.PRIM_TYPE:
5644 if (remain < 3)
5645 return;
5646
5647 code = (int)rules.GetLSLIntegerItem(idx++);
5648
5649 remain = rules.Length - idx;
5650 float hollow;
5651 LSL_Vector twist;
5652 LSL_Vector taper_b;
5653 LSL_Vector topshear;
5654 float revolutions;
5655 float radiusoffset;
5656 float skew;
5657 LSL_Vector holesize;
5658 LSL_Vector profilecut;
5659
5660 switch (code)
5661 {
5662 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
5663 if (remain < 6)
5664 return;
5665
5666 face = (int)rules.GetLSLIntegerItem(idx++);
5667 v = rules.GetVector3Item(idx++); // cut
5668 hollow = (float)rules.GetLSLFloatItem(idx++);
5669 twist = rules.GetVector3Item(idx++);
5670 taper_b = rules.GetVector3Item(idx++);
5671 topshear = rules.GetVector3Item(idx++);
5672
5673 part.Shape.PathCurve = (byte)Extrusion.Straight;
5674 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 1);
5675 break;
5676
5677 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
5678 if (remain < 6)
5679 return;
5680
5681 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5682 v = rules.GetVector3Item(idx++); // cut
5683 hollow = (float)rules.GetLSLFloatItem(idx++);
5684 twist = rules.GetVector3Item(idx++);
5685 taper_b = rules.GetVector3Item(idx++);
5686 topshear = rules.GetVector3Item(idx++);
5687 part.Shape.ProfileShape = ProfileShape.Circle;
5688 part.Shape.PathCurve = (byte)Extrusion.Straight;
5689 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 0);
5690 break;
5691
5692 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
5693 if (remain < 6)
5694 return;
5695
5696 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5697 v = rules.GetVector3Item(idx++); //cut
5698 hollow = (float)rules.GetLSLFloatItem(idx++);
5699 twist = rules.GetVector3Item(idx++);
5700 taper_b = rules.GetVector3Item(idx++);
5701 topshear = rules.GetVector3Item(idx++);
5702 part.Shape.PathCurve = (byte)Extrusion.Straight;
5703 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 3);
5704 break;
5705
5706 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
5707 if (remain < 5)
5708 return;
5709
5710 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5711 v = rules.GetVector3Item(idx++); // cut
5712 hollow = (float)rules.GetLSLFloatItem(idx++);
5713 twist = rules.GetVector3Item(idx++);
5714 taper_b = rules.GetVector3Item(idx++); // dimple
5715 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5716 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, 5);
5717 break;
5718
5719 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
5720 if (remain < 11)
5721 return;
5722
5723 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5724 v = rules.GetVector3Item(idx++); //cut
5725 hollow = (float)rules.GetLSLFloatItem(idx++);
5726 twist = rules.GetVector3Item(idx++);
5727 holesize = rules.GetVector3Item(idx++);
5728 topshear = rules.GetVector3Item(idx++);
5729 profilecut = rules.GetVector3Item(idx++);
5730 taper_b = rules.GetVector3Item(idx++); // taper_a
5731 revolutions = (float)rules.GetLSLFloatItem(idx++);
5732 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
5733 skew = (float)rules.GetLSLFloatItem(idx++);
5734 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5735 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 0);
5736 break;
5737
5738 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
5739 if (remain < 11)
5740 return;
5741
5742 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5743 v = rules.GetVector3Item(idx++); //cut
5744 hollow = (float)rules.GetLSLFloatItem(idx++);
5745 twist = rules.GetVector3Item(idx++);
5746 holesize = rules.GetVector3Item(idx++);
5747 topshear = rules.GetVector3Item(idx++);
5748 profilecut = rules.GetVector3Item(idx++);
5749 taper_b = rules.GetVector3Item(idx++); // taper_a
5750 revolutions = (float)rules.GetLSLFloatItem(idx++);
5751 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
5752 skew = (float)rules.GetLSLFloatItem(idx++);
5753 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5754 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 1);
5755 break;
5756
5757 case (int)ScriptBaseClass.PRIM_TYPE_RING:
5758 if (remain < 11)
5759 return;
5760
5761 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
5762 v = rules.GetVector3Item(idx++); //cut
5763 hollow = (float)rules.GetLSLFloatItem(idx++);
5764 twist = rules.GetVector3Item(idx++);
5765 holesize = rules.GetVector3Item(idx++);
5766 topshear = rules.GetVector3Item(idx++);
5767 profilecut = rules.GetVector3Item(idx++);
5768 taper_b = rules.GetVector3Item(idx++); // taper_a
5769 revolutions = (float)rules.GetLSLFloatItem(idx++);
5770 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
5771 skew = (float)rules.GetLSLFloatItem(idx++);
5772 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5773 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 3);
5774 break;
5775
5776 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
5777 if (remain < 2)
5778 return;
5779
5780 string map = rules.Data[idx++].ToString();
5781 face = (int)rules.GetLSLIntegerItem(idx++); // type
5782 part.Shape.PathCurve = (byte)Extrusion.Curve1;
5783 SetPrimitiveShapeParams(part, map, face);
5784 break;
5785 }
5786
5787 break;
5788
5789 case (int)ScriptBaseClass.PRIM_TEXTURE:
5790 if (remain < 5)
5791 return;
5792
5793 face=(int)rules.GetLSLIntegerItem(idx++);
5794 string tex=rules.Data[idx++].ToString();
5795 LSL_Vector repeats=rules.GetVector3Item(idx++);
5796 LSL_Vector offsets=rules.GetVector3Item(idx++);
5797 double rotation=(double)rules.GetLSLFloatItem(idx++);
5798
5799 SetTexture(part, tex, face);
5800 ScaleTexture(part, repeats.x, repeats.y, face);
5801 OffsetTexture(part, offsets.x, offsets.y, face);
5802 RotateTexture(part, rotation, face);
5803
5804 break;
5805
5806 case (int)ScriptBaseClass.PRIM_COLOR:
5807 if (remain < 3)
5808 return;
5809
5810 face=(int)rules.GetLSLIntegerItem(idx++);
5811 LSL_Vector color=rules.GetVector3Item(idx++);
5812 double alpha=(double)rules.GetLSLFloatItem(idx++);
5813
5814 SetColor(part, color, face);
5815 SetAlpha(part, alpha, face);
5816
5817 break;
5818 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
5819 if (remain < 7)
5820 return;
5821
5822 bool flexi = rules.GetLSLIntegerItem(idx++);
5823 int softness = rules.GetLSLIntegerItem(idx++);
5824 float gravity = (float)rules.GetLSLFloatItem(idx++);
5825 float friction = (float)rules.GetLSLFloatItem(idx++);
5826 float wind = (float)rules.GetLSLFloatItem(idx++);
5827 float tension = (float)rules.GetLSLFloatItem(idx++);
5828 LSL_Vector force = rules.GetVector3Item(idx++);
5829
5830 SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force);
5831
5832 break;
5833 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
5834 if (remain < 5)
5835 return;
5836 bool light = rules.GetLSLIntegerItem(idx++);
5837 LSL_Vector lightcolor = rules.GetVector3Item(idx++);
5838 float intensity = (float)rules.GetLSLFloatItem(idx++);
5839 float radius = (float)rules.GetLSLFloatItem(idx++);
5840 float falloff = (float)rules.GetLSLFloatItem(idx++);
5841
5842 SetPointLight(part, light, lightcolor, intensity, radius, falloff);
5843
5844 break;
5845 case (int)ScriptBaseClass.PRIM_GLOW:
5846 if (remain < 2)
5847 return;
5848 face = rules.GetLSLIntegerItem(idx++);
5849 float glow = (float)rules.GetLSLFloatItem(idx++);
5850
5851 SetGlow(part, face, glow);
5852
5853 break;
5854 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
5855 if (remain < 3)
5856 return;
5857 face = (int)rules.GetLSLIntegerItem(idx++);
5858 int shiny = (int)rules.GetLSLIntegerItem(idx++);
5859 Bumpiness bump = (Bumpiness)Convert.ToByte((int)rules.GetLSLIntegerItem(idx++));
5860
5861 SetShiny(part, face, shiny, bump);
5862
5863 break;
5864 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
5865 if (remain < 2)
5866 return;
5867 face = rules.GetLSLIntegerItem(idx++);
5868 bool st = rules.GetLSLIntegerItem(idx++);
5869 SetFullBright(part, face , st);
5870 break;
5871 case (int)ScriptBaseClass.PRIM_MATERIAL:
5872 if (remain < 1)
5873 return;
5874 if (part != null)
5875 {
5876 /* Unhandled at this time - sends "Unhandled" message
5877 will enable when available
5878 byte material = Convert.ToByte((int)rules.GetLSLIntegerItem(idx++));
5879 part.Material = material;
5880 */
5881 return;
5882 }
5883 break;
5884 case (int)ScriptBaseClass.PRIM_PHANTOM:
5885 if (remain < 1)
5886 return;
5887
5888 string ph = rules.Data[idx++].ToString();
5889 bool phantom;
5890
5891 if (ph.Equals("1"))
5892 phantom = true;
5893 else
5894 phantom = false;
5895
5896 part.ScriptSetPhantomStatus(phantom);
5897 part.ScheduleFullUpdate();
5898 break;
5899 case (int)ScriptBaseClass.PRIM_PHYSICS:
5900 if (remain < 1)
5901 return;
5902 string phy = rules.Data[idx++].ToString();
5903 bool physics;
5904
5905 if (phy.Equals("1"))
5906 physics = true;
5907 else
5908 physics = false;
5909
5910 m_host.ScriptSetPhysicsStatus(physics);
5911 part.ScheduleFullUpdate();
5912 break;
5913 }
5914 }
5915 }
5916
5917 public LSL_String llStringToBase64(string str)
5918 {
5919 m_host.AddScriptLPS(1);
5920 try
5921 {
5922 byte[] encData_byte = new byte[str.Length];
5923 encData_byte = Encoding.UTF8.GetBytes(str);
5924 string encodedData = Convert.ToBase64String(encData_byte);
5925 return encodedData;
5926 }
5927 catch (Exception e)
5928 {
5929 throw new Exception("Error in base64Encode" + e.Message);
5930 }
5931 }
5932
5933 public LSL_String llBase64ToString(string str)
5934 {
5935 m_host.AddScriptLPS(1);
5936 UTF8Encoding encoder = new UTF8Encoding();
5937 Decoder utf8Decode = encoder.GetDecoder();
5938 try
5939 {
5940 byte[] todecode_byte = Convert.FromBase64String(str);
5941 int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
5942 char[] decoded_char = new char[charCount];
5943 utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
5944 string result = new String(decoded_char);
5945 return result;
5946 }
5947 catch (Exception e)
5948 {
5949 throw new Exception("Error in base64Decode" + e.Message);
5950 }
5951 }
5952
5953 public void llXorBase64Strings()
5954 {
5955 m_host.AddScriptLPS(1);
5956 Deprecated("llXorBase64Strings");
5957 // ScriptSleep(300);
5958 }
5959
5960 public void llRemoteDataSetRegion()
5961 {
5962 m_host.AddScriptLPS(1);
5963 NotImplemented("llRemoteDataSetRegion");
5964 }
5965
5966 public LSL_Float llLog10(double val)
5967 {
5968 m_host.AddScriptLPS(1);
5969 return (double)Math.Log10(val);
5970 }
5971
5972 public LSL_Float llLog(double val)
5973 {
5974 m_host.AddScriptLPS(1);
5975 return (double)Math.Log(val);
5976 }
5977
5978 public LSL_List llGetAnimationList( string id )
5979 {
5980 m_host.AddScriptLPS(1);
5981
5982 LSL_List l = new LSL_List();
5983 ScenePresence av = World.GetScenePresence(id);
5984 if (av == null)
5985 return l;
5986 UUID[] anims;
5987 anims = av.GetAnimationArray();
5988 foreach (UUID foo in anims)
5989 l.Add(foo.ToString());
5990 return l;
5991 }
5992
5993 public void llSetParcelMusicURL(string url)
5994 {
5995 m_host.AddScriptLPS(1);
5996 UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
5997 if (landowner == UUID.Zero)
5998 {
5999 return;
6000 }
6001 if (landowner != m_host.ObjectOwner)
6002 {
6003 return;
6004 }
6005 World.SetLandMusicURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url);
6006 // ScriptSleep(2000);
6007 }
6008
6009 public LSL_Vector llGetRootPosition()
6010 {
6011 m_host.AddScriptLPS(1);
6012 return new LSL_Vector(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, m_host.ParentGroup.AbsolutePosition.Z);
6013 }
6014
6015 public LSL_Rotation llGetRootRotation()
6016 {
6017 m_host.AddScriptLPS(1);
6018 return new LSL_Rotation(m_host.ParentGroup.GroupRotation.X, m_host.ParentGroup.GroupRotation.Y, m_host.ParentGroup.GroupRotation.Z, m_host.ParentGroup.GroupRotation.W);
6019 }
6020
6021 public LSL_String llGetObjectDesc()
6022 {
6023 return m_host.Description!=null?m_host.Description:String.Empty;
6024 }
6025
6026 public void llSetObjectDesc(string desc)
6027 {
6028 m_host.AddScriptLPS(1);
6029 m_host.Description = desc!=null?desc:String.Empty;
6030 }
6031
6032 public LSL_String llGetCreator()
6033 {
6034 m_host.AddScriptLPS(1);
6035 return m_host.ObjectCreator.ToString();
6036 }
6037
6038 public LSL_String llGetTimestamp()
6039 {
6040 m_host.AddScriptLPS(1);
6041 return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
6042 }
6043
6044 public void llSetLinkAlpha(int linknumber, double alpha, int face)
6045 {
6046 m_host.AddScriptLPS(1);
6047 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber);
6048 if (linknumber > -1)
6049 {
6050 Primitive.TextureEntry tex = part.Shape.Textures;
6051 Color4 texcolor;
6052 if (face >= 0 && face < GetNumberOfSides(m_host))
6053 {
6054 texcolor = tex.CreateFace((uint)face).RGBA;
6055 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6056 tex.FaceTextures[face].RGBA = texcolor;
6057 part.UpdateTexture(tex);
6058 return;
6059 }
6060 else if (face == ScriptBaseClass.ALL_SIDES)
6061 {
6062 texcolor = tex.DefaultTexture.RGBA;
6063 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6064 tex.DefaultTexture.RGBA = texcolor;
6065 for (uint i = 0; i < GetNumberOfSides(m_host); i++)
6066 {
6067 if (tex.FaceTextures[i] != null)
6068 {
6069 texcolor = tex.FaceTextures[i].RGBA;
6070 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6071 tex.FaceTextures[i].RGBA = texcolor;
6072 }
6073 }
6074 texcolor = tex.DefaultTexture.RGBA;
6075 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6076 tex.DefaultTexture.RGBA = texcolor;
6077 part.UpdateTexture(tex);
6078 return;
6079 }
6080 return;
6081 }
6082 else if (linknumber == -1)
6083 {
6084 int num = m_host.ParentGroup.PrimCount;
6085 for (int w = 0; w < num; w++)
6086 {
6087 linknumber = w;
6088 part = m_host.ParentGroup.GetLinkNumPart(linknumber);
6089 Primitive.TextureEntry tex = part.Shape.Textures;
6090 Color4 texcolor;
6091 if (face > -1)
6092 {
6093 texcolor = tex.CreateFace((uint)face).RGBA;
6094 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6095 tex.FaceTextures[face].RGBA = texcolor;
6096 part.UpdateTexture(tex);
6097 }
6098 else if (face == -1)
6099 {
6100 texcolor = tex.DefaultTexture.RGBA;
6101 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6102 tex.DefaultTexture.RGBA = texcolor;
6103 for (uint i = 0; i < 32; i++)
6104 {
6105 if (tex.FaceTextures[i] != null)
6106 {
6107 texcolor = tex.FaceTextures[i].RGBA;
6108 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6109 tex.FaceTextures[i].RGBA = texcolor;
6110 }
6111 }
6112 texcolor = tex.DefaultTexture.RGBA;
6113 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
6114 tex.DefaultTexture.RGBA = texcolor;
6115 part.UpdateTexture(tex);
6116 }
6117 }
6118 return;
6119 }
6120 }
6121
6122 public LSL_Integer llGetNumberOfPrims()
6123 {
6124 m_host.AddScriptLPS(1);
6125 return m_host.ParentGroup.PrimCount;
6126 }
6127
6128 public LSL_List llGetBoundingBox(string obj)
6129 {
6130 m_host.AddScriptLPS(1);
6131 NotImplemented("llGetBoundingBox");
6132 return new LSL_List();
6133 }
6134
6135 public LSL_Vector llGetGeometricCenter()
6136 {
6137 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z);
6138 }
6139
6140 public LSL_List llGetPrimitiveParams(LSL_List rules)
6141 {
6142 m_host.AddScriptLPS(1);
6143
6144 LSL_List res = new LSL_List();
6145 int idx=0;
6146 while (idx < rules.Length)
6147 {
6148 int code=(int)rules.GetLSLIntegerItem(idx++);
6149 int remain=rules.Length-idx;
6150
6151 switch (code)
6152 {
6153 case (int)ScriptBaseClass.PRIM_MATERIAL:
6154 res.Add(new LSL_Integer(m_host.Material));
6155 break;
6156
6157 case (int)ScriptBaseClass.PRIM_PHYSICS:
6158 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0)
6159 res.Add(new LSL_Integer(1));
6160 else
6161 res.Add(new LSL_Integer(0));
6162 break;
6163
6164 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
6165 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0)
6166 res.Add(new LSL_Integer(1));
6167 else
6168 res.Add(new LSL_Integer(0));
6169 break;
6170
6171 case (int)ScriptBaseClass.PRIM_PHANTOM:
6172 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
6173 res.Add(new LSL_Integer(1));
6174 else
6175 res.Add(new LSL_Integer(0));
6176 break;
6177
6178 case (int)ScriptBaseClass.PRIM_POSITION:
6179 res.Add(new LSL_Vector(m_host.AbsolutePosition.X,
6180 m_host.AbsolutePosition.Y,
6181 m_host.AbsolutePosition.Z));
6182 break;
6183
6184 case (int)ScriptBaseClass.PRIM_SIZE:
6185 res.Add(new LSL_Vector(m_host.Scale.X,
6186 m_host.Scale.Y,
6187 m_host.Scale.Z));
6188 break;
6189
6190 case (int)ScriptBaseClass.PRIM_ROTATION:
6191 res.Add(new LSL_Rotation(m_host.RotationOffset.X,
6192 m_host.RotationOffset.Y,
6193 m_host.RotationOffset.Z,
6194 m_host.RotationOffset.W));
6195 break;
6196
6197 case (int)ScriptBaseClass.PRIM_TYPE:
6198 // implementing box
6199 PrimitiveBaseShape Shape = m_host.Shape;
6200 int primType = getScriptPrimType(m_host.Shape);
6201 res.Add(new LSL_Integer(primType));
6202 switch (primType)
6203 {
6204 case ScriptBaseClass.PRIM_TYPE_BOX:
6205 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
6206 case ScriptBaseClass.PRIM_TYPE_PRISM:
6207 res.Add(new LSL_Integer(Shape.ProfileCurve));
6208 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
6209 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
6210 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
6211 res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
6212 res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0));
6213 break;
6214
6215 case ScriptBaseClass.PRIM_TYPE_SPHERE:
6216 res.Add(new LSL_Integer(Shape.ProfileCurve));
6217 res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
6218 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
6219 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
6220 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
6221 break;
6222
6223 case ScriptBaseClass.PRIM_TYPE_SCULPT:
6224 res.Add(Shape.SculptTexture.ToString());
6225 res.Add(new LSL_Integer(Shape.SculptType));
6226 break;
6227
6228 case ScriptBaseClass.PRIM_TYPE_RING:
6229 case ScriptBaseClass.PRIM_TYPE_TUBE:
6230 case ScriptBaseClass.PRIM_TYPE_TORUS:
6231 // holeshape
6232 res.Add(new LSL_Integer(Shape.ProfileCurve));
6233
6234 // cut
6235 res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
6236
6237 // hollow
6238 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
6239
6240 // twist
6241 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
6242
6243 // vector holesize
6244 res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
6245
6246 // vector topshear
6247 res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0));
6248
6249 // vector profilecut
6250 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
6251
6252
6253 // vector tapera
6254 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
6255
6256 // float revolutions,
6257 res.Add(new LSL_Float(Shape.PathRevolutions / 50.0)); // needs fixing :(
6258
6259 // float radiusoffset,
6260 res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));
6261
6262 // float skew
6263 res.Add(new LSL_Float(Shape.PathSkew / 100.0));
6264 break;
6265
6266 }
6267 break;
6268
6269 case (int)ScriptBaseClass.PRIM_TEXTURE:
6270 if (remain < 1)
6271 return res;
6272
6273 int face = (int)rules.GetLSLIntegerItem(idx++);
6274 Primitive.TextureEntry tex = m_host.Shape.Textures;
6275 if (face == ScriptBaseClass.ALL_SIDES)
6276 {
6277 for (face = 0 ; face < GetNumberOfSides(m_host) ; face++)
6278 {
6279 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
6280
6281 res.Add(new LSL_String(texface.TextureID.ToString()));
6282 res.Add(new LSL_Vector(texface.RepeatU,
6283 texface.RepeatV,
6284 0));
6285 res.Add(new LSL_Vector(texface.OffsetU,
6286 texface.OffsetV,
6287 0));
6288 res.Add(new LSL_Float(texface.Rotation));
6289 }
6290 }
6291 else
6292 {
6293 if (face >= 0 && face < GetNumberOfSides(m_host))
6294 {
6295 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
6296
6297 res.Add(new LSL_String(texface.TextureID.ToString()));
6298 res.Add(new LSL_Vector(texface.RepeatU,
6299 texface.RepeatV,
6300 0));
6301 res.Add(new LSL_Vector(texface.OffsetU,
6302 texface.OffsetV,
6303 0));
6304 res.Add(new LSL_Float(texface.Rotation));
6305 }
6306 }
6307 break;
6308
6309 case (int)ScriptBaseClass.PRIM_COLOR:
6310 if (remain < 1)
6311 return res;
6312
6313 face=(int)rules.GetLSLIntegerItem(idx++);
6314
6315 tex = m_host.Shape.Textures;
6316 Color4 texcolor;
6317 if (face == ScriptBaseClass.ALL_SIDES)
6318 {
6319 for (face = 0 ; face < GetNumberOfSides(m_host) ; face++)
6320 {
6321 texcolor = tex.GetFace((uint)face).RGBA;
6322 res.Add(new LSL_Vector(texcolor.R,
6323 texcolor.G,
6324 texcolor.B));
6325 res.Add(new LSL_Float(texcolor.A));
6326 }
6327 }
6328 else
6329 {
6330 texcolor = tex.GetFace((uint)face).RGBA;
6331 res.Add(new LSL_Vector(texcolor.R,
6332 texcolor.G,
6333 texcolor.B));
6334 res.Add(new LSL_Float(texcolor.A));
6335 }
6336 break;
6337
6338 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
6339 // TODO--------------
6340 if (remain < 1)
6341 return res;
6342
6343 face=(int)rules.GetLSLIntegerItem(idx++);
6344
6345 res.Add(new LSL_Integer(0));
6346 res.Add(new LSL_Integer(0));
6347 break;
6348
6349 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
6350 // TODO--------------
6351 if (remain < 1)
6352 return res;
6353
6354 face=(int)rules.GetLSLIntegerItem(idx++);
6355
6356 res.Add(new LSL_Integer(0));
6357 break;
6358
6359 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
6360 PrimitiveBaseShape shape = m_host.Shape;
6361
6362 if (shape.FlexiEntry)
6363 res.Add(new LSL_Integer(1)); // active
6364 else
6365 res.Add(new LSL_Integer(0));
6366 res.Add(new LSL_Integer(shape.FlexiSoftness));// softness
6367 res.Add(new LSL_Float(shape.FlexiGravity)); // gravity
6368 res.Add(new LSL_Float(shape.FlexiDrag)); // friction
6369 res.Add(new LSL_Float(shape.FlexiWind)); // wind
6370 res.Add(new LSL_Float(shape.FlexiTension)); // tension
6371 res.Add(new LSL_Vector(shape.FlexiForceX, // force
6372 shape.FlexiForceY,
6373 shape.FlexiForceZ));
6374 break;
6375
6376 case (int)ScriptBaseClass.PRIM_TEXGEN:
6377 // TODO--------------
6378 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
6379 if (remain < 1)
6380 return res;
6381
6382 face=(int)rules.GetLSLIntegerItem(idx++);
6383
6384 res.Add(new LSL_Integer(0));
6385 break;
6386
6387 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
6388 shape = m_host.Shape;
6389
6390 if (shape.LightEntry)
6391 res.Add(new LSL_Integer(1)); // active
6392 else
6393 res.Add(new LSL_Integer(0));
6394 res.Add(new LSL_Vector(shape.LightColorR, // color
6395 shape.LightColorG,
6396 shape.LightColorB));
6397 res.Add(new LSL_Float(shape.LightIntensity)); // intensity
6398 res.Add(new LSL_Float(shape.LightRadius)); // radius
6399 res.Add(new LSL_Float(shape.LightFalloff)); // falloff
6400 break;
6401
6402 case (int)ScriptBaseClass.PRIM_GLOW:
6403 // TODO--------------
6404 if (remain < 1)
6405 return res;
6406
6407 face=(int)rules.GetLSLIntegerItem(idx++);
6408
6409 res.Add(new LSL_Float(0));
6410 break;
6411 }
6412 }
6413 return res;
6414 }
6415
6416 // <remarks>
6417 // <para>
6418 // The .NET definition of base 64 is:
6419 // <list>
6420 // <item>
6421 // Significant: A-Z a-z 0-9 + -
6422 // </item>
6423 // <item>
6424 // Whitespace: \t \n \r ' '
6425 // </item>
6426 // <item>
6427 // Valueless: =
6428 // </item>
6429 // <item>
6430 // End-of-string: \0 or '=='
6431 // </item>
6432 // </list>
6433 // </para>
6434 // <para>
6435 // Each point in a base-64 string represents
6436 // a 6 bit value. A 32-bit integer can be
6437 // represented using 6 characters (with some
6438 // redundancy).
6439 // </para>
6440 // <para>
6441 // LSL requires a base64 string to be 8
6442 // characters in length. LSL also uses '/'
6443 // rather than '-' (MIME compliant).
6444 // </para>
6445 // <para>
6446 // RFC 1341 used as a reference (as specified
6447 // by the SecondLife Wiki).
6448 // </para>
6449 // <para>
6450 // SL do not record any kind of exception for
6451 // these functions, so the string to integer
6452 // conversion returns '0' if an invalid
6453 // character is encountered during conversion.
6454 // </para>
6455 // <para>
6456 // References
6457 // <list>
6458 // <item>
6459 // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64
6460 // </item>
6461 // <item>
6462 // </item>
6463 // </list>
6464 // </para>
6465 // </remarks>
6466
6467 // <summary>
6468 // Table for converting 6-bit integers into
6469 // base-64 characters
6470 // </summary>
6471
6472 private static readonly char[] i2ctable =
6473 {
6474 'A','B','C','D','E','F','G','H',
6475 'I','J','K','L','M','N','O','P',
6476 'Q','R','S','T','U','V','W','X',
6477 'Y','Z',
6478 'a','b','c','d','e','f','g','h',
6479 'i','j','k','l','m','n','o','p',
6480 'q','r','s','t','u','v','w','x',
6481 'y','z',
6482 '0','1','2','3','4','5','6','7',
6483 '8','9',
6484 '+','/'
6485 };
6486
6487 // <summary>
6488 // Table for converting base-64 characters
6489 // into 6-bit integers.
6490 // </summary>
6491
6492 private static readonly int[] c2itable =
6493 {
6494 -1,-1,-1,-1,-1,-1,-1,-1, // 0x
6495 -1,-1,-1,-1,-1,-1,-1,-1,
6496 -1,-1,-1,-1,-1,-1,-1,-1, // 1x
6497 -1,-1,-1,-1,-1,-1,-1,-1,
6498 -1,-1,-1,-1,-1,-1,-1,-1, // 2x
6499 -1,-1,-1,63,-1,-1,-1,64,
6500 53,54,55,56,57,58,59,60, // 3x
6501 61,62,-1,-1,-1,0,-1,-1,
6502 -1,1,2,3,4,5,6,7, // 4x
6503 8,9,10,11,12,13,14,15,
6504 16,17,18,19,20,21,22,23, // 5x
6505 24,25,26,-1,-1,-1,-1,-1,
6506 -1,27,28,29,30,31,32,33, // 6x
6507 34,35,36,37,38,39,40,41,
6508 42,43,44,45,46,47,48,49, // 7x
6509 50,51,52,-1,-1,-1,-1,-1,
6510 -1,-1,-1,-1,-1,-1,-1,-1, // 8x
6511 -1,-1,-1,-1,-1,-1,-1,-1,
6512 -1,-1,-1,-1,-1,-1,-1,-1, // 9x
6513 -1,-1,-1,-1,-1,-1,-1,-1,
6514 -1,-1,-1,-1,-1,-1,-1,-1, // Ax
6515 -1,-1,-1,-1,-1,-1,-1,-1,
6516 -1,-1,-1,-1,-1,-1,-1,-1, // Bx
6517 -1,-1,-1,-1,-1,-1,-1,-1,
6518 -1,-1,-1,-1,-1,-1,-1,-1, // Cx
6519 -1,-1,-1,-1,-1,-1,-1,-1,
6520 -1,-1,-1,-1,-1,-1,-1,-1, // Dx
6521 -1,-1,-1,-1,-1,-1,-1,-1,
6522 -1,-1,-1,-1,-1,-1,-1,-1, // Ex
6523 -1,-1,-1,-1,-1,-1,-1,-1,
6524 -1,-1,-1,-1,-1,-1,-1,-1, // Fx
6525 -1,-1,-1,-1,-1,-1,-1,-1
6526 };
6527
6528 // <summary>
6529 // Converts a 32-bit integer into a Base64
6530 // character string. Base64 character strings
6531 // are always 8 characters long. All iinteger
6532 // values are acceptable.
6533 // </summary>
6534 // <param name="number">
6535 // 32-bit integer to be converted.
6536 // </param>
6537 // <returns>
6538 // 8 character string. The 1st six characters
6539 // contain the encoded number, the last two
6540 // characters are padded with "=".
6541 // </returns>
6542
6543 public LSL_String llIntegerToBase64(int number)
6544 {
6545 // uninitialized string
6546
6547 char[] imdt = new char[8];
6548
6549 m_host.AddScriptLPS(1);
6550
6551 // Manually unroll the loop
6552
6553 imdt[7] = '=';
6554 imdt[6] = '=';
6555 imdt[5] = i2ctable[number<<4 & 0x3F];
6556 imdt[4] = i2ctable[number>>2 & 0x3F];
6557 imdt[3] = i2ctable[number>>8 & 0x3F];
6558 imdt[2] = i2ctable[number>>14 & 0x3F];
6559 imdt[1] = i2ctable[number>>20 & 0x3F];
6560 imdt[0] = i2ctable[number>>26 & 0x3F];
6561
6562 return new string(imdt);
6563 }
6564
6565 // <summary>
6566 // Converts an eight character base-64 string
6567 // into a 32-bit integer.
6568 // </summary>
6569 // <param name="str">
6570 // 8 characters string to be converted. Other
6571 // length strings return zero.
6572 // </param>
6573 // <returns>
6574 // Returns an integer representing the
6575 // encoded value providedint he 1st 6
6576 // characters of the string.
6577 // </returns>
6578 // <remarks>
6579 // This is coded to behave like LSL's
6580 // implementation (I think), based upon the
6581 // information available at the Wiki.
6582 // If more than 8 characters are supplied,
6583 // zero is returned.
6584 // If a NULL string is supplied, zero will
6585 // be returned.
6586 // If fewer than 6 characters are supplied, then
6587 // the answer will reflect a partial
6588 // accumulation.
6589 // <para>
6590 // The 6-bit segments are
6591 // extracted left-to-right in big-endian mode,
6592 // which means that segment 6 only contains the
6593 // two low-order bits of the 32 bit integer as
6594 // its high order 2 bits. A short string therefore
6595 // means loss of low-order information. E.g.
6596 //
6597 // |<---------------------- 32-bit integer ----------------------->|<-Pad->|
6598 // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->|
6599 // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P|
6600 // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P|
6601 // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] |
6602 //
6603 // </para>
6604 // </remarks>
6605
6606 public LSL_Integer llBase64ToInteger(string str)
6607 {
6608 int number = 0;
6609 int digit;
6610
6611 m_host.AddScriptLPS(1);
6612
6613 // Require a well-fromed base64 string
6614
6615 if (str.Length > 8)
6616 return 0;
6617
6618 // The loop is unrolled in the interests
6619 // of performance and simple necessity.
6620 //
6621 // MUST find 6 digits to be well formed
6622 // -1 == invalid
6623 // 0 == padding
6624
6625 if ((digit=c2itable[str[0]])<=0)
6626 {
6627 return digit<0?(int)0:number;
6628 }
6629 number += --digit<<26;
6630
6631 if ((digit=c2itable[str[1]])<=0)
6632 {
6633 return digit<0?(int)0:number;
6634 }
6635 number += --digit<<20;
6636
6637 if ((digit=c2itable[str[2]])<=0)
6638 {
6639 return digit<0?(int)0:number;
6640 }
6641 number += --digit<<14;
6642
6643 if ((digit=c2itable[str[3]])<=0)
6644 {
6645 return digit<0?(int)0:number;
6646 }
6647 number += --digit<<8;
6648
6649 if ((digit=c2itable[str[4]])<=0)
6650 {
6651 return digit<0?(int)0:number;
6652 }
6653 number += --digit<<2;
6654
6655 if ((digit=c2itable[str[5]])<=0)
6656 {
6657 return digit<0?(int)0:number;
6658 }
6659 number += --digit>>4;
6660
6661 // ignore trailing padding
6662
6663 return number;
6664 }
6665
6666 public LSL_Float llGetGMTclock()
6667 {
6668 m_host.AddScriptLPS(1);
6669 return DateTime.UtcNow.TimeOfDay.TotalSeconds;
6670 }
6671
6672 public LSL_String llGetSimulatorHostname()
6673 {
6674 m_host.AddScriptLPS(1);
6675 return System.Environment.MachineName;
6676 }
6677
6678 public void llSetLocalRot(LSL_Rotation rot)
6679 {
6680 m_host.AddScriptLPS(1);
6681 m_host.RotationOffset = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
6682 // ScriptSleep(200);
6683 }
6684
6685 // <summary>
6686 // Scan the string supplied in 'src' and
6687 // tokenize it based upon two sets of
6688 // tokenizers provided in two lists,
6689 // separators and spacers.
6690 // </summary>
6691 //
6692 // <remarks>
6693 // Separators demarcate tokens and are
6694 // elided as they are encountered. Spacers
6695 // also demarcate tokens, but are themselves
6696 // retained as tokens.
6697 //
6698 // Both separators and spacers may be arbitrarily
6699 // long strings. i.e. ":::".
6700 //
6701 // The function returns an ordered list
6702 // representing the tokens found in the supplied
6703 // sources string. If two successive tokenizers
6704 // are encountered, then a NULL entry is added
6705 // to the list.
6706 //
6707 // It is a precondition that the source and
6708 // toekizer lisst are non-null. If they are null,
6709 // then a null pointer exception will be thrown
6710 // while their lengths are being determined.
6711 //
6712 // A small amount of working memoryis required
6713 // of approximately 8*#tokenizers.
6714 //
6715 // There are many ways in which this function
6716 // can be implemented, this implementation is
6717 // fairly naive and assumes that when the
6718 // function is invooked with a short source
6719 // string and/or short lists of tokenizers, then
6720 // performance will not be an issue.
6721 //
6722 // In order to minimize the perofrmance
6723 // effects of long strings, or large numbers
6724 // of tokeizers, the function skips as far as
6725 // possible whenever a toekenizer is found,
6726 // and eliminates redundant tokenizers as soon
6727 // as is possible.
6728 //
6729 // The implementation tries to avoid any copying
6730 // of arrays or other objects.
6731 // </remarks>
6732
6733 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
6734 {
6735 int beginning = 0;
6736 int srclen = src.Length;
6737 int seplen = separators.Length;
6738 object[] separray = separators.Data;
6739 int spclen = spacers.Length;
6740 object[] spcarray = spacers.Data;
6741 int mlen = seplen+spclen;
6742
6743 int[] offset = new int[mlen+1];
6744 bool[] active = new bool[mlen];
6745
6746 int best;
6747 int j;
6748
6749 // Initial capacity reduces resize cost
6750
6751 LSL_List tokens = new LSL_List();
6752
6753 m_host.AddScriptLPS(1);
6754
6755 // All entries are initially valid
6756
6757 for (int i = 0; i < mlen; i++)
6758 active[i] = true;
6759
6760 offset[mlen] = srclen;
6761
6762 while (beginning < srclen)
6763 {
6764
6765 best = mlen; // as bad as it gets
6766
6767 // Scan for separators
6768
6769 for (j = 0; j < seplen; j++)
6770 {
6771 if (active[j])
6772 {
6773 // scan all of the markers
6774 if ((offset[j] = src.IndexOf(separray[j].ToString(),beginning)) == -1)
6775 {
6776 // not present at all
6777 active[j] = false;
6778 }
6779 else
6780 {
6781 // present and correct
6782 if (offset[j] < offset[best])
6783 {
6784 // closest so far
6785 best = j;
6786 if (offset[best] == beginning)
6787 break;
6788 }
6789 }
6790 }
6791 }
6792
6793 // Scan for spacers
6794
6795 if (offset[best] != beginning)
6796 {
6797 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++)
6798 {
6799 if (active[j])
6800 {
6801 // scan all of the markers
6802 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
6803 {
6804 // not present at all
6805 active[j] = false;
6806 }
6807 else
6808 {
6809 // present and correct
6810 if (offset[j] < offset[best])
6811 {
6812 // closest so far
6813 best = j;
6814 }
6815 }
6816 }
6817 }
6818 }
6819
6820 // This is the normal exit from the scanning loop
6821
6822 if (best == mlen)
6823 {
6824 // no markers were found on this pass
6825 // so we're pretty much done
6826 tokens.Add(src.Substring(beginning, srclen - beginning));
6827 break;
6828 }
6829
6830 // Otherwise we just add the newly delimited token
6831 // and recalculate where the search should continue.
6832
6833 tokens.Add(src.Substring(beginning,offset[best]-beginning));
6834
6835 if (best < seplen)
6836 {
6837 beginning = offset[best] + (separray[best].ToString()).Length;
6838 }
6839 else
6840 {
6841 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
6842 tokens.Add(spcarray[best - seplen]);
6843 }
6844 }
6845
6846 // This an awkward an not very intuitive boundary case. If the
6847 // last substring is a tokenizer, then there is an implied trailing
6848 // null list entry. Hopefully the single comparison will not be too
6849 // arduous. Alternatively the 'break' could be replced with a return
6850 // but that's shabby programming.
6851
6852 if (beginning == srclen)
6853 {
6854 if (srclen != 0)
6855 tokens.Add("");
6856 }
6857
6858 return tokens;
6859 }
6860
6861 public LSL_Integer llGetObjectPermMask(int mask)
6862 {
6863 m_host.AddScriptLPS(1);
6864
6865 int permmask = 0;
6866
6867 if (mask == ScriptBaseClass.MASK_BASE)//0
6868 {
6869 permmask = (int)m_host.BaseMask;
6870 }
6871
6872 else if (mask == ScriptBaseClass.MASK_OWNER)//1
6873 {
6874 permmask = (int)m_host.OwnerMask;
6875 }
6876
6877 else if (mask == ScriptBaseClass.MASK_GROUP)//2
6878 {
6879 permmask = (int)m_host.GroupMask;
6880 }
6881
6882 else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
6883 {
6884 permmask = (int)m_host.EveryoneMask;
6885 }
6886
6887 else if (mask == ScriptBaseClass.MASK_NEXT)//4
6888 {
6889 permmask = (int)m_host.NextOwnerMask;
6890 }
6891
6892 return permmask;
6893 }
6894
6895 public void llSetObjectPermMask(int mask, int value)
6896 {
6897 m_host.AddScriptLPS(1);
6898 IConfigSource config = new IniConfigSource(Application.iniFilePath);
6899 if (config.Configs["XEngine"] == null)
6900 config.AddConfig("XEngine");
6901
6902 if (config.Configs["XEngine"].GetBoolean("AllowGodFunctions", false))
6903 {
6904 if (World.ExternalChecks.ExternalChecksCanRunConsoleCommand(m_host.OwnerID))
6905 {
6906 if (mask == ScriptBaseClass.MASK_BASE)//0
6907 {
6908 m_host.BaseMask = (uint)value;
6909 }
6910
6911 else if (mask == ScriptBaseClass.MASK_OWNER)//1
6912 {
6913 m_host.OwnerMask = (uint)value;
6914 }
6915
6916 else if (mask == ScriptBaseClass.MASK_GROUP)//2
6917 {
6918 m_host.GroupMask = (uint)value;
6919 }
6920
6921 else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
6922 {
6923 m_host.EveryoneMask = (uint)value;
6924 }
6925
6926 else if (mask == ScriptBaseClass.MASK_NEXT)//4
6927 {
6928 m_host.NextOwnerMask = (uint)value;
6929 }
6930 }
6931 }
6932 }
6933
6934 public LSL_Integer llGetInventoryPermMask(string item, int mask)
6935 {
6936 m_host.AddScriptLPS(1);
6937 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6938 {
6939 if (inv.Value.Name == item)
6940 {
6941 switch (mask)
6942 {
6943 case 0:
6944 return (int)inv.Value.BasePermissions;
6945 case 1:
6946 return (int)inv.Value.CurrentPermissions;
6947 case 2:
6948 return (int)inv.Value.GroupPermissions;
6949 case 3:
6950 return (int)inv.Value.EveryonePermissions;
6951 case 4:
6952 return (int)inv.Value.NextPermissions;
6953 }
6954 }
6955 }
6956 return -1;
6957 }
6958
6959 public void llSetInventoryPermMask(string item, int mask, int value)
6960 {
6961 m_host.AddScriptLPS(1);
6962 NotImplemented("llSetInventoryPermMask");
6963 }
6964
6965 public LSL_String llGetInventoryCreator(string item)
6966 {
6967 m_host.AddScriptLPS(1);
6968 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6969 {
6970 if (inv.Value.Name == item)
6971 {
6972 return inv.Value.CreatorID.ToString();
6973 }
6974 }
6975 llSay(0, "No item name '" + item + "'");
6976 return String.Empty;
6977 }
6978
6979 public void llOwnerSay(string msg)
6980 {
6981 m_host.AddScriptLPS(1);
6982
6983 World.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
6984// IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
6985// wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg);
6986 }
6987
6988 public LSL_String llRequestSimulatorData(string simulator, int data)
6989 {
6990 try
6991 {
6992 m_host.AddScriptLPS(1);
6993
6994 string reply = String.Empty;
6995
6996 RegionInfo info = m_ScriptEngine.World.RequestClosestRegion(simulator);
6997
6998 switch (data)
6999 {
7000 case 5: // DATA_SIM_POS
7001 if (info == null)
7002 {
7003 // ScriptSleep(1000);
7004 return UUID.Zero.ToString();
7005 }
7006 reply = new LSL_Vector(
7007 info.RegionLocX * Constants.RegionSize,
7008 info.RegionLocY * Constants.RegionSize,
7009 0).ToString();
7010 break;
7011 case 6: // DATA_SIM_STATUS
7012 if (info != null)
7013 reply = "up"; // Duh!
7014 else
7015 reply = "unknown";
7016 break;
7017 case 7: // DATA_SIM_RATING
7018 if (info == null)
7019 {
7020 // ScriptSleep(1000);
7021 return UUID.Zero.ToString();
7022 }
7023 int access = info.RegionSettings.Maturity;
7024 if (access == 0)
7025 reply = "PG";
7026 else if (access == 1)
7027 reply = "MATURE";
7028 else
7029 reply = "UNKNOWN";
7030 break;
7031 case 128: // SIM_RELEASE
7032 reply = m_ScriptEngine.World.GetSimulatorVersion();
7033 break;
7034 default:
7035 // ScriptSleep(1000);
7036 return UUID.Zero.ToString(); // Raise no event
7037 }
7038 UUID rq = UUID.Random();
7039
7040 UUID tid = AsyncCommands.
7041 DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString());
7042
7043 AsyncCommands.
7044 DataserverPlugin.DataserverReply(rq.ToString(), reply);
7045
7046 // ScriptSleep(1000);
7047 return tid.ToString();
7048 }
7049 catch(Exception e)
7050 {
7051 Console.WriteLine(e.ToString());
7052 return UUID.Zero.ToString();
7053 }
7054 }
7055
7056 public void llForceMouselook(int mouselook)
7057 {
7058 m_host.AddScriptLPS(1);
7059 m_host.SetForceMouselook(mouselook != 0);
7060 }
7061
7062 public LSL_Float llGetObjectMass(string id)
7063 {
7064 m_host.AddScriptLPS(1);
7065 UUID key = new UUID();
7066 if (UUID.TryParse(id, out key))
7067 {
7068 try
7069 {
7070 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
7071 if (obj != null)
7072 return (double)obj.GetMass();
7073 // the object is null so the key is for an avatar
7074 ScenePresence avatar = World.GetScenePresence(key);
7075 if (avatar != null)
7076 if (avatar.IsChildAgent)
7077 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
7078 // child agents have a mass of 1.0
7079 return 1;
7080 else
7081 return (double)avatar.PhysicsActor.Mass;
7082 }
7083 catch (KeyNotFoundException)
7084 {
7085 return 0; // The Object/Agent not in the region so just return zero
7086 }
7087 }
7088 return 0;
7089 }
7090
7091 /// <summary>
7092 /// illListReplaceList removes the sub-list defined by the inclusive indices
7093 /// start and end and inserts the src list in its place. The inclusive
7094 /// nature of the indices means that at least one element must be deleted
7095 /// if the indices are within the bounds of the existing list. I.e. 2,2
7096 /// will remove the element at index 2 and replace it with the source
7097 /// list. Both indices may be negative, with the usual interpretation. An
7098 /// interesting case is where end is lower than start. As these indices
7099 /// bound the list to be removed, then 0->end, and start->lim are removed
7100 /// and the source list is added as a suffix.
7101 /// </summary>
7102
7103 public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end)
7104 {
7105 LSL_List pref = null;
7106
7107 m_host.AddScriptLPS(1);
7108
7109 // Note that although we have normalized, both
7110 // indices could still be negative.
7111 if (start < 0)
7112 {
7113 start = start+dest.Length;
7114 }
7115
7116 if (end < 0)
7117 {
7118 end = end+dest.Length;
7119 }
7120 // The comventional case, remove a sequence starting with
7121 // start and ending with end. And then insert the source
7122 // list.
7123 if (start <= end)
7124 {
7125 // If greater than zero, then there is going to be a
7126 // surviving prefix. Otherwise the inclusive nature
7127 // of the indices mean that we're going to add the
7128 // source list as a prefix.
7129 if (start > 0)
7130 {
7131 pref = dest.GetSublist(0,start-1);
7132 // Only add a suffix if there is something
7133 // beyond the end index (it's inclusive too).
7134 if (end + 1 < dest.Length)
7135 {
7136 return pref + src + dest.GetSublist(end + 1, -1);
7137 }
7138 else
7139 {
7140 return pref + src;
7141 }
7142 }
7143 // If start is less than or equal to zero, then
7144 // the new list is simply a prefix. We still need to
7145 // figure out any necessary surgery to the destination
7146 // based upon end. Note that if end exceeds the upper
7147 // bound in this case, the entire destination list
7148 // is removed.
7149 else
7150 {
7151 if (end + 1 < dest.Length)
7152 {
7153 return src + dest.GetSublist(end + 1, -1);
7154 }
7155 else
7156 {
7157 return src;
7158 }
7159 }
7160 }
7161 // Finally, if start > end, we strip away a prefix and
7162 // a suffix, to leave the list that sits <between> ens
7163 // and start, and then tag on the src list. AT least
7164 // that's my interpretation. We can get sublist to do
7165 // this for us. Note that one, or both of the indices
7166 // might have been negative.
7167 else
7168 {
7169 return dest.GetSublist(end + 1, start - 1) + src;
7170 }
7171 }
7172
7173 public void llLoadURL(string avatar_id, string message, string url)
7174 {
7175 m_host.AddScriptLPS(1);
7176 UUID avatarId = new UUID(avatar_id);
7177 m_ScriptEngine.World.SendUrlToUser(avatarId, m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message,
7178 url);
7179 // ScriptSleep(10000);
7180 }
7181
7182 public void llParcelMediaCommandList(LSL_List commandList)
7183 {
7184 //TO DO: Implement the missing commands
7185 //PARCEL_MEDIA_COMMAND_STOP Stop the media stream and go back to the first frame.
7186 //PARCEL_MEDIA_COMMAND_PAUSE Pause the media stream (stop playing but stay on current frame).
7187 //PARCEL_MEDIA_COMMAND_PLAY Start the media stream playing from the current frame and stop when the end is reached.
7188 //PARCEL_MEDIA_COMMAND_LOOP Start the media stream playing from the current frame. When the end is reached, loop to the beginning and continue.
7189 //PARCEL_MEDIA_COMMAND_TEXTURE key uuid Use this to get or set the parcel's media texture.
7190 //PARCEL_MEDIA_COMMAND_URL string url Used to get or set the parcel's media url.
7191 //PARCEL_MEDIA_COMMAND_TIME float time Move a media stream to a specific time.
7192 //PARCEL_MEDIA_COMMAND_AGENT key uuid Applies the media command to the specified agent only.
7193 //PARCEL_MEDIA_COMMAND_UNLOAD Completely unloads the movie and restores the original texture.
7194 //PARCEL_MEDIA_COMMAND_AUTO_ALIGN integer boolean Sets the parcel option 'Auto scale content'.
7195 //PARCEL_MEDIA_COMMAND_TYPE string mime_type Use this to get or set the parcel media MIME type (e.g. "text/html"). (1.19.1 RC0 or later)
7196 //PARCEL_MEDIA_COMMAND_SIZE integer x, integer y Use this to get or set the parcel media pixel resolution. (1.19.1 RC0 or later)
7197 //PARCEL_MEDIA_COMMAND_DESC string desc Use this to get or set the parcel media description. (1.19.1 RC0 or later)
7198 //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
7199 m_host.AddScriptLPS(1);
7200 for (int i = 0; i < commandList.Data.Length; i++)
7201 {
7202 switch ((ParcelMediaCommandEnum)commandList.Data[i])
7203 {
7204 case ParcelMediaCommandEnum.Play:
7205 List<ScenePresence> scenePresencePlayList = World.GetScenePresences();
7206 foreach (ScenePresence agent in scenePresencePlayList)
7207 {
7208 if (!agent.IsChildAgent)
7209 {
7210 agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Play, 0);
7211 }
7212 }
7213 break;
7214 case ParcelMediaCommandEnum.Stop:
7215 List<ScenePresence> scenePresenceStopList = World.GetScenePresences();
7216 foreach (ScenePresence agent in scenePresenceStopList)
7217 {
7218 if (!agent.IsChildAgent)
7219 {
7220 agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Stop, 0);
7221 }
7222 }
7223 break;
7224 case ParcelMediaCommandEnum.Pause:
7225 List<ScenePresence> scenePresencePauseList = World.GetScenePresences();
7226 foreach (ScenePresence agent in scenePresencePauseList)
7227 {
7228 if (!agent.IsChildAgent)
7229 {
7230 agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Pause, 0);
7231 }
7232 }
7233 break;
7234
7235 case ParcelMediaCommandEnum.Url:
7236 if ((i + 1) < commandList.Length)
7237 {
7238 if (commandList.Data[i + 1] is string)
7239 {
7240 UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
7241
7242 if (landowner == UUID.Zero)
7243 {
7244 return;
7245 }
7246
7247 if (landowner != m_host.ObjectOwner)
7248 {
7249 return;
7250 }
7251
7252 World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, (string)commandList.GetLSLStringItem(i + 1));
7253
7254 List<ScenePresence> scenePresenceList = World.GetScenePresences();
7255 LandData landData = World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
7256 //Send an update of the mediaURL to all the clients that are in the parcel
7257 foreach (ScenePresence agent in scenePresenceList)
7258 {
7259 if (!agent.IsChildAgent)
7260 {
7261 //Send parcel media update to the client
7262 agent.ControllingClient.SendParcelMediaUpdate(landData.MediaURL, landData.MediaID, landData.MediaAutoScale, "", landData.Description, 0, 0, 1);
7263 }
7264 }
7265
7266 }
7267 i++;
7268 }
7269 break;
7270 default:
7271 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
7272 NotImplemented("llParcelMediaCommandList parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType(), commandList.Data[i].ToString()).ToString());
7273 break;
7274 }//end switch
7275
7276 }
7277 // ScriptSleep(2000);
7278 }
7279
7280 public LSL_List llParcelMediaQuery(LSL_List aList)
7281 {
7282 m_host.AddScriptLPS(1);
7283 LSL_List list = new LSL_List();
7284 //TO DO: make the implementation for the missing commands
7285 //PARCEL_MEDIA_COMMAND_TEXTURE key uuid Use this to get or set the parcel's media texture.
7286 //PARCEL_MEDIA_COMMAND_URL string url Used to get or set the parcel's media url.
7287 //PARCEL_MEDIA_COMMAND_TYPE string mime_type Use this to get or set the parcel media MIME type (e.g. "text/html"). (1.19.1 RC0 or later)
7288 //PARCEL_MEDIA_COMMAND_SIZE integer x, integer y Use this to get or set the parcel media pixel resolution. (1.19.1 RC0 or later)
7289 //PARCEL_MEDIA_COMMAND_DESC string desc Use this to get or set the parcel media description. (1.19.1 RC0 or later)
7290 //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
7291 for (int i = 0; i < aList.Data.Length; i++)
7292 {
7293
7294 if (aList.Data[i] != null)
7295 {
7296 switch ((ParcelMediaCommandEnum) aList.Data[i])
7297 {
7298 case ParcelMediaCommandEnum.Url:
7299 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
7300 break;
7301 case ParcelMediaCommandEnum.Desc:
7302 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description));
7303 break;
7304 case ParcelMediaCommandEnum.Texture:
7305 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString()));
7306 break;
7307 default:
7308 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
7309 NotImplemented("llParcelMediaQuery parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString());
7310 break;
7311 }
7312
7313 }
7314 }
7315 // ScriptSleep(2000);
7316 return list;
7317 }
7318
7319 public LSL_Integer llModPow(int a, int b, int c)
7320 {
7321 m_host.AddScriptLPS(1);
7322 Int64 tmp = 0;
7323 Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp);
7324 // ScriptSleep(1000);
7325 return Convert.ToInt32(tmp);
7326 }
7327
7328 public LSL_Integer llGetInventoryType(string name)
7329 {
7330 m_host.AddScriptLPS(1);
7331 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
7332 {
7333 if (inv.Value.Name == name)
7334 {
7335 return inv.Value.InvType;
7336 }
7337 }
7338 return -1;
7339 }
7340
7341 public void llSetPayPrice(int price, LSL_List quick_pay_buttons)
7342 {
7343 m_host.AddScriptLPS(1);
7344
7345 if (quick_pay_buttons.Data.Length < 4)
7346 {
7347 LSLError("List must have at least 4 elements");
7348 return;
7349 }
7350 m_host.ParentGroup.RootPart.PayPrice[0]=price;
7351
7352 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0];
7353 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1];
7354 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2];
7355 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3];
7356 m_host.ParentGroup.HasGroupChanged = true;
7357 }
7358
7359 public LSL_Vector llGetCameraPos()
7360 {
7361 m_host.AddScriptLPS(1);
7362 UUID invItemID=InventorySelf();
7363 if (invItemID == UUID.Zero)
7364 return new LSL_Vector();
7365 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
7366 return new LSL_Vector();
7367 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
7368 {
7369 ShoutError("No permissions to track the camera");
7370 return new LSL_Vector();
7371 }
7372 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
7373 if (presence != null)
7374 {
7375 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
7376 return pos;
7377 }
7378 return new LSL_Vector();
7379 }
7380
7381 public LSL_Rotation llGetCameraRot()
7382 {
7383 m_host.AddScriptLPS(1);
7384 NotImplemented("llGetCameraRot");
7385 return new LSL_Rotation();
7386 }
7387
7388 public void llSetPrimURL()
7389 {
7390 m_host.AddScriptLPS(1);
7391 NotImplemented("llSetPrimURL");
7392 // ScriptSleep(2000);
7393 }
7394
7395 public void llRefreshPrimURL()
7396 {
7397 m_host.AddScriptLPS(1);
7398 NotImplemented("llRefreshPrimURL");
7399 // ScriptSleep(20000);
7400 }
7401
7402 public LSL_String llEscapeURL(string url)
7403 {
7404 m_host.AddScriptLPS(1);
7405 try
7406 {
7407 return Uri.EscapeUriString(url);
7408 }
7409 catch (Exception ex)
7410 {
7411 return "llEscapeURL: " + ex.ToString();
7412 }
7413 }
7414
7415 public LSL_String llUnescapeURL(string url)
7416 {
7417 m_host.AddScriptLPS(1);
7418 try
7419 {
7420 return Uri.UnescapeDataString(url);
7421 }
7422 catch (Exception ex)
7423 {
7424 return "llUnescapeURL: " + ex.ToString();
7425 }
7426 }
7427
7428 public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector look_at)
7429 {
7430 m_host.AddScriptLPS(1);
7431 NotImplemented("llMapDestination");
7432 // ScriptSleep(1000);
7433 }
7434
7435 public void llAddToLandBanList(string avatar, double hours)
7436 {
7437 m_host.AddScriptLPS(1);
7438 UUID key;
7439 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7440 if (land.OwnerID == m_host.OwnerID)
7441 {
7442 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
7443 if (UUID.TryParse(avatar, out key))
7444 {
7445 entry.AgentID = key;
7446 entry.Flags = ParcelManager.AccessList.Ban;
7447 entry.Time = DateTime.Now.AddHours(hours);
7448 land.ParcelAccessList.Add(entry);
7449 }
7450 }
7451 // ScriptSleep(100);
7452 }
7453
7454 public void llRemoveFromLandPassList(string avatar)
7455 {
7456 m_host.AddScriptLPS(1);
7457 UUID key;
7458 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7459 if (land.OwnerID == m_host.OwnerID)
7460 {
7461 if (UUID.TryParse(avatar, out key))
7462 {
7463 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
7464 {
7465 if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Access)
7466 {
7467 land.ParcelAccessList.Remove(entry);
7468 break;
7469 }
7470 }
7471 }
7472 }
7473 // ScriptSleep(100);
7474 }
7475
7476 public void llRemoveFromLandBanList(string avatar)
7477 {
7478 m_host.AddScriptLPS(1);
7479 UUID key;
7480 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7481 if (land.OwnerID == m_host.OwnerID)
7482 {
7483 if (UUID.TryParse(avatar, out key))
7484 {
7485 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
7486 {
7487 if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Ban)
7488 {
7489 land.ParcelAccessList.Remove(entry);
7490 break;
7491 }
7492 }
7493 }
7494 }
7495 // ScriptSleep(100);
7496 }
7497
7498 public void llSetCameraParams(LSL_List rules)
7499 {
7500 m_host.AddScriptLPS(1);
7501
7502 // our key in the object we are in
7503 UUID invItemID=InventorySelf();
7504 if (invItemID == UUID.Zero) return;
7505
7506 // the object we are in
7507 UUID objectID = m_host.ParentUUID;
7508 if (objectID == UUID.Zero) return;
7509
7510 // we need the permission first, to know which avatar we want to set the camera for
7511 UUID agentID = m_host.TaskInventory[invItemID].PermsGranter;
7512 if (agentID == UUID.Zero) return;
7513 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
7514
7515 ScenePresence presence = World.GetScenePresence(agentID);
7516
7517 // we are not interested in child-agents
7518 if (presence.IsChildAgent) return;
7519
7520 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
7521 object[] data = rules.Data;
7522 for (int i = 0; i < data.Length; ++i) {
7523 int type = Convert.ToInt32(data[i++].ToString());
7524 if (i >= data.Length) break; // odd number of entries => ignore the last
7525
7526 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
7527 switch (type) {
7528 case ScriptBaseClass.CAMERA_FOCUS:
7529 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
7530 case ScriptBaseClass.CAMERA_POSITION:
7531 LSL_Vector v = (LSL_Vector)data[i];
7532 parameters.Add(type + 1, (float)v.x);
7533 parameters.Add(type + 2, (float)v.y);
7534 parameters.Add(type + 3, (float)v.z);
7535 break;
7536 default:
7537 // TODO: clean that up as soon as the implicit casts are in
7538 if (data[i] is LSL_Float)
7539 parameters.Add(type, (float)((LSL_Float)data[i]).value);
7540 else if (data[i] is LSL_Integer)
7541 parameters.Add(type, (float)((LSL_Integer)data[i]).value);
7542 else parameters.Add(type, Convert.ToSingle(data[i]));
7543 break;
7544 }
7545 }
7546 if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters);
7547 }
7548
7549 public void llClearCameraParams()
7550 {
7551 m_host.AddScriptLPS(1);
7552
7553 // our key in the object we are in
7554 UUID invItemID=InventorySelf();
7555 if (invItemID == UUID.Zero) return;
7556
7557 // the object we are in
7558 UUID objectID = m_host.ParentUUID;
7559 if (objectID == UUID.Zero) return;
7560
7561 // we need the permission first, to know which avatar we want to clear the camera for
7562 UUID agentID = m_host.TaskInventory[invItemID].PermsGranter;
7563 if (agentID == UUID.Zero) return;
7564 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
7565
7566 ScenePresence presence = World.GetScenePresence(agentID);
7567
7568 // we are not interested in child-agents
7569 if (presence.IsChildAgent) return;
7570
7571 presence.ControllingClient.SendClearFollowCamProperties(objectID);
7572 }
7573
7574 public LSL_Float llListStatistics(int operation, LSL_List src)
7575 {
7576 m_host.AddScriptLPS(1);
7577 LSL_List nums = LSL_List.ToDoubleList(src);
7578 switch (operation)
7579 {
7580 case ScriptBaseClass.LIST_STAT_RANGE:
7581 return nums.Range();
7582 case ScriptBaseClass.LIST_STAT_MIN:
7583 return nums.Min();
7584 case ScriptBaseClass.LIST_STAT_MAX:
7585 return nums.Max();
7586 case ScriptBaseClass.LIST_STAT_MEAN:
7587 return nums.Mean();
7588 case ScriptBaseClass.LIST_STAT_MEDIAN:
7589 return nums.Median();
7590 case ScriptBaseClass.LIST_STAT_NUM_COUNT:
7591 return nums.NumericLength();
7592 case ScriptBaseClass.LIST_STAT_STD_DEV:
7593 return nums.StdDev();
7594 case ScriptBaseClass.LIST_STAT_SUM:
7595 return nums.Sum();
7596 case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
7597 return nums.SumSqrs();
7598 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
7599 return nums.GeometricMean();
7600 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
7601 return nums.HarmonicMean();
7602 default:
7603 return 0.0;
7604 }
7605 }
7606
7607 public LSL_Integer llGetUnixTime()
7608 {
7609 m_host.AddScriptLPS(1);
7610 return Util.UnixTimeSinceEpoch();
7611 }
7612
7613 public LSL_Integer llGetParcelFlags(LSL_Vector pos)
7614 {
7615 m_host.AddScriptLPS(1);
7616 return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).landData.Flags;
7617 }
7618
7619 public LSL_Integer llGetRegionFlags()
7620 {
7621 m_host.AddScriptLPS(1);
7622 IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
7623 if (estate == null)
7624 return 67108864;
7625 return (int)estate.GetRegionFlags();
7626 }
7627
7628 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
7629 {
7630 m_host.AddScriptLPS(1);
7631 string ret = String.Empty;
7632 string src1 = llBase64ToString(str1);
7633 string src2 = llBase64ToString(str2);
7634 int c = 0;
7635 for (int i = 0; i < src1.Length; i++)
7636 {
7637 ret += src1[i] ^ src2[c];
7638
7639 c++;
7640 if (c >= src2.Length)
7641 c = 0;
7642 }
7643 return llStringToBase64(ret);
7644 }
7645
7646 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
7647 {
7648 // Partial implementation: support for parameter flags needed
7649 // see http://wiki.secondlife.com/wiki/LlHTTPRequest
7650 // parameter flags support are implemented in ScriptsHttpRequests.cs
7651 // in StartHttpRequest
7652
7653 m_host.AddScriptLPS(1);
7654 IHttpRequests httpScriptMod =
7655 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
7656 List<string> param = new List<string>();
7657 foreach (object o in parameters.Data)
7658 {
7659 param.Add(o.ToString());
7660 }
7661
7662 Vector3 position = m_host.AbsolutePosition;
7663 Vector3 velocity = m_host.Velocity;
7664 Quaternion rotation = m_host.RotationOffset;
7665 ScenePresence scenePresence = World.GetScenePresence(m_host.ObjectOwner);
7666 RegionInfo regionInfo = World.RegionInfo;
7667
7668 Dictionary<string, string> httpHeaders = new Dictionary<string, string>();
7669
7670 httpHeaders["X-SecondLife-Shard"] = "OpenSim";
7671 httpHeaders["X-SecondLife-Object-Name"] = m_host.Name;
7672 httpHeaders["X-SecondLife-Object-Key"] = m_itemID.ToString();
7673 httpHeaders["X-SecondLife-Region"] = string.Format("{0} ({1}, {2})", regionInfo.RegionName, regionInfo.RegionLocX, regionInfo.RegionLocY);
7674 httpHeaders["X-SecondLife-Local-Position"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", position.X, position.Y, position.Z);
7675 httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z);
7676 httpHeaders["X-SecondLife-Local-Rotation"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})", rotation.X, rotation.Y, rotation.Z, rotation.W);
7677 httpHeaders["X-SecondLife-Owner-Name"] = scenePresence == null ? string.Empty : scenePresence.ControllingClient.Name;
7678 httpHeaders["X-SecondLife-Owner-Key"] = m_host.ObjectOwner.ToString();
7679
7680 UUID reqID = httpScriptMod.
7681 StartHttpRequest(m_localID, m_itemID, url, param, httpHeaders, body);
7682
7683 if (reqID != UUID.Zero)
7684 return reqID.ToString();
7685 else
7686 return null;
7687 }
7688
7689 public void llResetLandBanList()
7690 {
7691 m_host.AddScriptLPS(1);
7692 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7693 if (land.OwnerID == m_host.OwnerID)
7694 {
7695 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
7696 {
7697 if (entry.Flags == ParcelManager.AccessList.Ban)
7698 {
7699 land.ParcelAccessList.Remove(entry);
7700 }
7701 }
7702 }
7703 // ScriptSleep(100);
7704 }
7705
7706 public void llResetLandPassList()
7707 {
7708 m_host.AddScriptLPS(1);
7709 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
7710 if (land.OwnerID == m_host.OwnerID)
7711 {
7712 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
7713 {
7714 if (entry.Flags == ParcelManager.AccessList.Access)
7715 {
7716 land.ParcelAccessList.Remove(entry);
7717 }
7718 }
7719 }
7720 // ScriptSleep(100);
7721 }
7722
7723 public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide)
7724 {
7725 m_host.AddScriptLPS(1);
7726
7727 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
7728
7729 if (land == null)
7730 {
7731 return 0;
7732 }
7733
7734 else
7735 {
7736 if (sim_wide == 1)
7737 {
7738 if (category == 0)
7739 {
7740 return land.SimwidePrims;
7741 }
7742
7743 else
7744 {
7745 //public int simwideArea = 0;
7746 return 0;
7747 }
7748 }
7749
7750 else
7751 {
7752 if (category == 0)//Total Prims
7753 {
7754 return 0;//land.
7755 }
7756
7757 else if (category == 1)//Owner Prims
7758 {
7759 return land.OwnerPrims;
7760 }
7761
7762 else if (category == 2)//Group Prims
7763 {
7764 return land.GroupPrims;
7765 }
7766
7767 else if (category == 3)//Other Prims
7768 {
7769 return land.OtherPrims;
7770 }
7771
7772 else if (category == 4)//Selected
7773 {
7774 return land.SelectedPrims;
7775 }
7776
7777 else if (category == 5)//Temp
7778 {
7779 return 0;//land.
7780 }
7781 }
7782 }
7783 return 0;
7784 }
7785
7786 public LSL_List llGetParcelPrimOwners(LSL_Vector pos)
7787 {
7788 m_host.AddScriptLPS(1);
7789 LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
7790 LSL_List ret = new LSL_List();
7791 if (land != null)
7792 {
7793 foreach (KeyValuePair<UUID, int> d in land.getLandObjectOwners())
7794 {
7795 ret.Add(d.Key.ToString());
7796 ret.Add(d.Value);
7797 }
7798 }
7799 // ScriptSleep(2000);
7800 return ret;
7801 }
7802
7803 public LSL_Integer llGetObjectPrimCount(string object_id)
7804 {
7805 m_host.AddScriptLPS(1);
7806 SceneObjectPart part = World.GetSceneObjectPart(new UUID(object_id));
7807 if (part == null)
7808 {
7809 return 0;
7810 }
7811 else
7812 {
7813 return part.ParentGroup.Children.Count;
7814 }
7815 }
7816
7817 public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide)
7818 {
7819 m_host.AddScriptLPS(1);
7820 // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation
7821 // Which probably will be irrelevent in OpenSim....
7822 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
7823
7824 float bonusfactor = (float)World.RegionInfo.RegionSettings.ObjectBonus;
7825
7826 if (land == null)
7827 {
7828 return 0;
7829 }
7830
7831 if (sim_wide == 1)
7832 {
7833 decimal v = land.SimwideArea * (decimal)(0.22) * (decimal)bonusfactor;
7834
7835 return (int)v;
7836 }
7837
7838 else
7839 {
7840 decimal v = land.Area * (decimal)(0.22) * (decimal)bonusfactor;
7841
7842 return (int)v;
7843 }
7844
7845 }
7846
7847 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param)
7848 {
7849 m_host.AddScriptLPS(1);
7850 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
7851 if (land == null)
7852 {
7853 return new LSL_List(0);
7854 }
7855 LSL_List ret = new LSL_List();
7856 foreach (object o in param.Data)
7857 {
7858 switch (o.ToString())
7859 {
7860 case "0":
7861 ret = ret + new LSL_List(land.Name);
7862 break;
7863 case "1":
7864 ret = ret + new LSL_List(land.Description);
7865 break;
7866 case "2":
7867 ret = ret + new LSL_List(land.OwnerID.ToString());
7868 break;
7869 case "3":
7870 ret = ret + new LSL_List(land.GroupID.ToString());
7871 break;
7872 case "4":
7873 ret = ret + new LSL_List(land.Area);
7874 break;
7875 default:
7876 ret = ret + new LSL_List(0);
7877 break;
7878 }
7879 }
7880 return ret;
7881 }
7882
7883 public void llSetLinkTexture(int linknumber, string texture, int face)
7884 {
7885 m_host.AddScriptLPS(1);
7886
7887 if (m_host.ParentGroup == null)
7888 return;
7889
7890 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber);
7891
7892 if (part == null)
7893 return;
7894
7895 SetTexture(part, texture, face);
7896 // ScriptSleep(200);
7897 }
7898
7899 public LSL_String llStringTrim(string src, int type)
7900 {
7901 m_host.AddScriptLPS(1);
7902 if (type == (int)ScriptBaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); }
7903 if (type == (int)ScriptBaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); }
7904 if (type == (int)ScriptBaseClass.STRING_TRIM) { return src.Trim(); }
7905 return src;
7906 }
7907
7908 public LSL_List llGetObjectDetails(string id, LSL_List args)
7909 {
7910 m_host.AddScriptLPS(1);
7911 LSL_List ret = new LSL_List();
7912 UUID key = new UUID();
7913 if (UUID.TryParse(id, out key))
7914 {
7915 ScenePresence av = World.GetScenePresence(key);
7916
7917 if (av != null)
7918 {
7919 foreach (object o in args.Data)
7920 {
7921 switch (o.ToString())
7922 {
7923 case "1":
7924 ret.Add(av.Firstname + " " + av.Lastname);
7925 break;
7926 case "2":
7927 ret.Add("");
7928 break;
7929 case "3":
7930 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z));
7931 break;
7932 case "4":
7933 ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W));
7934 break;
7935 case "5":
7936 ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z));
7937 break;
7938 case "6":
7939 ret.Add(id);
7940 break;
7941 case "7":
7942 ret.Add(UUID.Zero.ToString());
7943 break;
7944 case "8":
7945 ret.Add(UUID.Zero.ToString());
7946 break;
7947 }
7948 }
7949 return ret;
7950 }
7951 SceneObjectPart obj = World.GetSceneObjectPart(key);
7952 if (obj != null)
7953 {
7954 foreach (object o in args.Data)
7955 {
7956 switch (o.ToString())
7957 {
7958 case "1":
7959 ret.Add(obj.Name);
7960 break;
7961 case "2":
7962 ret.Add(obj.Description);
7963 break;
7964 case "3":
7965 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z));
7966 break;
7967 case "4":
7968 ret.Add(new LSL_Rotation(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W));
7969 break;
7970 case "5":
7971 ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z));
7972 break;
7973 case "6":
7974 ret.Add(obj.OwnerID.ToString());
7975 break;
7976 case "7":
7977 ret.Add(obj.GroupID.ToString());
7978 break;
7979 case "8":
7980 ret.Add(obj.CreatorID.ToString());
7981 break;
7982 }
7983 }
7984 return ret;
7985 }
7986 }
7987 return new LSL_List();
7988 }
7989
7990
7991 internal UUID ScriptByName(string name)
7992 {
7993 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
7994 {
7995 if (item.Type == 10 && item.Name == name)
7996 return item.ItemID;
7997 }
7998 return UUID.Zero;
7999 }
8000
8001 internal void ShoutError(string msg)
8002 {
8003 llShout(ScriptBaseClass.DEBUG_CHANNEL, msg);
8004 }
8005
8006 internal void NotImplemented(string command)
8007 {
8008 if (throwErrorOnNotImplemented)
8009 throw new NotImplementedException("Command not implemented: " + command);
8010 }
8011
8012 internal void Deprecated(string command)
8013 {
8014 throw new Exception("Command deprecated: " + command);
8015 }
8016
8017 internal void LSLError(string msg)
8018 {
8019 throw new Exception("LSL Runtime Error: " + msg);
8020 }
8021
8022 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset);
8023 private void WithNotecard(UUID assetID, AssetRequestCallback cb)
8024 {
8025 World.AssetCache.GetAsset(assetID, delegate(UUID i, AssetBase a) { cb(i, a); }, false);
8026 }
8027
8028 public LSL_String llGetNumberOfNotecardLines(string name)
8029 {
8030 m_host.AddScriptLPS(1);
8031
8032 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
8033 {
8034 if (item.Type == 7 && item.Name == name)
8035 {
8036 UUID tid = AsyncCommands.
8037 DataserverPlugin.RegisterRequest(m_localID,
8038 m_itemID, item.AssetID.ToString());
8039 if (NotecardCache.IsCached(item.AssetID))
8040 {
8041 AsyncCommands.
8042 DataserverPlugin.DataserverReply(item.AssetID.ToString(),
8043 NotecardCache.GetLines(item.AssetID).ToString());
8044 // ScriptSleep(100);
8045 return tid.ToString();
8046 }
8047 WithNotecard(item.AssetID, delegate (UUID id, AssetBase a)
8048 {
8049 System.Text.ASCIIEncoding enc =
8050 new System.Text.ASCIIEncoding();
8051 string data = enc.GetString(a.Data);
8052 //Console.WriteLine(data);
8053 NotecardCache.Cache(id, data);
8054 AsyncCommands.
8055 DataserverPlugin.DataserverReply(id.ToString(),
8056 NotecardCache.GetLines(id).ToString());
8057 });
8058 // ScriptSleep(100);
8059 return tid.ToString();
8060 }
8061 }
8062 // if we got to here, we didn't find the notecard the script was asking for
8063 // => complain loudly, as specified by the LSL docs
8064 ShoutError("Notecard '" + name + "' could not be found.");
8065
8066 // ScriptSleep(100);
8067 return UUID.Zero.ToString();
8068 }
8069
8070 public LSL_String llGetNotecardLine(string name, int line)
8071 {
8072 m_host.AddScriptLPS(1);
8073
8074 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
8075 {
8076 if (item.Type == 7 && item.Name == name)
8077 {
8078 UUID tid = AsyncCommands.
8079 DataserverPlugin.RegisterRequest(m_localID,
8080 m_itemID, item.AssetID.ToString());
8081
8082 if (NotecardCache.IsCached(item.AssetID))
8083 {
8084 AsyncCommands.
8085 DataserverPlugin.DataserverReply(item.AssetID.ToString(),
8086 NotecardCache.GetLine(item.AssetID, line));
8087 // ScriptSleep(100);
8088 return tid.ToString();
8089 }
8090
8091 WithNotecard(item.AssetID, delegate (UUID id, AssetBase a)
8092 {
8093 System.Text.ASCIIEncoding enc =
8094 new System.Text.ASCIIEncoding();
8095 string data = enc.GetString(a.Data);
8096 //Console.WriteLine(data);
8097 NotecardCache.Cache(id, data);
8098 AsyncCommands.
8099 DataserverPlugin.DataserverReply(id.ToString(),
8100 NotecardCache.GetLine(id, line));
8101 });
8102
8103 // ScriptSleep(100);
8104 return tid.ToString();
8105 }
8106 }
8107
8108 // if we got to here, we didn't find the notecard the script was asking for
8109 // => complain loudly, as specified by the LSL docs
8110 ShoutError("Notecard '" + name + "' could not be found.");
8111
8112 // ScriptSleep(100);
8113 return UUID.Zero.ToString();
8114 }
8115
8116 }
8117
8118 public class NotecardCache
8119 {
8120 private class Notecard
8121 {
8122 public string[] text;
8123 public DateTime lastRef;
8124 }
8125
8126 private static Dictionary<UUID, Notecard> m_Notecards =
8127 new Dictionary<UUID, Notecard>();
8128
8129 public static void Cache(UUID assetID, string text)
8130 {
8131 CacheCheck();
8132
8133 lock (m_Notecards)
8134 {
8135 if (m_Notecards.ContainsKey(assetID))
8136 return;
8137
8138 Notecard nc = new Notecard();
8139 nc.lastRef = DateTime.Now;
8140 nc.text = ParseText(text.Replace("\r", "").Split('\n'));
8141 m_Notecards[assetID] = nc;
8142 }
8143 }
8144
8145 private static string[] ParseText(string[] input)
8146 {
8147 int idx = 0;
8148 int level = 0;
8149 List<string> output = new List<string>();
8150 string[] words;
8151
8152 while (idx < input.Length)
8153 {
8154 if (input[idx] == "{")
8155 {
8156 level++;
8157 idx++;
8158 continue;
8159 }
8160
8161 if (input[idx]== "}")
8162 {
8163 level--;
8164 idx++;
8165 continue;
8166 }
8167
8168 switch (level)
8169 {
8170 case 0:
8171 words = input[idx].Split(' '); // Linden text ver
8172 // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard)
8173 if (words.Length < 3)
8174 return new String[0];
8175
8176 int version = int.Parse(words[3]);
8177 if (version != 2)
8178 return new String[0];
8179 break;
8180 case 1:
8181 words = input[idx].Split(' ');
8182 if (words[0] == "LLEmbeddedItems")
8183 break;
8184 if (words[0] == "Text")
8185 {
8186 int len = int.Parse(words[2]);
8187 idx++;
8188
8189 int count = -1;
8190
8191 while (count < len)
8192 {
8193 // int l = input[idx].Length;
8194 string ln = input[idx];
8195
8196 int need = len-count-1;
8197 if (ln.Length > need)
8198 ln = ln.Substring(0, need);
8199
8200 output.Add(ln);
8201 count += ln.Length + 1;
8202 idx++;
8203 }
8204
8205 return output.ToArray();
8206 }
8207 break;
8208 case 2:
8209 words = input[idx].Split(' '); // count
8210 if (words[0] == "count")
8211 {
8212 int c = int.Parse(words[1]);
8213 if (c > 0)
8214 return new String[0];
8215 break;
8216 }
8217 break;
8218 }
8219 idx++;
8220 }
8221 return output.ToArray();
8222 }
8223
8224 public static bool IsCached(UUID assetID)
8225 {
8226 lock (m_Notecards)
8227 {
8228 return m_Notecards.ContainsKey(assetID);
8229 }
8230 }
8231
8232 public static int GetLines(UUID assetID)
8233 {
8234 if (!IsCached(assetID))
8235 return -1;
8236
8237 lock (m_Notecards)
8238 {
8239 m_Notecards[assetID].lastRef = DateTime.Now;
8240 return m_Notecards[assetID].text.Length;
8241 }
8242 }
8243
8244 public static string GetLine(UUID assetID, int line)
8245 {
8246 if (line < 0)
8247 return "";
8248
8249 string data;
8250
8251 if (!IsCached(assetID))
8252 return "";
8253
8254 lock (m_Notecards)
8255 {
8256 m_Notecards[assetID].lastRef = DateTime.Now;
8257
8258 if (line >= m_Notecards[assetID].text.Length)
8259 return "\n\n\n";
8260
8261 data = m_Notecards[assetID].text[line];
8262 if (data.Length > 255)
8263 data = data.Substring(0, 255);
8264
8265 return data;
8266 }
8267 }
8268
8269 public static void CacheCheck()
8270 {
8271 foreach (UUID key in new List<UUID>(m_Notecards.Keys))
8272 {
8273 Notecard nc = m_Notecards[key];
8274 if (nc.lastRef.AddSeconds(30) < DateTime.Now)
8275 m_Notecards.Remove(key);
8276 }
8277 }
8278 }
8279}