aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
Diffstat (limited to '')
-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.cs3002
-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.cs9
-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.cs46
-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
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs362
19 files changed, 2928 insertions, 1075 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 89f2068..713f832 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()
@@ -2232,16 +2498,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2232 { 2498 {
2233 m_host.AddScriptLPS(1); 2499 m_host.AddScriptLPS(1);
2234 2500
2235 Vector3 vel; 2501 Vector3 vel = Vector3.Zero;
2236 2502
2237 if (m_host.ParentGroup.IsAttachment) 2503 if (m_host.ParentGroup.IsAttachment)
2238 { 2504 {
2239 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); 2505 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2240 vel = avatar.Velocity; 2506 if (avatar != null)
2507 vel = avatar.Velocity;
2241 } 2508 }
2242 else 2509 else
2243 { 2510 {
2244 vel = m_host.Velocity; 2511 vel = m_host.ParentGroup.RootPart.Velocity;
2245 } 2512 }
2246 2513
2247 return new LSL_Vector(vel.X, vel.Y, vel.Z); 2514 return new LSL_Vector(vel.X, vel.Y, vel.Z);
@@ -2790,8 +3057,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2790 3057
2791 if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) 3058 if (pa != null && pa.IsPhysical && llvel != Vector3.Zero)
2792 { 3059 {
2793 //Recoil. 3060 // recoil
2794 llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); 3061 llvel *= -groupmass;
3062 llApplyImpulse(new LSL_Vector(llvel.X, llvel.Y,llvel.Z), 0);
2795 } 3063 }
2796 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3064 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
2797 return; 3065 return;
@@ -2813,35 +3081,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2813 public void llLookAt(LSL_Vector target, double strength, double damping) 3081 public void llLookAt(LSL_Vector target, double strength, double damping)
2814 { 3082 {
2815 m_host.AddScriptLPS(1); 3083 m_host.AddScriptLPS(1);
2816 // Determine where we are looking from
2817 LSL_Vector from = llGetPos();
2818 3084
2819 // Work out the normalised vector from the source to the target 3085 // Get the normalized vector to the target
2820 LSL_Vector delta = llVecNorm(target - from); 3086 LSL_Vector d1 = llVecNorm(target - llGetPos());
2821 LSL_Vector angle = new LSL_Vector(0,0,0);
2822 3087
2823 // Calculate the yaw 3088 // Get the bearing (yaw)
2824 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3089 LSL_Vector a1 = new LSL_Vector(0,0,0);
2825 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3090 a1.z = llAtan2(d1.y, d1.x);
2826 3091
2827 // Calculate pitch 3092 // Get the elevation (pitch)
2828 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3093 LSL_Vector a2 = new LSL_Vector(0,0,0);
3094 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2829 3095
2830 // we need to convert from a vector describing 3096 LSL_Rotation r1 = llEuler2Rot(a1);
2831 // the angles of rotation in radians into rotation value 3097 LSL_Rotation r2 = llEuler2Rot(a2);
2832 LSL_Rotation rot = llEuler2Rot(angle); 3098 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 3099
2838 if (strength == 0 || pa == null || !pa.IsPhysical) 3100 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2839 { 3101 {
2840 llSetRot(rot); 3102 // Do nothing if either value is 0 (this has been checked in SL)
3103 if (strength <= 0.0 || damping <= 0.0)
3104 return;
3105
3106 llSetRot(r3 * r2 * r1);
2841 } 3107 }
2842 else 3108 else
2843 { 3109 {
2844 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3110 if (strength == 0)
3111 {
3112 llSetRot(r3 * r2 * r1);
3113 return;
3114 }
3115
3116 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2845 } 3117 }
2846 } 3118 }
2847 3119
@@ -2887,17 +3159,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2887 } 3159 }
2888 else 3160 else
2889 { 3161 {
2890 if (m_host.IsRoot) 3162 // new SL always returns object mass
2891 { 3163// if (m_host.IsRoot)
3164// {
2892 return m_host.ParentGroup.GetMass(); 3165 return m_host.ParentGroup.GetMass();
2893 } 3166// }
2894 else 3167// else
2895 { 3168// {
2896 return m_host.GetMass(); 3169// return m_host.GetMass();
2897 } 3170// }
2898 } 3171 }
2899 } 3172 }
2900 3173
3174
3175 public LSL_Float llGetMassMKS()
3176 {
3177 return 100f * llGetMass();
3178 }
3179
2901 public void llCollisionFilter(string name, string id, int accept) 3180 public void llCollisionFilter(string name, string id, int accept)
2902 { 3181 {
2903 m_host.AddScriptLPS(1); 3182 m_host.AddScriptLPS(1);
@@ -2972,7 +3251,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2972 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3251 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
2973 3252
2974 if (attachmentsModule != null) 3253 if (attachmentsModule != null)
2975 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false); 3254 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true);
2976 else 3255 else
2977 return false; 3256 return false;
2978 } 3257 }
@@ -3005,9 +3284,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3005 { 3284 {
3006 m_host.AddScriptLPS(1); 3285 m_host.AddScriptLPS(1);
3007 3286
3008// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3009// return;
3010
3011 if (m_item.PermsGranter != m_host.OwnerID) 3287 if (m_item.PermsGranter != m_host.OwnerID)
3012 return; 3288 return;
3013 3289
@@ -3050,6 +3326,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3050 3326
3051 public void llInstantMessage(string user, string message) 3327 public void llInstantMessage(string user, string message)
3052 { 3328 {
3329 UUID result;
3330 if (!UUID.TryParse(user, out result))
3331 {
3332 ShoutError("An invalid key was passed to llInstantMessage");
3333 ScriptSleep(2000);
3334 return;
3335 }
3336
3337
3053 m_host.AddScriptLPS(1); 3338 m_host.AddScriptLPS(1);
3054 3339
3055 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3340 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3064,14 +3349,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3064 UUID friendTransactionID = UUID.Random(); 3349 UUID friendTransactionID = UUID.Random();
3065 3350
3066 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3351 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3067 3352
3068 GridInstantMessage msg = new GridInstantMessage(); 3353 GridInstantMessage msg = new GridInstantMessage();
3069 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3354 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3070 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3355 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3071 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3356 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); 3357// 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()); 3358// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3074 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3359// DateTime dt = DateTime.UtcNow;
3360//
3361// // Ticks from UtcNow, but make it look like local. Evil, huh?
3362// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3363//
3364// try
3365// {
3366// // Convert that to the PST timezone
3367// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3368// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3369// }
3370// catch
3371// {
3372// // No logging here, as it could be VERY spammy
3373// }
3374//
3375// // And make it look local again to fool the unix time util
3376// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3377
3378 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3379
3075 //if (client != null) 3380 //if (client != null)
3076 //{ 3381 //{
3077 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3382 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3085,12 +3390,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3085 msg.message = message.Substring(0, 1024); 3390 msg.message = message.Substring(0, 1024);
3086 else 3391 else
3087 msg.message = message; 3392 msg.message = message;
3088 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3393 msg.dialog = (byte)19; // MessageFromObject
3089 msg.fromGroup = false;// fromGroup; 3394 msg.fromGroup = false;// fromGroup;
3090 msg.offline = (byte)0; //offline; 3395 msg.offline = (byte)0; //offline;
3091 msg.ParentEstateID = 0; //ParentEstateID; 3396 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3092 msg.Position = new Vector3(m_host.AbsolutePosition); 3397 msg.Position = new Vector3(m_host.AbsolutePosition);
3093 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3398 msg.RegionID = World.RegionInfo.RegionID.Guid;
3094 msg.binaryBucket 3399 msg.binaryBucket
3095 = Util.StringToBytes256( 3400 = Util.StringToBytes256(
3096 "{0}/{1}/{2}/{3}", 3401 "{0}/{1}/{2}/{3}",
@@ -3118,7 +3423,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3118 } 3423 }
3119 3424
3120 emailModule.SendEmail(m_host.UUID, address, subject, message); 3425 emailModule.SendEmail(m_host.UUID, address, subject, message);
3121 llSleep(EMAIL_PAUSE_TIME); 3426 ScriptSleep(EMAIL_PAUSE_TIME * 1000);
3122 } 3427 }
3123 3428
3124 public void llGetNextEmail(string address, string subject) 3429 public void llGetNextEmail(string address, string subject)
@@ -3362,15 +3667,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3362 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3667 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3363 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3668 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3364 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3669 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3670 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3365 ScriptBaseClass.PERMISSION_ATTACH; 3671 ScriptBaseClass.PERMISSION_ATTACH;
3366 3672
3367 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3673 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3368 { 3674 {
3369 lock (m_host.TaskInventory) 3675 m_host.TaskInventory.LockItemsForWrite(true);
3370 { 3676 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3371 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3677 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3372 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3678 m_host.TaskInventory.LockItemsForWrite(false);
3373 }
3374 3679
3375 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3680 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3376 "run_time_permissions", new Object[] { 3681 "run_time_permissions", new Object[] {
@@ -3380,28 +3685,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3380 return; 3685 return;
3381 } 3686 }
3382 } 3687 }
3383 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3688 else
3384 { 3689 {
3385 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3690 bool sitting = false;
3386 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3691 if (m_host.SitTargetAvatar == agentID)
3387 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3692 {
3388 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3693 sitting = true;
3389 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3694 }
3695 else
3696 {
3697 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3698 {
3699 if (p.SitTargetAvatar == agentID)
3700 sitting = true;
3701 }
3702 }
3390 3703
3391 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3704 if (sitting)
3392 { 3705 {
3393 lock (m_host.TaskInventory) 3706 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3707 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3708 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3709 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3710 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3711
3712 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3394 { 3713 {
3714 m_host.TaskInventory.LockItemsForWrite(true);
3395 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3715 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3396 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3716 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3397 } 3717 m_host.TaskInventory.LockItemsForWrite(false);
3398 3718
3399 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3719 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3400 "run_time_permissions", new Object[] { 3720 "run_time_permissions", new Object[] {
3401 new LSL_Integer(perm) }, 3721 new LSL_Integer(perm) },
3402 new DetectParams[0])); 3722 new DetectParams[0]));
3403 3723
3404 return; 3724 return;
3725 }
3405 } 3726 }
3406 } 3727 }
3407 3728
@@ -3438,11 +3759,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3438 3759
3439 if (!m_waitingForScriptAnswer) 3760 if (!m_waitingForScriptAnswer)
3440 { 3761 {
3441 lock (m_host.TaskInventory) 3762 m_host.TaskInventory.LockItemsForWrite(true);
3442 { 3763 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3443 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3764 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3444 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 3765 m_host.TaskInventory.LockItemsForWrite(false);
3445 }
3446 3766
3447 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3767 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3448 m_waitingForScriptAnswer=true; 3768 m_waitingForScriptAnswer=true;
@@ -3471,14 +3791,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3471 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3791 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3472 llReleaseControls(); 3792 llReleaseControls();
3473 3793
3474 lock (m_host.TaskInventory) 3794 m_host.TaskInventory.LockItemsForWrite(true);
3475 { 3795 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3476 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 3796 m_host.TaskInventory.LockItemsForWrite(false);
3477 } 3797
3478 3798 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3479 m_ScriptEngine.PostScriptEvent( 3799 "run_time_permissions", new Object[] {
3480 m_item.ItemID, 3800 new LSL_Integer(answer) },
3481 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); 3801 new DetectParams[0]));
3482 } 3802 }
3483 3803
3484 public LSL_String llGetPermissionsKey() 3804 public LSL_String llGetPermissionsKey()
@@ -3517,14 +3837,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3517 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3837 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3518 { 3838 {
3519 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3839 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3520 3840 if (parts.Count > 0)
3521 foreach (SceneObjectPart part in parts) 3841 {
3522 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3842 try
3843 {
3844 parts[0].ParentGroup.areUpdatesSuspended = true;
3845 foreach (SceneObjectPart part in parts)
3846 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3847 }
3848 finally
3849 {
3850 parts[0].ParentGroup.areUpdatesSuspended = false;
3851 }
3852 }
3523 } 3853 }
3524 3854
3525 public void llCreateLink(string target, int parent) 3855 public void llCreateLink(string target, int parent)
3526 { 3856 {
3527 m_host.AddScriptLPS(1); 3857 m_host.AddScriptLPS(1);
3858
3528 UUID targetID; 3859 UUID targetID;
3529 3860
3530 if (!UUID.TryParse(target, out targetID)) 3861 if (!UUID.TryParse(target, out targetID))
@@ -3630,10 +3961,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3630 // Restructuring Multiple Prims. 3961 // Restructuring Multiple Prims.
3631 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 3962 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3632 parts.Remove(parentPrim.RootPart); 3963 parts.Remove(parentPrim.RootPart);
3633 foreach (SceneObjectPart part in parts) 3964 if (parts.Count > 0)
3634 { 3965 {
3635 parentPrim.DelinkFromGroup(part.LocalId, true); 3966 try
3967 {
3968 parts[0].ParentGroup.areUpdatesSuspended = true;
3969 foreach (SceneObjectPart part in parts)
3970 {
3971 parentPrim.DelinkFromGroup(part.LocalId, true);
3972 }
3973 }
3974 finally
3975 {
3976 parts[0].ParentGroup.areUpdatesSuspended = false;
3977 }
3636 } 3978 }
3979
3637 parentPrim.HasGroupChanged = true; 3980 parentPrim.HasGroupChanged = true;
3638 parentPrim.ScheduleGroupForFullUpdate(); 3981 parentPrim.ScheduleGroupForFullUpdate();
3639 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3982 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3642,12 +3985,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3642 { 3985 {
3643 SceneObjectPart newRoot = parts[0]; 3986 SceneObjectPart newRoot = parts[0];
3644 parts.Remove(newRoot); 3987 parts.Remove(newRoot);
3645 foreach (SceneObjectPart part in parts) 3988
3989 try
3646 { 3990 {
3647 // Required for linking 3991 parts[0].ParentGroup.areUpdatesSuspended = true;
3648 part.ClearUpdateSchedule(); 3992 foreach (SceneObjectPart part in parts)
3649 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 3993 {
3994 part.ClearUpdateSchedule();
3995 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3996 }
3650 } 3997 }
3998 finally
3999 {
4000 parts[0].ParentGroup.areUpdatesSuspended = false;
4001 }
4002
4003
3651 newRoot.ParentGroup.HasGroupChanged = true; 4004 newRoot.ParentGroup.HasGroupChanged = true;
3652 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4005 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3653 } 4006 }
@@ -3667,6 +4020,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3667 public void llBreakAllLinks() 4020 public void llBreakAllLinks()
3668 { 4021 {
3669 m_host.AddScriptLPS(1); 4022 m_host.AddScriptLPS(1);
4023
4024 TaskInventoryItem item = m_item;
4025
4026 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4027 && !m_automaticLinkPermission)
4028 {
4029 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4030 return;
4031 }
4032
3670 SceneObjectGroup parentPrim = m_host.ParentGroup; 4033 SceneObjectGroup parentPrim = m_host.ParentGroup;
3671 if (parentPrim.AttachmentPoint != 0) 4034 if (parentPrim.AttachmentPoint != 0)
3672 return; // Fail silently if attached 4035 return; // Fail silently if attached
@@ -3686,25 +4049,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3686 public LSL_String llGetLinkKey(int linknum) 4049 public LSL_String llGetLinkKey(int linknum)
3687 { 4050 {
3688 m_host.AddScriptLPS(1); 4051 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); 4052 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3709 if (part != null) 4053 if (part != null)
3710 { 4054 {
@@ -3712,6 +4056,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3712 } 4056 }
3713 else 4057 else
3714 { 4058 {
4059 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4060 {
4061 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4062
4063 if (linknum < 0)
4064 return UUID.Zero.ToString();
4065
4066 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4067 if (avatars.Count > linknum)
4068 {
4069 return avatars[linknum].UUID.ToString();
4070 }
4071 }
3715 return UUID.Zero.ToString(); 4072 return UUID.Zero.ToString();
3716 } 4073 }
3717 } 4074 }
@@ -3811,17 +4168,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3811 m_host.AddScriptLPS(1); 4168 m_host.AddScriptLPS(1);
3812 int count = 0; 4169 int count = 0;
3813 4170
3814 lock (m_host.TaskInventory) 4171 m_host.TaskInventory.LockItemsForRead(true);
4172 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3815 { 4173 {
3816 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4174 if (inv.Value.Type == type || type == -1)
3817 { 4175 {
3818 if (inv.Value.Type == type || type == -1) 4176 count = count + 1;
3819 {
3820 count = count + 1;
3821 }
3822 } 4177 }
3823 } 4178 }
3824 4179
4180 m_host.TaskInventory.LockItemsForRead(false);
3825 return count; 4181 return count;
3826 } 4182 }
3827 4183
@@ -3830,16 +4186,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3830 m_host.AddScriptLPS(1); 4186 m_host.AddScriptLPS(1);
3831 ArrayList keys = new ArrayList(); 4187 ArrayList keys = new ArrayList();
3832 4188
3833 lock (m_host.TaskInventory) 4189 m_host.TaskInventory.LockItemsForRead(true);
4190 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3834 { 4191 {
3835 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4192 if (inv.Value.Type == type || type == -1)
3836 { 4193 {
3837 if (inv.Value.Type == type || type == -1) 4194 keys.Add(inv.Value.Name);
3838 {
3839 keys.Add(inv.Value.Name);
3840 }
3841 } 4195 }
3842 } 4196 }
4197 m_host.TaskInventory.LockItemsForRead(false);
3843 4198
3844 if (keys.Count == 0) 4199 if (keys.Count == 0)
3845 { 4200 {
@@ -3876,25 +4231,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3876 } 4231 }
3877 4232
3878 // move the first object found with this inventory name 4233 // move the first object found with this inventory name
3879 lock (m_host.TaskInventory) 4234 m_host.TaskInventory.LockItemsForRead(true);
4235 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3880 { 4236 {
3881 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4237 if (inv.Value.Name == inventory)
3882 { 4238 {
3883 if (inv.Value.Name == inventory) 4239 found = true;
3884 { 4240 objId = inv.Key;
3885 found = true; 4241 assetType = inv.Value.Type;
3886 objId = inv.Key; 4242 objName = inv.Value.Name;
3887 assetType = inv.Value.Type; 4243 break;
3888 objName = inv.Value.Name;
3889 break;
3890 }
3891 } 4244 }
3892 } 4245 }
4246 m_host.TaskInventory.LockItemsForRead(false);
3893 4247
3894 if (!found) 4248 if (!found)
3895 { 4249 {
3896 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4250 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)); 4251 return;
4252// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3898 } 4253 }
3899 4254
3900 // check if destination is an object 4255 // check if destination is an object
@@ -3920,48 +4275,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3920 return; 4275 return;
3921 } 4276 }
3922 } 4277 }
4278
3923 // destination is an avatar 4279 // destination is an avatar
3924 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4280 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3925 4281
3926 if (agentItem == null) 4282 if (agentItem == null)
3927 return; 4283 return;
3928 4284
3929 byte[] bucket = new byte[17]; 4285 byte[] bucket = new byte[1];
3930 bucket[0] = (byte)assetType; 4286 bucket[0] = (byte)assetType;
3931 byte[] objBytes = agentItem.ID.GetBytes(); 4287 //byte[] objBytes = agentItem.ID.GetBytes();
3932 Array.Copy(objBytes, 0, bucket, 1, 16); 4288 //Array.Copy(objBytes, 0, bucket, 1, 16);
3933 4289
3934 GridInstantMessage msg = new GridInstantMessage(World, 4290 GridInstantMessage msg = new GridInstantMessage(World,
3935 m_host.UUID, m_host.Name+", an object owned by "+ 4291 m_host.OwnerID, m_host.Name, destId,
3936 resolveName(m_host.OwnerID)+",", destId,
3937 (byte)InstantMessageDialog.TaskInventoryOffered, 4292 (byte)InstantMessageDialog.TaskInventoryOffered,
3938 false, objName+"\n"+m_host.Name+" is located at "+ 4293 false, objName+". "+m_host.Name+" is located at "+
3939 World.RegionInfo.RegionName+" "+ 4294 World.RegionInfo.RegionName+" "+
3940 m_host.AbsolutePosition.ToString(), 4295 m_host.AbsolutePosition.ToString(),
3941 agentItem.ID, true, m_host.AbsolutePosition, 4296 agentItem.ID, true, m_host.AbsolutePosition,
3942 bucket); 4297 bucket);
3943 if (m_TransferModule != null) 4298
3944 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4299 ScenePresence sp;
4300
4301 if (World.TryGetScenePresence(destId, out sp))
4302 {
4303 sp.ControllingClient.SendInstantMessage(msg);
4304 }
4305 else
4306 {
4307 if (m_TransferModule != null)
4308 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4309 }
4310
4311 //This delay should only occur when giving inventory to avatars.
3945 ScriptSleep(3000); 4312 ScriptSleep(3000);
3946 } 4313 }
3947 } 4314 }
3948 4315
4316 [DebuggerNonUserCode]
3949 public void llRemoveInventory(string name) 4317 public void llRemoveInventory(string name)
3950 { 4318 {
3951 m_host.AddScriptLPS(1); 4319 m_host.AddScriptLPS(1);
3952 4320
3953 lock (m_host.TaskInventory) 4321 List<TaskInventoryItem> inv;
4322 try
3954 { 4323 {
3955 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4324 m_host.TaskInventory.LockItemsForRead(true);
4325 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4326 }
4327 finally
4328 {
4329 m_host.TaskInventory.LockItemsForRead(false);
4330 }
4331 foreach (TaskInventoryItem item in inv)
4332 {
4333 if (item.Name == name)
3956 { 4334 {
3957 if (item.Name == name) 4335 if (item.ItemID == m_item.ItemID)
3958 { 4336 throw new ScriptDeleteException();
3959 if (item.ItemID == m_item.ItemID) 4337 else
3960 throw new ScriptDeleteException(); 4338 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3961 else 4339 return;
3962 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3963 return;
3964 }
3965 } 4340 }
3966 } 4341 }
3967 } 4342 }
@@ -3996,115 +4371,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3996 { 4371 {
3997 m_host.AddScriptLPS(1); 4372 m_host.AddScriptLPS(1);
3998 4373
3999 UUID uuid = (UUID)id; 4374 UUID uuid;
4000 PresenceInfo pinfo = null; 4375 if (UUID.TryParse(id, out uuid))
4001 UserAccount account;
4002
4003 UserInfoCacheEntry ce;
4004 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4005 { 4376 {
4006 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4377 PresenceInfo pinfo = null;
4007 if (account == null) 4378 UserAccount account;
4379
4380 UserInfoCacheEntry ce;
4381 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4008 { 4382 {
4009 m_userInfoCache[uuid] = null; // Cache negative 4383 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4010 return UUID.Zero.ToString(); 4384 if (account == null)
4011 } 4385 {
4386 m_userInfoCache[uuid] = null; // Cache negative
4387 return UUID.Zero.ToString();
4388 }
4012 4389
4013 4390
4014 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4391 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4015 if (pinfos != null && pinfos.Length > 0) 4392 if (pinfos != null && pinfos.Length > 0)
4016 {
4017 foreach (PresenceInfo p in pinfos)
4018 { 4393 {
4019 if (p.RegionID != UUID.Zero) 4394 foreach (PresenceInfo p in pinfos)
4020 { 4395 {
4021 pinfo = p; 4396 if (p.RegionID != UUID.Zero)
4397 {
4398 pinfo = p;
4399 }
4022 } 4400 }
4023 } 4401 }
4024 }
4025 4402
4026 ce = new UserInfoCacheEntry(); 4403 ce = new UserInfoCacheEntry();
4027 ce.time = Util.EnvironmentTickCount(); 4404 ce.time = Util.EnvironmentTickCount();
4028 ce.account = account; 4405 ce.account = account;
4029 ce.pinfo = pinfo; 4406 ce.pinfo = pinfo;
4030 } 4407 m_userInfoCache[uuid] = ce;
4031 else 4408 }
4032 { 4409 else
4033 if (ce == null) 4410 {
4034 return UUID.Zero.ToString(); 4411 if (ce == null)
4412 return UUID.Zero.ToString();
4035 4413
4036 account = ce.account; 4414 account = ce.account;
4037 pinfo = ce.pinfo; 4415 pinfo = ce.pinfo;
4038 } 4416 }
4039 4417
4040 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4418 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 { 4419 {
4045 foreach (PresenceInfo p in pinfos) 4420 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4421 if (pinfos != null && pinfos.Length > 0)
4046 { 4422 {
4047 if (p.RegionID != UUID.Zero) 4423 foreach (PresenceInfo p in pinfos)
4048 { 4424 {
4049 pinfo = p; 4425 if (p.RegionID != UUID.Zero)
4426 {
4427 pinfo = p;
4428 }
4050 } 4429 }
4051 } 4430 }
4052 } 4431 else
4053 else 4432 pinfo = null;
4054 pinfo = null;
4055 4433
4056 ce.time = Util.EnvironmentTickCount(); 4434 ce.time = Util.EnvironmentTickCount();
4057 ce.pinfo = pinfo; 4435 ce.pinfo = pinfo;
4058 } 4436 }
4059 4437
4060 string reply = String.Empty; 4438 string reply = String.Empty;
4061 4439
4062 switch (data) 4440 switch (data)
4063 { 4441 {
4064 case 1: // DATA_ONLINE (0|1) 4442 case 1: // DATA_ONLINE (0|1)
4065 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4443 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4066 reply = "1"; 4444 reply = "1";
4067 else 4445 else
4068 reply = "0"; 4446 reply = "0";
4069 break; 4447 break;
4070 case 2: // DATA_NAME (First Last) 4448 case 2: // DATA_NAME (First Last)
4071 reply = account.FirstName + " " + account.LastName; 4449 reply = account.FirstName + " " + account.LastName;
4072 break; 4450 break;
4073 case 3: // DATA_BORN (YYYY-MM-DD) 4451 case 3: // DATA_BORN (YYYY-MM-DD)
4074 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4452 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4075 born = born.AddSeconds(account.Created); 4453 born = born.AddSeconds(account.Created);
4076 reply = born.ToString("yyyy-MM-dd"); 4454 reply = born.ToString("yyyy-MM-dd");
4077 break; 4455 break;
4078 case 4: // DATA_RATING (0,0,0,0,0,0) 4456 case 4: // DATA_RATING (0,0,0,0,0,0)
4079 reply = "0,0,0,0,0,0"; 4457 reply = "0,0,0,0,0,0";
4080 break; 4458 break;
4081 case 7: // DATA_USERLEVEL (integer) 4459 case 8: // DATA_PAYINFO (0|1|2|3)
4082 reply = account.UserLevel.ToString(); 4460 reply = "0";
4083 break; 4461 break;
4084 case 8: // DATA_PAYINFO (0|1|2|3) 4462 default:
4085 reply = "0"; 4463 return UUID.Zero.ToString(); // Raise no event
4086 break; 4464 }
4087 default:
4088 return UUID.Zero.ToString(); // Raise no event
4089 }
4090 4465
4091 UUID rq = UUID.Random(); 4466 UUID rq = UUID.Random();
4092 4467
4093 UUID tid = AsyncCommands. 4468 UUID tid = AsyncCommands.
4094 DataserverPlugin.RegisterRequest(m_host.LocalId, 4469 DataserverPlugin.RegisterRequest(m_host.LocalId,
4095 m_item.ItemID, rq.ToString()); 4470 m_item.ItemID, rq.ToString());
4096 4471
4097 AsyncCommands. 4472 AsyncCommands.
4098 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4473 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4099 4474
4100 ScriptSleep(100); 4475 ScriptSleep(100);
4101 return tid.ToString(); 4476 return tid.ToString();
4477 }
4478 else
4479 {
4480 ShoutError("Invalid UUID passed to llRequestAgentData.");
4481 }
4482 return "";
4102 } 4483 }
4103 4484
4104 public LSL_String llRequestInventoryData(string name) 4485 public LSL_String llRequestInventoryData(string name)
4105 { 4486 {
4106 m_host.AddScriptLPS(1); 4487 m_host.AddScriptLPS(1);
4107 4488
4489 //Clone is thread safe
4108 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4490 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4109 4491
4110 foreach (TaskInventoryItem item in itemDictionary.Values) 4492 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4156,13 +4538,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4156 if (UUID.TryParse(agent, out agentId)) 4538 if (UUID.TryParse(agent, out agentId))
4157 { 4539 {
4158 ScenePresence presence = World.GetScenePresence(agentId); 4540 ScenePresence presence = World.GetScenePresence(agentId);
4159 if (presence != null) 4541 if (presence != null && presence.PresenceType != PresenceType.Npc)
4160 { 4542 {
4543 // agent must not be a god
4544 if (presence.UserLevel >= 200) return;
4545
4161 // agent must be over the owners land 4546 // agent must be over the owners land
4162 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4547 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4163 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4548 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4164 { 4549 {
4165 World.TeleportClientHome(agentId, presence.ControllingClient); 4550 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4551 {
4552 // They can't be teleported home for some reason
4553 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4554 if (regionInfo != null)
4555 {
4556 World.RequestTeleportLocation(
4557 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4558 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4559 }
4560 }
4166 } 4561 }
4167 } 4562 }
4168 } 4563 }
@@ -4274,7 +4669,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4274 UUID av = new UUID(); 4669 UUID av = new UUID();
4275 if (!UUID.TryParse(agent,out av)) 4670 if (!UUID.TryParse(agent,out av))
4276 { 4671 {
4277 LSLError("First parameter to llDialog needs to be a key"); 4672 //LSLError("First parameter to llDialog needs to be a key");
4278 return; 4673 return;
4279 } 4674 }
4280 4675
@@ -4306,25 +4701,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4306 public void llCollisionSound(string impact_sound, double impact_volume) 4701 public void llCollisionSound(string impact_sound, double impact_volume)
4307 { 4702 {
4308 m_host.AddScriptLPS(1); 4703 m_host.AddScriptLPS(1);
4309 4704
4705 if(impact_sound == "")
4706 {
4707 m_host.CollisionSoundVolume = (float)impact_volume;
4708 m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
4709 m_host.CollisionSoundType = 0;
4710 return;
4711 }
4310 // TODO: Parameter check logic required. 4712 // TODO: Parameter check logic required.
4311 UUID soundId = UUID.Zero; 4713 UUID soundId = UUID.Zero;
4312 if (!UUID.TryParse(impact_sound, out soundId)) 4714 if (!UUID.TryParse(impact_sound, out soundId))
4313 { 4715 {
4314 lock (m_host.TaskInventory) 4716 m_host.TaskInventory.LockItemsForRead(true);
4717 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4315 { 4718 {
4316 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4719 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4317 { 4720 {
4318 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4721 soundId = item.AssetID;
4319 { 4722 break;
4320 soundId = item.AssetID;
4321 break;
4322 }
4323 } 4723 }
4324 } 4724 }
4725 m_host.TaskInventory.LockItemsForRead(false);
4325 } 4726 }
4326 m_host.CollisionSound = soundId;
4327 m_host.CollisionSoundVolume = (float)impact_volume; 4727 m_host.CollisionSoundVolume = (float)impact_volume;
4728 m_host.CollisionSound = soundId;
4729 m_host.CollisionSoundType = 1;
4328 } 4730 }
4329 4731
4330 public LSL_String llGetAnimation(string id) 4732 public LSL_String llGetAnimation(string id)
@@ -4338,14 +4740,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4338 4740
4339 if (m_host.RegionHandle == presence.RegionHandle) 4741 if (m_host.RegionHandle == presence.RegionHandle)
4340 { 4742 {
4341 Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames;
4342
4343 if (presence != null) 4743 if (presence != null)
4344 { 4744 {
4345 AnimationSet currentAnims = presence.Animator.Animations; 4745 if (presence.SitGround)
4346 string currentAnimationState = String.Empty; 4746 return "Sitting on Ground";
4347 if (animationstateNames.TryGetValue(currentAnims.DefaultAnimation.AnimID, out currentAnimationState)) 4747 if (presence.ParentID != 0 || presence.ParentUUID != UUID.Zero)
4348 return currentAnimationState; 4748 return "Sitting";
4749
4750 string movementAnimation = presence.Animator.CurrentMovementAnimation;
4751 string lslMovementAnimation;
4752
4753 if (MovementAnimationsForLSL.TryGetValue(movementAnimation, out lslMovementAnimation))
4754 return lslMovementAnimation;
4349 } 4755 }
4350 } 4756 }
4351 4757
@@ -4361,6 +4767,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4361 UUID partItemID; 4767 UUID partItemID;
4362 foreach (SceneObjectPart part in parts) 4768 foreach (SceneObjectPart part in parts)
4363 { 4769 {
4770 //Clone is thread safe
4364 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4771 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4365 4772
4366 foreach (TaskInventoryItem item in itemsDictionary.Values) 4773 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4494,7 +4901,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4494 { 4901 {
4495 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4902 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4496 float distance_term = distance * distance * distance; // Script Energy 4903 float distance_term = distance * distance * distance; // Script Energy
4497 float pusher_mass = m_host.GetMass(); 4904 // use total object mass and not part
4905 float pusher_mass = m_host.ParentGroup.GetMass();
4498 4906
4499 float PUSH_ATTENUATION_DISTANCE = 17f; 4907 float PUSH_ATTENUATION_DISTANCE = 17f;
4500 float PUSH_ATTENUATION_SCALE = 5f; 4908 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4733,23 +5141,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4733 { 5141 {
4734 m_host.AddScriptLPS(1); 5142 m_host.AddScriptLPS(1);
4735 5143
4736 lock (m_host.TaskInventory) 5144 m_host.TaskInventory.LockItemsForRead(true);
5145 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4737 { 5146 {
4738 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5147 if (inv.Value.Name == name)
4739 { 5148 {
4740 if (inv.Value.Name == name) 5149 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4741 { 5150 {
4742 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5151 m_host.TaskInventory.LockItemsForRead(false);
4743 { 5152 return inv.Value.AssetID.ToString();
4744 return inv.Value.AssetID.ToString(); 5153 }
4745 } 5154 else
4746 else 5155 {
4747 { 5156 m_host.TaskInventory.LockItemsForRead(false);
4748 return UUID.Zero.ToString(); 5157 return UUID.Zero.ToString();
4749 }
4750 } 5158 }
4751 } 5159 }
4752 } 5160 }
5161 m_host.TaskInventory.LockItemsForRead(false);
4753 5162
4754 return UUID.Zero.ToString(); 5163 return UUID.Zero.ToString();
4755 } 5164 }
@@ -4883,7 +5292,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4883 public LSL_Vector llGetCenterOfMass() 5292 public LSL_Vector llGetCenterOfMass()
4884 { 5293 {
4885 m_host.AddScriptLPS(1); 5294 m_host.AddScriptLPS(1);
4886 Vector3 center = m_host.GetGeometricCenter(); 5295 Vector3 center = m_host.GetCenterOfMass();
4887 return new LSL_Vector(center.X,center.Y,center.Z); 5296 return new LSL_Vector(center.X,center.Y,center.Z);
4888 } 5297 }
4889 5298
@@ -4902,14 +5311,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4902 { 5311 {
4903 m_host.AddScriptLPS(1); 5312 m_host.AddScriptLPS(1);
4904 5313
4905 if (src == null) 5314 return src.Length;
4906 {
4907 return 0;
4908 }
4909 else
4910 {
4911 return src.Length;
4912 }
4913 } 5315 }
4914 5316
4915 public LSL_Integer llList2Integer(LSL_List src, int index) 5317 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4955,7 +5357,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4955 else if (src.Data[index] is LSL_Float) 5357 else if (src.Data[index] is LSL_Float)
4956 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5358 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4957 else if (src.Data[index] is LSL_String) 5359 else if (src.Data[index] is LSL_String)
4958 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5360 {
5361 string str = ((LSL_String) src.Data[index]).m_string;
5362 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5363 if (m != Match.Empty)
5364 {
5365 str = m.Value;
5366 double d = 0.0;
5367 if (!Double.TryParse(str, out d))
5368 return 0.0;
5369
5370 return d;
5371 }
5372 return 0.0;
5373 }
4959 return Convert.ToDouble(src.Data[index]); 5374 return Convert.ToDouble(src.Data[index]);
4960 } 5375 }
4961 catch (FormatException) 5376 catch (FormatException)
@@ -5228,7 +5643,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5228 } 5643 }
5229 } 5644 }
5230 } 5645 }
5231 else { 5646 else
5647 {
5232 object[] array = new object[src.Length]; 5648 object[] array = new object[src.Length];
5233 Array.Copy(src.Data, 0, array, 0, src.Length); 5649 Array.Copy(src.Data, 0, array, 0, src.Length);
5234 result = new LSL_List(array); 5650 result = new LSL_List(array);
@@ -5335,7 +5751,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5335 public LSL_Integer llGetRegionAgentCount() 5751 public LSL_Integer llGetRegionAgentCount()
5336 { 5752 {
5337 m_host.AddScriptLPS(1); 5753 m_host.AddScriptLPS(1);
5338 return new LSL_Integer(World.GetRootAgentCount()); 5754
5755 int count = 0;
5756 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5757 count++;
5758 });
5759
5760 return new LSL_Integer(count);
5339 } 5761 }
5340 5762
5341 public LSL_Vector llGetRegionCorner() 5763 public LSL_Vector llGetRegionCorner()
@@ -5615,6 +6037,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5615 flags |= ScriptBaseClass.AGENT_SITTING; 6037 flags |= ScriptBaseClass.AGENT_SITTING;
5616 } 6038 }
5617 6039
6040 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
6041 {
6042 flags |= ScriptBaseClass.AGENT_MALE;
6043 }
6044
5618 return flags; 6045 return flags;
5619 } 6046 }
5620 6047
@@ -5761,10 +6188,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5761 m_host.AddScriptLPS(1); 6188 m_host.AddScriptLPS(1);
5762 6189
5763 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6190 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5764 6191 if (parts.Count > 0)
5765 foreach (var part in parts)
5766 { 6192 {
5767 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6193 try
6194 {
6195 parts[0].ParentGroup.areUpdatesSuspended = true;
6196 foreach (var part in parts)
6197 {
6198 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6199 }
6200 }
6201 finally
6202 {
6203 parts[0].ParentGroup.areUpdatesSuspended = false;
6204 }
5768 } 6205 }
5769 } 6206 }
5770 6207
@@ -5816,13 +6253,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5816 6253
5817 if (m_host.OwnerID == land.LandData.OwnerID) 6254 if (m_host.OwnerID == land.LandData.OwnerID)
5818 { 6255 {
5819 World.TeleportClientHome(agentID, presence.ControllingClient); 6256 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6257 presence.TeleportWithMomentum(pos, null);
6258 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5820 } 6259 }
5821 } 6260 }
5822 } 6261 }
5823 ScriptSleep(5000); 6262 ScriptSleep(5000);
5824 } 6263 }
5825 6264
6265 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6266 {
6267 return ParseString2List(str, separators, in_spacers, false);
6268 }
6269
5826 public LSL_Integer llOverMyLand(string id) 6270 public LSL_Integer llOverMyLand(string id)
5827 { 6271 {
5828 m_host.AddScriptLPS(1); 6272 m_host.AddScriptLPS(1);
@@ -5887,8 +6331,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5887 UUID agentId = new UUID(); 6331 UUID agentId = new UUID();
5888 if (!UUID.TryParse(agent, out agentId)) 6332 if (!UUID.TryParse(agent, out agentId))
5889 return new LSL_Integer(0); 6333 return new LSL_Integer(0);
6334 if (agentId == m_host.GroupID)
6335 return new LSL_Integer(1);
5890 ScenePresence presence = World.GetScenePresence(agentId); 6336 ScenePresence presence = World.GetScenePresence(agentId);
5891 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6337 if (presence == null || presence.IsChildAgent) // Return false for child agents
5892 return new LSL_Integer(0); 6338 return new LSL_Integer(0);
5893 IClientAPI client = presence.ControllingClient; 6339 IClientAPI client = presence.ControllingClient;
5894 if (m_host.GroupID == client.ActiveGroupId) 6340 if (m_host.GroupID == client.ActiveGroupId)
@@ -6023,7 +6469,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6023 return m_host.ParentGroup.AttachmentPoint; 6469 return m_host.ParentGroup.AttachmentPoint;
6024 } 6470 }
6025 6471
6026 public LSL_Integer llGetFreeMemory() 6472 public virtual LSL_Integer llGetFreeMemory()
6027 { 6473 {
6028 m_host.AddScriptLPS(1); 6474 m_host.AddScriptLPS(1);
6029 // Make scripts designed for LSO happy 6475 // Make scripts designed for LSO happy
@@ -6140,7 +6586,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6140 SetParticleSystem(m_host, rules); 6586 SetParticleSystem(m_host, rules);
6141 } 6587 }
6142 6588
6143 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6589 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6590 {
6144 6591
6145 6592
6146 if (rules.Length == 0) 6593 if (rules.Length == 0)
@@ -6334,14 +6781,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6334 6781
6335 protected UUID GetTaskInventoryItem(string name) 6782 protected UUID GetTaskInventoryItem(string name)
6336 { 6783 {
6337 lock (m_host.TaskInventory) 6784 m_host.TaskInventory.LockItemsForRead(true);
6785 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6338 { 6786 {
6339 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6787 if (inv.Value.Name == name)
6340 { 6788 {
6341 if (inv.Value.Name == name) 6789 m_host.TaskInventory.LockItemsForRead(false);
6342 return inv.Key; 6790 return inv.Key;
6343 } 6791 }
6344 } 6792 }
6793 m_host.TaskInventory.LockItemsForRead(false);
6345 6794
6346 return UUID.Zero; 6795 return UUID.Zero;
6347 } 6796 }
@@ -6379,16 +6828,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6379 if (folderID == UUID.Zero) 6828 if (folderID == UUID.Zero)
6380 return; 6829 return;
6381 6830
6382 byte[] bucket = new byte[17]; 6831 byte[] bucket = new byte[1];
6383 bucket[0] = (byte)AssetType.Folder; 6832 bucket[0] = (byte)AssetType.Folder;
6384 byte[] objBytes = folderID.GetBytes(); 6833 //byte[] objBytes = folderID.GetBytes();
6385 Array.Copy(objBytes, 0, bucket, 1, 16); 6834 //Array.Copy(objBytes, 0, bucket, 1, 16);
6386 6835
6387 GridInstantMessage msg = new GridInstantMessage(World, 6836 GridInstantMessage msg = new GridInstantMessage(World,
6388 m_host.UUID, m_host.Name+", an object owned by "+ 6837 m_host.OwnerID, m_host.Name, destID,
6389 resolveName(m_host.OwnerID)+",", destID, 6838 (byte)InstantMessageDialog.TaskInventoryOffered,
6390 (byte)InstantMessageDialog.InventoryOffered, 6839 false, category+". "+m_host.Name+" is located at "+
6391 false, category+"\n"+m_host.Name+" is located at "+
6392 World.RegionInfo.RegionName+" "+ 6840 World.RegionInfo.RegionName+" "+
6393 m_host.AbsolutePosition.ToString(), 6841 m_host.AbsolutePosition.ToString(),
6394 folderID, true, m_host.AbsolutePosition, 6842 folderID, true, m_host.AbsolutePosition,
@@ -6626,13 +7074,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6626 UUID av = new UUID(); 7074 UUID av = new UUID();
6627 if (!UUID.TryParse(avatar,out av)) 7075 if (!UUID.TryParse(avatar,out av))
6628 { 7076 {
6629 LSLError("First parameter to llDialog needs to be a key"); 7077 //LSLError("First parameter to llDialog needs to be a key");
6630 return; 7078 return;
6631 } 7079 }
6632 if (buttons.Length < 1) 7080 if (buttons.Length < 1)
6633 { 7081 {
6634 LSLError("No less than 1 button can be shown"); 7082 buttons.Add("OK");
6635 return;
6636 } 7083 }
6637 if (buttons.Length > 12) 7084 if (buttons.Length > 12)
6638 { 7085 {
@@ -6649,7 +7096,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6649 } 7096 }
6650 if (buttons.Data[i].ToString().Length > 24) 7097 if (buttons.Data[i].ToString().Length > 24)
6651 { 7098 {
6652 LSLError("button label cannot be longer than 24 characters"); 7099 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6653 return; 7100 return;
6654 } 7101 }
6655 buts[i] = buttons.Data[i].ToString(); 7102 buts[i] = buttons.Data[i].ToString();
@@ -6708,22 +7155,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6708 } 7155 }
6709 7156
6710 // copy the first script found with this inventory name 7157 // copy the first script found with this inventory name
6711 lock (m_host.TaskInventory) 7158 TaskInventoryItem scriptItem = null;
7159 m_host.TaskInventory.LockItemsForRead(true);
7160 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6712 { 7161 {
6713 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 7162 if (inv.Value.Name == name)
6714 { 7163 {
6715 if (inv.Value.Name == name) 7164 // make sure the object is a script
7165 if (10 == inv.Value.Type)
6716 { 7166 {
6717 // make sure the object is a script 7167 found = true;
6718 if (10 == inv.Value.Type) 7168 srcId = inv.Key;
6719 { 7169 scriptItem = inv.Value;
6720 found = true; 7170 break;
6721 srcId = inv.Key;
6722 break;
6723 }
6724 } 7171 }
6725 } 7172 }
6726 } 7173 }
7174 m_host.TaskInventory.LockItemsForRead(false);
6727 7175
6728 if (!found) 7176 if (!found)
6729 { 7177 {
@@ -6731,9 +7179,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6731 return; 7179 return;
6732 } 7180 }
6733 7181
6734 // the rest of the permission checks are done in RezScript, so check the pin there as well 7182 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6735 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7183 if (dest != null)
7184 {
7185 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7186 {
7187 // the rest of the permission checks are done in RezScript, so check the pin there as well
7188 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6736 7189
7190 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7191 m_host.Inventory.RemoveInventoryItem(srcId);
7192 }
7193 }
6737 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7194 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6738 ScriptSleep(3000); 7195 ScriptSleep(3000);
6739 } 7196 }
@@ -6796,19 +7253,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6796 public LSL_String llMD5String(string src, int nonce) 7253 public LSL_String llMD5String(string src, int nonce)
6797 { 7254 {
6798 m_host.AddScriptLPS(1); 7255 m_host.AddScriptLPS(1);
6799 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7256 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6800 } 7257 }
6801 7258
6802 public LSL_String llSHA1String(string src) 7259 public LSL_String llSHA1String(string src)
6803 { 7260 {
6804 m_host.AddScriptLPS(1); 7261 m_host.AddScriptLPS(1);
6805 return Util.SHA1Hash(src).ToLower(); 7262 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6806 } 7263 }
6807 7264
6808 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7265 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6809 { 7266 {
6810 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7267 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6811 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7268 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7269 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7270 return shapeBlock;
6812 7271
6813 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7272 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6814 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7273 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6913,6 +7372,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6913 // Prim type box, cylinder and prism. 7372 // Prim type box, cylinder and prism.
6914 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) 7373 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)
6915 { 7374 {
7375 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7376 return;
7377
6916 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7378 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6917 ObjectShapePacket.ObjectDataBlock shapeBlock; 7379 ObjectShapePacket.ObjectDataBlock shapeBlock;
6918 7380
@@ -6966,6 +7428,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6966 // Prim type sphere. 7428 // Prim type sphere.
6967 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7429 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6968 { 7430 {
7431 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7432 return;
7433
6969 ObjectShapePacket.ObjectDataBlock shapeBlock; 7434 ObjectShapePacket.ObjectDataBlock shapeBlock;
6970 7435
6971 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7436 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -7007,6 +7472,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7007 // Prim type torus, tube and ring. 7472 // Prim type torus, tube and ring.
7008 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) 7473 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)
7009 { 7474 {
7475 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7476 return;
7477
7010 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7478 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7011 ObjectShapePacket.ObjectDataBlock shapeBlock; 7479 ObjectShapePacket.ObjectDataBlock shapeBlock;
7012 7480
@@ -7142,6 +7610,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7142 // Prim type sculpt. 7610 // Prim type sculpt.
7143 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7611 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7144 { 7612 {
7613 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7614 return;
7615
7145 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7616 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7146 UUID sculptId; 7617 UUID sculptId;
7147 7618
@@ -7166,7 +7637,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7166 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7637 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7167 { 7638 {
7168 // default 7639 // default
7169 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7640 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7170 } 7641 }
7171 7642
7172 part.Shape.SetSculptProperties((byte)type, sculptId); 7643 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7182,32 +7653,149 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7182 ScriptSleep(200); 7653 ScriptSleep(200);
7183 } 7654 }
7184 7655
7185 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7656 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7186 { 7657 {
7187 m_host.AddScriptLPS(1); 7658 m_host.AddScriptLPS(1);
7188 7659
7189 setLinkPrimParams(linknumber, rules); 7660 setLinkPrimParams(linknumber, rules);
7661 }
7190 7662
7191 ScriptSleep(200); 7663 private void setLinkPrimParams(int linknumber, LSL_List rules)
7664 {
7665 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7666 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7667 if (parts.Count>0)
7668 {
7669 try
7670 {
7671 parts[0].ParentGroup.areUpdatesSuspended = true;
7672 foreach (SceneObjectPart part in parts)
7673 SetPrimParams(part, rules);
7674 }
7675 finally
7676 {
7677 parts[0].ParentGroup.areUpdatesSuspended = false;
7678 }
7679 }
7680 if (avatars.Count > 0)
7681 {
7682 foreach (ScenePresence avatar in avatars)
7683 SetPrimParams(avatar, rules);
7684 }
7192 } 7685 }
7193 7686
7194 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7687 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7688 float material_density, float material_friction,
7689 float material_restitution, float material_gravity_modifier)
7195 { 7690 {
7196 m_host.AddScriptLPS(1); 7691 ExtraPhysicsData physdata = new ExtraPhysicsData();
7692 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7693 physdata.Density = part.Density;
7694 physdata.Friction = part.Friction;
7695 physdata.Bounce = part.Bounciness;
7696 physdata.GravitationModifier = part.GravityModifier;
7197 7697
7198 setLinkPrimParams(linknumber, rules); 7698 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7699 physdata.Density = material_density;
7700 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7701 physdata.Friction = material_friction;
7702 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7703 physdata.Bounce = material_restitution;
7704 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7705 physdata.GravitationModifier = material_gravity_modifier;
7706
7707 part.UpdateExtraPhysics(physdata);
7199 } 7708 }
7200 7709
7201 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7710 public void llSetPhysicsMaterial(int material_bits,
7711 float material_gravity_modifier, float material_restitution,
7712 float material_friction, float material_density)
7202 { 7713 {
7203 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7714 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7715 }
7204 7716
7205 foreach (SceneObjectPart part in parts) 7717 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7206 SetPrimParams(part, rules); 7718 {
7719 llSetLinkPrimitiveParamsFast(linknumber, rules);
7720 ScriptSleep(200);
7721 }
7722
7723 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7724 {
7725 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7726 //We only support PRIM_POSITION and PRIM_ROTATION
7727
7728 int idx = 0;
7729
7730 while (idx < rules.Length)
7731 {
7732 int code = rules.GetLSLIntegerItem(idx++);
7733
7734 int remain = rules.Length - idx;
7735
7736 switch (code)
7737 {
7738 case (int)ScriptBaseClass.PRIM_POSITION:
7739 {
7740 if (remain < 1)
7741 return;
7742 LSL_Vector v;
7743 v = rules.GetVector3Item(idx++);
7744
7745 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7746 if (part == null)
7747 break;
7748
7749 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7750 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7751 if (llGetLinkNumber() > 1)
7752 {
7753 localRot = llGetLocalRot();
7754 localPos = llGetLocalPos();
7755 }
7756
7757 v -= localPos;
7758 v /= localRot;
7759
7760 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
7761
7762 v = v + 2 * sitOffset;
7763
7764 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7765 av.SendAvatarDataToAllAgents();
7766
7767 }
7768 break;
7769
7770 case (int)ScriptBaseClass.PRIM_ROTATION:
7771 {
7772 if (remain < 1)
7773 return;
7774
7775 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7776 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7777 if (llGetLinkNumber() > 1)
7778 {
7779 localRot = llGetLocalRot();
7780 localPos = llGetLocalPos();
7781 }
7782
7783 LSL_Rotation r;
7784 r = rules.GetQuaternionItem(idx++);
7785 r = r * llGetRootRotation() / localRot;
7786 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7787 av.SendAvatarDataToAllAgents();
7788 }
7789 break;
7790 }
7791 }
7207 } 7792 }
7208 7793
7209 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7794 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7210 { 7795 {
7796 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7797 return;
7798
7211 int idx = 0; 7799 int idx = 0;
7212 7800
7213 bool positionChanged = false; 7801 bool positionChanged = false;
@@ -7529,6 +8117,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7529 part.ScriptSetPhysicsStatus(physics); 8117 part.ScriptSetPhysicsStatus(physics);
7530 break; 8118 break;
7531 8119
8120 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
8121 if (remain < 1)
8122 return;
8123
8124 int shape_type = rules.GetLSLIntegerItem(idx++);
8125
8126 ExtraPhysicsData physdata = new ExtraPhysicsData();
8127 physdata.Density = part.Density;
8128 physdata.Bounce = part.Bounciness;
8129 physdata.GravitationModifier = part.GravityModifier;
8130 physdata.PhysShapeType = (PhysShapeType)shape_type;
8131
8132 part.UpdateExtraPhysics(physdata);
8133
8134 break;
8135
8136 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8137 if (remain < 5)
8138 return;
8139
8140 int material_bits = rules.GetLSLIntegerItem(idx++);
8141 float material_density = (float)rules.GetLSLFloatItem(idx++);
8142 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8143 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8144 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8145
8146 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8147
8148 break;
8149
7532 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8150 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7533 if (remain < 1) 8151 if (remain < 1)
7534 return; 8152 return;
@@ -7602,7 +8220,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7602 if (part.ParentGroup.RootPart == part) 8220 if (part.ParentGroup.RootPart == part)
7603 { 8221 {
7604 SceneObjectGroup parent = part.ParentGroup; 8222 SceneObjectGroup parent = part.ParentGroup;
7605 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8223 Util.FireAndForget(delegate(object x) {
8224 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8225 });
7606 } 8226 }
7607 else 8227 else
7608 { 8228 {
@@ -7613,6 +8233,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7613 } 8233 }
7614 } 8234 }
7615 } 8235 }
8236
8237 if (positionChanged)
8238 {
8239 if (part.ParentGroup.RootPart == part)
8240 {
8241 SceneObjectGroup parent = part.ParentGroup;
8242 Util.FireAndForget(delegate(object x) {
8243 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8244 });
8245 }
8246 else
8247 {
8248 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8249 SceneObjectGroup parent = part.ParentGroup;
8250 parent.HasGroupChanged = true;
8251 parent.ScheduleGroupForTerseUpdate();
8252 }
8253 }
7616 } 8254 }
7617 8255
7618 public LSL_String llStringToBase64(string str) 8256 public LSL_String llStringToBase64(string str)
@@ -7773,13 +8411,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7773 public LSL_Integer llGetNumberOfPrims() 8411 public LSL_Integer llGetNumberOfPrims()
7774 { 8412 {
7775 m_host.AddScriptLPS(1); 8413 m_host.AddScriptLPS(1);
7776 int avatarCount = 0; 8414 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7777 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8415
7778 {
7779 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
7780 avatarCount++;
7781 });
7782
7783 return m_host.ParentGroup.PrimCount + avatarCount; 8416 return m_host.ParentGroup.PrimCount + avatarCount;
7784 } 8417 }
7785 8418
@@ -7795,55 +8428,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7795 m_host.AddScriptLPS(1); 8428 m_host.AddScriptLPS(1);
7796 UUID objID = UUID.Zero; 8429 UUID objID = UUID.Zero;
7797 LSL_List result = new LSL_List(); 8430 LSL_List result = new LSL_List();
8431
8432 // If the ID is not valid, return null result
7798 if (!UUID.TryParse(obj, out objID)) 8433 if (!UUID.TryParse(obj, out objID))
7799 { 8434 {
7800 result.Add(new LSL_Vector()); 8435 result.Add(new LSL_Vector());
7801 result.Add(new LSL_Vector()); 8436 result.Add(new LSL_Vector());
7802 return result; 8437 return result;
7803 } 8438 }
8439
8440 // Check if this is an attached prim. If so, replace
8441 // the UUID with the avatar UUID and report it's bounding box
8442 SceneObjectPart part = World.GetSceneObjectPart(objID);
8443 if (part != null && part.ParentGroup.IsAttachment)
8444 objID = part.ParentGroup.AttachedAvatar;
8445
8446 // Find out if this is an avatar ID. If so, return it's box
7804 ScenePresence presence = World.GetScenePresence(objID); 8447 ScenePresence presence = World.GetScenePresence(objID);
7805 if (presence != null) 8448 if (presence != null)
7806 { 8449 {
7807 if (presence.ParentID == 0) // not sat on an object 8450 // As per LSL Wiki, there is no difference between sitting
8451 // and standing avatar since server 1.36
8452 LSL_Vector lower;
8453 LSL_Vector upper;
8454 if (presence.Animator.Animations.DefaultAnimation.AnimID
8455 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7808 { 8456 {
7809 LSL_Vector lower; 8457 // This is for ground sitting avatars
7810 LSL_Vector upper; 8458 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7811 if (presence.Animator.Animations.DefaultAnimation.AnimID 8459 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7812 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8460 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7813 {
7814 // This is for ground sitting avatars
7815 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7816 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7817 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7818 }
7819 else
7820 {
7821 // This is for standing/flying avatars
7822 float height = presence.Appearance.AvatarHeight / 2.0f;
7823 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7824 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7825 }
7826 result.Add(lower);
7827 result.Add(upper);
7828 return result;
7829 } 8461 }
7830 else 8462 else
7831 { 8463 {
7832 // sitting on an object so we need the bounding box of that 8464 // This is for standing/flying avatars
7833 // which should include the avatar so set the UUID to the 8465 float height = presence.Appearance.AvatarHeight / 2.0f;
7834 // UUID of the object the avatar is sat on and allow it to fall through 8466 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7835 // to processing an object 8467 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7836 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7837 objID = p.UUID;
7838 } 8468 }
8469
8470 // Adjust to the documented error offsets (see LSL Wiki)
8471 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8472 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8473
8474 if (lower.x > upper.x)
8475 lower.x = upper.x;
8476 if (lower.y > upper.y)
8477 lower.y = upper.y;
8478 if (lower.z > upper.z)
8479 lower.z = upper.z;
8480
8481 result.Add(lower);
8482 result.Add(upper);
8483 return result;
7839 } 8484 }
7840 SceneObjectPart part = World.GetSceneObjectPart(objID); 8485
8486 part = World.GetSceneObjectPart(objID);
7841 // Currently only works for single prims without a sitting avatar 8487 // Currently only works for single prims without a sitting avatar
7842 if (part != null) 8488 if (part != null)
7843 { 8489 {
7844 Vector3 halfSize = part.Scale / 2.0f; 8490 float minX;
7845 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8491 float maxX;
7846 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8492 float minY;
8493 float maxY;
8494 float minZ;
8495 float maxZ;
8496
8497 // This BBox is in sim coordinates, with the offset being
8498 // a contained point.
8499 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8500 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8501
8502 minX -= offsets[0].X;
8503 maxX -= offsets[0].X;
8504 minY -= offsets[0].Y;
8505 maxY -= offsets[0].Y;
8506 minZ -= offsets[0].Z;
8507 maxZ -= offsets[0].Z;
8508
8509 LSL_Vector lower;
8510 LSL_Vector upper;
8511
8512 // Adjust to the documented error offsets (see LSL Wiki)
8513 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8514 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8515
8516 if (lower.x > upper.x)
8517 lower.x = upper.x;
8518 if (lower.y > upper.y)
8519 lower.y = upper.y;
8520 if (lower.z > upper.z)
8521 lower.z = upper.z;
8522
7847 result.Add(lower); 8523 result.Add(lower);
7848 result.Add(upper); 8524 result.Add(upper);
7849 return result; 8525 return result;
@@ -7857,7 +8533,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7857 8533
7858 public LSL_Vector llGetGeometricCenter() 8534 public LSL_Vector llGetGeometricCenter()
7859 { 8535 {
7860 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 8536 Vector3 tmp = m_host.GetGeometricCenter();
8537 return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
7861 } 8538 }
7862 8539
7863 public LSL_List llGetPrimitiveParams(LSL_List rules) 8540 public LSL_List llGetPrimitiveParams(LSL_List rules)
@@ -7923,13 +8600,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7923 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8600 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7924 part.AbsolutePosition.Y, 8601 part.AbsolutePosition.Y,
7925 part.AbsolutePosition.Z); 8602 part.AbsolutePosition.Z);
7926 // For some reason, the part.AbsolutePosition.* values do not change if the
7927 // linkset is rotated; they always reflect the child prim's world position
7928 // as though the linkset is unrotated. This is incompatible behavior with SL's
7929 // implementation, so will break scripts imported from there (not to mention it
7930 // makes it more difficult to determine a child prim's actual inworld position).
7931 if (part.ParentID != 0)
7932 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7933 res.Add(v); 8603 res.Add(v);
7934 break; 8604 break;
7935 8605
@@ -8100,56 +8770,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8100 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8770 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8101 if (remain < 1) 8771 if (remain < 1)
8102 return res; 8772 return res;
8103 8773 face = (int)rules.GetLSLIntegerItem(idx++);
8104 face=(int)rules.GetLSLIntegerItem(idx++);
8105 8774
8106 tex = part.Shape.Textures; 8775 tex = part.Shape.Textures;
8776 int shiny;
8107 if (face == ScriptBaseClass.ALL_SIDES) 8777 if (face == ScriptBaseClass.ALL_SIDES)
8108 { 8778 {
8109 for (face = 0; face < GetNumberOfSides(part); face++) 8779 for (face = 0; face < GetNumberOfSides(part); face++)
8110 { 8780 {
8111 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8781 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8112 // Convert Shininess to PRIM_SHINY_* 8782 if (shinyness == Shininess.High)
8113 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8783 {
8114 // PRIM_BUMP_* 8784 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8115 res.Add(new LSL_Integer((int)texface.Bump)); 8785 }
8786 else if (shinyness == Shininess.Medium)
8787 {
8788 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8789 }
8790 else if (shinyness == Shininess.Low)
8791 {
8792 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8793 }
8794 else
8795 {
8796 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8797 }
8798 res.Add(new LSL_Integer(shiny));
8799 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8116 } 8800 }
8117 } 8801 }
8118 else 8802 else
8119 { 8803 {
8120 if (face >= 0 && face < GetNumberOfSides(part)) 8804 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8805 if (shinyness == Shininess.High)
8121 { 8806 {
8122 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8807 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8123 // Convert Shininess to PRIM_SHINY_* 8808 }
8124 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8809 else if (shinyness == Shininess.Medium)
8125 // PRIM_BUMP_* 8810 {
8126 res.Add(new LSL_Integer((int)texface.Bump)); 8811 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8127 } 8812 }
8813 else if (shinyness == Shininess.Low)
8814 {
8815 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8816 }
8817 else
8818 {
8819 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8820 }
8821 res.Add(new LSL_Integer(shiny));
8822 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8128 } 8823 }
8129 break; 8824 break;
8130 8825
8131 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8826 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8132 if (remain < 1) 8827 if (remain < 1)
8133 return res; 8828 return res;
8134 8829 face = (int)rules.GetLSLIntegerItem(idx++);
8135 face=(int)rules.GetLSLIntegerItem(idx++);
8136 8830
8137 tex = part.Shape.Textures; 8831 tex = part.Shape.Textures;
8832 int fullbright;
8138 if (face == ScriptBaseClass.ALL_SIDES) 8833 if (face == ScriptBaseClass.ALL_SIDES)
8139 { 8834 {
8140 for (face = 0; face < GetNumberOfSides(part); face++) 8835 for (face = 0; face < GetNumberOfSides(part); face++)
8141 { 8836 {
8142 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8837 if (tex.GetFace((uint)face).Fullbright == true)
8143 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8838 {
8839 fullbright = ScriptBaseClass.TRUE;
8840 }
8841 else
8842 {
8843 fullbright = ScriptBaseClass.FALSE;
8844 }
8845 res.Add(new LSL_Integer(fullbright));
8144 } 8846 }
8145 } 8847 }
8146 else 8848 else
8147 { 8849 {
8148 if (face >= 0 && face < GetNumberOfSides(part)) 8850 if (tex.GetFace((uint)face).Fullbright == true)
8149 { 8851 {
8150 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8852 fullbright = ScriptBaseClass.TRUE;
8151 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
8152 } 8853 }
8854 else
8855 {
8856 fullbright = ScriptBaseClass.FALSE;
8857 }
8858 res.Add(new LSL_Integer(fullbright));
8153 } 8859 }
8154 break; 8860 break;
8155 8861
@@ -8171,27 +8877,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8171 break; 8877 break;
8172 8878
8173 case (int)ScriptBaseClass.PRIM_TEXGEN: 8879 case (int)ScriptBaseClass.PRIM_TEXGEN:
8880 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8174 if (remain < 1) 8881 if (remain < 1)
8175 return res; 8882 return res;
8176 8883 face = (int)rules.GetLSLIntegerItem(idx++);
8177 face=(int)rules.GetLSLIntegerItem(idx++);
8178 8884
8179 tex = part.Shape.Textures; 8885 tex = part.Shape.Textures;
8180 if (face == ScriptBaseClass.ALL_SIDES) 8886 if (face == ScriptBaseClass.ALL_SIDES)
8181 { 8887 {
8182 for (face = 0; face < GetNumberOfSides(part); face++) 8888 for (face = 0; face < GetNumberOfSides(part); face++)
8183 { 8889 {
8184 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8890 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8185 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8891 {
8186 res.Add(new LSL_Integer((uint)texgen >> 1)); 8892 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8893 }
8894 else
8895 {
8896 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8897 }
8187 } 8898 }
8188 } 8899 }
8189 else 8900 else
8190 { 8901 {
8191 if (face >= 0 && face < GetNumberOfSides(part)) 8902 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8903 {
8904 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8905 }
8906 else
8192 { 8907 {
8193 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8908 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8194 res.Add(new LSL_Integer((uint)texgen >> 1));
8195 } 8909 }
8196 } 8910 }
8197 break; 8911 break;
@@ -8214,28 +8928,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8214 case (int)ScriptBaseClass.PRIM_GLOW: 8928 case (int)ScriptBaseClass.PRIM_GLOW:
8215 if (remain < 1) 8929 if (remain < 1)
8216 return res; 8930 return res;
8217 8931 face = (int)rules.GetLSLIntegerItem(idx++);
8218 face=(int)rules.GetLSLIntegerItem(idx++);
8219 8932
8220 tex = part.Shape.Textures; 8933 tex = part.Shape.Textures;
8934 float primglow;
8221 if (face == ScriptBaseClass.ALL_SIDES) 8935 if (face == ScriptBaseClass.ALL_SIDES)
8222 { 8936 {
8223 for (face = 0; face < GetNumberOfSides(part); face++) 8937 for (face = 0; face < GetNumberOfSides(part); face++)
8224 { 8938 {
8225 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8939 primglow = tex.GetFace((uint)face).Glow;
8226 res.Add(new LSL_Float(texface.Glow)); 8940 res.Add(new LSL_Float(primglow));
8227 } 8941 }
8228 } 8942 }
8229 else 8943 else
8230 { 8944 {
8231 if (face >= 0 && face < GetNumberOfSides(part)) 8945 primglow = tex.GetFace((uint)face).Glow;
8232 { 8946 res.Add(new LSL_Float(primglow));
8233 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8234 res.Add(new LSL_Float(texface.Glow));
8235 }
8236 } 8947 }
8237 break; 8948 break;
8238
8239 case (int)ScriptBaseClass.PRIM_TEXT: 8949 case (int)ScriptBaseClass.PRIM_TEXT:
8240 Color4 textColor = part.GetTextColor(); 8950 Color4 textColor = part.GetTextColor();
8241 res.Add(new LSL_String(part.Text)); 8951 res.Add(new LSL_String(part.Text));
@@ -8848,8 +9558,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8848 // The function returns an ordered list 9558 // The function returns an ordered list
8849 // representing the tokens found in the supplied 9559 // representing the tokens found in the supplied
8850 // sources string. If two successive tokenizers 9560 // sources string. If two successive tokenizers
8851 // are encountered, then a NULL entry is added 9561 // are encountered, then a null-string entry is
8852 // to the list. 9562 // added to the list.
8853 // 9563 //
8854 // It is a precondition that the source and 9564 // It is a precondition that the source and
8855 // toekizer lisst are non-null. If they are null, 9565 // toekizer lisst are non-null. If they are null,
@@ -8857,7 +9567,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8857 // while their lengths are being determined. 9567 // while their lengths are being determined.
8858 // 9568 //
8859 // A small amount of working memoryis required 9569 // A small amount of working memoryis required
8860 // of approximately 8*#tokenizers. 9570 // of approximately 8*#tokenizers + 8*srcstrlen.
8861 // 9571 //
8862 // There are many ways in which this function 9572 // There are many ways in which this function
8863 // can be implemented, this implementation is 9573 // can be implemented, this implementation is
@@ -8873,155 +9583,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8873 // and eliminates redundant tokenizers as soon 9583 // and eliminates redundant tokenizers as soon
8874 // as is possible. 9584 // as is possible.
8875 // 9585 //
8876 // The implementation tries to avoid any copying 9586 // The implementation tries to minimize temporary
8877 // of arrays or other objects. 9587 // garbage generation.
8878 // </remarks> 9588 // </remarks>
8879 9589
8880 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9590 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8881 { 9591 {
8882 int beginning = 0; 9592 return ParseString2List(src, separators, spacers, true);
8883 int srclen = src.Length; 9593 }
8884 int seplen = separators.Length;
8885 object[] separray = separators.Data;
8886 int spclen = spacers.Length;
8887 object[] spcarray = spacers.Data;
8888 int mlen = seplen+spclen;
8889
8890 int[] offset = new int[mlen+1];
8891 bool[] active = new bool[mlen];
8892
8893 int best;
8894 int j;
8895
8896 // Initial capacity reduces resize cost
8897 9594
8898 LSL_List tokens = new LSL_List(); 9595 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9596 {
9597 int srclen = src.Length;
9598 int seplen = separators.Length;
9599 object[] separray = separators.Data;
9600 int spclen = spacers.Length;
9601 object[] spcarray = spacers.Data;
9602 int dellen = 0;
9603 string[] delarray = new string[seplen+spclen];
8899 9604
8900 // All entries are initially valid 9605 int outlen = 0;
9606 string[] outarray = new string[srclen*2+1];
8901 9607
8902 for (int i = 0; i < mlen; i++) 9608 int i, j;
8903 active[i] = true; 9609 string d;
8904 9610
8905 offset[mlen] = srclen; 9611 m_host.AddScriptLPS(1);
8906 9612
8907 while (beginning < srclen) 9613 /*
9614 * Convert separator and spacer lists to C# strings.
9615 * Also filter out null strings so we don't hang.
9616 */
9617 for (i = 0; i < seplen; i ++)
8908 { 9618 {
9619 d = separray[i].ToString();
9620 if (d.Length > 0)
9621 {
9622 delarray[dellen++] = d;
9623 }
9624 }
9625 seplen = dellen;
8909 9626
8910 best = mlen; // as bad as it gets 9627 for (i = 0; i < spclen; i ++)
9628 {
9629 d = spcarray[i].ToString();
9630 if (d.Length > 0)
9631 {
9632 delarray[dellen++] = d;
9633 }
9634 }
8911 9635
8912 // Scan for separators 9636 /*
9637 * Scan through source string from beginning to end.
9638 */
9639 for (i = 0;;)
9640 {
8913 9641
8914 for (j = 0; j < seplen; j++) 9642 /*
9643 * Find earliest delimeter in src starting at i (if any).
9644 */
9645 int earliestDel = -1;
9646 int earliestSrc = srclen;
9647 string earliestStr = null;
9648 for (j = 0; j < dellen; j ++)
8915 { 9649 {
8916 if (separray[j].ToString() == String.Empty) 9650 d = delarray[j];
8917 active[j] = false; 9651 if (d != null)
8918
8919 if (active[j])
8920 { 9652 {
8921 // scan all of the markers 9653 int index = src.IndexOf(d, i);
8922 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9654 if (index < 0)
8923 { 9655 {
8924 // not present at all 9656 delarray[j] = null; // delim nowhere in src, don't check it anymore
8925 active[j] = false;
8926 } 9657 }
8927 else 9658 else if (index < earliestSrc)
8928 { 9659 {
8929 // present and correct 9660 earliestSrc = index; // where delimeter starts in source string
8930 if (offset[j] < offset[best]) 9661 earliestDel = j; // where delimeter is in delarray[]
8931 { 9662 earliestStr = d; // the delimeter string from delarray[]
8932 // closest so far 9663 if (index == i) break; // can't do any better than found at beg of string
8933 best = j;
8934 if (offset[best] == beginning)
8935 break;
8936 }
8937 } 9664 }
8938 } 9665 }
8939 } 9666 }
8940 9667
8941 // Scan for spacers 9668 /*
8942 9669 * Output source string starting at i through start of earliest delimeter.
8943 if (offset[best] != beginning) 9670 */
9671 if (keepNulls || (earliestSrc > i))
8944 { 9672 {
8945 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9673 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8946 {
8947 if (spcarray[j-seplen].ToString() == String.Empty)
8948 active[j] = false;
8949
8950 if (active[j])
8951 {
8952 // scan all of the markers
8953 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8954 {
8955 // not present at all
8956 active[j] = false;
8957 }
8958 else
8959 {
8960 // present and correct
8961 if (offset[j] < offset[best])
8962 {
8963 // closest so far
8964 best = j;
8965 }
8966 }
8967 }
8968 }
8969 } 9674 }
8970 9675
8971 // This is the normal exit from the scanning loop 9676 /*
9677 * If no delimeter found at or after i, we're done scanning.
9678 */
9679 if (earliestDel < 0) break;
8972 9680
8973 if (best == mlen) 9681 /*
9682 * If delimeter was a spacer, output the spacer.
9683 */
9684 if (earliestDel >= seplen)
8974 { 9685 {
8975 // no markers were found on this pass 9686 outarray[outlen++] = earliestStr;
8976 // so we're pretty much done
8977 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8978 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8979 break;
8980 } 9687 }
8981 9688
8982 // Otherwise we just add the newly delimited token 9689 /*
8983 // and recalculate where the search should continue. 9690 * Look at rest of src string following delimeter.
8984 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9691 */
8985 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9692 i = earliestSrc + earliestStr.Length;
8986
8987 if (best < seplen)
8988 {
8989 beginning = offset[best] + (separray[best].ToString()).Length;
8990 }
8991 else
8992 {
8993 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8994 string str = spcarray[best - seplen].ToString();
8995 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8996 tokens.Add(new LSL_String(str));
8997 }
8998 } 9693 }
8999 9694
9000 // This an awkward an not very intuitive boundary case. If the 9695 /*
9001 // last substring is a tokenizer, then there is an implied trailing 9696 * Make up an exact-sized output array suitable for an LSL_List object.
9002 // null list entry. Hopefully the single comparison will not be too 9697 */
9003 // arduous. Alternatively the 'break' could be replced with a return 9698 object[] outlist = new object[outlen];
9004 // but that's shabby programming. 9699 for (i = 0; i < outlen; i ++)
9005
9006 if ((beginning == srclen) && (keepNulls))
9007 { 9700 {
9008 if (srclen != 0) 9701 outlist[i] = new LSL_String(outarray[i]);
9009 tokens.Add(new LSL_String(""));
9010 } 9702 }
9011 9703 return new LSL_List(outlist);
9012 return tokens;
9013 }
9014
9015 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
9016 {
9017 m_host.AddScriptLPS(1);
9018 return this.ParseString(src, separators, spacers, false);
9019 }
9020
9021 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
9022 {
9023 m_host.AddScriptLPS(1);
9024 return this.ParseString(src, separators, spacers, true);
9025 } 9704 }
9026 9705
9027 public LSL_Integer llGetObjectPermMask(int mask) 9706 public LSL_Integer llGetObjectPermMask(int mask)
@@ -9098,28 +9777,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9098 { 9777 {
9099 m_host.AddScriptLPS(1); 9778 m_host.AddScriptLPS(1);
9100 9779
9101 lock (m_host.TaskInventory) 9780 m_host.TaskInventory.LockItemsForRead(true);
9781 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9102 { 9782 {
9103 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9783 if (inv.Value.Name == item)
9104 { 9784 {
9105 if (inv.Value.Name == item) 9785 m_host.TaskInventory.LockItemsForRead(false);
9786 switch (mask)
9106 { 9787 {
9107 switch (mask) 9788 case 0:
9108 { 9789 return (int)inv.Value.BasePermissions;
9109 case 0: 9790 case 1:
9110 return (int)inv.Value.BasePermissions; 9791 return (int)inv.Value.CurrentPermissions;
9111 case 1: 9792 case 2:
9112 return (int)inv.Value.CurrentPermissions; 9793 return (int)inv.Value.GroupPermissions;
9113 case 2: 9794 case 3:
9114 return (int)inv.Value.GroupPermissions; 9795 return (int)inv.Value.EveryonePermissions;
9115 case 3: 9796 case 4:
9116 return (int)inv.Value.EveryonePermissions; 9797 return (int)inv.Value.NextPermissions;
9117 case 4:
9118 return (int)inv.Value.NextPermissions;
9119 }
9120 } 9798 }
9121 } 9799 }
9122 } 9800 }
9801 m_host.TaskInventory.LockItemsForRead(false);
9123 9802
9124 return -1; 9803 return -1;
9125 } 9804 }
@@ -9166,16 +9845,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9166 { 9845 {
9167 m_host.AddScriptLPS(1); 9846 m_host.AddScriptLPS(1);
9168 9847
9169 lock (m_host.TaskInventory) 9848 m_host.TaskInventory.LockItemsForRead(true);
9849 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9170 { 9850 {
9171 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9851 if (inv.Value.Name == item)
9172 { 9852 {
9173 if (inv.Value.Name == item) 9853 m_host.TaskInventory.LockItemsForRead(false);
9174 { 9854 return inv.Value.CreatorID.ToString();
9175 return inv.Value.CreatorID.ToString();
9176 }
9177 } 9855 }
9178 } 9856 }
9857 m_host.TaskInventory.LockItemsForRead(false);
9179 9858
9180 llSay(0, "No item name '" + item + "'"); 9859 llSay(0, "No item name '" + item + "'");
9181 9860
@@ -9317,9 +9996,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9317 { 9996 {
9318 try 9997 try
9319 { 9998 {
9999 /*
9320 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 10000 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
9321 if (obj != null) 10001 if (obj != null)
9322 return (double)obj.GetMass(); 10002 return (double)obj.GetMass();
10003 */
10004 // return total object mass
10005 SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
10006 if (obj != null)
10007 return obj.GetMass();
10008
9323 // the object is null so the key is for an avatar 10009 // the object is null so the key is for an avatar
9324 ScenePresence avatar = World.GetScenePresence(key); 10010 ScenePresence avatar = World.GetScenePresence(key);
9325 if (avatar != null) 10011 if (avatar != null)
@@ -9339,7 +10025,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9339 } 10025 }
9340 10026
9341 /// <summary> 10027 /// <summary>
9342 /// illListReplaceList removes the sub-list defined by the inclusive indices 10028 /// llListReplaceList removes the sub-list defined by the inclusive indices
9343 /// start and end and inserts the src list in its place. The inclusive 10029 /// start and end and inserts the src list in its place. The inclusive
9344 /// nature of the indices means that at least one element must be deleted 10030 /// nature of the indices means that at least one element must be deleted
9345 /// if the indices are within the bounds of the existing list. I.e. 2,2 10031 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9396,16 +10082,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9396 // based upon end. Note that if end exceeds the upper 10082 // based upon end. Note that if end exceeds the upper
9397 // bound in this case, the entire destination list 10083 // bound in this case, the entire destination list
9398 // is removed. 10084 // is removed.
9399 else 10085 else if (start == 0)
9400 { 10086 {
9401 if (end + 1 < dest.Length) 10087 if (end + 1 < dest.Length)
9402 {
9403 return src + dest.GetSublist(end + 1, -1); 10088 return src + dest.GetSublist(end + 1, -1);
9404 }
9405 else 10089 else
9406 {
9407 return src; 10090 return src;
9408 } 10091 }
10092 else // Start < 0
10093 {
10094 if (end + 1 < dest.Length)
10095 return dest.GetSublist(end + 1, -1);
10096 else
10097 return new LSL_List();
9409 } 10098 }
9410 } 10099 }
9411 // Finally, if start > end, we strip away a prefix and 10100 // Finally, if start > end, we strip away a prefix and
@@ -9456,17 +10145,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9456 int width = 0; 10145 int width = 0;
9457 int height = 0; 10146 int height = 0;
9458 10147
9459 ParcelMediaCommandEnum? commandToSend = null; 10148 uint commandToSend = 0;
9460 float time = 0.0f; // default is from start 10149 float time = 0.0f; // default is from start
9461 10150
9462 ScenePresence presence = null; 10151 ScenePresence presence = null;
9463 10152
9464 for (int i = 0; i < commandList.Data.Length; i++) 10153 for (int i = 0; i < commandList.Data.Length; i++)
9465 { 10154 {
9466 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10155 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9467 switch (command) 10156 switch (command)
9468 { 10157 {
9469 case ParcelMediaCommandEnum.Agent: 10158 case (uint)ParcelMediaCommandEnum.Agent:
9470 // we send only to one agent 10159 // we send only to one agent
9471 if ((i + 1) < commandList.Length) 10160 if ((i + 1) < commandList.Length)
9472 { 10161 {
@@ -9483,25 +10172,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9483 } 10172 }
9484 break; 10173 break;
9485 10174
9486 case ParcelMediaCommandEnum.Loop: 10175 case (uint)ParcelMediaCommandEnum.Loop:
9487 loop = 1; 10176 loop = 1;
9488 commandToSend = command; 10177 commandToSend = command;
9489 update = true; //need to send the media update packet to set looping 10178 update = true; //need to send the media update packet to set looping
9490 break; 10179 break;
9491 10180
9492 case ParcelMediaCommandEnum.Play: 10181 case (uint)ParcelMediaCommandEnum.Play:
9493 loop = 0; 10182 loop = 0;
9494 commandToSend = command; 10183 commandToSend = command;
9495 update = true; //need to send the media update packet to make sure it doesn't loop 10184 update = true; //need to send the media update packet to make sure it doesn't loop
9496 break; 10185 break;
9497 10186
9498 case ParcelMediaCommandEnum.Pause: 10187 case (uint)ParcelMediaCommandEnum.Pause:
9499 case ParcelMediaCommandEnum.Stop: 10188 case (uint)ParcelMediaCommandEnum.Stop:
9500 case ParcelMediaCommandEnum.Unload: 10189 case (uint)ParcelMediaCommandEnum.Unload:
9501 commandToSend = command; 10190 commandToSend = command;
9502 break; 10191 break;
9503 10192
9504 case ParcelMediaCommandEnum.Url: 10193 case (uint)ParcelMediaCommandEnum.Url:
9505 if ((i + 1) < commandList.Length) 10194 if ((i + 1) < commandList.Length)
9506 { 10195 {
9507 if (commandList.Data[i + 1] is LSL_String) 10196 if (commandList.Data[i + 1] is LSL_String)
@@ -9514,7 +10203,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9514 } 10203 }
9515 break; 10204 break;
9516 10205
9517 case ParcelMediaCommandEnum.Texture: 10206 case (uint)ParcelMediaCommandEnum.Texture:
9518 if ((i + 1) < commandList.Length) 10207 if ((i + 1) < commandList.Length)
9519 { 10208 {
9520 if (commandList.Data[i + 1] is LSL_String) 10209 if (commandList.Data[i + 1] is LSL_String)
@@ -9527,7 +10216,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9527 } 10216 }
9528 break; 10217 break;
9529 10218
9530 case ParcelMediaCommandEnum.Time: 10219 case (uint)ParcelMediaCommandEnum.Time:
9531 if ((i + 1) < commandList.Length) 10220 if ((i + 1) < commandList.Length)
9532 { 10221 {
9533 if (commandList.Data[i + 1] is LSL_Float) 10222 if (commandList.Data[i + 1] is LSL_Float)
@@ -9539,7 +10228,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9539 } 10228 }
9540 break; 10229 break;
9541 10230
9542 case ParcelMediaCommandEnum.AutoAlign: 10231 case (uint)ParcelMediaCommandEnum.AutoAlign:
9543 if ((i + 1) < commandList.Length) 10232 if ((i + 1) < commandList.Length)
9544 { 10233 {
9545 if (commandList.Data[i + 1] is LSL_Integer) 10234 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9553,7 +10242,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9553 } 10242 }
9554 break; 10243 break;
9555 10244
9556 case ParcelMediaCommandEnum.Type: 10245 case (uint)ParcelMediaCommandEnum.Type:
9557 if ((i + 1) < commandList.Length) 10246 if ((i + 1) < commandList.Length)
9558 { 10247 {
9559 if (commandList.Data[i + 1] is LSL_String) 10248 if (commandList.Data[i + 1] is LSL_String)
@@ -9566,7 +10255,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9566 } 10255 }
9567 break; 10256 break;
9568 10257
9569 case ParcelMediaCommandEnum.Desc: 10258 case (uint)ParcelMediaCommandEnum.Desc:
9570 if ((i + 1) < commandList.Length) 10259 if ((i + 1) < commandList.Length)
9571 { 10260 {
9572 if (commandList.Data[i + 1] is LSL_String) 10261 if (commandList.Data[i + 1] is LSL_String)
@@ -9579,7 +10268,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9579 } 10268 }
9580 break; 10269 break;
9581 10270
9582 case ParcelMediaCommandEnum.Size: 10271 case (uint)ParcelMediaCommandEnum.Size:
9583 if ((i + 2) < commandList.Length) 10272 if ((i + 2) < commandList.Length)
9584 { 10273 {
9585 if (commandList.Data[i + 1] is LSL_Integer) 10274 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9649,7 +10338,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9649 } 10338 }
9650 } 10339 }
9651 10340
9652 if (commandToSend != null) 10341 if (commandToSend != 0)
9653 { 10342 {
9654 // the commandList contained a start/stop/... command, too 10343 // the commandList contained a start/stop/... command, too
9655 if (presence == null) 10344 if (presence == null)
@@ -9686,7 +10375,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9686 10375
9687 if (aList.Data[i] != null) 10376 if (aList.Data[i] != null)
9688 { 10377 {
9689 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10378 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9690 { 10379 {
9691 case ParcelMediaCommandEnum.Url: 10380 case ParcelMediaCommandEnum.Url:
9692 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10381 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9729,16 +10418,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9729 { 10418 {
9730 m_host.AddScriptLPS(1); 10419 m_host.AddScriptLPS(1);
9731 10420
9732 lock (m_host.TaskInventory) 10421 m_host.TaskInventory.LockItemsForRead(true);
10422 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9733 { 10423 {
9734 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10424 if (inv.Value.Name == name)
9735 { 10425 {
9736 if (inv.Value.Name == name) 10426 m_host.TaskInventory.LockItemsForRead(false);
9737 { 10427 return inv.Value.Type;
9738 return inv.Value.Type;
9739 }
9740 } 10428 }
9741 } 10429 }
10430 m_host.TaskInventory.LockItemsForRead(false);
9742 10431
9743 return -1; 10432 return -1;
9744 } 10433 }
@@ -9749,15 +10438,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9749 10438
9750 if (quick_pay_buttons.Data.Length < 4) 10439 if (quick_pay_buttons.Data.Length < 4)
9751 { 10440 {
9752 LSLError("List must have at least 4 elements"); 10441 int x;
9753 return; 10442 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10443 {
10444 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10445 }
9754 } 10446 }
9755 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10447 int[] nPrice = new int[5];
9756 10448 nPrice[0] = price;
9757 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10449 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9758 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10450 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9759 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10451 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9760 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10452 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10453 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9761 m_host.ParentGroup.HasGroupChanged = true; 10454 m_host.ParentGroup.HasGroupChanged = true;
9762 } 10455 }
9763 10456
@@ -9774,7 +10467,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9774 return new LSL_Vector(); 10467 return new LSL_Vector();
9775 } 10468 }
9776 10469
9777 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10470// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10471 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9778 if (presence != null) 10472 if (presence != null)
9779 { 10473 {
9780 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); 10474 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
@@ -9796,7 +10490,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9796 return new LSL_Rotation(); 10490 return new LSL_Rotation();
9797 } 10491 }
9798 10492
9799 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10493// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10494 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9800 if (presence != null) 10495 if (presence != null)
9801 { 10496 {
9802 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); 10497 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W);
@@ -9856,8 +10551,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9856 { 10551 {
9857 m_host.AddScriptLPS(1); 10552 m_host.AddScriptLPS(1);
9858 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 10553 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
9859 if (detectedParams == null) return; // only works on the first detected avatar 10554 if (detectedParams == null)
9860 10555 {
10556 if (m_host.ParentGroup.IsAttachment == true)
10557 {
10558 detectedParams = new DetectParams();
10559 detectedParams.Key = m_host.OwnerID;
10560 }
10561 else
10562 {
10563 return;
10564 }
10565 }
10566
9861 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10567 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9862 if (avatar != null) 10568 if (avatar != null)
9863 { 10569 {
@@ -9865,6 +10571,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9865 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10571 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9866 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10572 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9867 } 10573 }
10574
9868 ScriptSleep(1000); 10575 ScriptSleep(1000);
9869 } 10576 }
9870 10577
@@ -9988,12 +10695,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9988 10695
9989 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10696 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9990 object[] data = rules.Data; 10697 object[] data = rules.Data;
9991 for (int i = 0; i < data.Length; ++i) { 10698 for (int i = 0; i < data.Length; ++i)
10699 {
9992 int type = Convert.ToInt32(data[i++].ToString()); 10700 int type = Convert.ToInt32(data[i++].ToString());
9993 if (i >= data.Length) break; // odd number of entries => ignore the last 10701 if (i >= data.Length) break; // odd number of entries => ignore the last
9994 10702
9995 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10703 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9996 switch (type) { 10704 switch (type)
10705 {
9997 case ScriptBaseClass.CAMERA_FOCUS: 10706 case ScriptBaseClass.CAMERA_FOCUS:
9998 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10707 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9999 case ScriptBaseClass.CAMERA_POSITION: 10708 case ScriptBaseClass.CAMERA_POSITION:
@@ -10099,19 +10808,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10099 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10808 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
10100 { 10809 {
10101 m_host.AddScriptLPS(1); 10810 m_host.AddScriptLPS(1);
10102 string ret = String.Empty; 10811
10103 string src1 = llBase64ToString(str1); 10812 if (str1 == String.Empty)
10104 string src2 = llBase64ToString(str2); 10813 return String.Empty;
10105 int c = 0; 10814 if (str2 == String.Empty)
10106 for (int i = 0; i < src1.Length; i++) 10815 return str1;
10816
10817 int len = str2.Length;
10818 if ((len % 4) != 0) // LL is EVIL!!!!
10107 { 10819 {
10108 ret += (char) (src1[i] ^ src2[c]); 10820 while (str2.EndsWith("="))
10821 str2 = str2.Substring(0, str2.Length - 1);
10822
10823 len = str2.Length;
10824 int mod = len % 4;
10825
10826 if (mod == 1)
10827 str2 = str2.Substring(0, str2.Length - 1);
10828 else if (mod == 2)
10829 str2 += "==";
10830 else if (mod == 3)
10831 str2 += "=";
10832 }
10109 10833
10110 c++; 10834 byte[] data1;
10111 if (c >= src2.Length) 10835 byte[] data2;
10112 c = 0; 10836 try
10837 {
10838 data1 = Convert.FromBase64String(str1);
10839 data2 = Convert.FromBase64String(str2);
10113 } 10840 }
10114 return llStringToBase64(ret); 10841 catch (Exception)
10842 {
10843 return new LSL_String(String.Empty);
10844 }
10845
10846 byte[] d2 = new Byte[data1.Length];
10847 int pos = 0;
10848
10849 if (data1.Length <= data2.Length)
10850 {
10851 Array.Copy(data2, 0, d2, 0, data1.Length);
10852 }
10853 else
10854 {
10855 while (pos < data1.Length)
10856 {
10857 len = data1.Length - pos;
10858 if (len > data2.Length)
10859 len = data2.Length;
10860
10861 Array.Copy(data2, 0, d2, pos, len);
10862 pos += len;
10863 }
10864 }
10865
10866 for (pos = 0 ; pos < data1.Length ; pos++ )
10867 data1[pos] ^= d2[pos];
10868
10869 return Convert.ToBase64String(data1);
10115 } 10870 }
10116 10871
10117 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10872 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10168,12 +10923,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10168 Regex r = new Regex(authregex); 10923 Regex r = new Regex(authregex);
10169 int[] gnums = r.GetGroupNumbers(); 10924 int[] gnums = r.GetGroupNumbers();
10170 Match m = r.Match(url); 10925 Match m = r.Match(url);
10171 if (m.Success) { 10926 if (m.Success)
10172 for (int i = 1; i < gnums.Length; i++) { 10927 {
10928 for (int i = 1; i < gnums.Length; i++)
10929 {
10173 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10930 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10174 //CaptureCollection cc = g.Captures; 10931 //CaptureCollection cc = g.Captures;
10175 } 10932 }
10176 if (m.Groups.Count == 5) { 10933 if (m.Groups.Count == 5)
10934 {
10177 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10935 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10178 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10936 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10179 } 10937 }
@@ -10536,15 +11294,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10536 11294
10537 internal UUID ScriptByName(string name) 11295 internal UUID ScriptByName(string name)
10538 { 11296 {
10539 lock (m_host.TaskInventory) 11297 m_host.TaskInventory.LockItemsForRead(true);
11298
11299 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10540 { 11300 {
10541 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 11301 if (item.Type == 10 && item.Name == name)
10542 { 11302 {
10543 if (item.Type == 10 && item.Name == name) 11303 m_host.TaskInventory.LockItemsForRead(false);
10544 return item.ItemID; 11304 return item.ItemID;
10545 } 11305 }
10546 } 11306 }
10547 11307
11308 m_host.TaskInventory.LockItemsForRead(false);
11309
10548 return UUID.Zero; 11310 return UUID.Zero;
10549 } 11311 }
10550 11312
@@ -10585,6 +11347,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10585 { 11347 {
10586 m_host.AddScriptLPS(1); 11348 m_host.AddScriptLPS(1);
10587 11349
11350 //Clone is thread safe
10588 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11351 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10589 11352
10590 UUID assetID = UUID.Zero; 11353 UUID assetID = UUID.Zero;
@@ -10647,6 +11410,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10647 { 11410 {
10648 m_host.AddScriptLPS(1); 11411 m_host.AddScriptLPS(1);
10649 11412
11413 //Clone is thread safe
10650 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11414 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10651 11415
10652 UUID assetID = UUID.Zero; 11416 UUID assetID = UUID.Zero;
@@ -10727,15 +11491,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10727 return GetLinkPrimitiveParams(obj, rules); 11491 return GetLinkPrimitiveParams(obj, rules);
10728 } 11492 }
10729 11493
10730 public void print(string str) 11494 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10731 { 11495 {
10732 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11496 List<SceneObjectPart> parts = GetLinkParts(link);
10733 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11497 if (parts.Count < 1)
10734 if (ossl != null) 11498 return 0;
10735 { 11499
10736 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11500 return GetNumberOfSides(parts[0]);
10737 m_log.Info("LSL print():" + str);
10738 }
10739 } 11501 }
10740 11502
10741 private string Name2Username(string name) 11503 private string Name2Username(string name)
@@ -10781,155 +11543,482 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10781 return rq.ToString(); 11543 return rq.ToString();
10782 } 11544 }
10783 11545
11546 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11547 {
11548 m_SayShoutCount = 0;
11549 }
11550
11551 private struct Tri
11552 {
11553 public Vector3 p1;
11554 public Vector3 p2;
11555 public Vector3 p3;
11556 }
11557
11558 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11559 {
11560 float height = avatar.Appearance.AvatarHeight;
11561 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11562 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11563
11564 if (point.X > b1.X && point.X < b2.X &&
11565 point.Y > b1.Y && point.Y < b2.Y &&
11566 point.Z > b1.Z && point.Z < b2.Z)
11567 return true;
11568 return false;
11569 }
11570
11571 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11572 {
11573 List<ContactResult> contacts = new List<ContactResult>();
11574
11575 Vector3 ab = rayEnd - rayStart;
11576
11577 World.ForEachScenePresence(delegate(ScenePresence sp)
11578 {
11579 Vector3 ac = sp.AbsolutePosition - rayStart;
11580 Vector3 bc = sp.AbsolutePosition - rayEnd;
11581
11582 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11583
11584 if (d > 1.5)
11585 return;
11586
11587 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11588
11589 if (d2 > 0)
11590 return;
11591
11592 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11593 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11594
11595 if (!InBoundingBox(sp, p))
11596 return;
11597
11598 ContactResult result = new ContactResult ();
11599 result.ConsumerID = sp.LocalId;
11600 result.Depth = Vector3.Distance(rayStart, p);
11601 result.Normal = Vector3.Zero;
11602 result.Pos = p;
11603
11604 contacts.Add(result);
11605 });
11606
11607 return contacts.ToArray();
11608 }
11609
11610 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11611 {
11612 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11613 List<ContactResult> contacts = new List<ContactResult>();
11614
11615 Vector3 ab = rayEnd - rayStart;
11616
11617 World.ForEachSOG(delegate(SceneObjectGroup group)
11618 {
11619 if (m_host.ParentGroup == group)
11620 return;
11621
11622 if (group.IsAttachment)
11623 return;
11624
11625 if (group.RootPart.PhysActor == null)
11626 {
11627 if (!includePhantom)
11628 return;
11629 }
11630 else
11631 {
11632 if (group.RootPart.PhysActor.IsPhysical)
11633 {
11634 if (!includePhysical)
11635 return;
11636 }
11637 else
11638 {
11639 if (!includeNonPhysical)
11640 return;
11641 }
11642 }
11643
11644 // Find the radius ouside of which we don't even need to hit test
11645 float minX;
11646 float maxX;
11647 float minY;
11648 float maxY;
11649 float minZ;
11650 float maxZ;
11651
11652 float radius = 0.0f;
11653
11654 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11655
11656 if (Math.Abs(minX) > radius)
11657 radius = Math.Abs(minX);
11658 if (Math.Abs(minY) > radius)
11659 radius = Math.Abs(minY);
11660 if (Math.Abs(minZ) > radius)
11661 radius = Math.Abs(minZ);
11662 if (Math.Abs(maxX) > radius)
11663 radius = Math.Abs(maxX);
11664 if (Math.Abs(maxY) > radius)
11665 radius = Math.Abs(maxY);
11666 if (Math.Abs(maxZ) > radius)
11667 radius = Math.Abs(maxZ);
11668
11669 Vector3 ac = group.AbsolutePosition - rayStart;
11670 Vector3 bc = group.AbsolutePosition - rayEnd;
11671
11672 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11673
11674 // Too far off ray, don't bother
11675 if (d > radius)
11676 return;
11677
11678 // Behind ray, drop
11679 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11680 if (d2 > 0)
11681 return;
11682
11683 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11684 // Miss.
11685 if (!intersection.HitTF)
11686 return;
11687
11688 ContactResult result = new ContactResult ();
11689 result.ConsumerID = group.LocalId;
11690 result.Depth = intersection.distance;
11691 result.Normal = intersection.normal;
11692 result.Pos = intersection.ipoint;
11693
11694 contacts.Add(result);
11695 });
11696
11697 return contacts.ToArray();
11698 }
11699
11700 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11701 {
11702 double[,] heightfield = World.Heightmap.GetDoubles();
11703 List<ContactResult> contacts = new List<ContactResult>();
11704
11705 double min = 2048.0;
11706 double max = 0.0;
11707
11708 // Find the min and max of the heightfield
11709 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11710 {
11711 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11712 {
11713 if (heightfield[x, y] > max)
11714 max = heightfield[x, y];
11715 if (heightfield[x, y] < min)
11716 min = heightfield[x, y];
11717 }
11718 }
11719
11720
11721 // A ray extends past rayEnd, but doesn't go back before
11722 // rayStart. If the start is above the highest point of the ground
11723 // and the ray goes up, we can't hit the ground. Ever.
11724 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11725 return null;
11726
11727 // Same for going down
11728 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11729 return null;
11730
11731 List<Tri> trilist = new List<Tri>();
11732
11733 // Create our triangle list
11734 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11735 {
11736 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11737 {
11738 Tri t1 = new Tri();
11739 Tri t2 = new Tri();
11740
11741 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11742 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11743 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11744 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11745
11746 t1.p1 = p1;
11747 t1.p2 = p2;
11748 t1.p3 = p3;
11749
11750 t2.p1 = p3;
11751 t2.p2 = p4;
11752 t2.p3 = p1;
11753
11754 trilist.Add(t1);
11755 trilist.Add(t2);
11756 }
11757 }
11758
11759 // Ray direction
11760 Vector3 rayDirection = rayEnd - rayStart;
11761
11762 foreach (Tri t in trilist)
11763 {
11764 // Compute triangle plane normal and edges
11765 Vector3 u = t.p2 - t.p1;
11766 Vector3 v = t.p3 - t.p1;
11767 Vector3 n = Vector3.Cross(u, v);
11768
11769 if (n == Vector3.Zero)
11770 continue;
11771
11772 Vector3 w0 = rayStart - t.p1;
11773 double a = -Vector3.Dot(n, w0);
11774 double b = Vector3.Dot(n, rayDirection);
11775
11776 // Not intersecting the plane, or in plane (same thing)
11777 // Ignoring this MAY cause the ground to not be detected
11778 // sometimes
11779 if (Math.Abs(b) < 0.000001)
11780 continue;
11781
11782 double r = a / b;
11783
11784 // ray points away from plane
11785 if (r < 0.0)
11786 continue;
11787
11788 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11789
11790 float uu = Vector3.Dot(u, u);
11791 float uv = Vector3.Dot(u, v);
11792 float vv = Vector3.Dot(v, v);
11793 Vector3 w = ip - t.p1;
11794 float wu = Vector3.Dot(w, u);
11795 float wv = Vector3.Dot(w, v);
11796 float d = uv * uv - uu * vv;
11797
11798 float cs = (uv * wv - vv * wu) / d;
11799 if (cs < 0 || cs > 1.0)
11800 continue;
11801 float ct = (uv * wu - uu * wv) / d;
11802 if (ct < 0 || (cs + ct) > 1.0)
11803 continue;
11804
11805 // Add contact point
11806 ContactResult result = new ContactResult ();
11807 result.ConsumerID = 0;
11808 result.Depth = Vector3.Distance(rayStart, ip);
11809 result.Normal = n;
11810 result.Pos = ip;
11811
11812 contacts.Add(result);
11813 }
11814
11815 if (contacts.Count == 0)
11816 return null;
11817
11818 contacts.Sort(delegate(ContactResult a, ContactResult b)
11819 {
11820 return (int)(a.Depth - b.Depth);
11821 });
11822
11823 return contacts[0];
11824 }
11825/*
11826 // not done:
11827 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
11828 {
11829 ContactResult[] contacts = null;
11830 World.ForEachSOG(delegate(SceneObjectGroup group)
11831 {
11832 if (m_host.ParentGroup == group)
11833 return;
11834
11835 if (group.IsAttachment)
11836 return;
11837
11838 if(group.RootPart.PhysActor != null)
11839 return;
11840
11841 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
11842 });
11843 return contacts;
11844 }
11845*/
11846
10784 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11847 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10785 { 11848 {
11849 LSL_List list = new LSL_List();
11850
10786 m_host.AddScriptLPS(1); 11851 m_host.AddScriptLPS(1);
10787 11852
10788 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11853 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10789 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11854 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10790 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11855 Vector3 dir = rayEnd - rayStart;
10791 11856
10792 int count = 0; 11857 float dist = Vector3.Mag(dir);
10793// int detectPhantom = 0; 11858
11859 int count = 1;
11860 bool detectPhantom = false;
10794 int dataFlags = 0; 11861 int dataFlags = 0;
10795 int rejectTypes = 0; 11862 int rejectTypes = 0;
10796 11863
10797 for (int i = 0; i < options.Length; i += 2) 11864 for (int i = 0; i < options.Length; i += 2)
10798 { 11865 {
10799 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11866 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10800 {
10801 count = options.GetLSLIntegerItem(i + 1); 11867 count = options.GetLSLIntegerItem(i + 1);
10802 } 11868 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10803// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11869 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10804// {
10805// detectPhantom = options.GetLSLIntegerItem(i + 1);
10806// }
10807 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11870 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10808 {
10809 dataFlags = options.GetLSLIntegerItem(i + 1); 11871 dataFlags = options.GetLSLIntegerItem(i + 1);
10810 }
10811 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11872 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10812 {
10813 rejectTypes = options.GetLSLIntegerItem(i + 1); 11873 rejectTypes = options.GetLSLIntegerItem(i + 1);
10814 }
10815 } 11874 }
10816 11875
10817 LSL_List list = new LSL_List(); 11876 if (count > 16)
10818 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11877 count = 16;
10819 11878
10820 double distance = Util.GetDistanceTo(startvector, endvector); 11879 List<ContactResult> results = new List<ContactResult>();
10821
10822 if (distance == 0)
10823 distance = 0.001;
10824
10825 Vector3 posToCheck = startvector;
10826 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10827 11880
10828 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11881 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10829 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11882 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10830 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11883 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10831 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11884 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10832 11885
10833 for (float i = 0; i <= distance; i += 0.1f) 11886
11887 if (World.SuportsRayCastFiltered())
10834 { 11888 {
10835 posToCheck = startvector + (dir * (i / (float)distance)); 11889 if (dist == 0)
11890 return list;
11891
11892 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
11893 if (checkTerrain)
11894 rayfilter |= RayFilterFlags.land;
11895// if (checkAgents)
11896// rayfilter |= RayFilterFlags.agent;
11897 if (checkPhysical)
11898 rayfilter |= RayFilterFlags.physical;
11899 if (checkNonPhysical)
11900 rayfilter |= RayFilterFlags.nonphysical;
11901 if (detectPhantom)
11902 rayfilter |= RayFilterFlags.LSLPhanton;
10836 11903
10837 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11904 Vector3 direction = dir * ( 1/dist);
11905
11906 if(rayfilter == 0)
10838 { 11907 {
10839 ContactResult result = new ContactResult(); 11908 list.Add(new LSL_Integer(0));
10840 result.ConsumerID = 0; 11909 return list;
10841 result.Depth = 0;
10842 result.Normal = Vector3.Zero;
10843 result.Pos = posToCheck;
10844 results.Add(result);
10845 checkTerrain = false;
10846 } 11910 }
10847 11911
10848 if (checkAgents) 11912 // get some more contacts to sort ???
11913 int physcount = 4 * count;
11914 if (physcount > 20)
11915 physcount = 20;
11916
11917 object physresults;
11918 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
11919
11920 if (physresults == null)
10849 { 11921 {
10850 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11922 list.Add(new LSL_Integer(-3)); // timeout error
10851 { 11923 return list;
10852 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X))
10853 {
10854 ContactResult result = new ContactResult ();
10855 result.ConsumerID = sp.LocalId;
10856 result.Depth = 0;
10857 result.Normal = Vector3.Zero;
10858 result.Pos = posToCheck;
10859 results.Add(result);
10860 }
10861 });
10862 } 11924 }
10863 }
10864 11925
10865 int refcount = 0; 11926 results = (List<ContactResult>)physresults;
10866 foreach (ContactResult result in results)
10867 {
10868 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND)
10869 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0)
10870 continue;
10871 11927
10872 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID); 11928 // for now physics doesn't detect sitted avatars so do it outside physics
11929 if (checkAgents)
11930 {
11931 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11932 foreach (ContactResult r in agentHits)
11933 results.Add(r);
11934 }
10873 11935
10874 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) 11936 // bug: will not detect phantom unless they are physical
10875 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents 11937 // don't use ObjectIntersection because its also bad
10876 11938
10877 if (entity == null) 11939 }
11940 else
11941 {
11942 if (checkTerrain)
10878 { 11943 {
10879 list.Add(UUID.Zero); 11944 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11945 if (groundContact != null)
11946 results.Add((ContactResult)groundContact);
11947 }
10880 11948
10881 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11949 if (checkAgents)
10882 list.Add(0); 11950 {
11951 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11952 foreach (ContactResult r in agentHits)
11953 results.Add(r);
11954 }
10883 11955
10884 list.Add(result.Pos); 11956 if (checkPhysical || checkNonPhysical || detectPhantom)
11957 {
11958 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
11959 foreach (ContactResult r in objectHits)
11960 results.Add(r);
11961 }
11962 }
10885 11963
10886 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11964 results.Sort(delegate(ContactResult a, ContactResult b)
10887 list.Add(result.Normal); 11965 {
11966 return a.Depth.CompareTo(b.Depth);
11967 });
11968
11969 int values = 0;
11970 SceneObjectGroup thisgrp = m_host.ParentGroup;
10888 11971
10889 continue; //Can't find it, so add UUID.Zero 11972 foreach (ContactResult result in results)
10890 } 11973 {
11974 if (result.Depth > dist)
11975 continue;
11976
11977 // physics ray can return colisions with host prim
11978 if (m_host.LocalId == result.ConsumerID)
11979 continue;
10891 11980
10892 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity && 11981 UUID itemID = UUID.Zero;
10893 ((ISceneChildEntity)intersection.obj).PhysActor == null) 11982 int linkNum = 0;
10894 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
10895 11983
10896 if (entity is SceneObjectPart) 11984 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
11985 // It's a prim!
11986 if (part != null)
10897 { 11987 {
10898 PhysicsActor pa = ((SceneObjectPart)entity).PhysActor; 11988 // dont detect members of same object ???
11989 if (part.ParentGroup == thisgrp)
11990 continue;
10899 11991
10900 if (pa != null && pa.IsPhysical) 11992 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10901 { 11993 itemID = part.ParentGroup.UUID;
10902 if (!checkPhysical)
10903 continue;
10904 }
10905 else 11994 else
10906 { 11995 itemID = part.UUID;
10907 if (!checkNonPhysical)
10908 continue;
10909 }
10910 }
10911 11996
10912 refcount++; 11997 linkNum = part.LinkNum;
10913 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11998 }
10914 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10915 else 11999 else
10916 list.Add(entity.UUID);
10917
10918 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10919 { 12000 {
10920 if (entity is SceneObjectPart) 12001 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10921 list.Add(((SceneObjectPart)entity).LinkNum); 12002 /// It it a boy? a girl?
10922 else 12003 if (sp != null)
10923 list.Add(0); 12004 itemID = sp.UUID;
10924 } 12005 }
10925 12006
10926 list.Add(result.Pos); 12007 list.Add(new LSL_String(itemID.ToString()));
12008 list.Add(new LSL_String(result.Pos.ToString()));
12009
12010 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
12011 list.Add(new LSL_Integer(linkNum));
10927 12012
10928 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 12013 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10929 list.Add(result.Normal); 12014 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
12015
12016 values++;
12017 if (values >= count)
12018 break;
10930 } 12019 }
10931 12020
10932 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 12021 list.Add(new LSL_Integer(values));
10933 12022
10934 return list; 12023 return list;
10935 } 12024 }
@@ -10969,7 +12058,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10969 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 12058 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10970 if (!isAccount) return 0; 12059 if (!isAccount) return 0;
10971 if (estate.HasAccess(id)) return 1; 12060 if (estate.HasAccess(id)) return 1;
10972 if (estate.IsBanned(id)) 12061 if (estate.IsBanned(id, World.GetUserFlags(id)))
10973 estate.RemoveBan(id); 12062 estate.RemoveBan(id);
10974 estate.AddEstateUser(id); 12063 estate.AddEstateUser(id);
10975 break; 12064 break;
@@ -10988,14 +12077,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10988 break; 12077 break;
10989 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 12078 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10990 if (!isAccount) return 0; 12079 if (!isAccount) return 0;
10991 if (estate.IsBanned(id)) return 1; 12080 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10992 EstateBan ban = new EstateBan(); 12081 EstateBan ban = new EstateBan();
10993 ban.EstateID = estate.EstateID; 12082 ban.EstateID = estate.EstateID;
10994 ban.BannedUserID = id; 12083 ban.BannedUserID = id;
10995 estate.AddBan(ban); 12084 estate.AddBan(ban);
10996 break; 12085 break;
10997 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 12086 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10998 if (!isAccount || !estate.IsBanned(id)) return 0; 12087 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10999 estate.RemoveBan(id); 12088 estate.RemoveBan(id);
11000 break; 12089 break;
11001 default: return 0; 12090 default: return 0;
@@ -11024,7 +12113,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11024 return 16384; 12113 return 16384;
11025 } 12114 }
11026 12115
11027 public LSL_Integer llGetUsedMemory() 12116 public virtual LSL_Integer llGetUsedMemory()
11028 { 12117 {
11029 m_host.AddScriptLPS(1); 12118 m_host.AddScriptLPS(1);
11030 // The value returned for LSO scripts in SL 12119 // The value returned for LSO scripts in SL
@@ -11052,7 +12141,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11052 public void llSetSoundQueueing(int queue) 12141 public void llSetSoundQueueing(int queue)
11053 { 12142 {
11054 m_host.AddScriptLPS(1); 12143 m_host.AddScriptLPS(1);
11055 NotImplemented("llSetSoundQueueing");
11056 } 12144 }
11057 12145
11058 public void llCollisionSprite(string impact_sprite) 12146 public void llCollisionSprite(string impact_sprite)
@@ -11064,10 +12152,270 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11064 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12152 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
11065 { 12153 {
11066 m_host.AddScriptLPS(1); 12154 m_host.AddScriptLPS(1);
11067 NotImplemented("llGodLikeRezObject"); 12155
12156 if (!World.Permissions.IsGod(m_host.OwnerID))
12157 NotImplemented("llGodLikeRezObject");
12158
12159 AssetBase rezAsset = World.AssetService.Get(inventory);
12160 if (rezAsset == null)
12161 {
12162 llSay(0, "Asset not found");
12163 return;
12164 }
12165
12166 SceneObjectGroup group = null;
12167
12168 try
12169 {
12170 string xmlData = Utils.BytesToString(rezAsset.Data);
12171 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12172 }
12173 catch
12174 {
12175 llSay(0, "Asset not found");
12176 return;
12177 }
12178
12179 if (group == null)
12180 {
12181 llSay(0, "Asset not found");
12182 return;
12183 }
12184
12185 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12186 group.RootPart.AttachOffset = group.AbsolutePosition;
12187
12188 group.ResetIDs();
12189
12190 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12191 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12192 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12193 group.ScheduleGroupForFullUpdate();
12194
12195 // objects rezzed with this method are die_at_edge by default.
12196 group.RootPart.SetDieAtEdge(true);
12197
12198 group.ResumeScripts();
12199
12200 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12201 "object_rez", new Object[] {
12202 new LSL_String(
12203 group.RootPart.UUID.ToString()) },
12204 new DetectParams[0]));
12205 }
12206
12207 public LSL_String llTransferLindenDollars(string destination, int amount)
12208 {
12209 UUID txn = UUID.Random();
12210
12211 Util.FireAndForget(delegate(object x)
12212 {
12213 int replycode = 0;
12214 string replydata = destination + "," + amount.ToString();
12215
12216 try
12217 {
12218 TaskInventoryItem item = m_item;
12219 if (item == null)
12220 {
12221 replydata = "SERVICE_ERROR";
12222 return;
12223 }
12224
12225 m_host.AddScriptLPS(1);
12226
12227 if (item.PermsGranter == UUID.Zero)
12228 {
12229 replydata = "MISSING_PERMISSION_DEBIT";
12230 return;
12231 }
12232
12233 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
12234 {
12235 replydata = "MISSING_PERMISSION_DEBIT";
12236 return;
12237 }
12238
12239 UUID toID = new UUID();
12240
12241 if (!UUID.TryParse(destination, out toID))
12242 {
12243 replydata = "INVALID_AGENT";
12244 return;
12245 }
12246
12247 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
12248
12249 if (money == null)
12250 {
12251 replydata = "TRANSFERS_DISABLED";
12252 return;
12253 }
12254
12255 bool result = money.ObjectGiveMoney(
12256 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
12257
12258 if (result)
12259 {
12260 replycode = 1;
12261 return;
12262 }
12263
12264 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
12265 }
12266 finally
12267 {
12268 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
12269 "transaction_result", new Object[] {
12270 new LSL_String(txn.ToString()),
12271 new LSL_Integer(replycode),
12272 new LSL_String(replydata) },
12273 new DetectParams[0]));
12274 }
12275 });
12276
12277 return txn.ToString();
11068 } 12278 }
11069 12279
11070 #endregion 12280 #endregion
12281
12282 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12283 {
12284 SceneObjectGroup group = m_host.ParentGroup;
12285
12286 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12287 return;
12288 if (group.IsAttachment)
12289 return;
12290
12291 if (frames.Data.Length > 0) // We are getting a new motion
12292 {
12293 if (group.RootPart.KeyframeMotion != null)
12294 group.RootPart.KeyframeMotion.Stop();
12295 group.RootPart.KeyframeMotion = null;
12296
12297 int idx = 0;
12298
12299 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12300 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12301
12302 while (idx < options.Data.Length)
12303 {
12304 int option = (int)options.GetLSLIntegerItem(idx++);
12305 int remain = options.Data.Length - idx;
12306
12307 switch (option)
12308 {
12309 case ScriptBaseClass.KFM_MODE:
12310 if (remain < 1)
12311 break;
12312 int modeval = (int)options.GetLSLIntegerItem(idx++);
12313 switch(modeval)
12314 {
12315 case ScriptBaseClass.KFM_FORWARD:
12316 mode = KeyframeMotion.PlayMode.Forward;
12317 break;
12318 case ScriptBaseClass.KFM_REVERSE:
12319 mode = KeyframeMotion.PlayMode.Reverse;
12320 break;
12321 case ScriptBaseClass.KFM_LOOP:
12322 mode = KeyframeMotion.PlayMode.Loop;
12323 break;
12324 case ScriptBaseClass.KFM_PING_PONG:
12325 mode = KeyframeMotion.PlayMode.PingPong;
12326 break;
12327 }
12328 break;
12329 case ScriptBaseClass.KFM_DATA:
12330 if (remain < 1)
12331 break;
12332 int dataval = (int)options.GetLSLIntegerItem(idx++);
12333 data = (KeyframeMotion.DataFormat)dataval;
12334 break;
12335 }
12336 }
12337
12338 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12339
12340 idx = 0;
12341
12342 int elemLength = 2;
12343 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12344 elemLength = 3;
12345
12346 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12347 while (idx < frames.Data.Length)
12348 {
12349 int remain = frames.Data.Length - idx;
12350
12351 if (remain < elemLength)
12352 break;
12353
12354 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12355 frame.Position = null;
12356 frame.Rotation = null;
12357
12358 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12359 {
12360 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12361 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12362 }
12363 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12364 {
12365 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12366 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12367 }
12368
12369 float tempf = (float)frames.GetLSLFloatItem(idx++);
12370 frame.TimeMS = (int)(tempf * 1000.0f);
12371
12372 keyframes.Add(frame);
12373 }
12374
12375 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12376 group.RootPart.KeyframeMotion.Start();
12377 }
12378 else
12379 {
12380 if (group.RootPart.KeyframeMotion == null)
12381 return;
12382
12383 if (options.Data.Length == 0)
12384 {
12385 group.RootPart.KeyframeMotion.Stop();
12386 return;
12387 }
12388
12389 int code = (int)options.GetLSLIntegerItem(0);
12390
12391 int idx = 0;
12392
12393 while (idx < options.Data.Length)
12394 {
12395 int option = (int)options.GetLSLIntegerItem(idx++);
12396 int remain = options.Data.Length - idx;
12397
12398 switch (option)
12399 {
12400 case ScriptBaseClass.KFM_COMMAND:
12401 int cmd = (int)options.GetLSLIntegerItem(idx++);
12402 switch (cmd)
12403 {
12404 case ScriptBaseClass.KFM_CMD_PLAY:
12405 group.RootPart.KeyframeMotion.Start();
12406 break;
12407 case ScriptBaseClass.KFM_CMD_STOP:
12408 group.RootPart.KeyframeMotion.Stop();
12409 break;
12410 case ScriptBaseClass.KFM_CMD_PAUSE:
12411 group.RootPart.KeyframeMotion.Pause();
12412 break;
12413 }
12414 break;
12415 }
12416 }
12417 }
12418 }
11071 } 12419 }
11072 12420
11073 public class NotecardCache 12421 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 d39b204..749fc97 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);
@@ -421,9 +424,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
421 LSL_Vector llWind(LSL_Vector offset); 424 LSL_Vector llWind(LSL_Vector offset);
422 LSL_String llXorBase64Strings(string str1, string str2); 425 LSL_String llXorBase64Strings(string str1, string str2);
423 LSL_String llXorBase64StringsCorrect(string str1, string str2); 426 LSL_String llXorBase64StringsCorrect(string str1, string str2);
424 void print(string str); 427 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link);
428 void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density);
425 429
426 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 430 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
427 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 431 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
432 void llSetKeyframedMotion(LSL_List frames, LSL_List options);
428 } 433 }
429} 434}
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 06f5617..976969a 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);
@@ -1958,9 +1980,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1958 return m_LSL_Functions.llClearLinkMedia(link, face); 1980 return m_LSL_Functions.llClearLinkMedia(link, face);
1959 } 1981 }
1960 1982
1961 public void print(string str) 1983 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
1984 {
1985 return m_LSL_Functions.llGetLinkNumberOfSides(link);
1986 }
1987
1988 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
1989 {
1990 m_LSL_Functions.llSetKeyframedMotion(frames, options);
1991 }
1992
1993 public void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density)
1962 { 1994 {
1963 m_LSL_Functions.print(str); 1995 m_LSL_Functions.llSetPhysicsMaterial(material_bits, material_gravity_modifier, material_restitution, material_friction, material_density);
1964 } 1996 }
1965 } 1997 }
1966} 1998}
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 {
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index a9b6e67..eeb125e 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -28,6 +28,7 @@
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.Globalization; 32using System.Globalization;
32using System.IO; 33using System.IO;
33using System.Reflection; 34using System.Reflection;
@@ -112,6 +113,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
112 private Dictionary<UUID, IScriptInstance> m_Scripts = 113 private Dictionary<UUID, IScriptInstance> m_Scripts =
113 new Dictionary<UUID, IScriptInstance>(); 114 new Dictionary<UUID, IScriptInstance>();
114 115
116 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
117
115 // Maps the asset ID to the assembly 118 // Maps the asset ID to the assembly
116 119
117 private Dictionary<UUID, string> m_Assemblies = 120 private Dictionary<UUID, string> m_Assemblies =
@@ -134,6 +137,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
134 IWorkItemResult m_CurrentCompile = null; 137 IWorkItemResult m_CurrentCompile = null;
135 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 138 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
136 139
140 private void lockScriptsForRead(bool locked)
141 {
142 if (locked)
143 {
144 if (m_scriptsLock.RecursiveReadCount > 0)
145 {
146 m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
147 m_scriptsLock.ExitReadLock();
148 }
149 if (m_scriptsLock.RecursiveWriteCount > 0)
150 {
151 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
152 m_scriptsLock.ExitWriteLock();
153 }
154
155 while (!m_scriptsLock.TryEnterReadLock(60000))
156 {
157 m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire READ lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
158 if (m_scriptsLock.IsWriteLockHeld)
159 {
160 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
161 }
162 }
163 }
164 else
165 {
166 if (m_scriptsLock.RecursiveReadCount > 0)
167 {
168 m_scriptsLock.ExitReadLock();
169 }
170 }
171 }
172 private void lockScriptsForWrite(bool locked)
173 {
174 if (locked)
175 {
176 if (m_scriptsLock.RecursiveReadCount > 0)
177 {
178 m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
179 m_scriptsLock.ExitReadLock();
180 }
181 if (m_scriptsLock.RecursiveWriteCount > 0)
182 {
183 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
184 m_scriptsLock.ExitWriteLock();
185 }
186
187 while (!m_scriptsLock.TryEnterWriteLock(60000))
188 {
189 m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
190 if (m_scriptsLock.IsWriteLockHeld)
191 {
192 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
193 }
194 }
195 }
196 else
197 {
198 if (m_scriptsLock.RecursiveWriteCount > 0)
199 {
200 m_scriptsLock.ExitWriteLock();
201 }
202 }
203 }
204
137 public string ScriptEngineName 205 public string ScriptEngineName
138 { 206 {
139 get { return "XEngine"; } 207 get { return "XEngine"; }
@@ -527,44 +595,37 @@ namespace OpenSim.Region.ScriptEngine.XEngine
527 { 595 {
528 if (!m_Enabled) 596 if (!m_Enabled)
529 return; 597 return;
530 598 lockScriptsForRead(true);
531 lock (m_Scripts) 599 foreach (IScriptInstance instance in m_Scripts.Values)
532 { 600 {
533 m_log.InfoFormat( 601 // Force a final state save
534 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 602 //
535 603 if (m_Assemblies.ContainsKey(instance.AssetID))
536 foreach (IScriptInstance instance in m_Scripts.Values)
537 { 604 {
538 // Force a final state save 605 string assembly = m_Assemblies[instance.AssetID];
539 // 606 instance.SaveState(assembly);
540 if (m_Assemblies.ContainsKey(instance.AssetID)) 607 }
541 {
542 string assembly = m_Assemblies[instance.AssetID];
543 instance.SaveState(assembly);
544 }
545 608
546 // Clear the event queue and abort the instance thread 609 // Clear the event queue and abort the instance thread
547 // 610 //
548 instance.ClearQueue(); 611 instance.ClearQueue();
549 instance.Stop(0); 612 instance.Stop(0);
550 613
551 // Release events, timer, etc 614 // Release events, timer, etc
552 // 615 //
553 instance.DestroyScriptInstance(); 616 instance.DestroyScriptInstance();
554 617
555 // Unload scripts and app domains. 618 // Unload scripts and app domains
556 // Must be done explicitly because they have infinite 619 // Must be done explicitly because they have infinite
557 // lifetime. 620 // lifetime
558 // However, don't bother to do this if the simulator is shutting 621 //
559 // down since it takes a long time with many scripts. 622 if (!m_SimulatorShuttingDown)
560 if (!m_SimulatorShuttingDown) 623 {
624 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
625 if (m_DomainScripts[instance.AppDomain].Count == 0)
561 { 626 {
562 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 627 m_DomainScripts.Remove(instance.AppDomain);
563 if (m_DomainScripts[instance.AppDomain].Count == 0) 628 UnloadAppDomain(instance.AppDomain);
564 {
565 m_DomainScripts.Remove(instance.AppDomain);
566 UnloadAppDomain(instance.AppDomain);
567 }
568 } 629 }
569 } 630 }
570 631
@@ -573,6 +634,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
573 m_Assemblies.Clear(); 634 m_Assemblies.Clear();
574 m_DomainScripts.Clear(); 635 m_DomainScripts.Clear();
575 } 636 }
637 lockScriptsForRead(false);
638 lockScriptsForWrite(true);
639 m_Scripts.Clear();
640 lockScriptsForWrite(false);
641 m_PrimObjects.Clear();
642 m_Assemblies.Clear();
643 m_DomainScripts.Clear();
644
576 lock (m_ScriptEngines) 645 lock (m_ScriptEngines)
577 { 646 {
578 m_ScriptEngines.Remove(this); 647 m_ScriptEngines.Remove(this);
@@ -637,22 +706,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
637 706
638 List<IScriptInstance> instances = new List<IScriptInstance>(); 707 List<IScriptInstance> instances = new List<IScriptInstance>();
639 708
640 lock (m_Scripts) 709 lockScriptsForRead(true);
641 { 710 foreach (IScriptInstance instance in m_Scripts.Values)
642 foreach (IScriptInstance instance in m_Scripts.Values)
643 instances.Add(instance); 711 instances.Add(instance);
644 } 712 lockScriptsForRead(false);
645 713
646 foreach (IScriptInstance i in instances) 714 foreach (IScriptInstance i in instances)
647 { 715 {
648 string assembly = String.Empty; 716 string assembly = String.Empty;
649 717
650 lock (m_Scripts) 718
651 {
652 if (!m_Assemblies.ContainsKey(i.AssetID)) 719 if (!m_Assemblies.ContainsKey(i.AssetID))
653 continue; 720 continue;
654 assembly = m_Assemblies[i.AssetID]; 721 assembly = m_Assemblies[i.AssetID];
655 } 722
656 723
657 i.SaveState(assembly); 724 i.SaveState(assembly);
658 } 725 }
@@ -996,95 +1063,99 @@ namespace OpenSim.Region.ScriptEngine.XEngine
996 } 1063 }
997 1064
998 ScriptInstance instance = null; 1065 ScriptInstance instance = null;
999 lock (m_Scripts) 1066 // Create the object record
1067 lockScriptsForRead(true);
1068 if ((!m_Scripts.ContainsKey(itemID)) ||
1069 (m_Scripts[itemID].AssetID != assetID))
1000 { 1070 {
1001 // Create the object record 1071 lockScriptsForRead(false);
1002 if ((!m_Scripts.ContainsKey(itemID)) ||
1003 (m_Scripts[itemID].AssetID != assetID))
1004 {
1005 UUID appDomain = assetID;
1006 1072
1007 if (part.ParentGroup.IsAttachment) 1073 UUID appDomain = assetID;
1008 appDomain = part.ParentGroup.RootPart.UUID;
1009 1074
1010 if (!m_AppDomains.ContainsKey(appDomain)) 1075 if (part.ParentGroup.IsAttachment)
1011 { 1076 appDomain = part.ParentGroup.RootPart.UUID;
1012 try
1013 {
1014 AppDomainSetup appSetup = new AppDomainSetup();
1015 appSetup.PrivateBinPath = Path.Combine(
1016 m_ScriptEnginesPath,
1017 m_Scene.RegionInfo.RegionID.ToString());
1018 1077
1019 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1078 if (!m_AppDomains.ContainsKey(appDomain))
1020 Evidence evidence = new Evidence(baseEvidence); 1079 {
1080 try
1081 {
1082 AppDomainSetup appSetup = new AppDomainSetup();
1083 appSetup.PrivateBinPath = Path.Combine(
1084 m_ScriptEnginesPath,
1085 m_Scene.RegionInfo.RegionID.ToString());
1021 1086
1022 AppDomain sandbox; 1087 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1023 if (m_AppDomainLoading) 1088 Evidence evidence = new Evidence(baseEvidence);
1024 {
1025 sandbox = AppDomain.CreateDomain(
1026 m_Scene.RegionInfo.RegionID.ToString(),
1027 evidence, appSetup);
1028 sandbox.AssemblyResolve +=
1029 new ResolveEventHandler(
1030 AssemblyResolver.OnAssemblyResolve);
1031 }
1032 else
1033 {
1034 sandbox = AppDomain.CurrentDomain;
1035 }
1036
1037 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1038 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1039 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1040 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1041 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1042 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1043 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1044
1045 m_AppDomains[appDomain] = sandbox;
1046 1089
1047 m_DomainScripts[appDomain] = new List<UUID>(); 1090 AppDomain sandbox;
1091 if (m_AppDomainLoading)
1092 {
1093 sandbox = AppDomain.CreateDomain(
1094 m_Scene.RegionInfo.RegionID.ToString(),
1095 evidence, appSetup);
1096 m_AppDomains[appDomain].AssemblyResolve +=
1097 new ResolveEventHandler(
1098 AssemblyResolver.OnAssemblyResolve);
1048 } 1099 }
1049 catch (Exception e) 1100 else
1050 { 1101 {
1051 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1102 sandbox = AppDomain.CurrentDomain;
1052 m_ScriptErrorMessage += "Exception creating app domain:\n";
1053 m_ScriptFailCount++;
1054 lock (m_AddingAssemblies)
1055 {
1056 m_AddingAssemblies[assembly]--;
1057 }
1058 return false;
1059 } 1103 }
1060 }
1061 m_DomainScripts[appDomain].Add(itemID);
1062
1063 instance = new ScriptInstance(this, part,
1064 itemID, assetID, assembly,
1065 m_AppDomains[appDomain],
1066 part.ParentGroup.RootPart.Name,
1067 item.Name, startParam, postOnRez,
1068 stateSource, m_MaxScriptQueue);
1069
1070 m_log.DebugFormat(
1071 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1072 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1073 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1074 1104
1075 if (presence != null) 1105 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1106 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1107 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1108 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1109 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1110 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1111 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1112
1113 m_AppDomains[appDomain] = sandbox;
1114
1115 m_DomainScripts[appDomain] = new List<UUID>();
1116 }
1117 catch (Exception e)
1076 { 1118 {
1077 ShowScriptSaveResponse(item.OwnerID, 1119 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1078 assetID, "Compile successful", true); 1120 m_ScriptErrorMessage += "Exception creating app domain:\n";
1121 m_ScriptFailCount++;
1122 lock (m_AddingAssemblies)
1123 {
1124 m_AddingAssemblies[assembly]--;
1125 }
1126 return false;
1079 } 1127 }
1128 }
1129 m_DomainScripts[appDomain].Add(itemID);
1130
1131 instance = new ScriptInstance(this, part,
1132 itemID, assetID, assembly,
1133 m_AppDomains[appDomain],
1134 part.ParentGroup.RootPart.Name,
1135 item.Name, startParam, postOnRez,
1136 stateSource, m_MaxScriptQueue);
1137
1138 m_log.DebugFormat(
1139 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1140 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1141 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1080 1142
1081 instance.AppDomain = appDomain; 1143 if (presence != null)
1082 instance.LineMap = linemap; 1144 {
1083 1145 ShowScriptSaveResponse(item.OwnerID,
1084 m_Scripts[itemID] = instance; 1146 assetID, "Compile successful", true);
1085 } 1147 }
1086 }
1087 1148
1149 instance.AppDomain = appDomain;
1150 instance.LineMap = linemap;
1151 lockScriptsForWrite(true);
1152 m_Scripts[itemID] = instance;
1153 lockScriptsForWrite(false);
1154 }
1155 else
1156 {
1157 lockScriptsForRead(false);
1158 }
1088 lock (m_PrimObjects) 1159 lock (m_PrimObjects)
1089 { 1160 {
1090 if (!m_PrimObjects.ContainsKey(localID)) 1161 if (!m_PrimObjects.ContainsKey(localID))
@@ -1102,9 +1173,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1102 m_AddingAssemblies[assembly]--; 1173 m_AddingAssemblies[assembly]--;
1103 } 1174 }
1104 1175
1105 if (instance != null) 1176 if (instance!=null)
1106 instance.Init(); 1177 instance.Init();
1107 1178
1108 return true; 1179 return true;
1109 } 1180 }
1110 1181
@@ -1117,18 +1188,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1117 m_CompileDict.Remove(itemID); 1188 m_CompileDict.Remove(itemID);
1118 } 1189 }
1119 1190
1120 IScriptInstance instance = null; 1191 lockScriptsForRead(true);
1121 1192 // Do we even have it?
1122 lock (m_Scripts) 1193 if (!m_Scripts.ContainsKey(itemID))
1123 { 1194 {
1124 // Do we even have it? 1195 // Do we even have it?
1125 if (!m_Scripts.ContainsKey(itemID)) 1196 if (!m_Scripts.ContainsKey(itemID))
1126 return; 1197 return;
1127 1198
1128 instance = m_Scripts[itemID]; 1199 lockScriptsForRead(false);
1200 lockScriptsForWrite(true);
1129 m_Scripts.Remove(itemID); 1201 m_Scripts.Remove(itemID);
1202 lockScriptsForWrite(false);
1203
1204 return;
1130 } 1205 }
1206
1131 1207
1208 IScriptInstance instance=m_Scripts[itemID];
1209 lockScriptsForRead(false);
1210 lockScriptsForWrite(true);
1211 m_Scripts.Remove(itemID);
1212 lockScriptsForWrite(false);
1132 instance.ClearQueue(); 1213 instance.ClearQueue();
1133 1214
1134 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1215 // Give the script some time to finish processing its last event. Simply aborting the script thread can
@@ -1167,8 +1248,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1167 1248
1168 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1249 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1169 if (handlerObjectRemoved != null) 1250 if (handlerObjectRemoved != null)
1170 handlerObjectRemoved(instance.ObjectID); 1251 {
1252 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1253 handlerObjectRemoved(part.UUID);
1254 }
1171 1255
1256 CleanAssemblies();
1257
1172 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1258 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1173 if (handlerScriptRemoved != null) 1259 if (handlerScriptRemoved != null)
1174 handlerScriptRemoved(itemID); 1260 handlerScriptRemoved(itemID);
@@ -1310,7 +1396,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1310 return false; 1396 return false;
1311 1397
1312 uuids = m_PrimObjects[localID]; 1398 uuids = m_PrimObjects[localID];
1313 } 1399
1314 1400
1315 foreach (UUID itemID in uuids) 1401 foreach (UUID itemID in uuids)
1316 { 1402 {
@@ -1328,6 +1414,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1328 result = true; 1414 result = true;
1329 } 1415 }
1330 } 1416 }
1417 }
1331 1418
1332 return result; 1419 return result;
1333 } 1420 }
@@ -1429,12 +1516,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1429 private IScriptInstance GetInstance(UUID itemID) 1516 private IScriptInstance GetInstance(UUID itemID)
1430 { 1517 {
1431 IScriptInstance instance; 1518 IScriptInstance instance;
1432 lock (m_Scripts) 1519 lockScriptsForRead(true);
1520 if (!m_Scripts.ContainsKey(itemID))
1433 { 1521 {
1434 if (!m_Scripts.ContainsKey(itemID)) 1522 lockScriptsForRead(false);
1435 return null; 1523 return null;
1436 instance = m_Scripts[itemID];
1437 } 1524 }
1525 instance = m_Scripts[itemID];
1526 lockScriptsForRead(false);
1438 return instance; 1527 return instance;
1439 } 1528 }
1440 1529
@@ -1458,6 +1547,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1458 return false; 1547 return false;
1459 } 1548 }
1460 1549
1550 [DebuggerNonUserCode]
1461 public void ApiResetScript(UUID itemID) 1551 public void ApiResetScript(UUID itemID)
1462 { 1552 {
1463 IScriptInstance instance = GetInstance(itemID); 1553 IScriptInstance instance = GetInstance(itemID);
@@ -1509,6 +1599,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1509 return UUID.Zero; 1599 return UUID.Zero;
1510 } 1600 }
1511 1601
1602 [DebuggerNonUserCode]
1512 public void SetState(UUID itemID, string newState) 1603 public void SetState(UUID itemID, string newState)
1513 { 1604 {
1514 IScriptInstance instance = GetInstance(itemID); 1605 IScriptInstance instance = GetInstance(itemID);
@@ -1531,11 +1622,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1531 1622
1532 List<IScriptInstance> instances = new List<IScriptInstance>(); 1623 List<IScriptInstance> instances = new List<IScriptInstance>();
1533 1624
1534 lock (m_Scripts) 1625 lockScriptsForRead(true);
1535 { 1626 foreach (IScriptInstance instance in m_Scripts.Values)
1536 foreach (IScriptInstance instance in m_Scripts.Values)
1537 instances.Add(instance); 1627 instances.Add(instance);
1538 } 1628 lockScriptsForRead(false);
1539 1629
1540 foreach (IScriptInstance i in instances) 1630 foreach (IScriptInstance i in instances)
1541 { 1631 {
@@ -1989,5 +2079,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1989// else 2079// else
1990// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); 2080// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID);
1991 } 2081 }
2082
2083 public bool HasScript(UUID itemID, out bool running)
2084 {
2085 running = true;
2086
2087 IScriptInstance instance = GetInstance(itemID);
2088 if (instance == null)
2089 return false;
2090
2091 running = instance.Running;
2092 return true;
2093 }
1992 } 2094 }
1993} 2095}