aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs3003
1 files changed, 2049 insertions, 954 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 2eba2b1..ba02a78 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -28,10 +28,12 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode]
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using System.Text; 33using System.Text;
33using System.Threading; 34using System.Threading;
34using System.Text.RegularExpressions; 35using System.Text.RegularExpressions;
36using System.Timers;
35using Nini.Config; 37using Nini.Config;
36using log4net; 38using log4net;
37using OpenMetaverse; 39using OpenMetaverse;
@@ -44,6 +46,7 @@ using OpenSim.Region.CoreModules.World.Land;
44using OpenSim.Region.CoreModules.World.Terrain; 46using OpenSim.Region.CoreModules.World.Terrain;
45using OpenSim.Region.Framework.Interfaces; 47using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Framework.Scenes.Serialization;
47using OpenSim.Region.Framework.Scenes.Animation; 50using OpenSim.Region.Framework.Scenes.Animation;
48using OpenSim.Region.Physics.Manager; 51using OpenSim.Region.Physics.Manager;
49using OpenSim.Region.ScriptEngine.Shared; 52using OpenSim.Region.ScriptEngine.Shared;
@@ -65,6 +68,7 @@ using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
65using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 68using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
66using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; 69using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
67using System.Reflection; 70using System.Reflection;
71using Timer = System.Timers.Timer;
68 72
69namespace OpenSim.Region.ScriptEngine.Shared.Api 73namespace OpenSim.Region.ScriptEngine.Shared.Api
70{ 74{
@@ -99,16 +103,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
99 protected int m_notecardLineReadCharsMax = 255; 103 protected int m_notecardLineReadCharsMax = 255;
100 protected int m_scriptConsoleChannel = 0; 104 protected int m_scriptConsoleChannel = 0;
101 protected bool m_scriptConsoleChannelEnabled = false; 105 protected bool m_scriptConsoleChannelEnabled = false;
106 protected bool m_debuggerSafe = false;
102 protected IUrlModule m_UrlModule = null; 107 protected IUrlModule m_UrlModule = null;
103 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 108 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
104 new Dictionary<UUID, UserInfoCacheEntry>(); 109 new Dictionary<UUID, UserInfoCacheEntry>();
105 110
111 protected Timer m_ShoutSayTimer;
112 protected int m_SayShoutCount = 0;
113
106 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 114 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
107 { 115 {
116 m_ShoutSayTimer = new Timer(1000);
117 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
118 m_ShoutSayTimer.AutoReset = true;
119 m_ShoutSayTimer.Start();
120
108 m_ScriptEngine = ScriptEngine; 121 m_ScriptEngine = ScriptEngine;
109 m_host = host; 122 m_host = host;
110 m_localID = localID; 123 m_localID = localID;
111 m_itemID = itemID; 124 m_itemID = itemID;
125 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
112 126
113 m_ScriptDelayFactor = 127 m_ScriptDelayFactor =
114 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 128 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
@@ -156,6 +170,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
156 get { return m_ScriptEngine.World; } 170 get { return m_ScriptEngine.World; }
157 } 171 }
158 172
173 [DebuggerNonUserCode]
159 public void state(string newState) 174 public void state(string newState)
160 { 175 {
161 m_ScriptEngine.SetState(m_itemID, newState); 176 m_ScriptEngine.SetState(m_itemID, newState);
@@ -165,6 +180,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
165 /// Reset the named script. The script must be present 180 /// Reset the named script. The script must be present
166 /// in the same prim. 181 /// in the same prim.
167 /// </summary> 182 /// </summary>
183 [DebuggerNonUserCode]
168 public void llResetScript() 184 public void llResetScript()
169 { 185 {
170 m_host.AddScriptLPS(1); 186 m_host.AddScriptLPS(1);
@@ -221,9 +237,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
221 } 237 }
222 } 238 }
223 239
240 public List<ScenePresence> GetLinkAvatars(int linkType)
241 {
242 List<ScenePresence> ret = new List<ScenePresence>();
243 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
244 return ret;
245
246 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
247
248 switch (linkType)
249 {
250 case ScriptBaseClass.LINK_SET:
251 return avs;
252
253 case ScriptBaseClass.LINK_ROOT:
254 return ret;
255
256 case ScriptBaseClass.LINK_ALL_OTHERS:
257 return avs;
258
259 case ScriptBaseClass.LINK_ALL_CHILDREN:
260 return avs;
261
262 case ScriptBaseClass.LINK_THIS:
263 return ret;
264
265 default:
266 if (linkType < 0)
267 return ret;
268
269 int partCount = m_host.ParentGroup.GetPartCount();
270
271 if (linkType <= partCount)
272 {
273 return ret;
274 }
275 else
276 {
277 linkType = linkType - partCount;
278 if (linkType > avs.Count)
279 {
280 return ret;
281 }
282 else
283 {
284 ret.Add(avs[linkType-1]);
285 return ret;
286 }
287 }
288 }
289 }
290
224 public List<SceneObjectPart> GetLinkParts(int linkType) 291 public List<SceneObjectPart> GetLinkParts(int linkType)
225 { 292 {
226 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 293 List<SceneObjectPart> ret = new List<SceneObjectPart>();
294 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
295 return ret;
227 ret.Add(m_host); 296 ret.Add(m_host);
228 297
229 switch (linkType) 298 switch (linkType)
@@ -270,40 +339,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
270 protected UUID InventorySelf() 339 protected UUID InventorySelf()
271 { 340 {
272 UUID invItemID = new UUID(); 341 UUID invItemID = new UUID();
273 342 bool unlock = false;
274 lock (m_host.TaskInventory) 343 if (!m_host.TaskInventory.IsReadLockedByMe())
275 { 344 {
276 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 345 m_host.TaskInventory.LockItemsForRead(true);
346 unlock = true;
347 }
348 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
349 {
350 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
277 { 351 {
278 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) 352 invItemID = inv.Key;
279 { 353 break;
280 invItemID = inv.Key;
281 break;
282 }
283 } 354 }
284 } 355 }
285 356 if (unlock)
357 {
358 m_host.TaskInventory.LockItemsForRead(false);
359 }
286 return invItemID; 360 return invItemID;
287 } 361 }
288 362
289 protected UUID InventoryKey(string name, int type) 363 protected UUID InventoryKey(string name, int type)
290 { 364 {
291 m_host.AddScriptLPS(1); 365 m_host.AddScriptLPS(1);
292 366 m_host.TaskInventory.LockItemsForRead(true);
293 lock (m_host.TaskInventory) 367
368 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
294 { 369 {
295 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 370 if (inv.Value.Name == name)
296 { 371 {
297 if (inv.Value.Name == name) 372 m_host.TaskInventory.LockItemsForRead(false);
373
374 if (inv.Value.Type != type)
298 { 375 {
299 if (inv.Value.Type != type) 376 return UUID.Zero;
300 return UUID.Zero;
301
302 return inv.Value.AssetID;
303 } 377 }
378
379 return inv.Value.AssetID;
304 } 380 }
305 } 381 }
306 382
383 m_host.TaskInventory.LockItemsForRead(false);
307 return UUID.Zero; 384 return UUID.Zero;
308 } 385 }
309 386
@@ -311,17 +388,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
311 { 388 {
312 m_host.AddScriptLPS(1); 389 m_host.AddScriptLPS(1);
313 390
314 lock (m_host.TaskInventory) 391
392 m_host.TaskInventory.LockItemsForRead(true);
393
394 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
315 { 395 {
316 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 396 if (inv.Value.Name == name)
317 { 397 {
318 if (inv.Value.Name == name) 398 m_host.TaskInventory.LockItemsForRead(false);
319 { 399 return inv.Value.AssetID;
320 return inv.Value.AssetID;
321 }
322 } 400 }
323 } 401 }
324 402
403 m_host.TaskInventory.LockItemsForRead(false);
404
405
325 return UUID.Zero; 406 return UUID.Zero;
326 } 407 }
327 408
@@ -463,31 +544,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
463 544
464 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 545 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
465 546
466 /// <summary> 547 // Utility function for llRot2Euler
467 /// Convert an LSL rotation to a Euler vector. 548
468 /// </summary> 549 // normalize an angle between -PI and PI (-180 to +180 degrees)
469 /// <remarks> 550 protected double NormalizeAngle(double angle)
470 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
471 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
472 /// </remarks>
473 /// <param name="r"></param>
474 /// <returns></returns>
475 public LSL_Vector llRot2Euler(LSL_Rotation r)
476 { 551 {
477 m_host.AddScriptLPS(1); 552 if (angle > -Math.PI && angle < Math.PI)
553 return angle;
554
555 int numPis = (int)(Math.PI / angle);
556 double remainder = angle - Math.PI * numPis;
557 if (numPis % 2 == 1)
558 return Math.PI - angle;
559 return remainder;
560 }
478 561
479 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 562 public LSL_Vector llRot2Euler(LSL_Rotation q1)
480 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 563 {
481 if (m == 0.0) return new LSL_Vector(); 564 m_host.AddScriptLPS(1);
482 double x = Math.Atan2(-v.y, v.z); 565 LSL_Vector eul = new LSL_Vector();
483 double sin = v.x / m;
484 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities.
485 double y = Math.Asin(sin);
486 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
487 v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0)));
488 double z = Math.Atan2(v.y, v.x);
489 566
490 return new LSL_Vector(x, y, z); 567 double sqw = q1.s*q1.s;
568 double sqx = q1.x*q1.x;
569 double sqy = q1.z*q1.z;
570 double sqz = q1.y*q1.y;
571 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
572 double test = q1.x*q1.z + q1.y*q1.s;
573 if (test > 0.4999*unit) { // singularity at north pole
574 eul.z = 2 * Math.Atan2(q1.x,q1.s);
575 eul.y = Math.PI/2;
576 eul.x = 0;
577 return eul;
578 }
579 if (test < -0.4999*unit) { // singularity at south pole
580 eul.z = -2 * Math.Atan2(q1.x,q1.s);
581 eul.y = -Math.PI/2;
582 eul.x = 0;
583 return eul;
584 }
585 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
586 eul.y = Math.Asin(2*test/unit);
587 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
588 return eul;
491 } 589 }
492 590
493 /* From wiki: 591 /* From wiki:
@@ -689,77 +787,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
689 { 787 {
690 //A and B should both be normalized 788 //A and B should both be normalized
691 m_host.AddScriptLPS(1); 789 m_host.AddScriptLPS(1);
692 LSL_Rotation rotBetween; 790 /* This method is more accurate than the SL one, and thus causes problems
693 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 791 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
694 // continue calculation. 792
695 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 793 double dotProduct = LSL_Vector.Dot(a, b);
794 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
795 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
796 double angle = Math.Acos(dotProduct / magProduct);
797 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
798 double s = Math.Sin(angle / 2);
799
800 double x = axis.x * s;
801 double y = axis.y * s;
802 double z = axis.z * s;
803 double w = Math.Cos(angle / 2);
804
805 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
806 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
807
808 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
809 */
810
811 // This method mimics the 180 errors found in SL
812 // See www.euclideanspace.com... angleBetween
813 LSL_Vector vec_a = a;
814 LSL_Vector vec_b = b;
815
816 // Eliminate zero length
817 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
818 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
819 if (vec_a_mag < 0.00001 ||
820 vec_b_mag < 0.00001)
696 { 821 {
697 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 822 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
698 } 823 }
699 else 824
825 // Normalize
826 vec_a = llVecNorm(vec_a);
827 vec_b = llVecNorm(vec_b);
828
829 // Calculate axis and rotation angle
830 LSL_Vector axis = vec_a % vec_b;
831 LSL_Float cos_theta = vec_a * vec_b;
832
833 // Check if parallel
834 if (cos_theta > 0.99999)
700 { 835 {
701 a = LSL_Vector.Norm(a); 836 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
702 b = LSL_Vector.Norm(b); 837 }
703 double dotProduct = LSL_Vector.Dot(a, b); 838
704 // There are two degenerate cases possible. These are for vectors 180 or 839 // Check if anti-parallel
705 // 0 degrees apart. These have to be detected and handled individually. 840 else if (cos_theta < -0.99999)
706 // 841 {
707 // Check for vectors 180 degrees apart. 842 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
708 // A dot product of -1 would mean the angle between vectors is 180 degrees. 843 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
709 if (dotProduct < -0.9999999f) 844 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
710 { 845 }
711 // First assume X axis is orthogonal to the vectors. 846 else // other rotation
712 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 847 {
713 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 848 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
714 // Check for near zero vector. A very small non-zero number here will create 849 axis = llVecNorm(axis);
715 // a rotation in an undesired direction. 850 double x, y, z, s, t;
716 if (LSL_Vector.Mag(orthoVector) > 0.0001) 851 s = Math.Cos(theta);
717 { 852 t = Math.Sin(theta);
718 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 853 x = axis.x * t;
719 } 854 y = axis.y * t;
720 // If the magnitude of the vector was near zero, then assume the X axis is not 855 z = axis.z * t;
721 // orthogonal and use the Z axis instead. 856 return new LSL_Rotation(x,y,z,s);
722 else
723 {
724 // Set 180 z rotation.
725 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
726 }
727 }
728 // Check for parallel vectors.
729 // A dot product of 1 would mean the angle between vectors is 0 degrees.
730 else if (dotProduct > 0.9999999f)
731 {
732 // Set zero rotation.
733 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
734 }
735 else
736 {
737 // All special checks have been performed so get the axis of rotation.
738 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
739 // Quarternion s value is the length of the unit vector + dot product.
740 double qs = 1.0 + dotProduct;
741 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
742 // Normalize the rotation.
743 double mag = LSL_Rotation.Mag(rotBetween);
744 // We shouldn't have to worry about a divide by zero here. The qs value will be
745 // non-zero because we already know if we're here, then the dotProduct is not -1 so
746 // qs will not be zero. Also, we've already handled the input vectors being zero so the
747 // crossProduct vector should also not be zero.
748 rotBetween.x = rotBetween.x / mag;
749 rotBetween.y = rotBetween.y / mag;
750 rotBetween.z = rotBetween.z / mag;
751 rotBetween.s = rotBetween.s / mag;
752 // Check for undefined values and set zero rotation if any found. This code might not actually be required
753 // any longer since zero vectors are checked for at the top.
754 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
755 {
756 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
757 }
758 }
759 } 857 }
760 return rotBetween;
761 } 858 }
762 859
763 public void llWhisper(int channelID, string text) 860 public void llWhisper(int channelID, string text)
764 { 861 {
765 m_host.AddScriptLPS(1); 862 m_host.AddScriptLPS(1);
@@ -779,6 +876,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
779 { 876 {
780 m_host.AddScriptLPS(1); 877 m_host.AddScriptLPS(1);
781 878
879 if (channelID == 0)
880 m_SayShoutCount++;
881
882 if (m_SayShoutCount >= 11)
883 ScriptSleep(2000);
884
782 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 885 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
783 { 886 {
784 Console.WriteLine(text); 887 Console.WriteLine(text);
@@ -801,6 +904,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
801 { 904 {
802 m_host.AddScriptLPS(1); 905 m_host.AddScriptLPS(1);
803 906
907 if (channelID == 0)
908 m_SayShoutCount++;
909
910 if (m_SayShoutCount >= 11)
911 ScriptSleep(2000);
912
804 if (text.Length > 1023) 913 if (text.Length > 1023)
805 text = text.Substring(0, 1023); 914 text = text.Substring(0, 1023);
806 915
@@ -1101,10 +1210,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1101 return detectedParams.TouchUV; 1210 return detectedParams.TouchUV;
1102 } 1211 }
1103 1212
1213 [DebuggerNonUserCode]
1104 public virtual void llDie() 1214 public virtual void llDie()
1105 { 1215 {
1106 m_host.AddScriptLPS(1); 1216 m_host.AddScriptLPS(1);
1107 throw new SelfDeleteException(); 1217 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1108 } 1218 }
1109 1219
1110 public LSL_Float llGround(LSL_Vector offset) 1220 public LSL_Float llGround(LSL_Vector offset)
@@ -1177,6 +1287,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1177 1287
1178 public void llSetStatus(int status, int value) 1288 public void llSetStatus(int status, int value)
1179 { 1289 {
1290 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1291 return;
1180 m_host.AddScriptLPS(1); 1292 m_host.AddScriptLPS(1);
1181 1293
1182 int statusrotationaxis = 0; 1294 int statusrotationaxis = 0;
@@ -1406,6 +1518,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1406 { 1518 {
1407 m_host.AddScriptLPS(1); 1519 m_host.AddScriptLPS(1);
1408 1520
1521 SetColor(m_host, color, face);
1522 }
1523
1524 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1525 {
1526 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1527 return;
1528
1529 Primitive.TextureEntry tex = part.Shape.Textures;
1530 Color4 texcolor;
1531 if (face >= 0 && face < GetNumberOfSides(part))
1532 {
1533 texcolor = tex.CreateFace((uint)face).RGBA;
1534 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1535 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1536 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1537 tex.FaceTextures[face].RGBA = texcolor;
1538 part.UpdateTextureEntry(tex.GetBytes());
1539 return;
1540 }
1541 else if (face == ScriptBaseClass.ALL_SIDES)
1542 {
1543 for (uint i = 0; i < GetNumberOfSides(part); i++)
1544 {
1545 if (tex.FaceTextures[i] != null)
1546 {
1547 texcolor = tex.FaceTextures[i].RGBA;
1548 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1549 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1550 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1551 tex.FaceTextures[i].RGBA = texcolor;
1552 }
1553 texcolor = tex.DefaultTexture.RGBA;
1554 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1555 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1556 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1557 tex.DefaultTexture.RGBA = texcolor;
1558 }
1559 part.UpdateTextureEntry(tex.GetBytes());
1560 return;
1561 }
1562
1409 if (face == ScriptBaseClass.ALL_SIDES) 1563 if (face == ScriptBaseClass.ALL_SIDES)
1410 face = SceneObjectPart.ALL_SIDES; 1564 face = SceneObjectPart.ALL_SIDES;
1411 1565
@@ -1414,6 +1568,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1414 1568
1415 public void SetTexGen(SceneObjectPart part, int face,int style) 1569 public void SetTexGen(SceneObjectPart part, int face,int style)
1416 { 1570 {
1571 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1572 return;
1573
1417 Primitive.TextureEntry tex = part.Shape.Textures; 1574 Primitive.TextureEntry tex = part.Shape.Textures;
1418 MappingType textype; 1575 MappingType textype;
1419 textype = MappingType.Default; 1576 textype = MappingType.Default;
@@ -1444,6 +1601,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1444 1601
1445 public void SetGlow(SceneObjectPart part, int face, float glow) 1602 public void SetGlow(SceneObjectPart part, int face, float glow)
1446 { 1603 {
1604 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1605 return;
1606
1447 Primitive.TextureEntry tex = part.Shape.Textures; 1607 Primitive.TextureEntry tex = part.Shape.Textures;
1448 if (face >= 0 && face < GetNumberOfSides(part)) 1608 if (face >= 0 && face < GetNumberOfSides(part))
1449 { 1609 {
@@ -1469,6 +1629,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1469 1629
1470 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1630 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1471 { 1631 {
1632 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1633 return;
1472 1634
1473 Shininess sval = new Shininess(); 1635 Shininess sval = new Shininess();
1474 1636
@@ -1519,6 +1681,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1519 1681
1520 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1682 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1521 { 1683 {
1684 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1685 return;
1686
1522 Primitive.TextureEntry tex = part.Shape.Textures; 1687 Primitive.TextureEntry tex = part.Shape.Textures;
1523 if (face >= 0 && face < GetNumberOfSides(part)) 1688 if (face >= 0 && face < GetNumberOfSides(part))
1524 { 1689 {
@@ -1579,13 +1744,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1579 m_host.AddScriptLPS(1); 1744 m_host.AddScriptLPS(1);
1580 1745
1581 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1746 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1582 1747 if (parts.Count > 0)
1583 foreach (SceneObjectPart part in parts) 1748 {
1584 SetAlpha(part, alpha, face); 1749 try
1750 {
1751 parts[0].ParentGroup.areUpdatesSuspended = true;
1752 foreach (SceneObjectPart part in parts)
1753 SetAlpha(part, alpha, face);
1754 }
1755 finally
1756 {
1757 parts[0].ParentGroup.areUpdatesSuspended = false;
1758 }
1759 }
1585 } 1760 }
1586 1761
1587 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1762 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1588 { 1763 {
1764 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1765 return;
1766
1589 Primitive.TextureEntry tex = part.Shape.Textures; 1767 Primitive.TextureEntry tex = part.Shape.Textures;
1590 Color4 texcolor; 1768 Color4 texcolor;
1591 if (face >= 0 && face < GetNumberOfSides(part)) 1769 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1638,7 +1816,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1638 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1816 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1639 float wind, float tension, LSL_Vector Force) 1817 float wind, float tension, LSL_Vector Force)
1640 { 1818 {
1641 if (part == null) 1819 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1642 return; 1820 return;
1643 1821
1644 if (flexi) 1822 if (flexi)
@@ -1672,7 +1850,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1672 /// <param name="falloff"></param> 1850 /// <param name="falloff"></param>
1673 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1851 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1674 { 1852 {
1675 if (part == null) 1853 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1676 return; 1854 return;
1677 1855
1678 if (light) 1856 if (light)
@@ -1749,15 +1927,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1749 m_host.AddScriptLPS(1); 1927 m_host.AddScriptLPS(1);
1750 1928
1751 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1929 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1752 1930 if (parts.Count > 0)
1753 foreach (SceneObjectPart part in parts) 1931 {
1754 SetTexture(part, texture, face); 1932 try
1755 1933 {
1934 parts[0].ParentGroup.areUpdatesSuspended = true;
1935 foreach (SceneObjectPart part in parts)
1936 SetTexture(part, texture, face);
1937 }
1938 finally
1939 {
1940 parts[0].ParentGroup.areUpdatesSuspended = false;
1941 }
1942 }
1756 ScriptSleep(200); 1943 ScriptSleep(200);
1757 } 1944 }
1758 1945
1759 protected void SetTexture(SceneObjectPart part, string texture, int face) 1946 protected void SetTexture(SceneObjectPart part, string texture, int face)
1760 { 1947 {
1948 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1949 return;
1950
1761 UUID textureID = new UUID(); 1951 UUID textureID = new UUID();
1762 1952
1763 textureID = InventoryKey(texture, (int)AssetType.Texture); 1953 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1802,6 +1992,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1802 1992
1803 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 1993 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1804 { 1994 {
1995 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1996 return;
1997
1805 Primitive.TextureEntry tex = part.Shape.Textures; 1998 Primitive.TextureEntry tex = part.Shape.Textures;
1806 if (face >= 0 && face < GetNumberOfSides(part)) 1999 if (face >= 0 && face < GetNumberOfSides(part))
1807 { 2000 {
@@ -1838,6 +2031,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1838 2031
1839 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2032 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1840 { 2033 {
2034 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2035 return;
2036
1841 Primitive.TextureEntry tex = part.Shape.Textures; 2037 Primitive.TextureEntry tex = part.Shape.Textures;
1842 if (face >= 0 && face < GetNumberOfSides(part)) 2038 if (face >= 0 && face < GetNumberOfSides(part))
1843 { 2039 {
@@ -1874,6 +2070,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1874 2070
1875 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2071 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1876 { 2072 {
2073 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2074 return;
2075
1877 Primitive.TextureEntry tex = part.Shape.Textures; 2076 Primitive.TextureEntry tex = part.Shape.Textures;
1878 if (face >= 0 && face < GetNumberOfSides(part)) 2077 if (face >= 0 && face < GetNumberOfSides(part))
1879 { 2078 {
@@ -1978,26 +2177,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1978 return real_vec; 2177 return real_vec;
1979 } 2178 }
1980 2179
2180 public LSL_Integer llSetRegionPos(LSL_Vector pos)
2181 {
2182 return new LSL_Integer(SetRegionPos(m_host, pos));
2183 }
2184
2185 protected int SetRegionPos(SceneObjectPart part, LSL_Vector targetPos)
2186 {
2187 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2188 return 0;
2189
2190 SceneObjectGroup grp = part.ParentGroup;
2191
2192 if (grp.IsAttachment)
2193 return 0;
2194
2195 if (grp.RootPart.PhysActor != null && grp.RootPart.PhysActor.IsPhysical)
2196 return 0;
2197
2198 if (targetPos.x < -10.0f || targetPos.x >= (float)Constants.RegionSize || targetPos.y < -10.0f || targetPos.y >= (float)Constants.RegionSize || targetPos.z < 0 || targetPos.z >= 4096.0f)
2199 return 0;
2200
2201 float constrainedX = (float)targetPos.x;
2202 float constrainedY = (float)targetPos.y;
2203
2204 if (constrainedX < 0.0f)
2205 constrainedX = 0.0f;
2206 if (constrainedY < 0.0f)
2207 constrainedY = 0.0f;
2208 if (constrainedX >= (float)Constants.RegionSize)
2209 constrainedX = (float)Constants.RegionSize - 0.1f;
2210 if (constrainedY >= (float)Constants.RegionSize)
2211 constrainedY = (float)Constants.RegionSize -0.1f;
2212
2213 float ground = World.GetGroundHeight(constrainedX, constrainedY);
2214
2215 if (targetPos.z < ground)
2216 targetPos.z = ground;
2217
2218 Vector3 dest = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z);
2219
2220 if (!World.Permissions.CanObjectEntry(grp.UUID, false, dest))
2221 return 0;
2222
2223 grp.UpdateGroupPosition(dest);
2224
2225 return 1;
2226 }
2227
1981 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2228 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1982 { 2229 {
1983 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2230 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2231 return;
2232
1984 LSL_Vector currentPos = GetPartLocalPos(part); 2233 LSL_Vector currentPos = GetPartLocalPos(part);
2234 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
1985 2235
1986 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
1987 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
1988 2236
1989 if (part.ParentGroup.RootPart == part) 2237 if (part.ParentGroup.RootPart == part)
1990 { 2238 {
1991 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
1992 targetPos.z = ground;
1993 SceneObjectGroup parent = part.ParentGroup; 2239 SceneObjectGroup parent = part.ParentGroup;
1994 LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); 2240 Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
1995 parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z)); 2241 if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest))
2242 return;
2243 Util.FireAndForget(delegate(object x) {
2244 parent.UpdateGroupPosition(dest);
2245 });
1996 } 2246 }
1997 else 2247 else
1998 { 2248 {
1999 LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); 2249 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
2000 part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z);
2001 SceneObjectGroup parent = part.ParentGroup; 2250 SceneObjectGroup parent = part.ParentGroup;
2002 parent.HasGroupChanged = true; 2251 parent.HasGroupChanged = true;
2003 parent.ScheduleGroupForTerseUpdate(); 2252 parent.ScheduleGroupForTerseUpdate();
@@ -2028,11 +2277,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2028 } 2277 }
2029 else 2278 else
2030 { 2279 {
2031 if (m_host.IsRoot) 2280 if (part.IsRoot)
2032 { 2281 {
2033 return new LSL_Vector(m_host.AttachedPos.X, 2282 return new LSL_Vector(part.AttachedPos.X,
2034 m_host.AttachedPos.Y, 2283 part.AttachedPos.Y,
2035 m_host.AttachedPos.Z); 2284 part.AttachedPos.Z);
2036 } 2285 }
2037 else 2286 else
2038 { 2287 {
@@ -2048,9 +2297,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2048 m_host.AddScriptLPS(1); 2297 m_host.AddScriptLPS(1);
2049 2298
2050 // try to let this work as in SL... 2299 // try to let this work as in SL...
2051 if (m_host.ParentID == 0) 2300 if (m_host.LinkNum < 2)
2052 { 2301 {
2053 // special case: If we are root, rotate complete SOG to new rotation 2302 // Special case: If we are root, rotate complete SOG to new
2303 // rotation.
2304 // We are root if the link number is 0 (single prim) or 1
2305 // (root prim). ParentID may be nonzero in attachments and
2306 // using it would cause attachments and HUDs to rotate
2307 // to the wrong positions.
2054 SetRot(m_host, Rot2Quaternion(rot)); 2308 SetRot(m_host, Rot2Quaternion(rot));
2055 } 2309 }
2056 else 2310 else
@@ -2075,6 +2329,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2075 2329
2076 protected void SetRot(SceneObjectPart part, Quaternion rot) 2330 protected void SetRot(SceneObjectPart part, Quaternion rot)
2077 { 2331 {
2332 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2333 return;
2334
2078 part.UpdateRotation(rot); 2335 part.UpdateRotation(rot);
2079 // Update rotation does not move the object in the physics scene if it's a linkset. 2336 // Update rotation does not move the object in the physics scene if it's a linkset.
2080 2337
@@ -2698,12 +2955,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2698 2955
2699 m_host.AddScriptLPS(1); 2956 m_host.AddScriptLPS(1);
2700 2957
2958 m_host.TaskInventory.LockItemsForRead(true);
2701 TaskInventoryItem item = m_host.TaskInventory[invItemID]; 2959 TaskInventoryItem item = m_host.TaskInventory[invItemID];
2702 2960 m_host.TaskInventory.LockItemsForRead(false);
2703 lock (m_host.TaskInventory)
2704 {
2705 item = m_host.TaskInventory[invItemID];
2706 }
2707 2961
2708 if (item.PermsGranter == UUID.Zero) 2962 if (item.PermsGranter == UUID.Zero)
2709 return 0; 2963 return 0;
@@ -2771,64 +3025,69 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2771 { 3025 {
2772 m_host.AddScriptLPS(1); 3026 m_host.AddScriptLPS(1);
2773 3027
2774 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) 3028 Util.FireAndForget(delegate (object x)
2775 return; 3029 {
2776 float dist = (float)llVecDist(llGetPos(), pos); 3030 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
3031 return;
3032 float dist = (float)llVecDist(llGetPos(), pos);
2777 3033
2778 if (dist > m_ScriptDistanceFactor * 10.0f) 3034 if (dist > m_ScriptDistanceFactor * 10.0f)
2779 return; 3035 return;
2780 3036
2781 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 3037 //Clone is thread-safe
3038 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
2782 3039
2783 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory) 3040 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
2784 {
2785 if (inv.Value.Name == inventory)
2786 { 3041 {
2787 // make sure we're an object. 3042 if (inv.Value.Name == inventory)
2788 if (inv.Value.InvType != (int)InventoryType.Object)
2789 { 3043 {
2790 llSay(0, "Unable to create requested object. Object is missing from database."); 3044 // make sure we're an object.
2791 return; 3045 if (inv.Value.InvType != (int)InventoryType.Object)
2792 } 3046 {
3047 llSay(0, "Unable to create requested object. Object is missing from database.");
3048 return;
3049 }
2793 3050
2794 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); 3051 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
2795 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); 3052 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z);
2796 3053
2797 // need the magnitude later 3054 // need the magnitude later
2798 float velmag = (float)Util.GetMagnitude(llvel); 3055 // float velmag = (float)Util.GetMagnitude(llvel);
2799 3056
2800 SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, Rot2Quaternion(rot), llvel, param); 3057 SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, Rot2Quaternion(rot), llvel, param);
2801 3058
2802 // If either of these are null, then there was an unknown error. 3059 // If either of these are null, then there was an unknown error.
2803 if (new_group == null) 3060 if (new_group == null)
2804 continue; 3061 continue;
2805 3062
2806 // objects rezzed with this method are die_at_edge by default. 3063 // objects rezzed with this method are die_at_edge by default.
2807 new_group.RootPart.SetDieAtEdge(true); 3064 new_group.RootPart.SetDieAtEdge(true);
2808 3065
2809 new_group.ResumeScripts(); 3066 new_group.ResumeScripts();
2810 3067
2811 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 3068 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
2812 "object_rez", new Object[] { 3069 "object_rez", new Object[] {
2813 new LSL_String( 3070 new LSL_String(
2814 new_group.RootPart.UUID.ToString()) }, 3071 new_group.RootPart.UUID.ToString()) },
2815 new DetectParams[0])); 3072 new DetectParams[0]));
2816 3073
2817 float groupmass = new_group.GetMass(); 3074 float groupmass = new_group.GetMass();
2818 3075
2819 if (new_group.RootPart.PhysActor != null && new_group.RootPart.PhysActor.IsPhysical && llvel != Vector3.Zero) 3076 if (new_group.RootPart.PhysActor != null && new_group.RootPart.PhysActor.IsPhysical && llvel != Vector3.Zero)
2820 { 3077 {
2821 //Recoil. 3078 //Recoil.
2822 llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); 3079 llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0);
3080 }
3081 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3082 return;
2823 } 3083 }
2824 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
2825 ScriptSleep((int)((groupmass * velmag) / 10));
2826 ScriptSleep(100);
2827 return;
2828 } 3084 }
2829 }
2830 3085
2831 llSay(0, "Could not find object " + inventory); 3086 llSay(0, "Could not find object " + inventory);
3087 });
3088
3089 //ScriptSleep((int)((groupmass * velmag) / 10));
3090 ScriptSleep(100);
2832 } 3091 }
2833 3092
2834 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) 3093 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
@@ -2839,34 +3098,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2839 public void llLookAt(LSL_Vector target, double strength, double damping) 3098 public void llLookAt(LSL_Vector target, double strength, double damping)
2840 { 3099 {
2841 m_host.AddScriptLPS(1); 3100 m_host.AddScriptLPS(1);
2842 // Determine where we are looking from
2843 LSL_Vector from = llGetPos();
2844 3101
2845 // Work out the normalised vector from the source to the target 3102 // Get the normalized vector to the target
2846 LSL_Vector delta = llVecNorm(target - from); 3103 LSL_Vector d1 = llVecNorm(target - llGetPos());
2847 LSL_Vector angle = new LSL_Vector(0,0,0);
2848 3104
2849 // Calculate the yaw 3105 // Get the bearing (yaw)
2850 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3106 LSL_Vector a1 = new LSL_Vector(0,0,0);
2851 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3107 a1.z = llAtan2(d1.y, d1.x);
2852 3108
2853 // Calculate pitch 3109 // Get the elevation (pitch)
2854 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3110 LSL_Vector a2 = new LSL_Vector(0,0,0);
3111 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2855 3112
2856 // we need to convert from a vector describing 3113 LSL_Rotation r1 = llEuler2Rot(a1);
2857 // the angles of rotation in radians into rotation value 3114 LSL_Rotation r2 = llEuler2Rot(a2);
3115 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2858 3116
2859 LSL_Rotation rot = llEuler2Rot(angle); 3117 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2860
2861 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2862 // set the rotation of the object, copy that behavior
2863 if (strength == 0 || m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2864 { 3118 {
2865 llSetRot(rot); 3119 // Do nothing if either value is 0 (this has been checked in SL)
3120 if (strength <= 0.0 || damping <= 0.0)
3121 return;
3122
3123 llSetRot(r3 * r2 * r1);
2866 } 3124 }
2867 else 3125 else
2868 { 3126 {
2869 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3127 if (strength == 0)
3128 {
3129 llSetRot(r3 * r2 * r1);
3130 return;
3131 }
3132
3133 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2870 } 3134 }
2871 } 3135 }
2872 3136
@@ -2916,13 +3180,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2916 { 3180 {
2917 TaskInventoryItem item; 3181 TaskInventoryItem item;
2918 3182
2919 lock (m_host.TaskInventory) 3183 m_host.TaskInventory.LockItemsForRead(true);
3184 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2920 { 3185 {
2921 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3186 m_host.TaskInventory.LockItemsForRead(false);
2922 return; 3187 return;
2923 else
2924 item = m_host.TaskInventory[InventorySelf()];
2925 } 3188 }
3189 else
3190 {
3191 item = m_host.TaskInventory[InventorySelf()];
3192 }
3193 m_host.TaskInventory.LockItemsForRead(false);
2926 3194
2927 if (item.PermsGranter != UUID.Zero) 3195 if (item.PermsGranter != UUID.Zero)
2928 { 3196 {
@@ -2944,13 +3212,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2944 { 3212 {
2945 TaskInventoryItem item; 3213 TaskInventoryItem item;
2946 3214
3215 m_host.TaskInventory.LockItemsForRead(true);
2947 lock (m_host.TaskInventory) 3216 lock (m_host.TaskInventory)
2948 { 3217 {
3218
2949 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3219 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3220 {
3221 m_host.TaskInventory.LockItemsForRead(false);
2950 return; 3222 return;
3223 }
2951 else 3224 else
3225 {
2952 item = m_host.TaskInventory[InventorySelf()]; 3226 item = m_host.TaskInventory[InventorySelf()];
3227 }
2953 } 3228 }
3229 m_host.TaskInventory.LockItemsForRead(false);
2954 3230
2955 m_host.AddScriptLPS(1); 3231 m_host.AddScriptLPS(1);
2956 3232
@@ -2982,18 +3258,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2982 { 3258 {
2983 m_host.AddScriptLPS(1); 3259 m_host.AddScriptLPS(1);
2984 3260
2985// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
2986// return;
2987
2988 TaskInventoryItem item; 3261 TaskInventoryItem item;
2989 3262
2990 lock (m_host.TaskInventory) 3263 m_host.TaskInventory.LockItemsForRead(true);
3264
3265 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2991 { 3266 {
2992 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3267 m_host.TaskInventory.LockItemsForRead(false);
2993 return; 3268 return;
2994 else
2995 item = m_host.TaskInventory[InventorySelf()];
2996 } 3269 }
3270 else
3271 {
3272 item = m_host.TaskInventory[InventorySelf()];
3273 }
3274
3275 m_host.TaskInventory.LockItemsForRead(false);
2997 3276
2998 if (item.PermsGranter != m_host.OwnerID) 3277 if (item.PermsGranter != m_host.OwnerID)
2999 return; 3278 return;
@@ -3019,13 +3298,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3019 3298
3020 TaskInventoryItem item; 3299 TaskInventoryItem item;
3021 3300
3022 lock (m_host.TaskInventory) 3301 m_host.TaskInventory.LockItemsForRead(true);
3302
3303 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3023 { 3304 {
3024 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3305 m_host.TaskInventory.LockItemsForRead(false);
3025 return; 3306 return;
3026 else
3027 item = m_host.TaskInventory[InventorySelf()];
3028 } 3307 }
3308 else
3309 {
3310 item = m_host.TaskInventory[InventorySelf()];
3311 }
3312 m_host.TaskInventory.LockItemsForRead(false);
3313
3029 3314
3030 if (item.PermsGranter != m_host.OwnerID) 3315 if (item.PermsGranter != m_host.OwnerID)
3031 return; 3316 return;
@@ -3072,6 +3357,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3072 3357
3073 public void llInstantMessage(string user, string message) 3358 public void llInstantMessage(string user, string message)
3074 { 3359 {
3360 UUID result;
3361 if (!UUID.TryParse(user, out result))
3362 {
3363 ShoutError("An invalid key was passed to llInstantMessage");
3364 ScriptSleep(2000);
3365 return;
3366 }
3367
3368
3075 m_host.AddScriptLPS(1); 3369 m_host.AddScriptLPS(1);
3076 3370
3077 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3371 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3086,14 +3380,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3086 UUID friendTransactionID = UUID.Random(); 3380 UUID friendTransactionID = UUID.Random();
3087 3381
3088 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3382 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3089 3383
3090 GridInstantMessage msg = new GridInstantMessage(); 3384 GridInstantMessage msg = new GridInstantMessage();
3091 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3385 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3092 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3386 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3093 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3387 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3094// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3388// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3095// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3389// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3096 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3390// DateTime dt = DateTime.UtcNow;
3391//
3392// // Ticks from UtcNow, but make it look like local. Evil, huh?
3393// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3394//
3395// try
3396// {
3397// // Convert that to the PST timezone
3398// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3399// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3400// }
3401// catch
3402// {
3403// // No logging here, as it could be VERY spammy
3404// }
3405//
3406// // And make it look local again to fool the unix time util
3407// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3408
3409 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3410
3097 //if (client != null) 3411 //if (client != null)
3098 //{ 3412 //{
3099 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3413 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3107,12 +3421,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3107 msg.message = message.Substring(0, 1024); 3421 msg.message = message.Substring(0, 1024);
3108 else 3422 else
3109 msg.message = message; 3423 msg.message = message;
3110 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3424 msg.dialog = (byte)19; // MessageFromObject
3111 msg.fromGroup = false;// fromGroup; 3425 msg.fromGroup = false;// fromGroup;
3112 msg.offline = (byte)0; //offline; 3426 msg.offline = (byte)0; //offline;
3113 msg.ParentEstateID = 0; //ParentEstateID; 3427 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3114 msg.Position = new Vector3(m_host.AbsolutePosition); 3428 msg.Position = new Vector3(m_host.AbsolutePosition);
3115 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3429 msg.RegionID = World.RegionInfo.RegionID.Guid;
3116 msg.binaryBucket 3430 msg.binaryBucket
3117 = Util.StringToBytes256( 3431 = Util.StringToBytes256(
3118 "{0}/{1}/{2}/{3}", 3432 "{0}/{1}/{2}/{3}",
@@ -3140,7 +3454,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3140 } 3454 }
3141 3455
3142 emailModule.SendEmail(m_host.UUID, address, subject, message); 3456 emailModule.SendEmail(m_host.UUID, address, subject, message);
3143 ScriptSleep(20000); 3457 ScriptSleep(15000);
3144 } 3458 }
3145 3459
3146 public void llGetNextEmail(string address, string subject) 3460 public void llGetNextEmail(string address, string subject)
@@ -3279,14 +3593,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3279 3593
3280 TaskInventoryItem item; 3594 TaskInventoryItem item;
3281 3595
3282 lock (m_host.TaskInventory) 3596 m_host.TaskInventory.LockItemsForRead(true);
3597 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3283 { 3598 {
3284 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3599 m_host.TaskInventory.LockItemsForRead(false);
3285 return; 3600 return;
3286 else
3287 item = m_host.TaskInventory[InventorySelf()];
3288 } 3601 }
3289 3602 else
3603 {
3604 item = m_host.TaskInventory[InventorySelf()];
3605 }
3606 m_host.TaskInventory.LockItemsForRead(false);
3290 if (item.PermsGranter == UUID.Zero) 3607 if (item.PermsGranter == UUID.Zero)
3291 return; 3608 return;
3292 3609
@@ -3316,13 +3633,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3316 3633
3317 TaskInventoryItem item; 3634 TaskInventoryItem item;
3318 3635
3319 lock (m_host.TaskInventory) 3636 m_host.TaskInventory.LockItemsForRead(true);
3637 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3320 { 3638 {
3321 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3639 m_host.TaskInventory.LockItemsForRead(false);
3322 return; 3640 return;
3323 else 3641 }
3324 item = m_host.TaskInventory[InventorySelf()]; 3642 else
3643 {
3644 item = m_host.TaskInventory[InventorySelf()];
3325 } 3645 }
3646 m_host.TaskInventory.LockItemsForRead(false);
3647
3326 3648
3327 if (item.PermsGranter == UUID.Zero) 3649 if (item.PermsGranter == UUID.Zero)
3328 return; 3650 return;
@@ -3389,10 +3711,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3389 3711
3390 TaskInventoryItem item; 3712 TaskInventoryItem item;
3391 3713
3392 lock (m_host.TaskInventory) 3714
3715 m_host.TaskInventory.LockItemsForRead(true);
3716 if (!m_host.TaskInventory.ContainsKey(invItemID))
3717 {
3718 m_host.TaskInventory.LockItemsForRead(false);
3719 return;
3720 }
3721 else
3393 { 3722 {
3394 item = m_host.TaskInventory[invItemID]; 3723 item = m_host.TaskInventory[invItemID];
3395 } 3724 }
3725 m_host.TaskInventory.LockItemsForRead(false);
3396 3726
3397 if (agentID == UUID.Zero || perm == 0) // Releasing permissions 3727 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
3398 { 3728 {
@@ -3420,15 +3750,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3420 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3750 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3421 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3751 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3422 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3752 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3753 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3423 ScriptBaseClass.PERMISSION_ATTACH; 3754 ScriptBaseClass.PERMISSION_ATTACH;
3424 3755
3425 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3756 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3426 { 3757 {
3427 lock (m_host.TaskInventory) 3758 m_host.TaskInventory.LockItemsForWrite(true);
3428 { 3759 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3429 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3760 m_host.TaskInventory[invItemID].PermsMask = perm;
3430 m_host.TaskInventory[invItemID].PermsMask = perm; 3761 m_host.TaskInventory.LockItemsForWrite(false);
3431 }
3432 3762
3433 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3763 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3434 "run_time_permissions", new Object[] { 3764 "run_time_permissions", new Object[] {
@@ -3438,28 +3768,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3438 return; 3768 return;
3439 } 3769 }
3440 } 3770 }
3441 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3771 else
3442 { 3772 {
3443 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3773 bool sitting = false;
3444 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3774 if (m_host.SitTargetAvatar == agentID)
3445 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3775 {
3446 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3776 sitting = true;
3447 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3777 }
3778 else
3779 {
3780 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3781 {
3782 if (p.SitTargetAvatar == agentID)
3783 sitting = true;
3784 }
3785 }
3448 3786
3449 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3787 if (sitting)
3450 { 3788 {
3451 lock (m_host.TaskInventory) 3789 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3790 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3791 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3792 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3793 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3794
3795 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3452 { 3796 {
3797 m_host.TaskInventory.LockItemsForWrite(true);
3453 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3798 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3454 m_host.TaskInventory[invItemID].PermsMask = perm; 3799 m_host.TaskInventory[invItemID].PermsMask = perm;
3455 } 3800 m_host.TaskInventory.LockItemsForWrite(false);
3456 3801
3457 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3802 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3458 "run_time_permissions", new Object[] { 3803 "run_time_permissions", new Object[] {
3459 new LSL_Integer(perm) }, 3804 new LSL_Integer(perm) },
3460 new DetectParams[0])); 3805 new DetectParams[0]));
3461 3806
3462 return; 3807 return;
3808 }
3463 } 3809 }
3464 } 3810 }
3465 3811
@@ -3473,11 +3819,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3473 3819
3474 if (!m_waitingForScriptAnswer) 3820 if (!m_waitingForScriptAnswer)
3475 { 3821 {
3476 lock (m_host.TaskInventory) 3822 m_host.TaskInventory.LockItemsForWrite(true);
3477 { 3823 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3478 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3824 m_host.TaskInventory[invItemID].PermsMask = 0;
3479 m_host.TaskInventory[invItemID].PermsMask = 0; 3825 m_host.TaskInventory.LockItemsForWrite(false);
3480 }
3481 3826
3482 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3827 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3483 m_waitingForScriptAnswer=true; 3828 m_waitingForScriptAnswer=true;
@@ -3512,10 +3857,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3512 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3857 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3513 llReleaseControls(); 3858 llReleaseControls();
3514 3859
3515 lock (m_host.TaskInventory) 3860
3516 { 3861 m_host.TaskInventory.LockItemsForWrite(true);
3517 m_host.TaskInventory[invItemID].PermsMask = answer; 3862 m_host.TaskInventory[invItemID].PermsMask = answer;
3518 } 3863 m_host.TaskInventory.LockItemsForWrite(false);
3864
3519 3865
3520 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3866 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3521 "run_time_permissions", new Object[] { 3867 "run_time_permissions", new Object[] {
@@ -3527,16 +3873,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3527 { 3873 {
3528 m_host.AddScriptLPS(1); 3874 m_host.AddScriptLPS(1);
3529 3875
3530 lock (m_host.TaskInventory) 3876 m_host.TaskInventory.LockItemsForRead(true);
3877
3878 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3531 { 3879 {
3532 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3880 if (item.Type == 10 && item.ItemID == m_itemID)
3533 { 3881 {
3534 if (item.Type == 10 && item.ItemID == m_itemID) 3882 m_host.TaskInventory.LockItemsForRead(false);
3535 { 3883 return item.PermsGranter.ToString();
3536 return item.PermsGranter.ToString();
3537 }
3538 } 3884 }
3539 } 3885 }
3886 m_host.TaskInventory.LockItemsForRead(false);
3540 3887
3541 return UUID.Zero.ToString(); 3888 return UUID.Zero.ToString();
3542 } 3889 }
@@ -3545,19 +3892,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3545 { 3892 {
3546 m_host.AddScriptLPS(1); 3893 m_host.AddScriptLPS(1);
3547 3894
3548 lock (m_host.TaskInventory) 3895 m_host.TaskInventory.LockItemsForRead(true);
3896
3897 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3549 { 3898 {
3550 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3899 if (item.Type == 10 && item.ItemID == m_itemID)
3551 { 3900 {
3552 if (item.Type == 10 && item.ItemID == m_itemID) 3901 int perms = item.PermsMask;
3553 { 3902 if (m_automaticLinkPermission)
3554 int perms = item.PermsMask; 3903 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
3555 if (m_automaticLinkPermission) 3904 m_host.TaskInventory.LockItemsForRead(false);
3556 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 3905 return perms;
3557 return perms;
3558 }
3559 } 3906 }
3560 } 3907 }
3908 m_host.TaskInventory.LockItemsForRead(false);
3561 3909
3562 return 0; 3910 return 0;
3563 } 3911 }
@@ -3579,9 +3927,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3579 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3927 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3580 { 3928 {
3581 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3929 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3582 3930 if (parts.Count > 0)
3583 foreach (SceneObjectPart part in parts) 3931 {
3584 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3932 try
3933 {
3934 parts[0].ParentGroup.areUpdatesSuspended = true;
3935 foreach (SceneObjectPart part in parts)
3936 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3937 }
3938 finally
3939 {
3940 parts[0].ParentGroup.areUpdatesSuspended = false;
3941 }
3942 }
3585 } 3943 }
3586 3944
3587 public void llCreateLink(string target, int parent) 3945 public void llCreateLink(string target, int parent)
@@ -3594,11 +3952,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3594 return; 3952 return;
3595 3953
3596 TaskInventoryItem item; 3954 TaskInventoryItem item;
3597 lock (m_host.TaskInventory) 3955 m_host.TaskInventory.LockItemsForRead(true);
3598 { 3956 item = m_host.TaskInventory[invItemID];
3599 item = m_host.TaskInventory[invItemID]; 3957 m_host.TaskInventory.LockItemsForRead(false);
3600 } 3958
3601
3602 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3959 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3603 && !m_automaticLinkPermission) 3960 && !m_automaticLinkPermission)
3604 { 3961 {
@@ -3615,11 +3972,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3615 3972
3616 if (targetPart.ParentGroup.AttachmentPoint != 0) 3973 if (targetPart.ParentGroup.AttachmentPoint != 0)
3617 return; // Fail silently if attached 3974 return; // Fail silently if attached
3975
3976 if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID)
3977 return;
3978
3618 SceneObjectGroup parentPrim = null, childPrim = null; 3979 SceneObjectGroup parentPrim = null, childPrim = null;
3619 3980
3620 if (targetPart != null) 3981 if (targetPart != null)
3621 { 3982 {
3622 if (parent != 0) { 3983 if (parent != 0)
3984 {
3623 parentPrim = m_host.ParentGroup; 3985 parentPrim = m_host.ParentGroup;
3624 childPrim = targetPart.ParentGroup; 3986 childPrim = targetPart.ParentGroup;
3625 } 3987 }
@@ -3631,7 +3993,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3631 3993
3632 // Required for linking 3994 // Required for linking
3633 childPrim.RootPart.ClearUpdateSchedule(); 3995 childPrim.RootPart.ClearUpdateSchedule();
3634 parentPrim.LinkToGroup(childPrim); 3996 parentPrim.LinkToGroup(childPrim, true);
3635 } 3997 }
3636 3998
3637 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3999 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3650,16 +4012,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3650 m_host.AddScriptLPS(1); 4012 m_host.AddScriptLPS(1);
3651 UUID invItemID = InventorySelf(); 4013 UUID invItemID = InventorySelf();
3652 4014
3653 lock (m_host.TaskInventory) 4015 m_host.TaskInventory.LockItemsForRead(true);
3654 {
3655 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 4016 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3656 && !m_automaticLinkPermission) 4017 && !m_automaticLinkPermission)
3657 { 4018 {
3658 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 4019 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4020 m_host.TaskInventory.LockItemsForRead(false);
3659 return; 4021 return;
3660 } 4022 }
3661 } 4023 m_host.TaskInventory.LockItemsForRead(false);
3662 4024
3663 if (linknum < ScriptBaseClass.LINK_THIS) 4025 if (linknum < ScriptBaseClass.LINK_THIS)
3664 return; 4026 return;
3665 4027
@@ -3698,10 +4060,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3698 // Restructuring Multiple Prims. 4060 // Restructuring Multiple Prims.
3699 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4061 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3700 parts.Remove(parentPrim.RootPart); 4062 parts.Remove(parentPrim.RootPart);
3701 foreach (SceneObjectPart part in parts) 4063 if (parts.Count > 0)
3702 { 4064 {
3703 parentPrim.DelinkFromGroup(part.LocalId, true); 4065 try
4066 {
4067 parts[0].ParentGroup.areUpdatesSuspended = true;
4068 foreach (SceneObjectPart part in parts)
4069 {
4070 parentPrim.DelinkFromGroup(part.LocalId, true);
4071 }
4072 }
4073 finally
4074 {
4075 parts[0].ParentGroup.areUpdatesSuspended = false;
4076 }
3704 } 4077 }
4078
3705 parentPrim.HasGroupChanged = true; 4079 parentPrim.HasGroupChanged = true;
3706 parentPrim.ScheduleGroupForFullUpdate(); 4080 parentPrim.ScheduleGroupForFullUpdate();
3707 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4081 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3710,12 +4084,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3710 { 4084 {
3711 SceneObjectPart newRoot = parts[0]; 4085 SceneObjectPart newRoot = parts[0];
3712 parts.Remove(newRoot); 4086 parts.Remove(newRoot);
3713 foreach (SceneObjectPart part in parts) 4087
4088 try
3714 { 4089 {
3715 // Required for linking 4090 parts[0].ParentGroup.areUpdatesSuspended = true;
3716 part.ClearUpdateSchedule(); 4091 foreach (SceneObjectPart part in parts)
3717 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4092 {
4093 part.ClearUpdateSchedule();
4094 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4095 }
3718 } 4096 }
4097 finally
4098 {
4099 parts[0].ParentGroup.areUpdatesSuspended = false;
4100 }
4101
4102
3719 newRoot.ParentGroup.HasGroupChanged = true; 4103 newRoot.ParentGroup.HasGroupChanged = true;
3720 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4104 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3721 } 4105 }
@@ -3735,6 +4119,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3735 public void llBreakAllLinks() 4119 public void llBreakAllLinks()
3736 { 4120 {
3737 m_host.AddScriptLPS(1); 4121 m_host.AddScriptLPS(1);
4122
4123 UUID invItemID = InventorySelf();
4124
4125 TaskInventoryItem item;
4126 m_host.TaskInventory.LockItemsForRead(true);
4127 item = m_host.TaskInventory[invItemID];
4128 m_host.TaskInventory.LockItemsForRead(false);
4129
4130 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4131 && !m_automaticLinkPermission)
4132 {
4133 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4134 return;
4135 }
4136
3738 SceneObjectGroup parentPrim = m_host.ParentGroup; 4137 SceneObjectGroup parentPrim = m_host.ParentGroup;
3739 if (parentPrim.AttachmentPoint != 0) 4138 if (parentPrim.AttachmentPoint != 0)
3740 return; // Fail silently if attached 4139 return; // Fail silently if attached
@@ -3754,25 +4153,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3754 public LSL_String llGetLinkKey(int linknum) 4153 public LSL_String llGetLinkKey(int linknum)
3755 { 4154 {
3756 m_host.AddScriptLPS(1); 4155 m_host.AddScriptLPS(1);
3757 List<UUID> keytable = new List<UUID>();
3758 // parse for sitting avatare-uuids
3759 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3760 {
3761 if (presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID))
3762 keytable.Add(presence.UUID);
3763 });
3764
3765 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3766 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3767 {
3768 return keytable[totalprims - linknum].ToString();
3769 }
3770
3771 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3772 {
3773 return m_host.UUID.ToString();
3774 }
3775
3776 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4156 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3777 if (part != null) 4157 if (part != null)
3778 { 4158 {
@@ -3780,6 +4160,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3780 } 4160 }
3781 else 4161 else
3782 { 4162 {
4163 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4164 {
4165 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4166
4167 if (linknum < 0)
4168 return UUID.Zero.ToString();
4169
4170 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4171 if (avatars.Count > linknum)
4172 {
4173 return avatars[linknum].UUID.ToString();
4174 }
4175 }
3783 return UUID.Zero.ToString(); 4176 return UUID.Zero.ToString();
3784 } 4177 }
3785 } 4178 }
@@ -3878,17 +4271,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3878 m_host.AddScriptLPS(1); 4271 m_host.AddScriptLPS(1);
3879 int count = 0; 4272 int count = 0;
3880 4273
3881 lock (m_host.TaskInventory) 4274 m_host.TaskInventory.LockItemsForRead(true);
4275 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3882 { 4276 {
3883 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4277 if (inv.Value.Type == type || type == -1)
3884 { 4278 {
3885 if (inv.Value.Type == type || type == -1) 4279 count = count + 1;
3886 {
3887 count = count + 1;
3888 }
3889 } 4280 }
3890 } 4281 }
3891 4282
4283 m_host.TaskInventory.LockItemsForRead(false);
3892 return count; 4284 return count;
3893 } 4285 }
3894 4286
@@ -3897,16 +4289,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3897 m_host.AddScriptLPS(1); 4289 m_host.AddScriptLPS(1);
3898 ArrayList keys = new ArrayList(); 4290 ArrayList keys = new ArrayList();
3899 4291
3900 lock (m_host.TaskInventory) 4292 m_host.TaskInventory.LockItemsForRead(true);
4293 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3901 { 4294 {
3902 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4295 if (inv.Value.Type == type || type == -1)
3903 { 4296 {
3904 if (inv.Value.Type == type || type == -1) 4297 keys.Add(inv.Value.Name);
3905 {
3906 keys.Add(inv.Value.Name);
3907 }
3908 } 4298 }
3909 } 4299 }
4300 m_host.TaskInventory.LockItemsForRead(false);
3910 4301
3911 if (keys.Count == 0) 4302 if (keys.Count == 0)
3912 { 4303 {
@@ -3943,25 +4334,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3943 } 4334 }
3944 4335
3945 // move the first object found with this inventory name 4336 // move the first object found with this inventory name
3946 lock (m_host.TaskInventory) 4337 m_host.TaskInventory.LockItemsForRead(true);
4338 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3947 { 4339 {
3948 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4340 if (inv.Value.Name == inventory)
3949 { 4341 {
3950 if (inv.Value.Name == inventory) 4342 found = true;
3951 { 4343 objId = inv.Key;
3952 found = true; 4344 assetType = inv.Value.Type;
3953 objId = inv.Key; 4345 objName = inv.Value.Name;
3954 assetType = inv.Value.Type; 4346 break;
3955 objName = inv.Value.Name;
3956 break;
3957 }
3958 } 4347 }
3959 } 4348 }
4349 m_host.TaskInventory.LockItemsForRead(false);
3960 4350
3961 if (!found) 4351 if (!found)
3962 { 4352 {
3963 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4353 llSay(0, String.Format("Could not find object '{0}'", inventory));
3964 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4354 return;
4355// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3965 } 4356 }
3966 4357
3967 // check if destination is an object 4358 // check if destination is an object
@@ -3987,48 +4378,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3987 return; 4378 return;
3988 } 4379 }
3989 } 4380 }
4381
3990 // destination is an avatar 4382 // destination is an avatar
3991 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4383 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3992 4384
3993 if (agentItem == null) 4385 if (agentItem == null)
3994 return; 4386 return;
3995 4387
3996 byte[] bucket = new byte[17]; 4388 byte[] bucket = new byte[1];
3997 bucket[0] = (byte)assetType; 4389 bucket[0] = (byte)assetType;
3998 byte[] objBytes = agentItem.ID.GetBytes(); 4390 //byte[] objBytes = agentItem.ID.GetBytes();
3999 Array.Copy(objBytes, 0, bucket, 1, 16); 4391 //Array.Copy(objBytes, 0, bucket, 1, 16);
4000 4392
4001 GridInstantMessage msg = new GridInstantMessage(World, 4393 GridInstantMessage msg = new GridInstantMessage(World,
4002 m_host.UUID, m_host.Name+", an object owned by "+ 4394 m_host.OwnerID, m_host.Name, destId,
4003 resolveName(m_host.OwnerID)+",", destId,
4004 (byte)InstantMessageDialog.TaskInventoryOffered, 4395 (byte)InstantMessageDialog.TaskInventoryOffered,
4005 false, objName+"\n"+m_host.Name+" is located at "+ 4396 false, objName+". "+m_host.Name+" is located at "+
4006 World.RegionInfo.RegionName+" "+ 4397 World.RegionInfo.RegionName+" "+
4007 m_host.AbsolutePosition.ToString(), 4398 m_host.AbsolutePosition.ToString(),
4008 agentItem.ID, true, m_host.AbsolutePosition, 4399 agentItem.ID, true, m_host.AbsolutePosition,
4009 bucket); 4400 bucket);
4010 if (m_TransferModule != null) 4401
4011 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4402 ScenePresence sp;
4403
4404 if (World.TryGetScenePresence(destId, out sp))
4405 {
4406 sp.ControllingClient.SendInstantMessage(msg);
4407 }
4408 else
4409 {
4410 if (m_TransferModule != null)
4411 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4412 }
4413
4414 //This delay should only occur when giving inventory to avatars.
4012 ScriptSleep(3000); 4415 ScriptSleep(3000);
4013 } 4416 }
4014 } 4417 }
4015 4418
4419 [DebuggerNonUserCode]
4016 public void llRemoveInventory(string name) 4420 public void llRemoveInventory(string name)
4017 { 4421 {
4018 m_host.AddScriptLPS(1); 4422 m_host.AddScriptLPS(1);
4019 4423
4020 lock (m_host.TaskInventory) 4424 List<TaskInventoryItem> inv;
4425 try
4021 { 4426 {
4022 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4427 m_host.TaskInventory.LockItemsForRead(true);
4428 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4429 }
4430 finally
4431 {
4432 m_host.TaskInventory.LockItemsForRead(false);
4433 }
4434 foreach (TaskInventoryItem item in inv)
4435 {
4436 if (item.Name == name)
4023 { 4437 {
4024 if (item.Name == name) 4438 if (item.ItemID == m_itemID)
4025 { 4439 throw new ScriptDeleteException();
4026 if (item.ItemID == m_itemID) 4440 else
4027 throw new ScriptDeleteException(); 4441 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4028 else 4442 return;
4029 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4030 return;
4031 }
4032 } 4443 }
4033 } 4444 }
4034 } 4445 }
@@ -4063,112 +4474,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4063 { 4474 {
4064 m_host.AddScriptLPS(1); 4475 m_host.AddScriptLPS(1);
4065 4476
4066 UUID uuid = (UUID)id; 4477 UUID uuid;
4067 PresenceInfo pinfo = null; 4478 if (UUID.TryParse(id, out uuid))
4068 UserAccount account;
4069
4070 UserInfoCacheEntry ce;
4071 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4072 { 4479 {
4073 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4480 PresenceInfo pinfo = null;
4074 if (account == null) 4481 UserAccount account;
4482
4483 UserInfoCacheEntry ce;
4484 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4075 { 4485 {
4076 m_userInfoCache[uuid] = null; // Cache negative 4486 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4077 return UUID.Zero.ToString(); 4487 if (account == null)
4078 } 4488 {
4489 m_userInfoCache[uuid] = null; // Cache negative
4490 return UUID.Zero.ToString();
4491 }
4079 4492
4080 4493
4081 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4494 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4082 if (pinfos != null && pinfos.Length > 0) 4495 if (pinfos != null && pinfos.Length > 0)
4083 {
4084 foreach (PresenceInfo p in pinfos)
4085 { 4496 {
4086 if (p.RegionID != UUID.Zero) 4497 foreach (PresenceInfo p in pinfos)
4087 { 4498 {
4088 pinfo = p; 4499 if (p.RegionID != UUID.Zero)
4500 {
4501 pinfo = p;
4502 }
4089 } 4503 }
4090 } 4504 }
4091 }
4092 4505
4093 ce = new UserInfoCacheEntry(); 4506 ce = new UserInfoCacheEntry();
4094 ce.time = Util.EnvironmentTickCount(); 4507 ce.time = Util.EnvironmentTickCount();
4095 ce.account = account; 4508 ce.account = account;
4096 ce.pinfo = pinfo; 4509 ce.pinfo = pinfo;
4097 } 4510 m_userInfoCache[uuid] = ce;
4098 else 4511 }
4099 { 4512 else
4100 if (ce == null) 4513 {
4101 return UUID.Zero.ToString(); 4514 if (ce == null)
4515 return UUID.Zero.ToString();
4102 4516
4103 account = ce.account; 4517 account = ce.account;
4104 pinfo = ce.pinfo; 4518 pinfo = ce.pinfo;
4105 } 4519 }
4106 4520
4107 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4521 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4108 {
4109 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4110 if (pinfos != null && pinfos.Length > 0)
4111 { 4522 {
4112 foreach (PresenceInfo p in pinfos) 4523 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4524 if (pinfos != null && pinfos.Length > 0)
4113 { 4525 {
4114 if (p.RegionID != UUID.Zero) 4526 foreach (PresenceInfo p in pinfos)
4115 { 4527 {
4116 pinfo = p; 4528 if (p.RegionID != UUID.Zero)
4529 {
4530 pinfo = p;
4531 }
4117 } 4532 }
4118 } 4533 }
4119 } 4534 else
4120 else 4535 pinfo = null;
4121 pinfo = null;
4122 4536
4123 ce.time = Util.EnvironmentTickCount(); 4537 ce.time = Util.EnvironmentTickCount();
4124 ce.pinfo = pinfo; 4538 ce.pinfo = pinfo;
4125 } 4539 }
4126 4540
4127 string reply = String.Empty; 4541 string reply = String.Empty;
4128 4542
4129 switch (data) 4543 switch (data)
4130 { 4544 {
4131 case 1: // DATA_ONLINE (0|1) 4545 case 1: // DATA_ONLINE (0|1)
4132 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4546 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4133 reply = "1"; 4547 reply = "1";
4134 else 4548 else
4135 reply = "0"; 4549 reply = "0";
4136 break; 4550 break;
4137 case 2: // DATA_NAME (First Last) 4551 case 2: // DATA_NAME (First Last)
4138 reply = account.FirstName + " " + account.LastName; 4552 reply = account.FirstName + " " + account.LastName;
4139 break; 4553 break;
4140 case 3: // DATA_BORN (YYYY-MM-DD) 4554 case 3: // DATA_BORN (YYYY-MM-DD)
4141 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4555 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4142 born = born.AddSeconds(account.Created); 4556 born = born.AddSeconds(account.Created);
4143 reply = born.ToString("yyyy-MM-dd"); 4557 reply = born.ToString("yyyy-MM-dd");
4144 break; 4558 break;
4145 case 4: // DATA_RATING (0,0,0,0,0,0) 4559 case 4: // DATA_RATING (0,0,0,0,0,0)
4146 reply = "0,0,0,0,0,0"; 4560 reply = "0,0,0,0,0,0";
4147 break; 4561 break;
4148 case 8: // DATA_PAYINFO (0|1|2|3) 4562 case 8: // DATA_PAYINFO (0|1|2|3)
4149 reply = "0"; 4563 reply = "0";
4150 break; 4564 break;
4151 default: 4565 default:
4152 return UUID.Zero.ToString(); // Raise no event 4566 return UUID.Zero.ToString(); // Raise no event
4153 } 4567 }
4154 4568
4155 UUID rq = UUID.Random(); 4569 UUID rq = UUID.Random();
4156 4570
4157 UUID tid = AsyncCommands. 4571 UUID tid = AsyncCommands.
4158 DataserverPlugin.RegisterRequest(m_localID, 4572 DataserverPlugin.RegisterRequest(m_localID,
4159 m_itemID, rq.ToString()); 4573 m_itemID, rq.ToString());
4160 4574
4161 AsyncCommands. 4575 AsyncCommands.
4162 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4576 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4163 4577
4164 ScriptSleep(100); 4578 ScriptSleep(100);
4165 return tid.ToString(); 4579 return tid.ToString();
4580 }
4581 else
4582 {
4583 ShoutError("Invalid UUID passed to llRequestAgentData.");
4584 }
4585 return "";
4166 } 4586 }
4167 4587
4168 public LSL_String llRequestInventoryData(string name) 4588 public LSL_String llRequestInventoryData(string name)
4169 { 4589 {
4170 m_host.AddScriptLPS(1); 4590 m_host.AddScriptLPS(1);
4171 4591
4592 //Clone is thread safe
4172 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4593 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4173 4594
4174 foreach (TaskInventoryItem item in itemDictionary.Values) 4595 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4222,6 +4643,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4222 ScenePresence presence = World.GetScenePresence(agentId); 4643 ScenePresence presence = World.GetScenePresence(agentId);
4223 if (presence != null) 4644 if (presence != null)
4224 { 4645 {
4646 // agent must not be a god
4647 if (presence.UserLevel >= 200) return;
4648
4225 // agent must be over the owners land 4649 // agent must be over the owners land
4226 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4650 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4227 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4651 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
@@ -4244,7 +4668,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4244 UUID av = new UUID(); 4668 UUID av = new UUID();
4245 if (!UUID.TryParse(agent,out av)) 4669 if (!UUID.TryParse(agent,out av))
4246 { 4670 {
4247 LSLError("First parameter to llDialog needs to be a key"); 4671 //LSLError("First parameter to llDialog needs to be a key");
4248 return; 4672 return;
4249 } 4673 }
4250 4674
@@ -4281,17 +4705,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4281 UUID soundId = UUID.Zero; 4705 UUID soundId = UUID.Zero;
4282 if (!UUID.TryParse(impact_sound, out soundId)) 4706 if (!UUID.TryParse(impact_sound, out soundId))
4283 { 4707 {
4284 lock (m_host.TaskInventory) 4708 m_host.TaskInventory.LockItemsForRead(true);
4709 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4285 { 4710 {
4286 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4711 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4287 { 4712 {
4288 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4713 soundId = item.AssetID;
4289 { 4714 break;
4290 soundId = item.AssetID;
4291 break;
4292 }
4293 } 4715 }
4294 } 4716 }
4717 m_host.TaskInventory.LockItemsForRead(false);
4295 } 4718 }
4296 m_host.CollisionSound = soundId; 4719 m_host.CollisionSound = soundId;
4297 m_host.CollisionSoundVolume = (float)impact_volume; 4720 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4331,6 +4754,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4331 UUID partItemID; 4754 UUID partItemID;
4332 foreach (SceneObjectPart part in parts) 4755 foreach (SceneObjectPart part in parts)
4333 { 4756 {
4757 //Clone is thread safe
4334 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4758 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4335 4759
4336 foreach (TaskInventoryItem item in itemsDictionary.Values) 4760 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4545,17 +4969,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4545 4969
4546 m_host.AddScriptLPS(1); 4970 m_host.AddScriptLPS(1);
4547 4971
4548 lock (m_host.TaskInventory) 4972 m_host.TaskInventory.LockItemsForRead(true);
4973 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4549 { 4974 {
4550 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4975 if (item.Type == 10 && item.ItemID == m_itemID)
4551 { 4976 {
4552 if (item.Type == 10 && item.ItemID == m_itemID) 4977 result = item.Name!=null?item.Name:String.Empty;
4553 { 4978 break;
4554 result = item.Name != null ? item.Name : String.Empty;
4555 break;
4556 }
4557 } 4979 }
4558 } 4980 }
4981 m_host.TaskInventory.LockItemsForRead(false);
4559 4982
4560 return result; 4983 return result;
4561 } 4984 }
@@ -4728,23 +5151,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4728 { 5151 {
4729 m_host.AddScriptLPS(1); 5152 m_host.AddScriptLPS(1);
4730 5153
4731 lock (m_host.TaskInventory) 5154 m_host.TaskInventory.LockItemsForRead(true);
5155 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4732 { 5156 {
4733 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5157 if (inv.Value.Name == name)
4734 { 5158 {
4735 if (inv.Value.Name == name) 5159 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4736 { 5160 {
4737 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5161 m_host.TaskInventory.LockItemsForRead(false);
4738 { 5162 return inv.Value.AssetID.ToString();
4739 return inv.Value.AssetID.ToString(); 5163 }
4740 } 5164 else
4741 else 5165 {
4742 { 5166 m_host.TaskInventory.LockItemsForRead(false);
4743 return UUID.Zero.ToString(); 5167 return UUID.Zero.ToString();
4744 }
4745 } 5168 }
4746 } 5169 }
4747 } 5170 }
5171 m_host.TaskInventory.LockItemsForRead(false);
4748 5172
4749 return UUID.Zero.ToString(); 5173 return UUID.Zero.ToString();
4750 } 5174 }
@@ -4897,14 +5321,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4897 { 5321 {
4898 m_host.AddScriptLPS(1); 5322 m_host.AddScriptLPS(1);
4899 5323
4900 if (src == null) 5324 return src.Length;
4901 {
4902 return 0;
4903 }
4904 else
4905 {
4906 return src.Length;
4907 }
4908 } 5325 }
4909 5326
4910 public LSL_Integer llList2Integer(LSL_List src, int index) 5327 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4950,7 +5367,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4950 else if (src.Data[index] is LSL_Float) 5367 else if (src.Data[index] is LSL_Float)
4951 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5368 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4952 else if (src.Data[index] is LSL_String) 5369 else if (src.Data[index] is LSL_String)
4953 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5370 {
5371 string str = ((LSL_String) src.Data[index]).m_string;
5372 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5373 if (m != Match.Empty)
5374 {
5375 str = m.Value;
5376 double d = 0.0;
5377 if (!Double.TryParse(str, out d))
5378 return 0.0;
5379
5380 return d;
5381 }
5382 return 0.0;
5383 }
4954 return Convert.ToDouble(src.Data[index]); 5384 return Convert.ToDouble(src.Data[index]);
4955 } 5385 }
4956 catch (FormatException) 5386 catch (FormatException)
@@ -5223,7 +5653,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5223 } 5653 }
5224 } 5654 }
5225 } 5655 }
5226 else { 5656 else
5657 {
5227 object[] array = new object[src.Length]; 5658 object[] array = new object[src.Length];
5228 Array.Copy(src.Data, 0, array, 0, src.Length); 5659 Array.Copy(src.Data, 0, array, 0, src.Length);
5229 result = new LSL_List(array); 5660 result = new LSL_List(array);
@@ -5330,7 +5761,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5330 public LSL_Integer llGetRegionAgentCount() 5761 public LSL_Integer llGetRegionAgentCount()
5331 { 5762 {
5332 m_host.AddScriptLPS(1); 5763 m_host.AddScriptLPS(1);
5333 return new LSL_Integer(World.GetRootAgentCount()); 5764
5765 int count = 0;
5766 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5767 count++;
5768 });
5769
5770 return new LSL_Integer(count);
5334 } 5771 }
5335 5772
5336 public LSL_Vector llGetRegionCorner() 5773 public LSL_Vector llGetRegionCorner()
@@ -5672,10 +6109,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5672 m_host.AddScriptLPS(1); 6109 m_host.AddScriptLPS(1);
5673 6110
5674 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6111 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5675 6112 if (parts.Count > 0)
5676 foreach (var part in parts)
5677 { 6113 {
5678 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6114 try
6115 {
6116 parts[0].ParentGroup.areUpdatesSuspended = true;
6117 foreach (var part in parts)
6118 {
6119 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6120 }
6121 }
6122 finally
6123 {
6124 parts[0].ParentGroup.areUpdatesSuspended = false;
6125 }
5679 } 6126 }
5680 } 6127 }
5681 6128
@@ -5727,13 +6174,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5727 6174
5728 if (m_host.OwnerID == land.LandData.OwnerID) 6175 if (m_host.OwnerID == land.LandData.OwnerID)
5729 { 6176 {
5730 World.TeleportClientHome(agentID, presence.ControllingClient); 6177 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6178 presence.TeleportWithMomentum(pos);
6179 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5731 } 6180 }
5732 } 6181 }
5733 } 6182 }
5734 ScriptSleep(5000); 6183 ScriptSleep(5000);
5735 } 6184 }
5736 6185
6186 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6187 {
6188 return ParseString2List(str, separators, in_spacers, false);
6189 }
6190
5737 public LSL_Integer llOverMyLand(string id) 6191 public LSL_Integer llOverMyLand(string id)
5738 { 6192 {
5739 m_host.AddScriptLPS(1); 6193 m_host.AddScriptLPS(1);
@@ -5798,8 +6252,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5798 UUID agentId = new UUID(); 6252 UUID agentId = new UUID();
5799 if (!UUID.TryParse(agent, out agentId)) 6253 if (!UUID.TryParse(agent, out agentId))
5800 return new LSL_Integer(0); 6254 return new LSL_Integer(0);
6255 if (agentId == m_host.GroupID)
6256 return new LSL_Integer(1);
5801 ScenePresence presence = World.GetScenePresence(agentId); 6257 ScenePresence presence = World.GetScenePresence(agentId);
5802 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6258 if (presence == null || presence.IsChildAgent) // Return false for child agents
5803 return new LSL_Integer(0); 6259 return new LSL_Integer(0);
5804 IClientAPI client = presence.ControllingClient; 6260 IClientAPI client = presence.ControllingClient;
5805 if (m_host.GroupID == client.ActiveGroupId) 6261 if (m_host.GroupID == client.ActiveGroupId)
@@ -5934,7 +6390,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5934 return m_host.ParentGroup.AttachmentPoint; 6390 return m_host.ParentGroup.AttachmentPoint;
5935 } 6391 }
5936 6392
5937 public LSL_Integer llGetFreeMemory() 6393 public virtual LSL_Integer llGetFreeMemory()
5938 { 6394 {
5939 m_host.AddScriptLPS(1); 6395 m_host.AddScriptLPS(1);
5940 // Make scripts designed for LSO happy 6396 // Make scripts designed for LSO happy
@@ -6051,7 +6507,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6051 SetParticleSystem(m_host, rules); 6507 SetParticleSystem(m_host, rules);
6052 } 6508 }
6053 6509
6054 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6510 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6511 {
6055 6512
6056 6513
6057 if (rules.Length == 0) 6514 if (rules.Length == 0)
@@ -6245,14 +6702,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6245 6702
6246 protected UUID GetTaskInventoryItem(string name) 6703 protected UUID GetTaskInventoryItem(string name)
6247 { 6704 {
6248 lock (m_host.TaskInventory) 6705 m_host.TaskInventory.LockItemsForRead(true);
6706 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6249 { 6707 {
6250 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6708 if (inv.Value.Name == name)
6251 { 6709 {
6252 if (inv.Value.Name == name) 6710 m_host.TaskInventory.LockItemsForRead(false);
6253 return inv.Key; 6711 return inv.Key;
6254 } 6712 }
6255 } 6713 }
6714 m_host.TaskInventory.LockItemsForRead(false);
6256 6715
6257 return UUID.Zero; 6716 return UUID.Zero;
6258 } 6717 }
@@ -6290,16 +6749,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6290 if (folderID == UUID.Zero) 6749 if (folderID == UUID.Zero)
6291 return; 6750 return;
6292 6751
6293 byte[] bucket = new byte[17]; 6752 byte[] bucket = new byte[1];
6294 bucket[0] = (byte)AssetType.Folder; 6753 bucket[0] = (byte)AssetType.Folder;
6295 byte[] objBytes = folderID.GetBytes(); 6754 //byte[] objBytes = folderID.GetBytes();
6296 Array.Copy(objBytes, 0, bucket, 1, 16); 6755 //Array.Copy(objBytes, 0, bucket, 1, 16);
6297 6756
6298 GridInstantMessage msg = new GridInstantMessage(World, 6757 GridInstantMessage msg = new GridInstantMessage(World,
6299 m_host.UUID, m_host.Name+", an object owned by "+ 6758 m_host.OwnerID, m_host.Name, destID,
6300 resolveName(m_host.OwnerID)+",", destID, 6759 (byte)InstantMessageDialog.TaskInventoryOffered,
6301 (byte)InstantMessageDialog.InventoryOffered, 6760 false, category+". "+m_host.Name+" is located at "+
6302 false, category+"\n"+m_host.Name+" is located at "+
6303 World.RegionInfo.RegionName+" "+ 6761 World.RegionInfo.RegionName+" "+
6304 m_host.AbsolutePosition.ToString(), 6762 m_host.AbsolutePosition.ToString(),
6305 folderID, true, m_host.AbsolutePosition, 6763 folderID, true, m_host.AbsolutePosition,
@@ -6537,13 +6995,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6537 UUID av = new UUID(); 6995 UUID av = new UUID();
6538 if (!UUID.TryParse(avatar,out av)) 6996 if (!UUID.TryParse(avatar,out av))
6539 { 6997 {
6540 LSLError("First parameter to llDialog needs to be a key"); 6998 //LSLError("First parameter to llDialog needs to be a key");
6541 return; 6999 return;
6542 } 7000 }
6543 if (buttons.Length < 1) 7001 if (buttons.Length < 1)
6544 { 7002 {
6545 LSLError("No less than 1 button can be shown"); 7003 buttons.Add("OK");
6546 return;
6547 } 7004 }
6548 if (buttons.Length > 12) 7005 if (buttons.Length > 12)
6549 { 7006 {
@@ -6560,7 +7017,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6560 } 7017 }
6561 if (buttons.Data[i].ToString().Length > 24) 7018 if (buttons.Data[i].ToString().Length > 24)
6562 { 7019 {
6563 LSLError("button label cannot be longer than 24 characters"); 7020 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6564 return; 7021 return;
6565 } 7022 }
6566 buts[i] = buttons.Data[i].ToString(); 7023 buts[i] = buttons.Data[i].ToString();
@@ -6619,22 +7076,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6619 } 7076 }
6620 7077
6621 // copy the first script found with this inventory name 7078 // copy the first script found with this inventory name
6622 lock (m_host.TaskInventory) 7079 TaskInventoryItem scriptItem = null;
7080 m_host.TaskInventory.LockItemsForRead(true);
7081 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6623 { 7082 {
6624 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 7083 if (inv.Value.Name == name)
6625 { 7084 {
6626 if (inv.Value.Name == name) 7085 // make sure the object is a script
7086 if (10 == inv.Value.Type)
6627 { 7087 {
6628 // make sure the object is a script 7088 found = true;
6629 if (10 == inv.Value.Type) 7089 srcId = inv.Key;
6630 { 7090 scriptItem = inv.Value;
6631 found = true; 7091 break;
6632 srcId = inv.Key;
6633 break;
6634 }
6635 } 7092 }
6636 } 7093 }
6637 } 7094 }
7095 m_host.TaskInventory.LockItemsForRead(false);
6638 7096
6639 if (!found) 7097 if (!found)
6640 { 7098 {
@@ -6642,9 +7100,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6642 return; 7100 return;
6643 } 7101 }
6644 7102
6645 // the rest of the permission checks are done in RezScript, so check the pin there as well 7103 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6646 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7104 if (dest != null)
7105 {
7106 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7107 {
7108 // the rest of the permission checks are done in RezScript, so check the pin there as well
7109 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6647 7110
7111 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7112 m_host.Inventory.RemoveInventoryItem(srcId);
7113 }
7114 }
6648 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7115 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6649 ScriptSleep(3000); 7116 ScriptSleep(3000);
6650 } 7117 }
@@ -6707,19 +7174,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6707 public LSL_String llMD5String(string src, int nonce) 7174 public LSL_String llMD5String(string src, int nonce)
6708 { 7175 {
6709 m_host.AddScriptLPS(1); 7176 m_host.AddScriptLPS(1);
6710 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7177 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6711 } 7178 }
6712 7179
6713 public LSL_String llSHA1String(string src) 7180 public LSL_String llSHA1String(string src)
6714 { 7181 {
6715 m_host.AddScriptLPS(1); 7182 m_host.AddScriptLPS(1);
6716 return Util.SHA1Hash(src).ToLower(); 7183 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6717 } 7184 }
6718 7185
6719 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7186 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6720 { 7187 {
6721 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7188 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6722 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7189 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7190 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7191 return shapeBlock;
6723 7192
6724 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7193 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6725 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7194 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6824,6 +7293,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6824 // Prim type box, cylinder and prism. 7293 // Prim type box, cylinder and prism.
6825 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve) 7294 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve)
6826 { 7295 {
7296 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7297 return;
7298
6827 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7299 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6828 ObjectShapePacket.ObjectDataBlock shapeBlock; 7300 ObjectShapePacket.ObjectDataBlock shapeBlock;
6829 7301
@@ -6877,6 +7349,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6877 // Prim type sphere. 7349 // Prim type sphere.
6878 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7350 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6879 { 7351 {
7352 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7353 return;
7354
6880 ObjectShapePacket.ObjectDataBlock shapeBlock; 7355 ObjectShapePacket.ObjectDataBlock shapeBlock;
6881 7356
6882 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7357 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6918,6 +7393,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6918 // Prim type torus, tube and ring. 7393 // Prim type torus, tube and ring.
6919 protected 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 profileshape, byte pathcurve) 7394 protected 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 profileshape, byte pathcurve)
6920 { 7395 {
7396 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7397 return;
7398
6921 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7399 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6922 ObjectShapePacket.ObjectDataBlock shapeBlock; 7400 ObjectShapePacket.ObjectDataBlock shapeBlock;
6923 7401
@@ -7053,6 +7531,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7053 // Prim type sculpt. 7531 // Prim type sculpt.
7054 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7532 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7055 { 7533 {
7534 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7535 return;
7536
7056 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7537 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7057 UUID sculptId; 7538 UUID sculptId;
7058 7539
@@ -7069,13 +7550,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7069 shapeBlock.PathScaleX = 100; 7550 shapeBlock.PathScaleX = 100;
7070 shapeBlock.PathScaleY = 150; 7551 shapeBlock.PathScaleY = 150;
7071 7552
7072 if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER && 7553 if ((type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER) == 0 &&
7073 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE && 7554 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE) == 0 &&
7074 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE && 7555 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE) == 0 &&
7075 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) 7556 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) == 0)
7076 { 7557 {
7077 // default 7558 // default
7078 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7559 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7079 } 7560 }
7080 7561
7081 part.Shape.SetSculptProperties((byte)type, sculptId); 7562 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7091,32 +7572,119 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7091 ScriptSleep(200); 7572 ScriptSleep(200);
7092 } 7573 }
7093 7574
7094 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7575 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7095 { 7576 {
7096 m_host.AddScriptLPS(1); 7577 m_host.AddScriptLPS(1);
7097 7578
7098 setLinkPrimParams(linknumber, rules); 7579 setLinkPrimParams(linknumber, rules);
7099
7100 ScriptSleep(200);
7101 } 7580 }
7102 7581
7103 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7582 private void setLinkPrimParams(int linknumber, LSL_List rules)
7104 { 7583 {
7105 m_host.AddScriptLPS(1); 7584 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7585 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7586 if (parts.Count>0)
7587 {
7588 try
7589 {
7590 parts[0].ParentGroup.areUpdatesSuspended = true;
7591 foreach (SceneObjectPart part in parts)
7592 SetPrimParams(part, rules);
7593 }
7594 finally
7595 {
7596 parts[0].ParentGroup.areUpdatesSuspended = false;
7597 }
7598 }
7599 if (avatars.Count > 0)
7600 {
7601 foreach (ScenePresence avatar in avatars)
7602 SetPrimParams(avatar, rules);
7603 }
7604 }
7106 7605
7107 setLinkPrimParams(linknumber, rules); 7606 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7607 {
7608 llSetLinkPrimitiveParamsFast(linknumber, rules);
7609 ScriptSleep(200);
7108 } 7610 }
7109 7611
7110 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7612 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7111 { 7613 {
7112 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7614 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7615 //We only support PRIM_POSITION and PRIM_ROTATION
7113 7616
7114 foreach (SceneObjectPart part in parts) 7617 int idx = 0;
7115 SetPrimParams(part, rules); 7618
7619 while (idx < rules.Length)
7620 {
7621 int code = rules.GetLSLIntegerItem(idx++);
7622
7623 int remain = rules.Length - idx;
7624
7625 switch (code)
7626 {
7627 case (int)ScriptBaseClass.PRIM_POSITION:
7628 {
7629 if (remain < 1)
7630 return;
7631 LSL_Vector v;
7632 v = rules.GetVector3Item(idx++);
7633
7634 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7635 if (part == null)
7636 break;
7637
7638 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7639 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7640 if (llGetLinkNumber() > 1)
7641 {
7642 localRot = llGetLocalRot();
7643 localPos = llGetLocalPos();
7644 }
7645
7646 v -= localPos;
7647 v /= localRot;
7648
7649 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
7650
7651 v = v + 2 * sitOffset;
7652
7653 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7654 av.SendAvatarDataToAllAgents();
7655
7656 }
7657 break;
7658
7659 case (int)ScriptBaseClass.PRIM_ROTATION:
7660 {
7661 if (remain < 1)
7662 return;
7663
7664 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7665 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7666 if (llGetLinkNumber() > 1)
7667 {
7668 localRot = llGetLocalRot();
7669 localPos = llGetLocalPos();
7670 }
7671
7672 LSL_Rotation r;
7673 r = rules.GetQuaternionItem(idx++);
7674 r = r * llGetRootRotation() / localRot;
7675 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7676 av.SendAvatarDataToAllAgents();
7677 }
7678 break;
7679 }
7680 }
7116 } 7681 }
7117 7682
7118 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7683 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7119 { 7684 {
7685 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7686 return;
7687
7120 int idx = 0; 7688 int idx = 0;
7121 7689
7122 bool positionChanged = false; 7690 bool positionChanged = false;
@@ -7144,6 +7712,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7144 currentPosition = GetSetPosTarget(part, v, currentPosition); 7712 currentPosition = GetSetPosTarget(part, v, currentPosition);
7145 7713
7146 break; 7714 break;
7715 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
7716 if (remain < 1)
7717 return;
7718
7719 v=rules.GetVector3Item(idx++);
7720 positionChanged = true;
7721 currentPosition = GetSetPosTarget(part, v, currentPosition);
7722
7723 break;
7147 case (int)ScriptBaseClass.PRIM_SIZE: 7724 case (int)ScriptBaseClass.PRIM_SIZE:
7148 if (remain < 1) 7725 if (remain < 1)
7149 return; 7726 return;
@@ -7510,7 +8087,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7510 if (part.ParentGroup.RootPart == part) 8087 if (part.ParentGroup.RootPart == part)
7511 { 8088 {
7512 SceneObjectGroup parent = part.ParentGroup; 8089 SceneObjectGroup parent = part.ParentGroup;
7513 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8090 Util.FireAndForget(delegate(object x) {
8091 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8092 });
7514 } 8093 }
7515 else 8094 else
7516 { 8095 {
@@ -7521,6 +8100,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7521 } 8100 }
7522 } 8101 }
7523 } 8102 }
8103
8104 if (positionChanged)
8105 {
8106 if (part.ParentGroup.RootPart == part)
8107 {
8108 SceneObjectGroup parent = part.ParentGroup;
8109 Util.FireAndForget(delegate(object x) {
8110 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8111 });
8112 }
8113 else
8114 {
8115 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8116 SceneObjectGroup parent = part.ParentGroup;
8117 parent.HasGroupChanged = true;
8118 parent.ScheduleGroupForTerseUpdate();
8119 }
8120 }
7524 } 8121 }
7525 8122
7526 public LSL_String llStringToBase64(string str) 8123 public LSL_String llStringToBase64(string str)
@@ -7681,13 +8278,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7681 public LSL_Integer llGetNumberOfPrims() 8278 public LSL_Integer llGetNumberOfPrims()
7682 { 8279 {
7683 m_host.AddScriptLPS(1); 8280 m_host.AddScriptLPS(1);
7684 int avatarCount = 0; 8281 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7685 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8282
7686 {
7687 if (presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID))
7688 avatarCount++;
7689 });
7690
7691 return m_host.ParentGroup.PrimCount + avatarCount; 8283 return m_host.ParentGroup.PrimCount + avatarCount;
7692 } 8284 }
7693 8285
@@ -7703,55 +8295,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7703 m_host.AddScriptLPS(1); 8295 m_host.AddScriptLPS(1);
7704 UUID objID = UUID.Zero; 8296 UUID objID = UUID.Zero;
7705 LSL_List result = new LSL_List(); 8297 LSL_List result = new LSL_List();
8298
8299 // If the ID is not valid, return null result
7706 if (!UUID.TryParse(obj, out objID)) 8300 if (!UUID.TryParse(obj, out objID))
7707 { 8301 {
7708 result.Add(new LSL_Vector()); 8302 result.Add(new LSL_Vector());
7709 result.Add(new LSL_Vector()); 8303 result.Add(new LSL_Vector());
7710 return result; 8304 return result;
7711 } 8305 }
8306
8307 // Check if this is an attached prim. If so, replace
8308 // the UUID with the avatar UUID and report it's bounding box
8309 SceneObjectPart part = World.GetSceneObjectPart(objID);
8310 if (part != null && part.ParentGroup.IsAttachment)
8311 objID = part.ParentGroup.AttachedAvatar;
8312
8313 // Find out if this is an avatar ID. If so, return it's box
7712 ScenePresence presence = World.GetScenePresence(objID); 8314 ScenePresence presence = World.GetScenePresence(objID);
7713 if (presence != null) 8315 if (presence != null)
7714 { 8316 {
7715 if (presence.ParentID == 0) // not sat on an object 8317 // As per LSL Wiki, there is no difference between sitting
8318 // and standing avatar since server 1.36
8319 LSL_Vector lower;
8320 LSL_Vector upper;
8321 if (presence.Animator.Animations.DefaultAnimation.AnimID
8322 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7716 { 8323 {
7717 LSL_Vector lower; 8324 // This is for ground sitting avatars
7718 LSL_Vector upper; 8325 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7719 if (presence.Animator.Animations.DefaultAnimation.AnimID 8326 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7720 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8327 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7721 {
7722 // This is for ground sitting avatars
7723 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7724 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7725 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7726 }
7727 else
7728 {
7729 // This is for standing/flying avatars
7730 float height = presence.Appearance.AvatarHeight / 2.0f;
7731 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7732 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7733 }
7734 result.Add(lower);
7735 result.Add(upper);
7736 return result;
7737 } 8328 }
7738 else 8329 else
7739 { 8330 {
7740 // sitting on an object so we need the bounding box of that 8331 // This is for standing/flying avatars
7741 // which should include the avatar so set the UUID to the 8332 float height = presence.Appearance.AvatarHeight / 2.0f;
7742 // UUID of the object the avatar is sat on and allow it to fall through 8333 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7743 // to processing an object 8334 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7744 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7745 objID = p.UUID;
7746 } 8335 }
8336
8337 // Adjust to the documented error offsets (see LSL Wiki)
8338 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8339 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8340
8341 if (lower.x > upper.x)
8342 lower.x = upper.x;
8343 if (lower.y > upper.y)
8344 lower.y = upper.y;
8345 if (lower.z > upper.z)
8346 lower.z = upper.z;
8347
8348 result.Add(lower);
8349 result.Add(upper);
8350 return result;
7747 } 8351 }
7748 SceneObjectPart part = World.GetSceneObjectPart(objID); 8352
8353 part = World.GetSceneObjectPart(objID);
7749 // Currently only works for single prims without a sitting avatar 8354 // Currently only works for single prims without a sitting avatar
7750 if (part != null) 8355 if (part != null)
7751 { 8356 {
7752 Vector3 halfSize = part.Scale / 2.0f; 8357 float minX;
7753 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8358 float maxX;
7754 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8359 float minY;
8360 float maxY;
8361 float minZ;
8362 float maxZ;
8363
8364 // This BBox is in sim coordinates, with the offset being
8365 // a contained point.
8366 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8367 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8368
8369 minX -= offsets[0].X;
8370 maxX -= offsets[0].X;
8371 minY -= offsets[0].Y;
8372 maxY -= offsets[0].Y;
8373 minZ -= offsets[0].Z;
8374 maxZ -= offsets[0].Z;
8375
8376 LSL_Vector lower;
8377 LSL_Vector upper;
8378
8379 // Adjust to the documented error offsets (see LSL Wiki)
8380 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8381 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8382
8383 if (lower.x > upper.x)
8384 lower.x = upper.x;
8385 if (lower.y > upper.y)
8386 lower.y = upper.y;
8387 if (lower.z > upper.z)
8388 lower.z = upper.z;
8389
7755 result.Add(lower); 8390 result.Add(lower);
7756 result.Add(upper); 8391 result.Add(upper);
7757 return result; 8392 return result;
@@ -7831,13 +8466,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7831 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8466 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7832 part.AbsolutePosition.Y, 8467 part.AbsolutePosition.Y,
7833 part.AbsolutePosition.Z); 8468 part.AbsolutePosition.Z);
7834 // For some reason, the part.AbsolutePosition.* values do not change if the
7835 // linkset is rotated; they always reflect the child prim's world position
7836 // as though the linkset is unrotated. This is incompatible behavior with SL's
7837 // implementation, so will break scripts imported from there (not to mention it
7838 // makes it more difficult to determine a child prim's actual inworld position).
7839 if (part.ParentID != 0)
7840 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7841 res.Add(v); 8469 res.Add(v);
7842 break; 8470 break;
7843 8471
@@ -8008,56 +8636,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8008 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8636 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8009 if (remain < 1) 8637 if (remain < 1)
8010 return res; 8638 return res;
8011 8639 face = (int)rules.GetLSLIntegerItem(idx++);
8012 face=(int)rules.GetLSLIntegerItem(idx++);
8013 8640
8014 tex = part.Shape.Textures; 8641 tex = part.Shape.Textures;
8642 int shiny;
8015 if (face == ScriptBaseClass.ALL_SIDES) 8643 if (face == ScriptBaseClass.ALL_SIDES)
8016 { 8644 {
8017 for (face = 0; face < GetNumberOfSides(part); face++) 8645 for (face = 0; face < GetNumberOfSides(part); face++)
8018 { 8646 {
8019 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8647 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8020 // Convert Shininess to PRIM_SHINY_* 8648 if (shinyness == Shininess.High)
8021 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8649 {
8022 // PRIM_BUMP_* 8650 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8023 res.Add(new LSL_Integer((int)texface.Bump)); 8651 }
8652 else if (shinyness == Shininess.Medium)
8653 {
8654 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8655 }
8656 else if (shinyness == Shininess.Low)
8657 {
8658 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8659 }
8660 else
8661 {
8662 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8663 }
8664 res.Add(new LSL_Integer(shiny));
8665 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8024 } 8666 }
8025 } 8667 }
8026 else 8668 else
8027 { 8669 {
8028 if (face >= 0 && face < GetNumberOfSides(part)) 8670 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8671 if (shinyness == Shininess.High)
8029 { 8672 {
8030 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8673 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8031 // Convert Shininess to PRIM_SHINY_*
8032 res.Add(new LSL_Integer((uint)texface.Shiny >> 6));
8033 // PRIM_BUMP_*
8034 res.Add(new LSL_Integer((int)texface.Bump));
8035 } 8674 }
8675 else if (shinyness == Shininess.Medium)
8676 {
8677 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8678 }
8679 else if (shinyness == Shininess.Low)
8680 {
8681 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8682 }
8683 else
8684 {
8685 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8686 }
8687 res.Add(new LSL_Integer(shiny));
8688 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8036 } 8689 }
8037 break; 8690 break;
8038 8691
8039 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8692 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8040 if (remain < 1) 8693 if (remain < 1)
8041 return res; 8694 return res;
8042 8695 face = (int)rules.GetLSLIntegerItem(idx++);
8043 face=(int)rules.GetLSLIntegerItem(idx++);
8044 8696
8045 tex = part.Shape.Textures; 8697 tex = part.Shape.Textures;
8698 int fullbright;
8046 if (face == ScriptBaseClass.ALL_SIDES) 8699 if (face == ScriptBaseClass.ALL_SIDES)
8047 { 8700 {
8048 for (face = 0; face < GetNumberOfSides(part); face++) 8701 for (face = 0; face < GetNumberOfSides(part); face++)
8049 { 8702 {
8050 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8703 if (tex.GetFace((uint)face).Fullbright == true)
8051 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8704 {
8705 fullbright = ScriptBaseClass.TRUE;
8706 }
8707 else
8708 {
8709 fullbright = ScriptBaseClass.FALSE;
8710 }
8711 res.Add(new LSL_Integer(fullbright));
8052 } 8712 }
8053 } 8713 }
8054 else 8714 else
8055 { 8715 {
8056 if (face >= 0 && face < GetNumberOfSides(part)) 8716 if (tex.GetFace((uint)face).Fullbright == true)
8057 { 8717 {
8058 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8718 fullbright = ScriptBaseClass.TRUE;
8059 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8719 }
8720 else
8721 {
8722 fullbright = ScriptBaseClass.FALSE;
8060 } 8723 }
8724 res.Add(new LSL_Integer(fullbright));
8061 } 8725 }
8062 break; 8726 break;
8063 8727
@@ -8079,27 +8743,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8079 break; 8743 break;
8080 8744
8081 case (int)ScriptBaseClass.PRIM_TEXGEN: 8745 case (int)ScriptBaseClass.PRIM_TEXGEN:
8746 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8082 if (remain < 1) 8747 if (remain < 1)
8083 return res; 8748 return res;
8084 8749 face = (int)rules.GetLSLIntegerItem(idx++);
8085 face=(int)rules.GetLSLIntegerItem(idx++);
8086 8750
8087 tex = part.Shape.Textures; 8751 tex = part.Shape.Textures;
8088 if (face == ScriptBaseClass.ALL_SIDES) 8752 if (face == ScriptBaseClass.ALL_SIDES)
8089 { 8753 {
8090 for (face = 0; face < GetNumberOfSides(part); face++) 8754 for (face = 0; face < GetNumberOfSides(part); face++)
8091 { 8755 {
8092 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8756 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8093 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8757 {
8094 res.Add(new LSL_Integer((uint)texgen >> 1)); 8758 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8759 }
8760 else
8761 {
8762 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8763 }
8095 } 8764 }
8096 } 8765 }
8097 else 8766 else
8098 { 8767 {
8099 if (face >= 0 && face < GetNumberOfSides(part)) 8768 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8100 { 8769 {
8101 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8770 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8102 res.Add(new LSL_Integer((uint)texgen >> 1)); 8771 }
8772 else
8773 {
8774 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8103 } 8775 }
8104 } 8776 }
8105 break; 8777 break;
@@ -8122,28 +8794,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8122 case (int)ScriptBaseClass.PRIM_GLOW: 8794 case (int)ScriptBaseClass.PRIM_GLOW:
8123 if (remain < 1) 8795 if (remain < 1)
8124 return res; 8796 return res;
8125 8797 face = (int)rules.GetLSLIntegerItem(idx++);
8126 face=(int)rules.GetLSLIntegerItem(idx++);
8127 8798
8128 tex = part.Shape.Textures; 8799 tex = part.Shape.Textures;
8800 float primglow;
8129 if (face == ScriptBaseClass.ALL_SIDES) 8801 if (face == ScriptBaseClass.ALL_SIDES)
8130 { 8802 {
8131 for (face = 0; face < GetNumberOfSides(part); face++) 8803 for (face = 0; face < GetNumberOfSides(part); face++)
8132 { 8804 {
8133 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8805 primglow = tex.GetFace((uint)face).Glow;
8134 res.Add(new LSL_Float(texface.Glow)); 8806 res.Add(new LSL_Float(primglow));
8135 } 8807 }
8136 } 8808 }
8137 else 8809 else
8138 { 8810 {
8139 if (face >= 0 && face < GetNumberOfSides(part)) 8811 primglow = tex.GetFace((uint)face).Glow;
8140 { 8812 res.Add(new LSL_Float(primglow));
8141 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8142 res.Add(new LSL_Float(texface.Glow));
8143 }
8144 } 8813 }
8145 break; 8814 break;
8146
8147 case (int)ScriptBaseClass.PRIM_TEXT: 8815 case (int)ScriptBaseClass.PRIM_TEXT:
8148 Color4 textColor = part.GetTextColor(); 8816 Color4 textColor = part.GetTextColor();
8149 res.Add(new LSL_String(part.Text)); 8817 res.Add(new LSL_String(part.Text));
@@ -8695,8 +9363,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8695 // The function returns an ordered list 9363 // The function returns an ordered list
8696 // representing the tokens found in the supplied 9364 // representing the tokens found in the supplied
8697 // sources string. If two successive tokenizers 9365 // sources string. If two successive tokenizers
8698 // are encountered, then a NULL entry is added 9366 // are encountered, then a null-string entry is
8699 // to the list. 9367 // added to the list.
8700 // 9368 //
8701 // It is a precondition that the source and 9369 // It is a precondition that the source and
8702 // toekizer lisst are non-null. If they are null, 9370 // toekizer lisst are non-null. If they are null,
@@ -8704,7 +9372,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8704 // while their lengths are being determined. 9372 // while their lengths are being determined.
8705 // 9373 //
8706 // A small amount of working memoryis required 9374 // A small amount of working memoryis required
8707 // of approximately 8*#tokenizers. 9375 // of approximately 8*#tokenizers + 8*srcstrlen.
8708 // 9376 //
8709 // There are many ways in which this function 9377 // There are many ways in which this function
8710 // can be implemented, this implementation is 9378 // can be implemented, this implementation is
@@ -8720,155 +9388,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8720 // and eliminates redundant tokenizers as soon 9388 // and eliminates redundant tokenizers as soon
8721 // as is possible. 9389 // as is possible.
8722 // 9390 //
8723 // The implementation tries to avoid any copying 9391 // The implementation tries to minimize temporary
8724 // of arrays or other objects. 9392 // garbage generation.
8725 // </remarks> 9393 // </remarks>
8726 9394
8727 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9395 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8728 { 9396 {
8729 int beginning = 0; 9397 return ParseString2List(src, separators, spacers, true);
8730 int srclen = src.Length; 9398 }
8731 int seplen = separators.Length;
8732 object[] separray = separators.Data;
8733 int spclen = spacers.Length;
8734 object[] spcarray = spacers.Data;
8735 int mlen = seplen+spclen;
8736
8737 int[] offset = new int[mlen+1];
8738 bool[] active = new bool[mlen];
8739
8740 int best;
8741 int j;
8742
8743 // Initial capacity reduces resize cost
8744 9399
8745 LSL_List tokens = new LSL_List(); 9400 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9401 {
9402 int srclen = src.Length;
9403 int seplen = separators.Length;
9404 object[] separray = separators.Data;
9405 int spclen = spacers.Length;
9406 object[] spcarray = spacers.Data;
9407 int dellen = 0;
9408 string[] delarray = new string[seplen+spclen];
8746 9409
8747 // All entries are initially valid 9410 int outlen = 0;
9411 string[] outarray = new string[srclen*2+1];
8748 9412
8749 for (int i = 0; i < mlen; i++) 9413 int i, j;
8750 active[i] = true; 9414 string d;
8751 9415
8752 offset[mlen] = srclen; 9416 m_host.AddScriptLPS(1);
8753 9417
8754 while (beginning < srclen) 9418 /*
9419 * Convert separator and spacer lists to C# strings.
9420 * Also filter out null strings so we don't hang.
9421 */
9422 for (i = 0; i < seplen; i ++)
8755 { 9423 {
9424 d = separray[i].ToString();
9425 if (d.Length > 0)
9426 {
9427 delarray[dellen++] = d;
9428 }
9429 }
9430 seplen = dellen;
8756 9431
8757 best = mlen; // as bad as it gets 9432 for (i = 0; i < spclen; i ++)
9433 {
9434 d = spcarray[i].ToString();
9435 if (d.Length > 0)
9436 {
9437 delarray[dellen++] = d;
9438 }
9439 }
8758 9440
8759 // Scan for separators 9441 /*
9442 * Scan through source string from beginning to end.
9443 */
9444 for (i = 0;;)
9445 {
8760 9446
8761 for (j = 0; j < seplen; j++) 9447 /*
9448 * Find earliest delimeter in src starting at i (if any).
9449 */
9450 int earliestDel = -1;
9451 int earliestSrc = srclen;
9452 string earliestStr = null;
9453 for (j = 0; j < dellen; j ++)
8762 { 9454 {
8763 if (separray[j].ToString() == String.Empty) 9455 d = delarray[j];
8764 active[j] = false; 9456 if (d != null)
8765
8766 if (active[j])
8767 { 9457 {
8768 // scan all of the markers 9458 int index = src.IndexOf(d, i);
8769 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9459 if (index < 0)
8770 { 9460 {
8771 // not present at all 9461 delarray[j] = null; // delim nowhere in src, don't check it anymore
8772 active[j] = false;
8773 } 9462 }
8774 else 9463 else if (index < earliestSrc)
8775 { 9464 {
8776 // present and correct 9465 earliestSrc = index; // where delimeter starts in source string
8777 if (offset[j] < offset[best]) 9466 earliestDel = j; // where delimeter is in delarray[]
8778 { 9467 earliestStr = d; // the delimeter string from delarray[]
8779 // closest so far 9468 if (index == i) break; // can't do any better than found at beg of string
8780 best = j;
8781 if (offset[best] == beginning)
8782 break;
8783 }
8784 } 9469 }
8785 } 9470 }
8786 } 9471 }
8787 9472
8788 // Scan for spacers 9473 /*
8789 9474 * Output source string starting at i through start of earliest delimeter.
8790 if (offset[best] != beginning) 9475 */
9476 if (keepNulls || (earliestSrc > i))
8791 { 9477 {
8792 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9478 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8793 {
8794 if (spcarray[j-seplen].ToString() == String.Empty)
8795 active[j] = false;
8796
8797 if (active[j])
8798 {
8799 // scan all of the markers
8800 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8801 {
8802 // not present at all
8803 active[j] = false;
8804 }
8805 else
8806 {
8807 // present and correct
8808 if (offset[j] < offset[best])
8809 {
8810 // closest so far
8811 best = j;
8812 }
8813 }
8814 }
8815 }
8816 } 9479 }
8817 9480
8818 // This is the normal exit from the scanning loop 9481 /*
9482 * If no delimeter found at or after i, we're done scanning.
9483 */
9484 if (earliestDel < 0) break;
8819 9485
8820 if (best == mlen) 9486 /*
9487 * If delimeter was a spacer, output the spacer.
9488 */
9489 if (earliestDel >= seplen)
8821 { 9490 {
8822 // no markers were found on this pass 9491 outarray[outlen++] = earliestStr;
8823 // so we're pretty much done
8824 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8825 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8826 break;
8827 } 9492 }
8828 9493
8829 // Otherwise we just add the newly delimited token 9494 /*
8830 // and recalculate where the search should continue. 9495 * Look at rest of src string following delimeter.
8831 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9496 */
8832 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9497 i = earliestSrc + earliestStr.Length;
8833
8834 if (best < seplen)
8835 {
8836 beginning = offset[best] + (separray[best].ToString()).Length;
8837 }
8838 else
8839 {
8840 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8841 string str = spcarray[best - seplen].ToString();
8842 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8843 tokens.Add(new LSL_String(str));
8844 }
8845 } 9498 }
8846 9499
8847 // This an awkward an not very intuitive boundary case. If the 9500 /*
8848 // last substring is a tokenizer, then there is an implied trailing 9501 * Make up an exact-sized output array suitable for an LSL_List object.
8849 // null list entry. Hopefully the single comparison will not be too 9502 */
8850 // arduous. Alternatively the 'break' could be replced with a return 9503 object[] outlist = new object[outlen];
8851 // but that's shabby programming. 9504 for (i = 0; i < outlen; i ++)
8852
8853 if ((beginning == srclen) && (keepNulls))
8854 { 9505 {
8855 if (srclen != 0) 9506 outlist[i] = new LSL_String(outarray[i]);
8856 tokens.Add(new LSL_String(""));
8857 } 9507 }
8858 9508 return new LSL_List(outlist);
8859 return tokens;
8860 }
8861
8862 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8863 {
8864 m_host.AddScriptLPS(1);
8865 return this.ParseString(src, separators, spacers, false);
8866 }
8867
8868 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8869 {
8870 m_host.AddScriptLPS(1);
8871 return this.ParseString(src, separators, spacers, true);
8872 } 9509 }
8873 9510
8874 public LSL_Integer llGetObjectPermMask(int mask) 9511 public LSL_Integer llGetObjectPermMask(int mask)
@@ -8945,28 +9582,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8945 { 9582 {
8946 m_host.AddScriptLPS(1); 9583 m_host.AddScriptLPS(1);
8947 9584
8948 lock (m_host.TaskInventory) 9585 m_host.TaskInventory.LockItemsForRead(true);
9586 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8949 { 9587 {
8950 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9588 if (inv.Value.Name == item)
8951 { 9589 {
8952 if (inv.Value.Name == item) 9590 m_host.TaskInventory.LockItemsForRead(false);
9591 switch (mask)
8953 { 9592 {
8954 switch (mask) 9593 case 0:
8955 { 9594 return (int)inv.Value.BasePermissions;
8956 case 0: 9595 case 1:
8957 return (int)inv.Value.BasePermissions; 9596 return (int)inv.Value.CurrentPermissions;
8958 case 1: 9597 case 2:
8959 return (int)inv.Value.CurrentPermissions; 9598 return (int)inv.Value.GroupPermissions;
8960 case 2: 9599 case 3:
8961 return (int)inv.Value.GroupPermissions; 9600 return (int)inv.Value.EveryonePermissions;
8962 case 3: 9601 case 4:
8963 return (int)inv.Value.EveryonePermissions; 9602 return (int)inv.Value.NextPermissions;
8964 case 4:
8965 return (int)inv.Value.NextPermissions;
8966 }
8967 } 9603 }
8968 } 9604 }
8969 } 9605 }
9606 m_host.TaskInventory.LockItemsForRead(false);
8970 9607
8971 return -1; 9608 return -1;
8972 } 9609 }
@@ -9013,16 +9650,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9013 { 9650 {
9014 m_host.AddScriptLPS(1); 9651 m_host.AddScriptLPS(1);
9015 9652
9016 lock (m_host.TaskInventory) 9653 m_host.TaskInventory.LockItemsForRead(true);
9654 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9017 { 9655 {
9018 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9656 if (inv.Value.Name == item)
9019 { 9657 {
9020 if (inv.Value.Name == item) 9658 m_host.TaskInventory.LockItemsForRead(false);
9021 { 9659 return inv.Value.CreatorID.ToString();
9022 return inv.Value.CreatorID.ToString();
9023 }
9024 } 9660 }
9025 } 9661 }
9662 m_host.TaskInventory.LockItemsForRead(false);
9026 9663
9027 llSay(0, "No item name '" + item + "'"); 9664 llSay(0, "No item name '" + item + "'");
9028 9665
@@ -9170,7 +9807,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9170 } 9807 }
9171 9808
9172 /// <summary> 9809 /// <summary>
9173 /// illListReplaceList removes the sub-list defined by the inclusive indices 9810 /// llListReplaceList removes the sub-list defined by the inclusive indices
9174 /// start and end and inserts the src list in its place. The inclusive 9811 /// start and end and inserts the src list in its place. The inclusive
9175 /// nature of the indices means that at least one element must be deleted 9812 /// nature of the indices means that at least one element must be deleted
9176 /// if the indices are within the bounds of the existing list. I.e. 2,2 9813 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9227,16 +9864,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9227 // based upon end. Note that if end exceeds the upper 9864 // based upon end. Note that if end exceeds the upper
9228 // bound in this case, the entire destination list 9865 // bound in this case, the entire destination list
9229 // is removed. 9866 // is removed.
9230 else 9867 else if (start == 0)
9231 { 9868 {
9232 if (end + 1 < dest.Length) 9869 if (end + 1 < dest.Length)
9233 {
9234 return src + dest.GetSublist(end + 1, -1); 9870 return src + dest.GetSublist(end + 1, -1);
9235 }
9236 else 9871 else
9237 {
9238 return src; 9872 return src;
9239 } 9873 }
9874 else // Start < 0
9875 {
9876 if (end + 1 < dest.Length)
9877 return dest.GetSublist(end + 1, -1);
9878 else
9879 return new LSL_List();
9240 } 9880 }
9241 } 9881 }
9242 // Finally, if start > end, we strip away a prefix and 9882 // Finally, if start > end, we strip away a prefix and
@@ -9287,17 +9927,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9287 int width = 0; 9927 int width = 0;
9288 int height = 0; 9928 int height = 0;
9289 9929
9290 ParcelMediaCommandEnum? commandToSend = null; 9930 uint commandToSend = 0;
9291 float time = 0.0f; // default is from start 9931 float time = 0.0f; // default is from start
9292 9932
9293 ScenePresence presence = null; 9933 ScenePresence presence = null;
9294 9934
9295 for (int i = 0; i < commandList.Data.Length; i++) 9935 for (int i = 0; i < commandList.Data.Length; i++)
9296 { 9936 {
9297 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 9937 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9298 switch (command) 9938 switch (command)
9299 { 9939 {
9300 case ParcelMediaCommandEnum.Agent: 9940 case (uint)ParcelMediaCommandEnum.Agent:
9301 // we send only to one agent 9941 // we send only to one agent
9302 if ((i + 1) < commandList.Length) 9942 if ((i + 1) < commandList.Length)
9303 { 9943 {
@@ -9314,25 +9954,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9314 } 9954 }
9315 break; 9955 break;
9316 9956
9317 case ParcelMediaCommandEnum.Loop: 9957 case (uint)ParcelMediaCommandEnum.Loop:
9318 loop = 1; 9958 loop = 1;
9319 commandToSend = command; 9959 commandToSend = command;
9320 update = true; //need to send the media update packet to set looping 9960 update = true; //need to send the media update packet to set looping
9321 break; 9961 break;
9322 9962
9323 case ParcelMediaCommandEnum.Play: 9963 case (uint)ParcelMediaCommandEnum.Play:
9324 loop = 0; 9964 loop = 0;
9325 commandToSend = command; 9965 commandToSend = command;
9326 update = true; //need to send the media update packet to make sure it doesn't loop 9966 update = true; //need to send the media update packet to make sure it doesn't loop
9327 break; 9967 break;
9328 9968
9329 case ParcelMediaCommandEnum.Pause: 9969 case (uint)ParcelMediaCommandEnum.Pause:
9330 case ParcelMediaCommandEnum.Stop: 9970 case (uint)ParcelMediaCommandEnum.Stop:
9331 case ParcelMediaCommandEnum.Unload: 9971 case (uint)ParcelMediaCommandEnum.Unload:
9332 commandToSend = command; 9972 commandToSend = command;
9333 break; 9973 break;
9334 9974
9335 case ParcelMediaCommandEnum.Url: 9975 case (uint)ParcelMediaCommandEnum.Url:
9336 if ((i + 1) < commandList.Length) 9976 if ((i + 1) < commandList.Length)
9337 { 9977 {
9338 if (commandList.Data[i + 1] is LSL_String) 9978 if (commandList.Data[i + 1] is LSL_String)
@@ -9345,7 +9985,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9345 } 9985 }
9346 break; 9986 break;
9347 9987
9348 case ParcelMediaCommandEnum.Texture: 9988 case (uint)ParcelMediaCommandEnum.Texture:
9349 if ((i + 1) < commandList.Length) 9989 if ((i + 1) < commandList.Length)
9350 { 9990 {
9351 if (commandList.Data[i + 1] is LSL_String) 9991 if (commandList.Data[i + 1] is LSL_String)
@@ -9358,7 +9998,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9358 } 9998 }
9359 break; 9999 break;
9360 10000
9361 case ParcelMediaCommandEnum.Time: 10001 case (uint)ParcelMediaCommandEnum.Time:
9362 if ((i + 1) < commandList.Length) 10002 if ((i + 1) < commandList.Length)
9363 { 10003 {
9364 if (commandList.Data[i + 1] is LSL_Float) 10004 if (commandList.Data[i + 1] is LSL_Float)
@@ -9370,7 +10010,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9370 } 10010 }
9371 break; 10011 break;
9372 10012
9373 case ParcelMediaCommandEnum.AutoAlign: 10013 case (uint)ParcelMediaCommandEnum.AutoAlign:
9374 if ((i + 1) < commandList.Length) 10014 if ((i + 1) < commandList.Length)
9375 { 10015 {
9376 if (commandList.Data[i + 1] is LSL_Integer) 10016 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9384,7 +10024,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9384 } 10024 }
9385 break; 10025 break;
9386 10026
9387 case ParcelMediaCommandEnum.Type: 10027 case (uint)ParcelMediaCommandEnum.Type:
9388 if ((i + 1) < commandList.Length) 10028 if ((i + 1) < commandList.Length)
9389 { 10029 {
9390 if (commandList.Data[i + 1] is LSL_String) 10030 if (commandList.Data[i + 1] is LSL_String)
@@ -9397,7 +10037,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9397 } 10037 }
9398 break; 10038 break;
9399 10039
9400 case ParcelMediaCommandEnum.Desc: 10040 case (uint)ParcelMediaCommandEnum.Desc:
9401 if ((i + 1) < commandList.Length) 10041 if ((i + 1) < commandList.Length)
9402 { 10042 {
9403 if (commandList.Data[i + 1] is LSL_String) 10043 if (commandList.Data[i + 1] is LSL_String)
@@ -9410,7 +10050,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9410 } 10050 }
9411 break; 10051 break;
9412 10052
9413 case ParcelMediaCommandEnum.Size: 10053 case (uint)ParcelMediaCommandEnum.Size:
9414 if ((i + 2) < commandList.Length) 10054 if ((i + 2) < commandList.Length)
9415 { 10055 {
9416 if (commandList.Data[i + 1] is LSL_Integer) 10056 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9480,7 +10120,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9480 } 10120 }
9481 } 10121 }
9482 10122
9483 if (commandToSend != null) 10123 if (commandToSend != 0)
9484 { 10124 {
9485 // the commandList contained a start/stop/... command, too 10125 // the commandList contained a start/stop/... command, too
9486 if (presence == null) 10126 if (presence == null)
@@ -9517,7 +10157,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9517 10157
9518 if (aList.Data[i] != null) 10158 if (aList.Data[i] != null)
9519 { 10159 {
9520 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10160 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9521 { 10161 {
9522 case ParcelMediaCommandEnum.Url: 10162 case ParcelMediaCommandEnum.Url:
9523 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10163 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9560,16 +10200,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9560 { 10200 {
9561 m_host.AddScriptLPS(1); 10201 m_host.AddScriptLPS(1);
9562 10202
9563 lock (m_host.TaskInventory) 10203 m_host.TaskInventory.LockItemsForRead(true);
10204 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9564 { 10205 {
9565 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10206 if (inv.Value.Name == name)
9566 { 10207 {
9567 if (inv.Value.Name == name) 10208 m_host.TaskInventory.LockItemsForRead(false);
9568 { 10209 return inv.Value.Type;
9569 return inv.Value.Type;
9570 }
9571 } 10210 }
9572 } 10211 }
10212 m_host.TaskInventory.LockItemsForRead(false);
9573 10213
9574 return -1; 10214 return -1;
9575 } 10215 }
@@ -9580,15 +10220,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9580 10220
9581 if (quick_pay_buttons.Data.Length < 4) 10221 if (quick_pay_buttons.Data.Length < 4)
9582 { 10222 {
9583 LSLError("List must have at least 4 elements"); 10223 int x;
9584 return; 10224 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10225 {
10226 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10227 }
9585 } 10228 }
9586 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10229 int[] nPrice = new int[5];
9587 10230 nPrice[0] = price;
9588 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10231 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9589 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10232 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9590 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10233 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9591 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10234 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10235 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9592 m_host.ParentGroup.HasGroupChanged = true; 10236 m_host.ParentGroup.HasGroupChanged = true;
9593 } 10237 }
9594 10238
@@ -9600,17 +10244,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9600 if (invItemID == UUID.Zero) 10244 if (invItemID == UUID.Zero)
9601 return new LSL_Vector(); 10245 return new LSL_Vector();
9602 10246
9603 lock (m_host.TaskInventory) 10247 m_host.TaskInventory.LockItemsForRead(true);
10248 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9604 { 10249 {
9605 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10250 m_host.TaskInventory.LockItemsForRead(false);
9606 return new LSL_Vector(); 10251 return new LSL_Vector();
10252 }
9607 10253
9608 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 10254 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9609 { 10255 {
9610 ShoutError("No permissions to track the camera"); 10256 ShoutError("No permissions to track the camera");
9611 return new LSL_Vector(); 10257 m_host.TaskInventory.LockItemsForRead(false);
9612 } 10258 return new LSL_Vector();
9613 } 10259 }
10260 m_host.TaskInventory.LockItemsForRead(false);
9614 10261
9615 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10262 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9616 if (presence != null) 10263 if (presence != null)
@@ -9628,17 +10275,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9628 if (invItemID == UUID.Zero) 10275 if (invItemID == UUID.Zero)
9629 return new LSL_Rotation(); 10276 return new LSL_Rotation();
9630 10277
9631 lock (m_host.TaskInventory) 10278 m_host.TaskInventory.LockItemsForRead(true);
10279 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9632 { 10280 {
9633 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10281 m_host.TaskInventory.LockItemsForRead(false);
9634 return new LSL_Rotation(); 10282 return new LSL_Rotation();
9635 10283 }
9636 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 10284 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9637 { 10285 {
9638 ShoutError("No permissions to track the camera"); 10286 ShoutError("No permissions to track the camera");
9639 return new LSL_Rotation(); 10287 m_host.TaskInventory.LockItemsForRead(false);
9640 } 10288 return new LSL_Rotation();
9641 } 10289 }
10290 m_host.TaskInventory.LockItemsForRead(false);
9642 10291
9643 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10292 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9644 if (presence != null) 10293 if (presence != null)
@@ -9700,8 +10349,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9700 { 10349 {
9701 m_host.AddScriptLPS(1); 10350 m_host.AddScriptLPS(1);
9702 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0); 10351 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0);
9703 if (detectedParams == null) return; // only works on the first detected avatar 10352 if (detectedParams == null)
9704 10353 {
10354 if (m_host.ParentGroup.IsAttachment == true)
10355 {
10356 detectedParams = new DetectParams();
10357 detectedParams.Key = m_host.OwnerID;
10358 }
10359 else
10360 {
10361 return;
10362 }
10363 }
10364
9705 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10365 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9706 if (avatar != null) 10366 if (avatar != null)
9707 { 10367 {
@@ -9709,6 +10369,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9709 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10369 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9710 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10370 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9711 } 10371 }
10372
9712 ScriptSleep(1000); 10373 ScriptSleep(1000);
9713 } 10374 }
9714 10375
@@ -9820,14 +10481,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9820 if (objectID == UUID.Zero) return; 10481 if (objectID == UUID.Zero) return;
9821 10482
9822 UUID agentID; 10483 UUID agentID;
9823 lock (m_host.TaskInventory) 10484 m_host.TaskInventory.LockItemsForRead(true);
9824 { 10485 // we need the permission first, to know which avatar we want to set the camera for
9825 // we need the permission first, to know which avatar we want to set the camera for 10486 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9826 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9827 10487
9828 if (agentID == UUID.Zero) return; 10488 if (agentID == UUID.Zero)
9829 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 10489 {
10490 m_host.TaskInventory.LockItemsForRead(false);
10491 return;
9830 } 10492 }
10493 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10494 {
10495 m_host.TaskInventory.LockItemsForRead(false);
10496 return;
10497 }
10498 m_host.TaskInventory.LockItemsForRead(false);
9831 10499
9832 ScenePresence presence = World.GetScenePresence(agentID); 10500 ScenePresence presence = World.GetScenePresence(agentID);
9833 10501
@@ -9836,12 +10504,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9836 10504
9837 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10505 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9838 object[] data = rules.Data; 10506 object[] data = rules.Data;
9839 for (int i = 0; i < data.Length; ++i) { 10507 for (int i = 0; i < data.Length; ++i)
10508 {
9840 int type = Convert.ToInt32(data[i++].ToString()); 10509 int type = Convert.ToInt32(data[i++].ToString());
9841 if (i >= data.Length) break; // odd number of entries => ignore the last 10510 if (i >= data.Length) break; // odd number of entries => ignore the last
9842 10511
9843 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10512 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9844 switch (type) { 10513 switch (type)
10514 {
9845 case ScriptBaseClass.CAMERA_FOCUS: 10515 case ScriptBaseClass.CAMERA_FOCUS:
9846 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10516 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9847 case ScriptBaseClass.CAMERA_POSITION: 10517 case ScriptBaseClass.CAMERA_POSITION:
@@ -9877,12 +10547,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9877 10547
9878 // we need the permission first, to know which avatar we want to clear the camera for 10548 // we need the permission first, to know which avatar we want to clear the camera for
9879 UUID agentID; 10549 UUID agentID;
9880 lock (m_host.TaskInventory) 10550 m_host.TaskInventory.LockItemsForRead(true);
10551 agentID = m_host.TaskInventory[invItemID].PermsGranter;
10552 if (agentID == UUID.Zero)
9881 { 10553 {
9882 agentID = m_host.TaskInventory[invItemID].PermsGranter; 10554 m_host.TaskInventory.LockItemsForRead(false);
9883 if (agentID == UUID.Zero) return; 10555 return;
9884 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 10556 }
10557 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10558 {
10559 m_host.TaskInventory.LockItemsForRead(false);
10560 return;
9885 } 10561 }
10562 m_host.TaskInventory.LockItemsForRead(false);
9886 10563
9887 ScenePresence presence = World.GetScenePresence(agentID); 10564 ScenePresence presence = World.GetScenePresence(agentID);
9888 10565
@@ -9949,19 +10626,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9949 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10626 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
9950 { 10627 {
9951 m_host.AddScriptLPS(1); 10628 m_host.AddScriptLPS(1);
9952 string ret = String.Empty; 10629
9953 string src1 = llBase64ToString(str1); 10630 if (str1 == String.Empty)
9954 string src2 = llBase64ToString(str2); 10631 return String.Empty;
9955 int c = 0; 10632 if (str2 == String.Empty)
9956 for (int i = 0; i < src1.Length; i++) 10633 return str1;
10634
10635 int len = str2.Length;
10636 if ((len % 4) != 0) // LL is EVIL!!!!
10637 {
10638 while (str2.EndsWith("="))
10639 str2 = str2.Substring(0, str2.Length - 1);
10640
10641 len = str2.Length;
10642 int mod = len % 4;
10643
10644 if (mod == 1)
10645 str2 = str2.Substring(0, str2.Length - 1);
10646 else if (mod == 2)
10647 str2 += "==";
10648 else if (mod == 3)
10649 str2 += "=";
10650 }
10651
10652 byte[] data1;
10653 byte[] data2;
10654 try
10655 {
10656 data1 = Convert.FromBase64String(str1);
10657 data2 = Convert.FromBase64String(str2);
10658 }
10659 catch (Exception)
9957 { 10660 {
9958 ret += (char) (src1[i] ^ src2[c]); 10661 return new LSL_String(String.Empty);
10662 }
9959 10663
9960 c++; 10664 byte[] d2 = new Byte[data1.Length];
9961 if (c >= src2.Length) 10665 int pos = 0;
9962 c = 0; 10666
10667 if (data1.Length <= data2.Length)
10668 {
10669 Array.Copy(data2, 0, d2, 0, data1.Length);
9963 } 10670 }
9964 return llStringToBase64(ret); 10671 else
10672 {
10673 while (pos < data1.Length)
10674 {
10675 len = data1.Length - pos;
10676 if (len > data2.Length)
10677 len = data2.Length;
10678
10679 Array.Copy(data2, 0, d2, pos, len);
10680 pos += len;
10681 }
10682 }
10683
10684 for (pos = 0 ; pos < data1.Length ; pos++ )
10685 data1[pos] ^= d2[pos];
10686
10687 return Convert.ToBase64String(data1);
9965 } 10688 }
9966 10689
9967 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10690 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10018,12 +10741,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10018 Regex r = new Regex(authregex); 10741 Regex r = new Regex(authregex);
10019 int[] gnums = r.GetGroupNumbers(); 10742 int[] gnums = r.GetGroupNumbers();
10020 Match m = r.Match(url); 10743 Match m = r.Match(url);
10021 if (m.Success) { 10744 if (m.Success)
10022 for (int i = 1; i < gnums.Length; i++) { 10745 {
10746 for (int i = 1; i < gnums.Length; i++)
10747 {
10023 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10748 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10024 //CaptureCollection cc = g.Captures; 10749 //CaptureCollection cc = g.Captures;
10025 } 10750 }
10026 if (m.Groups.Count == 5) { 10751 if (m.Groups.Count == 5)
10752 {
10027 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10753 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10028 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10754 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10029 } 10755 }
@@ -10309,15 +11035,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10309 11035
10310 internal UUID ScriptByName(string name) 11036 internal UUID ScriptByName(string name)
10311 { 11037 {
10312 lock (m_host.TaskInventory) 11038 m_host.TaskInventory.LockItemsForRead(true);
11039
11040 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10313 { 11041 {
10314 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 11042 if (item.Type == 10 && item.Name == name)
10315 { 11043 {
10316 if (item.Type == 10 && item.Name == name) 11044 m_host.TaskInventory.LockItemsForRead(false);
10317 return item.ItemID; 11045 return item.ItemID;
10318 } 11046 }
10319 } 11047 }
10320 11048
11049 m_host.TaskInventory.LockItemsForRead(false);
11050
10321 return UUID.Zero; 11051 return UUID.Zero;
10322 } 11052 }
10323 11053
@@ -10358,6 +11088,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10358 { 11088 {
10359 m_host.AddScriptLPS(1); 11089 m_host.AddScriptLPS(1);
10360 11090
11091 //Clone is thread safe
10361 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11092 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10362 11093
10363 UUID assetID = UUID.Zero; 11094 UUID assetID = UUID.Zero;
@@ -10420,6 +11151,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10420 { 11151 {
10421 m_host.AddScriptLPS(1); 11152 m_host.AddScriptLPS(1);
10422 11153
11154 //Clone is thread safe
10423 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11155 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10424 11156
10425 UUID assetID = UUID.Zero; 11157 UUID assetID = UUID.Zero;
@@ -10500,15 +11232,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10500 return GetLinkPrimitiveParams(obj, rules); 11232 return GetLinkPrimitiveParams(obj, rules);
10501 } 11233 }
10502 11234
10503 public void print(string str) 11235 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10504 { 11236 {
10505 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11237 List<SceneObjectPart> parts = GetLinkParts(link);
10506 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_itemID, "OSSL"); 11238 if (parts.Count < 1)
10507 if (ossl != null) 11239 return 0;
10508 { 11240
10509 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11241 return GetNumberOfSides(parts[0]);
10510 m_log.Info("LSL print():" + str);
10511 }
10512 } 11242 }
10513 11243
10514 private string Name2Username(string name) 11244 private string Name2Username(string name)
@@ -10554,153 +11284,392 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10554 return rq.ToString(); 11284 return rq.ToString();
10555 } 11285 }
10556 11286
11287 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11288 {
11289 m_SayShoutCount = 0;
11290 }
11291
11292 private struct Tri
11293 {
11294 public Vector3 p1;
11295 public Vector3 p2;
11296 public Vector3 p3;
11297 }
11298
11299 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11300 {
11301 float height = avatar.Appearance.AvatarHeight;
11302 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11303 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11304
11305 if (point.X > b1.X && point.X < b2.X &&
11306 point.Y > b1.Y && point.Y < b2.Y &&
11307 point.Z > b1.Z && point.Z < b2.Z)
11308 return true;
11309 return false;
11310 }
11311
11312 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11313 {
11314 List<ContactResult> contacts = new List<ContactResult>();
11315
11316 Vector3 ab = rayEnd - rayStart;
11317
11318 World.ForEachScenePresence(delegate(ScenePresence sp)
11319 {
11320 Vector3 ac = sp.AbsolutePosition - rayStart;
11321 Vector3 bc = sp.AbsolutePosition - rayEnd;
11322
11323 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11324
11325 if (d > 1.5)
11326 return;
11327
11328 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11329
11330 if (d2 > 0)
11331 return;
11332
11333 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11334 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11335
11336 if (!InBoundingBox(sp, p))
11337 return;
11338
11339 ContactResult result = new ContactResult ();
11340 result.ConsumerID = sp.LocalId;
11341 result.Depth = Vector3.Distance(rayStart, p);
11342 result.Normal = Vector3.Zero;
11343 result.Pos = p;
11344
11345 contacts.Add(result);
11346 });
11347
11348 return contacts.ToArray();
11349 }
11350
11351 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11352 {
11353 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11354 List<ContactResult> contacts = new List<ContactResult>();
11355
11356 Vector3 ab = rayEnd - rayStart;
11357
11358 World.ForEachSOG(delegate(SceneObjectGroup group)
11359 {
11360 if (m_host.ParentGroup == group)
11361 return;
11362
11363 if (group.IsAttachment)
11364 return;
11365
11366 if (group.RootPart.PhysActor == null)
11367 {
11368 if (!includePhantom)
11369 return;
11370 }
11371 else
11372 {
11373 if (group.RootPart.PhysActor.IsPhysical)
11374 {
11375 if (!includePhysical)
11376 return;
11377 }
11378 else
11379 {
11380 if (!includeNonPhysical)
11381 return;
11382 }
11383 }
11384
11385 // Find the radius ouside of which we don't even need to hit test
11386 float minX;
11387 float maxX;
11388 float minY;
11389 float maxY;
11390 float minZ;
11391 float maxZ;
11392
11393 float radius = 0.0f;
11394
11395 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11396
11397 if (Math.Abs(minX) > radius)
11398 radius = Math.Abs(minX);
11399 if (Math.Abs(minY) > radius)
11400 radius = Math.Abs(minY);
11401 if (Math.Abs(minZ) > radius)
11402 radius = Math.Abs(minZ);
11403 if (Math.Abs(maxX) > radius)
11404 radius = Math.Abs(maxX);
11405 if (Math.Abs(maxY) > radius)
11406 radius = Math.Abs(maxY);
11407 if (Math.Abs(maxZ) > radius)
11408 radius = Math.Abs(maxZ);
11409
11410 Vector3 ac = group.AbsolutePosition - rayStart;
11411 Vector3 bc = group.AbsolutePosition - rayEnd;
11412
11413 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11414
11415 // Too far off ray, don't bother
11416 if (d > radius)
11417 return;
11418
11419 // Behind ray, drop
11420 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11421 if (d2 > 0)
11422 return;
11423
11424 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11425 // Miss.
11426 if (!intersection.HitTF)
11427 return;
11428
11429 ContactResult result = new ContactResult ();
11430 result.ConsumerID = group.LocalId;
11431 result.Depth = intersection.distance;
11432 result.Normal = intersection.normal;
11433 result.Pos = intersection.ipoint;
11434
11435 contacts.Add(result);
11436 });
11437
11438 return contacts.ToArray();
11439 }
11440
11441 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11442 {
11443 double[,] heightfield = World.Heightmap.GetDoubles();
11444 List<ContactResult> contacts = new List<ContactResult>();
11445
11446 double min = 2048.0;
11447 double max = 0.0;
11448
11449 // Find the min and max of the heightfield
11450 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11451 {
11452 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11453 {
11454 if (heightfield[x, y] > max)
11455 max = heightfield[x, y];
11456 if (heightfield[x, y] < min)
11457 min = heightfield[x, y];
11458 }
11459 }
11460
11461
11462 // A ray extends past rayEnd, but doesn't go back before
11463 // rayStart. If the start is above the highest point of the ground
11464 // and the ray goes up, we can't hit the ground. Ever.
11465 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11466 return null;
11467
11468 // Same for going down
11469 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11470 return null;
11471
11472 List<Tri> trilist = new List<Tri>();
11473
11474 // Create our triangle list
11475 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11476 {
11477 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11478 {
11479 Tri t1 = new Tri();
11480 Tri t2 = new Tri();
11481
11482 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11483 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11484 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11485 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11486
11487 t1.p1 = p1;
11488 t1.p2 = p2;
11489 t1.p3 = p3;
11490
11491 t2.p1 = p3;
11492 t2.p2 = p4;
11493 t2.p3 = p1;
11494
11495 trilist.Add(t1);
11496 trilist.Add(t2);
11497 }
11498 }
11499
11500 // Ray direction
11501 Vector3 rayDirection = rayEnd - rayStart;
11502
11503 foreach (Tri t in trilist)
11504 {
11505 // Compute triangle plane normal and edges
11506 Vector3 u = t.p2 - t.p1;
11507 Vector3 v = t.p3 - t.p1;
11508 Vector3 n = Vector3.Cross(u, v);
11509
11510 if (n == Vector3.Zero)
11511 continue;
11512
11513 Vector3 w0 = rayStart - t.p1;
11514 double a = -Vector3.Dot(n, w0);
11515 double b = Vector3.Dot(n, rayDirection);
11516
11517 // Not intersecting the plane, or in plane (same thing)
11518 // Ignoring this MAY cause the ground to not be detected
11519 // sometimes
11520 if (Math.Abs(b) < 0.000001)
11521 continue;
11522
11523 double r = a / b;
11524
11525 // ray points away from plane
11526 if (r < 0.0)
11527 continue;
11528
11529 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11530
11531 float uu = Vector3.Dot(u, u);
11532 float uv = Vector3.Dot(u, v);
11533 float vv = Vector3.Dot(v, v);
11534 Vector3 w = ip - t.p1;
11535 float wu = Vector3.Dot(w, u);
11536 float wv = Vector3.Dot(w, v);
11537 float d = uv * uv - uu * vv;
11538
11539 float cs = (uv * wv - vv * wu) / d;
11540 if (cs < 0 || cs > 1.0)
11541 continue;
11542 float ct = (uv * wu - uu * wv) / d;
11543 if (ct < 0 || (cs + ct) > 1.0)
11544 continue;
11545
11546 // Add contact point
11547 ContactResult result = new ContactResult ();
11548 result.ConsumerID = 0;
11549 result.Depth = Vector3.Distance(rayStart, ip);
11550 result.Normal = n;
11551 result.Pos = ip;
11552
11553 contacts.Add(result);
11554 }
11555
11556 if (contacts.Count == 0)
11557 return null;
11558
11559 contacts.Sort(delegate(ContactResult a, ContactResult b)
11560 {
11561 return (int)(a.Depth - b.Depth);
11562 });
11563
11564 return contacts[0];
11565 }
11566
10557 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11567 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10558 { 11568 {
11569 LSL_List list = new LSL_List();
11570
10559 m_host.AddScriptLPS(1); 11571 m_host.AddScriptLPS(1);
10560 11572
10561 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11573 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10562 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11574 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10563 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11575 Vector3 dir = rayEnd - rayStart;
10564 11576
10565 int count = 0; 11577 int count = 1;
10566// int detectPhantom = 0; 11578 bool detectPhantom = false;
10567 int dataFlags = 0; 11579 int dataFlags = 0;
10568 int rejectTypes = 0; 11580 int rejectTypes = 0;
10569 11581
10570 for (int i = 0; i < options.Length; i += 2) 11582 for (int i = 0; i < options.Length; i += 2)
10571 { 11583 {
10572 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11584 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10573 {
10574 count = options.GetLSLIntegerItem(i + 1); 11585 count = options.GetLSLIntegerItem(i + 1);
10575 } 11586 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10576// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11587 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10577// {
10578// detectPhantom = options.GetLSLIntegerItem(i + 1);
10579// }
10580 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11588 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10581 {
10582 dataFlags = options.GetLSLIntegerItem(i + 1); 11589 dataFlags = options.GetLSLIntegerItem(i + 1);
10583 }
10584 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11590 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10585 {
10586 rejectTypes = options.GetLSLIntegerItem(i + 1); 11591 rejectTypes = options.GetLSLIntegerItem(i + 1);
10587 }
10588 } 11592 }
10589 11593
10590 LSL_List list = new LSL_List(); 11594 if (count > 16)
10591 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11595 count = 16;
10592
10593 double distance = Util.GetDistanceTo(startvector, endvector);
10594 11596
10595 if (distance == 0) 11597 List<ContactResult> results = new List<ContactResult>();
10596 distance = 0.001;
10597
10598 Vector3 posToCheck = startvector;
10599 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10600 11598
10601 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11599 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10602 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11600 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10603 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11601 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10604 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11602 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10605 11603
10606 for (float i = 0; i <= distance; i += 0.1f) 11604 if (checkTerrain)
10607 { 11605 {
10608 posToCheck = startvector + (dir * (i / (float)distance)); 11606 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11607 if (groundContact != null)
11608 results.Add((ContactResult)groundContact);
11609 }
10609 11610
10610 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11611 if (checkAgents)
10611 { 11612 {
10612 ContactResult result = new ContactResult(); 11613 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
10613 result.ConsumerID = 0; 11614 foreach (ContactResult r in agentHits)
10614 result.Depth = 0; 11615 results.Add(r);
10615 result.Normal = Vector3.Zero; 11616 }
10616 result.Pos = posToCheck;
10617 results.Add(result);
10618 checkTerrain = false;
10619 }
10620 11617
10621 if (checkAgents) 11618 if (checkPhysical || checkNonPhysical)
10622 { 11619 {
10623 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11620 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
10624 { 11621 foreach (ContactResult r in objectHits)
10625 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X)) 11622 results.Add(r);
10626 {
10627 ContactResult result = new ContactResult ();
10628 result.ConsumerID = sp.LocalId;
10629 result.Depth = 0;
10630 result.Normal = Vector3.Zero;
10631 result.Pos = posToCheck;
10632 results.Add(result);
10633 }
10634 });
10635 }
10636 } 11623 }
10637 11624
10638 int refcount = 0; 11625 results.Sort(delegate(ContactResult a, ContactResult b)
11626 {
11627 return (int)(a.Depth - b.Depth);
11628 });
11629
11630 int values = 0;
10639 foreach (ContactResult result in results) 11631 foreach (ContactResult result in results)
10640 { 11632 {
10641 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) 11633 UUID itemID = UUID.Zero;
10642 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0) 11634 int linkNum = 0;
10643 continue;
10644
10645 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID);
10646
10647 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS)
10648 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents
10649 11635
10650 if (entity == null) 11636 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
11637 // It's a prim!
11638 if (part != null)
10651 { 11639 {
10652 list.Add(UUID.Zero); 11640 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10653 11641 itemID = part.ParentGroup.UUID;
10654 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11642 else
10655 list.Add(0); 11643 itemID = part.UUID;
10656
10657 list.Add(result.Pos);
10658
10659 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10660 list.Add(result.Normal);
10661 11644
10662 continue; //Can't find it, so add UUID.Zero 11645 linkNum = part.LinkNum;
10663 } 11646 }
10664 11647 else
10665 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity &&
10666 ((ISceneChildEntity)intersection.obj).PhysActor == null)
10667 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
10668
10669 if (entity is SceneObjectPart)
10670 { 11648 {
10671 if (((SceneObjectPart)entity).PhysActor != null && ((SceneObjectPart)entity).PhysActor.IsPhysical) 11649 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10672 { 11650 /// It it a boy? a girl?
10673 if (!checkPhysical) 11651 if (sp != null)
10674 continue; 11652 itemID = sp.UUID;
10675 }
10676 else
10677 {
10678 if (!checkNonPhysical)
10679 continue;
10680 }
10681 } 11653 }
10682 11654
10683 refcount++; 11655 list.Add(new LSL_String(itemID.ToString()));
10684 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11656 list.Add(new LSL_String(result.Pos.ToString()));
10685 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10686 else
10687 list.Add(entity.UUID);
10688 11657
10689 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11658 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10690 { 11659 list.Add(new LSL_Integer(linkNum));
10691 if (entity is SceneObjectPart)
10692 list.Add(((SceneObjectPart)entity).LinkNum);
10693 else
10694 list.Add(0);
10695 }
10696 11660
10697 list.Add(result.Pos);
10698 11661
10699 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11662 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10700 list.Add(result.Normal); 11663 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11664
11665 values++;
11666 count--;
11667
11668 if (count == 0)
11669 break;
10701 } 11670 }
10702 11671
10703 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11672 list.Add(new LSL_Integer(values));
10704 11673
10705 return list; 11674 return list;
10706 } 11675 }
@@ -10740,7 +11709,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10740 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 11709 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10741 if (!isAccount) return 0; 11710 if (!isAccount) return 0;
10742 if (estate.HasAccess(id)) return 1; 11711 if (estate.HasAccess(id)) return 1;
10743 if (estate.IsBanned(id)) 11712 if (estate.IsBanned(id, World.GetUserFlags(id)))
10744 estate.RemoveBan(id); 11713 estate.RemoveBan(id);
10745 estate.AddEstateUser(id); 11714 estate.AddEstateUser(id);
10746 break; 11715 break;
@@ -10759,14 +11728,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10759 break; 11728 break;
10760 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 11729 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10761 if (!isAccount) return 0; 11730 if (!isAccount) return 0;
10762 if (estate.IsBanned(id)) return 1; 11731 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10763 EstateBan ban = new EstateBan(); 11732 EstateBan ban = new EstateBan();
10764 ban.EstateID = estate.EstateID; 11733 ban.EstateID = estate.EstateID;
10765 ban.BannedUserID = id; 11734 ban.BannedUserID = id;
10766 estate.AddBan(ban); 11735 estate.AddBan(ban);
10767 break; 11736 break;
10768 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 11737 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10769 if (!isAccount || !estate.IsBanned(id)) return 0; 11738 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10770 estate.RemoveBan(id); 11739 estate.RemoveBan(id);
10771 break; 11740 break;
10772 default: return 0; 11741 default: return 0;
@@ -10792,22 +11761,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10792 NotImplemented("llGetSPMaxMemory"); 11761 NotImplemented("llGetSPMaxMemory");
10793 } 11762 }
10794 11763
10795 public void llGetUsedMemory() 11764 public virtual LSL_Integer llGetUsedMemory()
10796 { 11765 {
10797 m_host.AddScriptLPS(1); 11766 m_host.AddScriptLPS(1);
10798 NotImplemented("llGetUsedMemory"); 11767 NotImplemented("llGetUsedMemory");
11768 return 0;
10799 } 11769 }
10800 11770
10801 public void llScriptProfiler(LSL_Integer flags) 11771 public void llScriptProfiler(LSL_Integer flags)
10802 { 11772 {
10803 m_host.AddScriptLPS(1); 11773 m_host.AddScriptLPS(1);
10804 NotImplemented("llScriptProfiler"); 11774 //NotImplemented("llScriptProfiler");
10805 } 11775 }
10806 11776
10807 public void llSetSoundQueueing(int queue) 11777 public void llSetSoundQueueing(int queue)
10808 { 11778 {
10809 m_host.AddScriptLPS(1); 11779 m_host.AddScriptLPS(1);
10810 NotImplemented("llSetSoundQueueing");
10811 } 11780 }
10812 11781
10813 public void llCollisionSprite(string impact_sprite) 11782 public void llCollisionSprite(string impact_sprite)
@@ -10819,7 +11788,133 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10819 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 11788 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10820 { 11789 {
10821 m_host.AddScriptLPS(1); 11790 m_host.AddScriptLPS(1);
10822 NotImplemented("llGodLikeRezObject"); 11791
11792 if (!World.Permissions.IsGod(m_host.OwnerID))
11793 NotImplemented("llGodLikeRezObject");
11794
11795 AssetBase rezAsset = World.AssetService.Get(inventory);
11796 if (rezAsset == null)
11797 {
11798 llSay(0, "Asset not found");
11799 return;
11800 }
11801
11802 SceneObjectGroup group = null;
11803
11804 try
11805 {
11806 string xmlData = Utils.BytesToString(rezAsset.Data);
11807 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
11808 }
11809 catch
11810 {
11811 llSay(0, "Asset not found");
11812 return;
11813 }
11814
11815 if (group == null)
11816 {
11817 llSay(0, "Asset not found");
11818 return;
11819 }
11820
11821 group.RootPart.AttachPoint = group.RootPart.Shape.State;
11822 group.RootPart.AttachOffset = group.AbsolutePosition;
11823
11824 group.ResetIDs();
11825
11826 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
11827 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
11828 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
11829 group.ScheduleGroupForFullUpdate();
11830
11831 // objects rezzed with this method are die_at_edge by default.
11832 group.RootPart.SetDieAtEdge(true);
11833
11834 group.ResumeScripts();
11835
11836 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
11837 "object_rez", new Object[] {
11838 new LSL_String(
11839 group.RootPart.UUID.ToString()) },
11840 new DetectParams[0]));
11841 }
11842
11843 public LSL_String llTransferLindenDollars(string destination, int amount)
11844 {
11845 UUID txn = UUID.Random();
11846
11847 Util.FireAndForget(delegate(object x)
11848 {
11849 int replycode = 0;
11850 string replydata = destination + "," + amount.ToString();
11851
11852 try
11853 {
11854 UUID invItemID=InventorySelf();
11855 if (invItemID == UUID.Zero)
11856 {
11857 replydata = "SERVICE_ERROR";
11858 return;
11859 }
11860
11861 m_host.AddScriptLPS(1);
11862
11863 m_host.TaskInventory.LockItemsForRead(true);
11864 TaskInventoryItem item = m_host.TaskInventory[invItemID];
11865 m_host.TaskInventory.LockItemsForRead(false);
11866
11867 if (item.PermsGranter == UUID.Zero)
11868 {
11869 replydata = "MISSING_PERMISSION_DEBIT";
11870 return;
11871 }
11872
11873 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
11874 {
11875 replydata = "MISSING_PERMISSION_DEBIT";
11876 return;
11877 }
11878
11879 UUID toID = new UUID();
11880
11881 if (!UUID.TryParse(destination, out toID))
11882 {
11883 replydata = "INVALID_AGENT";
11884 return;
11885 }
11886
11887 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
11888
11889 if (money == null)
11890 {
11891 replydata = "TRANSFERS_DISABLED";
11892 return;
11893 }
11894
11895 bool result = money.ObjectGiveMoney(
11896 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
11897
11898 if (result)
11899 {
11900 replycode = 1;
11901 return;
11902 }
11903
11904 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
11905 }
11906 finally
11907 {
11908 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
11909 "transaction_result", new Object[] {
11910 new LSL_String(txn.ToString()),
11911 new LSL_Integer(replycode),
11912 new LSL_String(replydata) },
11913 new DetectParams[0]));
11914 }
11915 });
11916
11917 return txn.ToString();
10823 } 11918 }
10824 11919
10825 #endregion 11920 #endregion