aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Api/Implementation
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs20
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs116
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs2978
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs102
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs32
6 files changed, 2399 insertions, 860 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 993d10f..3cbdde5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -301,6 +301,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
301 return null; 301 return null;
302 } 302 }
303 303
304 public static void StateChange(IScriptEngine engine, uint localID, UUID itemID)
305 {
306 // Remove a specific script
307
308 // Remove dataserver events
309 m_Dataserver[engine].RemoveEvents(localID, itemID);
310
311 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>();
312 if (comms != null)
313 comms.DeleteListener(itemID);
314
315 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>();
316 xmlrpc.DeleteChannels(itemID);
317 xmlrpc.CancelSRDRequests(itemID);
318
319 // Remove Sensors
320 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID);
321
322 }
323
304 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID) 324 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID)
305 { 325 {
306 List<Object> data = new List<Object>(); 326 List<Object> data = new List<Object>();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
new file mode 100644
index 0000000..b5fa6de
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
@@ -0,0 +1,116 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using System.Collections;
31using System.Collections.Generic;
32using System.Runtime.Remoting.Lifetime;
33using OpenMetaverse;
34using Nini.Config;
35using OpenSim;
36using OpenSim.Framework;
37using OpenSim.Region.CoreModules.World.LightShare;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Region.ScriptEngine.Shared;
41using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
42using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
43using OpenSim.Region.ScriptEngine.Interfaces;
44using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
45using OpenSim.Services.Interfaces;
46
47using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
48using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
49using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
50using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
51using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
52using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
53using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
54
55namespace OpenSim.Region.ScriptEngine.Shared.Api
56{
57 [Serializable]
58 public class CM_Api : MarshalByRefObject, ICM_Api, IScriptApi
59 {
60 internal IScriptEngine m_ScriptEngine;
61 internal SceneObjectPart m_host;
62 internal TaskInventoryItem m_item;
63 internal bool m_CMFunctionsEnabled = false;
64
65 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
66 {
67 m_ScriptEngine = ScriptEngine;
68 m_host = host;
69 m_item = item;
70
71 if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false))
72 m_CMFunctionsEnabled = true;
73 }
74
75 public override Object InitializeLifetimeService()
76 {
77 ILease lease = (ILease)base.InitializeLifetimeService();
78
79 if (lease.CurrentState == LeaseState.Initial)
80 {
81 lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
82 // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
83 // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
84 }
85 return lease;
86 }
87
88 public Scene World
89 {
90 get { return m_ScriptEngine.World; }
91 }
92
93 public string cmDetectedCountry(int number)
94 {
95 m_host.AddScriptLPS(1);
96 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
97 if (detectedParams == null)
98 return String.Empty;
99 return detectedParams.Country;
100 }
101
102 public string cmGetAgentCountry(LSL_Key key)
103 {
104 if (!World.Permissions.IsGod(m_host.OwnerID))
105 return String.Empty;
106
107 UUID uuid;
108
109 if (!UUID.TryParse(key, out uuid))
110 return String.Empty;
111
112 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
113 return account.UserCountry;
114 }
115 }
116}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index deb68b8..03f4108 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{
@@ -103,15 +107,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
103 protected int m_notecardLineReadCharsMax = 255; 107 protected int m_notecardLineReadCharsMax = 255;
104 protected int m_scriptConsoleChannel = 0; 108 protected int m_scriptConsoleChannel = 0;
105 protected bool m_scriptConsoleChannelEnabled = false; 109 protected bool m_scriptConsoleChannelEnabled = false;
110 protected bool m_debuggerSafe = false;
106 protected IUrlModule m_UrlModule = null; 111 protected IUrlModule m_UrlModule = null;
107 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); 112 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
108 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 113 new Dictionary<UUID, UserInfoCacheEntry>();
114 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
115
116 protected Timer m_ShoutSayTimer;
117 protected int m_SayShoutCount = 0;
109 118
110 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 119 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
111 { 120 {
121 m_ShoutSayTimer = new Timer(1000);
122 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
123 m_ShoutSayTimer.AutoReset = true;
124 m_ShoutSayTimer.Start();
125
112 m_ScriptEngine = ScriptEngine; 126 m_ScriptEngine = ScriptEngine;
113 m_host = host; 127 m_host = host;
114 m_item = item; 128 m_item = item;
129 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
115 130
116 LoadLimits(); // read script limits from config. 131 LoadLimits(); // read script limits from config.
117 132
@@ -171,6 +186,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
171 get { return m_ScriptEngine.World; } 186 get { return m_ScriptEngine.World; }
172 } 187 }
173 188
189 [DebuggerNonUserCode]
174 public void state(string newState) 190 public void state(string newState)
175 { 191 {
176 m_ScriptEngine.SetState(m_item.ItemID, newState); 192 m_ScriptEngine.SetState(m_item.ItemID, newState);
@@ -180,6 +196,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
180 /// Reset the named script. The script must be present 196 /// Reset the named script. The script must be present
181 /// in the same prim. 197 /// in the same prim.
182 /// </summary> 198 /// </summary>
199 [DebuggerNonUserCode]
183 public void llResetScript() 200 public void llResetScript()
184 { 201 {
185 m_host.AddScriptLPS(1); 202 m_host.AddScriptLPS(1);
@@ -236,9 +253,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
236 } 253 }
237 } 254 }
238 255
256 public List<ScenePresence> GetLinkAvatars(int linkType)
257 {
258 List<ScenePresence> ret = new List<ScenePresence>();
259 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
260 return ret;
261
262 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
263
264 switch (linkType)
265 {
266 case ScriptBaseClass.LINK_SET:
267 return avs;
268
269 case ScriptBaseClass.LINK_ROOT:
270 return ret;
271
272 case ScriptBaseClass.LINK_ALL_OTHERS:
273 return avs;
274
275 case ScriptBaseClass.LINK_ALL_CHILDREN:
276 return avs;
277
278 case ScriptBaseClass.LINK_THIS:
279 return ret;
280
281 default:
282 if (linkType < 0)
283 return ret;
284
285 int partCount = m_host.ParentGroup.GetPartCount();
286
287 if (linkType <= partCount)
288 {
289 return ret;
290 }
291 else
292 {
293 linkType = linkType - partCount;
294 if (linkType > avs.Count)
295 {
296 return ret;
297 }
298 else
299 {
300 ret.Add(avs[linkType-1]);
301 return ret;
302 }
303 }
304 }
305 }
306
239 public List<SceneObjectPart> GetLinkParts(int linkType) 307 public List<SceneObjectPart> GetLinkParts(int linkType)
240 { 308 {
241 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 309 List<SceneObjectPart> ret = new List<SceneObjectPart>();
310 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
311 return ret;
242 ret.Add(m_host); 312 ret.Add(m_host);
243 313
244 switch (linkType) 314 switch (linkType)
@@ -432,31 +502,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
432 502
433 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 503 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
434 504
435 /// <summary> 505 // Utility function for llRot2Euler
436 /// Convert an LSL rotation to a Euler vector. 506
437 /// </summary> 507 // normalize an angle between -PI and PI (-180 to +180 degrees)
438 /// <remarks> 508 protected double NormalizeAngle(double angle)
439 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
440 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
441 /// </remarks>
442 /// <param name="r"></param>
443 /// <returns></returns>
444 public LSL_Vector llRot2Euler(LSL_Rotation r)
445 { 509 {
446 m_host.AddScriptLPS(1); 510 if (angle > -Math.PI && angle < Math.PI)
511 return angle;
512
513 int numPis = (int)(Math.PI / angle);
514 double remainder = angle - Math.PI * numPis;
515 if (numPis % 2 == 1)
516 return Math.PI - angle;
517 return remainder;
518 }
447 519
448 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 520 public LSL_Vector llRot2Euler(LSL_Rotation q1)
449 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 521 {
450 if (m == 0.0) return new LSL_Vector(); 522 m_host.AddScriptLPS(1);
451 double x = Math.Atan2(-v.y, v.z); 523 LSL_Vector eul = new LSL_Vector();
452 double sin = v.x / m;
453 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities.
454 double y = Math.Asin(sin);
455 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
456 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)));
457 double z = Math.Atan2(v.y, v.x);
458 524
459 return new LSL_Vector(x, y, z); 525 double sqw = q1.s*q1.s;
526 double sqx = q1.x*q1.x;
527 double sqy = q1.z*q1.z;
528 double sqz = q1.y*q1.y;
529 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
530 double test = q1.x*q1.z + q1.y*q1.s;
531 if (test > 0.4999*unit) { // singularity at north pole
532 eul.z = 2 * Math.Atan2(q1.x,q1.s);
533 eul.y = Math.PI/2;
534 eul.x = 0;
535 return eul;
536 }
537 if (test < -0.4999*unit) { // singularity at south pole
538 eul.z = -2 * Math.Atan2(q1.x,q1.s);
539 eul.y = -Math.PI/2;
540 eul.x = 0;
541 return eul;
542 }
543 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
544 eul.y = Math.Asin(2*test/unit);
545 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
546 return eul;
460 } 547 }
461 548
462 /* From wiki: 549 /* From wiki:
@@ -658,77 +745,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
658 { 745 {
659 //A and B should both be normalized 746 //A and B should both be normalized
660 m_host.AddScriptLPS(1); 747 m_host.AddScriptLPS(1);
661 LSL_Rotation rotBetween; 748 /* This method is more accurate than the SL one, and thus causes problems
662 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 749 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
663 // continue calculation. 750
664 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 751 double dotProduct = LSL_Vector.Dot(a, b);
752 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
753 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
754 double angle = Math.Acos(dotProduct / magProduct);
755 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
756 double s = Math.Sin(angle / 2);
757
758 double x = axis.x * s;
759 double y = axis.y * s;
760 double z = axis.z * s;
761 double w = Math.Cos(angle / 2);
762
763 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
764 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
765
766 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
767 */
768
769 // This method mimics the 180 errors found in SL
770 // See www.euclideanspace.com... angleBetween
771 LSL_Vector vec_a = a;
772 LSL_Vector vec_b = b;
773
774 // Eliminate zero length
775 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
776 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
777 if (vec_a_mag < 0.00001 ||
778 vec_b_mag < 0.00001)
665 { 779 {
666 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 780 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
667 } 781 }
668 else 782
783 // Normalize
784 vec_a = llVecNorm(vec_a);
785 vec_b = llVecNorm(vec_b);
786
787 // Calculate axis and rotation angle
788 LSL_Vector axis = vec_a % vec_b;
789 LSL_Float cos_theta = vec_a * vec_b;
790
791 // Check if parallel
792 if (cos_theta > 0.99999)
669 { 793 {
670 a = LSL_Vector.Norm(a); 794 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
671 b = LSL_Vector.Norm(b); 795 }
672 double dotProduct = LSL_Vector.Dot(a, b); 796
673 // There are two degenerate cases possible. These are for vectors 180 or 797 // Check if anti-parallel
674 // 0 degrees apart. These have to be detected and handled individually. 798 else if (cos_theta < -0.99999)
675 // 799 {
676 // Check for vectors 180 degrees apart. 800 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
677 // A dot product of -1 would mean the angle between vectors is 180 degrees. 801 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
678 if (dotProduct < -0.9999999f) 802 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
679 { 803 }
680 // First assume X axis is orthogonal to the vectors. 804 else // other rotation
681 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 805 {
682 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 806 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
683 // Check for near zero vector. A very small non-zero number here will create 807 axis = llVecNorm(axis);
684 // a rotation in an undesired direction. 808 double x, y, z, s, t;
685 if (LSL_Vector.Mag(orthoVector) > 0.0001) 809 s = Math.Cos(theta);
686 { 810 t = Math.Sin(theta);
687 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 811 x = axis.x * t;
688 } 812 y = axis.y * t;
689 // If the magnitude of the vector was near zero, then assume the X axis is not 813 z = axis.z * t;
690 // orthogonal and use the Z axis instead. 814 return new LSL_Rotation(x,y,z,s);
691 else
692 {
693 // Set 180 z rotation.
694 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
695 }
696 }
697 // Check for parallel vectors.
698 // A dot product of 1 would mean the angle between vectors is 0 degrees.
699 else if (dotProduct > 0.9999999f)
700 {
701 // Set zero rotation.
702 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
703 }
704 else
705 {
706 // All special checks have been performed so get the axis of rotation.
707 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
708 // Quarternion s value is the length of the unit vector + dot product.
709 double qs = 1.0 + dotProduct;
710 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
711 // Normalize the rotation.
712 double mag = LSL_Rotation.Mag(rotBetween);
713 // We shouldn't have to worry about a divide by zero here. The qs value will be
714 // non-zero because we already know if we're here, then the dotProduct is not -1 so
715 // qs will not be zero. Also, we've already handled the input vectors being zero so the
716 // crossProduct vector should also not be zero.
717 rotBetween.x = rotBetween.x / mag;
718 rotBetween.y = rotBetween.y / mag;
719 rotBetween.z = rotBetween.z / mag;
720 rotBetween.s = rotBetween.s / mag;
721 // Check for undefined values and set zero rotation if any found. This code might not actually be required
722 // any longer since zero vectors are checked for at the top.
723 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
724 {
725 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
726 }
727 }
728 } 815 }
729 return rotBetween;
730 } 816 }
731 817
732 public void llWhisper(int channelID, string text) 818 public void llWhisper(int channelID, string text)
733 { 819 {
734 m_host.AddScriptLPS(1); 820 m_host.AddScriptLPS(1);
@@ -748,6 +834,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
748 { 834 {
749 m_host.AddScriptLPS(1); 835 m_host.AddScriptLPS(1);
750 836
837 if (channelID == 0)
838 m_SayShoutCount++;
839
840 if (m_SayShoutCount >= 11)
841 ScriptSleep(2000);
842
751 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 843 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
752 { 844 {
753 Console.WriteLine(text); 845 Console.WriteLine(text);
@@ -770,6 +862,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
770 { 862 {
771 m_host.AddScriptLPS(1); 863 m_host.AddScriptLPS(1);
772 864
865 if (channelID == 0)
866 m_SayShoutCount++;
867
868 if (m_SayShoutCount >= 11)
869 ScriptSleep(2000);
870
773 if (text.Length > 1023) 871 if (text.Length > 1023)
774 text = text.Substring(0, 1023); 872 text = text.Substring(0, 1023);
775 873
@@ -1072,10 +1170,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1072 return detectedParams.TouchUV; 1170 return detectedParams.TouchUV;
1073 } 1171 }
1074 1172
1173 [DebuggerNonUserCode]
1075 public virtual void llDie() 1174 public virtual void llDie()
1076 { 1175 {
1077 m_host.AddScriptLPS(1); 1176 m_host.AddScriptLPS(1);
1078 throw new SelfDeleteException(); 1177 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1079 } 1178 }
1080 1179
1081 public LSL_Float llGround(LSL_Vector offset) 1180 public LSL_Float llGround(LSL_Vector offset)
@@ -1148,6 +1247,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1148 1247
1149 public void llSetStatus(int status, int value) 1248 public void llSetStatus(int status, int value)
1150 { 1249 {
1250 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1251 return;
1151 m_host.AddScriptLPS(1); 1252 m_host.AddScriptLPS(1);
1152 1253
1153 int statusrotationaxis = 0; 1254 int statusrotationaxis = 0;
@@ -1379,6 +1480,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1379 { 1480 {
1380 m_host.AddScriptLPS(1); 1481 m_host.AddScriptLPS(1);
1381 1482
1483 SetColor(m_host, color, face);
1484 }
1485
1486 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1487 {
1488 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1489 return;
1490
1491 Primitive.TextureEntry tex = part.Shape.Textures;
1492 Color4 texcolor;
1493 if (face >= 0 && face < GetNumberOfSides(part))
1494 {
1495 texcolor = tex.CreateFace((uint)face).RGBA;
1496 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1497 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1498 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1499 tex.FaceTextures[face].RGBA = texcolor;
1500 part.UpdateTextureEntry(tex.GetBytes());
1501 return;
1502 }
1503 else if (face == ScriptBaseClass.ALL_SIDES)
1504 {
1505 for (uint i = 0; i < GetNumberOfSides(part); i++)
1506 {
1507 if (tex.FaceTextures[i] != null)
1508 {
1509 texcolor = tex.FaceTextures[i].RGBA;
1510 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1511 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1512 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1513 tex.FaceTextures[i].RGBA = texcolor;
1514 }
1515 texcolor = tex.DefaultTexture.RGBA;
1516 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1517 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1518 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1519 tex.DefaultTexture.RGBA = texcolor;
1520 }
1521 part.UpdateTextureEntry(tex.GetBytes());
1522 return;
1523 }
1524
1382 if (face == ScriptBaseClass.ALL_SIDES) 1525 if (face == ScriptBaseClass.ALL_SIDES)
1383 face = SceneObjectPart.ALL_SIDES; 1526 face = SceneObjectPart.ALL_SIDES;
1384 1527
@@ -1387,6 +1530,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1387 1530
1388 public void SetTexGen(SceneObjectPart part, int face,int style) 1531 public void SetTexGen(SceneObjectPart part, int face,int style)
1389 { 1532 {
1533 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1534 return;
1535
1390 Primitive.TextureEntry tex = part.Shape.Textures; 1536 Primitive.TextureEntry tex = part.Shape.Textures;
1391 MappingType textype; 1537 MappingType textype;
1392 textype = MappingType.Default; 1538 textype = MappingType.Default;
@@ -1417,6 +1563,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1417 1563
1418 public void SetGlow(SceneObjectPart part, int face, float glow) 1564 public void SetGlow(SceneObjectPart part, int face, float glow)
1419 { 1565 {
1566 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1567 return;
1568
1420 Primitive.TextureEntry tex = part.Shape.Textures; 1569 Primitive.TextureEntry tex = part.Shape.Textures;
1421 if (face >= 0 && face < GetNumberOfSides(part)) 1570 if (face >= 0 && face < GetNumberOfSides(part))
1422 { 1571 {
@@ -1442,6 +1591,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1442 1591
1443 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1592 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1444 { 1593 {
1594 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1595 return;
1445 1596
1446 Shininess sval = new Shininess(); 1597 Shininess sval = new Shininess();
1447 1598
@@ -1492,6 +1643,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1492 1643
1493 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1644 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1494 { 1645 {
1646 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1647 return;
1648
1495 Primitive.TextureEntry tex = part.Shape.Textures; 1649 Primitive.TextureEntry tex = part.Shape.Textures;
1496 if (face >= 0 && face < GetNumberOfSides(part)) 1650 if (face >= 0 && face < GetNumberOfSides(part))
1497 { 1651 {
@@ -1552,13 +1706,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1552 m_host.AddScriptLPS(1); 1706 m_host.AddScriptLPS(1);
1553 1707
1554 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1708 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1555 1709 if (parts.Count > 0)
1556 foreach (SceneObjectPart part in parts) 1710 {
1557 SetAlpha(part, alpha, face); 1711 try
1712 {
1713 parts[0].ParentGroup.areUpdatesSuspended = true;
1714 foreach (SceneObjectPart part in parts)
1715 SetAlpha(part, alpha, face);
1716 }
1717 finally
1718 {
1719 parts[0].ParentGroup.areUpdatesSuspended = false;
1720 }
1721 }
1558 } 1722 }
1559 1723
1560 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1724 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1561 { 1725 {
1726 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1727 return;
1728
1562 Primitive.TextureEntry tex = part.Shape.Textures; 1729 Primitive.TextureEntry tex = part.Shape.Textures;
1563 Color4 texcolor; 1730 Color4 texcolor;
1564 if (face >= 0 && face < GetNumberOfSides(part)) 1731 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1611,7 +1778,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1611 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1778 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1612 float wind, float tension, LSL_Vector Force) 1779 float wind, float tension, LSL_Vector Force)
1613 { 1780 {
1614 if (part == null) 1781 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1615 return; 1782 return;
1616 1783
1617 if (flexi) 1784 if (flexi)
@@ -1645,7 +1812,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1645 /// <param name="falloff"></param> 1812 /// <param name="falloff"></param>
1646 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1813 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1647 { 1814 {
1648 if (part == null) 1815 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1649 return; 1816 return;
1650 1817
1651 if (light) 1818 if (light)
@@ -1724,15 +1891,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1724 m_host.AddScriptLPS(1); 1891 m_host.AddScriptLPS(1);
1725 1892
1726 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1893 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1727 1894 if (parts.Count > 0)
1728 foreach (SceneObjectPart part in parts) 1895 {
1729 SetTexture(part, texture, face); 1896 try
1730 1897 {
1898 parts[0].ParentGroup.areUpdatesSuspended = true;
1899 foreach (SceneObjectPart part in parts)
1900 SetTexture(part, texture, face);
1901 }
1902 finally
1903 {
1904 parts[0].ParentGroup.areUpdatesSuspended = false;
1905 }
1906 }
1731 ScriptSleep(200); 1907 ScriptSleep(200);
1732 } 1908 }
1733 1909
1734 protected void SetTexture(SceneObjectPart part, string texture, int face) 1910 protected void SetTexture(SceneObjectPart part, string texture, int face)
1735 { 1911 {
1912 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1913 return;
1914
1736 UUID textureID = new UUID(); 1915 UUID textureID = new UUID();
1737 1916
1738 textureID = InventoryKey(texture, (int)AssetType.Texture); 1917 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1777,6 +1956,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1777 1956
1778 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 1957 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1779 { 1958 {
1959 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1960 return;
1961
1780 Primitive.TextureEntry tex = part.Shape.Textures; 1962 Primitive.TextureEntry tex = part.Shape.Textures;
1781 if (face >= 0 && face < GetNumberOfSides(part)) 1963 if (face >= 0 && face < GetNumberOfSides(part))
1782 { 1964 {
@@ -1813,6 +1995,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1813 1995
1814 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 1996 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1815 { 1997 {
1998 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1999 return;
2000
1816 Primitive.TextureEntry tex = part.Shape.Textures; 2001 Primitive.TextureEntry tex = part.Shape.Textures;
1817 if (face >= 0 && face < GetNumberOfSides(part)) 2002 if (face >= 0 && face < GetNumberOfSides(part))
1818 { 2003 {
@@ -1849,6 +2034,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1849 2034
1850 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2035 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1851 { 2036 {
2037 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2038 return;
2039
1852 Primitive.TextureEntry tex = part.Shape.Textures; 2040 Primitive.TextureEntry tex = part.Shape.Textures;
1853 if (face >= 0 && face < GetNumberOfSides(part)) 2041 if (face >= 0 && face < GetNumberOfSides(part))
1854 { 2042 {
@@ -1953,26 +2141,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1953 return real_vec; 2141 return real_vec;
1954 } 2142 }
1955 2143
2144 public LSL_Integer llSetRegionPos(LSL_Vector pos)
2145 {
2146 return new LSL_Integer(SetRegionPos(m_host, pos));
2147 }
2148
2149 protected int SetRegionPos(SceneObjectPart part, LSL_Vector targetPos)
2150 {
2151 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2152 return 0;
2153
2154 SceneObjectGroup grp = part.ParentGroup;
2155
2156 if (grp.IsAttachment)
2157 return 0;
2158
2159 if (grp.RootPart.PhysActor != null && grp.RootPart.PhysActor.IsPhysical)
2160 return 0;
2161
2162 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)
2163 return 0;
2164
2165 float constrainedX = (float)targetPos.x;
2166 float constrainedY = (float)targetPos.y;
2167
2168 if (constrainedX < 0.0f)
2169 constrainedX = 0.0f;
2170 if (constrainedY < 0.0f)
2171 constrainedY = 0.0f;
2172 if (constrainedX >= (float)Constants.RegionSize)
2173 constrainedX = (float)Constants.RegionSize - 0.1f;
2174 if (constrainedY >= (float)Constants.RegionSize)
2175 constrainedY = (float)Constants.RegionSize -0.1f;
2176
2177 float ground = World.GetGroundHeight(constrainedX, constrainedY);
2178
2179 if (targetPos.z < ground)
2180 targetPos.z = ground;
2181
2182 Vector3 dest = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z);
2183
2184 if (!World.Permissions.CanObjectEntry(grp.UUID, false, dest))
2185 return 0;
2186
2187 grp.UpdateGroupPosition(dest);
2188
2189 return 1;
2190 }
2191
1956 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2192 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1957 { 2193 {
1958 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2194 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2195 return;
2196
1959 LSL_Vector currentPos = GetPartLocalPos(part); 2197 LSL_Vector currentPos = GetPartLocalPos(part);
2198 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
1960 2199
1961 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
1962 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
1963 2200
1964 if (part.ParentGroup.RootPart == part) 2201 if (part.ParentGroup.RootPart == part)
1965 { 2202 {
1966 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
1967 targetPos.z = ground;
1968 SceneObjectGroup parent = part.ParentGroup; 2203 SceneObjectGroup parent = part.ParentGroup;
1969 LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); 2204 Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
1970 parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z)); 2205 if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest))
2206 return;
2207 Util.FireAndForget(delegate(object x) {
2208 parent.UpdateGroupPosition(dest);
2209 });
1971 } 2210 }
1972 else 2211 else
1973 { 2212 {
1974 LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); 2213 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
1975 part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z);
1976 SceneObjectGroup parent = part.ParentGroup; 2214 SceneObjectGroup parent = part.ParentGroup;
1977 parent.HasGroupChanged = true; 2215 parent.HasGroupChanged = true;
1978 parent.ScheduleGroupForTerseUpdate(); 2216 parent.ScheduleGroupForTerseUpdate();
@@ -2005,17 +2243,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2005 else 2243 else
2006 { 2244 {
2007 if (part.ParentGroup.IsAttachment) 2245 if (part.ParentGroup.IsAttachment)
2008 {
2009 pos = part.AttachedPos; 2246 pos = part.AttachedPos;
2010 }
2011 else 2247 else
2012 {
2013 pos = part.AbsolutePosition; 2248 pos = part.AbsolutePosition;
2014 }
2015 } 2249 }
2016 2250
2017// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2018
2019 return new LSL_Vector(pos.X, pos.Y, pos.Z); 2251 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2020 } 2252 }
2021 2253
@@ -2024,9 +2256,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2024 m_host.AddScriptLPS(1); 2256 m_host.AddScriptLPS(1);
2025 2257
2026 // try to let this work as in SL... 2258 // try to let this work as in SL...
2027 if (m_host.ParentID == 0) 2259 if (m_host.LinkNum < 2)
2028 { 2260 {
2029 // special case: If we are root, rotate complete SOG to new rotation 2261 // Special case: If we are root, rotate complete SOG to new
2262 // rotation.
2263 // We are root if the link number is 0 (single prim) or 1
2264 // (root prim). ParentID may be nonzero in attachments and
2265 // using it would cause attachments and HUDs to rotate
2266 // to the wrong positions.
2030 SetRot(m_host, Rot2Quaternion(rot)); 2267 SetRot(m_host, Rot2Quaternion(rot));
2031 } 2268 }
2032 else 2269 else
@@ -2051,6 +2288,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2051 2288
2052 protected void SetRot(SceneObjectPart part, Quaternion rot) 2289 protected void SetRot(SceneObjectPart part, Quaternion rot)
2053 { 2290 {
2291 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2292 return;
2293
2054 part.UpdateRotation(rot); 2294 part.UpdateRotation(rot);
2055 // Update rotation does not move the object in the physics scene if it's a linkset. 2295 // Update rotation does not move the object in the physics scene if it's a linkset.
2056 2296
@@ -2205,13 +2445,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2205 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2445 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2206 { 2446 {
2207 m_host.AddScriptLPS(1); 2447 m_host.AddScriptLPS(1);
2208 m_host.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); 2448 m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
2209 } 2449 }
2210 2450
2211 public void llSetTorque(LSL_Vector torque, int local) 2451 public void llSetTorque(LSL_Vector torque, int local)
2212 { 2452 {
2213 m_host.AddScriptLPS(1); 2453 m_host.AddScriptLPS(1);
2214 m_host.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); 2454 m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0);
2215 } 2455 }
2216 2456
2217 public LSL_Vector llGetTorque() 2457 public LSL_Vector llGetTorque()
@@ -2813,35 +3053,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2813 public void llLookAt(LSL_Vector target, double strength, double damping) 3053 public void llLookAt(LSL_Vector target, double strength, double damping)
2814 { 3054 {
2815 m_host.AddScriptLPS(1); 3055 m_host.AddScriptLPS(1);
2816 // Determine where we are looking from
2817 LSL_Vector from = llGetPos();
2818 3056
2819 // Work out the normalised vector from the source to the target 3057 // Get the normalized vector to the target
2820 LSL_Vector delta = llVecNorm(target - from); 3058 LSL_Vector d1 = llVecNorm(target - llGetPos());
2821 LSL_Vector angle = new LSL_Vector(0,0,0);
2822 3059
2823 // Calculate the yaw 3060 // Get the bearing (yaw)
2824 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3061 LSL_Vector a1 = new LSL_Vector(0,0,0);
2825 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3062 a1.z = llAtan2(d1.y, d1.x);
2826 3063
2827 // Calculate pitch 3064 // Get the elevation (pitch)
2828 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3065 LSL_Vector a2 = new LSL_Vector(0,0,0);
3066 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2829 3067
2830 // we need to convert from a vector describing 3068 LSL_Rotation r1 = llEuler2Rot(a1);
2831 // the angles of rotation in radians into rotation value 3069 LSL_Rotation r2 = llEuler2Rot(a2);
2832 LSL_Rotation rot = llEuler2Rot(angle); 3070 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2833
2834 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2835 // set the rotation of the object, copy that behavior
2836 PhysicsActor pa = m_host.PhysActor;
2837 3071
2838 if (strength == 0 || pa == null || !pa.IsPhysical) 3072 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2839 { 3073 {
2840 llSetRot(rot); 3074 // Do nothing if either value is 0 (this has been checked in SL)
3075 if (strength <= 0.0 || damping <= 0.0)
3076 return;
3077
3078 llSetRot(r3 * r2 * r1);
2841 } 3079 }
2842 else 3080 else
2843 { 3081 {
2844 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3082 if (strength == 0)
3083 {
3084 llSetRot(r3 * r2 * r1);
3085 return;
3086 }
3087
3088 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2845 } 3089 }
2846 } 3090 }
2847 3091
@@ -2887,17 +3131,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2887 } 3131 }
2888 else 3132 else
2889 { 3133 {
2890 if (m_host.IsRoot) 3134 // new SL always returns object mass
2891 { 3135// if (m_host.IsRoot)
3136// {
2892 return m_host.ParentGroup.GetMass(); 3137 return m_host.ParentGroup.GetMass();
2893 } 3138// }
2894 else 3139// else
2895 { 3140// {
2896 return m_host.GetMass(); 3141// return m_host.GetMass();
2897 } 3142// }
2898 } 3143 }
2899 } 3144 }
2900 3145
3146
3147 public LSL_Float llGetMassMKS()
3148 {
3149 return 100f * llGetMass();
3150 }
3151
2901 public void llCollisionFilter(string name, string id, int accept) 3152 public void llCollisionFilter(string name, string id, int accept)
2902 { 3153 {
2903 m_host.AddScriptLPS(1); 3154 m_host.AddScriptLPS(1);
@@ -3005,9 +3256,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3005 { 3256 {
3006 m_host.AddScriptLPS(1); 3257 m_host.AddScriptLPS(1);
3007 3258
3008// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3009// return;
3010
3011 if (m_item.PermsGranter != m_host.OwnerID) 3259 if (m_item.PermsGranter != m_host.OwnerID)
3012 return; 3260 return;
3013 3261
@@ -3050,6 +3298,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3050 3298
3051 public void llInstantMessage(string user, string message) 3299 public void llInstantMessage(string user, string message)
3052 { 3300 {
3301 UUID result;
3302 if (!UUID.TryParse(user, out result))
3303 {
3304 ShoutError("An invalid key was passed to llInstantMessage");
3305 ScriptSleep(2000);
3306 return;
3307 }
3308
3309
3053 m_host.AddScriptLPS(1); 3310 m_host.AddScriptLPS(1);
3054 3311
3055 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3312 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3064,14 +3321,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3064 UUID friendTransactionID = UUID.Random(); 3321 UUID friendTransactionID = UUID.Random();
3065 3322
3066 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3323 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3067 3324
3068 GridInstantMessage msg = new GridInstantMessage(); 3325 GridInstantMessage msg = new GridInstantMessage();
3069 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3326 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3070 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3327 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3071 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3328 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3072// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3329// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3073// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3330// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3074 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3331// DateTime dt = DateTime.UtcNow;
3332//
3333// // Ticks from UtcNow, but make it look like local. Evil, huh?
3334// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3335//
3336// try
3337// {
3338// // Convert that to the PST timezone
3339// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3340// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3341// }
3342// catch
3343// {
3344// // No logging here, as it could be VERY spammy
3345// }
3346//
3347// // And make it look local again to fool the unix time util
3348// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3349
3350 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3351
3075 //if (client != null) 3352 //if (client != null)
3076 //{ 3353 //{
3077 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3354 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3085,12 +3362,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3085 msg.message = message.Substring(0, 1024); 3362 msg.message = message.Substring(0, 1024);
3086 else 3363 else
3087 msg.message = message; 3364 msg.message = message;
3088 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3365 msg.dialog = (byte)19; // MessageFromObject
3089 msg.fromGroup = false;// fromGroup; 3366 msg.fromGroup = false;// fromGroup;
3090 msg.offline = (byte)0; //offline; 3367 msg.offline = (byte)0; //offline;
3091 msg.ParentEstateID = 0; //ParentEstateID; 3368 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3092 msg.Position = new Vector3(m_host.AbsolutePosition); 3369 msg.Position = new Vector3(m_host.AbsolutePosition);
3093 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3370 msg.RegionID = World.RegionInfo.RegionID.Guid;
3094 msg.binaryBucket 3371 msg.binaryBucket
3095 = Util.StringToBytes256( 3372 = Util.StringToBytes256(
3096 "{0}/{1}/{2}/{3}", 3373 "{0}/{1}/{2}/{3}",
@@ -3118,7 +3395,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3118 } 3395 }
3119 3396
3120 emailModule.SendEmail(m_host.UUID, address, subject, message); 3397 emailModule.SendEmail(m_host.UUID, address, subject, message);
3121 llSleep(EMAIL_PAUSE_TIME); 3398 ScriptSleep(EMAIL_PAUSE_TIME * 1000);
3122 } 3399 }
3123 3400
3124 public void llGetNextEmail(string address, string subject) 3401 public void llGetNextEmail(string address, string subject)
@@ -3362,15 +3639,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3362 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3639 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3363 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3640 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3364 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3641 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3642 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3365 ScriptBaseClass.PERMISSION_ATTACH; 3643 ScriptBaseClass.PERMISSION_ATTACH;
3366 3644
3367 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3645 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3368 { 3646 {
3369 lock (m_host.TaskInventory) 3647 m_host.TaskInventory.LockItemsForWrite(true);
3370 { 3648 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3371 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3649 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3372 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3650 m_host.TaskInventory.LockItemsForWrite(false);
3373 }
3374 3651
3375 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3652 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3376 "run_time_permissions", new Object[] { 3653 "run_time_permissions", new Object[] {
@@ -3380,28 +3657,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3380 return; 3657 return;
3381 } 3658 }
3382 } 3659 }
3383 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3660 else
3384 { 3661 {
3385 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3662 bool sitting = false;
3386 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3663 if (m_host.SitTargetAvatar == agentID)
3387 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3664 {
3388 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3665 sitting = true;
3389 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3666 }
3667 else
3668 {
3669 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3670 {
3671 if (p.SitTargetAvatar == agentID)
3672 sitting = true;
3673 }
3674 }
3390 3675
3391 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3676 if (sitting)
3392 { 3677 {
3393 lock (m_host.TaskInventory) 3678 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3679 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3680 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3681 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3682 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3683
3684 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3394 { 3685 {
3686 m_host.TaskInventory.LockItemsForWrite(true);
3395 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3687 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3396 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3688 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3397 } 3689 m_host.TaskInventory.LockItemsForWrite(false);
3398 3690
3399 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3691 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3400 "run_time_permissions", new Object[] { 3692 "run_time_permissions", new Object[] {
3401 new LSL_Integer(perm) }, 3693 new LSL_Integer(perm) },
3402 new DetectParams[0])); 3694 new DetectParams[0]));
3403 3695
3404 return; 3696 return;
3697 }
3405 } 3698 }
3406 } 3699 }
3407 3700
@@ -3438,11 +3731,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3438 3731
3439 if (!m_waitingForScriptAnswer) 3732 if (!m_waitingForScriptAnswer)
3440 { 3733 {
3441 lock (m_host.TaskInventory) 3734 m_host.TaskInventory.LockItemsForWrite(true);
3442 { 3735 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3443 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3736 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3444 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 3737 m_host.TaskInventory.LockItemsForWrite(false);
3445 }
3446 3738
3447 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3739 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3448 m_waitingForScriptAnswer=true; 3740 m_waitingForScriptAnswer=true;
@@ -3471,14 +3763,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3471 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3763 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3472 llReleaseControls(); 3764 llReleaseControls();
3473 3765
3474 lock (m_host.TaskInventory) 3766 m_host.TaskInventory.LockItemsForWrite(true);
3475 { 3767 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3476 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 3768 m_host.TaskInventory.LockItemsForWrite(false);
3477 } 3769
3478 3770 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3479 m_ScriptEngine.PostScriptEvent( 3771 "run_time_permissions", new Object[] {
3480 m_item.ItemID, 3772 new LSL_Integer(answer) },
3481 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); 3773 new DetectParams[0]));
3482 } 3774 }
3483 3775
3484 public LSL_String llGetPermissionsKey() 3776 public LSL_String llGetPermissionsKey()
@@ -3517,14 +3809,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3517 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3809 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3518 { 3810 {
3519 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3811 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3520 3812 if (parts.Count > 0)
3521 foreach (SceneObjectPart part in parts) 3813 {
3522 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3814 try
3815 {
3816 parts[0].ParentGroup.areUpdatesSuspended = true;
3817 foreach (SceneObjectPart part in parts)
3818 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3819 }
3820 finally
3821 {
3822 parts[0].ParentGroup.areUpdatesSuspended = false;
3823 }
3824 }
3523 } 3825 }
3524 3826
3525 public void llCreateLink(string target, int parent) 3827 public void llCreateLink(string target, int parent)
3526 { 3828 {
3527 m_host.AddScriptLPS(1); 3829 m_host.AddScriptLPS(1);
3830
3528 UUID targetID; 3831 UUID targetID;
3529 3832
3530 if (!UUID.TryParse(target, out targetID)) 3833 if (!UUID.TryParse(target, out targetID))
@@ -3630,10 +3933,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3630 // Restructuring Multiple Prims. 3933 // Restructuring Multiple Prims.
3631 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 3934 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3632 parts.Remove(parentPrim.RootPart); 3935 parts.Remove(parentPrim.RootPart);
3633 foreach (SceneObjectPart part in parts) 3936 if (parts.Count > 0)
3634 { 3937 {
3635 parentPrim.DelinkFromGroup(part.LocalId, true); 3938 try
3939 {
3940 parts[0].ParentGroup.areUpdatesSuspended = true;
3941 foreach (SceneObjectPart part in parts)
3942 {
3943 parentPrim.DelinkFromGroup(part.LocalId, true);
3944 }
3945 }
3946 finally
3947 {
3948 parts[0].ParentGroup.areUpdatesSuspended = false;
3949 }
3636 } 3950 }
3951
3637 parentPrim.HasGroupChanged = true; 3952 parentPrim.HasGroupChanged = true;
3638 parentPrim.ScheduleGroupForFullUpdate(); 3953 parentPrim.ScheduleGroupForFullUpdate();
3639 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3954 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3642,12 +3957,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3642 { 3957 {
3643 SceneObjectPart newRoot = parts[0]; 3958 SceneObjectPart newRoot = parts[0];
3644 parts.Remove(newRoot); 3959 parts.Remove(newRoot);
3645 foreach (SceneObjectPart part in parts) 3960
3961 try
3646 { 3962 {
3647 // Required for linking 3963 parts[0].ParentGroup.areUpdatesSuspended = true;
3648 part.ClearUpdateSchedule(); 3964 foreach (SceneObjectPart part in parts)
3649 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 3965 {
3966 part.ClearUpdateSchedule();
3967 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3968 }
3650 } 3969 }
3970 finally
3971 {
3972 parts[0].ParentGroup.areUpdatesSuspended = false;
3973 }
3974
3975
3651 newRoot.ParentGroup.HasGroupChanged = true; 3976 newRoot.ParentGroup.HasGroupChanged = true;
3652 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 3977 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3653 } 3978 }
@@ -3667,6 +3992,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3667 public void llBreakAllLinks() 3992 public void llBreakAllLinks()
3668 { 3993 {
3669 m_host.AddScriptLPS(1); 3994 m_host.AddScriptLPS(1);
3995
3996 TaskInventoryItem item = m_item;
3997
3998 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3999 && !m_automaticLinkPermission)
4000 {
4001 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4002 return;
4003 }
4004
3670 SceneObjectGroup parentPrim = m_host.ParentGroup; 4005 SceneObjectGroup parentPrim = m_host.ParentGroup;
3671 if (parentPrim.AttachmentPoint != 0) 4006 if (parentPrim.AttachmentPoint != 0)
3672 return; // Fail silently if attached 4007 return; // Fail silently if attached
@@ -3686,25 +4021,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3686 public LSL_String llGetLinkKey(int linknum) 4021 public LSL_String llGetLinkKey(int linknum)
3687 { 4022 {
3688 m_host.AddScriptLPS(1); 4023 m_host.AddScriptLPS(1);
3689 List<UUID> keytable = new List<UUID>();
3690 // parse for sitting avatare-uuids
3691 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3692 {
3693 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
3694 keytable.Add(presence.UUID);
3695 });
3696
3697 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3698 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3699 {
3700 return keytable[totalprims - linknum].ToString();
3701 }
3702
3703 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3704 {
3705 return m_host.UUID.ToString();
3706 }
3707
3708 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4024 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3709 if (part != null) 4025 if (part != null)
3710 { 4026 {
@@ -3712,6 +4028,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3712 } 4028 }
3713 else 4029 else
3714 { 4030 {
4031 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4032 {
4033 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4034
4035 if (linknum < 0)
4036 return UUID.Zero.ToString();
4037
4038 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4039 if (avatars.Count > linknum)
4040 {
4041 return avatars[linknum].UUID.ToString();
4042 }
4043 }
3715 return UUID.Zero.ToString(); 4044 return UUID.Zero.ToString();
3716 } 4045 }
3717 } 4046 }
@@ -3811,17 +4140,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3811 m_host.AddScriptLPS(1); 4140 m_host.AddScriptLPS(1);
3812 int count = 0; 4141 int count = 0;
3813 4142
3814 lock (m_host.TaskInventory) 4143 m_host.TaskInventory.LockItemsForRead(true);
4144 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3815 { 4145 {
3816 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4146 if (inv.Value.Type == type || type == -1)
3817 { 4147 {
3818 if (inv.Value.Type == type || type == -1) 4148 count = count + 1;
3819 {
3820 count = count + 1;
3821 }
3822 } 4149 }
3823 } 4150 }
3824 4151
4152 m_host.TaskInventory.LockItemsForRead(false);
3825 return count; 4153 return count;
3826 } 4154 }
3827 4155
@@ -3830,16 +4158,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3830 m_host.AddScriptLPS(1); 4158 m_host.AddScriptLPS(1);
3831 ArrayList keys = new ArrayList(); 4159 ArrayList keys = new ArrayList();
3832 4160
3833 lock (m_host.TaskInventory) 4161 m_host.TaskInventory.LockItemsForRead(true);
4162 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3834 { 4163 {
3835 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4164 if (inv.Value.Type == type || type == -1)
3836 { 4165 {
3837 if (inv.Value.Type == type || type == -1) 4166 keys.Add(inv.Value.Name);
3838 {
3839 keys.Add(inv.Value.Name);
3840 }
3841 } 4167 }
3842 } 4168 }
4169 m_host.TaskInventory.LockItemsForRead(false);
3843 4170
3844 if (keys.Count == 0) 4171 if (keys.Count == 0)
3845 { 4172 {
@@ -3876,25 +4203,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3876 } 4203 }
3877 4204
3878 // move the first object found with this inventory name 4205 // move the first object found with this inventory name
3879 lock (m_host.TaskInventory) 4206 m_host.TaskInventory.LockItemsForRead(true);
4207 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3880 { 4208 {
3881 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4209 if (inv.Value.Name == inventory)
3882 { 4210 {
3883 if (inv.Value.Name == inventory) 4211 found = true;
3884 { 4212 objId = inv.Key;
3885 found = true; 4213 assetType = inv.Value.Type;
3886 objId = inv.Key; 4214 objName = inv.Value.Name;
3887 assetType = inv.Value.Type; 4215 break;
3888 objName = inv.Value.Name;
3889 break;
3890 }
3891 } 4216 }
3892 } 4217 }
4218 m_host.TaskInventory.LockItemsForRead(false);
3893 4219
3894 if (!found) 4220 if (!found)
3895 { 4221 {
3896 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4222 llSay(0, String.Format("Could not find object '{0}'", inventory));
3897 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4223 return;
4224// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3898 } 4225 }
3899 4226
3900 // check if destination is an object 4227 // check if destination is an object
@@ -3920,48 +4247,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3920 return; 4247 return;
3921 } 4248 }
3922 } 4249 }
4250
3923 // destination is an avatar 4251 // destination is an avatar
3924 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4252 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3925 4253
3926 if (agentItem == null) 4254 if (agentItem == null)
3927 return; 4255 return;
3928 4256
3929 byte[] bucket = new byte[17]; 4257 byte[] bucket = new byte[1];
3930 bucket[0] = (byte)assetType; 4258 bucket[0] = (byte)assetType;
3931 byte[] objBytes = agentItem.ID.GetBytes(); 4259 //byte[] objBytes = agentItem.ID.GetBytes();
3932 Array.Copy(objBytes, 0, bucket, 1, 16); 4260 //Array.Copy(objBytes, 0, bucket, 1, 16);
3933 4261
3934 GridInstantMessage msg = new GridInstantMessage(World, 4262 GridInstantMessage msg = new GridInstantMessage(World,
3935 m_host.UUID, m_host.Name+", an object owned by "+ 4263 m_host.OwnerID, m_host.Name, destId,
3936 resolveName(m_host.OwnerID)+",", destId,
3937 (byte)InstantMessageDialog.TaskInventoryOffered, 4264 (byte)InstantMessageDialog.TaskInventoryOffered,
3938 false, objName+"\n"+m_host.Name+" is located at "+ 4265 false, objName+". "+m_host.Name+" is located at "+
3939 World.RegionInfo.RegionName+" "+ 4266 World.RegionInfo.RegionName+" "+
3940 m_host.AbsolutePosition.ToString(), 4267 m_host.AbsolutePosition.ToString(),
3941 agentItem.ID, true, m_host.AbsolutePosition, 4268 agentItem.ID, true, m_host.AbsolutePosition,
3942 bucket); 4269 bucket);
3943 if (m_TransferModule != null) 4270
3944 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4271 ScenePresence sp;
4272
4273 if (World.TryGetScenePresence(destId, out sp))
4274 {
4275 sp.ControllingClient.SendInstantMessage(msg);
4276 }
4277 else
4278 {
4279 if (m_TransferModule != null)
4280 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4281 }
4282
4283 //This delay should only occur when giving inventory to avatars.
3945 ScriptSleep(3000); 4284 ScriptSleep(3000);
3946 } 4285 }
3947 } 4286 }
3948 4287
4288 [DebuggerNonUserCode]
3949 public void llRemoveInventory(string name) 4289 public void llRemoveInventory(string name)
3950 { 4290 {
3951 m_host.AddScriptLPS(1); 4291 m_host.AddScriptLPS(1);
3952 4292
3953 lock (m_host.TaskInventory) 4293 List<TaskInventoryItem> inv;
4294 try
3954 { 4295 {
3955 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4296 m_host.TaskInventory.LockItemsForRead(true);
4297 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4298 }
4299 finally
4300 {
4301 m_host.TaskInventory.LockItemsForRead(false);
4302 }
4303 foreach (TaskInventoryItem item in inv)
4304 {
4305 if (item.Name == name)
3956 { 4306 {
3957 if (item.Name == name) 4307 if (item.ItemID == m_item.ItemID)
3958 { 4308 throw new ScriptDeleteException();
3959 if (item.ItemID == m_item.ItemID) 4309 else
3960 throw new ScriptDeleteException(); 4310 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3961 else 4311 return;
3962 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3963 return;
3964 }
3965 } 4312 }
3966 } 4313 }
3967 } 4314 }
@@ -3996,115 +4343,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3996 { 4343 {
3997 m_host.AddScriptLPS(1); 4344 m_host.AddScriptLPS(1);
3998 4345
3999 UUID uuid = (UUID)id; 4346 UUID uuid;
4000 PresenceInfo pinfo = null; 4347 if (UUID.TryParse(id, out uuid))
4001 UserAccount account;
4002
4003 UserInfoCacheEntry ce;
4004 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4005 { 4348 {
4006 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4349 PresenceInfo pinfo = null;
4007 if (account == null) 4350 UserAccount account;
4351
4352 UserInfoCacheEntry ce;
4353 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4008 { 4354 {
4009 m_userInfoCache[uuid] = null; // Cache negative 4355 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4010 return UUID.Zero.ToString(); 4356 if (account == null)
4011 } 4357 {
4358 m_userInfoCache[uuid] = null; // Cache negative
4359 return UUID.Zero.ToString();
4360 }
4012 4361
4013 4362
4014 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4363 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4015 if (pinfos != null && pinfos.Length > 0) 4364 if (pinfos != null && pinfos.Length > 0)
4016 {
4017 foreach (PresenceInfo p in pinfos)
4018 { 4365 {
4019 if (p.RegionID != UUID.Zero) 4366 foreach (PresenceInfo p in pinfos)
4020 { 4367 {
4021 pinfo = p; 4368 if (p.RegionID != UUID.Zero)
4369 {
4370 pinfo = p;
4371 }
4022 } 4372 }
4023 } 4373 }
4024 }
4025 4374
4026 ce = new UserInfoCacheEntry(); 4375 ce = new UserInfoCacheEntry();
4027 ce.time = Util.EnvironmentTickCount(); 4376 ce.time = Util.EnvironmentTickCount();
4028 ce.account = account; 4377 ce.account = account;
4029 ce.pinfo = pinfo; 4378 ce.pinfo = pinfo;
4030 } 4379 m_userInfoCache[uuid] = ce;
4031 else 4380 }
4032 { 4381 else
4033 if (ce == null) 4382 {
4034 return UUID.Zero.ToString(); 4383 if (ce == null)
4384 return UUID.Zero.ToString();
4035 4385
4036 account = ce.account; 4386 account = ce.account;
4037 pinfo = ce.pinfo; 4387 pinfo = ce.pinfo;
4038 } 4388 }
4039 4389
4040 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4390 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4041 {
4042 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4043 if (pinfos != null && pinfos.Length > 0)
4044 { 4391 {
4045 foreach (PresenceInfo p in pinfos) 4392 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4393 if (pinfos != null && pinfos.Length > 0)
4046 { 4394 {
4047 if (p.RegionID != UUID.Zero) 4395 foreach (PresenceInfo p in pinfos)
4048 { 4396 {
4049 pinfo = p; 4397 if (p.RegionID != UUID.Zero)
4398 {
4399 pinfo = p;
4400 }
4050 } 4401 }
4051 } 4402 }
4052 } 4403 else
4053 else 4404 pinfo = null;
4054 pinfo = null;
4055 4405
4056 ce.time = Util.EnvironmentTickCount(); 4406 ce.time = Util.EnvironmentTickCount();
4057 ce.pinfo = pinfo; 4407 ce.pinfo = pinfo;
4058 } 4408 }
4059 4409
4060 string reply = String.Empty; 4410 string reply = String.Empty;
4061 4411
4062 switch (data) 4412 switch (data)
4063 { 4413 {
4064 case 1: // DATA_ONLINE (0|1) 4414 case 1: // DATA_ONLINE (0|1)
4065 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4415 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4066 reply = "1"; 4416 reply = "1";
4067 else 4417 else
4068 reply = "0"; 4418 reply = "0";
4069 break; 4419 break;
4070 case 2: // DATA_NAME (First Last) 4420 case 2: // DATA_NAME (First Last)
4071 reply = account.FirstName + " " + account.LastName; 4421 reply = account.FirstName + " " + account.LastName;
4072 break; 4422 break;
4073 case 3: // DATA_BORN (YYYY-MM-DD) 4423 case 3: // DATA_BORN (YYYY-MM-DD)
4074 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4424 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4075 born = born.AddSeconds(account.Created); 4425 born = born.AddSeconds(account.Created);
4076 reply = born.ToString("yyyy-MM-dd"); 4426 reply = born.ToString("yyyy-MM-dd");
4077 break; 4427 break;
4078 case 4: // DATA_RATING (0,0,0,0,0,0) 4428 case 4: // DATA_RATING (0,0,0,0,0,0)
4079 reply = "0,0,0,0,0,0"; 4429 reply = "0,0,0,0,0,0";
4080 break; 4430 break;
4081 case 7: // DATA_USERLEVEL (integer) 4431 case 8: // DATA_PAYINFO (0|1|2|3)
4082 reply = account.UserLevel.ToString(); 4432 reply = "0";
4083 break; 4433 break;
4084 case 8: // DATA_PAYINFO (0|1|2|3) 4434 default:
4085 reply = "0"; 4435 return UUID.Zero.ToString(); // Raise no event
4086 break; 4436 }
4087 default:
4088 return UUID.Zero.ToString(); // Raise no event
4089 }
4090 4437
4091 UUID rq = UUID.Random(); 4438 UUID rq = UUID.Random();
4092 4439
4093 UUID tid = AsyncCommands. 4440 UUID tid = AsyncCommands.
4094 DataserverPlugin.RegisterRequest(m_host.LocalId, 4441 DataserverPlugin.RegisterRequest(m_host.LocalId,
4095 m_item.ItemID, rq.ToString()); 4442 m_item.ItemID, rq.ToString());
4096 4443
4097 AsyncCommands. 4444 AsyncCommands.
4098 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4445 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4099 4446
4100 ScriptSleep(100); 4447 ScriptSleep(100);
4101 return tid.ToString(); 4448 return tid.ToString();
4449 }
4450 else
4451 {
4452 ShoutError("Invalid UUID passed to llRequestAgentData.");
4453 }
4454 return "";
4102 } 4455 }
4103 4456
4104 public LSL_String llRequestInventoryData(string name) 4457 public LSL_String llRequestInventoryData(string name)
4105 { 4458 {
4106 m_host.AddScriptLPS(1); 4459 m_host.AddScriptLPS(1);
4107 4460
4461 //Clone is thread safe
4108 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4462 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4109 4463
4110 foreach (TaskInventoryItem item in itemDictionary.Values) 4464 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4156,19 +4510,64 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4156 if (UUID.TryParse(agent, out agentId)) 4510 if (UUID.TryParse(agent, out agentId))
4157 { 4511 {
4158 ScenePresence presence = World.GetScenePresence(agentId); 4512 ScenePresence presence = World.GetScenePresence(agentId);
4159 if (presence != null) 4513 if (presence != null && presence.PresenceType != PresenceType.Npc)
4160 { 4514 {
4515 // agent must not be a god
4516 if (presence.UserLevel >= 200) return;
4517
4161 // agent must be over the owners land 4518 // agent must be over the owners land
4162 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4519 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4163 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4520 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4164 { 4521 {
4165 World.TeleportClientHome(agentId, presence.ControllingClient); 4522 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4523 {
4524 // They can't be teleported home for some reason
4525 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4526 if (regionInfo != null)
4527 {
4528 World.RequestTeleportLocation(
4529 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4530 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4531 }
4532 }
4166 } 4533 }
4167 } 4534 }
4168 } 4535 }
4169 ScriptSleep(5000); 4536 ScriptSleep(5000);
4170 } 4537 }
4171 4538
4539 public void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt)
4540 {
4541 m_host.AddScriptLPS(1);
4542 UUID agentId = new UUID();
4543 if (UUID.TryParse(agent, out agentId))
4544 {
4545 ScenePresence presence = World.GetScenePresence(agentId);
4546 if (presence != null && presence.PresenceType != PresenceType.Npc)
4547 {
4548 // agent must not be a god
4549 if (presence.GodLevel >= 200) return;
4550
4551 if (simname == String.Empty)
4552 simname = World.RegionInfo.RegionName;
4553
4554 // agent must be over the owners land
4555 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4556 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4557 {
4558 World.RequestTeleportLocation(presence.ControllingClient, simname, new Vector3((float)pos.x, (float)pos.y, (float)pos.z), new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z), (uint)TeleportFlags.ViaLocation);
4559 }
4560 else // or must be wearing the prim
4561 {
4562 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4563 {
4564 World.RequestTeleportLocation(presence.ControllingClient, simname, new Vector3((float)pos.x, (float)pos.y, (float)pos.z), new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z), (uint)TeleportFlags.ViaLocation);
4565 }
4566 }
4567 }
4568 }
4569 }
4570
4172 public void llTextBox(string agent, string message, int chatChannel) 4571 public void llTextBox(string agent, string message, int chatChannel)
4173 { 4572 {
4174 IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); 4573 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
@@ -4180,7 +4579,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4180 UUID av = new UUID(); 4579 UUID av = new UUID();
4181 if (!UUID.TryParse(agent,out av)) 4580 if (!UUID.TryParse(agent,out av))
4182 { 4581 {
4183 LSLError("First parameter to llDialog needs to be a key"); 4582 //LSLError("First parameter to llDialog needs to be a key");
4184 return; 4583 return;
4185 } 4584 }
4186 4585
@@ -4212,25 +4611,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4212 public void llCollisionSound(string impact_sound, double impact_volume) 4611 public void llCollisionSound(string impact_sound, double impact_volume)
4213 { 4612 {
4214 m_host.AddScriptLPS(1); 4613 m_host.AddScriptLPS(1);
4215 4614
4615 if(impact_sound == "")
4616 {
4617 m_host.CollisionSoundVolume = (float)impact_volume;
4618 m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
4619 return;
4620 }
4216 // TODO: Parameter check logic required. 4621 // TODO: Parameter check logic required.
4217 UUID soundId = UUID.Zero; 4622 UUID soundId = UUID.Zero;
4218 if (!UUID.TryParse(impact_sound, out soundId)) 4623 if (!UUID.TryParse(impact_sound, out soundId))
4219 { 4624 {
4220 lock (m_host.TaskInventory) 4625 m_host.TaskInventory.LockItemsForRead(true);
4626 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4221 { 4627 {
4222 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4628 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4223 { 4629 {
4224 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4630 soundId = item.AssetID;
4225 { 4631 break;
4226 soundId = item.AssetID;
4227 break;
4228 }
4229 } 4632 }
4230 } 4633 }
4634 m_host.TaskInventory.LockItemsForRead(false);
4231 } 4635 }
4232 m_host.CollisionSound = soundId;
4233 m_host.CollisionSoundVolume = (float)impact_volume; 4636 m_host.CollisionSoundVolume = (float)impact_volume;
4637 m_host.CollisionSound = soundId;
4234 } 4638 }
4235 4639
4236 public LSL_String llGetAnimation(string id) 4640 public LSL_String llGetAnimation(string id)
@@ -4267,6 +4671,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4267 UUID partItemID; 4671 UUID partItemID;
4268 foreach (SceneObjectPart part in parts) 4672 foreach (SceneObjectPart part in parts)
4269 { 4673 {
4674 //Clone is thread safe
4270 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4675 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4271 4676
4272 foreach (TaskInventoryItem item in itemsDictionary.Values) 4677 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4400,7 +4805,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4400 { 4805 {
4401 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4806 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4402 float distance_term = distance * distance * distance; // Script Energy 4807 float distance_term = distance * distance * distance; // Script Energy
4403 float pusher_mass = m_host.GetMass(); 4808 // use total object mass and not part
4809 float pusher_mass = m_host.ParentGroup.GetMass();
4404 4810
4405 float PUSH_ATTENUATION_DISTANCE = 17f; 4811 float PUSH_ATTENUATION_DISTANCE = 17f;
4406 float PUSH_ATTENUATION_SCALE = 5f; 4812 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4639,23 +5045,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4639 { 5045 {
4640 m_host.AddScriptLPS(1); 5046 m_host.AddScriptLPS(1);
4641 5047
4642 lock (m_host.TaskInventory) 5048 m_host.TaskInventory.LockItemsForRead(true);
5049 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4643 { 5050 {
4644 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5051 if (inv.Value.Name == name)
4645 { 5052 {
4646 if (inv.Value.Name == name) 5053 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4647 { 5054 {
4648 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5055 m_host.TaskInventory.LockItemsForRead(false);
4649 { 5056 return inv.Value.AssetID.ToString();
4650 return inv.Value.AssetID.ToString(); 5057 }
4651 } 5058 else
4652 else 5059 {
4653 { 5060 m_host.TaskInventory.LockItemsForRead(false);
4654 return UUID.Zero.ToString(); 5061 return UUID.Zero.ToString();
4655 }
4656 } 5062 }
4657 } 5063 }
4658 } 5064 }
5065 m_host.TaskInventory.LockItemsForRead(false);
4659 5066
4660 return UUID.Zero.ToString(); 5067 return UUID.Zero.ToString();
4661 } 5068 }
@@ -4789,7 +5196,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4789 public LSL_Vector llGetCenterOfMass() 5196 public LSL_Vector llGetCenterOfMass()
4790 { 5197 {
4791 m_host.AddScriptLPS(1); 5198 m_host.AddScriptLPS(1);
4792 Vector3 center = m_host.GetGeometricCenter(); 5199 Vector3 center = m_host.GetCenterOfMass();
4793 return new LSL_Vector(center.X,center.Y,center.Z); 5200 return new LSL_Vector(center.X,center.Y,center.Z);
4794 } 5201 }
4795 5202
@@ -4808,14 +5215,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4808 { 5215 {
4809 m_host.AddScriptLPS(1); 5216 m_host.AddScriptLPS(1);
4810 5217
4811 if (src == null) 5218 return src.Length;
4812 {
4813 return 0;
4814 }
4815 else
4816 {
4817 return src.Length;
4818 }
4819 } 5219 }
4820 5220
4821 public LSL_Integer llList2Integer(LSL_List src, int index) 5221 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4861,7 +5261,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4861 else if (src.Data[index] is LSL_Float) 5261 else if (src.Data[index] is LSL_Float)
4862 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5262 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4863 else if (src.Data[index] is LSL_String) 5263 else if (src.Data[index] is LSL_String)
4864 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5264 {
5265 string str = ((LSL_String) src.Data[index]).m_string;
5266 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5267 if (m != Match.Empty)
5268 {
5269 str = m.Value;
5270 double d = 0.0;
5271 if (!Double.TryParse(str, out d))
5272 return 0.0;
5273
5274 return d;
5275 }
5276 return 0.0;
5277 }
4865 return Convert.ToDouble(src.Data[index]); 5278 return Convert.ToDouble(src.Data[index]);
4866 } 5279 }
4867 catch (FormatException) 5280 catch (FormatException)
@@ -5134,7 +5547,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5134 } 5547 }
5135 } 5548 }
5136 } 5549 }
5137 else { 5550 else
5551 {
5138 object[] array = new object[src.Length]; 5552 object[] array = new object[src.Length];
5139 Array.Copy(src.Data, 0, array, 0, src.Length); 5553 Array.Copy(src.Data, 0, array, 0, src.Length);
5140 result = new LSL_List(array); 5554 result = new LSL_List(array);
@@ -5241,7 +5655,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5241 public LSL_Integer llGetRegionAgentCount() 5655 public LSL_Integer llGetRegionAgentCount()
5242 { 5656 {
5243 m_host.AddScriptLPS(1); 5657 m_host.AddScriptLPS(1);
5244 return new LSL_Integer(World.GetRootAgentCount()); 5658
5659 int count = 0;
5660 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5661 count++;
5662 });
5663
5664 return new LSL_Integer(count);
5245 } 5665 }
5246 5666
5247 public LSL_Vector llGetRegionCorner() 5667 public LSL_Vector llGetRegionCorner()
@@ -5521,6 +5941,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5521 flags |= ScriptBaseClass.AGENT_SITTING; 5941 flags |= ScriptBaseClass.AGENT_SITTING;
5522 } 5942 }
5523 5943
5944 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
5945 {
5946 flags |= ScriptBaseClass.AGENT_MALE;
5947 }
5948
5524 return flags; 5949 return flags;
5525 } 5950 }
5526 5951
@@ -5668,10 +6093,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5668 m_host.AddScriptLPS(1); 6093 m_host.AddScriptLPS(1);
5669 6094
5670 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6095 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5671 6096 if (parts.Count > 0)
5672 foreach (var part in parts)
5673 { 6097 {
5674 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6098 try
6099 {
6100 parts[0].ParentGroup.areUpdatesSuspended = true;
6101 foreach (var part in parts)
6102 {
6103 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6104 }
6105 }
6106 finally
6107 {
6108 parts[0].ParentGroup.areUpdatesSuspended = false;
6109 }
5675 } 6110 }
5676 } 6111 }
5677 6112
@@ -5723,13 +6158,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5723 6158
5724 if (m_host.OwnerID == land.LandData.OwnerID) 6159 if (m_host.OwnerID == land.LandData.OwnerID)
5725 { 6160 {
5726 World.TeleportClientHome(agentID, presence.ControllingClient); 6161 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6162 presence.TeleportWithMomentum(pos, null);
6163 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5727 } 6164 }
5728 } 6165 }
5729 } 6166 }
5730 ScriptSleep(5000); 6167 ScriptSleep(5000);
5731 } 6168 }
5732 6169
6170 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6171 {
6172 return ParseString2List(str, separators, in_spacers, false);
6173 }
6174
5733 public LSL_Integer llOverMyLand(string id) 6175 public LSL_Integer llOverMyLand(string id)
5734 { 6176 {
5735 m_host.AddScriptLPS(1); 6177 m_host.AddScriptLPS(1);
@@ -5794,8 +6236,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5794 UUID agentId = new UUID(); 6236 UUID agentId = new UUID();
5795 if (!UUID.TryParse(agent, out agentId)) 6237 if (!UUID.TryParse(agent, out agentId))
5796 return new LSL_Integer(0); 6238 return new LSL_Integer(0);
6239 if (agentId == m_host.GroupID)
6240 return new LSL_Integer(1);
5797 ScenePresence presence = World.GetScenePresence(agentId); 6241 ScenePresence presence = World.GetScenePresence(agentId);
5798 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6242 if (presence == null || presence.IsChildAgent) // Return false for child agents
5799 return new LSL_Integer(0); 6243 return new LSL_Integer(0);
5800 IClientAPI client = presence.ControllingClient; 6244 IClientAPI client = presence.ControllingClient;
5801 if (m_host.GroupID == client.ActiveGroupId) 6245 if (m_host.GroupID == client.ActiveGroupId)
@@ -5930,7 +6374,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5930 return m_host.ParentGroup.AttachmentPoint; 6374 return m_host.ParentGroup.AttachmentPoint;
5931 } 6375 }
5932 6376
5933 public LSL_Integer llGetFreeMemory() 6377 public virtual LSL_Integer llGetFreeMemory()
5934 { 6378 {
5935 m_host.AddScriptLPS(1); 6379 m_host.AddScriptLPS(1);
5936 // Make scripts designed for LSO happy 6380 // Make scripts designed for LSO happy
@@ -6047,7 +6491,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6047 SetParticleSystem(m_host, rules); 6491 SetParticleSystem(m_host, rules);
6048 } 6492 }
6049 6493
6050 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6494 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6495 {
6051 6496
6052 6497
6053 if (rules.Length == 0) 6498 if (rules.Length == 0)
@@ -6241,14 +6686,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6241 6686
6242 protected UUID GetTaskInventoryItem(string name) 6687 protected UUID GetTaskInventoryItem(string name)
6243 { 6688 {
6244 lock (m_host.TaskInventory) 6689 m_host.TaskInventory.LockItemsForRead(true);
6690 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6245 { 6691 {
6246 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6692 if (inv.Value.Name == name)
6247 { 6693 {
6248 if (inv.Value.Name == name) 6694 m_host.TaskInventory.LockItemsForRead(false);
6249 return inv.Key; 6695 return inv.Key;
6250 } 6696 }
6251 } 6697 }
6698 m_host.TaskInventory.LockItemsForRead(false);
6252 6699
6253 return UUID.Zero; 6700 return UUID.Zero;
6254 } 6701 }
@@ -6286,16 +6733,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6286 if (folderID == UUID.Zero) 6733 if (folderID == UUID.Zero)
6287 return; 6734 return;
6288 6735
6289 byte[] bucket = new byte[17]; 6736 byte[] bucket = new byte[1];
6290 bucket[0] = (byte)AssetType.Folder; 6737 bucket[0] = (byte)AssetType.Folder;
6291 byte[] objBytes = folderID.GetBytes(); 6738 //byte[] objBytes = folderID.GetBytes();
6292 Array.Copy(objBytes, 0, bucket, 1, 16); 6739 //Array.Copy(objBytes, 0, bucket, 1, 16);
6293 6740
6294 GridInstantMessage msg = new GridInstantMessage(World, 6741 GridInstantMessage msg = new GridInstantMessage(World,
6295 m_host.UUID, m_host.Name+", an object owned by "+ 6742 m_host.OwnerID, m_host.Name, destID,
6296 resolveName(m_host.OwnerID)+",", destID, 6743 (byte)InstantMessageDialog.TaskInventoryOffered,
6297 (byte)InstantMessageDialog.InventoryOffered, 6744 false, category+". "+m_host.Name+" is located at "+
6298 false, category+"\n"+m_host.Name+" is located at "+
6299 World.RegionInfo.RegionName+" "+ 6745 World.RegionInfo.RegionName+" "+
6300 m_host.AbsolutePosition.ToString(), 6746 m_host.AbsolutePosition.ToString(),
6301 folderID, true, m_host.AbsolutePosition, 6747 folderID, true, m_host.AbsolutePosition,
@@ -6533,13 +6979,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6533 UUID av = new UUID(); 6979 UUID av = new UUID();
6534 if (!UUID.TryParse(avatar,out av)) 6980 if (!UUID.TryParse(avatar,out av))
6535 { 6981 {
6536 LSLError("First parameter to llDialog needs to be a key"); 6982 //LSLError("First parameter to llDialog needs to be a key");
6537 return; 6983 return;
6538 } 6984 }
6539 if (buttons.Length < 1) 6985 if (buttons.Length < 1)
6540 { 6986 {
6541 LSLError("No less than 1 button can be shown"); 6987 buttons.Add("OK");
6542 return;
6543 } 6988 }
6544 if (buttons.Length > 12) 6989 if (buttons.Length > 12)
6545 { 6990 {
@@ -6556,7 +7001,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6556 } 7001 }
6557 if (buttons.Data[i].ToString().Length > 24) 7002 if (buttons.Data[i].ToString().Length > 24)
6558 { 7003 {
6559 LSLError("button label cannot be longer than 24 characters"); 7004 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6560 return; 7005 return;
6561 } 7006 }
6562 buts[i] = buttons.Data[i].ToString(); 7007 buts[i] = buttons.Data[i].ToString();
@@ -6615,22 +7060,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6615 } 7060 }
6616 7061
6617 // copy the first script found with this inventory name 7062 // copy the first script found with this inventory name
6618 lock (m_host.TaskInventory) 7063 TaskInventoryItem scriptItem = null;
7064 m_host.TaskInventory.LockItemsForRead(true);
7065 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6619 { 7066 {
6620 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 7067 if (inv.Value.Name == name)
6621 { 7068 {
6622 if (inv.Value.Name == name) 7069 // make sure the object is a script
7070 if (10 == inv.Value.Type)
6623 { 7071 {
6624 // make sure the object is a script 7072 found = true;
6625 if (10 == inv.Value.Type) 7073 srcId = inv.Key;
6626 { 7074 scriptItem = inv.Value;
6627 found = true; 7075 break;
6628 srcId = inv.Key;
6629 break;
6630 }
6631 } 7076 }
6632 } 7077 }
6633 } 7078 }
7079 m_host.TaskInventory.LockItemsForRead(false);
6634 7080
6635 if (!found) 7081 if (!found)
6636 { 7082 {
@@ -6638,9 +7084,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6638 return; 7084 return;
6639 } 7085 }
6640 7086
6641 // the rest of the permission checks are done in RezScript, so check the pin there as well 7087 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6642 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7088 if (dest != null)
7089 {
7090 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7091 {
7092 // the rest of the permission checks are done in RezScript, so check the pin there as well
7093 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6643 7094
7095 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7096 m_host.Inventory.RemoveInventoryItem(srcId);
7097 }
7098 }
6644 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7099 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6645 ScriptSleep(3000); 7100 ScriptSleep(3000);
6646 } 7101 }
@@ -6703,19 +7158,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6703 public LSL_String llMD5String(string src, int nonce) 7158 public LSL_String llMD5String(string src, int nonce)
6704 { 7159 {
6705 m_host.AddScriptLPS(1); 7160 m_host.AddScriptLPS(1);
6706 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7161 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6707 } 7162 }
6708 7163
6709 public LSL_String llSHA1String(string src) 7164 public LSL_String llSHA1String(string src)
6710 { 7165 {
6711 m_host.AddScriptLPS(1); 7166 m_host.AddScriptLPS(1);
6712 return Util.SHA1Hash(src).ToLower(); 7167 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6713 } 7168 }
6714 7169
6715 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7170 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6716 { 7171 {
6717 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7172 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6718 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7173 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7174 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7175 return shapeBlock;
6719 7176
6720 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7177 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6721 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7178 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6820,6 +7277,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6820 // Prim type box, cylinder and prism. 7277 // Prim type box, cylinder and prism.
6821 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) 7278 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)
6822 { 7279 {
7280 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7281 return;
7282
6823 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7283 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6824 ObjectShapePacket.ObjectDataBlock shapeBlock; 7284 ObjectShapePacket.ObjectDataBlock shapeBlock;
6825 7285
@@ -6873,6 +7333,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6873 // Prim type sphere. 7333 // Prim type sphere.
6874 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7334 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6875 { 7335 {
7336 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7337 return;
7338
6876 ObjectShapePacket.ObjectDataBlock shapeBlock; 7339 ObjectShapePacket.ObjectDataBlock shapeBlock;
6877 7340
6878 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7341 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6914,6 +7377,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6914 // Prim type torus, tube and ring. 7377 // Prim type torus, tube and ring.
6915 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) 7378 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)
6916 { 7379 {
7380 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7381 return;
7382
6917 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7383 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6918 ObjectShapePacket.ObjectDataBlock shapeBlock; 7384 ObjectShapePacket.ObjectDataBlock shapeBlock;
6919 7385
@@ -7049,6 +7515,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7049 // Prim type sculpt. 7515 // Prim type sculpt.
7050 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7516 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7051 { 7517 {
7518 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7519 return;
7520
7052 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7521 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7053 UUID sculptId; 7522 UUID sculptId;
7054 7523
@@ -7073,7 +7542,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7073 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7542 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7074 { 7543 {
7075 // default 7544 // default
7076 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7545 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7077 } 7546 }
7078 7547
7079 part.Shape.SetSculptProperties((byte)type, sculptId); 7548 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7089,32 +7558,149 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7089 ScriptSleep(200); 7558 ScriptSleep(200);
7090 } 7559 }
7091 7560
7092 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7561 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7093 { 7562 {
7094 m_host.AddScriptLPS(1); 7563 m_host.AddScriptLPS(1);
7095 7564
7096 setLinkPrimParams(linknumber, rules); 7565 setLinkPrimParams(linknumber, rules);
7566 }
7097 7567
7098 ScriptSleep(200); 7568 private void setLinkPrimParams(int linknumber, LSL_List rules)
7569 {
7570 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7571 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7572 if (parts.Count>0)
7573 {
7574 try
7575 {
7576 parts[0].ParentGroup.areUpdatesSuspended = true;
7577 foreach (SceneObjectPart part in parts)
7578 SetPrimParams(part, rules);
7579 }
7580 finally
7581 {
7582 parts[0].ParentGroup.areUpdatesSuspended = false;
7583 }
7584 }
7585 if (avatars.Count > 0)
7586 {
7587 foreach (ScenePresence avatar in avatars)
7588 SetPrimParams(avatar, rules);
7589 }
7099 } 7590 }
7100 7591
7101 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7592 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7593 float material_density, float material_friction,
7594 float material_restitution, float material_gravity_modifier)
7102 { 7595 {
7103 m_host.AddScriptLPS(1); 7596 ExtraPhysicsData physdata = new ExtraPhysicsData();
7597 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7598 physdata.Density = part.Density;
7599 physdata.Friction = part.Friction;
7600 physdata.Bounce = part.Bounciness;
7601 physdata.GravitationModifier = part.GravityModifier;
7104 7602
7105 setLinkPrimParams(linknumber, rules); 7603 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7604 physdata.Density = material_density;
7605 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7606 physdata.Friction = material_friction;
7607 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7608 physdata.Bounce = material_restitution;
7609 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7610 physdata.GravitationModifier = material_gravity_modifier;
7611
7612 part.UpdateExtraPhysics(physdata);
7106 } 7613 }
7107 7614
7108 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7615 public void llSetPhysicsMaterial(int material_bits,
7616 float material_gravity_modifier, float material_restitution,
7617 float material_friction, float material_density)
7109 { 7618 {
7110 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7619 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7620 }
7111 7621
7112 foreach (SceneObjectPart part in parts) 7622 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7113 SetPrimParams(part, rules); 7623 {
7624 llSetLinkPrimitiveParamsFast(linknumber, rules);
7625 ScriptSleep(200);
7626 }
7627
7628 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7629 {
7630 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7631 //We only support PRIM_POSITION and PRIM_ROTATION
7632
7633 int idx = 0;
7634
7635 while (idx < rules.Length)
7636 {
7637 int code = rules.GetLSLIntegerItem(idx++);
7638
7639 int remain = rules.Length - idx;
7640
7641 switch (code)
7642 {
7643 case (int)ScriptBaseClass.PRIM_POSITION:
7644 {
7645 if (remain < 1)
7646 return;
7647 LSL_Vector v;
7648 v = rules.GetVector3Item(idx++);
7649
7650 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7651 if (part == null)
7652 break;
7653
7654 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7655 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7656 if (llGetLinkNumber() > 1)
7657 {
7658 localRot = llGetLocalRot();
7659 localPos = llGetLocalPos();
7660 }
7661
7662 v -= localPos;
7663 v /= localRot;
7664
7665 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
7666
7667 v = v + 2 * sitOffset;
7668
7669 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7670 av.SendAvatarDataToAllAgents();
7671
7672 }
7673 break;
7674
7675 case (int)ScriptBaseClass.PRIM_ROTATION:
7676 {
7677 if (remain < 1)
7678 return;
7679
7680 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7681 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7682 if (llGetLinkNumber() > 1)
7683 {
7684 localRot = llGetLocalRot();
7685 localPos = llGetLocalPos();
7686 }
7687
7688 LSL_Rotation r;
7689 r = rules.GetQuaternionItem(idx++);
7690 r = r * llGetRootRotation() / localRot;
7691 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7692 av.SendAvatarDataToAllAgents();
7693 }
7694 break;
7695 }
7696 }
7114 } 7697 }
7115 7698
7116 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7699 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7117 { 7700 {
7701 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7702 return;
7703
7118 int idx = 0; 7704 int idx = 0;
7119 7705
7120 bool positionChanged = false; 7706 bool positionChanged = false;
@@ -7436,6 +8022,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7436 part.ScriptSetPhysicsStatus(physics); 8022 part.ScriptSetPhysicsStatus(physics);
7437 break; 8023 break;
7438 8024
8025 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
8026 if (remain < 1)
8027 return;
8028
8029 int shape_type = rules.GetLSLIntegerItem(idx++);
8030
8031 ExtraPhysicsData physdata = new ExtraPhysicsData();
8032 physdata.Density = part.Density;
8033 physdata.Bounce = part.Bounciness;
8034 physdata.GravitationModifier = part.GravityModifier;
8035 physdata.PhysShapeType = (PhysShapeType)shape_type;
8036
8037 part.UpdateExtraPhysics(physdata);
8038
8039 break;
8040
8041 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8042 if (remain < 5)
8043 return;
8044
8045 int material_bits = rules.GetLSLIntegerItem(idx++);
8046 float material_density = (float)rules.GetLSLFloatItem(idx++);
8047 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8048 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8049 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8050
8051 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8052
8053 break;
8054
7439 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8055 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7440 if (remain < 1) 8056 if (remain < 1)
7441 return; 8057 return;
@@ -7509,7 +8125,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7509 if (part.ParentGroup.RootPart == part) 8125 if (part.ParentGroup.RootPart == part)
7510 { 8126 {
7511 SceneObjectGroup parent = part.ParentGroup; 8127 SceneObjectGroup parent = part.ParentGroup;
7512 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8128 Util.FireAndForget(delegate(object x) {
8129 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8130 });
7513 } 8131 }
7514 else 8132 else
7515 { 8133 {
@@ -7520,6 +8138,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7520 } 8138 }
7521 } 8139 }
7522 } 8140 }
8141
8142 if (positionChanged)
8143 {
8144 if (part.ParentGroup.RootPart == part)
8145 {
8146 SceneObjectGroup parent = part.ParentGroup;
8147 Util.FireAndForget(delegate(object x) {
8148 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8149 });
8150 }
8151 else
8152 {
8153 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8154 SceneObjectGroup parent = part.ParentGroup;
8155 parent.HasGroupChanged = true;
8156 parent.ScheduleGroupForTerseUpdate();
8157 }
8158 }
7523 } 8159 }
7524 8160
7525 public LSL_String llStringToBase64(string str) 8161 public LSL_String llStringToBase64(string str)
@@ -7680,13 +8316,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7680 public LSL_Integer llGetNumberOfPrims() 8316 public LSL_Integer llGetNumberOfPrims()
7681 { 8317 {
7682 m_host.AddScriptLPS(1); 8318 m_host.AddScriptLPS(1);
7683 int avatarCount = 0; 8319 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7684 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8320
7685 {
7686 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
7687 avatarCount++;
7688 });
7689
7690 return m_host.ParentGroup.PrimCount + avatarCount; 8321 return m_host.ParentGroup.PrimCount + avatarCount;
7691 } 8322 }
7692 8323
@@ -7702,55 +8333,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7702 m_host.AddScriptLPS(1); 8333 m_host.AddScriptLPS(1);
7703 UUID objID = UUID.Zero; 8334 UUID objID = UUID.Zero;
7704 LSL_List result = new LSL_List(); 8335 LSL_List result = new LSL_List();
8336
8337 // If the ID is not valid, return null result
7705 if (!UUID.TryParse(obj, out objID)) 8338 if (!UUID.TryParse(obj, out objID))
7706 { 8339 {
7707 result.Add(new LSL_Vector()); 8340 result.Add(new LSL_Vector());
7708 result.Add(new LSL_Vector()); 8341 result.Add(new LSL_Vector());
7709 return result; 8342 return result;
7710 } 8343 }
8344
8345 // Check if this is an attached prim. If so, replace
8346 // the UUID with the avatar UUID and report it's bounding box
8347 SceneObjectPart part = World.GetSceneObjectPart(objID);
8348 if (part != null && part.ParentGroup.IsAttachment)
8349 objID = part.ParentGroup.AttachedAvatar;
8350
8351 // Find out if this is an avatar ID. If so, return it's box
7711 ScenePresence presence = World.GetScenePresence(objID); 8352 ScenePresence presence = World.GetScenePresence(objID);
7712 if (presence != null) 8353 if (presence != null)
7713 { 8354 {
7714 if (presence.ParentID == 0) // not sat on an object 8355 // As per LSL Wiki, there is no difference between sitting
8356 // and standing avatar since server 1.36
8357 LSL_Vector lower;
8358 LSL_Vector upper;
8359 if (presence.Animator.Animations.DefaultAnimation.AnimID
8360 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7715 { 8361 {
7716 LSL_Vector lower; 8362 // This is for ground sitting avatars
7717 LSL_Vector upper; 8363 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7718 if (presence.Animator.Animations.DefaultAnimation.AnimID 8364 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7719 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8365 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7720 {
7721 // This is for ground sitting avatars
7722 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7723 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7724 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7725 }
7726 else
7727 {
7728 // This is for standing/flying avatars
7729 float height = presence.Appearance.AvatarHeight / 2.0f;
7730 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7731 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7732 }
7733 result.Add(lower);
7734 result.Add(upper);
7735 return result;
7736 } 8366 }
7737 else 8367 else
7738 { 8368 {
7739 // sitting on an object so we need the bounding box of that 8369 // This is for standing/flying avatars
7740 // which should include the avatar so set the UUID to the 8370 float height = presence.Appearance.AvatarHeight / 2.0f;
7741 // UUID of the object the avatar is sat on and allow it to fall through 8371 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7742 // to processing an object 8372 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7743 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7744 objID = p.UUID;
7745 } 8373 }
8374
8375 // Adjust to the documented error offsets (see LSL Wiki)
8376 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8377 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8378
8379 if (lower.x > upper.x)
8380 lower.x = upper.x;
8381 if (lower.y > upper.y)
8382 lower.y = upper.y;
8383 if (lower.z > upper.z)
8384 lower.z = upper.z;
8385
8386 result.Add(lower);
8387 result.Add(upper);
8388 return result;
7746 } 8389 }
7747 SceneObjectPart part = World.GetSceneObjectPart(objID); 8390
8391 part = World.GetSceneObjectPart(objID);
7748 // Currently only works for single prims without a sitting avatar 8392 // Currently only works for single prims without a sitting avatar
7749 if (part != null) 8393 if (part != null)
7750 { 8394 {
7751 Vector3 halfSize = part.Scale / 2.0f; 8395 float minX;
7752 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8396 float maxX;
7753 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8397 float minY;
8398 float maxY;
8399 float minZ;
8400 float maxZ;
8401
8402 // This BBox is in sim coordinates, with the offset being
8403 // a contained point.
8404 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8405 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8406
8407 minX -= offsets[0].X;
8408 maxX -= offsets[0].X;
8409 minY -= offsets[0].Y;
8410 maxY -= offsets[0].Y;
8411 minZ -= offsets[0].Z;
8412 maxZ -= offsets[0].Z;
8413
8414 LSL_Vector lower;
8415 LSL_Vector upper;
8416
8417 // Adjust to the documented error offsets (see LSL Wiki)
8418 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8419 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8420
8421 if (lower.x > upper.x)
8422 lower.x = upper.x;
8423 if (lower.y > upper.y)
8424 lower.y = upper.y;
8425 if (lower.z > upper.z)
8426 lower.z = upper.z;
8427
7754 result.Add(lower); 8428 result.Add(lower);
7755 result.Add(upper); 8429 result.Add(upper);
7756 return result; 8430 return result;
@@ -7764,7 +8438,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7764 8438
7765 public LSL_Vector llGetGeometricCenter() 8439 public LSL_Vector llGetGeometricCenter()
7766 { 8440 {
7767 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 8441 Vector3 tmp = m_host.GetGeometricCenter();
8442 return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
7768 } 8443 }
7769 8444
7770 public LSL_List llGetPrimitiveParams(LSL_List rules) 8445 public LSL_List llGetPrimitiveParams(LSL_List rules)
@@ -7830,13 +8505,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7830 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8505 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7831 part.AbsolutePosition.Y, 8506 part.AbsolutePosition.Y,
7832 part.AbsolutePosition.Z); 8507 part.AbsolutePosition.Z);
7833 // For some reason, the part.AbsolutePosition.* values do not change if the
7834 // linkset is rotated; they always reflect the child prim's world position
7835 // as though the linkset is unrotated. This is incompatible behavior with SL's
7836 // implementation, so will break scripts imported from there (not to mention it
7837 // makes it more difficult to determine a child prim's actual inworld position).
7838 if (part.ParentID != 0)
7839 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7840 res.Add(v); 8508 res.Add(v);
7841 break; 8509 break;
7842 8510
@@ -8007,56 +8675,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8007 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8675 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8008 if (remain < 1) 8676 if (remain < 1)
8009 return res; 8677 return res;
8010 8678 face = (int)rules.GetLSLIntegerItem(idx++);
8011 face=(int)rules.GetLSLIntegerItem(idx++);
8012 8679
8013 tex = part.Shape.Textures; 8680 tex = part.Shape.Textures;
8681 int shiny;
8014 if (face == ScriptBaseClass.ALL_SIDES) 8682 if (face == ScriptBaseClass.ALL_SIDES)
8015 { 8683 {
8016 for (face = 0; face < GetNumberOfSides(part); face++) 8684 for (face = 0; face < GetNumberOfSides(part); face++)
8017 { 8685 {
8018 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8686 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8019 // Convert Shininess to PRIM_SHINY_* 8687 if (shinyness == Shininess.High)
8020 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8688 {
8021 // PRIM_BUMP_* 8689 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8022 res.Add(new LSL_Integer((int)texface.Bump)); 8690 }
8691 else if (shinyness == Shininess.Medium)
8692 {
8693 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8694 }
8695 else if (shinyness == Shininess.Low)
8696 {
8697 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8698 }
8699 else
8700 {
8701 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8702 }
8703 res.Add(new LSL_Integer(shiny));
8704 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8023 } 8705 }
8024 } 8706 }
8025 else 8707 else
8026 { 8708 {
8027 if (face >= 0 && face < GetNumberOfSides(part)) 8709 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8710 if (shinyness == Shininess.High)
8028 { 8711 {
8029 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8712 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8030 // Convert Shininess to PRIM_SHINY_* 8713 }
8031 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8714 else if (shinyness == Shininess.Medium)
8032 // PRIM_BUMP_* 8715 {
8033 res.Add(new LSL_Integer((int)texface.Bump)); 8716 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8717 }
8718 else if (shinyness == Shininess.Low)
8719 {
8720 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8034 } 8721 }
8722 else
8723 {
8724 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8725 }
8726 res.Add(new LSL_Integer(shiny));
8727 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8035 } 8728 }
8036 break; 8729 break;
8037 8730
8038 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8731 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8039 if (remain < 1) 8732 if (remain < 1)
8040 return res; 8733 return res;
8041 8734 face = (int)rules.GetLSLIntegerItem(idx++);
8042 face=(int)rules.GetLSLIntegerItem(idx++);
8043 8735
8044 tex = part.Shape.Textures; 8736 tex = part.Shape.Textures;
8737 int fullbright;
8045 if (face == ScriptBaseClass.ALL_SIDES) 8738 if (face == ScriptBaseClass.ALL_SIDES)
8046 { 8739 {
8047 for (face = 0; face < GetNumberOfSides(part); face++) 8740 for (face = 0; face < GetNumberOfSides(part); face++)
8048 { 8741 {
8049 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8742 if (tex.GetFace((uint)face).Fullbright == true)
8050 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8743 {
8744 fullbright = ScriptBaseClass.TRUE;
8745 }
8746 else
8747 {
8748 fullbright = ScriptBaseClass.FALSE;
8749 }
8750 res.Add(new LSL_Integer(fullbright));
8051 } 8751 }
8052 } 8752 }
8053 else 8753 else
8054 { 8754 {
8055 if (face >= 0 && face < GetNumberOfSides(part)) 8755 if (tex.GetFace((uint)face).Fullbright == true)
8056 { 8756 {
8057 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8757 fullbright = ScriptBaseClass.TRUE;
8058 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
8059 } 8758 }
8759 else
8760 {
8761 fullbright = ScriptBaseClass.FALSE;
8762 }
8763 res.Add(new LSL_Integer(fullbright));
8060 } 8764 }
8061 break; 8765 break;
8062 8766
@@ -8078,27 +8782,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8078 break; 8782 break;
8079 8783
8080 case (int)ScriptBaseClass.PRIM_TEXGEN: 8784 case (int)ScriptBaseClass.PRIM_TEXGEN:
8785 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8081 if (remain < 1) 8786 if (remain < 1)
8082 return res; 8787 return res;
8083 8788 face = (int)rules.GetLSLIntegerItem(idx++);
8084 face=(int)rules.GetLSLIntegerItem(idx++);
8085 8789
8086 tex = part.Shape.Textures; 8790 tex = part.Shape.Textures;
8087 if (face == ScriptBaseClass.ALL_SIDES) 8791 if (face == ScriptBaseClass.ALL_SIDES)
8088 { 8792 {
8089 for (face = 0; face < GetNumberOfSides(part); face++) 8793 for (face = 0; face < GetNumberOfSides(part); face++)
8090 { 8794 {
8091 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8795 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8092 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8796 {
8093 res.Add(new LSL_Integer((uint)texgen >> 1)); 8797 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8798 }
8799 else
8800 {
8801 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8802 }
8094 } 8803 }
8095 } 8804 }
8096 else 8805 else
8097 { 8806 {
8098 if (face >= 0 && face < GetNumberOfSides(part)) 8807 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8099 { 8808 {
8100 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8809 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8101 res.Add(new LSL_Integer((uint)texgen >> 1)); 8810 }
8811 else
8812 {
8813 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8102 } 8814 }
8103 } 8815 }
8104 break; 8816 break;
@@ -8121,28 +8833,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8121 case (int)ScriptBaseClass.PRIM_GLOW: 8833 case (int)ScriptBaseClass.PRIM_GLOW:
8122 if (remain < 1) 8834 if (remain < 1)
8123 return res; 8835 return res;
8124 8836 face = (int)rules.GetLSLIntegerItem(idx++);
8125 face=(int)rules.GetLSLIntegerItem(idx++);
8126 8837
8127 tex = part.Shape.Textures; 8838 tex = part.Shape.Textures;
8839 float primglow;
8128 if (face == ScriptBaseClass.ALL_SIDES) 8840 if (face == ScriptBaseClass.ALL_SIDES)
8129 { 8841 {
8130 for (face = 0; face < GetNumberOfSides(part); face++) 8842 for (face = 0; face < GetNumberOfSides(part); face++)
8131 { 8843 {
8132 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8844 primglow = tex.GetFace((uint)face).Glow;
8133 res.Add(new LSL_Float(texface.Glow)); 8845 res.Add(new LSL_Float(primglow));
8134 } 8846 }
8135 } 8847 }
8136 else 8848 else
8137 { 8849 {
8138 if (face >= 0 && face < GetNumberOfSides(part)) 8850 primglow = tex.GetFace((uint)face).Glow;
8139 { 8851 res.Add(new LSL_Float(primglow));
8140 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8141 res.Add(new LSL_Float(texface.Glow));
8142 }
8143 } 8852 }
8144 break; 8853 break;
8145
8146 case (int)ScriptBaseClass.PRIM_TEXT: 8854 case (int)ScriptBaseClass.PRIM_TEXT:
8147 Color4 textColor = part.GetTextColor(); 8855 Color4 textColor = part.GetTextColor();
8148 res.Add(new LSL_String(part.Text)); 8856 res.Add(new LSL_String(part.Text));
@@ -8755,8 +9463,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8755 // The function returns an ordered list 9463 // The function returns an ordered list
8756 // representing the tokens found in the supplied 9464 // representing the tokens found in the supplied
8757 // sources string. If two successive tokenizers 9465 // sources string. If two successive tokenizers
8758 // are encountered, then a NULL entry is added 9466 // are encountered, then a null-string entry is
8759 // to the list. 9467 // added to the list.
8760 // 9468 //
8761 // It is a precondition that the source and 9469 // It is a precondition that the source and
8762 // toekizer lisst are non-null. If they are null, 9470 // toekizer lisst are non-null. If they are null,
@@ -8764,7 +9472,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8764 // while their lengths are being determined. 9472 // while their lengths are being determined.
8765 // 9473 //
8766 // A small amount of working memoryis required 9474 // A small amount of working memoryis required
8767 // of approximately 8*#tokenizers. 9475 // of approximately 8*#tokenizers + 8*srcstrlen.
8768 // 9476 //
8769 // There are many ways in which this function 9477 // There are many ways in which this function
8770 // can be implemented, this implementation is 9478 // can be implemented, this implementation is
@@ -8780,155 +9488,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8780 // and eliminates redundant tokenizers as soon 9488 // and eliminates redundant tokenizers as soon
8781 // as is possible. 9489 // as is possible.
8782 // 9490 //
8783 // The implementation tries to avoid any copying 9491 // The implementation tries to minimize temporary
8784 // of arrays or other objects. 9492 // garbage generation.
8785 // </remarks> 9493 // </remarks>
8786 9494
8787 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9495 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8788 { 9496 {
8789 int beginning = 0; 9497 return ParseString2List(src, separators, spacers, true);
8790 int srclen = src.Length; 9498 }
8791 int seplen = separators.Length;
8792 object[] separray = separators.Data;
8793 int spclen = spacers.Length;
8794 object[] spcarray = spacers.Data;
8795 int mlen = seplen+spclen;
8796
8797 int[] offset = new int[mlen+1];
8798 bool[] active = new bool[mlen];
8799
8800 int best;
8801 int j;
8802
8803 // Initial capacity reduces resize cost
8804 9499
8805 LSL_List tokens = new LSL_List(); 9500 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9501 {
9502 int srclen = src.Length;
9503 int seplen = separators.Length;
9504 object[] separray = separators.Data;
9505 int spclen = spacers.Length;
9506 object[] spcarray = spacers.Data;
9507 int dellen = 0;
9508 string[] delarray = new string[seplen+spclen];
8806 9509
8807 // All entries are initially valid 9510 int outlen = 0;
9511 string[] outarray = new string[srclen*2+1];
8808 9512
8809 for (int i = 0; i < mlen; i++) 9513 int i, j;
8810 active[i] = true; 9514 string d;
8811 9515
8812 offset[mlen] = srclen; 9516 m_host.AddScriptLPS(1);
8813 9517
8814 while (beginning < srclen) 9518 /*
9519 * Convert separator and spacer lists to C# strings.
9520 * Also filter out null strings so we don't hang.
9521 */
9522 for (i = 0; i < seplen; i ++)
8815 { 9523 {
9524 d = separray[i].ToString();
9525 if (d.Length > 0)
9526 {
9527 delarray[dellen++] = d;
9528 }
9529 }
9530 seplen = dellen;
8816 9531
8817 best = mlen; // as bad as it gets 9532 for (i = 0; i < spclen; i ++)
9533 {
9534 d = spcarray[i].ToString();
9535 if (d.Length > 0)
9536 {
9537 delarray[dellen++] = d;
9538 }
9539 }
8818 9540
8819 // Scan for separators 9541 /*
9542 * Scan through source string from beginning to end.
9543 */
9544 for (i = 0;;)
9545 {
8820 9546
8821 for (j = 0; j < seplen; j++) 9547 /*
9548 * Find earliest delimeter in src starting at i (if any).
9549 */
9550 int earliestDel = -1;
9551 int earliestSrc = srclen;
9552 string earliestStr = null;
9553 for (j = 0; j < dellen; j ++)
8822 { 9554 {
8823 if (separray[j].ToString() == String.Empty) 9555 d = delarray[j];
8824 active[j] = false; 9556 if (d != null)
8825
8826 if (active[j])
8827 { 9557 {
8828 // scan all of the markers 9558 int index = src.IndexOf(d, i);
8829 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9559 if (index < 0)
8830 { 9560 {
8831 // not present at all 9561 delarray[j] = null; // delim nowhere in src, don't check it anymore
8832 active[j] = false;
8833 } 9562 }
8834 else 9563 else if (index < earliestSrc)
8835 { 9564 {
8836 // present and correct 9565 earliestSrc = index; // where delimeter starts in source string
8837 if (offset[j] < offset[best]) 9566 earliestDel = j; // where delimeter is in delarray[]
8838 { 9567 earliestStr = d; // the delimeter string from delarray[]
8839 // closest so far 9568 if (index == i) break; // can't do any better than found at beg of string
8840 best = j;
8841 if (offset[best] == beginning)
8842 break;
8843 }
8844 } 9569 }
8845 } 9570 }
8846 } 9571 }
8847 9572
8848 // Scan for spacers 9573 /*
8849 9574 * Output source string starting at i through start of earliest delimeter.
8850 if (offset[best] != beginning) 9575 */
9576 if (keepNulls || (earliestSrc > i))
8851 { 9577 {
8852 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9578 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8853 {
8854 if (spcarray[j-seplen].ToString() == String.Empty)
8855 active[j] = false;
8856
8857 if (active[j])
8858 {
8859 // scan all of the markers
8860 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8861 {
8862 // not present at all
8863 active[j] = false;
8864 }
8865 else
8866 {
8867 // present and correct
8868 if (offset[j] < offset[best])
8869 {
8870 // closest so far
8871 best = j;
8872 }
8873 }
8874 }
8875 }
8876 } 9579 }
8877 9580
8878 // This is the normal exit from the scanning loop 9581 /*
9582 * If no delimeter found at or after i, we're done scanning.
9583 */
9584 if (earliestDel < 0) break;
8879 9585
8880 if (best == mlen) 9586 /*
9587 * If delimeter was a spacer, output the spacer.
9588 */
9589 if (earliestDel >= seplen)
8881 { 9590 {
8882 // no markers were found on this pass 9591 outarray[outlen++] = earliestStr;
8883 // so we're pretty much done
8884 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8885 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8886 break;
8887 } 9592 }
8888 9593
8889 // Otherwise we just add the newly delimited token 9594 /*
8890 // and recalculate where the search should continue. 9595 * Look at rest of src string following delimeter.
8891 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9596 */
8892 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9597 i = earliestSrc + earliestStr.Length;
8893
8894 if (best < seplen)
8895 {
8896 beginning = offset[best] + (separray[best].ToString()).Length;
8897 }
8898 else
8899 {
8900 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8901 string str = spcarray[best - seplen].ToString();
8902 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8903 tokens.Add(new LSL_String(str));
8904 }
8905 } 9598 }
8906 9599
8907 // This an awkward an not very intuitive boundary case. If the 9600 /*
8908 // last substring is a tokenizer, then there is an implied trailing 9601 * Make up an exact-sized output array suitable for an LSL_List object.
8909 // null list entry. Hopefully the single comparison will not be too 9602 */
8910 // arduous. Alternatively the 'break' could be replced with a return 9603 object[] outlist = new object[outlen];
8911 // but that's shabby programming. 9604 for (i = 0; i < outlen; i ++)
8912
8913 if ((beginning == srclen) && (keepNulls))
8914 { 9605 {
8915 if (srclen != 0) 9606 outlist[i] = new LSL_String(outarray[i]);
8916 tokens.Add(new LSL_String(""));
8917 } 9607 }
8918 9608 return new LSL_List(outlist);
8919 return tokens;
8920 }
8921
8922 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8923 {
8924 m_host.AddScriptLPS(1);
8925 return this.ParseString(src, separators, spacers, false);
8926 }
8927
8928 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8929 {
8930 m_host.AddScriptLPS(1);
8931 return this.ParseString(src, separators, spacers, true);
8932 } 9609 }
8933 9610
8934 public LSL_Integer llGetObjectPermMask(int mask) 9611 public LSL_Integer llGetObjectPermMask(int mask)
@@ -9005,28 +9682,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9005 { 9682 {
9006 m_host.AddScriptLPS(1); 9683 m_host.AddScriptLPS(1);
9007 9684
9008 lock (m_host.TaskInventory) 9685 m_host.TaskInventory.LockItemsForRead(true);
9686 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9009 { 9687 {
9010 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9688 if (inv.Value.Name == item)
9011 { 9689 {
9012 if (inv.Value.Name == item) 9690 m_host.TaskInventory.LockItemsForRead(false);
9691 switch (mask)
9013 { 9692 {
9014 switch (mask) 9693 case 0:
9015 { 9694 return (int)inv.Value.BasePermissions;
9016 case 0: 9695 case 1:
9017 return (int)inv.Value.BasePermissions; 9696 return (int)inv.Value.CurrentPermissions;
9018 case 1: 9697 case 2:
9019 return (int)inv.Value.CurrentPermissions; 9698 return (int)inv.Value.GroupPermissions;
9020 case 2: 9699 case 3:
9021 return (int)inv.Value.GroupPermissions; 9700 return (int)inv.Value.EveryonePermissions;
9022 case 3: 9701 case 4:
9023 return (int)inv.Value.EveryonePermissions; 9702 return (int)inv.Value.NextPermissions;
9024 case 4:
9025 return (int)inv.Value.NextPermissions;
9026 }
9027 } 9703 }
9028 } 9704 }
9029 } 9705 }
9706 m_host.TaskInventory.LockItemsForRead(false);
9030 9707
9031 return -1; 9708 return -1;
9032 } 9709 }
@@ -9073,16 +9750,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9073 { 9750 {
9074 m_host.AddScriptLPS(1); 9751 m_host.AddScriptLPS(1);
9075 9752
9076 lock (m_host.TaskInventory) 9753 m_host.TaskInventory.LockItemsForRead(true);
9754 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9077 { 9755 {
9078 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9756 if (inv.Value.Name == item)
9079 { 9757 {
9080 if (inv.Value.Name == item) 9758 m_host.TaskInventory.LockItemsForRead(false);
9081 { 9759 return inv.Value.CreatorID.ToString();
9082 return inv.Value.CreatorID.ToString();
9083 }
9084 } 9760 }
9085 } 9761 }
9762 m_host.TaskInventory.LockItemsForRead(false);
9086 9763
9087 llSay(0, "No item name '" + item + "'"); 9764 llSay(0, "No item name '" + item + "'");
9088 9765
@@ -9224,9 +9901,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9224 { 9901 {
9225 try 9902 try
9226 { 9903 {
9904 /*
9227 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 9905 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
9228 if (obj != null) 9906 if (obj != null)
9229 return (double)obj.GetMass(); 9907 return (double)obj.GetMass();
9908 */
9909 // return total object mass
9910 SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
9911 if (obj != null)
9912 return obj.GetMass();
9913
9230 // the object is null so the key is for an avatar 9914 // the object is null so the key is for an avatar
9231 ScenePresence avatar = World.GetScenePresence(key); 9915 ScenePresence avatar = World.GetScenePresence(key);
9232 if (avatar != null) 9916 if (avatar != null)
@@ -9246,7 +9930,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9246 } 9930 }
9247 9931
9248 /// <summary> 9932 /// <summary>
9249 /// illListReplaceList removes the sub-list defined by the inclusive indices 9933 /// llListReplaceList removes the sub-list defined by the inclusive indices
9250 /// start and end and inserts the src list in its place. The inclusive 9934 /// start and end and inserts the src list in its place. The inclusive
9251 /// nature of the indices means that at least one element must be deleted 9935 /// nature of the indices means that at least one element must be deleted
9252 /// if the indices are within the bounds of the existing list. I.e. 2,2 9936 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9303,16 +9987,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9303 // based upon end. Note that if end exceeds the upper 9987 // based upon end. Note that if end exceeds the upper
9304 // bound in this case, the entire destination list 9988 // bound in this case, the entire destination list
9305 // is removed. 9989 // is removed.
9306 else 9990 else if (start == 0)
9307 { 9991 {
9308 if (end + 1 < dest.Length) 9992 if (end + 1 < dest.Length)
9309 {
9310 return src + dest.GetSublist(end + 1, -1); 9993 return src + dest.GetSublist(end + 1, -1);
9311 }
9312 else 9994 else
9313 {
9314 return src; 9995 return src;
9315 } 9996 }
9997 else // Start < 0
9998 {
9999 if (end + 1 < dest.Length)
10000 return dest.GetSublist(end + 1, -1);
10001 else
10002 return new LSL_List();
9316 } 10003 }
9317 } 10004 }
9318 // Finally, if start > end, we strip away a prefix and 10005 // Finally, if start > end, we strip away a prefix and
@@ -9363,17 +10050,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9363 int width = 0; 10050 int width = 0;
9364 int height = 0; 10051 int height = 0;
9365 10052
9366 ParcelMediaCommandEnum? commandToSend = null; 10053 uint commandToSend = 0;
9367 float time = 0.0f; // default is from start 10054 float time = 0.0f; // default is from start
9368 10055
9369 ScenePresence presence = null; 10056 ScenePresence presence = null;
9370 10057
9371 for (int i = 0; i < commandList.Data.Length; i++) 10058 for (int i = 0; i < commandList.Data.Length; i++)
9372 { 10059 {
9373 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10060 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9374 switch (command) 10061 switch (command)
9375 { 10062 {
9376 case ParcelMediaCommandEnum.Agent: 10063 case (uint)ParcelMediaCommandEnum.Agent:
9377 // we send only to one agent 10064 // we send only to one agent
9378 if ((i + 1) < commandList.Length) 10065 if ((i + 1) < commandList.Length)
9379 { 10066 {
@@ -9390,25 +10077,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9390 } 10077 }
9391 break; 10078 break;
9392 10079
9393 case ParcelMediaCommandEnum.Loop: 10080 case (uint)ParcelMediaCommandEnum.Loop:
9394 loop = 1; 10081 loop = 1;
9395 commandToSend = command; 10082 commandToSend = command;
9396 update = true; //need to send the media update packet to set looping 10083 update = true; //need to send the media update packet to set looping
9397 break; 10084 break;
9398 10085
9399 case ParcelMediaCommandEnum.Play: 10086 case (uint)ParcelMediaCommandEnum.Play:
9400 loop = 0; 10087 loop = 0;
9401 commandToSend = command; 10088 commandToSend = command;
9402 update = true; //need to send the media update packet to make sure it doesn't loop 10089 update = true; //need to send the media update packet to make sure it doesn't loop
9403 break; 10090 break;
9404 10091
9405 case ParcelMediaCommandEnum.Pause: 10092 case (uint)ParcelMediaCommandEnum.Pause:
9406 case ParcelMediaCommandEnum.Stop: 10093 case (uint)ParcelMediaCommandEnum.Stop:
9407 case ParcelMediaCommandEnum.Unload: 10094 case (uint)ParcelMediaCommandEnum.Unload:
9408 commandToSend = command; 10095 commandToSend = command;
9409 break; 10096 break;
9410 10097
9411 case ParcelMediaCommandEnum.Url: 10098 case (uint)ParcelMediaCommandEnum.Url:
9412 if ((i + 1) < commandList.Length) 10099 if ((i + 1) < commandList.Length)
9413 { 10100 {
9414 if (commandList.Data[i + 1] is LSL_String) 10101 if (commandList.Data[i + 1] is LSL_String)
@@ -9421,7 +10108,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9421 } 10108 }
9422 break; 10109 break;
9423 10110
9424 case ParcelMediaCommandEnum.Texture: 10111 case (uint)ParcelMediaCommandEnum.Texture:
9425 if ((i + 1) < commandList.Length) 10112 if ((i + 1) < commandList.Length)
9426 { 10113 {
9427 if (commandList.Data[i + 1] is LSL_String) 10114 if (commandList.Data[i + 1] is LSL_String)
@@ -9434,7 +10121,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9434 } 10121 }
9435 break; 10122 break;
9436 10123
9437 case ParcelMediaCommandEnum.Time: 10124 case (uint)ParcelMediaCommandEnum.Time:
9438 if ((i + 1) < commandList.Length) 10125 if ((i + 1) < commandList.Length)
9439 { 10126 {
9440 if (commandList.Data[i + 1] is LSL_Float) 10127 if (commandList.Data[i + 1] is LSL_Float)
@@ -9446,7 +10133,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9446 } 10133 }
9447 break; 10134 break;
9448 10135
9449 case ParcelMediaCommandEnum.AutoAlign: 10136 case (uint)ParcelMediaCommandEnum.AutoAlign:
9450 if ((i + 1) < commandList.Length) 10137 if ((i + 1) < commandList.Length)
9451 { 10138 {
9452 if (commandList.Data[i + 1] is LSL_Integer) 10139 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9460,7 +10147,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9460 } 10147 }
9461 break; 10148 break;
9462 10149
9463 case ParcelMediaCommandEnum.Type: 10150 case (uint)ParcelMediaCommandEnum.Type:
9464 if ((i + 1) < commandList.Length) 10151 if ((i + 1) < commandList.Length)
9465 { 10152 {
9466 if (commandList.Data[i + 1] is LSL_String) 10153 if (commandList.Data[i + 1] is LSL_String)
@@ -9473,7 +10160,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9473 } 10160 }
9474 break; 10161 break;
9475 10162
9476 case ParcelMediaCommandEnum.Desc: 10163 case (uint)ParcelMediaCommandEnum.Desc:
9477 if ((i + 1) < commandList.Length) 10164 if ((i + 1) < commandList.Length)
9478 { 10165 {
9479 if (commandList.Data[i + 1] is LSL_String) 10166 if (commandList.Data[i + 1] is LSL_String)
@@ -9486,7 +10173,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9486 } 10173 }
9487 break; 10174 break;
9488 10175
9489 case ParcelMediaCommandEnum.Size: 10176 case (uint)ParcelMediaCommandEnum.Size:
9490 if ((i + 2) < commandList.Length) 10177 if ((i + 2) < commandList.Length)
9491 { 10178 {
9492 if (commandList.Data[i + 1] is LSL_Integer) 10179 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9556,7 +10243,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9556 } 10243 }
9557 } 10244 }
9558 10245
9559 if (commandToSend != null) 10246 if (commandToSend != 0)
9560 { 10247 {
9561 // the commandList contained a start/stop/... command, too 10248 // the commandList contained a start/stop/... command, too
9562 if (presence == null) 10249 if (presence == null)
@@ -9593,7 +10280,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9593 10280
9594 if (aList.Data[i] != null) 10281 if (aList.Data[i] != null)
9595 { 10282 {
9596 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10283 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9597 { 10284 {
9598 case ParcelMediaCommandEnum.Url: 10285 case ParcelMediaCommandEnum.Url:
9599 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10286 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9636,16 +10323,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9636 { 10323 {
9637 m_host.AddScriptLPS(1); 10324 m_host.AddScriptLPS(1);
9638 10325
9639 lock (m_host.TaskInventory) 10326 m_host.TaskInventory.LockItemsForRead(true);
10327 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9640 { 10328 {
9641 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10329 if (inv.Value.Name == name)
9642 { 10330 {
9643 if (inv.Value.Name == name) 10331 m_host.TaskInventory.LockItemsForRead(false);
9644 { 10332 return inv.Value.Type;
9645 return inv.Value.Type;
9646 }
9647 } 10333 }
9648 } 10334 }
10335 m_host.TaskInventory.LockItemsForRead(false);
9649 10336
9650 return -1; 10337 return -1;
9651 } 10338 }
@@ -9656,15 +10343,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9656 10343
9657 if (quick_pay_buttons.Data.Length < 4) 10344 if (quick_pay_buttons.Data.Length < 4)
9658 { 10345 {
9659 LSLError("List must have at least 4 elements"); 10346 int x;
9660 return; 10347 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10348 {
10349 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10350 }
9661 } 10351 }
9662 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10352 int[] nPrice = new int[5];
9663 10353 nPrice[0] = price;
9664 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10354 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9665 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10355 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9666 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10356 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9667 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10357 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10358 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9668 m_host.ParentGroup.HasGroupChanged = true; 10359 m_host.ParentGroup.HasGroupChanged = true;
9669 } 10360 }
9670 10361
@@ -9680,8 +10371,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9680 ShoutError("No permissions to track the camera"); 10371 ShoutError("No permissions to track the camera");
9681 return new LSL_Vector(); 10372 return new LSL_Vector();
9682 } 10373 }
10374 m_host.TaskInventory.LockItemsForRead(false);
9683 10375
9684 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10376// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10377 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9685 if (presence != null) 10378 if (presence != null)
9686 { 10379 {
9687 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); 10380 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
@@ -9702,8 +10395,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9702 ShoutError("No permissions to track the camera"); 10395 ShoutError("No permissions to track the camera");
9703 return new LSL_Rotation(); 10396 return new LSL_Rotation();
9704 } 10397 }
10398 m_host.TaskInventory.LockItemsForRead(false);
9705 10399
9706 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10400// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10401 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9707 if (presence != null) 10402 if (presence != null)
9708 { 10403 {
9709 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); 10404 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W);
@@ -9763,8 +10458,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9763 { 10458 {
9764 m_host.AddScriptLPS(1); 10459 m_host.AddScriptLPS(1);
9765 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 10460 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
9766 if (detectedParams == null) return; // only works on the first detected avatar 10461 if (detectedParams == null)
9767 10462 {
10463 if (m_host.ParentGroup.IsAttachment == true)
10464 {
10465 detectedParams = new DetectParams();
10466 detectedParams.Key = m_host.OwnerID;
10467 }
10468 else
10469 {
10470 return;
10471 }
10472 }
10473
9768 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10474 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9769 if (avatar != null) 10475 if (avatar != null)
9770 { 10476 {
@@ -9772,6 +10478,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9772 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10478 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9773 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10479 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9774 } 10480 }
10481
9775 ScriptSleep(1000); 10482 ScriptSleep(1000);
9776 } 10483 }
9777 10484
@@ -9895,12 +10602,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9895 10602
9896 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10603 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9897 object[] data = rules.Data; 10604 object[] data = rules.Data;
9898 for (int i = 0; i < data.Length; ++i) { 10605 for (int i = 0; i < data.Length; ++i)
10606 {
9899 int type = Convert.ToInt32(data[i++].ToString()); 10607 int type = Convert.ToInt32(data[i++].ToString());
9900 if (i >= data.Length) break; // odd number of entries => ignore the last 10608 if (i >= data.Length) break; // odd number of entries => ignore the last
9901 10609
9902 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10610 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9903 switch (type) { 10611 switch (type)
10612 {
9904 case ScriptBaseClass.CAMERA_FOCUS: 10613 case ScriptBaseClass.CAMERA_FOCUS:
9905 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10614 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9906 case ScriptBaseClass.CAMERA_POSITION: 10615 case ScriptBaseClass.CAMERA_POSITION:
@@ -10006,19 +10715,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10006 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10715 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
10007 { 10716 {
10008 m_host.AddScriptLPS(1); 10717 m_host.AddScriptLPS(1);
10009 string ret = String.Empty; 10718
10010 string src1 = llBase64ToString(str1); 10719 if (str1 == String.Empty)
10011 string src2 = llBase64ToString(str2); 10720 return String.Empty;
10012 int c = 0; 10721 if (str2 == String.Empty)
10013 for (int i = 0; i < src1.Length; i++) 10722 return str1;
10723
10724 int len = str2.Length;
10725 if ((len % 4) != 0) // LL is EVIL!!!!
10014 { 10726 {
10015 ret += (char) (src1[i] ^ src2[c]); 10727 while (str2.EndsWith("="))
10728 str2 = str2.Substring(0, str2.Length - 1);
10729
10730 len = str2.Length;
10731 int mod = len % 4;
10016 10732
10017 c++; 10733 if (mod == 1)
10018 if (c >= src2.Length) 10734 str2 = str2.Substring(0, str2.Length - 1);
10019 c = 0; 10735 else if (mod == 2)
10736 str2 += "==";
10737 else if (mod == 3)
10738 str2 += "=";
10020 } 10739 }
10021 return llStringToBase64(ret); 10740
10741 byte[] data1;
10742 byte[] data2;
10743 try
10744 {
10745 data1 = Convert.FromBase64String(str1);
10746 data2 = Convert.FromBase64String(str2);
10747 }
10748 catch (Exception)
10749 {
10750 return new LSL_String(String.Empty);
10751 }
10752
10753 byte[] d2 = new Byte[data1.Length];
10754 int pos = 0;
10755
10756 if (data1.Length <= data2.Length)
10757 {
10758 Array.Copy(data2, 0, d2, 0, data1.Length);
10759 }
10760 else
10761 {
10762 while (pos < data1.Length)
10763 {
10764 len = data1.Length - pos;
10765 if (len > data2.Length)
10766 len = data2.Length;
10767
10768 Array.Copy(data2, 0, d2, pos, len);
10769 pos += len;
10770 }
10771 }
10772
10773 for (pos = 0 ; pos < data1.Length ; pos++ )
10774 data1[pos] ^= d2[pos];
10775
10776 return Convert.ToBase64String(data1);
10022 } 10777 }
10023 10778
10024 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10779 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10075,12 +10830,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10075 Regex r = new Regex(authregex); 10830 Regex r = new Regex(authregex);
10076 int[] gnums = r.GetGroupNumbers(); 10831 int[] gnums = r.GetGroupNumbers();
10077 Match m = r.Match(url); 10832 Match m = r.Match(url);
10078 if (m.Success) { 10833 if (m.Success)
10079 for (int i = 1; i < gnums.Length; i++) { 10834 {
10835 for (int i = 1; i < gnums.Length; i++)
10836 {
10080 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10837 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10081 //CaptureCollection cc = g.Captures; 10838 //CaptureCollection cc = g.Captures;
10082 } 10839 }
10083 if (m.Groups.Count == 5) { 10840 if (m.Groups.Count == 5)
10841 {
10084 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10842 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10085 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10843 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10086 } 10844 }
@@ -10443,15 +11201,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10443 11201
10444 internal UUID ScriptByName(string name) 11202 internal UUID ScriptByName(string name)
10445 { 11203 {
10446 lock (m_host.TaskInventory) 11204 m_host.TaskInventory.LockItemsForRead(true);
11205
11206 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10447 { 11207 {
10448 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 11208 if (item.Type == 10 && item.Name == name)
10449 { 11209 {
10450 if (item.Type == 10 && item.Name == name) 11210 m_host.TaskInventory.LockItemsForRead(false);
10451 return item.ItemID; 11211 return item.ItemID;
10452 } 11212 }
10453 } 11213 }
10454 11214
11215 m_host.TaskInventory.LockItemsForRead(false);
11216
10455 return UUID.Zero; 11217 return UUID.Zero;
10456 } 11218 }
10457 11219
@@ -10492,6 +11254,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10492 { 11254 {
10493 m_host.AddScriptLPS(1); 11255 m_host.AddScriptLPS(1);
10494 11256
11257 //Clone is thread safe
10495 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11258 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10496 11259
10497 UUID assetID = UUID.Zero; 11260 UUID assetID = UUID.Zero;
@@ -10554,6 +11317,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10554 { 11317 {
10555 m_host.AddScriptLPS(1); 11318 m_host.AddScriptLPS(1);
10556 11319
11320 //Clone is thread safe
10557 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11321 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10558 11322
10559 UUID assetID = UUID.Zero; 11323 UUID assetID = UUID.Zero;
@@ -10634,15 +11398,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10634 return GetLinkPrimitiveParams(obj, rules); 11398 return GetLinkPrimitiveParams(obj, rules);
10635 } 11399 }
10636 11400
10637 public void print(string str) 11401 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10638 { 11402 {
10639 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11403 List<SceneObjectPart> parts = GetLinkParts(link);
10640 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11404 if (parts.Count < 1)
10641 if (ossl != null) 11405 return 0;
10642 { 11406
10643 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11407 return GetNumberOfSides(parts[0]);
10644 m_log.Info("LSL print():" + str);
10645 }
10646 } 11408 }
10647 11409
10648 private string Name2Username(string name) 11410 private string Name2Username(string name)
@@ -10688,155 +11450,482 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10688 return rq.ToString(); 11450 return rq.ToString();
10689 } 11451 }
10690 11452
11453 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11454 {
11455 m_SayShoutCount = 0;
11456 }
11457
11458 private struct Tri
11459 {
11460 public Vector3 p1;
11461 public Vector3 p2;
11462 public Vector3 p3;
11463 }
11464
11465 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11466 {
11467 float height = avatar.Appearance.AvatarHeight;
11468 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11469 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11470
11471 if (point.X > b1.X && point.X < b2.X &&
11472 point.Y > b1.Y && point.Y < b2.Y &&
11473 point.Z > b1.Z && point.Z < b2.Z)
11474 return true;
11475 return false;
11476 }
11477
11478 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11479 {
11480 List<ContactResult> contacts = new List<ContactResult>();
11481
11482 Vector3 ab = rayEnd - rayStart;
11483
11484 World.ForEachScenePresence(delegate(ScenePresence sp)
11485 {
11486 Vector3 ac = sp.AbsolutePosition - rayStart;
11487 Vector3 bc = sp.AbsolutePosition - rayEnd;
11488
11489 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11490
11491 if (d > 1.5)
11492 return;
11493
11494 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11495
11496 if (d2 > 0)
11497 return;
11498
11499 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11500 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11501
11502 if (!InBoundingBox(sp, p))
11503 return;
11504
11505 ContactResult result = new ContactResult ();
11506 result.ConsumerID = sp.LocalId;
11507 result.Depth = Vector3.Distance(rayStart, p);
11508 result.Normal = Vector3.Zero;
11509 result.Pos = p;
11510
11511 contacts.Add(result);
11512 });
11513
11514 return contacts.ToArray();
11515 }
11516
11517 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11518 {
11519 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11520 List<ContactResult> contacts = new List<ContactResult>();
11521
11522 Vector3 ab = rayEnd - rayStart;
11523
11524 World.ForEachSOG(delegate(SceneObjectGroup group)
11525 {
11526 if (m_host.ParentGroup == group)
11527 return;
11528
11529 if (group.IsAttachment)
11530 return;
11531
11532 if (group.RootPart.PhysActor == null)
11533 {
11534 if (!includePhantom)
11535 return;
11536 }
11537 else
11538 {
11539 if (group.RootPart.PhysActor.IsPhysical)
11540 {
11541 if (!includePhysical)
11542 return;
11543 }
11544 else
11545 {
11546 if (!includeNonPhysical)
11547 return;
11548 }
11549 }
11550
11551 // Find the radius ouside of which we don't even need to hit test
11552 float minX;
11553 float maxX;
11554 float minY;
11555 float maxY;
11556 float minZ;
11557 float maxZ;
11558
11559 float radius = 0.0f;
11560
11561 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11562
11563 if (Math.Abs(minX) > radius)
11564 radius = Math.Abs(minX);
11565 if (Math.Abs(minY) > radius)
11566 radius = Math.Abs(minY);
11567 if (Math.Abs(minZ) > radius)
11568 radius = Math.Abs(minZ);
11569 if (Math.Abs(maxX) > radius)
11570 radius = Math.Abs(maxX);
11571 if (Math.Abs(maxY) > radius)
11572 radius = Math.Abs(maxY);
11573 if (Math.Abs(maxZ) > radius)
11574 radius = Math.Abs(maxZ);
11575
11576 Vector3 ac = group.AbsolutePosition - rayStart;
11577 Vector3 bc = group.AbsolutePosition - rayEnd;
11578
11579 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11580
11581 // Too far off ray, don't bother
11582 if (d > radius)
11583 return;
11584
11585 // Behind ray, drop
11586 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11587 if (d2 > 0)
11588 return;
11589
11590 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11591 // Miss.
11592 if (!intersection.HitTF)
11593 return;
11594
11595 ContactResult result = new ContactResult ();
11596 result.ConsumerID = group.LocalId;
11597 result.Depth = intersection.distance;
11598 result.Normal = intersection.normal;
11599 result.Pos = intersection.ipoint;
11600
11601 contacts.Add(result);
11602 });
11603
11604 return contacts.ToArray();
11605 }
11606
11607 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11608 {
11609 double[,] heightfield = World.Heightmap.GetDoubles();
11610 List<ContactResult> contacts = new List<ContactResult>();
11611
11612 double min = 2048.0;
11613 double max = 0.0;
11614
11615 // Find the min and max of the heightfield
11616 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11617 {
11618 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11619 {
11620 if (heightfield[x, y] > max)
11621 max = heightfield[x, y];
11622 if (heightfield[x, y] < min)
11623 min = heightfield[x, y];
11624 }
11625 }
11626
11627
11628 // A ray extends past rayEnd, but doesn't go back before
11629 // rayStart. If the start is above the highest point of the ground
11630 // and the ray goes up, we can't hit the ground. Ever.
11631 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11632 return null;
11633
11634 // Same for going down
11635 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11636 return null;
11637
11638 List<Tri> trilist = new List<Tri>();
11639
11640 // Create our triangle list
11641 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11642 {
11643 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11644 {
11645 Tri t1 = new Tri();
11646 Tri t2 = new Tri();
11647
11648 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11649 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11650 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11651 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11652
11653 t1.p1 = p1;
11654 t1.p2 = p2;
11655 t1.p3 = p3;
11656
11657 t2.p1 = p3;
11658 t2.p2 = p4;
11659 t2.p3 = p1;
11660
11661 trilist.Add(t1);
11662 trilist.Add(t2);
11663 }
11664 }
11665
11666 // Ray direction
11667 Vector3 rayDirection = rayEnd - rayStart;
11668
11669 foreach (Tri t in trilist)
11670 {
11671 // Compute triangle plane normal and edges
11672 Vector3 u = t.p2 - t.p1;
11673 Vector3 v = t.p3 - t.p1;
11674 Vector3 n = Vector3.Cross(u, v);
11675
11676 if (n == Vector3.Zero)
11677 continue;
11678
11679 Vector3 w0 = rayStart - t.p1;
11680 double a = -Vector3.Dot(n, w0);
11681 double b = Vector3.Dot(n, rayDirection);
11682
11683 // Not intersecting the plane, or in plane (same thing)
11684 // Ignoring this MAY cause the ground to not be detected
11685 // sometimes
11686 if (Math.Abs(b) < 0.000001)
11687 continue;
11688
11689 double r = a / b;
11690
11691 // ray points away from plane
11692 if (r < 0.0)
11693 continue;
11694
11695 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11696
11697 float uu = Vector3.Dot(u, u);
11698 float uv = Vector3.Dot(u, v);
11699 float vv = Vector3.Dot(v, v);
11700 Vector3 w = ip - t.p1;
11701 float wu = Vector3.Dot(w, u);
11702 float wv = Vector3.Dot(w, v);
11703 float d = uv * uv - uu * vv;
11704
11705 float cs = (uv * wv - vv * wu) / d;
11706 if (cs < 0 || cs > 1.0)
11707 continue;
11708 float ct = (uv * wu - uu * wv) / d;
11709 if (ct < 0 || (cs + ct) > 1.0)
11710 continue;
11711
11712 // Add contact point
11713 ContactResult result = new ContactResult ();
11714 result.ConsumerID = 0;
11715 result.Depth = Vector3.Distance(rayStart, ip);
11716 result.Normal = n;
11717 result.Pos = ip;
11718
11719 contacts.Add(result);
11720 }
11721
11722 if (contacts.Count == 0)
11723 return null;
11724
11725 contacts.Sort(delegate(ContactResult a, ContactResult b)
11726 {
11727 return (int)(a.Depth - b.Depth);
11728 });
11729
11730 return contacts[0];
11731 }
11732/*
11733 // not done:
11734 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
11735 {
11736 ContactResult[] contacts = null;
11737 World.ForEachSOG(delegate(SceneObjectGroup group)
11738 {
11739 if (m_host.ParentGroup == group)
11740 return;
11741
11742 if (group.IsAttachment)
11743 return;
11744
11745 if(group.RootPart.PhysActor != null)
11746 return;
11747
11748 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
11749 });
11750 return contacts;
11751 }
11752*/
11753
10691 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11754 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10692 { 11755 {
11756 LSL_List list = new LSL_List();
11757
10693 m_host.AddScriptLPS(1); 11758 m_host.AddScriptLPS(1);
10694 11759
10695 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11760 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10696 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11761 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10697 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11762 Vector3 dir = rayEnd - rayStart;
10698 11763
10699 int count = 0; 11764 float dist = Vector3.Mag(dir);
10700// int detectPhantom = 0; 11765
11766 int count = 1;
11767 bool detectPhantom = false;
10701 int dataFlags = 0; 11768 int dataFlags = 0;
10702 int rejectTypes = 0; 11769 int rejectTypes = 0;
10703 11770
10704 for (int i = 0; i < options.Length; i += 2) 11771 for (int i = 0; i < options.Length; i += 2)
10705 { 11772 {
10706 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11773 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10707 {
10708 count = options.GetLSLIntegerItem(i + 1); 11774 count = options.GetLSLIntegerItem(i + 1);
10709 } 11775 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10710// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11776 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10711// {
10712// detectPhantom = options.GetLSLIntegerItem(i + 1);
10713// }
10714 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11777 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10715 {
10716 dataFlags = options.GetLSLIntegerItem(i + 1); 11778 dataFlags = options.GetLSLIntegerItem(i + 1);
10717 }
10718 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11779 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10719 {
10720 rejectTypes = options.GetLSLIntegerItem(i + 1); 11780 rejectTypes = options.GetLSLIntegerItem(i + 1);
10721 }
10722 } 11781 }
10723 11782
10724 LSL_List list = new LSL_List(); 11783 if (count > 16)
10725 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11784 count = 16;
10726
10727 double distance = Util.GetDistanceTo(startvector, endvector);
10728 11785
10729 if (distance == 0) 11786 List<ContactResult> results = new List<ContactResult>();
10730 distance = 0.001;
10731
10732 Vector3 posToCheck = startvector;
10733 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10734 11787
10735 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11788 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10736 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11789 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10737 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11790 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10738 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11791 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10739 11792
10740 for (float i = 0; i <= distance; i += 0.1f) 11793
11794 if (World.SuportsRayCastFiltered())
10741 { 11795 {
10742 posToCheck = startvector + (dir * (i / (float)distance)); 11796 if (dist == 0)
11797 return list;
11798
11799 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
11800 if (checkTerrain)
11801 rayfilter |= RayFilterFlags.land;
11802// if (checkAgents)
11803// rayfilter |= RayFilterFlags.agent;
11804 if (checkPhysical)
11805 rayfilter |= RayFilterFlags.physical;
11806 if (checkNonPhysical)
11807 rayfilter |= RayFilterFlags.nonphysical;
11808 if (detectPhantom)
11809 rayfilter |= RayFilterFlags.LSLPhanton;
10743 11810
10744 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11811 Vector3 direction = dir * ( 1/dist);
11812
11813 if(rayfilter == 0)
10745 { 11814 {
10746 ContactResult result = new ContactResult(); 11815 list.Add(new LSL_Integer(0));
10747 result.ConsumerID = 0; 11816 return list;
10748 result.Depth = 0;
10749 result.Normal = Vector3.Zero;
10750 result.Pos = posToCheck;
10751 results.Add(result);
10752 checkTerrain = false;
10753 } 11817 }
10754 11818
10755 if (checkAgents) 11819 // get some more contacts to sort ???
11820 int physcount = 4 * count;
11821 if (physcount > 20)
11822 physcount = 20;
11823
11824 object physresults;
11825 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
11826
11827 if (physresults == null)
10756 { 11828 {
10757 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11829 list.Add(new LSL_Integer(-3)); // timeout error
10758 { 11830 return list;
10759 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X))
10760 {
10761 ContactResult result = new ContactResult ();
10762 result.ConsumerID = sp.LocalId;
10763 result.Depth = 0;
10764 result.Normal = Vector3.Zero;
10765 result.Pos = posToCheck;
10766 results.Add(result);
10767 }
10768 });
10769 } 11831 }
10770 }
10771 11832
10772 int refcount = 0; 11833 results = (List<ContactResult>)physresults;
10773 foreach (ContactResult result in results)
10774 {
10775 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND)
10776 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0)
10777 continue;
10778 11834
10779 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID); 11835 // for now physics doesn't detect sitted avatars so do it outside physics
11836 if (checkAgents)
11837 {
11838 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11839 foreach (ContactResult r in agentHits)
11840 results.Add(r);
11841 }
10780 11842
10781 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) 11843 // bug: will not detect phantom unless they are physical
10782 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents 11844 // don't use ObjectIntersection because its also bad
10783 11845
10784 if (entity == null) 11846 }
11847 else
11848 {
11849 if (checkTerrain)
10785 { 11850 {
10786 list.Add(UUID.Zero); 11851 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11852 if (groundContact != null)
11853 results.Add((ContactResult)groundContact);
11854 }
10787 11855
10788 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11856 if (checkAgents)
10789 list.Add(0); 11857 {
11858 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11859 foreach (ContactResult r in agentHits)
11860 results.Add(r);
11861 }
10790 11862
10791 list.Add(result.Pos); 11863 if (checkPhysical || checkNonPhysical || detectPhantom)
11864 {
11865 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
11866 foreach (ContactResult r in objectHits)
11867 results.Add(r);
11868 }
11869 }
10792 11870
10793 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11871 results.Sort(delegate(ContactResult a, ContactResult b)
10794 list.Add(result.Normal); 11872 {
11873 return a.Depth.CompareTo(b.Depth);
11874 });
11875
11876 int values = 0;
11877 SceneObjectGroup thisgrp = m_host.ParentGroup;
10795 11878
10796 continue; //Can't find it, so add UUID.Zero 11879 foreach (ContactResult result in results)
10797 } 11880 {
11881 if (result.Depth > dist)
11882 continue;
10798 11883
10799 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity && 11884 // physics ray can return colisions with host prim
10800 ((ISceneChildEntity)intersection.obj).PhysActor == null) 11885 if (m_host.LocalId == result.ConsumerID)
10801 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects 11886 continue;
11887
11888 UUID itemID = UUID.Zero;
11889 int linkNum = 0;
10802 11890
10803 if (entity is SceneObjectPart) 11891 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
11892 // It's a prim!
11893 if (part != null)
10804 { 11894 {
10805 PhysicsActor pa = ((SceneObjectPart)entity).PhysActor; 11895 // dont detect members of same object ???
11896 if (part.ParentGroup == thisgrp)
11897 continue;
10806 11898
10807 if (pa != null && pa.IsPhysical) 11899 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10808 { 11900 itemID = part.ParentGroup.UUID;
10809 if (!checkPhysical)
10810 continue;
10811 }
10812 else 11901 else
10813 { 11902 itemID = part.UUID;
10814 if (!checkNonPhysical)
10815 continue;
10816 }
10817 }
10818 11903
10819 refcount++; 11904 linkNum = part.LinkNum;
10820 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11905 }
10821 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10822 else 11906 else
10823 list.Add(entity.UUID);
10824
10825 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10826 { 11907 {
10827 if (entity is SceneObjectPart) 11908 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10828 list.Add(((SceneObjectPart)entity).LinkNum); 11909 /// It it a boy? a girl?
10829 else 11910 if (sp != null)
10830 list.Add(0); 11911 itemID = sp.UUID;
10831 } 11912 }
10832 11913
10833 list.Add(result.Pos); 11914 list.Add(new LSL_String(itemID.ToString()));
11915 list.Add(new LSL_String(result.Pos.ToString()));
11916
11917 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
11918 list.Add(new LSL_Integer(linkNum));
10834 11919
10835 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11920 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10836 list.Add(result.Normal); 11921 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11922
11923 values++;
11924 if (values >= count)
11925 break;
10837 } 11926 }
10838 11927
10839 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11928 list.Add(new LSL_Integer(values));
10840 11929
10841 return list; 11930 return list;
10842 } 11931 }
@@ -10876,7 +11965,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10876 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 11965 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10877 if (!isAccount) return 0; 11966 if (!isAccount) return 0;
10878 if (estate.HasAccess(id)) return 1; 11967 if (estate.HasAccess(id)) return 1;
10879 if (estate.IsBanned(id)) 11968 if (estate.IsBanned(id, World.GetUserFlags(id)))
10880 estate.RemoveBan(id); 11969 estate.RemoveBan(id);
10881 estate.AddEstateUser(id); 11970 estate.AddEstateUser(id);
10882 break; 11971 break;
@@ -10895,14 +11984,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10895 break; 11984 break;
10896 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 11985 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10897 if (!isAccount) return 0; 11986 if (!isAccount) return 0;
10898 if (estate.IsBanned(id)) return 1; 11987 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10899 EstateBan ban = new EstateBan(); 11988 EstateBan ban = new EstateBan();
10900 ban.EstateID = estate.EstateID; 11989 ban.EstateID = estate.EstateID;
10901 ban.BannedUserID = id; 11990 ban.BannedUserID = id;
10902 estate.AddBan(ban); 11991 estate.AddBan(ban);
10903 break; 11992 break;
10904 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 11993 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10905 if (!isAccount || !estate.IsBanned(id)) return 0; 11994 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10906 estate.RemoveBan(id); 11995 estate.RemoveBan(id);
10907 break; 11996 break;
10908 default: return 0; 11997 default: return 0;
@@ -10931,7 +12020,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10931 return 16384; 12020 return 16384;
10932 } 12021 }
10933 12022
10934 public LSL_Integer llGetUsedMemory() 12023 public virtual LSL_Integer llGetUsedMemory()
10935 { 12024 {
10936 m_host.AddScriptLPS(1); 12025 m_host.AddScriptLPS(1);
10937 // The value returned for LSO scripts in SL 12026 // The value returned for LSO scripts in SL
@@ -10959,7 +12048,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10959 public void llSetSoundQueueing(int queue) 12048 public void llSetSoundQueueing(int queue)
10960 { 12049 {
10961 m_host.AddScriptLPS(1); 12050 m_host.AddScriptLPS(1);
10962 NotImplemented("llSetSoundQueueing");
10963 } 12051 }
10964 12052
10965 public void llCollisionSprite(string impact_sprite) 12053 public void llCollisionSprite(string impact_sprite)
@@ -10971,10 +12059,270 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10971 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12059 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10972 { 12060 {
10973 m_host.AddScriptLPS(1); 12061 m_host.AddScriptLPS(1);
10974 NotImplemented("llGodLikeRezObject"); 12062
12063 if (!World.Permissions.IsGod(m_host.OwnerID))
12064 NotImplemented("llGodLikeRezObject");
12065
12066 AssetBase rezAsset = World.AssetService.Get(inventory);
12067 if (rezAsset == null)
12068 {
12069 llSay(0, "Asset not found");
12070 return;
12071 }
12072
12073 SceneObjectGroup group = null;
12074
12075 try
12076 {
12077 string xmlData = Utils.BytesToString(rezAsset.Data);
12078 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12079 }
12080 catch
12081 {
12082 llSay(0, "Asset not found");
12083 return;
12084 }
12085
12086 if (group == null)
12087 {
12088 llSay(0, "Asset not found");
12089 return;
12090 }
12091
12092 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12093 group.RootPart.AttachOffset = group.AbsolutePosition;
12094
12095 group.ResetIDs();
12096
12097 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12098 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12099 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12100 group.ScheduleGroupForFullUpdate();
12101
12102 // objects rezzed with this method are die_at_edge by default.
12103 group.RootPart.SetDieAtEdge(true);
12104
12105 group.ResumeScripts();
12106
12107 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12108 "object_rez", new Object[] {
12109 new LSL_String(
12110 group.RootPart.UUID.ToString()) },
12111 new DetectParams[0]));
12112 }
12113
12114 public LSL_String llTransferLindenDollars(string destination, int amount)
12115 {
12116 UUID txn = UUID.Random();
12117
12118 Util.FireAndForget(delegate(object x)
12119 {
12120 int replycode = 0;
12121 string replydata = destination + "," + amount.ToString();
12122
12123 try
12124 {
12125 TaskInventoryItem item = m_item;
12126 if (item == null)
12127 {
12128 replydata = "SERVICE_ERROR";
12129 return;
12130 }
12131
12132 m_host.AddScriptLPS(1);
12133
12134 if (item.PermsGranter == UUID.Zero)
12135 {
12136 replydata = "MISSING_PERMISSION_DEBIT";
12137 return;
12138 }
12139
12140 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
12141 {
12142 replydata = "MISSING_PERMISSION_DEBIT";
12143 return;
12144 }
12145
12146 UUID toID = new UUID();
12147
12148 if (!UUID.TryParse(destination, out toID))
12149 {
12150 replydata = "INVALID_AGENT";
12151 return;
12152 }
12153
12154 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
12155
12156 if (money == null)
12157 {
12158 replydata = "TRANSFERS_DISABLED";
12159 return;
12160 }
12161
12162 bool result = money.ObjectGiveMoney(
12163 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
12164
12165 if (result)
12166 {
12167 replycode = 1;
12168 return;
12169 }
12170
12171 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
12172 }
12173 finally
12174 {
12175 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
12176 "transaction_result", new Object[] {
12177 new LSL_String(txn.ToString()),
12178 new LSL_Integer(replycode),
12179 new LSL_String(replydata) },
12180 new DetectParams[0]));
12181 }
12182 });
12183
12184 return txn.ToString();
10975 } 12185 }
10976 12186
10977 #endregion 12187 #endregion
12188
12189 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12190 {
12191 SceneObjectGroup group = m_host.ParentGroup;
12192
12193 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12194 return;
12195 if (group.IsAttachment)
12196 return;
12197
12198 if (frames.Data.Length > 0) // We are getting a new motion
12199 {
12200 if (group.RootPart.KeyframeMotion != null)
12201 group.RootPart.KeyframeMotion.Stop();
12202 group.RootPart.KeyframeMotion = null;
12203
12204 int idx = 0;
12205
12206 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12207 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12208
12209 while (idx < options.Data.Length)
12210 {
12211 int option = (int)options.GetLSLIntegerItem(idx++);
12212 int remain = options.Data.Length - idx;
12213
12214 switch (option)
12215 {
12216 case ScriptBaseClass.KFM_MODE:
12217 if (remain < 1)
12218 break;
12219 int modeval = (int)options.GetLSLIntegerItem(idx++);
12220 switch(modeval)
12221 {
12222 case ScriptBaseClass.KFM_FORWARD:
12223 mode = KeyframeMotion.PlayMode.Forward;
12224 break;
12225 case ScriptBaseClass.KFM_REVERSE:
12226 mode = KeyframeMotion.PlayMode.Reverse;
12227 break;
12228 case ScriptBaseClass.KFM_LOOP:
12229 mode = KeyframeMotion.PlayMode.Loop;
12230 break;
12231 case ScriptBaseClass.KFM_PING_PONG:
12232 mode = KeyframeMotion.PlayMode.PingPong;
12233 break;
12234 }
12235 break;
12236 case ScriptBaseClass.KFM_DATA:
12237 if (remain < 1)
12238 break;
12239 int dataval = (int)options.GetLSLIntegerItem(idx++);
12240 data = (KeyframeMotion.DataFormat)dataval;
12241 break;
12242 }
12243 }
12244
12245 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12246
12247 idx = 0;
12248
12249 int elemLength = 2;
12250 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12251 elemLength = 3;
12252
12253 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12254 while (idx < frames.Data.Length)
12255 {
12256 int remain = frames.Data.Length - idx;
12257
12258 if (remain < elemLength)
12259 break;
12260
12261 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12262 frame.Position = null;
12263 frame.Rotation = null;
12264
12265 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12266 {
12267 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12268 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12269 }
12270 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12271 {
12272 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12273 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12274 }
12275
12276 float tempf = (float)frames.GetLSLFloatItem(idx++);
12277 frame.TimeMS = (int)(tempf * 1000.0f);
12278
12279 keyframes.Add(frame);
12280 }
12281
12282 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12283 group.RootPart.KeyframeMotion.Start();
12284 }
12285 else
12286 {
12287 if (group.RootPart.KeyframeMotion == null)
12288 return;
12289
12290 if (options.Data.Length == 0)
12291 {
12292 group.RootPart.KeyframeMotion.Stop();
12293 return;
12294 }
12295
12296 int code = (int)options.GetLSLIntegerItem(0);
12297
12298 int idx = 0;
12299
12300 while (idx < options.Data.Length)
12301 {
12302 int option = (int)options.GetLSLIntegerItem(idx++);
12303 int remain = options.Data.Length - idx;
12304
12305 switch (option)
12306 {
12307 case ScriptBaseClass.KFM_COMMAND:
12308 int cmd = (int)options.GetLSLIntegerItem(idx++);
12309 switch (cmd)
12310 {
12311 case ScriptBaseClass.KFM_CMD_PLAY:
12312 group.RootPart.KeyframeMotion.Start();
12313 break;
12314 case ScriptBaseClass.KFM_CMD_STOP:
12315 group.RootPart.KeyframeMotion.Stop();
12316 break;
12317 case ScriptBaseClass.KFM_CMD_PAUSE:
12318 group.RootPart.KeyframeMotion.Pause();
12319 break;
12320 }
12321 break;
12322 }
12323 }
12324 }
12325 }
10978 } 12326 }
10979 12327
10980 public class NotecardCache 12328 public class NotecardCache
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 7ea8b7a..8237b60 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -138,6 +138,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
138 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow; 138 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow;
139 internal float m_ScriptDelayFactor = 1.0f; 139 internal float m_ScriptDelayFactor = 1.0f;
140 internal float m_ScriptDistanceFactor = 1.0f; 140 internal float m_ScriptDistanceFactor = 1.0f;
141 internal bool m_debuggerSafe = false;
141 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); 142 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
142 143
143 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 144 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
@@ -145,6 +146,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
145 m_ScriptEngine = ScriptEngine; 146 m_ScriptEngine = ScriptEngine;
146 m_host = host; 147 m_host = host;
147 m_item = item; 148 m_item = item;
149 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
148 150
149 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) 151 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
150 m_OSFunctionsEnabled = true; 152 m_OSFunctionsEnabled = true;
@@ -206,7 +208,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
206 208
207 internal void OSSLError(string msg) 209 internal void OSSLError(string msg)
208 { 210 {
209 throw new Exception("OSSL Runtime Error: " + msg); 211 if (m_debuggerSafe)
212 {
213 OSSLShoutError(msg);
214 }
215 else
216 {
217 throw new Exception("OSSL Runtime Error: " + msg);
218 }
210 } 219 }
211 220
212 /// <summary> 221 /// <summary>
@@ -920,18 +929,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
920 if (target != null) 929 if (target != null)
921 { 930 {
922 UUID animID=UUID.Zero; 931 UUID animID=UUID.Zero;
923 lock (m_host.TaskInventory) 932 m_host.TaskInventory.LockItemsForRead(true);
933 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
924 { 934 {
925 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 935 if (inv.Value.Name == animation)
926 { 936 {
927 if (inv.Value.Name == animation) 937 if (inv.Value.Type == (int)AssetType.Animation)
928 { 938 animID = inv.Value.AssetID;
929 if (inv.Value.Type == (int)AssetType.Animation) 939 continue;
930 animID = inv.Value.AssetID;
931 continue;
932 }
933 } 940 }
934 } 941 }
942 m_host.TaskInventory.LockItemsForRead(false);
935 if (animID == UUID.Zero) 943 if (animID == UUID.Zero)
936 target.Animator.AddAnimation(animation, m_host.UUID); 944 target.Animator.AddAnimation(animation, m_host.UUID);
937 else 945 else
@@ -972,6 +980,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
972 else 980 else
973 animID = UUID.Zero; 981 animID = UUID.Zero;
974 } 982 }
983 m_host.TaskInventory.LockItemsForRead(false);
975 984
976 if (animID == UUID.Zero) 985 if (animID == UUID.Zero)
977 target.Animator.RemoveAnimation(animation); 986 target.Animator.RemoveAnimation(animation);
@@ -1792,6 +1801,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1792 1801
1793 if (!UUID.TryParse(notecardNameOrUuid, out assetID)) 1802 if (!UUID.TryParse(notecardNameOrUuid, out assetID))
1794 { 1803 {
1804 m_host.TaskInventory.LockItemsForRead(true);
1795 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1805 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1796 { 1806 {
1797 if (item.Type == 7 && item.Name == notecardNameOrUuid) 1807 if (item.Type == 7 && item.Name == notecardNameOrUuid)
@@ -1799,6 +1809,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1799 assetID = item.AssetID; 1809 assetID = item.AssetID;
1800 } 1810 }
1801 } 1811 }
1812 m_host.TaskInventory.LockItemsForRead(false);
1802 } 1813 }
1803 1814
1804 if (assetID == UUID.Zero) 1815 if (assetID == UUID.Zero)
@@ -2266,7 +2277,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2266 CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); 2277 CheckThreatLevel(ThreatLevel.High, "osNpcCreate");
2267 m_host.AddScriptLPS(1); 2278 m_host.AddScriptLPS(1);
2268 2279
2269 return NpcCreate(firstname, lastname, position, notecard, false, false); 2280 return NpcCreate(firstname, lastname, position, notecard, true, false);
2270 } 2281 }
2271 2282
2272 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options) 2283 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options)
@@ -2277,24 +2288,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2277 return NpcCreate( 2288 return NpcCreate(
2278 firstname, lastname, position, notecard, 2289 firstname, lastname, position, notecard,
2279 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0, 2290 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0,
2280 (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) != 0); 2291 false);
2292// (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) != 0);
2281 } 2293 }
2282 2294
2283 private LSL_Key NpcCreate( 2295 private LSL_Key NpcCreate(
2284 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent) 2296 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent)
2285 { 2297 {
2298 if (!owned)
2299 OSSLError("Unowned NPCs are unsupported");
2300
2301 string groupTitle = String.Empty;
2302
2303 if (!World.Permissions.CanRezObject(1, m_host.OwnerID, new Vector3((float)position.x, (float)position.y, (float)position.z)))
2304 return new LSL_Key(UUID.Zero.ToString());
2305
2306 if (firstname != String.Empty || lastname != String.Empty)
2307 {
2308 if (firstname != "Shown outfit:")
2309 groupTitle = "- NPC -";
2310 }
2311
2286 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2312 INPCModule module = World.RequestModuleInterface<INPCModule>();
2287 if (module != null) 2313 if (module != null)
2288 { 2314 {
2289 AvatarAppearance appearance = null; 2315 AvatarAppearance appearance = null;
2290 2316
2291 UUID id; 2317// UUID id;
2292 if (UUID.TryParse(notecard, out id)) 2318// if (UUID.TryParse(notecard, out id))
2293 { 2319// {
2294 ScenePresence clonePresence = World.GetScenePresence(id); 2320// ScenePresence clonePresence = World.GetScenePresence(id);
2295 if (clonePresence != null) 2321// if (clonePresence != null)
2296 appearance = clonePresence.Appearance; 2322// appearance = clonePresence.Appearance;
2297 } 2323// }
2298 2324
2299 if (appearance == null) 2325 if (appearance == null)
2300 { 2326 {
@@ -2322,6 +2348,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2322 World, 2348 World,
2323 appearance); 2349 appearance);
2324 2350
2351 ScenePresence sp;
2352 if (World.TryGetScenePresence(x, out sp))
2353 {
2354 sp.Grouptitle = groupTitle;
2355 sp.SendAvatarDataToAllAgents();
2356 }
2325 return new LSL_Key(x.ToString()); 2357 return new LSL_Key(x.ToString());
2326 } 2358 }
2327 2359
@@ -2613,16 +2645,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2613 CheckThreatLevel(ThreatLevel.High, "osNpcRemove"); 2645 CheckThreatLevel(ThreatLevel.High, "osNpcRemove");
2614 m_host.AddScriptLPS(1); 2646 m_host.AddScriptLPS(1);
2615 2647
2616 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2648 ManualResetEvent ev = new ManualResetEvent(false);
2617 if (module != null)
2618 {
2619 UUID npcId = new UUID(npc.m_string);
2620 2649
2621 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2650 Util.FireAndForget(delegate(object x) {
2622 return; 2651 try
2652 {
2653 INPCModule module = World.RequestModuleInterface<INPCModule>();
2654 if (module != null)
2655 {
2656 UUID npcId = new UUID(npc.m_string);
2623 2657
2624 module.DeleteNPC(npcId, World); 2658 ILandObject l = World.LandChannel.GetLandObject(m_host.GroupPosition.X, m_host.GroupPosition.Y);
2625 } 2659 if (l == null || m_host.OwnerID != l.LandData.OwnerID)
2660 {
2661 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2662 return;
2663 }
2664
2665 module.DeleteNPC(npcId, World);
2666 }
2667 }
2668 finally
2669 {
2670 ev.Set();
2671 }
2672 });
2673 ev.WaitOne();
2626 } 2674 }
2627 2675
2628 public void osNpcPlayAnimation(LSL_Key npc, string animation) 2676 public void osNpcPlayAnimation(LSL_Key npc, string animation)
@@ -3156,4 +3204,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3156 ((LSL_Api)m_LSL_Api).DetachFromAvatar(); 3204 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3157 } 3205 }
3158 } 3206 }
3159} \ No newline at end of file 3207}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 3844753..19f3ce1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -319,7 +319,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
319 float dy; 319 float dy;
320 float dz; 320 float dz;
321 321
322 Quaternion q = SensePoint.GetWorldRotation(); 322// Quaternion q = SensePoint.RotationOffset;
323 Quaternion q = SensePoint.GetWorldRotation(); // non-attached prim Sensor *always* uses World rotation!
323 if (SensePoint.ParentGroup.IsAttachment) 324 if (SensePoint.ParentGroup.IsAttachment)
324 { 325 {
325 // In attachments, rotate the sensor cone with the 326 // In attachments, rotate the sensor cone with the
@@ -333,7 +334,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
333 // Position of a sensor in a child prim attached to an avatar 334 // Position of a sensor in a child prim attached to an avatar
334 // will be still wrong. 335 // will be still wrong.
335 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 336 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
336 q = avatar.Rotation * q; 337 fromRegionPos = avatar.AbsolutePosition;
338 q = avatar.Rotation;
337 } 339 }
338 340
339 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 341 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
@@ -463,7 +465,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
463 // Position of a sensor in a child prim attached to an avatar 465 // Position of a sensor in a child prim attached to an avatar
464 // will be still wrong. 466 // will be still wrong.
465 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 467 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
466 q = avatar.Rotation * q; 468 if (avatar == null)
469 return sensedEntities;
470 fromRegionPos = avatar.AbsolutePosition;
471 q = avatar.Rotation;
467 } 472 }
468 473
469 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 474 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
index bc63030..9ee6946 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
@@ -118,25 +118,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
118 if (Timers.Count == 0) 118 if (Timers.Count == 0)
119 return; 119 return;
120 120
121 Dictionary<string, TimerClass>.ValueCollection tvals;
121 lock (TimerListLock) 122 lock (TimerListLock)
122 { 123 {
123 // Go through all timers 124 // Go through all timers
124 Dictionary<string, TimerClass>.ValueCollection tvals = Timers.Values; 125 tvals = Timers.Values;
125 foreach (TimerClass ts in tvals) 126 }
127
128 foreach (TimerClass ts in tvals)
129 {
130 // Time has passed?
131 if (ts.next < DateTime.Now.Ticks)
126 { 132 {
127 // Time has passed? 133 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next);
128 if (ts.next < DateTime.Now.Ticks) 134 // Add it to queue
129 { 135 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
130 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next); 136 new EventParams("timer", new Object[0],
131 // Add it to queue 137 new DetectParams[0]));
132 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, 138 // set next interval
133 new EventParams("timer", new Object[0], 139
134 new DetectParams[0])); 140 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
135 // set next interval 141 ts.next = DateTime.Now.Ticks + ts.interval;
136
137 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
138 ts.next = DateTime.Now.Ticks + ts.interval;
139 }
140 } 142 }
141 } 143 }
142 } 144 }