aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared')
-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.cs3022
-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
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs46
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs71
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs26
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs51
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs21
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs86
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs39
18 files changed, 2727 insertions, 940 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 fb0fdc9..9595d48 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,48 @@ 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;
118
119 private Dictionary<string, string> MovementAnimationsForLSL =
120 new Dictionary<string, string> {
121 {"FLY", "Flying"},
122 {"FLYSLOW", "FlyingSlow"},
123 {"HOVER_UP", "Hovering Up"},
124 {"HOVER_DOWN", "Hovering Down"},
125 {"HOVER", "Hovering"},
126 {"LAND", "Landing"},
127 {"FALLDOWN", "Falling Down"},
128 {"PREJUMP", "PreJumping"},
129 {"JUMP", "Jumping"},
130 {"STANDUP", "Standing Up"},
131 {"SOFT_LAND", "Soft Landing"},
132 {"STAND", "Standing"},
133 {"CROUCHWALK", "CrouchWalking"},
134 {"RUN", "Running"},
135 {"WALK", "Walking"},
136 {"CROUCH", "Crouching"},
137 {"TURNLEFT", "Turning Left"},
138 {"TURNRIGHT", "Turning Right"}
139 };
109 140
110 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 141 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
111 { 142 {
143 m_ShoutSayTimer = new Timer(1000);
144 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
145 m_ShoutSayTimer.AutoReset = true;
146 m_ShoutSayTimer.Start();
147
112 m_ScriptEngine = ScriptEngine; 148 m_ScriptEngine = ScriptEngine;
113 m_host = host; 149 m_host = host;
114 m_item = item; 150 m_item = item;
151 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
115 152
116 LoadLimits(); // read script limits from config. 153 LoadLimits(); // read script limits from config.
117 154
@@ -171,6 +208,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
171 get { return m_ScriptEngine.World; } 208 get { return m_ScriptEngine.World; }
172 } 209 }
173 210
211 [DebuggerNonUserCode]
174 public void state(string newState) 212 public void state(string newState)
175 { 213 {
176 m_ScriptEngine.SetState(m_item.ItemID, newState); 214 m_ScriptEngine.SetState(m_item.ItemID, newState);
@@ -180,6 +218,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
180 /// Reset the named script. The script must be present 218 /// Reset the named script. The script must be present
181 /// in the same prim. 219 /// in the same prim.
182 /// </summary> 220 /// </summary>
221 [DebuggerNonUserCode]
183 public void llResetScript() 222 public void llResetScript()
184 { 223 {
185 m_host.AddScriptLPS(1); 224 m_host.AddScriptLPS(1);
@@ -236,9 +275,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
236 } 275 }
237 } 276 }
238 277
278 public List<ScenePresence> GetLinkAvatars(int linkType)
279 {
280 List<ScenePresence> ret = new List<ScenePresence>();
281 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
282 return ret;
283
284 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
285
286 switch (linkType)
287 {
288 case ScriptBaseClass.LINK_SET:
289 return avs;
290
291 case ScriptBaseClass.LINK_ROOT:
292 return ret;
293
294 case ScriptBaseClass.LINK_ALL_OTHERS:
295 return avs;
296
297 case ScriptBaseClass.LINK_ALL_CHILDREN:
298 return avs;
299
300 case ScriptBaseClass.LINK_THIS:
301 return ret;
302
303 default:
304 if (linkType < 0)
305 return ret;
306
307 int partCount = m_host.ParentGroup.GetPartCount();
308
309 if (linkType <= partCount)
310 {
311 return ret;
312 }
313 else
314 {
315 linkType = linkType - partCount;
316 if (linkType > avs.Count)
317 {
318 return ret;
319 }
320 else
321 {
322 ret.Add(avs[linkType-1]);
323 return ret;
324 }
325 }
326 }
327 }
328
239 public List<SceneObjectPart> GetLinkParts(int linkType) 329 public List<SceneObjectPart> GetLinkParts(int linkType)
240 { 330 {
241 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 331 List<SceneObjectPart> ret = new List<SceneObjectPart>();
332 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
333 return ret;
242 ret.Add(m_host); 334 ret.Add(m_host);
243 335
244 switch (linkType) 336 switch (linkType)
@@ -432,31 +524,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
432 524
433 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 525 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
434 526
435 /// <summary> 527 // Utility function for llRot2Euler
436 /// Convert an LSL rotation to a Euler vector. 528
437 /// </summary> 529 // normalize an angle between -PI and PI (-180 to +180 degrees)
438 /// <remarks> 530 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 { 531 {
446 m_host.AddScriptLPS(1); 532 if (angle > -Math.PI && angle < Math.PI)
533 return angle;
534
535 int numPis = (int)(Math.PI / angle);
536 double remainder = angle - Math.PI * numPis;
537 if (numPis % 2 == 1)
538 return Math.PI - angle;
539 return remainder;
540 }
447 541
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. 542 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. 543 {
450 if (m == 0.0) return new LSL_Vector(); 544 m_host.AddScriptLPS(1);
451 double x = Math.Atan2(-v.y, v.z); 545 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 546
459 return new LSL_Vector(x, y, z); 547 double sqw = q1.s*q1.s;
548 double sqx = q1.x*q1.x;
549 double sqy = q1.z*q1.z;
550 double sqz = q1.y*q1.y;
551 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
552 double test = q1.x*q1.z + q1.y*q1.s;
553 if (test > 0.4999*unit) { // singularity at north pole
554 eul.z = 2 * Math.Atan2(q1.x,q1.s);
555 eul.y = Math.PI/2;
556 eul.x = 0;
557 return eul;
558 }
559 if (test < -0.4999*unit) { // singularity at south pole
560 eul.z = -2 * Math.Atan2(q1.x,q1.s);
561 eul.y = -Math.PI/2;
562 eul.x = 0;
563 return eul;
564 }
565 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
566 eul.y = Math.Asin(2*test/unit);
567 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
568 return eul;
460 } 569 }
461 570
462 /* From wiki: 571 /* From wiki:
@@ -658,77 +767,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
658 { 767 {
659 //A and B should both be normalized 768 //A and B should both be normalized
660 m_host.AddScriptLPS(1); 769 m_host.AddScriptLPS(1);
661 LSL_Rotation rotBetween; 770 /* 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, 771 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
663 // continue calculation. 772
664 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 773 double dotProduct = LSL_Vector.Dot(a, b);
774 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
775 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
776 double angle = Math.Acos(dotProduct / magProduct);
777 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
778 double s = Math.Sin(angle / 2);
779
780 double x = axis.x * s;
781 double y = axis.y * s;
782 double z = axis.z * s;
783 double w = Math.Cos(angle / 2);
784
785 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
786 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
787
788 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
789 */
790
791 // This method mimics the 180 errors found in SL
792 // See www.euclideanspace.com... angleBetween
793 LSL_Vector vec_a = a;
794 LSL_Vector vec_b = b;
795
796 // Eliminate zero length
797 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
798 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
799 if (vec_a_mag < 0.00001 ||
800 vec_b_mag < 0.00001)
665 { 801 {
666 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 802 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
667 } 803 }
668 else 804
805 // Normalize
806 vec_a = llVecNorm(vec_a);
807 vec_b = llVecNorm(vec_b);
808
809 // Calculate axis and rotation angle
810 LSL_Vector axis = vec_a % vec_b;
811 LSL_Float cos_theta = vec_a * vec_b;
812
813 // Check if parallel
814 if (cos_theta > 0.99999)
669 { 815 {
670 a = LSL_Vector.Norm(a); 816 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
671 b = LSL_Vector.Norm(b); 817 }
672 double dotProduct = LSL_Vector.Dot(a, b); 818
673 // There are two degenerate cases possible. These are for vectors 180 or 819 // Check if anti-parallel
674 // 0 degrees apart. These have to be detected and handled individually. 820 else if (cos_theta < -0.99999)
675 // 821 {
676 // Check for vectors 180 degrees apart. 822 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. 823 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
678 if (dotProduct < -0.9999999f) 824 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
679 { 825 }
680 // First assume X axis is orthogonal to the vectors. 826 else // other rotation
681 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 827 {
682 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 828 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 829 axis = llVecNorm(axis);
684 // a rotation in an undesired direction. 830 double x, y, z, s, t;
685 if (LSL_Vector.Mag(orthoVector) > 0.0001) 831 s = Math.Cos(theta);
686 { 832 t = Math.Sin(theta);
687 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 833 x = axis.x * t;
688 } 834 y = axis.y * t;
689 // If the magnitude of the vector was near zero, then assume the X axis is not 835 z = axis.z * t;
690 // orthogonal and use the Z axis instead. 836 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 } 837 }
729 return rotBetween;
730 } 838 }
731 839
732 public void llWhisper(int channelID, string text) 840 public void llWhisper(int channelID, string text)
733 { 841 {
734 m_host.AddScriptLPS(1); 842 m_host.AddScriptLPS(1);
@@ -748,6 +856,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
748 { 856 {
749 m_host.AddScriptLPS(1); 857 m_host.AddScriptLPS(1);
750 858
859 if (channelID == 0)
860 m_SayShoutCount++;
861
862 if (m_SayShoutCount >= 11)
863 ScriptSleep(2000);
864
751 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 865 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
752 { 866 {
753 Console.WriteLine(text); 867 Console.WriteLine(text);
@@ -770,6 +884,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
770 { 884 {
771 m_host.AddScriptLPS(1); 885 m_host.AddScriptLPS(1);
772 886
887 if (channelID == 0)
888 m_SayShoutCount++;
889
890 if (m_SayShoutCount >= 11)
891 ScriptSleep(2000);
892
773 if (text.Length > 1023) 893 if (text.Length > 1023)
774 text = text.Substring(0, 1023); 894 text = text.Substring(0, 1023);
775 895
@@ -1072,10 +1192,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1072 return detectedParams.TouchUV; 1192 return detectedParams.TouchUV;
1073 } 1193 }
1074 1194
1195 [DebuggerNonUserCode]
1075 public virtual void llDie() 1196 public virtual void llDie()
1076 { 1197 {
1077 m_host.AddScriptLPS(1); 1198 m_host.AddScriptLPS(1);
1078 throw new SelfDeleteException(); 1199 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1079 } 1200 }
1080 1201
1081 public LSL_Float llGround(LSL_Vector offset) 1202 public LSL_Float llGround(LSL_Vector offset)
@@ -1148,6 +1269,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1148 1269
1149 public void llSetStatus(int status, int value) 1270 public void llSetStatus(int status, int value)
1150 { 1271 {
1272 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1273 return;
1151 m_host.AddScriptLPS(1); 1274 m_host.AddScriptLPS(1);
1152 1275
1153 int statusrotationaxis = 0; 1276 int statusrotationaxis = 0;
@@ -1171,6 +1294,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1171 if (!allow) 1294 if (!allow)
1172 return; 1295 return;
1173 1296
1297 if (m_host.ParentGroup.RootPart.PhysActor != null &&
1298 m_host.ParentGroup.RootPart.PhysActor.IsPhysical)
1299 return;
1300
1174 m_host.ScriptSetPhysicsStatus(true); 1301 m_host.ScriptSetPhysicsStatus(true);
1175 } 1302 }
1176 else 1303 else
@@ -1379,6 +1506,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1379 { 1506 {
1380 m_host.AddScriptLPS(1); 1507 m_host.AddScriptLPS(1);
1381 1508
1509 SetColor(m_host, color, face);
1510 }
1511
1512 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1513 {
1514 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1515 return;
1516
1517 Primitive.TextureEntry tex = part.Shape.Textures;
1518 Color4 texcolor;
1519 if (face >= 0 && face < GetNumberOfSides(part))
1520 {
1521 texcolor = tex.CreateFace((uint)face).RGBA;
1522 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1523 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1524 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1525 tex.FaceTextures[face].RGBA = texcolor;
1526 part.UpdateTextureEntry(tex.GetBytes());
1527 return;
1528 }
1529 else if (face == ScriptBaseClass.ALL_SIDES)
1530 {
1531 for (uint i = 0; i < GetNumberOfSides(part); i++)
1532 {
1533 if (tex.FaceTextures[i] != null)
1534 {
1535 texcolor = tex.FaceTextures[i].RGBA;
1536 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1537 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1538 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1539 tex.FaceTextures[i].RGBA = texcolor;
1540 }
1541 texcolor = tex.DefaultTexture.RGBA;
1542 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1543 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1544 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1545 tex.DefaultTexture.RGBA = texcolor;
1546 }
1547 part.UpdateTextureEntry(tex.GetBytes());
1548 return;
1549 }
1550
1382 if (face == ScriptBaseClass.ALL_SIDES) 1551 if (face == ScriptBaseClass.ALL_SIDES)
1383 face = SceneObjectPart.ALL_SIDES; 1552 face = SceneObjectPart.ALL_SIDES;
1384 1553
@@ -1387,6 +1556,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1387 1556
1388 public void SetTexGen(SceneObjectPart part, int face,int style) 1557 public void SetTexGen(SceneObjectPart part, int face,int style)
1389 { 1558 {
1559 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1560 return;
1561
1390 Primitive.TextureEntry tex = part.Shape.Textures; 1562 Primitive.TextureEntry tex = part.Shape.Textures;
1391 MappingType textype; 1563 MappingType textype;
1392 textype = MappingType.Default; 1564 textype = MappingType.Default;
@@ -1417,6 +1589,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1417 1589
1418 public void SetGlow(SceneObjectPart part, int face, float glow) 1590 public void SetGlow(SceneObjectPart part, int face, float glow)
1419 { 1591 {
1592 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1593 return;
1594
1420 Primitive.TextureEntry tex = part.Shape.Textures; 1595 Primitive.TextureEntry tex = part.Shape.Textures;
1421 if (face >= 0 && face < GetNumberOfSides(part)) 1596 if (face >= 0 && face < GetNumberOfSides(part))
1422 { 1597 {
@@ -1442,6 +1617,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1442 1617
1443 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1618 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1444 { 1619 {
1620 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1621 return;
1445 1622
1446 Shininess sval = new Shininess(); 1623 Shininess sval = new Shininess();
1447 1624
@@ -1492,6 +1669,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1492 1669
1493 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1670 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1494 { 1671 {
1672 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1673 return;
1674
1495 Primitive.TextureEntry tex = part.Shape.Textures; 1675 Primitive.TextureEntry tex = part.Shape.Textures;
1496 if (face >= 0 && face < GetNumberOfSides(part)) 1676 if (face >= 0 && face < GetNumberOfSides(part))
1497 { 1677 {
@@ -1552,13 +1732,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1552 m_host.AddScriptLPS(1); 1732 m_host.AddScriptLPS(1);
1553 1733
1554 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1734 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1555 1735 if (parts.Count > 0)
1556 foreach (SceneObjectPart part in parts) 1736 {
1557 SetAlpha(part, alpha, face); 1737 try
1738 {
1739 parts[0].ParentGroup.areUpdatesSuspended = true;
1740 foreach (SceneObjectPart part in parts)
1741 SetAlpha(part, alpha, face);
1742 }
1743 finally
1744 {
1745 parts[0].ParentGroup.areUpdatesSuspended = false;
1746 }
1747 }
1558 } 1748 }
1559 1749
1560 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1750 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1561 { 1751 {
1752 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1753 return;
1754
1562 Primitive.TextureEntry tex = part.Shape.Textures; 1755 Primitive.TextureEntry tex = part.Shape.Textures;
1563 Color4 texcolor; 1756 Color4 texcolor;
1564 if (face >= 0 && face < GetNumberOfSides(part)) 1757 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1611,7 +1804,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1611 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1804 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1612 float wind, float tension, LSL_Vector Force) 1805 float wind, float tension, LSL_Vector Force)
1613 { 1806 {
1614 if (part == null) 1807 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1615 return; 1808 return;
1616 1809
1617 if (flexi) 1810 if (flexi)
@@ -1645,7 +1838,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1645 /// <param name="falloff"></param> 1838 /// <param name="falloff"></param>
1646 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1839 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1647 { 1840 {
1648 if (part == null) 1841 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1649 return; 1842 return;
1650 1843
1651 if (light) 1844 if (light)
@@ -1724,15 +1917,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1724 m_host.AddScriptLPS(1); 1917 m_host.AddScriptLPS(1);
1725 1918
1726 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1919 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1727 1920 if (parts.Count > 0)
1728 foreach (SceneObjectPart part in parts) 1921 {
1729 SetTexture(part, texture, face); 1922 try
1730 1923 {
1924 parts[0].ParentGroup.areUpdatesSuspended = true;
1925 foreach (SceneObjectPart part in parts)
1926 SetTexture(part, texture, face);
1927 }
1928 finally
1929 {
1930 parts[0].ParentGroup.areUpdatesSuspended = false;
1931 }
1932 }
1731 ScriptSleep(200); 1933 ScriptSleep(200);
1732 } 1934 }
1733 1935
1734 protected void SetTexture(SceneObjectPart part, string texture, int face) 1936 protected void SetTexture(SceneObjectPart part, string texture, int face)
1735 { 1937 {
1938 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1939 return;
1940
1736 UUID textureID = new UUID(); 1941 UUID textureID = new UUID();
1737 1942
1738 textureID = InventoryKey(texture, (int)AssetType.Texture); 1943 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1777,6 +1982,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1777 1982
1778 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 1983 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1779 { 1984 {
1985 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1986 return;
1987
1780 Primitive.TextureEntry tex = part.Shape.Textures; 1988 Primitive.TextureEntry tex = part.Shape.Textures;
1781 if (face >= 0 && face < GetNumberOfSides(part)) 1989 if (face >= 0 && face < GetNumberOfSides(part))
1782 { 1990 {
@@ -1813,6 +2021,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1813 2021
1814 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2022 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1815 { 2023 {
2024 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2025 return;
2026
1816 Primitive.TextureEntry tex = part.Shape.Textures; 2027 Primitive.TextureEntry tex = part.Shape.Textures;
1817 if (face >= 0 && face < GetNumberOfSides(part)) 2028 if (face >= 0 && face < GetNumberOfSides(part))
1818 { 2029 {
@@ -1849,6 +2060,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1849 2060
1850 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2061 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1851 { 2062 {
2063 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2064 return;
2065
1852 Primitive.TextureEntry tex = part.Shape.Textures; 2066 Primitive.TextureEntry tex = part.Shape.Textures;
1853 if (face >= 0 && face < GetNumberOfSides(part)) 2067 if (face >= 0 && face < GetNumberOfSides(part))
1854 { 2068 {
@@ -1953,26 +2167,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1953 return real_vec; 2167 return real_vec;
1954 } 2168 }
1955 2169
2170 public LSL_Integer llSetRegionPos(LSL_Vector pos)
2171 {
2172 return new LSL_Integer(SetRegionPos(m_host, pos));
2173 }
2174
2175 protected int SetRegionPos(SceneObjectPart part, LSL_Vector targetPos)
2176 {
2177 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2178 return 0;
2179
2180 SceneObjectGroup grp = part.ParentGroup;
2181
2182 if (grp.IsAttachment)
2183 return 0;
2184
2185 if (grp.RootPart.PhysActor != null && grp.RootPart.PhysActor.IsPhysical)
2186 return 0;
2187
2188 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)
2189 return 0;
2190
2191 float constrainedX = (float)targetPos.x;
2192 float constrainedY = (float)targetPos.y;
2193
2194 if (constrainedX < 0.0f)
2195 constrainedX = 0.0f;
2196 if (constrainedY < 0.0f)
2197 constrainedY = 0.0f;
2198 if (constrainedX >= (float)Constants.RegionSize)
2199 constrainedX = (float)Constants.RegionSize - 0.1f;
2200 if (constrainedY >= (float)Constants.RegionSize)
2201 constrainedY = (float)Constants.RegionSize -0.1f;
2202
2203 float ground = World.GetGroundHeight(constrainedX, constrainedY);
2204
2205 if (targetPos.z < ground)
2206 targetPos.z = ground;
2207
2208 Vector3 dest = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z);
2209
2210 if (!World.Permissions.CanObjectEntry(grp.UUID, false, dest))
2211 return 0;
2212
2213 grp.UpdateGroupPosition(dest);
2214
2215 return 1;
2216 }
2217
1956 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2218 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1957 { 2219 {
1958 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2220 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2221 return;
2222
1959 LSL_Vector currentPos = GetPartLocalPos(part); 2223 LSL_Vector currentPos = GetPartLocalPos(part);
2224 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
1960 2225
1961 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
1962 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
1963 2226
1964 if (part.ParentGroup.RootPart == part) 2227 if (part.ParentGroup.RootPart == part)
1965 { 2228 {
1966 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
1967 targetPos.z = ground;
1968 SceneObjectGroup parent = part.ParentGroup; 2229 SceneObjectGroup parent = part.ParentGroup;
1969 LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); 2230 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)); 2231 if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest))
2232 return;
2233 Util.FireAndForget(delegate(object x) {
2234 parent.UpdateGroupPosition(dest);
2235 });
1971 } 2236 }
1972 else 2237 else
1973 { 2238 {
1974 LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); 2239 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; 2240 SceneObjectGroup parent = part.ParentGroup;
1977 parent.HasGroupChanged = true; 2241 parent.HasGroupChanged = true;
1978 parent.ScheduleGroupForTerseUpdate(); 2242 parent.ScheduleGroupForTerseUpdate();
@@ -2005,17 +2269,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2005 else 2269 else
2006 { 2270 {
2007 if (part.ParentGroup.IsAttachment) 2271 if (part.ParentGroup.IsAttachment)
2008 {
2009 pos = part.AttachedPos; 2272 pos = part.AttachedPos;
2010 }
2011 else 2273 else
2012 {
2013 pos = part.AbsolutePosition; 2274 pos = part.AbsolutePosition;
2014 }
2015 } 2275 }
2016 2276
2017// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2018
2019 return new LSL_Vector(pos.X, pos.Y, pos.Z); 2277 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2020 } 2278 }
2021 2279
@@ -2024,9 +2282,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2024 m_host.AddScriptLPS(1); 2282 m_host.AddScriptLPS(1);
2025 2283
2026 // try to let this work as in SL... 2284 // try to let this work as in SL...
2027 if (m_host.ParentID == 0) 2285 if (m_host.LinkNum < 2)
2028 { 2286 {
2029 // special case: If we are root, rotate complete SOG to new rotation 2287 // Special case: If we are root, rotate complete SOG to new
2288 // rotation.
2289 // We are root if the link number is 0 (single prim) or 1
2290 // (root prim). ParentID may be nonzero in attachments and
2291 // using it would cause attachments and HUDs to rotate
2292 // to the wrong positions.
2030 SetRot(m_host, Rot2Quaternion(rot)); 2293 SetRot(m_host, Rot2Quaternion(rot));
2031 } 2294 }
2032 else 2295 else
@@ -2051,6 +2314,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2051 2314
2052 protected void SetRot(SceneObjectPart part, Quaternion rot) 2315 protected void SetRot(SceneObjectPart part, Quaternion rot)
2053 { 2316 {
2317 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2318 return;
2319
2054 part.UpdateRotation(rot); 2320 part.UpdateRotation(rot);
2055 // Update rotation does not move the object in the physics scene if it's a linkset. 2321 // Update rotation does not move the object in the physics scene if it's a linkset.
2056 2322
@@ -2205,13 +2471,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2205 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2471 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2206 { 2472 {
2207 m_host.AddScriptLPS(1); 2473 m_host.AddScriptLPS(1);
2208 m_host.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); 2474 m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
2209 } 2475 }
2210 2476
2211 public void llSetTorque(LSL_Vector torque, int local) 2477 public void llSetTorque(LSL_Vector torque, int local)
2212 { 2478 {
2213 m_host.AddScriptLPS(1); 2479 m_host.AddScriptLPS(1);
2214 m_host.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); 2480 m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0);
2215 } 2481 }
2216 2482
2217 public LSL_Vector llGetTorque() 2483 public LSL_Vector llGetTorque()
@@ -2241,7 +2507,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2241 } 2507 }
2242 else 2508 else
2243 { 2509 {
2244 vel = m_host.Velocity; 2510 vel = m_host.ParentGroup.RootPart.Velocity;
2245 } 2511 }
2246 2512
2247 return new LSL_Vector(vel.X, vel.Y, vel.Z); 2513 return new LSL_Vector(vel.X, vel.Y, vel.Z);
@@ -2813,35 +3079,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2813 public void llLookAt(LSL_Vector target, double strength, double damping) 3079 public void llLookAt(LSL_Vector target, double strength, double damping)
2814 { 3080 {
2815 m_host.AddScriptLPS(1); 3081 m_host.AddScriptLPS(1);
2816 // Determine where we are looking from
2817 LSL_Vector from = llGetPos();
2818 3082
2819 // Work out the normalised vector from the source to the target 3083 // Get the normalized vector to the target
2820 LSL_Vector delta = llVecNorm(target - from); 3084 LSL_Vector d1 = llVecNorm(target - llGetPos());
2821 LSL_Vector angle = new LSL_Vector(0,0,0);
2822 3085
2823 // Calculate the yaw 3086 // Get the bearing (yaw)
2824 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3087 LSL_Vector a1 = new LSL_Vector(0,0,0);
2825 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3088 a1.z = llAtan2(d1.y, d1.x);
2826 3089
2827 // Calculate pitch 3090 // Get the elevation (pitch)
2828 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3091 LSL_Vector a2 = new LSL_Vector(0,0,0);
3092 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2829 3093
2830 // we need to convert from a vector describing 3094 LSL_Rotation r1 = llEuler2Rot(a1);
2831 // the angles of rotation in radians into rotation value 3095 LSL_Rotation r2 = llEuler2Rot(a2);
2832 LSL_Rotation rot = llEuler2Rot(angle); 3096 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 3097
2838 if (strength == 0 || pa == null || !pa.IsPhysical) 3098 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2839 { 3099 {
2840 llSetRot(rot); 3100 // Do nothing if either value is 0 (this has been checked in SL)
3101 if (strength <= 0.0 || damping <= 0.0)
3102 return;
3103
3104 llSetRot(r3 * r2 * r1);
2841 } 3105 }
2842 else 3106 else
2843 { 3107 {
2844 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3108 if (strength == 0)
3109 {
3110 llSetRot(r3 * r2 * r1);
3111 return;
3112 }
3113
3114 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2845 } 3115 }
2846 } 3116 }
2847 3117
@@ -2887,17 +3157,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2887 } 3157 }
2888 else 3158 else
2889 { 3159 {
2890 if (m_host.IsRoot) 3160 // new SL always returns object mass
2891 { 3161// if (m_host.IsRoot)
3162// {
2892 return m_host.ParentGroup.GetMass(); 3163 return m_host.ParentGroup.GetMass();
2893 } 3164// }
2894 else 3165// else
2895 { 3166// {
2896 return m_host.GetMass(); 3167// return m_host.GetMass();
2897 } 3168// }
2898 } 3169 }
2899 } 3170 }
2900 3171
3172
3173 public LSL_Float llGetMassMKS()
3174 {
3175 return 100f * llGetMass();
3176 }
3177
2901 public void llCollisionFilter(string name, string id, int accept) 3178 public void llCollisionFilter(string name, string id, int accept)
2902 { 3179 {
2903 m_host.AddScriptLPS(1); 3180 m_host.AddScriptLPS(1);
@@ -3005,9 +3282,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3005 { 3282 {
3006 m_host.AddScriptLPS(1); 3283 m_host.AddScriptLPS(1);
3007 3284
3008// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3009// return;
3010
3011 if (m_item.PermsGranter != m_host.OwnerID) 3285 if (m_item.PermsGranter != m_host.OwnerID)
3012 return; 3286 return;
3013 3287
@@ -3050,6 +3324,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3050 3324
3051 public void llInstantMessage(string user, string message) 3325 public void llInstantMessage(string user, string message)
3052 { 3326 {
3327 UUID result;
3328 if (!UUID.TryParse(user, out result))
3329 {
3330 ShoutError("An invalid key was passed to llInstantMessage");
3331 ScriptSleep(2000);
3332 return;
3333 }
3334
3335
3053 m_host.AddScriptLPS(1); 3336 m_host.AddScriptLPS(1);
3054 3337
3055 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3338 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3064,14 +3347,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3064 UUID friendTransactionID = UUID.Random(); 3347 UUID friendTransactionID = UUID.Random();
3065 3348
3066 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3349 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3067 3350
3068 GridInstantMessage msg = new GridInstantMessage(); 3351 GridInstantMessage msg = new GridInstantMessage();
3069 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3352 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3070 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3353 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3071 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3354 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); 3355// 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()); 3356// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3074 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3357// DateTime dt = DateTime.UtcNow;
3358//
3359// // Ticks from UtcNow, but make it look like local. Evil, huh?
3360// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3361//
3362// try
3363// {
3364// // Convert that to the PST timezone
3365// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3366// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3367// }
3368// catch
3369// {
3370// // No logging here, as it could be VERY spammy
3371// }
3372//
3373// // And make it look local again to fool the unix time util
3374// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3375
3376 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3377
3075 //if (client != null) 3378 //if (client != null)
3076 //{ 3379 //{
3077 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3380 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3085,12 +3388,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3085 msg.message = message.Substring(0, 1024); 3388 msg.message = message.Substring(0, 1024);
3086 else 3389 else
3087 msg.message = message; 3390 msg.message = message;
3088 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3391 msg.dialog = (byte)19; // MessageFromObject
3089 msg.fromGroup = false;// fromGroup; 3392 msg.fromGroup = false;// fromGroup;
3090 msg.offline = (byte)0; //offline; 3393 msg.offline = (byte)0; //offline;
3091 msg.ParentEstateID = 0; //ParentEstateID; 3394 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3092 msg.Position = new Vector3(m_host.AbsolutePosition); 3395 msg.Position = new Vector3(m_host.AbsolutePosition);
3093 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3396 msg.RegionID = World.RegionInfo.RegionID.Guid;
3094 msg.binaryBucket 3397 msg.binaryBucket
3095 = Util.StringToBytes256( 3398 = Util.StringToBytes256(
3096 "{0}/{1}/{2}/{3}", 3399 "{0}/{1}/{2}/{3}",
@@ -3118,7 +3421,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3118 } 3421 }
3119 3422
3120 emailModule.SendEmail(m_host.UUID, address, subject, message); 3423 emailModule.SendEmail(m_host.UUID, address, subject, message);
3121 llSleep(EMAIL_PAUSE_TIME); 3424 ScriptSleep(EMAIL_PAUSE_TIME * 1000);
3122 } 3425 }
3123 3426
3124 public void llGetNextEmail(string address, string subject) 3427 public void llGetNextEmail(string address, string subject)
@@ -3362,15 +3665,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3362 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3665 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3363 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3666 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3364 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3667 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3668 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3365 ScriptBaseClass.PERMISSION_ATTACH; 3669 ScriptBaseClass.PERMISSION_ATTACH;
3366 3670
3367 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3671 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3368 { 3672 {
3369 lock (m_host.TaskInventory) 3673 m_host.TaskInventory.LockItemsForWrite(true);
3370 { 3674 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3371 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3675 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3372 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3676 m_host.TaskInventory.LockItemsForWrite(false);
3373 }
3374 3677
3375 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3678 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3376 "run_time_permissions", new Object[] { 3679 "run_time_permissions", new Object[] {
@@ -3380,28 +3683,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3380 return; 3683 return;
3381 } 3684 }
3382 } 3685 }
3383 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3686 else
3384 { 3687 {
3385 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3688 bool sitting = false;
3386 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3689 if (m_host.SitTargetAvatar == agentID)
3387 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3690 {
3388 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3691 sitting = true;
3389 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3692 }
3693 else
3694 {
3695 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3696 {
3697 if (p.SitTargetAvatar == agentID)
3698 sitting = true;
3699 }
3700 }
3390 3701
3391 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3702 if (sitting)
3392 { 3703 {
3393 lock (m_host.TaskInventory) 3704 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3705 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3706 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3707 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3708 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3709
3710 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3394 { 3711 {
3712 m_host.TaskInventory.LockItemsForWrite(true);
3395 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3713 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3396 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3714 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3397 } 3715 m_host.TaskInventory.LockItemsForWrite(false);
3398 3716
3399 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3717 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3400 "run_time_permissions", new Object[] { 3718 "run_time_permissions", new Object[] {
3401 new LSL_Integer(perm) }, 3719 new LSL_Integer(perm) },
3402 new DetectParams[0])); 3720 new DetectParams[0]));
3403 3721
3404 return; 3722 return;
3723 }
3405 } 3724 }
3406 } 3725 }
3407 3726
@@ -3438,11 +3757,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3438 3757
3439 if (!m_waitingForScriptAnswer) 3758 if (!m_waitingForScriptAnswer)
3440 { 3759 {
3441 lock (m_host.TaskInventory) 3760 m_host.TaskInventory.LockItemsForWrite(true);
3442 { 3761 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3443 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3762 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3444 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 3763 m_host.TaskInventory.LockItemsForWrite(false);
3445 }
3446 3764
3447 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3765 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3448 m_waitingForScriptAnswer=true; 3766 m_waitingForScriptAnswer=true;
@@ -3471,14 +3789,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3471 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3789 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3472 llReleaseControls(); 3790 llReleaseControls();
3473 3791
3474 lock (m_host.TaskInventory) 3792 m_host.TaskInventory.LockItemsForWrite(true);
3475 { 3793 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3476 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 3794 m_host.TaskInventory.LockItemsForWrite(false);
3477 } 3795
3478 3796 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3479 m_ScriptEngine.PostScriptEvent( 3797 "run_time_permissions", new Object[] {
3480 m_item.ItemID, 3798 new LSL_Integer(answer) },
3481 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); 3799 new DetectParams[0]));
3482 } 3800 }
3483 3801
3484 public LSL_String llGetPermissionsKey() 3802 public LSL_String llGetPermissionsKey()
@@ -3517,14 +3835,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3517 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3835 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3518 { 3836 {
3519 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3837 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3520 3838 if (parts.Count > 0)
3521 foreach (SceneObjectPart part in parts) 3839 {
3522 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3840 try
3841 {
3842 parts[0].ParentGroup.areUpdatesSuspended = true;
3843 foreach (SceneObjectPart part in parts)
3844 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3845 }
3846 finally
3847 {
3848 parts[0].ParentGroup.areUpdatesSuspended = false;
3849 }
3850 }
3523 } 3851 }
3524 3852
3525 public void llCreateLink(string target, int parent) 3853 public void llCreateLink(string target, int parent)
3526 { 3854 {
3527 m_host.AddScriptLPS(1); 3855 m_host.AddScriptLPS(1);
3856
3528 UUID targetID; 3857 UUID targetID;
3529 3858
3530 if (!UUID.TryParse(target, out targetID)) 3859 if (!UUID.TryParse(target, out targetID))
@@ -3630,10 +3959,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3630 // Restructuring Multiple Prims. 3959 // Restructuring Multiple Prims.
3631 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 3960 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3632 parts.Remove(parentPrim.RootPart); 3961 parts.Remove(parentPrim.RootPart);
3633 foreach (SceneObjectPart part in parts) 3962 if (parts.Count > 0)
3634 { 3963 {
3635 parentPrim.DelinkFromGroup(part.LocalId, true); 3964 try
3965 {
3966 parts[0].ParentGroup.areUpdatesSuspended = true;
3967 foreach (SceneObjectPart part in parts)
3968 {
3969 parentPrim.DelinkFromGroup(part.LocalId, true);
3970 }
3971 }
3972 finally
3973 {
3974 parts[0].ParentGroup.areUpdatesSuspended = false;
3975 }
3636 } 3976 }
3977
3637 parentPrim.HasGroupChanged = true; 3978 parentPrim.HasGroupChanged = true;
3638 parentPrim.ScheduleGroupForFullUpdate(); 3979 parentPrim.ScheduleGroupForFullUpdate();
3639 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3980 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3642,12 +3983,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3642 { 3983 {
3643 SceneObjectPart newRoot = parts[0]; 3984 SceneObjectPart newRoot = parts[0];
3644 parts.Remove(newRoot); 3985 parts.Remove(newRoot);
3645 foreach (SceneObjectPart part in parts) 3986
3987 try
3646 { 3988 {
3647 // Required for linking 3989 parts[0].ParentGroup.areUpdatesSuspended = true;
3648 part.ClearUpdateSchedule(); 3990 foreach (SceneObjectPart part in parts)
3649 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 3991 {
3992 part.ClearUpdateSchedule();
3993 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3994 }
3650 } 3995 }
3996 finally
3997 {
3998 parts[0].ParentGroup.areUpdatesSuspended = false;
3999 }
4000
4001
3651 newRoot.ParentGroup.HasGroupChanged = true; 4002 newRoot.ParentGroup.HasGroupChanged = true;
3652 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4003 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3653 } 4004 }
@@ -3667,6 +4018,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3667 public void llBreakAllLinks() 4018 public void llBreakAllLinks()
3668 { 4019 {
3669 m_host.AddScriptLPS(1); 4020 m_host.AddScriptLPS(1);
4021
4022 TaskInventoryItem item = m_item;
4023
4024 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4025 && !m_automaticLinkPermission)
4026 {
4027 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4028 return;
4029 }
4030
3670 SceneObjectGroup parentPrim = m_host.ParentGroup; 4031 SceneObjectGroup parentPrim = m_host.ParentGroup;
3671 if (parentPrim.AttachmentPoint != 0) 4032 if (parentPrim.AttachmentPoint != 0)
3672 return; // Fail silently if attached 4033 return; // Fail silently if attached
@@ -3686,25 +4047,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3686 public LSL_String llGetLinkKey(int linknum) 4047 public LSL_String llGetLinkKey(int linknum)
3687 { 4048 {
3688 m_host.AddScriptLPS(1); 4049 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); 4050 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3709 if (part != null) 4051 if (part != null)
3710 { 4052 {
@@ -3712,6 +4054,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3712 } 4054 }
3713 else 4055 else
3714 { 4056 {
4057 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4058 {
4059 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4060
4061 if (linknum < 0)
4062 return UUID.Zero.ToString();
4063
4064 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4065 if (avatars.Count > linknum)
4066 {
4067 return avatars[linknum].UUID.ToString();
4068 }
4069 }
3715 return UUID.Zero.ToString(); 4070 return UUID.Zero.ToString();
3716 } 4071 }
3717 } 4072 }
@@ -3811,17 +4166,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3811 m_host.AddScriptLPS(1); 4166 m_host.AddScriptLPS(1);
3812 int count = 0; 4167 int count = 0;
3813 4168
3814 lock (m_host.TaskInventory) 4169 m_host.TaskInventory.LockItemsForRead(true);
4170 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3815 { 4171 {
3816 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4172 if (inv.Value.Type == type || type == -1)
3817 { 4173 {
3818 if (inv.Value.Type == type || type == -1) 4174 count = count + 1;
3819 {
3820 count = count + 1;
3821 }
3822 } 4175 }
3823 } 4176 }
3824 4177
4178 m_host.TaskInventory.LockItemsForRead(false);
3825 return count; 4179 return count;
3826 } 4180 }
3827 4181
@@ -3830,16 +4184,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3830 m_host.AddScriptLPS(1); 4184 m_host.AddScriptLPS(1);
3831 ArrayList keys = new ArrayList(); 4185 ArrayList keys = new ArrayList();
3832 4186
3833 lock (m_host.TaskInventory) 4187 m_host.TaskInventory.LockItemsForRead(true);
4188 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3834 { 4189 {
3835 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4190 if (inv.Value.Type == type || type == -1)
3836 { 4191 {
3837 if (inv.Value.Type == type || type == -1) 4192 keys.Add(inv.Value.Name);
3838 {
3839 keys.Add(inv.Value.Name);
3840 }
3841 } 4193 }
3842 } 4194 }
4195 m_host.TaskInventory.LockItemsForRead(false);
3843 4196
3844 if (keys.Count == 0) 4197 if (keys.Count == 0)
3845 { 4198 {
@@ -3876,25 +4229,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3876 } 4229 }
3877 4230
3878 // move the first object found with this inventory name 4231 // move the first object found with this inventory name
3879 lock (m_host.TaskInventory) 4232 m_host.TaskInventory.LockItemsForRead(true);
4233 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3880 { 4234 {
3881 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4235 if (inv.Value.Name == inventory)
3882 { 4236 {
3883 if (inv.Value.Name == inventory) 4237 found = true;
3884 { 4238 objId = inv.Key;
3885 found = true; 4239 assetType = inv.Value.Type;
3886 objId = inv.Key; 4240 objName = inv.Value.Name;
3887 assetType = inv.Value.Type; 4241 break;
3888 objName = inv.Value.Name;
3889 break;
3890 }
3891 } 4242 }
3892 } 4243 }
4244 m_host.TaskInventory.LockItemsForRead(false);
3893 4245
3894 if (!found) 4246 if (!found)
3895 { 4247 {
3896 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4248 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)); 4249 return;
4250// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3898 } 4251 }
3899 4252
3900 // check if destination is an object 4253 // check if destination is an object
@@ -3920,48 +4273,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3920 return; 4273 return;
3921 } 4274 }
3922 } 4275 }
4276
3923 // destination is an avatar 4277 // destination is an avatar
3924 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4278 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3925 4279
3926 if (agentItem == null) 4280 if (agentItem == null)
3927 return; 4281 return;
3928 4282
3929 byte[] bucket = new byte[17]; 4283 byte[] bucket = new byte[1];
3930 bucket[0] = (byte)assetType; 4284 bucket[0] = (byte)assetType;
3931 byte[] objBytes = agentItem.ID.GetBytes(); 4285 //byte[] objBytes = agentItem.ID.GetBytes();
3932 Array.Copy(objBytes, 0, bucket, 1, 16); 4286 //Array.Copy(objBytes, 0, bucket, 1, 16);
3933 4287
3934 GridInstantMessage msg = new GridInstantMessage(World, 4288 GridInstantMessage msg = new GridInstantMessage(World,
3935 m_host.UUID, m_host.Name+", an object owned by "+ 4289 m_host.OwnerID, m_host.Name, destId,
3936 resolveName(m_host.OwnerID)+",", destId,
3937 (byte)InstantMessageDialog.TaskInventoryOffered, 4290 (byte)InstantMessageDialog.TaskInventoryOffered,
3938 false, objName+"\n"+m_host.Name+" is located at "+ 4291 false, objName+". "+m_host.Name+" is located at "+
3939 World.RegionInfo.RegionName+" "+ 4292 World.RegionInfo.RegionName+" "+
3940 m_host.AbsolutePosition.ToString(), 4293 m_host.AbsolutePosition.ToString(),
3941 agentItem.ID, true, m_host.AbsolutePosition, 4294 agentItem.ID, true, m_host.AbsolutePosition,
3942 bucket); 4295 bucket);
3943 if (m_TransferModule != null) 4296
3944 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4297 ScenePresence sp;
4298
4299 if (World.TryGetScenePresence(destId, out sp))
4300 {
4301 sp.ControllingClient.SendInstantMessage(msg);
4302 }
4303 else
4304 {
4305 if (m_TransferModule != null)
4306 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4307 }
4308
4309 //This delay should only occur when giving inventory to avatars.
3945 ScriptSleep(3000); 4310 ScriptSleep(3000);
3946 } 4311 }
3947 } 4312 }
3948 4313
4314 [DebuggerNonUserCode]
3949 public void llRemoveInventory(string name) 4315 public void llRemoveInventory(string name)
3950 { 4316 {
3951 m_host.AddScriptLPS(1); 4317 m_host.AddScriptLPS(1);
3952 4318
3953 lock (m_host.TaskInventory) 4319 List<TaskInventoryItem> inv;
4320 try
3954 { 4321 {
3955 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4322 m_host.TaskInventory.LockItemsForRead(true);
4323 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4324 }
4325 finally
4326 {
4327 m_host.TaskInventory.LockItemsForRead(false);
4328 }
4329 foreach (TaskInventoryItem item in inv)
4330 {
4331 if (item.Name == name)
3956 { 4332 {
3957 if (item.Name == name) 4333 if (item.ItemID == m_item.ItemID)
3958 { 4334 throw new ScriptDeleteException();
3959 if (item.ItemID == m_item.ItemID) 4335 else
3960 throw new ScriptDeleteException(); 4336 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3961 else 4337 return;
3962 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3963 return;
3964 }
3965 } 4338 }
3966 } 4339 }
3967 } 4340 }
@@ -3996,115 +4369,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3996 { 4369 {
3997 m_host.AddScriptLPS(1); 4370 m_host.AddScriptLPS(1);
3998 4371
3999 UUID uuid = (UUID)id; 4372 UUID uuid;
4000 PresenceInfo pinfo = null; 4373 if (UUID.TryParse(id, out uuid))
4001 UserAccount account;
4002
4003 UserInfoCacheEntry ce;
4004 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4005 { 4374 {
4006 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4375 PresenceInfo pinfo = null;
4007 if (account == null) 4376 UserAccount account;
4377
4378 UserInfoCacheEntry ce;
4379 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4008 { 4380 {
4009 m_userInfoCache[uuid] = null; // Cache negative 4381 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4010 return UUID.Zero.ToString(); 4382 if (account == null)
4011 } 4383 {
4384 m_userInfoCache[uuid] = null; // Cache negative
4385 return UUID.Zero.ToString();
4386 }
4012 4387
4013 4388
4014 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4389 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4015 if (pinfos != null && pinfos.Length > 0) 4390 if (pinfos != null && pinfos.Length > 0)
4016 {
4017 foreach (PresenceInfo p in pinfos)
4018 { 4391 {
4019 if (p.RegionID != UUID.Zero) 4392 foreach (PresenceInfo p in pinfos)
4020 { 4393 {
4021 pinfo = p; 4394 if (p.RegionID != UUID.Zero)
4395 {
4396 pinfo = p;
4397 }
4022 } 4398 }
4023 } 4399 }
4024 }
4025 4400
4026 ce = new UserInfoCacheEntry(); 4401 ce = new UserInfoCacheEntry();
4027 ce.time = Util.EnvironmentTickCount(); 4402 ce.time = Util.EnvironmentTickCount();
4028 ce.account = account; 4403 ce.account = account;
4029 ce.pinfo = pinfo; 4404 ce.pinfo = pinfo;
4030 } 4405 m_userInfoCache[uuid] = ce;
4031 else 4406 }
4032 { 4407 else
4033 if (ce == null) 4408 {
4034 return UUID.Zero.ToString(); 4409 if (ce == null)
4410 return UUID.Zero.ToString();
4035 4411
4036 account = ce.account; 4412 account = ce.account;
4037 pinfo = ce.pinfo; 4413 pinfo = ce.pinfo;
4038 } 4414 }
4039 4415
4040 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4416 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 { 4417 {
4045 foreach (PresenceInfo p in pinfos) 4418 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4419 if (pinfos != null && pinfos.Length > 0)
4046 { 4420 {
4047 if (p.RegionID != UUID.Zero) 4421 foreach (PresenceInfo p in pinfos)
4048 { 4422 {
4049 pinfo = p; 4423 if (p.RegionID != UUID.Zero)
4424 {
4425 pinfo = p;
4426 }
4050 } 4427 }
4051 } 4428 }
4052 } 4429 else
4053 else 4430 pinfo = null;
4054 pinfo = null;
4055 4431
4056 ce.time = Util.EnvironmentTickCount(); 4432 ce.time = Util.EnvironmentTickCount();
4057 ce.pinfo = pinfo; 4433 ce.pinfo = pinfo;
4058 } 4434 }
4059 4435
4060 string reply = String.Empty; 4436 string reply = String.Empty;
4061 4437
4062 switch (data) 4438 switch (data)
4063 { 4439 {
4064 case 1: // DATA_ONLINE (0|1) 4440 case 1: // DATA_ONLINE (0|1)
4065 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4441 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4066 reply = "1"; 4442 reply = "1";
4067 else 4443 else
4068 reply = "0"; 4444 reply = "0";
4069 break; 4445 break;
4070 case 2: // DATA_NAME (First Last) 4446 case 2: // DATA_NAME (First Last)
4071 reply = account.FirstName + " " + account.LastName; 4447 reply = account.FirstName + " " + account.LastName;
4072 break; 4448 break;
4073 case 3: // DATA_BORN (YYYY-MM-DD) 4449 case 3: // DATA_BORN (YYYY-MM-DD)
4074 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4450 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4075 born = born.AddSeconds(account.Created); 4451 born = born.AddSeconds(account.Created);
4076 reply = born.ToString("yyyy-MM-dd"); 4452 reply = born.ToString("yyyy-MM-dd");
4077 break; 4453 break;
4078 case 4: // DATA_RATING (0,0,0,0,0,0) 4454 case 4: // DATA_RATING (0,0,0,0,0,0)
4079 reply = "0,0,0,0,0,0"; 4455 reply = "0,0,0,0,0,0";
4080 break; 4456 break;
4081 case 7: // DATA_USERLEVEL (integer) 4457 case 8: // DATA_PAYINFO (0|1|2|3)
4082 reply = account.UserLevel.ToString(); 4458 reply = "0";
4083 break; 4459 break;
4084 case 8: // DATA_PAYINFO (0|1|2|3) 4460 default:
4085 reply = "0"; 4461 return UUID.Zero.ToString(); // Raise no event
4086 break; 4462 }
4087 default:
4088 return UUID.Zero.ToString(); // Raise no event
4089 }
4090 4463
4091 UUID rq = UUID.Random(); 4464 UUID rq = UUID.Random();
4092 4465
4093 UUID tid = AsyncCommands. 4466 UUID tid = AsyncCommands.
4094 DataserverPlugin.RegisterRequest(m_host.LocalId, 4467 DataserverPlugin.RegisterRequest(m_host.LocalId,
4095 m_item.ItemID, rq.ToString()); 4468 m_item.ItemID, rq.ToString());
4096 4469
4097 AsyncCommands. 4470 AsyncCommands.
4098 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4471 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4099 4472
4100 ScriptSleep(100); 4473 ScriptSleep(100);
4101 return tid.ToString(); 4474 return tid.ToString();
4475 }
4476 else
4477 {
4478 ShoutError("Invalid UUID passed to llRequestAgentData.");
4479 }
4480 return "";
4102 } 4481 }
4103 4482
4104 public LSL_String llRequestInventoryData(string name) 4483 public LSL_String llRequestInventoryData(string name)
4105 { 4484 {
4106 m_host.AddScriptLPS(1); 4485 m_host.AddScriptLPS(1);
4107 4486
4487 //Clone is thread safe
4108 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4488 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4109 4489
4110 foreach (TaskInventoryItem item in itemDictionary.Values) 4490 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4156,19 +4536,64 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4156 if (UUID.TryParse(agent, out agentId)) 4536 if (UUID.TryParse(agent, out agentId))
4157 { 4537 {
4158 ScenePresence presence = World.GetScenePresence(agentId); 4538 ScenePresence presence = World.GetScenePresence(agentId);
4159 if (presence != null) 4539 if (presence != null && presence.PresenceType != PresenceType.Npc)
4160 { 4540 {
4541 // agent must not be a god
4542 if (presence.UserLevel >= 200) return;
4543
4161 // agent must be over the owners land 4544 // agent must be over the owners land
4162 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4545 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4163 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4546 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4164 { 4547 {
4165 World.TeleportClientHome(agentId, presence.ControllingClient); 4548 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4549 {
4550 // They can't be teleported home for some reason
4551 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4552 if (regionInfo != null)
4553 {
4554 World.RequestTeleportLocation(
4555 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4556 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4557 }
4558 }
4166 } 4559 }
4167 } 4560 }
4168 } 4561 }
4169 ScriptSleep(5000); 4562 ScriptSleep(5000);
4170 } 4563 }
4171 4564
4565 public void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt)
4566 {
4567 m_host.AddScriptLPS(1);
4568 UUID agentId = new UUID();
4569 if (UUID.TryParse(agent, out agentId))
4570 {
4571 ScenePresence presence = World.GetScenePresence(agentId);
4572 if (presence != null && presence.PresenceType != PresenceType.Npc)
4573 {
4574 // agent must not be a god
4575 if (presence.GodLevel >= 200) return;
4576
4577 if (simname == String.Empty)
4578 simname = World.RegionInfo.RegionName;
4579
4580 // agent must be over the owners land
4581 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4582 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4583 {
4584 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);
4585 }
4586 else // or must be wearing the prim
4587 {
4588 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4589 {
4590 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);
4591 }
4592 }
4593 }
4594 }
4595 }
4596
4172 public void llTextBox(string agent, string message, int chatChannel) 4597 public void llTextBox(string agent, string message, int chatChannel)
4173 { 4598 {
4174 IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); 4599 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
@@ -4180,7 +4605,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4180 UUID av = new UUID(); 4605 UUID av = new UUID();
4181 if (!UUID.TryParse(agent,out av)) 4606 if (!UUID.TryParse(agent,out av))
4182 { 4607 {
4183 LSLError("First parameter to llDialog needs to be a key"); 4608 //LSLError("First parameter to llDialog needs to be a key");
4184 return; 4609 return;
4185 } 4610 }
4186 4611
@@ -4212,25 +4637,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4212 public void llCollisionSound(string impact_sound, double impact_volume) 4637 public void llCollisionSound(string impact_sound, double impact_volume)
4213 { 4638 {
4214 m_host.AddScriptLPS(1); 4639 m_host.AddScriptLPS(1);
4215 4640
4641 if(impact_sound == "")
4642 {
4643 m_host.CollisionSoundVolume = (float)impact_volume;
4644 m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
4645 return;
4646 }
4216 // TODO: Parameter check logic required. 4647 // TODO: Parameter check logic required.
4217 UUID soundId = UUID.Zero; 4648 UUID soundId = UUID.Zero;
4218 if (!UUID.TryParse(impact_sound, out soundId)) 4649 if (!UUID.TryParse(impact_sound, out soundId))
4219 { 4650 {
4220 lock (m_host.TaskInventory) 4651 m_host.TaskInventory.LockItemsForRead(true);
4652 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4221 { 4653 {
4222 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4654 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4223 { 4655 {
4224 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4656 soundId = item.AssetID;
4225 { 4657 break;
4226 soundId = item.AssetID;
4227 break;
4228 }
4229 } 4658 }
4230 } 4659 }
4660 m_host.TaskInventory.LockItemsForRead(false);
4231 } 4661 }
4232 m_host.CollisionSound = soundId;
4233 m_host.CollisionSoundVolume = (float)impact_volume; 4662 m_host.CollisionSoundVolume = (float)impact_volume;
4663 m_host.CollisionSound = soundId;
4234 } 4664 }
4235 4665
4236 public LSL_String llGetAnimation(string id) 4666 public LSL_String llGetAnimation(string id)
@@ -4244,14 +4674,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4244 4674
4245 if (m_host.RegionHandle == presence.RegionHandle) 4675 if (m_host.RegionHandle == presence.RegionHandle)
4246 { 4676 {
4247 Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames;
4248
4249 if (presence != null) 4677 if (presence != null)
4250 { 4678 {
4251 AnimationSet currentAnims = presence.Animator.Animations; 4679 if (presence.SitGround)
4252 string currentAnimationState = String.Empty; 4680 return "Sitting on Ground";
4253 if (animationstateNames.TryGetValue(currentAnims.DefaultAnimation.AnimID, out currentAnimationState)) 4681 if (presence.ParentID != 0 || presence.ParentUUID != UUID.Zero)
4254 return currentAnimationState; 4682 return "Sitting";
4683
4684 string movementAnimation = presence.Animator.CurrentMovementAnimation;
4685 string lslMovementAnimation;
4686
4687 if (MovementAnimationsForLSL.TryGetValue(movementAnimation, out lslMovementAnimation))
4688 return lslMovementAnimation;
4255 } 4689 }
4256 } 4690 }
4257 4691
@@ -4267,6 +4701,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4267 UUID partItemID; 4701 UUID partItemID;
4268 foreach (SceneObjectPart part in parts) 4702 foreach (SceneObjectPart part in parts)
4269 { 4703 {
4704 //Clone is thread safe
4270 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4705 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4271 4706
4272 foreach (TaskInventoryItem item in itemsDictionary.Values) 4707 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4400,7 +4835,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4400 { 4835 {
4401 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4836 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4402 float distance_term = distance * distance * distance; // Script Energy 4837 float distance_term = distance * distance * distance; // Script Energy
4403 float pusher_mass = m_host.GetMass(); 4838 // use total object mass and not part
4839 float pusher_mass = m_host.ParentGroup.GetMass();
4404 4840
4405 float PUSH_ATTENUATION_DISTANCE = 17f; 4841 float PUSH_ATTENUATION_DISTANCE = 17f;
4406 float PUSH_ATTENUATION_SCALE = 5f; 4842 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4639,23 +5075,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4639 { 5075 {
4640 m_host.AddScriptLPS(1); 5076 m_host.AddScriptLPS(1);
4641 5077
4642 lock (m_host.TaskInventory) 5078 m_host.TaskInventory.LockItemsForRead(true);
5079 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4643 { 5080 {
4644 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5081 if (inv.Value.Name == name)
4645 { 5082 {
4646 if (inv.Value.Name == name) 5083 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4647 { 5084 {
4648 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5085 m_host.TaskInventory.LockItemsForRead(false);
4649 { 5086 return inv.Value.AssetID.ToString();
4650 return inv.Value.AssetID.ToString(); 5087 }
4651 } 5088 else
4652 else 5089 {
4653 { 5090 m_host.TaskInventory.LockItemsForRead(false);
4654 return UUID.Zero.ToString(); 5091 return UUID.Zero.ToString();
4655 }
4656 } 5092 }
4657 } 5093 }
4658 } 5094 }
5095 m_host.TaskInventory.LockItemsForRead(false);
4659 5096
4660 return UUID.Zero.ToString(); 5097 return UUID.Zero.ToString();
4661 } 5098 }
@@ -4789,7 +5226,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4789 public LSL_Vector llGetCenterOfMass() 5226 public LSL_Vector llGetCenterOfMass()
4790 { 5227 {
4791 m_host.AddScriptLPS(1); 5228 m_host.AddScriptLPS(1);
4792 Vector3 center = m_host.GetGeometricCenter(); 5229 Vector3 center = m_host.GetCenterOfMass();
4793 return new LSL_Vector(center.X,center.Y,center.Z); 5230 return new LSL_Vector(center.X,center.Y,center.Z);
4794 } 5231 }
4795 5232
@@ -4808,14 +5245,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4808 { 5245 {
4809 m_host.AddScriptLPS(1); 5246 m_host.AddScriptLPS(1);
4810 5247
4811 if (src == null) 5248 return src.Length;
4812 {
4813 return 0;
4814 }
4815 else
4816 {
4817 return src.Length;
4818 }
4819 } 5249 }
4820 5250
4821 public LSL_Integer llList2Integer(LSL_List src, int index) 5251 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4861,7 +5291,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4861 else if (src.Data[index] is LSL_Float) 5291 else if (src.Data[index] is LSL_Float)
4862 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5292 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4863 else if (src.Data[index] is LSL_String) 5293 else if (src.Data[index] is LSL_String)
4864 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5294 {
5295 string str = ((LSL_String) src.Data[index]).m_string;
5296 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5297 if (m != Match.Empty)
5298 {
5299 str = m.Value;
5300 double d = 0.0;
5301 if (!Double.TryParse(str, out d))
5302 return 0.0;
5303
5304 return d;
5305 }
5306 return 0.0;
5307 }
4865 return Convert.ToDouble(src.Data[index]); 5308 return Convert.ToDouble(src.Data[index]);
4866 } 5309 }
4867 catch (FormatException) 5310 catch (FormatException)
@@ -5134,7 +5577,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5134 } 5577 }
5135 } 5578 }
5136 } 5579 }
5137 else { 5580 else
5581 {
5138 object[] array = new object[src.Length]; 5582 object[] array = new object[src.Length];
5139 Array.Copy(src.Data, 0, array, 0, src.Length); 5583 Array.Copy(src.Data, 0, array, 0, src.Length);
5140 result = new LSL_List(array); 5584 result = new LSL_List(array);
@@ -5241,7 +5685,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5241 public LSL_Integer llGetRegionAgentCount() 5685 public LSL_Integer llGetRegionAgentCount()
5242 { 5686 {
5243 m_host.AddScriptLPS(1); 5687 m_host.AddScriptLPS(1);
5244 return new LSL_Integer(World.GetRootAgentCount()); 5688
5689 int count = 0;
5690 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5691 count++;
5692 });
5693
5694 return new LSL_Integer(count);
5245 } 5695 }
5246 5696
5247 public LSL_Vector llGetRegionCorner() 5697 public LSL_Vector llGetRegionCorner()
@@ -5521,6 +5971,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5521 flags |= ScriptBaseClass.AGENT_SITTING; 5971 flags |= ScriptBaseClass.AGENT_SITTING;
5522 } 5972 }
5523 5973
5974 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
5975 {
5976 flags |= ScriptBaseClass.AGENT_MALE;
5977 }
5978
5524 return flags; 5979 return flags;
5525 } 5980 }
5526 5981
@@ -5667,10 +6122,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5667 m_host.AddScriptLPS(1); 6122 m_host.AddScriptLPS(1);
5668 6123
5669 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6124 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5670 6125 if (parts.Count > 0)
5671 foreach (var part in parts)
5672 { 6126 {
5673 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6127 try
6128 {
6129 parts[0].ParentGroup.areUpdatesSuspended = true;
6130 foreach (var part in parts)
6131 {
6132 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6133 }
6134 }
6135 finally
6136 {
6137 parts[0].ParentGroup.areUpdatesSuspended = false;
6138 }
5674 } 6139 }
5675 } 6140 }
5676 6141
@@ -5722,13 +6187,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5722 6187
5723 if (m_host.OwnerID == land.LandData.OwnerID) 6188 if (m_host.OwnerID == land.LandData.OwnerID)
5724 { 6189 {
5725 World.TeleportClientHome(agentID, presence.ControllingClient); 6190 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6191 presence.TeleportWithMomentum(pos, null);
6192 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5726 } 6193 }
5727 } 6194 }
5728 } 6195 }
5729 ScriptSleep(5000); 6196 ScriptSleep(5000);
5730 } 6197 }
5731 6198
6199 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6200 {
6201 return ParseString2List(str, separators, in_spacers, false);
6202 }
6203
5732 public LSL_Integer llOverMyLand(string id) 6204 public LSL_Integer llOverMyLand(string id)
5733 { 6205 {
5734 m_host.AddScriptLPS(1); 6206 m_host.AddScriptLPS(1);
@@ -5793,8 +6265,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5793 UUID agentId = new UUID(); 6265 UUID agentId = new UUID();
5794 if (!UUID.TryParse(agent, out agentId)) 6266 if (!UUID.TryParse(agent, out agentId))
5795 return new LSL_Integer(0); 6267 return new LSL_Integer(0);
6268 if (agentId == m_host.GroupID)
6269 return new LSL_Integer(1);
5796 ScenePresence presence = World.GetScenePresence(agentId); 6270 ScenePresence presence = World.GetScenePresence(agentId);
5797 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6271 if (presence == null || presence.IsChildAgent) // Return false for child agents
5798 return new LSL_Integer(0); 6272 return new LSL_Integer(0);
5799 IClientAPI client = presence.ControllingClient; 6273 IClientAPI client = presence.ControllingClient;
5800 if (m_host.GroupID == client.ActiveGroupId) 6274 if (m_host.GroupID == client.ActiveGroupId)
@@ -5929,7 +6403,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5929 return m_host.ParentGroup.AttachmentPoint; 6403 return m_host.ParentGroup.AttachmentPoint;
5930 } 6404 }
5931 6405
5932 public LSL_Integer llGetFreeMemory() 6406 public virtual LSL_Integer llGetFreeMemory()
5933 { 6407 {
5934 m_host.AddScriptLPS(1); 6408 m_host.AddScriptLPS(1);
5935 // Make scripts designed for LSO happy 6409 // Make scripts designed for LSO happy
@@ -6046,7 +6520,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6046 SetParticleSystem(m_host, rules); 6520 SetParticleSystem(m_host, rules);
6047 } 6521 }
6048 6522
6049 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6523 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6524 {
6050 6525
6051 6526
6052 if (rules.Length == 0) 6527 if (rules.Length == 0)
@@ -6240,14 +6715,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6240 6715
6241 protected UUID GetTaskInventoryItem(string name) 6716 protected UUID GetTaskInventoryItem(string name)
6242 { 6717 {
6243 lock (m_host.TaskInventory) 6718 m_host.TaskInventory.LockItemsForRead(true);
6719 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6244 { 6720 {
6245 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6721 if (inv.Value.Name == name)
6246 { 6722 {
6247 if (inv.Value.Name == name) 6723 m_host.TaskInventory.LockItemsForRead(false);
6248 return inv.Key; 6724 return inv.Key;
6249 } 6725 }
6250 } 6726 }
6727 m_host.TaskInventory.LockItemsForRead(false);
6251 6728
6252 return UUID.Zero; 6729 return UUID.Zero;
6253 } 6730 }
@@ -6285,16 +6762,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6285 if (folderID == UUID.Zero) 6762 if (folderID == UUID.Zero)
6286 return; 6763 return;
6287 6764
6288 byte[] bucket = new byte[17]; 6765 byte[] bucket = new byte[1];
6289 bucket[0] = (byte)AssetType.Folder; 6766 bucket[0] = (byte)AssetType.Folder;
6290 byte[] objBytes = folderID.GetBytes(); 6767 //byte[] objBytes = folderID.GetBytes();
6291 Array.Copy(objBytes, 0, bucket, 1, 16); 6768 //Array.Copy(objBytes, 0, bucket, 1, 16);
6292 6769
6293 GridInstantMessage msg = new GridInstantMessage(World, 6770 GridInstantMessage msg = new GridInstantMessage(World,
6294 m_host.UUID, m_host.Name+", an object owned by "+ 6771 m_host.OwnerID, m_host.Name, destID,
6295 resolveName(m_host.OwnerID)+",", destID, 6772 (byte)InstantMessageDialog.TaskInventoryOffered,
6296 (byte)InstantMessageDialog.InventoryOffered, 6773 false, category+". "+m_host.Name+" is located at "+
6297 false, category+"\n"+m_host.Name+" is located at "+
6298 World.RegionInfo.RegionName+" "+ 6774 World.RegionInfo.RegionName+" "+
6299 m_host.AbsolutePosition.ToString(), 6775 m_host.AbsolutePosition.ToString(),
6300 folderID, true, m_host.AbsolutePosition, 6776 folderID, true, m_host.AbsolutePosition,
@@ -6532,13 +7008,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6532 UUID av = new UUID(); 7008 UUID av = new UUID();
6533 if (!UUID.TryParse(avatar,out av)) 7009 if (!UUID.TryParse(avatar,out av))
6534 { 7010 {
6535 LSLError("First parameter to llDialog needs to be a key"); 7011 //LSLError("First parameter to llDialog needs to be a key");
6536 return; 7012 return;
6537 } 7013 }
6538 if (buttons.Length < 1) 7014 if (buttons.Length < 1)
6539 { 7015 {
6540 LSLError("No less than 1 button can be shown"); 7016 buttons.Add("OK");
6541 return;
6542 } 7017 }
6543 if (buttons.Length > 12) 7018 if (buttons.Length > 12)
6544 { 7019 {
@@ -6555,7 +7030,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6555 } 7030 }
6556 if (buttons.Data[i].ToString().Length > 24) 7031 if (buttons.Data[i].ToString().Length > 24)
6557 { 7032 {
6558 LSLError("button label cannot be longer than 24 characters"); 7033 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6559 return; 7034 return;
6560 } 7035 }
6561 buts[i] = buttons.Data[i].ToString(); 7036 buts[i] = buttons.Data[i].ToString();
@@ -6614,22 +7089,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6614 } 7089 }
6615 7090
6616 // copy the first script found with this inventory name 7091 // copy the first script found with this inventory name
6617 lock (m_host.TaskInventory) 7092 TaskInventoryItem scriptItem = null;
7093 m_host.TaskInventory.LockItemsForRead(true);
7094 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6618 { 7095 {
6619 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 7096 if (inv.Value.Name == name)
6620 { 7097 {
6621 if (inv.Value.Name == name) 7098 // make sure the object is a script
7099 if (10 == inv.Value.Type)
6622 { 7100 {
6623 // make sure the object is a script 7101 found = true;
6624 if (10 == inv.Value.Type) 7102 srcId = inv.Key;
6625 { 7103 scriptItem = inv.Value;
6626 found = true; 7104 break;
6627 srcId = inv.Key;
6628 break;
6629 }
6630 } 7105 }
6631 } 7106 }
6632 } 7107 }
7108 m_host.TaskInventory.LockItemsForRead(false);
6633 7109
6634 if (!found) 7110 if (!found)
6635 { 7111 {
@@ -6637,9 +7113,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6637 return; 7113 return;
6638 } 7114 }
6639 7115
6640 // the rest of the permission checks are done in RezScript, so check the pin there as well 7116 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6641 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7117 if (dest != null)
7118 {
7119 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7120 {
7121 // the rest of the permission checks are done in RezScript, so check the pin there as well
7122 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6642 7123
7124 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7125 m_host.Inventory.RemoveInventoryItem(srcId);
7126 }
7127 }
6643 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7128 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6644 ScriptSleep(3000); 7129 ScriptSleep(3000);
6645 } 7130 }
@@ -6702,19 +7187,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6702 public LSL_String llMD5String(string src, int nonce) 7187 public LSL_String llMD5String(string src, int nonce)
6703 { 7188 {
6704 m_host.AddScriptLPS(1); 7189 m_host.AddScriptLPS(1);
6705 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7190 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6706 } 7191 }
6707 7192
6708 public LSL_String llSHA1String(string src) 7193 public LSL_String llSHA1String(string src)
6709 { 7194 {
6710 m_host.AddScriptLPS(1); 7195 m_host.AddScriptLPS(1);
6711 return Util.SHA1Hash(src).ToLower(); 7196 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6712 } 7197 }
6713 7198
6714 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7199 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6715 { 7200 {
6716 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7201 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6717 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7202 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7203 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7204 return shapeBlock;
6718 7205
6719 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7206 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6720 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7207 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6819,6 +7306,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6819 // Prim type box, cylinder and prism. 7306 // Prim type box, cylinder and prism.
6820 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) 7307 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)
6821 { 7308 {
7309 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7310 return;
7311
6822 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7312 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6823 ObjectShapePacket.ObjectDataBlock shapeBlock; 7313 ObjectShapePacket.ObjectDataBlock shapeBlock;
6824 7314
@@ -6872,6 +7362,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6872 // Prim type sphere. 7362 // Prim type sphere.
6873 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7363 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6874 { 7364 {
7365 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7366 return;
7367
6875 ObjectShapePacket.ObjectDataBlock shapeBlock; 7368 ObjectShapePacket.ObjectDataBlock shapeBlock;
6876 7369
6877 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7370 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6913,6 +7406,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6913 // Prim type torus, tube and ring. 7406 // Prim type torus, tube and ring.
6914 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) 7407 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)
6915 { 7408 {
7409 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7410 return;
7411
6916 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7412 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6917 ObjectShapePacket.ObjectDataBlock shapeBlock; 7413 ObjectShapePacket.ObjectDataBlock shapeBlock;
6918 7414
@@ -7048,6 +7544,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7048 // Prim type sculpt. 7544 // Prim type sculpt.
7049 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7545 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7050 { 7546 {
7547 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7548 return;
7549
7051 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7550 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7052 UUID sculptId; 7551 UUID sculptId;
7053 7552
@@ -7072,7 +7571,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7072 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7571 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7073 { 7572 {
7074 // default 7573 // default
7075 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7574 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7076 } 7575 }
7077 7576
7078 part.Shape.SetSculptProperties((byte)type, sculptId); 7577 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7088,32 +7587,149 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7088 ScriptSleep(200); 7587 ScriptSleep(200);
7089 } 7588 }
7090 7589
7091 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7590 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7092 { 7591 {
7093 m_host.AddScriptLPS(1); 7592 m_host.AddScriptLPS(1);
7094 7593
7095 setLinkPrimParams(linknumber, rules); 7594 setLinkPrimParams(linknumber, rules);
7595 }
7096 7596
7097 ScriptSleep(200); 7597 private void setLinkPrimParams(int linknumber, LSL_List rules)
7598 {
7599 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7600 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7601 if (parts.Count>0)
7602 {
7603 try
7604 {
7605 parts[0].ParentGroup.areUpdatesSuspended = true;
7606 foreach (SceneObjectPart part in parts)
7607 SetPrimParams(part, rules);
7608 }
7609 finally
7610 {
7611 parts[0].ParentGroup.areUpdatesSuspended = false;
7612 }
7613 }
7614 if (avatars.Count > 0)
7615 {
7616 foreach (ScenePresence avatar in avatars)
7617 SetPrimParams(avatar, rules);
7618 }
7098 } 7619 }
7099 7620
7100 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7621 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7622 float material_density, float material_friction,
7623 float material_restitution, float material_gravity_modifier)
7101 { 7624 {
7102 m_host.AddScriptLPS(1); 7625 ExtraPhysicsData physdata = new ExtraPhysicsData();
7626 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7627 physdata.Density = part.Density;
7628 physdata.Friction = part.Friction;
7629 physdata.Bounce = part.Bounciness;
7630 physdata.GravitationModifier = part.GravityModifier;
7103 7631
7104 setLinkPrimParams(linknumber, rules); 7632 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7633 physdata.Density = material_density;
7634 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7635 physdata.Friction = material_friction;
7636 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7637 physdata.Bounce = material_restitution;
7638 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7639 physdata.GravitationModifier = material_gravity_modifier;
7640
7641 part.UpdateExtraPhysics(physdata);
7105 } 7642 }
7106 7643
7107 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7644 public void llSetPhysicsMaterial(int material_bits,
7645 float material_gravity_modifier, float material_restitution,
7646 float material_friction, float material_density)
7108 { 7647 {
7109 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7648 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7649 }
7110 7650
7111 foreach (SceneObjectPart part in parts) 7651 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7112 SetPrimParams(part, rules); 7652 {
7653 llSetLinkPrimitiveParamsFast(linknumber, rules);
7654 ScriptSleep(200);
7655 }
7656
7657 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7658 {
7659 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7660 //We only support PRIM_POSITION and PRIM_ROTATION
7661
7662 int idx = 0;
7663
7664 while (idx < rules.Length)
7665 {
7666 int code = rules.GetLSLIntegerItem(idx++);
7667
7668 int remain = rules.Length - idx;
7669
7670 switch (code)
7671 {
7672 case (int)ScriptBaseClass.PRIM_POSITION:
7673 {
7674 if (remain < 1)
7675 return;
7676 LSL_Vector v;
7677 v = rules.GetVector3Item(idx++);
7678
7679 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7680 if (part == null)
7681 break;
7682
7683 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7684 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7685 if (llGetLinkNumber() > 1)
7686 {
7687 localRot = llGetLocalRot();
7688 localPos = llGetLocalPos();
7689 }
7690
7691 v -= localPos;
7692 v /= localRot;
7693
7694 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
7695
7696 v = v + 2 * sitOffset;
7697
7698 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7699 av.SendAvatarDataToAllAgents();
7700
7701 }
7702 break;
7703
7704 case (int)ScriptBaseClass.PRIM_ROTATION:
7705 {
7706 if (remain < 1)
7707 return;
7708
7709 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7710 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7711 if (llGetLinkNumber() > 1)
7712 {
7713 localRot = llGetLocalRot();
7714 localPos = llGetLocalPos();
7715 }
7716
7717 LSL_Rotation r;
7718 r = rules.GetQuaternionItem(idx++);
7719 r = r * llGetRootRotation() / localRot;
7720 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7721 av.SendAvatarDataToAllAgents();
7722 }
7723 break;
7724 }
7725 }
7113 } 7726 }
7114 7727
7115 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7728 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7116 { 7729 {
7730 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7731 return;
7732
7117 int idx = 0; 7733 int idx = 0;
7118 7734
7119 bool positionChanged = false; 7735 bool positionChanged = false;
@@ -7435,6 +8051,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7435 part.ScriptSetPhysicsStatus(physics); 8051 part.ScriptSetPhysicsStatus(physics);
7436 break; 8052 break;
7437 8053
8054 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
8055 if (remain < 1)
8056 return;
8057
8058 int shape_type = rules.GetLSLIntegerItem(idx++);
8059
8060 ExtraPhysicsData physdata = new ExtraPhysicsData();
8061 physdata.Density = part.Density;
8062 physdata.Bounce = part.Bounciness;
8063 physdata.GravitationModifier = part.GravityModifier;
8064 physdata.PhysShapeType = (PhysShapeType)shape_type;
8065
8066 part.UpdateExtraPhysics(physdata);
8067
8068 break;
8069
8070 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8071 if (remain < 5)
8072 return;
8073
8074 int material_bits = rules.GetLSLIntegerItem(idx++);
8075 float material_density = (float)rules.GetLSLFloatItem(idx++);
8076 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8077 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8078 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8079
8080 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8081
8082 break;
8083
7438 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8084 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7439 if (remain < 1) 8085 if (remain < 1)
7440 return; 8086 return;
@@ -7508,7 +8154,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7508 if (part.ParentGroup.RootPart == part) 8154 if (part.ParentGroup.RootPart == part)
7509 { 8155 {
7510 SceneObjectGroup parent = part.ParentGroup; 8156 SceneObjectGroup parent = part.ParentGroup;
7511 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8157 Util.FireAndForget(delegate(object x) {
8158 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8159 });
7512 } 8160 }
7513 else 8161 else
7514 { 8162 {
@@ -7519,6 +8167,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7519 } 8167 }
7520 } 8168 }
7521 } 8169 }
8170
8171 if (positionChanged)
8172 {
8173 if (part.ParentGroup.RootPart == part)
8174 {
8175 SceneObjectGroup parent = part.ParentGroup;
8176 Util.FireAndForget(delegate(object x) {
8177 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8178 });
8179 }
8180 else
8181 {
8182 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8183 SceneObjectGroup parent = part.ParentGroup;
8184 parent.HasGroupChanged = true;
8185 parent.ScheduleGroupForTerseUpdate();
8186 }
8187 }
7522 } 8188 }
7523 8189
7524 public LSL_String llStringToBase64(string str) 8190 public LSL_String llStringToBase64(string str)
@@ -7679,13 +8345,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7679 public LSL_Integer llGetNumberOfPrims() 8345 public LSL_Integer llGetNumberOfPrims()
7680 { 8346 {
7681 m_host.AddScriptLPS(1); 8347 m_host.AddScriptLPS(1);
7682 int avatarCount = 0; 8348 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7683 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8349
7684 {
7685 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
7686 avatarCount++;
7687 });
7688
7689 return m_host.ParentGroup.PrimCount + avatarCount; 8350 return m_host.ParentGroup.PrimCount + avatarCount;
7690 } 8351 }
7691 8352
@@ -7701,55 +8362,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7701 m_host.AddScriptLPS(1); 8362 m_host.AddScriptLPS(1);
7702 UUID objID = UUID.Zero; 8363 UUID objID = UUID.Zero;
7703 LSL_List result = new LSL_List(); 8364 LSL_List result = new LSL_List();
8365
8366 // If the ID is not valid, return null result
7704 if (!UUID.TryParse(obj, out objID)) 8367 if (!UUID.TryParse(obj, out objID))
7705 { 8368 {
7706 result.Add(new LSL_Vector()); 8369 result.Add(new LSL_Vector());
7707 result.Add(new LSL_Vector()); 8370 result.Add(new LSL_Vector());
7708 return result; 8371 return result;
7709 } 8372 }
8373
8374 // Check if this is an attached prim. If so, replace
8375 // the UUID with the avatar UUID and report it's bounding box
8376 SceneObjectPart part = World.GetSceneObjectPart(objID);
8377 if (part != null && part.ParentGroup.IsAttachment)
8378 objID = part.ParentGroup.AttachedAvatar;
8379
8380 // Find out if this is an avatar ID. If so, return it's box
7710 ScenePresence presence = World.GetScenePresence(objID); 8381 ScenePresence presence = World.GetScenePresence(objID);
7711 if (presence != null) 8382 if (presence != null)
7712 { 8383 {
7713 if (presence.ParentID == 0) // not sat on an object 8384 // As per LSL Wiki, there is no difference between sitting
8385 // and standing avatar since server 1.36
8386 LSL_Vector lower;
8387 LSL_Vector upper;
8388 if (presence.Animator.Animations.DefaultAnimation.AnimID
8389 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7714 { 8390 {
7715 LSL_Vector lower; 8391 // This is for ground sitting avatars
7716 LSL_Vector upper; 8392 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7717 if (presence.Animator.Animations.DefaultAnimation.AnimID 8393 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7718 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8394 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7719 {
7720 // This is for ground sitting avatars
7721 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7722 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7723 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7724 }
7725 else
7726 {
7727 // This is for standing/flying avatars
7728 float height = presence.Appearance.AvatarHeight / 2.0f;
7729 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7730 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7731 }
7732 result.Add(lower);
7733 result.Add(upper);
7734 return result;
7735 } 8395 }
7736 else 8396 else
7737 { 8397 {
7738 // sitting on an object so we need the bounding box of that 8398 // This is for standing/flying avatars
7739 // which should include the avatar so set the UUID to the 8399 float height = presence.Appearance.AvatarHeight / 2.0f;
7740 // UUID of the object the avatar is sat on and allow it to fall through 8400 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7741 // to processing an object 8401 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7742 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7743 objID = p.UUID;
7744 } 8402 }
8403
8404 // Adjust to the documented error offsets (see LSL Wiki)
8405 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8406 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8407
8408 if (lower.x > upper.x)
8409 lower.x = upper.x;
8410 if (lower.y > upper.y)
8411 lower.y = upper.y;
8412 if (lower.z > upper.z)
8413 lower.z = upper.z;
8414
8415 result.Add(lower);
8416 result.Add(upper);
8417 return result;
7745 } 8418 }
7746 SceneObjectPart part = World.GetSceneObjectPart(objID); 8419
8420 part = World.GetSceneObjectPart(objID);
7747 // Currently only works for single prims without a sitting avatar 8421 // Currently only works for single prims without a sitting avatar
7748 if (part != null) 8422 if (part != null)
7749 { 8423 {
7750 Vector3 halfSize = part.Scale / 2.0f; 8424 float minX;
7751 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8425 float maxX;
7752 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8426 float minY;
8427 float maxY;
8428 float minZ;
8429 float maxZ;
8430
8431 // This BBox is in sim coordinates, with the offset being
8432 // a contained point.
8433 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8434 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8435
8436 minX -= offsets[0].X;
8437 maxX -= offsets[0].X;
8438 minY -= offsets[0].Y;
8439 maxY -= offsets[0].Y;
8440 minZ -= offsets[0].Z;
8441 maxZ -= offsets[0].Z;
8442
8443 LSL_Vector lower;
8444 LSL_Vector upper;
8445
8446 // Adjust to the documented error offsets (see LSL Wiki)
8447 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8448 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8449
8450 if (lower.x > upper.x)
8451 lower.x = upper.x;
8452 if (lower.y > upper.y)
8453 lower.y = upper.y;
8454 if (lower.z > upper.z)
8455 lower.z = upper.z;
8456
7753 result.Add(lower); 8457 result.Add(lower);
7754 result.Add(upper); 8458 result.Add(upper);
7755 return result; 8459 return result;
@@ -7763,7 +8467,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7763 8467
7764 public LSL_Vector llGetGeometricCenter() 8468 public LSL_Vector llGetGeometricCenter()
7765 { 8469 {
7766 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 8470 Vector3 tmp = m_host.GetGeometricCenter();
8471 return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
7767 } 8472 }
7768 8473
7769 public LSL_List llGetPrimitiveParams(LSL_List rules) 8474 public LSL_List llGetPrimitiveParams(LSL_List rules)
@@ -7829,13 +8534,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7829 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8534 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7830 part.AbsolutePosition.Y, 8535 part.AbsolutePosition.Y,
7831 part.AbsolutePosition.Z); 8536 part.AbsolutePosition.Z);
7832 // For some reason, the part.AbsolutePosition.* values do not change if the
7833 // linkset is rotated; they always reflect the child prim's world position
7834 // as though the linkset is unrotated. This is incompatible behavior with SL's
7835 // implementation, so will break scripts imported from there (not to mention it
7836 // makes it more difficult to determine a child prim's actual inworld position).
7837 if (part.ParentID != 0)
7838 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7839 res.Add(v); 8537 res.Add(v);
7840 break; 8538 break;
7841 8539
@@ -8006,56 +8704,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8006 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8704 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8007 if (remain < 1) 8705 if (remain < 1)
8008 return res; 8706 return res;
8009 8707 face = (int)rules.GetLSLIntegerItem(idx++);
8010 face=(int)rules.GetLSLIntegerItem(idx++);
8011 8708
8012 tex = part.Shape.Textures; 8709 tex = part.Shape.Textures;
8710 int shiny;
8013 if (face == ScriptBaseClass.ALL_SIDES) 8711 if (face == ScriptBaseClass.ALL_SIDES)
8014 { 8712 {
8015 for (face = 0; face < GetNumberOfSides(part); face++) 8713 for (face = 0; face < GetNumberOfSides(part); face++)
8016 { 8714 {
8017 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8715 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8018 // Convert Shininess to PRIM_SHINY_* 8716 if (shinyness == Shininess.High)
8019 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8717 {
8020 // PRIM_BUMP_* 8718 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8021 res.Add(new LSL_Integer((int)texface.Bump)); 8719 }
8720 else if (shinyness == Shininess.Medium)
8721 {
8722 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8723 }
8724 else if (shinyness == Shininess.Low)
8725 {
8726 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8727 }
8728 else
8729 {
8730 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8731 }
8732 res.Add(new LSL_Integer(shiny));
8733 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8022 } 8734 }
8023 } 8735 }
8024 else 8736 else
8025 { 8737 {
8026 if (face >= 0 && face < GetNumberOfSides(part)) 8738 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8739 if (shinyness == Shininess.High)
8027 { 8740 {
8028 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8741 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8029 // Convert Shininess to PRIM_SHINY_* 8742 }
8030 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8743 else if (shinyness == Shininess.Medium)
8031 // PRIM_BUMP_* 8744 {
8032 res.Add(new LSL_Integer((int)texface.Bump)); 8745 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8033 } 8746 }
8747 else if (shinyness == Shininess.Low)
8748 {
8749 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8750 }
8751 else
8752 {
8753 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8754 }
8755 res.Add(new LSL_Integer(shiny));
8756 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8034 } 8757 }
8035 break; 8758 break;
8036 8759
8037 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8760 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8038 if (remain < 1) 8761 if (remain < 1)
8039 return res; 8762 return res;
8040 8763 face = (int)rules.GetLSLIntegerItem(idx++);
8041 face=(int)rules.GetLSLIntegerItem(idx++);
8042 8764
8043 tex = part.Shape.Textures; 8765 tex = part.Shape.Textures;
8766 int fullbright;
8044 if (face == ScriptBaseClass.ALL_SIDES) 8767 if (face == ScriptBaseClass.ALL_SIDES)
8045 { 8768 {
8046 for (face = 0; face < GetNumberOfSides(part); face++) 8769 for (face = 0; face < GetNumberOfSides(part); face++)
8047 { 8770 {
8048 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8771 if (tex.GetFace((uint)face).Fullbright == true)
8049 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8772 {
8773 fullbright = ScriptBaseClass.TRUE;
8774 }
8775 else
8776 {
8777 fullbright = ScriptBaseClass.FALSE;
8778 }
8779 res.Add(new LSL_Integer(fullbright));
8050 } 8780 }
8051 } 8781 }
8052 else 8782 else
8053 { 8783 {
8054 if (face >= 0 && face < GetNumberOfSides(part)) 8784 if (tex.GetFace((uint)face).Fullbright == true)
8055 { 8785 {
8056 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8786 fullbright = ScriptBaseClass.TRUE;
8057 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
8058 } 8787 }
8788 else
8789 {
8790 fullbright = ScriptBaseClass.FALSE;
8791 }
8792 res.Add(new LSL_Integer(fullbright));
8059 } 8793 }
8060 break; 8794 break;
8061 8795
@@ -8077,27 +8811,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8077 break; 8811 break;
8078 8812
8079 case (int)ScriptBaseClass.PRIM_TEXGEN: 8813 case (int)ScriptBaseClass.PRIM_TEXGEN:
8814 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8080 if (remain < 1) 8815 if (remain < 1)
8081 return res; 8816 return res;
8082 8817 face = (int)rules.GetLSLIntegerItem(idx++);
8083 face=(int)rules.GetLSLIntegerItem(idx++);
8084 8818
8085 tex = part.Shape.Textures; 8819 tex = part.Shape.Textures;
8086 if (face == ScriptBaseClass.ALL_SIDES) 8820 if (face == ScriptBaseClass.ALL_SIDES)
8087 { 8821 {
8088 for (face = 0; face < GetNumberOfSides(part); face++) 8822 for (face = 0; face < GetNumberOfSides(part); face++)
8089 { 8823 {
8090 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8824 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8091 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8825 {
8092 res.Add(new LSL_Integer((uint)texgen >> 1)); 8826 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8827 }
8828 else
8829 {
8830 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8831 }
8093 } 8832 }
8094 } 8833 }
8095 else 8834 else
8096 { 8835 {
8097 if (face >= 0 && face < GetNumberOfSides(part)) 8836 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8837 {
8838 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8839 }
8840 else
8098 { 8841 {
8099 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8842 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8100 res.Add(new LSL_Integer((uint)texgen >> 1));
8101 } 8843 }
8102 } 8844 }
8103 break; 8845 break;
@@ -8120,28 +8862,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8120 case (int)ScriptBaseClass.PRIM_GLOW: 8862 case (int)ScriptBaseClass.PRIM_GLOW:
8121 if (remain < 1) 8863 if (remain < 1)
8122 return res; 8864 return res;
8123 8865 face = (int)rules.GetLSLIntegerItem(idx++);
8124 face=(int)rules.GetLSLIntegerItem(idx++);
8125 8866
8126 tex = part.Shape.Textures; 8867 tex = part.Shape.Textures;
8868 float primglow;
8127 if (face == ScriptBaseClass.ALL_SIDES) 8869 if (face == ScriptBaseClass.ALL_SIDES)
8128 { 8870 {
8129 for (face = 0; face < GetNumberOfSides(part); face++) 8871 for (face = 0; face < GetNumberOfSides(part); face++)
8130 { 8872 {
8131 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8873 primglow = tex.GetFace((uint)face).Glow;
8132 res.Add(new LSL_Float(texface.Glow)); 8874 res.Add(new LSL_Float(primglow));
8133 } 8875 }
8134 } 8876 }
8135 else 8877 else
8136 { 8878 {
8137 if (face >= 0 && face < GetNumberOfSides(part)) 8879 primglow = tex.GetFace((uint)face).Glow;
8138 { 8880 res.Add(new LSL_Float(primglow));
8139 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8140 res.Add(new LSL_Float(texface.Glow));
8141 }
8142 } 8881 }
8143 break; 8882 break;
8144
8145 case (int)ScriptBaseClass.PRIM_TEXT: 8883 case (int)ScriptBaseClass.PRIM_TEXT:
8146 Color4 textColor = part.GetTextColor(); 8884 Color4 textColor = part.GetTextColor();
8147 res.Add(new LSL_String(part.Text)); 8885 res.Add(new LSL_String(part.Text));
@@ -8754,8 +9492,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8754 // The function returns an ordered list 9492 // The function returns an ordered list
8755 // representing the tokens found in the supplied 9493 // representing the tokens found in the supplied
8756 // sources string. If two successive tokenizers 9494 // sources string. If two successive tokenizers
8757 // are encountered, then a NULL entry is added 9495 // are encountered, then a null-string entry is
8758 // to the list. 9496 // added to the list.
8759 // 9497 //
8760 // It is a precondition that the source and 9498 // It is a precondition that the source and
8761 // toekizer lisst are non-null. If they are null, 9499 // toekizer lisst are non-null. If they are null,
@@ -8763,7 +9501,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8763 // while their lengths are being determined. 9501 // while their lengths are being determined.
8764 // 9502 //
8765 // A small amount of working memoryis required 9503 // A small amount of working memoryis required
8766 // of approximately 8*#tokenizers. 9504 // of approximately 8*#tokenizers + 8*srcstrlen.
8767 // 9505 //
8768 // There are many ways in which this function 9506 // There are many ways in which this function
8769 // can be implemented, this implementation is 9507 // can be implemented, this implementation is
@@ -8779,155 +9517,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8779 // and eliminates redundant tokenizers as soon 9517 // and eliminates redundant tokenizers as soon
8780 // as is possible. 9518 // as is possible.
8781 // 9519 //
8782 // The implementation tries to avoid any copying 9520 // The implementation tries to minimize temporary
8783 // of arrays or other objects. 9521 // garbage generation.
8784 // </remarks> 9522 // </remarks>
8785 9523
8786 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9524 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8787 { 9525 {
8788 int beginning = 0; 9526 return ParseString2List(src, separators, spacers, true);
8789 int srclen = src.Length; 9527 }
8790 int seplen = separators.Length;
8791 object[] separray = separators.Data;
8792 int spclen = spacers.Length;
8793 object[] spcarray = spacers.Data;
8794 int mlen = seplen+spclen;
8795
8796 int[] offset = new int[mlen+1];
8797 bool[] active = new bool[mlen];
8798
8799 int best;
8800 int j;
8801
8802 // Initial capacity reduces resize cost
8803 9528
8804 LSL_List tokens = new LSL_List(); 9529 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9530 {
9531 int srclen = src.Length;
9532 int seplen = separators.Length;
9533 object[] separray = separators.Data;
9534 int spclen = spacers.Length;
9535 object[] spcarray = spacers.Data;
9536 int dellen = 0;
9537 string[] delarray = new string[seplen+spclen];
8805 9538
8806 // All entries are initially valid 9539 int outlen = 0;
9540 string[] outarray = new string[srclen*2+1];
8807 9541
8808 for (int i = 0; i < mlen; i++) 9542 int i, j;
8809 active[i] = true; 9543 string d;
8810 9544
8811 offset[mlen] = srclen; 9545 m_host.AddScriptLPS(1);
8812 9546
8813 while (beginning < srclen) 9547 /*
9548 * Convert separator and spacer lists to C# strings.
9549 * Also filter out null strings so we don't hang.
9550 */
9551 for (i = 0; i < seplen; i ++)
8814 { 9552 {
9553 d = separray[i].ToString();
9554 if (d.Length > 0)
9555 {
9556 delarray[dellen++] = d;
9557 }
9558 }
9559 seplen = dellen;
8815 9560
8816 best = mlen; // as bad as it gets 9561 for (i = 0; i < spclen; i ++)
9562 {
9563 d = spcarray[i].ToString();
9564 if (d.Length > 0)
9565 {
9566 delarray[dellen++] = d;
9567 }
9568 }
8817 9569
8818 // Scan for separators 9570 /*
9571 * Scan through source string from beginning to end.
9572 */
9573 for (i = 0;;)
9574 {
8819 9575
8820 for (j = 0; j < seplen; j++) 9576 /*
9577 * Find earliest delimeter in src starting at i (if any).
9578 */
9579 int earliestDel = -1;
9580 int earliestSrc = srclen;
9581 string earliestStr = null;
9582 for (j = 0; j < dellen; j ++)
8821 { 9583 {
8822 if (separray[j].ToString() == String.Empty) 9584 d = delarray[j];
8823 active[j] = false; 9585 if (d != null)
8824
8825 if (active[j])
8826 { 9586 {
8827 // scan all of the markers 9587 int index = src.IndexOf(d, i);
8828 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9588 if (index < 0)
8829 { 9589 {
8830 // not present at all 9590 delarray[j] = null; // delim nowhere in src, don't check it anymore
8831 active[j] = false;
8832 } 9591 }
8833 else 9592 else if (index < earliestSrc)
8834 { 9593 {
8835 // present and correct 9594 earliestSrc = index; // where delimeter starts in source string
8836 if (offset[j] < offset[best]) 9595 earliestDel = j; // where delimeter is in delarray[]
8837 { 9596 earliestStr = d; // the delimeter string from delarray[]
8838 // closest so far 9597 if (index == i) break; // can't do any better than found at beg of string
8839 best = j;
8840 if (offset[best] == beginning)
8841 break;
8842 }
8843 } 9598 }
8844 } 9599 }
8845 } 9600 }
8846 9601
8847 // Scan for spacers 9602 /*
8848 9603 * Output source string starting at i through start of earliest delimeter.
8849 if (offset[best] != beginning) 9604 */
9605 if (keepNulls || (earliestSrc > i))
8850 { 9606 {
8851 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9607 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8852 {
8853 if (spcarray[j-seplen].ToString() == String.Empty)
8854 active[j] = false;
8855
8856 if (active[j])
8857 {
8858 // scan all of the markers
8859 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8860 {
8861 // not present at all
8862 active[j] = false;
8863 }
8864 else
8865 {
8866 // present and correct
8867 if (offset[j] < offset[best])
8868 {
8869 // closest so far
8870 best = j;
8871 }
8872 }
8873 }
8874 }
8875 } 9608 }
8876 9609
8877 // This is the normal exit from the scanning loop 9610 /*
9611 * If no delimeter found at or after i, we're done scanning.
9612 */
9613 if (earliestDel < 0) break;
8878 9614
8879 if (best == mlen) 9615 /*
9616 * If delimeter was a spacer, output the spacer.
9617 */
9618 if (earliestDel >= seplen)
8880 { 9619 {
8881 // no markers were found on this pass 9620 outarray[outlen++] = earliestStr;
8882 // so we're pretty much done
8883 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8884 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8885 break;
8886 } 9621 }
8887 9622
8888 // Otherwise we just add the newly delimited token 9623 /*
8889 // and recalculate where the search should continue. 9624 * Look at rest of src string following delimeter.
8890 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9625 */
8891 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9626 i = earliestSrc + earliestStr.Length;
8892
8893 if (best < seplen)
8894 {
8895 beginning = offset[best] + (separray[best].ToString()).Length;
8896 }
8897 else
8898 {
8899 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8900 string str = spcarray[best - seplen].ToString();
8901 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8902 tokens.Add(new LSL_String(str));
8903 }
8904 } 9627 }
8905 9628
8906 // This an awkward an not very intuitive boundary case. If the 9629 /*
8907 // last substring is a tokenizer, then there is an implied trailing 9630 * Make up an exact-sized output array suitable for an LSL_List object.
8908 // null list entry. Hopefully the single comparison will not be too 9631 */
8909 // arduous. Alternatively the 'break' could be replced with a return 9632 object[] outlist = new object[outlen];
8910 // but that's shabby programming. 9633 for (i = 0; i < outlen; i ++)
8911
8912 if ((beginning == srclen) && (keepNulls))
8913 { 9634 {
8914 if (srclen != 0) 9635 outlist[i] = new LSL_String(outarray[i]);
8915 tokens.Add(new LSL_String(""));
8916 } 9636 }
8917 9637 return new LSL_List(outlist);
8918 return tokens;
8919 }
8920
8921 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8922 {
8923 m_host.AddScriptLPS(1);
8924 return this.ParseString(src, separators, spacers, false);
8925 }
8926
8927 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8928 {
8929 m_host.AddScriptLPS(1);
8930 return this.ParseString(src, separators, spacers, true);
8931 } 9638 }
8932 9639
8933 public LSL_Integer llGetObjectPermMask(int mask) 9640 public LSL_Integer llGetObjectPermMask(int mask)
@@ -9004,28 +9711,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9004 { 9711 {
9005 m_host.AddScriptLPS(1); 9712 m_host.AddScriptLPS(1);
9006 9713
9007 lock (m_host.TaskInventory) 9714 m_host.TaskInventory.LockItemsForRead(true);
9715 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9008 { 9716 {
9009 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9717 if (inv.Value.Name == item)
9010 { 9718 {
9011 if (inv.Value.Name == item) 9719 m_host.TaskInventory.LockItemsForRead(false);
9720 switch (mask)
9012 { 9721 {
9013 switch (mask) 9722 case 0:
9014 { 9723 return (int)inv.Value.BasePermissions;
9015 case 0: 9724 case 1:
9016 return (int)inv.Value.BasePermissions; 9725 return (int)inv.Value.CurrentPermissions;
9017 case 1: 9726 case 2:
9018 return (int)inv.Value.CurrentPermissions; 9727 return (int)inv.Value.GroupPermissions;
9019 case 2: 9728 case 3:
9020 return (int)inv.Value.GroupPermissions; 9729 return (int)inv.Value.EveryonePermissions;
9021 case 3: 9730 case 4:
9022 return (int)inv.Value.EveryonePermissions; 9731 return (int)inv.Value.NextPermissions;
9023 case 4:
9024 return (int)inv.Value.NextPermissions;
9025 }
9026 } 9732 }
9027 } 9733 }
9028 } 9734 }
9735 m_host.TaskInventory.LockItemsForRead(false);
9029 9736
9030 return -1; 9737 return -1;
9031 } 9738 }
@@ -9072,16 +9779,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9072 { 9779 {
9073 m_host.AddScriptLPS(1); 9780 m_host.AddScriptLPS(1);
9074 9781
9075 lock (m_host.TaskInventory) 9782 m_host.TaskInventory.LockItemsForRead(true);
9783 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9076 { 9784 {
9077 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9785 if (inv.Value.Name == item)
9078 { 9786 {
9079 if (inv.Value.Name == item) 9787 m_host.TaskInventory.LockItemsForRead(false);
9080 { 9788 return inv.Value.CreatorID.ToString();
9081 return inv.Value.CreatorID.ToString();
9082 }
9083 } 9789 }
9084 } 9790 }
9791 m_host.TaskInventory.LockItemsForRead(false);
9085 9792
9086 llSay(0, "No item name '" + item + "'"); 9793 llSay(0, "No item name '" + item + "'");
9087 9794
@@ -9223,9 +9930,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9223 { 9930 {
9224 try 9931 try
9225 { 9932 {
9933 /*
9226 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 9934 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
9227 if (obj != null) 9935 if (obj != null)
9228 return (double)obj.GetMass(); 9936 return (double)obj.GetMass();
9937 */
9938 // return total object mass
9939 SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
9940 if (obj != null)
9941 return obj.GetMass();
9942
9229 // the object is null so the key is for an avatar 9943 // the object is null so the key is for an avatar
9230 ScenePresence avatar = World.GetScenePresence(key); 9944 ScenePresence avatar = World.GetScenePresence(key);
9231 if (avatar != null) 9945 if (avatar != null)
@@ -9245,7 +9959,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9245 } 9959 }
9246 9960
9247 /// <summary> 9961 /// <summary>
9248 /// illListReplaceList removes the sub-list defined by the inclusive indices 9962 /// llListReplaceList removes the sub-list defined by the inclusive indices
9249 /// start and end and inserts the src list in its place. The inclusive 9963 /// start and end and inserts the src list in its place. The inclusive
9250 /// nature of the indices means that at least one element must be deleted 9964 /// nature of the indices means that at least one element must be deleted
9251 /// if the indices are within the bounds of the existing list. I.e. 2,2 9965 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9302,16 +10016,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9302 // based upon end. Note that if end exceeds the upper 10016 // based upon end. Note that if end exceeds the upper
9303 // bound in this case, the entire destination list 10017 // bound in this case, the entire destination list
9304 // is removed. 10018 // is removed.
9305 else 10019 else if (start == 0)
9306 { 10020 {
9307 if (end + 1 < dest.Length) 10021 if (end + 1 < dest.Length)
9308 {
9309 return src + dest.GetSublist(end + 1, -1); 10022 return src + dest.GetSublist(end + 1, -1);
9310 }
9311 else 10023 else
9312 {
9313 return src; 10024 return src;
9314 } 10025 }
10026 else // Start < 0
10027 {
10028 if (end + 1 < dest.Length)
10029 return dest.GetSublist(end + 1, -1);
10030 else
10031 return new LSL_List();
9315 } 10032 }
9316 } 10033 }
9317 // Finally, if start > end, we strip away a prefix and 10034 // Finally, if start > end, we strip away a prefix and
@@ -9362,17 +10079,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9362 int width = 0; 10079 int width = 0;
9363 int height = 0; 10080 int height = 0;
9364 10081
9365 ParcelMediaCommandEnum? commandToSend = null; 10082 uint commandToSend = 0;
9366 float time = 0.0f; // default is from start 10083 float time = 0.0f; // default is from start
9367 10084
9368 ScenePresence presence = null; 10085 ScenePresence presence = null;
9369 10086
9370 for (int i = 0; i < commandList.Data.Length; i++) 10087 for (int i = 0; i < commandList.Data.Length; i++)
9371 { 10088 {
9372 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10089 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9373 switch (command) 10090 switch (command)
9374 { 10091 {
9375 case ParcelMediaCommandEnum.Agent: 10092 case (uint)ParcelMediaCommandEnum.Agent:
9376 // we send only to one agent 10093 // we send only to one agent
9377 if ((i + 1) < commandList.Length) 10094 if ((i + 1) < commandList.Length)
9378 { 10095 {
@@ -9389,25 +10106,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9389 } 10106 }
9390 break; 10107 break;
9391 10108
9392 case ParcelMediaCommandEnum.Loop: 10109 case (uint)ParcelMediaCommandEnum.Loop:
9393 loop = 1; 10110 loop = 1;
9394 commandToSend = command; 10111 commandToSend = command;
9395 update = true; //need to send the media update packet to set looping 10112 update = true; //need to send the media update packet to set looping
9396 break; 10113 break;
9397 10114
9398 case ParcelMediaCommandEnum.Play: 10115 case (uint)ParcelMediaCommandEnum.Play:
9399 loop = 0; 10116 loop = 0;
9400 commandToSend = command; 10117 commandToSend = command;
9401 update = true; //need to send the media update packet to make sure it doesn't loop 10118 update = true; //need to send the media update packet to make sure it doesn't loop
9402 break; 10119 break;
9403 10120
9404 case ParcelMediaCommandEnum.Pause: 10121 case (uint)ParcelMediaCommandEnum.Pause:
9405 case ParcelMediaCommandEnum.Stop: 10122 case (uint)ParcelMediaCommandEnum.Stop:
9406 case ParcelMediaCommandEnum.Unload: 10123 case (uint)ParcelMediaCommandEnum.Unload:
9407 commandToSend = command; 10124 commandToSend = command;
9408 break; 10125 break;
9409 10126
9410 case ParcelMediaCommandEnum.Url: 10127 case (uint)ParcelMediaCommandEnum.Url:
9411 if ((i + 1) < commandList.Length) 10128 if ((i + 1) < commandList.Length)
9412 { 10129 {
9413 if (commandList.Data[i + 1] is LSL_String) 10130 if (commandList.Data[i + 1] is LSL_String)
@@ -9420,7 +10137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9420 } 10137 }
9421 break; 10138 break;
9422 10139
9423 case ParcelMediaCommandEnum.Texture: 10140 case (uint)ParcelMediaCommandEnum.Texture:
9424 if ((i + 1) < commandList.Length) 10141 if ((i + 1) < commandList.Length)
9425 { 10142 {
9426 if (commandList.Data[i + 1] is LSL_String) 10143 if (commandList.Data[i + 1] is LSL_String)
@@ -9433,7 +10150,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9433 } 10150 }
9434 break; 10151 break;
9435 10152
9436 case ParcelMediaCommandEnum.Time: 10153 case (uint)ParcelMediaCommandEnum.Time:
9437 if ((i + 1) < commandList.Length) 10154 if ((i + 1) < commandList.Length)
9438 { 10155 {
9439 if (commandList.Data[i + 1] is LSL_Float) 10156 if (commandList.Data[i + 1] is LSL_Float)
@@ -9445,7 +10162,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9445 } 10162 }
9446 break; 10163 break;
9447 10164
9448 case ParcelMediaCommandEnum.AutoAlign: 10165 case (uint)ParcelMediaCommandEnum.AutoAlign:
9449 if ((i + 1) < commandList.Length) 10166 if ((i + 1) < commandList.Length)
9450 { 10167 {
9451 if (commandList.Data[i + 1] is LSL_Integer) 10168 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9459,7 +10176,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9459 } 10176 }
9460 break; 10177 break;
9461 10178
9462 case ParcelMediaCommandEnum.Type: 10179 case (uint)ParcelMediaCommandEnum.Type:
9463 if ((i + 1) < commandList.Length) 10180 if ((i + 1) < commandList.Length)
9464 { 10181 {
9465 if (commandList.Data[i + 1] is LSL_String) 10182 if (commandList.Data[i + 1] is LSL_String)
@@ -9472,7 +10189,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9472 } 10189 }
9473 break; 10190 break;
9474 10191
9475 case ParcelMediaCommandEnum.Desc: 10192 case (uint)ParcelMediaCommandEnum.Desc:
9476 if ((i + 1) < commandList.Length) 10193 if ((i + 1) < commandList.Length)
9477 { 10194 {
9478 if (commandList.Data[i + 1] is LSL_String) 10195 if (commandList.Data[i + 1] is LSL_String)
@@ -9485,7 +10202,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9485 } 10202 }
9486 break; 10203 break;
9487 10204
9488 case ParcelMediaCommandEnum.Size: 10205 case (uint)ParcelMediaCommandEnum.Size:
9489 if ((i + 2) < commandList.Length) 10206 if ((i + 2) < commandList.Length)
9490 { 10207 {
9491 if (commandList.Data[i + 1] is LSL_Integer) 10208 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9555,7 +10272,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9555 } 10272 }
9556 } 10273 }
9557 10274
9558 if (commandToSend != null) 10275 if (commandToSend != 0)
9559 { 10276 {
9560 // the commandList contained a start/stop/... command, too 10277 // the commandList contained a start/stop/... command, too
9561 if (presence == null) 10278 if (presence == null)
@@ -9592,7 +10309,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9592 10309
9593 if (aList.Data[i] != null) 10310 if (aList.Data[i] != null)
9594 { 10311 {
9595 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10312 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9596 { 10313 {
9597 case ParcelMediaCommandEnum.Url: 10314 case ParcelMediaCommandEnum.Url:
9598 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10315 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9635,16 +10352,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9635 { 10352 {
9636 m_host.AddScriptLPS(1); 10353 m_host.AddScriptLPS(1);
9637 10354
9638 lock (m_host.TaskInventory) 10355 m_host.TaskInventory.LockItemsForRead(true);
10356 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9639 { 10357 {
9640 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10358 if (inv.Value.Name == name)
9641 { 10359 {
9642 if (inv.Value.Name == name) 10360 m_host.TaskInventory.LockItemsForRead(false);
9643 { 10361 return inv.Value.Type;
9644 return inv.Value.Type;
9645 }
9646 } 10362 }
9647 } 10363 }
10364 m_host.TaskInventory.LockItemsForRead(false);
9648 10365
9649 return -1; 10366 return -1;
9650 } 10367 }
@@ -9655,15 +10372,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9655 10372
9656 if (quick_pay_buttons.Data.Length < 4) 10373 if (quick_pay_buttons.Data.Length < 4)
9657 { 10374 {
9658 LSLError("List must have at least 4 elements"); 10375 int x;
9659 return; 10376 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10377 {
10378 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10379 }
9660 } 10380 }
9661 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10381 int[] nPrice = new int[5];
9662 10382 nPrice[0] = price;
9663 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10383 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9664 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10384 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9665 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10385 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9666 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10386 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10387 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9667 m_host.ParentGroup.HasGroupChanged = true; 10388 m_host.ParentGroup.HasGroupChanged = true;
9668 } 10389 }
9669 10390
@@ -9679,8 +10400,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9679 ShoutError("No permissions to track the camera"); 10400 ShoutError("No permissions to track the camera");
9680 return new LSL_Vector(); 10401 return new LSL_Vector();
9681 } 10402 }
10403 m_host.TaskInventory.LockItemsForRead(false);
9682 10404
9683 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10405// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10406 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9684 if (presence != null) 10407 if (presence != null)
9685 { 10408 {
9686 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); 10409 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
@@ -9701,8 +10424,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9701 ShoutError("No permissions to track the camera"); 10424 ShoutError("No permissions to track the camera");
9702 return new LSL_Rotation(); 10425 return new LSL_Rotation();
9703 } 10426 }
10427 m_host.TaskInventory.LockItemsForRead(false);
9704 10428
9705 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10429// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10430 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9706 if (presence != null) 10431 if (presence != null)
9707 { 10432 {
9708 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); 10433 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W);
@@ -9762,8 +10487,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9762 { 10487 {
9763 m_host.AddScriptLPS(1); 10488 m_host.AddScriptLPS(1);
9764 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 10489 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
9765 if (detectedParams == null) return; // only works on the first detected avatar 10490 if (detectedParams == null)
9766 10491 {
10492 if (m_host.ParentGroup.IsAttachment == true)
10493 {
10494 detectedParams = new DetectParams();
10495 detectedParams.Key = m_host.OwnerID;
10496 }
10497 else
10498 {
10499 return;
10500 }
10501 }
10502
9767 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10503 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9768 if (avatar != null) 10504 if (avatar != null)
9769 { 10505 {
@@ -9771,6 +10507,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9771 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10507 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9772 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10508 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9773 } 10509 }
10510
9774 ScriptSleep(1000); 10511 ScriptSleep(1000);
9775 } 10512 }
9776 10513
@@ -9894,12 +10631,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9894 10631
9895 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10632 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9896 object[] data = rules.Data; 10633 object[] data = rules.Data;
9897 for (int i = 0; i < data.Length; ++i) { 10634 for (int i = 0; i < data.Length; ++i)
10635 {
9898 int type = Convert.ToInt32(data[i++].ToString()); 10636 int type = Convert.ToInt32(data[i++].ToString());
9899 if (i >= data.Length) break; // odd number of entries => ignore the last 10637 if (i >= data.Length) break; // odd number of entries => ignore the last
9900 10638
9901 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10639 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9902 switch (type) { 10640 switch (type)
10641 {
9903 case ScriptBaseClass.CAMERA_FOCUS: 10642 case ScriptBaseClass.CAMERA_FOCUS:
9904 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10643 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9905 case ScriptBaseClass.CAMERA_POSITION: 10644 case ScriptBaseClass.CAMERA_POSITION:
@@ -10005,19 +10744,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10005 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10744 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
10006 { 10745 {
10007 m_host.AddScriptLPS(1); 10746 m_host.AddScriptLPS(1);
10008 string ret = String.Empty; 10747
10009 string src1 = llBase64ToString(str1); 10748 if (str1 == String.Empty)
10010 string src2 = llBase64ToString(str2); 10749 return String.Empty;
10011 int c = 0; 10750 if (str2 == String.Empty)
10012 for (int i = 0; i < src1.Length; i++) 10751 return str1;
10752
10753 int len = str2.Length;
10754 if ((len % 4) != 0) // LL is EVIL!!!!
10755 {
10756 while (str2.EndsWith("="))
10757 str2 = str2.Substring(0, str2.Length - 1);
10758
10759 len = str2.Length;
10760 int mod = len % 4;
10761
10762 if (mod == 1)
10763 str2 = str2.Substring(0, str2.Length - 1);
10764 else if (mod == 2)
10765 str2 += "==";
10766 else if (mod == 3)
10767 str2 += "=";
10768 }
10769
10770 byte[] data1;
10771 byte[] data2;
10772 try
10773 {
10774 data1 = Convert.FromBase64String(str1);
10775 data2 = Convert.FromBase64String(str2);
10776 }
10777 catch (Exception)
10013 { 10778 {
10014 ret += (char) (src1[i] ^ src2[c]); 10779 return new LSL_String(String.Empty);
10780 }
10015 10781
10016 c++; 10782 byte[] d2 = new Byte[data1.Length];
10017 if (c >= src2.Length) 10783 int pos = 0;
10018 c = 0; 10784
10785 if (data1.Length <= data2.Length)
10786 {
10787 Array.Copy(data2, 0, d2, 0, data1.Length);
10788 }
10789 else
10790 {
10791 while (pos < data1.Length)
10792 {
10793 len = data1.Length - pos;
10794 if (len > data2.Length)
10795 len = data2.Length;
10796
10797 Array.Copy(data2, 0, d2, pos, len);
10798 pos += len;
10799 }
10019 } 10800 }
10020 return llStringToBase64(ret); 10801
10802 for (pos = 0 ; pos < data1.Length ; pos++ )
10803 data1[pos] ^= d2[pos];
10804
10805 return Convert.ToBase64String(data1);
10021 } 10806 }
10022 10807
10023 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10808 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10074,12 +10859,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10074 Regex r = new Regex(authregex); 10859 Regex r = new Regex(authregex);
10075 int[] gnums = r.GetGroupNumbers(); 10860 int[] gnums = r.GetGroupNumbers();
10076 Match m = r.Match(url); 10861 Match m = r.Match(url);
10077 if (m.Success) { 10862 if (m.Success)
10078 for (int i = 1; i < gnums.Length; i++) { 10863 {
10864 for (int i = 1; i < gnums.Length; i++)
10865 {
10079 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10866 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10080 //CaptureCollection cc = g.Captures; 10867 //CaptureCollection cc = g.Captures;
10081 } 10868 }
10082 if (m.Groups.Count == 5) { 10869 if (m.Groups.Count == 5)
10870 {
10083 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10871 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10084 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10872 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10085 } 10873 }
@@ -10442,15 +11230,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10442 11230
10443 internal UUID ScriptByName(string name) 11231 internal UUID ScriptByName(string name)
10444 { 11232 {
10445 lock (m_host.TaskInventory) 11233 m_host.TaskInventory.LockItemsForRead(true);
11234
11235 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10446 { 11236 {
10447 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 11237 if (item.Type == 10 && item.Name == name)
10448 { 11238 {
10449 if (item.Type == 10 && item.Name == name) 11239 m_host.TaskInventory.LockItemsForRead(false);
10450 return item.ItemID; 11240 return item.ItemID;
10451 } 11241 }
10452 } 11242 }
10453 11243
11244 m_host.TaskInventory.LockItemsForRead(false);
11245
10454 return UUID.Zero; 11246 return UUID.Zero;
10455 } 11247 }
10456 11248
@@ -10491,6 +11283,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10491 { 11283 {
10492 m_host.AddScriptLPS(1); 11284 m_host.AddScriptLPS(1);
10493 11285
11286 //Clone is thread safe
10494 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11287 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10495 11288
10496 UUID assetID = UUID.Zero; 11289 UUID assetID = UUID.Zero;
@@ -10553,6 +11346,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10553 { 11346 {
10554 m_host.AddScriptLPS(1); 11347 m_host.AddScriptLPS(1);
10555 11348
11349 //Clone is thread safe
10556 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11350 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10557 11351
10558 UUID assetID = UUID.Zero; 11352 UUID assetID = UUID.Zero;
@@ -10633,15 +11427,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10633 return GetLinkPrimitiveParams(obj, rules); 11427 return GetLinkPrimitiveParams(obj, rules);
10634 } 11428 }
10635 11429
10636 public void print(string str) 11430 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10637 { 11431 {
10638 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11432 List<SceneObjectPart> parts = GetLinkParts(link);
10639 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11433 if (parts.Count < 1)
10640 if (ossl != null) 11434 return 0;
10641 { 11435
10642 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11436 return GetNumberOfSides(parts[0]);
10643 m_log.Info("LSL print():" + str);
10644 }
10645 } 11437 }
10646 11438
10647 private string Name2Username(string name) 11439 private string Name2Username(string name)
@@ -10687,155 +11479,482 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10687 return rq.ToString(); 11479 return rq.ToString();
10688 } 11480 }
10689 11481
11482 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11483 {
11484 m_SayShoutCount = 0;
11485 }
11486
11487 private struct Tri
11488 {
11489 public Vector3 p1;
11490 public Vector3 p2;
11491 public Vector3 p3;
11492 }
11493
11494 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11495 {
11496 float height = avatar.Appearance.AvatarHeight;
11497 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11498 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11499
11500 if (point.X > b1.X && point.X < b2.X &&
11501 point.Y > b1.Y && point.Y < b2.Y &&
11502 point.Z > b1.Z && point.Z < b2.Z)
11503 return true;
11504 return false;
11505 }
11506
11507 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11508 {
11509 List<ContactResult> contacts = new List<ContactResult>();
11510
11511 Vector3 ab = rayEnd - rayStart;
11512
11513 World.ForEachScenePresence(delegate(ScenePresence sp)
11514 {
11515 Vector3 ac = sp.AbsolutePosition - rayStart;
11516 Vector3 bc = sp.AbsolutePosition - rayEnd;
11517
11518 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11519
11520 if (d > 1.5)
11521 return;
11522
11523 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11524
11525 if (d2 > 0)
11526 return;
11527
11528 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11529 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11530
11531 if (!InBoundingBox(sp, p))
11532 return;
11533
11534 ContactResult result = new ContactResult ();
11535 result.ConsumerID = sp.LocalId;
11536 result.Depth = Vector3.Distance(rayStart, p);
11537 result.Normal = Vector3.Zero;
11538 result.Pos = p;
11539
11540 contacts.Add(result);
11541 });
11542
11543 return contacts.ToArray();
11544 }
11545
11546 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11547 {
11548 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11549 List<ContactResult> contacts = new List<ContactResult>();
11550
11551 Vector3 ab = rayEnd - rayStart;
11552
11553 World.ForEachSOG(delegate(SceneObjectGroup group)
11554 {
11555 if (m_host.ParentGroup == group)
11556 return;
11557
11558 if (group.IsAttachment)
11559 return;
11560
11561 if (group.RootPart.PhysActor == null)
11562 {
11563 if (!includePhantom)
11564 return;
11565 }
11566 else
11567 {
11568 if (group.RootPart.PhysActor.IsPhysical)
11569 {
11570 if (!includePhysical)
11571 return;
11572 }
11573 else
11574 {
11575 if (!includeNonPhysical)
11576 return;
11577 }
11578 }
11579
11580 // Find the radius ouside of which we don't even need to hit test
11581 float minX;
11582 float maxX;
11583 float minY;
11584 float maxY;
11585 float minZ;
11586 float maxZ;
11587
11588 float radius = 0.0f;
11589
11590 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11591
11592 if (Math.Abs(minX) > radius)
11593 radius = Math.Abs(minX);
11594 if (Math.Abs(minY) > radius)
11595 radius = Math.Abs(minY);
11596 if (Math.Abs(minZ) > radius)
11597 radius = Math.Abs(minZ);
11598 if (Math.Abs(maxX) > radius)
11599 radius = Math.Abs(maxX);
11600 if (Math.Abs(maxY) > radius)
11601 radius = Math.Abs(maxY);
11602 if (Math.Abs(maxZ) > radius)
11603 radius = Math.Abs(maxZ);
11604
11605 Vector3 ac = group.AbsolutePosition - rayStart;
11606 Vector3 bc = group.AbsolutePosition - rayEnd;
11607
11608 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11609
11610 // Too far off ray, don't bother
11611 if (d > radius)
11612 return;
11613
11614 // Behind ray, drop
11615 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11616 if (d2 > 0)
11617 return;
11618
11619 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11620 // Miss.
11621 if (!intersection.HitTF)
11622 return;
11623
11624 ContactResult result = new ContactResult ();
11625 result.ConsumerID = group.LocalId;
11626 result.Depth = intersection.distance;
11627 result.Normal = intersection.normal;
11628 result.Pos = intersection.ipoint;
11629
11630 contacts.Add(result);
11631 });
11632
11633 return contacts.ToArray();
11634 }
11635
11636 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11637 {
11638 double[,] heightfield = World.Heightmap.GetDoubles();
11639 List<ContactResult> contacts = new List<ContactResult>();
11640
11641 double min = 2048.0;
11642 double max = 0.0;
11643
11644 // Find the min and max of the heightfield
11645 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11646 {
11647 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11648 {
11649 if (heightfield[x, y] > max)
11650 max = heightfield[x, y];
11651 if (heightfield[x, y] < min)
11652 min = heightfield[x, y];
11653 }
11654 }
11655
11656
11657 // A ray extends past rayEnd, but doesn't go back before
11658 // rayStart. If the start is above the highest point of the ground
11659 // and the ray goes up, we can't hit the ground. Ever.
11660 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11661 return null;
11662
11663 // Same for going down
11664 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11665 return null;
11666
11667 List<Tri> trilist = new List<Tri>();
11668
11669 // Create our triangle list
11670 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11671 {
11672 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11673 {
11674 Tri t1 = new Tri();
11675 Tri t2 = new Tri();
11676
11677 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11678 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11679 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11680 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11681
11682 t1.p1 = p1;
11683 t1.p2 = p2;
11684 t1.p3 = p3;
11685
11686 t2.p1 = p3;
11687 t2.p2 = p4;
11688 t2.p3 = p1;
11689
11690 trilist.Add(t1);
11691 trilist.Add(t2);
11692 }
11693 }
11694
11695 // Ray direction
11696 Vector3 rayDirection = rayEnd - rayStart;
11697
11698 foreach (Tri t in trilist)
11699 {
11700 // Compute triangle plane normal and edges
11701 Vector3 u = t.p2 - t.p1;
11702 Vector3 v = t.p3 - t.p1;
11703 Vector3 n = Vector3.Cross(u, v);
11704
11705 if (n == Vector3.Zero)
11706 continue;
11707
11708 Vector3 w0 = rayStart - t.p1;
11709 double a = -Vector3.Dot(n, w0);
11710 double b = Vector3.Dot(n, rayDirection);
11711
11712 // Not intersecting the plane, or in plane (same thing)
11713 // Ignoring this MAY cause the ground to not be detected
11714 // sometimes
11715 if (Math.Abs(b) < 0.000001)
11716 continue;
11717
11718 double r = a / b;
11719
11720 // ray points away from plane
11721 if (r < 0.0)
11722 continue;
11723
11724 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11725
11726 float uu = Vector3.Dot(u, u);
11727 float uv = Vector3.Dot(u, v);
11728 float vv = Vector3.Dot(v, v);
11729 Vector3 w = ip - t.p1;
11730 float wu = Vector3.Dot(w, u);
11731 float wv = Vector3.Dot(w, v);
11732 float d = uv * uv - uu * vv;
11733
11734 float cs = (uv * wv - vv * wu) / d;
11735 if (cs < 0 || cs > 1.0)
11736 continue;
11737 float ct = (uv * wu - uu * wv) / d;
11738 if (ct < 0 || (cs + ct) > 1.0)
11739 continue;
11740
11741 // Add contact point
11742 ContactResult result = new ContactResult ();
11743 result.ConsumerID = 0;
11744 result.Depth = Vector3.Distance(rayStart, ip);
11745 result.Normal = n;
11746 result.Pos = ip;
11747
11748 contacts.Add(result);
11749 }
11750
11751 if (contacts.Count == 0)
11752 return null;
11753
11754 contacts.Sort(delegate(ContactResult a, ContactResult b)
11755 {
11756 return (int)(a.Depth - b.Depth);
11757 });
11758
11759 return contacts[0];
11760 }
11761/*
11762 // not done:
11763 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
11764 {
11765 ContactResult[] contacts = null;
11766 World.ForEachSOG(delegate(SceneObjectGroup group)
11767 {
11768 if (m_host.ParentGroup == group)
11769 return;
11770
11771 if (group.IsAttachment)
11772 return;
11773
11774 if(group.RootPart.PhysActor != null)
11775 return;
11776
11777 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
11778 });
11779 return contacts;
11780 }
11781*/
11782
10690 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11783 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10691 { 11784 {
11785 LSL_List list = new LSL_List();
11786
10692 m_host.AddScriptLPS(1); 11787 m_host.AddScriptLPS(1);
10693 11788
10694 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11789 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10695 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11790 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10696 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11791 Vector3 dir = rayEnd - rayStart;
10697 11792
10698 int count = 0; 11793 float dist = Vector3.Mag(dir);
10699// int detectPhantom = 0; 11794
11795 int count = 1;
11796 bool detectPhantom = false;
10700 int dataFlags = 0; 11797 int dataFlags = 0;
10701 int rejectTypes = 0; 11798 int rejectTypes = 0;
10702 11799
10703 for (int i = 0; i < options.Length; i += 2) 11800 for (int i = 0; i < options.Length; i += 2)
10704 { 11801 {
10705 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11802 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10706 {
10707 count = options.GetLSLIntegerItem(i + 1); 11803 count = options.GetLSLIntegerItem(i + 1);
10708 } 11804 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10709// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11805 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10710// {
10711// detectPhantom = options.GetLSLIntegerItem(i + 1);
10712// }
10713 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11806 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10714 {
10715 dataFlags = options.GetLSLIntegerItem(i + 1); 11807 dataFlags = options.GetLSLIntegerItem(i + 1);
10716 }
10717 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11808 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10718 {
10719 rejectTypes = options.GetLSLIntegerItem(i + 1); 11809 rejectTypes = options.GetLSLIntegerItem(i + 1);
10720 }
10721 } 11810 }
10722 11811
10723 LSL_List list = new LSL_List(); 11812 if (count > 16)
10724 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11813 count = 16;
10725
10726 double distance = Util.GetDistanceTo(startvector, endvector);
10727
10728 if (distance == 0)
10729 distance = 0.001;
10730 11814
10731 Vector3 posToCheck = startvector; 11815 List<ContactResult> results = new List<ContactResult>();
10732 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10733 11816
10734 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11817 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10735 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11818 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10736 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11819 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10737 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11820 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10738 11821
10739 for (float i = 0; i <= distance; i += 0.1f) 11822
11823 if (World.SuportsRayCastFiltered())
10740 { 11824 {
10741 posToCheck = startvector + (dir * (i / (float)distance)); 11825 if (dist == 0)
11826 return list;
11827
11828 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
11829 if (checkTerrain)
11830 rayfilter |= RayFilterFlags.land;
11831// if (checkAgents)
11832// rayfilter |= RayFilterFlags.agent;
11833 if (checkPhysical)
11834 rayfilter |= RayFilterFlags.physical;
11835 if (checkNonPhysical)
11836 rayfilter |= RayFilterFlags.nonphysical;
11837 if (detectPhantom)
11838 rayfilter |= RayFilterFlags.LSLPhanton;
11839
11840 Vector3 direction = dir * ( 1/dist);
10742 11841
10743 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11842 if(rayfilter == 0)
10744 { 11843 {
10745 ContactResult result = new ContactResult(); 11844 list.Add(new LSL_Integer(0));
10746 result.ConsumerID = 0; 11845 return list;
10747 result.Depth = 0;
10748 result.Normal = Vector3.Zero;
10749 result.Pos = posToCheck;
10750 results.Add(result);
10751 checkTerrain = false;
10752 } 11846 }
10753 11847
10754 if (checkAgents) 11848 // get some more contacts to sort ???
11849 int physcount = 4 * count;
11850 if (physcount > 20)
11851 physcount = 20;
11852
11853 object physresults;
11854 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
11855
11856 if (physresults == null)
10755 { 11857 {
10756 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11858 list.Add(new LSL_Integer(-3)); // timeout error
10757 { 11859 return list;
10758 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X))
10759 {
10760 ContactResult result = new ContactResult ();
10761 result.ConsumerID = sp.LocalId;
10762 result.Depth = 0;
10763 result.Normal = Vector3.Zero;
10764 result.Pos = posToCheck;
10765 results.Add(result);
10766 }
10767 });
10768 } 11860 }
10769 }
10770 11861
10771 int refcount = 0; 11862 results = (List<ContactResult>)physresults;
10772 foreach (ContactResult result in results) 11863
10773 { 11864 // for now physics doesn't detect sitted avatars so do it outside physics
10774 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) 11865 if (checkAgents)
10775 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0) 11866 {
10776 continue; 11867 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11868 foreach (ContactResult r in agentHits)
11869 results.Add(r);
11870 }
10777 11871
10778 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID); 11872 // bug: will not detect phantom unless they are physical
11873 // don't use ObjectIntersection because its also bad
10779 11874
10780 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) 11875 }
10781 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents 11876 else
11877 {
11878 if (checkTerrain)
11879 {
11880 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11881 if (groundContact != null)
11882 results.Add((ContactResult)groundContact);
11883 }
10782 11884
10783 if (entity == null) 11885 if (checkAgents)
10784 { 11886 {
10785 list.Add(UUID.Zero); 11887 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11888 foreach (ContactResult r in agentHits)
11889 results.Add(r);
11890 }
10786 11891
10787 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11892 if (checkPhysical || checkNonPhysical || detectPhantom)
10788 list.Add(0); 11893 {
11894 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
11895 foreach (ContactResult r in objectHits)
11896 results.Add(r);
11897 }
11898 }
10789 11899
10790 list.Add(result.Pos); 11900 results.Sort(delegate(ContactResult a, ContactResult b)
11901 {
11902 return a.Depth.CompareTo(b.Depth);
11903 });
11904
11905 int values = 0;
11906 SceneObjectGroup thisgrp = m_host.ParentGroup;
10791 11907
10792 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11908 foreach (ContactResult result in results)
10793 list.Add(result.Normal); 11909 {
11910 if (result.Depth > dist)
11911 continue;
10794 11912
10795 continue; //Can't find it, so add UUID.Zero 11913 // physics ray can return colisions with host prim
10796 } 11914 if (m_host.LocalId == result.ConsumerID)
11915 continue;
10797 11916
10798 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity && 11917 UUID itemID = UUID.Zero;
10799 ((ISceneChildEntity)intersection.obj).PhysActor == null) 11918 int linkNum = 0;
10800 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
10801 11919
10802 if (entity is SceneObjectPart) 11920 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
11921 // It's a prim!
11922 if (part != null)
10803 { 11923 {
10804 PhysicsActor pa = ((SceneObjectPart)entity).PhysActor; 11924 // dont detect members of same object ???
11925 if (part.ParentGroup == thisgrp)
11926 continue;
10805 11927
10806 if (pa != null && pa.IsPhysical) 11928 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10807 { 11929 itemID = part.ParentGroup.UUID;
10808 if (!checkPhysical)
10809 continue;
10810 }
10811 else 11930 else
10812 { 11931 itemID = part.UUID;
10813 if (!checkNonPhysical)
10814 continue;
10815 }
10816 }
10817 11932
10818 refcount++; 11933 linkNum = part.LinkNum;
10819 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11934 }
10820 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10821 else 11935 else
10822 list.Add(entity.UUID);
10823
10824 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10825 { 11936 {
10826 if (entity is SceneObjectPart) 11937 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10827 list.Add(((SceneObjectPart)entity).LinkNum); 11938 /// It it a boy? a girl?
10828 else 11939 if (sp != null)
10829 list.Add(0); 11940 itemID = sp.UUID;
10830 } 11941 }
10831 11942
10832 list.Add(result.Pos); 11943 list.Add(new LSL_String(itemID.ToString()));
11944 list.Add(new LSL_String(result.Pos.ToString()));
11945
11946 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
11947 list.Add(new LSL_Integer(linkNum));
10833 11948
10834 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11949 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10835 list.Add(result.Normal); 11950 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11951
11952 values++;
11953 if (values >= count)
11954 break;
10836 } 11955 }
10837 11956
10838 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11957 list.Add(new LSL_Integer(values));
10839 11958
10840 return list; 11959 return list;
10841 } 11960 }
@@ -10875,7 +11994,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10875 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 11994 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10876 if (!isAccount) return 0; 11995 if (!isAccount) return 0;
10877 if (estate.HasAccess(id)) return 1; 11996 if (estate.HasAccess(id)) return 1;
10878 if (estate.IsBanned(id)) 11997 if (estate.IsBanned(id, World.GetUserFlags(id)))
10879 estate.RemoveBan(id); 11998 estate.RemoveBan(id);
10880 estate.AddEstateUser(id); 11999 estate.AddEstateUser(id);
10881 break; 12000 break;
@@ -10894,14 +12013,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10894 break; 12013 break;
10895 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 12014 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10896 if (!isAccount) return 0; 12015 if (!isAccount) return 0;
10897 if (estate.IsBanned(id)) return 1; 12016 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10898 EstateBan ban = new EstateBan(); 12017 EstateBan ban = new EstateBan();
10899 ban.EstateID = estate.EstateID; 12018 ban.EstateID = estate.EstateID;
10900 ban.BannedUserID = id; 12019 ban.BannedUserID = id;
10901 estate.AddBan(ban); 12020 estate.AddBan(ban);
10902 break; 12021 break;
10903 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 12022 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10904 if (!isAccount || !estate.IsBanned(id)) return 0; 12023 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10905 estate.RemoveBan(id); 12024 estate.RemoveBan(id);
10906 break; 12025 break;
10907 default: return 0; 12026 default: return 0;
@@ -10930,7 +12049,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10930 return 16384; 12049 return 16384;
10931 } 12050 }
10932 12051
10933 public LSL_Integer llGetUsedMemory() 12052 public virtual LSL_Integer llGetUsedMemory()
10934 { 12053 {
10935 m_host.AddScriptLPS(1); 12054 m_host.AddScriptLPS(1);
10936 // The value returned for LSO scripts in SL 12055 // The value returned for LSO scripts in SL
@@ -10958,7 +12077,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10958 public void llSetSoundQueueing(int queue) 12077 public void llSetSoundQueueing(int queue)
10959 { 12078 {
10960 m_host.AddScriptLPS(1); 12079 m_host.AddScriptLPS(1);
10961 NotImplemented("llSetSoundQueueing");
10962 } 12080 }
10963 12081
10964 public void llCollisionSprite(string impact_sprite) 12082 public void llCollisionSprite(string impact_sprite)
@@ -10970,10 +12088,270 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10970 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12088 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10971 { 12089 {
10972 m_host.AddScriptLPS(1); 12090 m_host.AddScriptLPS(1);
10973 NotImplemented("llGodLikeRezObject"); 12091
12092 if (!World.Permissions.IsGod(m_host.OwnerID))
12093 NotImplemented("llGodLikeRezObject");
12094
12095 AssetBase rezAsset = World.AssetService.Get(inventory);
12096 if (rezAsset == null)
12097 {
12098 llSay(0, "Asset not found");
12099 return;
12100 }
12101
12102 SceneObjectGroup group = null;
12103
12104 try
12105 {
12106 string xmlData = Utils.BytesToString(rezAsset.Data);
12107 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12108 }
12109 catch
12110 {
12111 llSay(0, "Asset not found");
12112 return;
12113 }
12114
12115 if (group == null)
12116 {
12117 llSay(0, "Asset not found");
12118 return;
12119 }
12120
12121 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12122 group.RootPart.AttachOffset = group.AbsolutePosition;
12123
12124 group.ResetIDs();
12125
12126 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12127 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12128 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12129 group.ScheduleGroupForFullUpdate();
12130
12131 // objects rezzed with this method are die_at_edge by default.
12132 group.RootPart.SetDieAtEdge(true);
12133
12134 group.ResumeScripts();
12135
12136 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12137 "object_rez", new Object[] {
12138 new LSL_String(
12139 group.RootPart.UUID.ToString()) },
12140 new DetectParams[0]));
12141 }
12142
12143 public LSL_String llTransferLindenDollars(string destination, int amount)
12144 {
12145 UUID txn = UUID.Random();
12146
12147 Util.FireAndForget(delegate(object x)
12148 {
12149 int replycode = 0;
12150 string replydata = destination + "," + amount.ToString();
12151
12152 try
12153 {
12154 TaskInventoryItem item = m_item;
12155 if (item == null)
12156 {
12157 replydata = "SERVICE_ERROR";
12158 return;
12159 }
12160
12161 m_host.AddScriptLPS(1);
12162
12163 if (item.PermsGranter == UUID.Zero)
12164 {
12165 replydata = "MISSING_PERMISSION_DEBIT";
12166 return;
12167 }
12168
12169 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
12170 {
12171 replydata = "MISSING_PERMISSION_DEBIT";
12172 return;
12173 }
12174
12175 UUID toID = new UUID();
12176
12177 if (!UUID.TryParse(destination, out toID))
12178 {
12179 replydata = "INVALID_AGENT";
12180 return;
12181 }
12182
12183 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
12184
12185 if (money == null)
12186 {
12187 replydata = "TRANSFERS_DISABLED";
12188 return;
12189 }
12190
12191 bool result = money.ObjectGiveMoney(
12192 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
12193
12194 if (result)
12195 {
12196 replycode = 1;
12197 return;
12198 }
12199
12200 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
12201 }
12202 finally
12203 {
12204 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
12205 "transaction_result", new Object[] {
12206 new LSL_String(txn.ToString()),
12207 new LSL_Integer(replycode),
12208 new LSL_String(replydata) },
12209 new DetectParams[0]));
12210 }
12211 });
12212
12213 return txn.ToString();
10974 } 12214 }
10975 12215
10976 #endregion 12216 #endregion
12217
12218 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12219 {
12220 SceneObjectGroup group = m_host.ParentGroup;
12221
12222 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12223 return;
12224 if (group.IsAttachment)
12225 return;
12226
12227 if (frames.Data.Length > 0) // We are getting a new motion
12228 {
12229 if (group.RootPart.KeyframeMotion != null)
12230 group.RootPart.KeyframeMotion.Stop();
12231 group.RootPart.KeyframeMotion = null;
12232
12233 int idx = 0;
12234
12235 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12236 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12237
12238 while (idx < options.Data.Length)
12239 {
12240 int option = (int)options.GetLSLIntegerItem(idx++);
12241 int remain = options.Data.Length - idx;
12242
12243 switch (option)
12244 {
12245 case ScriptBaseClass.KFM_MODE:
12246 if (remain < 1)
12247 break;
12248 int modeval = (int)options.GetLSLIntegerItem(idx++);
12249 switch(modeval)
12250 {
12251 case ScriptBaseClass.KFM_FORWARD:
12252 mode = KeyframeMotion.PlayMode.Forward;
12253 break;
12254 case ScriptBaseClass.KFM_REVERSE:
12255 mode = KeyframeMotion.PlayMode.Reverse;
12256 break;
12257 case ScriptBaseClass.KFM_LOOP:
12258 mode = KeyframeMotion.PlayMode.Loop;
12259 break;
12260 case ScriptBaseClass.KFM_PING_PONG:
12261 mode = KeyframeMotion.PlayMode.PingPong;
12262 break;
12263 }
12264 break;
12265 case ScriptBaseClass.KFM_DATA:
12266 if (remain < 1)
12267 break;
12268 int dataval = (int)options.GetLSLIntegerItem(idx++);
12269 data = (KeyframeMotion.DataFormat)dataval;
12270 break;
12271 }
12272 }
12273
12274 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12275
12276 idx = 0;
12277
12278 int elemLength = 2;
12279 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12280 elemLength = 3;
12281
12282 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12283 while (idx < frames.Data.Length)
12284 {
12285 int remain = frames.Data.Length - idx;
12286
12287 if (remain < elemLength)
12288 break;
12289
12290 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12291 frame.Position = null;
12292 frame.Rotation = null;
12293
12294 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12295 {
12296 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12297 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12298 }
12299 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12300 {
12301 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12302 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12303 }
12304
12305 float tempf = (float)frames.GetLSLFloatItem(idx++);
12306 frame.TimeMS = (int)(tempf * 1000.0f);
12307
12308 keyframes.Add(frame);
12309 }
12310
12311 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12312 group.RootPart.KeyframeMotion.Start();
12313 }
12314 else
12315 {
12316 if (group.RootPart.KeyframeMotion == null)
12317 return;
12318
12319 if (options.Data.Length == 0)
12320 {
12321 group.RootPart.KeyframeMotion.Stop();
12322 return;
12323 }
12324
12325 int code = (int)options.GetLSLIntegerItem(0);
12326
12327 int idx = 0;
12328
12329 while (idx < options.Data.Length)
12330 {
12331 int option = (int)options.GetLSLIntegerItem(idx++);
12332 int remain = options.Data.Length - idx;
12333
12334 switch (option)
12335 {
12336 case ScriptBaseClass.KFM_COMMAND:
12337 int cmd = (int)options.GetLSLIntegerItem(idx++);
12338 switch (cmd)
12339 {
12340 case ScriptBaseClass.KFM_CMD_PLAY:
12341 group.RootPart.KeyframeMotion.Start();
12342 break;
12343 case ScriptBaseClass.KFM_CMD_STOP:
12344 group.RootPart.KeyframeMotion.Stop();
12345 break;
12346 case ScriptBaseClass.KFM_CMD_PAUSE:
12347 group.RootPart.KeyframeMotion.Pause();
12348 break;
12349 }
12350 break;
12351 }
12352 }
12353 }
12354 }
10977 } 12355 }
10978 12356
10979 public class NotecardCache 12357 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 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs
new file mode 100644
index 0000000..ab215f3
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs
@@ -0,0 +1,46 @@
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.Collections;
29using OpenSim.Region.ScriptEngine.Interfaces;
30
31using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
32using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
33using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
34using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
35using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
36using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
37using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
38
39namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
40{
41 public interface ICM_Api
42 {
43 string cmDetectedCountry(int num);
44 string cmGetAgentCountry(key key);
45 }
46}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index 7f5d1fe..048124d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -126,6 +126,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
126 LSL_Float llGetEnergy(); 126 LSL_Float llGetEnergy();
127 LSL_Vector llGetForce(); 127 LSL_Vector llGetForce();
128 LSL_Integer llGetFreeMemory(); 128 LSL_Integer llGetFreeMemory();
129 LSL_Integer llGetUsedMemory();
129 LSL_Integer llGetFreeURLs(); 130 LSL_Integer llGetFreeURLs();
130 LSL_Vector llGetGeometricCenter(); 131 LSL_Vector llGetGeometricCenter();
131 LSL_Float llGetGMTclock(); 132 LSL_Float llGetGMTclock();
@@ -149,6 +150,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
149 LSL_Vector llGetLocalPos(); 150 LSL_Vector llGetLocalPos();
150 LSL_Rotation llGetLocalRot(); 151 LSL_Rotation llGetLocalRot();
151 LSL_Float llGetMass(); 152 LSL_Float llGetMass();
153 LSL_Float llGetMassMKS();
152 LSL_Integer llGetMemoryLimit(); 154 LSL_Integer llGetMemoryLimit();
153 void llGetNextEmail(string address, string subject); 155 void llGetNextEmail(string address, string subject);
154 LSL_String llGetNotecardLine(string name, int line); 156 LSL_String llGetNotecardLine(string name, int line);
@@ -202,12 +204,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
202 LSL_String llGetTimestamp(); 204 LSL_String llGetTimestamp();
203 LSL_Vector llGetTorque(); 205 LSL_Vector llGetTorque();
204 LSL_Integer llGetUnixTime(); 206 LSL_Integer llGetUnixTime();
205 LSL_Integer llGetUsedMemory();
206 LSL_Vector llGetVel(); 207 LSL_Vector llGetVel();
207 LSL_Float llGetWallclock(); 208 LSL_Float llGetWallclock();
208 void llGiveInventory(string destination, string inventory); 209 void llGiveInventory(string destination, string inventory);
209 void llGiveInventoryList(string destination, string category, LSL_List inventory); 210 void llGiveInventoryList(string destination, string category, LSL_List inventory);
210 LSL_Integer llGiveMoney(string destination, int amount); 211 LSL_Integer llGiveMoney(string destination, int amount);
212 LSL_String llTransferLindenDollars(string destination, int amount);
211 void llGodLikeRezObject(string inventory, LSL_Vector pos); 213 void llGodLikeRezObject(string inventory, LSL_Vector pos);
212 LSL_Float llGround(LSL_Vector offset); 214 LSL_Float llGround(LSL_Vector offset);
213 LSL_Vector llGroundContour(LSL_Vector offset); 215 LSL_Vector llGroundContour(LSL_Vector offset);
@@ -355,6 +357,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
355 void llSetParcelMusicURL(string url); 357 void llSetParcelMusicURL(string url);
356 void llSetPayPrice(int price, LSL_List quick_pay_buttons); 358 void llSetPayPrice(int price, LSL_List quick_pay_buttons);
357 void llSetPos(LSL_Vector pos); 359 void llSetPos(LSL_Vector pos);
360 LSL_Integer llSetRegionPos(LSL_Vector pos);
358 LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules); 361 LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules);
359 void llSetPrimitiveParams(LSL_List rules); 362 void llSetPrimitiveParams(LSL_List rules);
360 void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules); 363 void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules);
@@ -403,6 +406,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
403 void llTargetOmega(LSL_Vector axis, double spinrate, double gain); 406 void llTargetOmega(LSL_Vector axis, double spinrate, double gain);
404 void llTargetRemove(int number); 407 void llTargetRemove(int number);
405 void llTeleportAgentHome(string agent); 408 void llTeleportAgentHome(string agent);
409 void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt);
406 void llTextBox(string avatar, string message, int chat_channel); 410 void llTextBox(string avatar, string message, int chat_channel);
407 LSL_String llToLower(string source); 411 LSL_String llToLower(string source);
408 LSL_String llToUpper(string source); 412 LSL_String llToUpper(string source);
@@ -419,9 +423,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
419 LSL_Vector llWind(LSL_Vector offset); 423 LSL_Vector llWind(LSL_Vector offset);
420 LSL_String llXorBase64Strings(string str1, string str2); 424 LSL_String llXorBase64Strings(string str1, string str2);
421 LSL_String llXorBase64StringsCorrect(string str1, string str2); 425 LSL_String llXorBase64StringsCorrect(string str1, string str2);
422 void print(string str); 426 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link);
427 void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density);
423 428
424 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 429 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
425 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 430 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
431 void llSetKeyframedMotion(LSL_List frames, LSL_List options);
426 } 432 }
427} 433}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index e92518d..7382495 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -85,7 +85,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
85 // Avatar Info Commands 85 // Avatar Info Commands
86 string osGetAgentIP(string agent); 86 string osGetAgentIP(string agent);
87 LSL_List osGetAgents(); 87 LSL_List osGetAgents();
88 88
89 // Teleport commands 89 // Teleport commands
90 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 90 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
91 void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 91 void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs
new file mode 100644
index 0000000..4132dfa
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs
@@ -0,0 +1,71 @@
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.Runtime.Remoting.Lifetime;
30using System.Threading;
31using System.Reflection;
32using System.Collections;
33using System.Collections.Generic;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
38using integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
39using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
40using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
41using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
42using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
43using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
44using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
45using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
46
47namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
48{
49 public partial class ScriptBaseClass : MarshalByRefObject
50 {
51 public ICM_Api m_CM_Functions;
52
53 public void ApiTypeCM(IScriptApi api)
54 {
55 if (!(api is ICM_Api))
56 return;
57
58 m_CM_Functions = (ICM_Api)api;
59 }
60
61 public string cmDetectedCountry(int num)
62 {
63 return m_CM_Functions.cmDetectedCountry(num);
64 }
65
66 public string cmGetAgentCountry(key key)
67 {
68 return m_CM_Functions.cmGetAgentCountry(key);
69 }
70 }
71}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
index 9615315..943d7a2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; //for [DebuggerNonUserCode]
30using System.Reflection; 31using System.Reflection;
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using OpenSim.Region.ScriptEngine.Shared; 33using OpenSim.Region.ScriptEngine.Shared;
@@ -132,6 +133,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
132 return (eventFlags); 133 return (eventFlags);
133 } 134 }
134 135
136 [DebuggerNonUserCode]
135 public void ExecuteEvent(string state, string FunctionName, object[] args) 137 public void ExecuteEvent(string state, string FunctionName, object[] args)
136 { 138 {
137 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. 139 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index b6c21e6..5c6ad8a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -94,6 +94,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
94 public const int AGENT_CROUCHING = 1024; 94 public const int AGENT_CROUCHING = 1024;
95 public const int AGENT_BUSY = 2048; 95 public const int AGENT_BUSY = 2048;
96 public const int AGENT_ALWAYS_RUN = 4096; 96 public const int AGENT_ALWAYS_RUN = 4096;
97 public const int AGENT_MALE = 8192;
97 98
98 //Particle Systems 99 //Particle Systems
99 public const int PSYS_PART_INTERP_COLOR_MASK = 1; 100 public const int PSYS_PART_INTERP_COLOR_MASK = 1;
@@ -282,6 +283,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
282 public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART 283 public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART
283 public const int CHANGED_MEDIA = 2048; 284 public const int CHANGED_MEDIA = 2048;
284 public const int CHANGED_ANIMATION = 16384; 285 public const int CHANGED_ANIMATION = 16384;
286 public const int CHANGED_POSITION = 32768;
285 public const int TYPE_INVALID = 0; 287 public const int TYPE_INVALID = 0;
286 public const int TYPE_INTEGER = 1; 288 public const int TYPE_INTEGER = 1;
287 public const int TYPE_FLOAT = 2; 289 public const int TYPE_FLOAT = 2;
@@ -586,6 +588,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
586 public const int PRIM_MEDIA_PERM_OWNER = 1; 588 public const int PRIM_MEDIA_PERM_OWNER = 1;
587 public const int PRIM_MEDIA_PERM_GROUP = 2; 589 public const int PRIM_MEDIA_PERM_GROUP = 2;
588 public const int PRIM_MEDIA_PERM_ANYONE = 4; 590 public const int PRIM_MEDIA_PERM_ANYONE = 4;
591
592 public const int PRIM_PHYSICS_SHAPE_TYPE = 30;
593 public const int PRIM_PHYSICS_SHAPE_PRIM = 0;
594 public const int PRIM_PHYSICS_SHAPE_CONVEX = 2;
595 public const int PRIM_PHYSICS_SHAPE_NONE = 1;
596
597 public const int PRIM_PHYSICS_MATERIAL = 31;
598 public const int DENSITY = 1;
599 public const int FRICTION = 2;
600 public const int RESTITUTION = 4;
601 public const int GRAVITY_MULTIPLIER = 8;
589 602
590 // extra constants for llSetPrimMediaParams 603 // extra constants for llSetPrimMediaParams
591 public static readonly LSLInteger LSL_STATUS_OK = new LSLInteger(0); 604 public static readonly LSLInteger LSL_STATUS_OK = new LSLInteger(0);
@@ -659,5 +672,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
659 public static readonly LSLInteger RCERR_UNKNOWN = -1; 672 public static readonly LSLInteger RCERR_UNKNOWN = -1;
660 public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2; 673 public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2;
661 public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3; 674 public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3;
675
676 public const int KFM_MODE = 1;
677 public const int KFM_LOOP = 1;
678 public const int KFM_REVERSE = 3;
679 public const int KFM_FORWARD = 0;
680 public const int KFM_PING_PONG = 2;
681 public const int KFM_DATA = 2;
682 public const int KFM_TRANSLATION = 2;
683 public const int KFM_ROTATION = 1;
684 public const int KFM_COMMAND = 0;
685 public const int KFM_CMD_PLAY = 0;
686 public const int KFM_CMD_STOP = 1;
687 public const int KFM_CMD_PAUSE = 2;
662 } 688 }
663} 689}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index c0bf29c..2d23d30 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Diagnostics; //for [DebuggerNonUserCode]
29using System.Runtime.Remoting.Lifetime; 30using System.Runtime.Remoting.Lifetime;
30using System.Threading; 31using System.Threading;
31using System.Reflection; 32using System.Reflection;
@@ -164,6 +165,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
164 m_LSL_Functions.llBreakLink(linknum); 165 m_LSL_Functions.llBreakLink(linknum);
165 } 166 }
166 167
168 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
169 {
170 return m_LSL_Functions.llCastRay(start, end, options);
171 }
172
167 public LSL_Integer llCeil(double f) 173 public LSL_Integer llCeil(double f)
168 { 174 {
169 return m_LSL_Functions.llCeil(f); 175 return m_LSL_Functions.llCeil(f);
@@ -314,6 +320,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
314 m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel); 320 m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel);
315 } 321 }
316 322
323 [DebuggerNonUserCode]
317 public void llDie() 324 public void llDie()
318 { 325 {
319 m_LSL_Functions.llDie(); 326 m_LSL_Functions.llDie();
@@ -474,6 +481,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
474 return m_LSL_Functions.llGetFreeMemory(); 481 return m_LSL_Functions.llGetFreeMemory();
475 } 482 }
476 483
484 public LSL_Integer llGetUsedMemory()
485 {
486 return m_LSL_Functions.llGetUsedMemory();
487 }
488
477 public LSL_Integer llGetFreeURLs() 489 public LSL_Integer llGetFreeURLs()
478 { 490 {
479 return m_LSL_Functions.llGetFreeURLs(); 491 return m_LSL_Functions.llGetFreeURLs();
@@ -579,6 +591,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
579 return m_LSL_Functions.llGetMass(); 591 return m_LSL_Functions.llGetMass();
580 } 592 }
581 593
594 public LSL_Float llGetMassMKS()
595 {
596 return m_LSL_Functions.llGetMassMKS();
597 }
598
582 public LSL_Integer llGetMemoryLimit() 599 public LSL_Integer llGetMemoryLimit()
583 { 600 {
584 return m_LSL_Functions.llGetMemoryLimit(); 601 return m_LSL_Functions.llGetMemoryLimit();
@@ -844,11 +861,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
844 return m_LSL_Functions.llGetUnixTime(); 861 return m_LSL_Functions.llGetUnixTime();
845 } 862 }
846 863
847 public LSL_Integer llGetUsedMemory()
848 {
849 return m_LSL_Functions.llGetUsedMemory();
850 }
851
852 public LSL_Vector llGetVel() 864 public LSL_Vector llGetVel()
853 { 865 {
854 return m_LSL_Functions.llGetVel(); 866 return m_LSL_Functions.llGetVel();
@@ -874,6 +886,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
874 return m_LSL_Functions.llGiveMoney(destination, amount); 886 return m_LSL_Functions.llGiveMoney(destination, amount);
875 } 887 }
876 888
889 public LSL_String llTransferLindenDollars(string destination, int amount)
890 {
891 return m_LSL_Functions.llTransferLindenDollars(destination, amount);
892 }
893
877 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 894 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
878 { 895 {
879 m_LSL_Functions.llGodLikeRezObject(inventory, pos); 896 m_LSL_Functions.llGodLikeRezObject(inventory, pos);
@@ -1598,6 +1615,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1598 m_LSL_Functions.llSetPos(pos); 1615 m_LSL_Functions.llSetPos(pos);
1599 } 1616 }
1600 1617
1618 public LSL_Integer llSetRegionPos(LSL_Vector pos)
1619 {
1620 return m_LSL_Functions.llSetRegionPos(pos);
1621 }
1622
1601 public void llSetPrimitiveParams(LSL_List rules) 1623 public void llSetPrimitiveParams(LSL_List rules)
1602 { 1624 {
1603 m_LSL_Functions.llSetPrimitiveParams(rules); 1625 m_LSL_Functions.llSetPrimitiveParams(rules);
@@ -1833,6 +1855,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1833 m_LSL_Functions.llTargetRemove(number); 1855 m_LSL_Functions.llTargetRemove(number);
1834 } 1856 }
1835 1857
1858 public void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt)
1859 {
1860 m_LSL_Functions.llTeleportAgent(agent, simname, pos, lookAt);
1861 }
1862
1836 public void llTeleportAgentHome(string agent) 1863 public void llTeleportAgentHome(string agent)
1837 { 1864 {
1838 m_LSL_Functions.llTeleportAgentHome(agent); 1865 m_LSL_Functions.llTeleportAgentHome(agent);
@@ -1948,9 +1975,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1948 return m_LSL_Functions.llClearLinkMedia(link, face); 1975 return m_LSL_Functions.llClearLinkMedia(link, face);
1949 } 1976 }
1950 1977
1951 public void print(string str) 1978 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
1979 {
1980 return m_LSL_Functions.llGetLinkNumberOfSides(link);
1981 }
1982
1983 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
1984 {
1985 m_LSL_Functions.llSetKeyframedMotion(frames, options);
1986 }
1987
1988 public void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density)
1952 { 1989 {
1953 m_LSL_Functions.print(str); 1990 m_LSL_Functions.llSetPhysicsMaterial(material_bits, material_gravity_modifier, material_restitution, material_friction, material_density);
1954 } 1991 }
1955 } 1992 }
1956} 1993}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
index 143b497..2e27f16 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
@@ -72,9 +72,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
72 { 72 {
73 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target); 73 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target);
74 } 74 }
75
75 public void lsClearWindlightScene() 76 public void lsClearWindlightScene()
76 { 77 {
77 m_LS_Functions.lsClearWindlightScene(); 78 m_LS_Functions.lsClearWindlightScene();
78 } 79 }
80
81 public LSL_List cmGetWindlightScene(LSL_List rules)
82 {
83 return m_LS_Functions.lsGetWindlightScene(rules);
84 }
85
86 public int cmSetWindlightScene(LSL_List rules)
87 {
88 return m_LS_Functions.lsSetWindlightScene(rules);
89 }
90
91 public int cmSetWindlightSceneTargeted(LSL_List rules, key target)
92 {
93 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target);
94 }
95
96 public void cmClearWindlightScene()
97 {
98 m_LS_Functions.lsClearWindlightScene();
99 }
79 } 100 }
80} 101}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
index edbbc2a..b138da3 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
@@ -33,6 +33,7 @@ using System.Threading;
33using System.Reflection; 33using System.Reflection;
34using System.Collections; 34using System.Collections;
35using System.Collections.Generic; 35using System.Collections.Generic;
36using System.Diagnostics; //for [DebuggerNonUserCode]
36using OpenSim.Region.ScriptEngine.Interfaces; 37using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared; 38using OpenSim.Region.ScriptEngine.Shared;
38using OpenSim.Region.ScriptEngine.Shared.Api.Runtime; 39using OpenSim.Region.ScriptEngine.Shared.Api.Runtime;
@@ -90,6 +91,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
90 return (int)m_Executor.GetStateEventFlags(state); 91 return (int)m_Executor.GetStateEventFlags(state);
91 } 92 }
92 93
94 [DebuggerNonUserCode]
93 public void ExecuteEvent(string state, string FunctionName, object[] args) 95 public void ExecuteEvent(string state, string FunctionName, object[] args)
94 { 96 {
95 m_Executor.ExecuteEvent(state, FunctionName, args); 97 m_Executor.ExecuteEvent(state, FunctionName, args);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 8cebb4a..7e7e278 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -35,6 +35,7 @@ using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Region.CoreModules; 36using OpenSim.Region.CoreModules;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces;
38 39
39namespace OpenSim.Region.ScriptEngine.Shared 40namespace OpenSim.Region.ScriptEngine.Shared
40{ 41{
@@ -95,6 +96,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
95 Type = 0; 96 Type = 0;
96 Velocity = new LSL_Types.Vector3(); 97 Velocity = new LSL_Types.Vector3();
97 initializeSurfaceTouch(); 98 initializeSurfaceTouch();
99 Country = String.Empty;
98 } 100 }
99 101
100 public UUID Key; 102 public UUID Key;
@@ -126,6 +128,8 @@ namespace OpenSim.Region.ScriptEngine.Shared
126 private int touchFace; 128 private int touchFace;
127 public int TouchFace { get { return touchFace; } } 129 public int TouchFace { get { return touchFace; } }
128 130
131 public string Country;
132
129 // This can be done in two places including the constructor 133 // This can be done in two places including the constructor
130 // so be carefull what gets added here 134 // so be carefull what gets added here
131 private void initializeSurfaceTouch() 135 private void initializeSurfaceTouch()
@@ -173,6 +177,10 @@ namespace OpenSim.Region.ScriptEngine.Shared
173 return; 177 return;
174 178
175 Name = presence.Firstname + " " + presence.Lastname; 179 Name = presence.Firstname + " " + presence.Lastname;
180 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, Key);
181 if (account != null)
182 Country = account.UserCountry;
183
176 Owner = Key; 184 Owner = Key;
177 Position = new LSL_Types.Vector3( 185 Position = new LSL_Types.Vector3(
178 presence.AbsolutePosition.X, 186 presence.AbsolutePosition.X,
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 329e361..1c59d45 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.IO; 29using System.IO;
30using System.Diagnostics; //for [DebuggerNonUserCode]
30using System.Runtime.Remoting; 31using System.Runtime.Remoting;
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using System.Threading; 33using System.Threading;
@@ -218,13 +219,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
218 219
219 if (part != null) 220 if (part != null)
220 { 221 {
221 lock (part.TaskInventory) 222 part.TaskInventory.LockItemsForRead(true);
223 if (part.TaskInventory.ContainsKey(ItemID))
222 { 224 {
223 if (part.TaskInventory.ContainsKey(ItemID)) 225 ScriptTask = part.TaskInventory[ItemID];
224 {
225 ScriptTask = part.TaskInventory[ItemID];
226 }
227 } 226 }
227 part.TaskInventory.LockItemsForRead(false);
228 } 228 }
229 229
230 ApiManager am = new ApiManager(); 230 ApiManager am = new ApiManager();
@@ -416,14 +416,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
416 { 416 {
417 int permsMask; 417 int permsMask;
418 UUID permsGranter; 418 UUID permsGranter;
419 lock (part.TaskInventory) 419 part.TaskInventory.LockItemsForRead(true);
420 if (!part.TaskInventory.ContainsKey(ItemID))
420 { 421 {
421 if (!part.TaskInventory.ContainsKey(ItemID)) 422 part.TaskInventory.LockItemsForRead(false);
422 return; 423 return;
423
424 permsGranter = part.TaskInventory[ItemID].PermsGranter;
425 permsMask = part.TaskInventory[ItemID].PermsMask;
426 } 424 }
425 permsGranter = part.TaskInventory[ItemID].PermsGranter;
426 permsMask = part.TaskInventory[ItemID].PermsMask;
427 part.TaskInventory.LockItemsForRead(false);
427 428
428 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) 429 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
429 { 430 {
@@ -551,6 +552,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
551 return true; 552 return true;
552 } 553 }
553 554
555 [DebuggerNonUserCode] //Prevents the debugger from farting in this function
554 public void SetState(string state) 556 public void SetState(string state)
555 { 557 {
556 if (state == State) 558 if (state == State)
@@ -562,7 +564,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
562 new DetectParams[0])); 564 new DetectParams[0]));
563 PostEvent(new EventParams("state_entry", new Object[0], 565 PostEvent(new EventParams("state_entry", new Object[0],
564 new DetectParams[0])); 566 new DetectParams[0]));
565 567
566 throw new EventAbortException(); 568 throw new EventAbortException();
567 } 569 }
568 570
@@ -652,45 +654,45 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
652 /// <returns></returns> 654 /// <returns></returns>
653 public object EventProcessor() 655 public object EventProcessor()
654 { 656 {
657 EventParams data = null;
655 // We check here as the thread stopping this instance from running may itself hold the m_Script lock. 658 // We check here as the thread stopping this instance from running may itself hold the m_Script lock.
656 if (!Running) 659 if (!Running)
657 return 0; 660 return 0;
658 661
659 lock (m_Script)
660 {
661// m_log.DebugFormat("[XEngine]: EventProcessor() invoked for {0}.{1}", PrimName, ScriptName); 662// m_log.DebugFormat("[XEngine]: EventProcessor() invoked for {0}.{1}", PrimName, ScriptName);
662 663
663 if (Suspended) 664 if (Suspended)
664 return 0; 665 return 0;
665
666 EventParams data = null;
667 666
668 lock (EventQueue) 667 lock (EventQueue)
668 {
669 data = (EventParams) EventQueue.Dequeue();
670 if (data == null) // Shouldn't happen
669 { 671 {
670 data = (EventParams)EventQueue.Dequeue(); 672 if (EventQueue.Count > 0 && Running && !ShuttingDown)
671 if (data == null) // Shouldn't happen
672 { 673 {
673 if (EventQueue.Count > 0 && Running && !ShuttingDown) 674 m_CurrentWorkItem = Engine.QueueEventHandler(this);
674 {
675 m_CurrentWorkItem = Engine.QueueEventHandler(this);
676 }
677 else
678 {
679 m_CurrentWorkItem = null;
680 }
681 return 0;
682 } 675 }
683 676 else
684 if (data.EventName == "timer")
685 m_TimerQueued = false;
686 if (data.EventName == "control")
687 { 677 {
688 if (m_ControlEventsInQueue > 0) 678 m_CurrentWorkItem = null;
689 m_ControlEventsInQueue--;
690 } 679 }
691 if (data.EventName == "collision") 680 return 0;
692 m_CollisionInQueue = false;
693 } 681 }
682
683 if (data.EventName == "timer")
684 m_TimerQueued = false;
685 if (data.EventName == "control")
686 {
687 if (m_ControlEventsInQueue > 0)
688 m_ControlEventsInQueue--;
689 }
690 if (data.EventName == "collision")
691 m_CollisionInQueue = false;
692 }
693
694 lock(m_Script)
695 {
694 696
695// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this); 697// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this);
696 698
@@ -845,6 +847,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
845 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID); 847 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
846 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0; 848 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0;
847 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero; 849 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero;
850 part.CollisionSound = UUID.Zero;
848 AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID); 851 AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID);
849 EventQueue.Clear(); 852 EventQueue.Clear();
850 m_Script.ResetVars(); 853 m_Script.ResetVars();
@@ -859,6 +862,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
859 new Object[0], new DetectParams[0])); 862 new Object[0], new DetectParams[0]));
860 } 863 }
861 864
865 [DebuggerNonUserCode] //Stops the VS debugger from farting in this function
862 public void ApiResetScript() 866 public void ApiResetScript()
863 { 867 {
864 // bool running = Running; 868 // bool running = Running;
@@ -870,6 +874,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
870 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID); 874 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
871 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0; 875 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0;
872 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero; 876 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero;
877 part.CollisionSound = UUID.Zero;
873 AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID); 878 AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID);
874 879
875 EventQueue.Clear(); 880 EventQueue.Clear();
@@ -890,10 +895,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
890 895
891 public Dictionary<string, object> GetVars() 896 public Dictionary<string, object> GetVars()
892 { 897 {
893 if (m_Script != null) 898 return m_Script.GetVars();
894 return m_Script.GetVars();
895 else
896 return new Dictionary<string, object>();
897 } 899 }
898 900
899 public void SetVars(Dictionary<string, object> vars) 901 public void SetVars(Dictionary<string, object> vars)
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index d848b2a..8adf4c5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -83,19 +83,19 @@ namespace OpenSim.Region.ScriptEngine.Shared
83 83
84 public override string ToString() 84 public override string ToString()
85 { 85 {
86 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", x, y, z); 86 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}>", x, y, z);
87 return s; 87 return s;
88 } 88 }
89 89
90 public static explicit operator LSLString(Vector3 vec) 90 public static explicit operator LSLString(Vector3 vec)
91 { 91 {
92 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z); 92 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}>", vec.x, vec.y, vec.z);
93 return new LSLString(s); 93 return new LSLString(s);
94 } 94 }
95 95
96 public static explicit operator string(Vector3 vec) 96 public static explicit operator string(Vector3 vec)
97 { 97 {
98 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z); 98 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}>", vec.x, vec.y, vec.z);
99 return s; 99 return s;
100 } 100 }
101 101
@@ -342,19 +342,19 @@ namespace OpenSim.Region.ScriptEngine.Shared
342 342
343 public override string ToString() 343 public override string ToString()
344 { 344 {
345 string st=String.Format(Culture.FormatProvider, "<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", x, y, z, s); 345 string st=String.Format(Culture.FormatProvider, "<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", x, y, z, s);
346 return st; 346 return st;
347 } 347 }
348 348
349 public static explicit operator string(Quaternion r) 349 public static explicit operator string(Quaternion r)
350 { 350 {
351 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s); 351 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", r.x, r.y, r.z, r.s);
352 return s; 352 return s;
353 } 353 }
354 354
355 public static explicit operator LSLString(Quaternion r) 355 public static explicit operator LSLString(Quaternion r)
356 { 356 {
357 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s); 357 string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", r.x, r.y, r.z, r.s);
358 return new LSLString(s); 358 return new LSLString(s);
359 } 359 }
360 360
@@ -459,6 +459,8 @@ namespace OpenSim.Region.ScriptEngine.Shared
459 size += 64; 459 size += 64;
460 else if (o is int) 460 else if (o is int)
461 size += 4; 461 size += 4;
462 else if (o is uint)
463 size += 4;
462 else if (o is string) 464 else if (o is string)
463 size += ((string)o).Length; 465 size += ((string)o).Length;
464 else if (o is float) 466 else if (o is float)
@@ -613,24 +615,16 @@ namespace OpenSim.Region.ScriptEngine.Shared
613 615
614 public static bool operator ==(list a, list b) 616 public static bool operator ==(list a, list b)
615 { 617 {
616 int la = -1; 618 int la = a.Length;
617 int lb = -1; 619 int lb = b.Length;
618 try { la = a.Length; }
619 catch (NullReferenceException) { }
620 try { lb = b.Length; }
621 catch (NullReferenceException) { }
622 620
623 return la == lb; 621 return la == lb;
624 } 622 }
625 623
626 public static bool operator !=(list a, list b) 624 public static bool operator !=(list a, list b)
627 { 625 {
628 int la = -1; 626 int la = a.Length;
629 int lb = -1; 627 int lb = b.Length;
630 try { la = a.Length; }
631 catch (NullReferenceException) { }
632 try {lb = b.Length;}
633 catch (NullReferenceException) { }
634 628
635 return la != lb; 629 return la != lb;
636 } 630 }
@@ -864,7 +858,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
864 ret = Math.Sign(Quaternion.Mag(l) - Quaternion.Mag(r)); 858 ret = Math.Sign(Quaternion.Mag(l) - Quaternion.Mag(r));
865 } 859 }
866 860
867 if (ascending == 0) 861 if (ascending != 1)
868 { 862 {
869 ret = 0 - ret; 863 ret = 0 - ret;
870 } 864 }
@@ -897,6 +891,9 @@ namespace OpenSim.Region.ScriptEngine.Shared
897 stride = 1; 891 stride = 1;
898 } 892 }
899 893
894 if ((Data.Length % stride) != 0)
895 return new list(ret);
896
900 // we can optimize here in the case where stride == 1 and the list 897 // we can optimize here in the case where stride == 1 and the list
901 // consists of homogeneous types 898 // consists of homogeneous types
902 899
@@ -916,7 +913,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
916 if (homogeneous) 913 if (homogeneous)
917 { 914 {
918 Array.Sort(ret, new HomogeneousComparer()); 915 Array.Sort(ret, new HomogeneousComparer());
919 if (ascending == 0) 916 if (ascending != 1)
920 { 917 {
921 Array.Reverse(ret); 918 Array.Reverse(ret);
922 } 919 }
@@ -1064,7 +1061,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
1064 { 1061 {
1065 list ret = new list(); 1062 list ret = new list();
1066 double entry; 1063 double entry;
1067 for (int i = 0; i < src.Data.Length - 1; i++) 1064 for (int i = 0; i < src.Data.Length; i++)
1068 { 1065 {
1069 if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry)) 1066 if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
1070 { 1067 {