aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
-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.cs2993
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs116
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs32
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs46
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs71
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs26
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs51
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs21
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs84
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs39
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs362
19 files changed, 2933 insertions, 1079 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 d213c35..c7e59ac 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,16 +107,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
103 protected int m_notecardLineReadCharsMax = 255; 107 protected int m_notecardLineReadCharsMax = 255;
104 protected int m_scriptConsoleChannel = 0; 108 protected int m_scriptConsoleChannel = 0;
105 protected bool m_scriptConsoleChannelEnabled = false; 109 protected bool m_scriptConsoleChannelEnabled = false;
110 protected bool m_debuggerSafe = false;
106 protected IUrlModule m_UrlModule = null; 111 protected IUrlModule m_UrlModule = null;
107 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 112 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
108 new Dictionary<UUID, UserInfoCacheEntry>(); 113 new Dictionary<UUID, UserInfoCacheEntry>();
109 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 114 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
115
116 protected Timer m_ShoutSayTimer;
117 protected int m_SayShoutCount = 0;
110 118
111 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 119 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
112 { 120 {
121 m_ShoutSayTimer = new Timer(1000);
122 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
123 m_ShoutSayTimer.AutoReset = true;
124 m_ShoutSayTimer.Start();
125
113 m_ScriptEngine = ScriptEngine; 126 m_ScriptEngine = ScriptEngine;
114 m_host = host; 127 m_host = host;
115 m_item = item; 128 m_item = item;
129 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
116 130
117 LoadLimits(); // read script limits from config. 131 LoadLimits(); // read script limits from config.
118 132
@@ -172,6 +186,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
172 get { return m_ScriptEngine.World; } 186 get { return m_ScriptEngine.World; }
173 } 187 }
174 188
189 [DebuggerNonUserCode]
175 public void state(string newState) 190 public void state(string newState)
176 { 191 {
177 m_ScriptEngine.SetState(m_item.ItemID, newState); 192 m_ScriptEngine.SetState(m_item.ItemID, newState);
@@ -181,6 +196,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
181 /// Reset the named script. The script must be present 196 /// Reset the named script. The script must be present
182 /// in the same prim. 197 /// in the same prim.
183 /// </summary> 198 /// </summary>
199 [DebuggerNonUserCode]
184 public void llResetScript() 200 public void llResetScript()
185 { 201 {
186 m_host.AddScriptLPS(1); 202 m_host.AddScriptLPS(1);
@@ -237,9 +253,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
237 } 253 }
238 } 254 }
239 255
256 public List<ScenePresence> GetLinkAvatars(int linkType)
257 {
258 List<ScenePresence> ret = new List<ScenePresence>();
259 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
260 return ret;
261
262 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
263
264 switch (linkType)
265 {
266 case ScriptBaseClass.LINK_SET:
267 return avs;
268
269 case ScriptBaseClass.LINK_ROOT:
270 return ret;
271
272 case ScriptBaseClass.LINK_ALL_OTHERS:
273 return avs;
274
275 case ScriptBaseClass.LINK_ALL_CHILDREN:
276 return avs;
277
278 case ScriptBaseClass.LINK_THIS:
279 return ret;
280
281 default:
282 if (linkType < 0)
283 return ret;
284
285 int partCount = m_host.ParentGroup.GetPartCount();
286
287 if (linkType <= partCount)
288 {
289 return ret;
290 }
291 else
292 {
293 linkType = linkType - partCount;
294 if (linkType > avs.Count)
295 {
296 return ret;
297 }
298 else
299 {
300 ret.Add(avs[linkType-1]);
301 return ret;
302 }
303 }
304 }
305 }
306
240 public List<SceneObjectPart> GetLinkParts(int linkType) 307 public List<SceneObjectPart> GetLinkParts(int linkType)
241 { 308 {
242 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 309 List<SceneObjectPart> ret = new List<SceneObjectPart>();
310 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
311 return ret;
243 ret.Add(m_host); 312 ret.Add(m_host);
244 313
245 switch (linkType) 314 switch (linkType)
@@ -286,21 +355,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
286 protected UUID InventoryKey(string name, int type) 355 protected UUID InventoryKey(string name, int type)
287 { 356 {
288 m_host.AddScriptLPS(1); 357 m_host.AddScriptLPS(1);
289 358 m_host.TaskInventory.LockItemsForRead(true);
290 lock (m_host.TaskInventory) 359
360 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
291 { 361 {
292 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 362 if (inv.Value.Name == name)
293 { 363 {
294 if (inv.Value.Name == name) 364 m_host.TaskInventory.LockItemsForRead(false);
365
366 if (inv.Value.Type != type)
295 { 367 {
296 if (inv.Value.Type != type) 368 return UUID.Zero;
297 return UUID.Zero;
298
299 return inv.Value.AssetID;
300 } 369 }
370
371 return inv.Value.AssetID;
301 } 372 }
302 } 373 }
303 374
375 m_host.TaskInventory.LockItemsForRead(false);
304 return UUID.Zero; 376 return UUID.Zero;
305 } 377 }
306 378
@@ -308,17 +380,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
308 { 380 {
309 m_host.AddScriptLPS(1); 381 m_host.AddScriptLPS(1);
310 382
311 lock (m_host.TaskInventory) 383
384 m_host.TaskInventory.LockItemsForRead(true);
385
386 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
312 { 387 {
313 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 388 if (inv.Value.Name == name)
314 { 389 {
315 if (inv.Value.Name == name) 390 m_host.TaskInventory.LockItemsForRead(false);
316 { 391 return inv.Value.AssetID;
317 return inv.Value.AssetID;
318 }
319 } 392 }
320 } 393 }
321 394
395 m_host.TaskInventory.LockItemsForRead(false);
396
397
322 return UUID.Zero; 398 return UUID.Zero;
323 } 399 }
324 400
@@ -460,31 +536,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
460 536
461 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 537 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
462 538
463 /// <summary> 539 // Utility function for llRot2Euler
464 /// Convert an LSL rotation to a Euler vector. 540
465 /// </summary> 541 // normalize an angle between -PI and PI (-180 to +180 degrees)
466 /// <remarks> 542 protected double NormalizeAngle(double angle)
467 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
468 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
469 /// </remarks>
470 /// <param name="r"></param>
471 /// <returns></returns>
472 public LSL_Vector llRot2Euler(LSL_Rotation r)
473 { 543 {
474 m_host.AddScriptLPS(1); 544 if (angle > -Math.PI && angle < Math.PI)
545 return angle;
475 546
476 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 547 int numPis = (int)(Math.PI / angle);
477 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 548 double remainder = angle - Math.PI * numPis;
478 if (m == 0.0) return new LSL_Vector(); 549 if (numPis % 2 == 1)
479 double x = Math.Atan2(-v.y, v.z); 550 return Math.PI - angle;
480 double sin = v.x / m; 551 return remainder;
481 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. 552 }
482 double y = Math.Asin(sin);
483 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
484 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)));
485 double z = Math.Atan2(v.y, v.x);
486 553
487 return new LSL_Vector(x, y, z); 554 public LSL_Vector llRot2Euler(LSL_Rotation q1)
555 {
556 m_host.AddScriptLPS(1);
557 LSL_Vector eul = new LSL_Vector();
558
559 double sqw = q1.s*q1.s;
560 double sqx = q1.x*q1.x;
561 double sqy = q1.z*q1.z;
562 double sqz = q1.y*q1.y;
563 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
564 double test = q1.x*q1.z + q1.y*q1.s;
565 if (test > 0.4999*unit) { // singularity at north pole
566 eul.z = 2 * Math.Atan2(q1.x,q1.s);
567 eul.y = Math.PI/2;
568 eul.x = 0;
569 return eul;
570 }
571 if (test < -0.4999*unit) { // singularity at south pole
572 eul.z = -2 * Math.Atan2(q1.x,q1.s);
573 eul.y = -Math.PI/2;
574 eul.x = 0;
575 return eul;
576 }
577 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
578 eul.y = Math.Asin(2*test/unit);
579 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
580 return eul;
488 } 581 }
489 582
490 /* From wiki: 583 /* From wiki:
@@ -686,77 +779,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
686 { 779 {
687 //A and B should both be normalized 780 //A and B should both be normalized
688 m_host.AddScriptLPS(1); 781 m_host.AddScriptLPS(1);
689 LSL_Rotation rotBetween; 782 /* This method is more accurate than the SL one, and thus causes problems
690 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 783 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
691 // continue calculation. 784
692 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 785 double dotProduct = LSL_Vector.Dot(a, b);
786 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
787 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
788 double angle = Math.Acos(dotProduct / magProduct);
789 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
790 double s = Math.Sin(angle / 2);
791
792 double x = axis.x * s;
793 double y = axis.y * s;
794 double z = axis.z * s;
795 double w = Math.Cos(angle / 2);
796
797 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
798 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
799
800 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
801 */
802
803 // This method mimics the 180 errors found in SL
804 // See www.euclideanspace.com... angleBetween
805 LSL_Vector vec_a = a;
806 LSL_Vector vec_b = b;
807
808 // Eliminate zero length
809 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
810 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
811 if (vec_a_mag < 0.00001 ||
812 vec_b_mag < 0.00001)
693 { 813 {
694 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 814 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
695 } 815 }
696 else 816
817 // Normalize
818 vec_a = llVecNorm(vec_a);
819 vec_b = llVecNorm(vec_b);
820
821 // Calculate axis and rotation angle
822 LSL_Vector axis = vec_a % vec_b;
823 LSL_Float cos_theta = vec_a * vec_b;
824
825 // Check if parallel
826 if (cos_theta > 0.99999)
697 { 827 {
698 a = LSL_Vector.Norm(a); 828 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
699 b = LSL_Vector.Norm(b); 829 }
700 double dotProduct = LSL_Vector.Dot(a, b); 830
701 // There are two degenerate cases possible. These are for vectors 180 or 831 // Check if anti-parallel
702 // 0 degrees apart. These have to be detected and handled individually. 832 else if (cos_theta < -0.99999)
703 // 833 {
704 // Check for vectors 180 degrees apart. 834 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
705 // A dot product of -1 would mean the angle between vectors is 180 degrees. 835 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
706 if (dotProduct < -0.9999999f) 836 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
707 { 837 }
708 // First assume X axis is orthogonal to the vectors. 838 else // other rotation
709 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 839 {
710 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 840 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
711 // Check for near zero vector. A very small non-zero number here will create 841 axis = llVecNorm(axis);
712 // a rotation in an undesired direction. 842 double x, y, z, s, t;
713 if (LSL_Vector.Mag(orthoVector) > 0.0001) 843 s = Math.Cos(theta);
714 { 844 t = Math.Sin(theta);
715 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 845 x = axis.x * t;
716 } 846 y = axis.y * t;
717 // If the magnitude of the vector was near zero, then assume the X axis is not 847 z = axis.z * t;
718 // orthogonal and use the Z axis instead. 848 return new LSL_Rotation(x,y,z,s);
719 else
720 {
721 // Set 180 z rotation.
722 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
723 }
724 }
725 // Check for parallel vectors.
726 // A dot product of 1 would mean the angle between vectors is 0 degrees.
727 else if (dotProduct > 0.9999999f)
728 {
729 // Set zero rotation.
730 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
731 }
732 else
733 {
734 // All special checks have been performed so get the axis of rotation.
735 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
736 // Quarternion s value is the length of the unit vector + dot product.
737 double qs = 1.0 + dotProduct;
738 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
739 // Normalize the rotation.
740 double mag = LSL_Rotation.Mag(rotBetween);
741 // We shouldn't have to worry about a divide by zero here. The qs value will be
742 // non-zero because we already know if we're here, then the dotProduct is not -1 so
743 // qs will not be zero. Also, we've already handled the input vectors being zero so the
744 // crossProduct vector should also not be zero.
745 rotBetween.x = rotBetween.x / mag;
746 rotBetween.y = rotBetween.y / mag;
747 rotBetween.z = rotBetween.z / mag;
748 rotBetween.s = rotBetween.s / mag;
749 // Check for undefined values and set zero rotation if any found. This code might not actually be required
750 // any longer since zero vectors are checked for at the top.
751 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
752 {
753 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
754 }
755 }
756 } 849 }
757 return rotBetween;
758 } 850 }
759 851
760 public void llWhisper(int channelID, string text) 852 public void llWhisper(int channelID, string text)
761 { 853 {
762 m_host.AddScriptLPS(1); 854 m_host.AddScriptLPS(1);
@@ -776,6 +868,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
776 { 868 {
777 m_host.AddScriptLPS(1); 869 m_host.AddScriptLPS(1);
778 870
871 if (channelID == 0)
872 m_SayShoutCount++;
873
874 if (m_SayShoutCount >= 11)
875 ScriptSleep(2000);
876
779 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 877 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
780 { 878 {
781 Console.WriteLine(text); 879 Console.WriteLine(text);
@@ -798,6 +896,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
798 { 896 {
799 m_host.AddScriptLPS(1); 897 m_host.AddScriptLPS(1);
800 898
899 if (channelID == 0)
900 m_SayShoutCount++;
901
902 if (m_SayShoutCount >= 11)
903 ScriptSleep(2000);
904
801 if (text.Length > 1023) 905 if (text.Length > 1023)
802 text = text.Substring(0, 1023); 906 text = text.Substring(0, 1023);
803 907
@@ -1100,10 +1204,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1100 return detectedParams.TouchUV; 1204 return detectedParams.TouchUV;
1101 } 1205 }
1102 1206
1207 [DebuggerNonUserCode]
1103 public virtual void llDie() 1208 public virtual void llDie()
1104 { 1209 {
1105 m_host.AddScriptLPS(1); 1210 m_host.AddScriptLPS(1);
1106 throw new SelfDeleteException(); 1211 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1107 } 1212 }
1108 1213
1109 public LSL_Float llGround(LSL_Vector offset) 1214 public LSL_Float llGround(LSL_Vector offset)
@@ -1176,6 +1281,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1176 1281
1177 public void llSetStatus(int status, int value) 1282 public void llSetStatus(int status, int value)
1178 { 1283 {
1284 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1285 return;
1179 m_host.AddScriptLPS(1); 1286 m_host.AddScriptLPS(1);
1180 1287
1181 int statusrotationaxis = 0; 1288 int statusrotationaxis = 0;
@@ -1407,6 +1514,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1407 { 1514 {
1408 m_host.AddScriptLPS(1); 1515 m_host.AddScriptLPS(1);
1409 1516
1517 SetColor(m_host, color, face);
1518 }
1519
1520 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1521 {
1522 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1523 return;
1524
1525 Primitive.TextureEntry tex = part.Shape.Textures;
1526 Color4 texcolor;
1527 if (face >= 0 && face < GetNumberOfSides(part))
1528 {
1529 texcolor = tex.CreateFace((uint)face).RGBA;
1530 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1531 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1532 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1533 tex.FaceTextures[face].RGBA = texcolor;
1534 part.UpdateTextureEntry(tex.GetBytes());
1535 return;
1536 }
1537 else if (face == ScriptBaseClass.ALL_SIDES)
1538 {
1539 for (uint i = 0; i < GetNumberOfSides(part); i++)
1540 {
1541 if (tex.FaceTextures[i] != null)
1542 {
1543 texcolor = tex.FaceTextures[i].RGBA;
1544 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1545 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1546 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1547 tex.FaceTextures[i].RGBA = texcolor;
1548 }
1549 texcolor = tex.DefaultTexture.RGBA;
1550 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1551 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1552 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1553 tex.DefaultTexture.RGBA = texcolor;
1554 }
1555 part.UpdateTextureEntry(tex.GetBytes());
1556 return;
1557 }
1558
1410 if (face == ScriptBaseClass.ALL_SIDES) 1559 if (face == ScriptBaseClass.ALL_SIDES)
1411 face = SceneObjectPart.ALL_SIDES; 1560 face = SceneObjectPart.ALL_SIDES;
1412 1561
@@ -1415,6 +1564,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1415 1564
1416 public void SetTexGen(SceneObjectPart part, int face,int style) 1565 public void SetTexGen(SceneObjectPart part, int face,int style)
1417 { 1566 {
1567 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1568 return;
1569
1418 Primitive.TextureEntry tex = part.Shape.Textures; 1570 Primitive.TextureEntry tex = part.Shape.Textures;
1419 MappingType textype; 1571 MappingType textype;
1420 textype = MappingType.Default; 1572 textype = MappingType.Default;
@@ -1445,6 +1597,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1445 1597
1446 public void SetGlow(SceneObjectPart part, int face, float glow) 1598 public void SetGlow(SceneObjectPart part, int face, float glow)
1447 { 1599 {
1600 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1601 return;
1602
1448 Primitive.TextureEntry tex = part.Shape.Textures; 1603 Primitive.TextureEntry tex = part.Shape.Textures;
1449 if (face >= 0 && face < GetNumberOfSides(part)) 1604 if (face >= 0 && face < GetNumberOfSides(part))
1450 { 1605 {
@@ -1470,6 +1625,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1470 1625
1471 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1626 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1472 { 1627 {
1628 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1629 return;
1473 1630
1474 Shininess sval = new Shininess(); 1631 Shininess sval = new Shininess();
1475 1632
@@ -1520,6 +1677,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1520 1677
1521 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1678 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1522 { 1679 {
1680 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1681 return;
1682
1523 Primitive.TextureEntry tex = part.Shape.Textures; 1683 Primitive.TextureEntry tex = part.Shape.Textures;
1524 if (face >= 0 && face < GetNumberOfSides(part)) 1684 if (face >= 0 && face < GetNumberOfSides(part))
1525 { 1685 {
@@ -1580,13 +1740,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1580 m_host.AddScriptLPS(1); 1740 m_host.AddScriptLPS(1);
1581 1741
1582 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1742 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1583 1743 if (parts.Count > 0)
1584 foreach (SceneObjectPart part in parts) 1744 {
1585 SetAlpha(part, alpha, face); 1745 try
1746 {
1747 parts[0].ParentGroup.areUpdatesSuspended = true;
1748 foreach (SceneObjectPart part in parts)
1749 SetAlpha(part, alpha, face);
1750 }
1751 finally
1752 {
1753 parts[0].ParentGroup.areUpdatesSuspended = false;
1754 }
1755 }
1586 } 1756 }
1587 1757
1588 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1758 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1589 { 1759 {
1760 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1761 return;
1762
1590 Primitive.TextureEntry tex = part.Shape.Textures; 1763 Primitive.TextureEntry tex = part.Shape.Textures;
1591 Color4 texcolor; 1764 Color4 texcolor;
1592 if (face >= 0 && face < GetNumberOfSides(part)) 1765 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1639,7 +1812,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1639 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1812 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1640 float wind, float tension, LSL_Vector Force) 1813 float wind, float tension, LSL_Vector Force)
1641 { 1814 {
1642 if (part == null) 1815 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1643 return; 1816 return;
1644 1817
1645 if (flexi) 1818 if (flexi)
@@ -1673,7 +1846,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1673 /// <param name="falloff"></param> 1846 /// <param name="falloff"></param>
1674 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1847 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1675 { 1848 {
1676 if (part == null) 1849 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1677 return; 1850 return;
1678 1851
1679 if (light) 1852 if (light)
@@ -1751,15 +1924,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1751 m_host.AddScriptLPS(1); 1924 m_host.AddScriptLPS(1);
1752 1925
1753 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1926 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1754 1927 if (parts.Count > 0)
1755 foreach (SceneObjectPart part in parts) 1928 {
1756 SetTexture(part, texture, face); 1929 try
1757 1930 {
1931 parts[0].ParentGroup.areUpdatesSuspended = true;
1932 foreach (SceneObjectPart part in parts)
1933 SetTexture(part, texture, face);
1934 }
1935 finally
1936 {
1937 parts[0].ParentGroup.areUpdatesSuspended = false;
1938 }
1939 }
1758 ScriptSleep(200); 1940 ScriptSleep(200);
1759 } 1941 }
1760 1942
1761 protected void SetTexture(SceneObjectPart part, string texture, int face) 1943 protected void SetTexture(SceneObjectPart part, string texture, int face)
1762 { 1944 {
1945 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1946 return;
1947
1763 UUID textureID = new UUID(); 1948 UUID textureID = new UUID();
1764 1949
1765 textureID = InventoryKey(texture, (int)AssetType.Texture); 1950 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1804,6 +1989,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1804 1989
1805 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 1990 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1806 { 1991 {
1992 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1993 return;
1994
1807 Primitive.TextureEntry tex = part.Shape.Textures; 1995 Primitive.TextureEntry tex = part.Shape.Textures;
1808 if (face >= 0 && face < GetNumberOfSides(part)) 1996 if (face >= 0 && face < GetNumberOfSides(part))
1809 { 1997 {
@@ -1840,6 +2028,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1840 2028
1841 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2029 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1842 { 2030 {
2031 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2032 return;
2033
1843 Primitive.TextureEntry tex = part.Shape.Textures; 2034 Primitive.TextureEntry tex = part.Shape.Textures;
1844 if (face >= 0 && face < GetNumberOfSides(part)) 2035 if (face >= 0 && face < GetNumberOfSides(part))
1845 { 2036 {
@@ -1876,6 +2067,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1876 2067
1877 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2068 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1878 { 2069 {
2070 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2071 return;
2072
1879 Primitive.TextureEntry tex = part.Shape.Textures; 2073 Primitive.TextureEntry tex = part.Shape.Textures;
1880 if (face >= 0 && face < GetNumberOfSides(part)) 2074 if (face >= 0 && face < GetNumberOfSides(part))
1881 { 2075 {
@@ -1980,26 +2174,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1980 return real_vec; 2174 return real_vec;
1981 } 2175 }
1982 2176
2177 public LSL_Integer llSetRegionPos(LSL_Vector pos)
2178 {
2179 return new LSL_Integer(SetRegionPos(m_host, pos));
2180 }
2181
2182 protected int SetRegionPos(SceneObjectPart part, LSL_Vector targetPos)
2183 {
2184 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2185 return 0;
2186
2187 SceneObjectGroup grp = part.ParentGroup;
2188
2189 if (grp.IsAttachment)
2190 return 0;
2191
2192 if (grp.RootPart.PhysActor != null && grp.RootPart.PhysActor.IsPhysical)
2193 return 0;
2194
2195 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)
2196 return 0;
2197
2198 float constrainedX = (float)targetPos.x;
2199 float constrainedY = (float)targetPos.y;
2200
2201 if (constrainedX < 0.0f)
2202 constrainedX = 0.0f;
2203 if (constrainedY < 0.0f)
2204 constrainedY = 0.0f;
2205 if (constrainedX >= (float)Constants.RegionSize)
2206 constrainedX = (float)Constants.RegionSize - 0.1f;
2207 if (constrainedY >= (float)Constants.RegionSize)
2208 constrainedY = (float)Constants.RegionSize -0.1f;
2209
2210 float ground = World.GetGroundHeight(constrainedX, constrainedY);
2211
2212 if (targetPos.z < ground)
2213 targetPos.z = ground;
2214
2215 Vector3 dest = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z);
2216
2217 if (!World.Permissions.CanObjectEntry(grp.UUID, false, dest))
2218 return 0;
2219
2220 grp.UpdateGroupPosition(dest);
2221
2222 return 1;
2223 }
2224
1983 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2225 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1984 { 2226 {
1985 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2227 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2228 return;
2229
1986 LSL_Vector currentPos = GetPartLocalPos(part); 2230 LSL_Vector currentPos = GetPartLocalPos(part);
2231 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
1987 2232
1988 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
1989 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
1990 2233
1991 if (part.ParentGroup.RootPart == part) 2234 if (part.ParentGroup.RootPart == part)
1992 { 2235 {
1993 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
1994 targetPos.z = ground;
1995 SceneObjectGroup parent = part.ParentGroup; 2236 SceneObjectGroup parent = part.ParentGroup;
1996 LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); 2237 Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
1997 parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z)); 2238 if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest))
2239 return;
2240 Util.FireAndForget(delegate(object x) {
2241 parent.UpdateGroupPosition(dest);
2242 });
1998 } 2243 }
1999 else 2244 else
2000 { 2245 {
2001 LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); 2246 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
2002 part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z);
2003 SceneObjectGroup parent = part.ParentGroup; 2247 SceneObjectGroup parent = part.ParentGroup;
2004 parent.HasGroupChanged = true; 2248 parent.HasGroupChanged = true;
2005 parent.ScheduleGroupForTerseUpdate(); 2249 parent.ScheduleGroupForTerseUpdate();
@@ -2032,17 +2276,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2032 else 2276 else
2033 { 2277 {
2034 if (part.ParentGroup.IsAttachment) 2278 if (part.ParentGroup.IsAttachment)
2035 {
2036 pos = part.AttachedPos; 2279 pos = part.AttachedPos;
2037 }
2038 else 2280 else
2039 {
2040 pos = part.AbsolutePosition; 2281 pos = part.AbsolutePosition;
2041 }
2042 } 2282 }
2043 2283
2044// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2045
2046 return new LSL_Vector(pos.X, pos.Y, pos.Z); 2284 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2047 } 2285 }
2048 2286
@@ -2051,9 +2289,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2051 m_host.AddScriptLPS(1); 2289 m_host.AddScriptLPS(1);
2052 2290
2053 // try to let this work as in SL... 2291 // try to let this work as in SL...
2054 if (m_host.ParentID == 0) 2292 if (m_host.LinkNum < 2)
2055 { 2293 {
2056 // special case: If we are root, rotate complete SOG to new rotation 2294 // Special case: If we are root, rotate complete SOG to new
2295 // rotation.
2296 // We are root if the link number is 0 (single prim) or 1
2297 // (root prim). ParentID may be nonzero in attachments and
2298 // using it would cause attachments and HUDs to rotate
2299 // to the wrong positions.
2057 SetRot(m_host, Rot2Quaternion(rot)); 2300 SetRot(m_host, Rot2Quaternion(rot));
2058 } 2301 }
2059 else 2302 else
@@ -2078,6 +2321,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2078 2321
2079 protected void SetRot(SceneObjectPart part, Quaternion rot) 2322 protected void SetRot(SceneObjectPart part, Quaternion rot)
2080 { 2323 {
2324 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2325 return;
2326
2081 part.UpdateRotation(rot); 2327 part.UpdateRotation(rot);
2082 // Update rotation does not move the object in the physics scene if it's a linkset. 2328 // Update rotation does not move the object in the physics scene if it's a linkset.
2083 2329
@@ -2232,13 +2478,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2232 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2478 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2233 { 2479 {
2234 m_host.AddScriptLPS(1); 2480 m_host.AddScriptLPS(1);
2235 m_host.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); 2481 m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
2236 } 2482 }
2237 2483
2238 public void llSetTorque(LSL_Vector torque, int local) 2484 public void llSetTorque(LSL_Vector torque, int local)
2239 { 2485 {
2240 m_host.AddScriptLPS(1); 2486 m_host.AddScriptLPS(1);
2241 m_host.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); 2487 m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0);
2242 } 2488 }
2243 2489
2244 public LSL_Vector llGetTorque() 2490 public LSL_Vector llGetTorque()
@@ -2840,35 +3086,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2840 public void llLookAt(LSL_Vector target, double strength, double damping) 3086 public void llLookAt(LSL_Vector target, double strength, double damping)
2841 { 3087 {
2842 m_host.AddScriptLPS(1); 3088 m_host.AddScriptLPS(1);
2843 // Determine where we are looking from
2844 LSL_Vector from = llGetPos();
2845 3089
2846 // Work out the normalised vector from the source to the target 3090 // Get the normalized vector to the target
2847 LSL_Vector delta = llVecNorm(target - from); 3091 LSL_Vector d1 = llVecNorm(target - llGetPos());
2848 LSL_Vector angle = new LSL_Vector(0,0,0);
2849 3092
2850 // Calculate the yaw 3093 // Get the bearing (yaw)
2851 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3094 LSL_Vector a1 = new LSL_Vector(0,0,0);
2852 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3095 a1.z = llAtan2(d1.y, d1.x);
2853 3096
2854 // Calculate pitch 3097 // Get the elevation (pitch)
2855 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3098 LSL_Vector a2 = new LSL_Vector(0,0,0);
3099 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2856 3100
2857 // we need to convert from a vector describing 3101 LSL_Rotation r1 = llEuler2Rot(a1);
2858 // the angles of rotation in radians into rotation value 3102 LSL_Rotation r2 = llEuler2Rot(a2);
2859 LSL_Rotation rot = llEuler2Rot(angle); 3103 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2860
2861 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2862 // set the rotation of the object, copy that behavior
2863 PhysicsActor pa = m_host.PhysActor;
2864 3104
2865 if (strength == 0 || pa == null || !pa.IsPhysical) 3105 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2866 { 3106 {
2867 llSetRot(rot); 3107 // Do nothing if either value is 0 (this has been checked in SL)
3108 if (strength <= 0.0 || damping <= 0.0)
3109 return;
3110
3111 llSetRot(r3 * r2 * r1);
2868 } 3112 }
2869 else 3113 else
2870 { 3114 {
2871 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3115 if (strength == 0)
3116 {
3117 llSetRot(r3 * r2 * r1);
3118 return;
3119 }
3120
3121 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2872 } 3122 }
2873 } 3123 }
2874 3124
@@ -2914,17 +3164,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2914 } 3164 }
2915 else 3165 else
2916 { 3166 {
2917 if (m_host.IsRoot) 3167 // new SL always returns object mass
2918 { 3168// if (m_host.IsRoot)
3169// {
2919 return m_host.ParentGroup.GetMass(); 3170 return m_host.ParentGroup.GetMass();
2920 } 3171// }
2921 else 3172// else
2922 { 3173// {
2923 return m_host.GetMass(); 3174// return m_host.GetMass();
2924 } 3175// }
2925 } 3176 }
2926 } 3177 }
2927 3178
3179
3180 public LSL_Float llGetMassMKS()
3181 {
3182 return 100f * llGetMass();
3183 }
3184
2928 public void llCollisionFilter(string name, string id, int accept) 3185 public void llCollisionFilter(string name, string id, int accept)
2929 { 3186 {
2930 m_host.AddScriptLPS(1); 3187 m_host.AddScriptLPS(1);
@@ -3032,9 +3289,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3032 { 3289 {
3033 m_host.AddScriptLPS(1); 3290 m_host.AddScriptLPS(1);
3034 3291
3035// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3036// return;
3037
3038 if (m_item.PermsGranter != m_host.OwnerID) 3292 if (m_item.PermsGranter != m_host.OwnerID)
3039 return; 3293 return;
3040 3294
@@ -3077,6 +3331,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3077 3331
3078 public void llInstantMessage(string user, string message) 3332 public void llInstantMessage(string user, string message)
3079 { 3333 {
3334 UUID result;
3335 if (!UUID.TryParse(user, out result))
3336 {
3337 ShoutError("An invalid key was passed to llInstantMessage");
3338 ScriptSleep(2000);
3339 return;
3340 }
3341
3342
3080 m_host.AddScriptLPS(1); 3343 m_host.AddScriptLPS(1);
3081 3344
3082 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3345 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3091,14 +3354,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3091 UUID friendTransactionID = UUID.Random(); 3354 UUID friendTransactionID = UUID.Random();
3092 3355
3093 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3356 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3094 3357
3095 GridInstantMessage msg = new GridInstantMessage(); 3358 GridInstantMessage msg = new GridInstantMessage();
3096 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3359 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3097 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3360 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3098 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3361 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3099// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3362// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3100// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3363// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3101 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3364// DateTime dt = DateTime.UtcNow;
3365//
3366// // Ticks from UtcNow, but make it look like local. Evil, huh?
3367// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3368//
3369// try
3370// {
3371// // Convert that to the PST timezone
3372// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3373// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3374// }
3375// catch
3376// {
3377// // No logging here, as it could be VERY spammy
3378// }
3379//
3380// // And make it look local again to fool the unix time util
3381// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3382
3383 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3384
3102 //if (client != null) 3385 //if (client != null)
3103 //{ 3386 //{
3104 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3387 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3112,12 +3395,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3112 msg.message = message.Substring(0, 1024); 3395 msg.message = message.Substring(0, 1024);
3113 else 3396 else
3114 msg.message = message; 3397 msg.message = message;
3115 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3398 msg.dialog = (byte)19; // MessageFromObject
3116 msg.fromGroup = false;// fromGroup; 3399 msg.fromGroup = false;// fromGroup;
3117 msg.offline = (byte)0; //offline; 3400 msg.offline = (byte)0; //offline;
3118 msg.ParentEstateID = 0; //ParentEstateID; 3401 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3119 msg.Position = new Vector3(m_host.AbsolutePosition); 3402 msg.Position = new Vector3(m_host.AbsolutePosition);
3120 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3403 msg.RegionID = World.RegionInfo.RegionID.Guid;
3121 msg.binaryBucket 3404 msg.binaryBucket
3122 = Util.StringToBytes256( 3405 = Util.StringToBytes256(
3123 "{0}/{1}/{2}/{3}", 3406 "{0}/{1}/{2}/{3}",
@@ -3145,7 +3428,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3145 } 3428 }
3146 3429
3147 emailModule.SendEmail(m_host.UUID, address, subject, message); 3430 emailModule.SendEmail(m_host.UUID, address, subject, message);
3148 llSleep(EMAIL_PAUSE_TIME); 3431 ScriptSleep(EMAIL_PAUSE_TIME * 1000);
3149 } 3432 }
3150 3433
3151 public void llGetNextEmail(string address, string subject) 3434 public void llGetNextEmail(string address, string subject)
@@ -3394,15 +3677,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3394 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3677 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3395 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3678 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3396 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3679 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3680 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3397 ScriptBaseClass.PERMISSION_ATTACH; 3681 ScriptBaseClass.PERMISSION_ATTACH;
3398 3682
3399 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3683 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3400 { 3684 {
3401 lock (m_host.TaskInventory) 3685 m_host.TaskInventory.LockItemsForWrite(true);
3402 { 3686 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3403 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3687 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3404 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3688 m_host.TaskInventory.LockItemsForWrite(false);
3405 }
3406 3689
3407 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3690 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3408 "run_time_permissions", new Object[] { 3691 "run_time_permissions", new Object[] {
@@ -3412,28 +3695,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3412 return; 3695 return;
3413 } 3696 }
3414 } 3697 }
3415 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3698 else
3416 { 3699 {
3417 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3700 bool sitting = false;
3418 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3701 if (m_host.SitTargetAvatar == agentID)
3419 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3702 {
3420 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3703 sitting = true;
3421 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3704 }
3705 else
3706 {
3707 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3708 {
3709 if (p.SitTargetAvatar == agentID)
3710 sitting = true;
3711 }
3712 }
3422 3713
3423 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3714 if (sitting)
3424 { 3715 {
3425 lock (m_host.TaskInventory) 3716 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3717 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3718 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3719 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3720 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3721
3722 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3426 { 3723 {
3724 m_host.TaskInventory.LockItemsForWrite(true);
3427 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3725 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3428 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3726 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3429 } 3727 m_host.TaskInventory.LockItemsForWrite(false);
3430 3728
3431 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3729 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3432 "run_time_permissions", new Object[] { 3730 "run_time_permissions", new Object[] {
3433 new LSL_Integer(perm) }, 3731 new LSL_Integer(perm) },
3434 new DetectParams[0])); 3732 new DetectParams[0]));
3435 3733
3436 return; 3734 return;
3735 }
3437 } 3736 }
3438 } 3737 }
3439 3738
@@ -3447,11 +3746,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3447 3746
3448 if (!m_waitingForScriptAnswer) 3747 if (!m_waitingForScriptAnswer)
3449 { 3748 {
3450 lock (m_host.TaskInventory) 3749 m_host.TaskInventory.LockItemsForWrite(true);
3451 { 3750 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3452 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3751 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3453 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 3752 m_host.TaskInventory.LockItemsForWrite(false);
3454 }
3455 3753
3456 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3754 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3457 m_waitingForScriptAnswer=true; 3755 m_waitingForScriptAnswer=true;
@@ -3481,11 +3779,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3481 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3779 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3482 llReleaseControls(); 3780 llReleaseControls();
3483 3781
3484 lock (m_host.TaskInventory) 3782 m_host.TaskInventory.LockItemsForWrite(true);
3485 { 3783 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3486 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 3784 m_host.TaskInventory.LockItemsForWrite(false);
3487 } 3785
3488
3489 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3786 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3490 "run_time_permissions", new Object[] { 3787 "run_time_permissions", new Object[] {
3491 new LSL_Integer(answer) }, 3788 new LSL_Integer(answer) },
@@ -3528,14 +3825,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3528 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3825 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3529 { 3826 {
3530 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3827 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3531 3828 if (parts.Count > 0)
3532 foreach (SceneObjectPart part in parts) 3829 {
3533 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3830 try
3831 {
3832 parts[0].ParentGroup.areUpdatesSuspended = true;
3833 foreach (SceneObjectPart part in parts)
3834 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3835 }
3836 finally
3837 {
3838 parts[0].ParentGroup.areUpdatesSuspended = false;
3839 }
3840 }
3534 } 3841 }
3535 3842
3536 public void llCreateLink(string target, int parent) 3843 public void llCreateLink(string target, int parent)
3537 { 3844 {
3538 m_host.AddScriptLPS(1); 3845 m_host.AddScriptLPS(1);
3846
3539 UUID targetID; 3847 UUID targetID;
3540 3848
3541 if (!UUID.TryParse(target, out targetID)) 3849 if (!UUID.TryParse(target, out targetID))
@@ -3641,10 +3949,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3641 // Restructuring Multiple Prims. 3949 // Restructuring Multiple Prims.
3642 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 3950 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3643 parts.Remove(parentPrim.RootPart); 3951 parts.Remove(parentPrim.RootPart);
3644 foreach (SceneObjectPart part in parts) 3952 if (parts.Count > 0)
3645 { 3953 {
3646 parentPrim.DelinkFromGroup(part.LocalId, true); 3954 try
3955 {
3956 parts[0].ParentGroup.areUpdatesSuspended = true;
3957 foreach (SceneObjectPart part in parts)
3958 {
3959 parentPrim.DelinkFromGroup(part.LocalId, true);
3960 }
3961 }
3962 finally
3963 {
3964 parts[0].ParentGroup.areUpdatesSuspended = false;
3965 }
3647 } 3966 }
3967
3648 parentPrim.HasGroupChanged = true; 3968 parentPrim.HasGroupChanged = true;
3649 parentPrim.ScheduleGroupForFullUpdate(); 3969 parentPrim.ScheduleGroupForFullUpdate();
3650 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3970 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3653,12 +3973,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3653 { 3973 {
3654 SceneObjectPart newRoot = parts[0]; 3974 SceneObjectPart newRoot = parts[0];
3655 parts.Remove(newRoot); 3975 parts.Remove(newRoot);
3656 foreach (SceneObjectPart part in parts) 3976
3977 try
3657 { 3978 {
3658 // Required for linking 3979 parts[0].ParentGroup.areUpdatesSuspended = true;
3659 part.ClearUpdateSchedule(); 3980 foreach (SceneObjectPart part in parts)
3660 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 3981 {
3982 part.ClearUpdateSchedule();
3983 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3984 }
3661 } 3985 }
3986 finally
3987 {
3988 parts[0].ParentGroup.areUpdatesSuspended = false;
3989 }
3990
3991
3662 newRoot.ParentGroup.HasGroupChanged = true; 3992 newRoot.ParentGroup.HasGroupChanged = true;
3663 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 3993 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3664 } 3994 }
@@ -3678,6 +4008,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3678 public void llBreakAllLinks() 4008 public void llBreakAllLinks()
3679 { 4009 {
3680 m_host.AddScriptLPS(1); 4010 m_host.AddScriptLPS(1);
4011
4012 TaskInventoryItem item = m_item;
4013
4014 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4015 && !m_automaticLinkPermission)
4016 {
4017 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4018 return;
4019 }
4020
3681 SceneObjectGroup parentPrim = m_host.ParentGroup; 4021 SceneObjectGroup parentPrim = m_host.ParentGroup;
3682 if (parentPrim.AttachmentPoint != 0) 4022 if (parentPrim.AttachmentPoint != 0)
3683 return; // Fail silently if attached 4023 return; // Fail silently if attached
@@ -3697,25 +4037,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3697 public LSL_String llGetLinkKey(int linknum) 4037 public LSL_String llGetLinkKey(int linknum)
3698 { 4038 {
3699 m_host.AddScriptLPS(1); 4039 m_host.AddScriptLPS(1);
3700 List<UUID> keytable = new List<UUID>();
3701 // parse for sitting avatare-uuids
3702 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3703 {
3704 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
3705 keytable.Add(presence.UUID);
3706 });
3707
3708 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3709 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3710 {
3711 return keytable[totalprims - linknum].ToString();
3712 }
3713
3714 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3715 {
3716 return m_host.UUID.ToString();
3717 }
3718
3719 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4040 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3720 if (part != null) 4041 if (part != null)
3721 { 4042 {
@@ -3723,6 +4044,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3723 } 4044 }
3724 else 4045 else
3725 { 4046 {
4047 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4048 {
4049 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4050
4051 if (linknum < 0)
4052 return UUID.Zero.ToString();
4053
4054 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4055 if (avatars.Count > linknum)
4056 {
4057 return avatars[linknum].UUID.ToString();
4058 }
4059 }
3726 return UUID.Zero.ToString(); 4060 return UUID.Zero.ToString();
3727 } 4061 }
3728 } 4062 }
@@ -3822,17 +4156,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3822 m_host.AddScriptLPS(1); 4156 m_host.AddScriptLPS(1);
3823 int count = 0; 4157 int count = 0;
3824 4158
3825 lock (m_host.TaskInventory) 4159 m_host.TaskInventory.LockItemsForRead(true);
4160 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3826 { 4161 {
3827 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4162 if (inv.Value.Type == type || type == -1)
3828 { 4163 {
3829 if (inv.Value.Type == type || type == -1) 4164 count = count + 1;
3830 {
3831 count = count + 1;
3832 }
3833 } 4165 }
3834 } 4166 }
3835 4167
4168 m_host.TaskInventory.LockItemsForRead(false);
3836 return count; 4169 return count;
3837 } 4170 }
3838 4171
@@ -3841,16 +4174,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3841 m_host.AddScriptLPS(1); 4174 m_host.AddScriptLPS(1);
3842 ArrayList keys = new ArrayList(); 4175 ArrayList keys = new ArrayList();
3843 4176
3844 lock (m_host.TaskInventory) 4177 m_host.TaskInventory.LockItemsForRead(true);
4178 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3845 { 4179 {
3846 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4180 if (inv.Value.Type == type || type == -1)
3847 { 4181 {
3848 if (inv.Value.Type == type || type == -1) 4182 keys.Add(inv.Value.Name);
3849 {
3850 keys.Add(inv.Value.Name);
3851 }
3852 } 4183 }
3853 } 4184 }
4185 m_host.TaskInventory.LockItemsForRead(false);
3854 4186
3855 if (keys.Count == 0) 4187 if (keys.Count == 0)
3856 { 4188 {
@@ -3887,25 +4219,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3887 } 4219 }
3888 4220
3889 // move the first object found with this inventory name 4221 // move the first object found with this inventory name
3890 lock (m_host.TaskInventory) 4222 m_host.TaskInventory.LockItemsForRead(true);
4223 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3891 { 4224 {
3892 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4225 if (inv.Value.Name == inventory)
3893 { 4226 {
3894 if (inv.Value.Name == inventory) 4227 found = true;
3895 { 4228 objId = inv.Key;
3896 found = true; 4229 assetType = inv.Value.Type;
3897 objId = inv.Key; 4230 objName = inv.Value.Name;
3898 assetType = inv.Value.Type; 4231 break;
3899 objName = inv.Value.Name;
3900 break;
3901 }
3902 } 4232 }
3903 } 4233 }
4234 m_host.TaskInventory.LockItemsForRead(false);
3904 4235
3905 if (!found) 4236 if (!found)
3906 { 4237 {
3907 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4238 llSay(0, String.Format("Could not find object '{0}'", inventory));
3908 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4239 return;
4240// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3909 } 4241 }
3910 4242
3911 // check if destination is an object 4243 // check if destination is an object
@@ -3931,48 +4263,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3931 return; 4263 return;
3932 } 4264 }
3933 } 4265 }
4266
3934 // destination is an avatar 4267 // destination is an avatar
3935 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4268 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3936 4269
3937 if (agentItem == null) 4270 if (agentItem == null)
3938 return; 4271 return;
3939 4272
3940 byte[] bucket = new byte[17]; 4273 byte[] bucket = new byte[1];
3941 bucket[0] = (byte)assetType; 4274 bucket[0] = (byte)assetType;
3942 byte[] objBytes = agentItem.ID.GetBytes(); 4275 //byte[] objBytes = agentItem.ID.GetBytes();
3943 Array.Copy(objBytes, 0, bucket, 1, 16); 4276 //Array.Copy(objBytes, 0, bucket, 1, 16);
3944 4277
3945 GridInstantMessage msg = new GridInstantMessage(World, 4278 GridInstantMessage msg = new GridInstantMessage(World,
3946 m_host.UUID, m_host.Name+", an object owned by "+ 4279 m_host.OwnerID, m_host.Name, destId,
3947 resolveName(m_host.OwnerID)+",", destId,
3948 (byte)InstantMessageDialog.TaskInventoryOffered, 4280 (byte)InstantMessageDialog.TaskInventoryOffered,
3949 false, objName+"\n"+m_host.Name+" is located at "+ 4281 false, objName+". "+m_host.Name+" is located at "+
3950 World.RegionInfo.RegionName+" "+ 4282 World.RegionInfo.RegionName+" "+
3951 m_host.AbsolutePosition.ToString(), 4283 m_host.AbsolutePosition.ToString(),
3952 agentItem.ID, true, m_host.AbsolutePosition, 4284 agentItem.ID, true, m_host.AbsolutePosition,
3953 bucket); 4285 bucket);
3954 if (m_TransferModule != null) 4286
3955 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4287 ScenePresence sp;
4288
4289 if (World.TryGetScenePresence(destId, out sp))
4290 {
4291 sp.ControllingClient.SendInstantMessage(msg);
4292 }
4293 else
4294 {
4295 if (m_TransferModule != null)
4296 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4297 }
4298
4299 //This delay should only occur when giving inventory to avatars.
3956 ScriptSleep(3000); 4300 ScriptSleep(3000);
3957 } 4301 }
3958 } 4302 }
3959 4303
4304 [DebuggerNonUserCode]
3960 public void llRemoveInventory(string name) 4305 public void llRemoveInventory(string name)
3961 { 4306 {
3962 m_host.AddScriptLPS(1); 4307 m_host.AddScriptLPS(1);
3963 4308
3964 lock (m_host.TaskInventory) 4309 List<TaskInventoryItem> inv;
4310 try
3965 { 4311 {
3966 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4312 m_host.TaskInventory.LockItemsForRead(true);
4313 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4314 }
4315 finally
4316 {
4317 m_host.TaskInventory.LockItemsForRead(false);
4318 }
4319 foreach (TaskInventoryItem item in inv)
4320 {
4321 if (item.Name == name)
3967 { 4322 {
3968 if (item.Name == name) 4323 if (item.ItemID == m_item.ItemID)
3969 { 4324 throw new ScriptDeleteException();
3970 if (item.ItemID == m_item.ItemID) 4325 else
3971 throw new ScriptDeleteException(); 4326 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3972 else 4327 return;
3973 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3974 return;
3975 }
3976 } 4328 }
3977 } 4329 }
3978 } 4330 }
@@ -4007,115 +4359,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4007 { 4359 {
4008 m_host.AddScriptLPS(1); 4360 m_host.AddScriptLPS(1);
4009 4361
4010 UUID uuid = (UUID)id; 4362 UUID uuid;
4011 PresenceInfo pinfo = null; 4363 if (UUID.TryParse(id, out uuid))
4012 UserAccount account;
4013
4014 UserInfoCacheEntry ce;
4015 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4016 { 4364 {
4017 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4365 PresenceInfo pinfo = null;
4018 if (account == null) 4366 UserAccount account;
4367
4368 UserInfoCacheEntry ce;
4369 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4019 { 4370 {
4020 m_userInfoCache[uuid] = null; // Cache negative 4371 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4021 return UUID.Zero.ToString(); 4372 if (account == null)
4022 } 4373 {
4374 m_userInfoCache[uuid] = null; // Cache negative
4375 return UUID.Zero.ToString();
4376 }
4023 4377
4024 4378
4025 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4379 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4026 if (pinfos != null && pinfos.Length > 0) 4380 if (pinfos != null && pinfos.Length > 0)
4027 {
4028 foreach (PresenceInfo p in pinfos)
4029 { 4381 {
4030 if (p.RegionID != UUID.Zero) 4382 foreach (PresenceInfo p in pinfos)
4031 { 4383 {
4032 pinfo = p; 4384 if (p.RegionID != UUID.Zero)
4385 {
4386 pinfo = p;
4387 }
4033 } 4388 }
4034 } 4389 }
4035 }
4036 4390
4037 ce = new UserInfoCacheEntry(); 4391 ce = new UserInfoCacheEntry();
4038 ce.time = Util.EnvironmentTickCount(); 4392 ce.time = Util.EnvironmentTickCount();
4039 ce.account = account; 4393 ce.account = account;
4040 ce.pinfo = pinfo; 4394 ce.pinfo = pinfo;
4041 } 4395 m_userInfoCache[uuid] = ce;
4042 else 4396 }
4043 { 4397 else
4044 if (ce == null) 4398 {
4045 return UUID.Zero.ToString(); 4399 if (ce == null)
4400 return UUID.Zero.ToString();
4046 4401
4047 account = ce.account; 4402 account = ce.account;
4048 pinfo = ce.pinfo; 4403 pinfo = ce.pinfo;
4049 } 4404 }
4050 4405
4051 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4406 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4052 {
4053 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4054 if (pinfos != null && pinfos.Length > 0)
4055 { 4407 {
4056 foreach (PresenceInfo p in pinfos) 4408 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4409 if (pinfos != null && pinfos.Length > 0)
4057 { 4410 {
4058 if (p.RegionID != UUID.Zero) 4411 foreach (PresenceInfo p in pinfos)
4059 { 4412 {
4060 pinfo = p; 4413 if (p.RegionID != UUID.Zero)
4414 {
4415 pinfo = p;
4416 }
4061 } 4417 }
4062 } 4418 }
4063 } 4419 else
4064 else 4420 pinfo = null;
4065 pinfo = null;
4066 4421
4067 ce.time = Util.EnvironmentTickCount(); 4422 ce.time = Util.EnvironmentTickCount();
4068 ce.pinfo = pinfo; 4423 ce.pinfo = pinfo;
4069 } 4424 }
4070 4425
4071 string reply = String.Empty; 4426 string reply = String.Empty;
4072 4427
4073 switch (data) 4428 switch (data)
4074 { 4429 {
4075 case 1: // DATA_ONLINE (0|1) 4430 case 1: // DATA_ONLINE (0|1)
4076 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4431 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4077 reply = "1"; 4432 reply = "1";
4078 else 4433 else
4079 reply = "0"; 4434 reply = "0";
4080 break; 4435 break;
4081 case 2: // DATA_NAME (First Last) 4436 case 2: // DATA_NAME (First Last)
4082 reply = account.FirstName + " " + account.LastName; 4437 reply = account.FirstName + " " + account.LastName;
4083 break; 4438 break;
4084 case 3: // DATA_BORN (YYYY-MM-DD) 4439 case 3: // DATA_BORN (YYYY-MM-DD)
4085 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4440 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4086 born = born.AddSeconds(account.Created); 4441 born = born.AddSeconds(account.Created);
4087 reply = born.ToString("yyyy-MM-dd"); 4442 reply = born.ToString("yyyy-MM-dd");
4088 break; 4443 break;
4089 case 4: // DATA_RATING (0,0,0,0,0,0) 4444 case 4: // DATA_RATING (0,0,0,0,0,0)
4090 reply = "0,0,0,0,0,0"; 4445 reply = "0,0,0,0,0,0";
4091 break; 4446 break;
4092 case 7: // DATA_USERLEVEL (integer) 4447 case 8: // DATA_PAYINFO (0|1|2|3)
4093 reply = account.UserLevel.ToString(); 4448 reply = "0";
4094 break; 4449 break;
4095 case 8: // DATA_PAYINFO (0|1|2|3) 4450 default:
4096 reply = "0"; 4451 return UUID.Zero.ToString(); // Raise no event
4097 break; 4452 }
4098 default:
4099 return UUID.Zero.ToString(); // Raise no event
4100 }
4101 4453
4102 UUID rq = UUID.Random(); 4454 UUID rq = UUID.Random();
4103 4455
4104 UUID tid = AsyncCommands. 4456 UUID tid = AsyncCommands.
4105 DataserverPlugin.RegisterRequest(m_host.LocalId, 4457 DataserverPlugin.RegisterRequest(m_host.LocalId,
4106 m_item.ItemID, rq.ToString()); 4458 m_item.ItemID, rq.ToString());
4107 4459
4108 AsyncCommands. 4460 AsyncCommands.
4109 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4461 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4110 4462
4111 ScriptSleep(100); 4463 ScriptSleep(100);
4112 return tid.ToString(); 4464 return tid.ToString();
4465 }
4466 else
4467 {
4468 ShoutError("Invalid UUID passed to llRequestAgentData.");
4469 }
4470 return "";
4113 } 4471 }
4114 4472
4115 public LSL_String llRequestInventoryData(string name) 4473 public LSL_String llRequestInventoryData(string name)
4116 { 4474 {
4117 m_host.AddScriptLPS(1); 4475 m_host.AddScriptLPS(1);
4118 4476
4477 //Clone is thread safe
4119 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4478 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4120 4479
4121 foreach (TaskInventoryItem item in itemDictionary.Values) 4480 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4167,19 +4526,64 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4167 if (UUID.TryParse(agent, out agentId)) 4526 if (UUID.TryParse(agent, out agentId))
4168 { 4527 {
4169 ScenePresence presence = World.GetScenePresence(agentId); 4528 ScenePresence presence = World.GetScenePresence(agentId);
4170 if (presence != null) 4529 if (presence != null && presence.PresenceType != PresenceType.Npc)
4171 { 4530 {
4531 // agent must not be a god
4532 if (presence.UserLevel >= 200) return;
4533
4172 // agent must be over the owners land 4534 // agent must be over the owners land
4173 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4535 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4174 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4536 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4175 { 4537 {
4176 World.TeleportClientHome(agentId, presence.ControllingClient); 4538 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4539 {
4540 // They can't be teleported home for some reason
4541 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4542 if (regionInfo != null)
4543 {
4544 World.RequestTeleportLocation(
4545 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4546 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4547 }
4548 }
4177 } 4549 }
4178 } 4550 }
4179 } 4551 }
4180 ScriptSleep(5000); 4552 ScriptSleep(5000);
4181 } 4553 }
4182 4554
4555 public void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt)
4556 {
4557 m_host.AddScriptLPS(1);
4558 UUID agentId = new UUID();
4559 if (UUID.TryParse(agent, out agentId))
4560 {
4561 ScenePresence presence = World.GetScenePresence(agentId);
4562 if (presence != null && presence.PresenceType != PresenceType.Npc)
4563 {
4564 // agent must not be a god
4565 if (presence.GodLevel >= 200) return;
4566
4567 if (simname == String.Empty)
4568 simname = World.RegionInfo.RegionName;
4569
4570 // agent must be over the owners land
4571 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4572 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4573 {
4574 World.RequestTeleportLocation(presence.ControllingClient, simname, new Vector3((float)pos.x, (float)pos.y, (float)pos.z), new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z), (uint)TeleportFlags.ViaLocation);
4575 }
4576 else // or must be wearing the prim
4577 {
4578 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4579 {
4580 World.RequestTeleportLocation(presence.ControllingClient, simname, new Vector3((float)pos.x, (float)pos.y, (float)pos.z), new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z), (uint)TeleportFlags.ViaLocation);
4581 }
4582 }
4583 }
4584 }
4585 }
4586
4183 public void llTextBox(string agent, string message, int chatChannel) 4587 public void llTextBox(string agent, string message, int chatChannel)
4184 { 4588 {
4185 IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); 4589 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
@@ -4191,7 +4595,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4191 UUID av = new UUID(); 4595 UUID av = new UUID();
4192 if (!UUID.TryParse(agent,out av)) 4596 if (!UUID.TryParse(agent,out av))
4193 { 4597 {
4194 LSLError("First parameter to llDialog needs to be a key"); 4598 //LSLError("First parameter to llDialog needs to be a key");
4195 return; 4599 return;
4196 } 4600 }
4197 4601
@@ -4228,17 +4632,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4228 UUID soundId = UUID.Zero; 4632 UUID soundId = UUID.Zero;
4229 if (!UUID.TryParse(impact_sound, out soundId)) 4633 if (!UUID.TryParse(impact_sound, out soundId))
4230 { 4634 {
4231 lock (m_host.TaskInventory) 4635 m_host.TaskInventory.LockItemsForRead(true);
4636 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4232 { 4637 {
4233 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4638 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4234 { 4639 {
4235 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4640 soundId = item.AssetID;
4236 { 4641 break;
4237 soundId = item.AssetID;
4238 break;
4239 }
4240 } 4642 }
4241 } 4643 }
4644 m_host.TaskInventory.LockItemsForRead(false);
4242 } 4645 }
4243 m_host.CollisionSound = soundId; 4646 m_host.CollisionSound = soundId;
4244 m_host.CollisionSoundVolume = (float)impact_volume; 4647 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4278,6 +4681,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4278 UUID partItemID; 4681 UUID partItemID;
4279 foreach (SceneObjectPart part in parts) 4682 foreach (SceneObjectPart part in parts)
4280 { 4683 {
4684 //Clone is thread safe
4281 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4685 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4282 4686
4283 foreach (TaskInventoryItem item in itemsDictionary.Values) 4687 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4411,7 +4815,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4411 { 4815 {
4412 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4816 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4413 float distance_term = distance * distance * distance; // Script Energy 4817 float distance_term = distance * distance * distance; // Script Energy
4414 float pusher_mass = m_host.GetMass(); 4818 // use total object mass and not part
4819 float pusher_mass = m_host.ParentGroup.GetMass();
4415 4820
4416 float PUSH_ATTENUATION_DISTANCE = 17f; 4821 float PUSH_ATTENUATION_DISTANCE = 17f;
4417 float PUSH_ATTENUATION_SCALE = 5f; 4822 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4650,23 +5055,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4650 { 5055 {
4651 m_host.AddScriptLPS(1); 5056 m_host.AddScriptLPS(1);
4652 5057
4653 lock (m_host.TaskInventory) 5058 m_host.TaskInventory.LockItemsForRead(true);
5059 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4654 { 5060 {
4655 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5061 if (inv.Value.Name == name)
4656 { 5062 {
4657 if (inv.Value.Name == name) 5063 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4658 { 5064 {
4659 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5065 m_host.TaskInventory.LockItemsForRead(false);
4660 { 5066 return inv.Value.AssetID.ToString();
4661 return inv.Value.AssetID.ToString(); 5067 }
4662 } 5068 else
4663 else 5069 {
4664 { 5070 m_host.TaskInventory.LockItemsForRead(false);
4665 return UUID.Zero.ToString(); 5071 return UUID.Zero.ToString();
4666 }
4667 } 5072 }
4668 } 5073 }
4669 } 5074 }
5075 m_host.TaskInventory.LockItemsForRead(false);
4670 5076
4671 return UUID.Zero.ToString(); 5077 return UUID.Zero.ToString();
4672 } 5078 }
@@ -4800,7 +5206,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4800 public LSL_Vector llGetCenterOfMass() 5206 public LSL_Vector llGetCenterOfMass()
4801 { 5207 {
4802 m_host.AddScriptLPS(1); 5208 m_host.AddScriptLPS(1);
4803 Vector3 center = m_host.GetGeometricCenter(); 5209 Vector3 center = m_host.GetCenterOfMass();
4804 return new LSL_Vector(center.X,center.Y,center.Z); 5210 return new LSL_Vector(center.X,center.Y,center.Z);
4805 } 5211 }
4806 5212
@@ -4819,14 +5225,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4819 { 5225 {
4820 m_host.AddScriptLPS(1); 5226 m_host.AddScriptLPS(1);
4821 5227
4822 if (src == null) 5228 return src.Length;
4823 {
4824 return 0;
4825 }
4826 else
4827 {
4828 return src.Length;
4829 }
4830 } 5229 }
4831 5230
4832 public LSL_Integer llList2Integer(LSL_List src, int index) 5231 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4872,7 +5271,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4872 else if (src.Data[index] is LSL_Float) 5271 else if (src.Data[index] is LSL_Float)
4873 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5272 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4874 else if (src.Data[index] is LSL_String) 5273 else if (src.Data[index] is LSL_String)
4875 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5274 {
5275 string str = ((LSL_String) src.Data[index]).m_string;
5276 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5277 if (m != Match.Empty)
5278 {
5279 str = m.Value;
5280 double d = 0.0;
5281 if (!Double.TryParse(str, out d))
5282 return 0.0;
5283
5284 return d;
5285 }
5286 return 0.0;
5287 }
4876 return Convert.ToDouble(src.Data[index]); 5288 return Convert.ToDouble(src.Data[index]);
4877 } 5289 }
4878 catch (FormatException) 5290 catch (FormatException)
@@ -5145,7 +5557,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5145 } 5557 }
5146 } 5558 }
5147 } 5559 }
5148 else { 5560 else
5561 {
5149 object[] array = new object[src.Length]; 5562 object[] array = new object[src.Length];
5150 Array.Copy(src.Data, 0, array, 0, src.Length); 5563 Array.Copy(src.Data, 0, array, 0, src.Length);
5151 result = new LSL_List(array); 5564 result = new LSL_List(array);
@@ -5252,7 +5665,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5252 public LSL_Integer llGetRegionAgentCount() 5665 public LSL_Integer llGetRegionAgentCount()
5253 { 5666 {
5254 m_host.AddScriptLPS(1); 5667 m_host.AddScriptLPS(1);
5255 return new LSL_Integer(World.GetRootAgentCount()); 5668
5669 int count = 0;
5670 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5671 count++;
5672 });
5673
5674 return new LSL_Integer(count);
5256 } 5675 }
5257 5676
5258 public LSL_Vector llGetRegionCorner() 5677 public LSL_Vector llGetRegionCorner()
@@ -5532,6 +5951,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5532 flags |= ScriptBaseClass.AGENT_SITTING; 5951 flags |= ScriptBaseClass.AGENT_SITTING;
5533 } 5952 }
5534 5953
5954 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
5955 {
5956 flags |= ScriptBaseClass.AGENT_MALE;
5957 }
5958
5535 return flags; 5959 return flags;
5536 } 5960 }
5537 5961
@@ -5679,10 +6103,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5679 m_host.AddScriptLPS(1); 6103 m_host.AddScriptLPS(1);
5680 6104
5681 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6105 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5682 6106 if (parts.Count > 0)
5683 foreach (var part in parts)
5684 { 6107 {
5685 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6108 try
6109 {
6110 parts[0].ParentGroup.areUpdatesSuspended = true;
6111 foreach (var part in parts)
6112 {
6113 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6114 }
6115 }
6116 finally
6117 {
6118 parts[0].ParentGroup.areUpdatesSuspended = false;
6119 }
5686 } 6120 }
5687 } 6121 }
5688 6122
@@ -5734,13 +6168,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5734 6168
5735 if (m_host.OwnerID == land.LandData.OwnerID) 6169 if (m_host.OwnerID == land.LandData.OwnerID)
5736 { 6170 {
5737 World.TeleportClientHome(agentID, presence.ControllingClient); 6171 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6172 presence.TeleportWithMomentum(pos, null);
6173 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5738 } 6174 }
5739 } 6175 }
5740 } 6176 }
5741 ScriptSleep(5000); 6177 ScriptSleep(5000);
5742 } 6178 }
5743 6179
6180 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6181 {
6182 return ParseString2List(str, separators, in_spacers, false);
6183 }
6184
5744 public LSL_Integer llOverMyLand(string id) 6185 public LSL_Integer llOverMyLand(string id)
5745 { 6186 {
5746 m_host.AddScriptLPS(1); 6187 m_host.AddScriptLPS(1);
@@ -5805,8 +6246,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5805 UUID agentId = new UUID(); 6246 UUID agentId = new UUID();
5806 if (!UUID.TryParse(agent, out agentId)) 6247 if (!UUID.TryParse(agent, out agentId))
5807 return new LSL_Integer(0); 6248 return new LSL_Integer(0);
6249 if (agentId == m_host.GroupID)
6250 return new LSL_Integer(1);
5808 ScenePresence presence = World.GetScenePresence(agentId); 6251 ScenePresence presence = World.GetScenePresence(agentId);
5809 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6252 if (presence == null || presence.IsChildAgent) // Return false for child agents
5810 return new LSL_Integer(0); 6253 return new LSL_Integer(0);
5811 IClientAPI client = presence.ControllingClient; 6254 IClientAPI client = presence.ControllingClient;
5812 if (m_host.GroupID == client.ActiveGroupId) 6255 if (m_host.GroupID == client.ActiveGroupId)
@@ -5941,7 +6384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5941 return m_host.ParentGroup.AttachmentPoint; 6384 return m_host.ParentGroup.AttachmentPoint;
5942 } 6385 }
5943 6386
5944 public LSL_Integer llGetFreeMemory() 6387 public virtual LSL_Integer llGetFreeMemory()
5945 { 6388 {
5946 m_host.AddScriptLPS(1); 6389 m_host.AddScriptLPS(1);
5947 // Make scripts designed for LSO happy 6390 // Make scripts designed for LSO happy
@@ -6058,7 +6501,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6058 SetParticleSystem(m_host, rules); 6501 SetParticleSystem(m_host, rules);
6059 } 6502 }
6060 6503
6061 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6504 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6505 {
6062 6506
6063 6507
6064 if (rules.Length == 0) 6508 if (rules.Length == 0)
@@ -6252,14 +6696,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6252 6696
6253 protected UUID GetTaskInventoryItem(string name) 6697 protected UUID GetTaskInventoryItem(string name)
6254 { 6698 {
6255 lock (m_host.TaskInventory) 6699 m_host.TaskInventory.LockItemsForRead(true);
6700 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6256 { 6701 {
6257 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6702 if (inv.Value.Name == name)
6258 { 6703 {
6259 if (inv.Value.Name == name) 6704 m_host.TaskInventory.LockItemsForRead(false);
6260 return inv.Key; 6705 return inv.Key;
6261 } 6706 }
6262 } 6707 }
6708 m_host.TaskInventory.LockItemsForRead(false);
6263 6709
6264 return UUID.Zero; 6710 return UUID.Zero;
6265 } 6711 }
@@ -6297,16 +6743,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6297 if (folderID == UUID.Zero) 6743 if (folderID == UUID.Zero)
6298 return; 6744 return;
6299 6745
6300 byte[] bucket = new byte[17]; 6746 byte[] bucket = new byte[1];
6301 bucket[0] = (byte)AssetType.Folder; 6747 bucket[0] = (byte)AssetType.Folder;
6302 byte[] objBytes = folderID.GetBytes(); 6748 //byte[] objBytes = folderID.GetBytes();
6303 Array.Copy(objBytes, 0, bucket, 1, 16); 6749 //Array.Copy(objBytes, 0, bucket, 1, 16);
6304 6750
6305 GridInstantMessage msg = new GridInstantMessage(World, 6751 GridInstantMessage msg = new GridInstantMessage(World,
6306 m_host.UUID, m_host.Name+", an object owned by "+ 6752 m_host.OwnerID, m_host.Name, destID,
6307 resolveName(m_host.OwnerID)+",", destID, 6753 (byte)InstantMessageDialog.TaskInventoryOffered,
6308 (byte)InstantMessageDialog.InventoryOffered, 6754 false, category+". "+m_host.Name+" is located at "+
6309 false, category+"\n"+m_host.Name+" is located at "+
6310 World.RegionInfo.RegionName+" "+ 6755 World.RegionInfo.RegionName+" "+
6311 m_host.AbsolutePosition.ToString(), 6756 m_host.AbsolutePosition.ToString(),
6312 folderID, true, m_host.AbsolutePosition, 6757 folderID, true, m_host.AbsolutePosition,
@@ -6544,13 +6989,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6544 UUID av = new UUID(); 6989 UUID av = new UUID();
6545 if (!UUID.TryParse(avatar,out av)) 6990 if (!UUID.TryParse(avatar,out av))
6546 { 6991 {
6547 LSLError("First parameter to llDialog needs to be a key"); 6992 //LSLError("First parameter to llDialog needs to be a key");
6548 return; 6993 return;
6549 } 6994 }
6550 if (buttons.Length < 1) 6995 if (buttons.Length < 1)
6551 { 6996 {
6552 LSLError("No less than 1 button can be shown"); 6997 buttons.Add("OK");
6553 return;
6554 } 6998 }
6555 if (buttons.Length > 12) 6999 if (buttons.Length > 12)
6556 { 7000 {
@@ -6567,7 +7011,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6567 } 7011 }
6568 if (buttons.Data[i].ToString().Length > 24) 7012 if (buttons.Data[i].ToString().Length > 24)
6569 { 7013 {
6570 LSLError("button label cannot be longer than 24 characters"); 7014 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6571 return; 7015 return;
6572 } 7016 }
6573 buts[i] = buttons.Data[i].ToString(); 7017 buts[i] = buttons.Data[i].ToString();
@@ -6626,22 +7070,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6626 } 7070 }
6627 7071
6628 // copy the first script found with this inventory name 7072 // copy the first script found with this inventory name
6629 lock (m_host.TaskInventory) 7073 TaskInventoryItem scriptItem = null;
7074 m_host.TaskInventory.LockItemsForRead(true);
7075 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6630 { 7076 {
6631 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 7077 if (inv.Value.Name == name)
6632 { 7078 {
6633 if (inv.Value.Name == name) 7079 // make sure the object is a script
7080 if (10 == inv.Value.Type)
6634 { 7081 {
6635 // make sure the object is a script 7082 found = true;
6636 if (10 == inv.Value.Type) 7083 srcId = inv.Key;
6637 { 7084 scriptItem = inv.Value;
6638 found = true; 7085 break;
6639 srcId = inv.Key;
6640 break;
6641 }
6642 } 7086 }
6643 } 7087 }
6644 } 7088 }
7089 m_host.TaskInventory.LockItemsForRead(false);
6645 7090
6646 if (!found) 7091 if (!found)
6647 { 7092 {
@@ -6649,9 +7094,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6649 return; 7094 return;
6650 } 7095 }
6651 7096
6652 // the rest of the permission checks are done in RezScript, so check the pin there as well 7097 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6653 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7098 if (dest != null)
7099 {
7100 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7101 {
7102 // the rest of the permission checks are done in RezScript, so check the pin there as well
7103 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6654 7104
7105 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7106 m_host.Inventory.RemoveInventoryItem(srcId);
7107 }
7108 }
6655 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7109 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6656 ScriptSleep(3000); 7110 ScriptSleep(3000);
6657 } 7111 }
@@ -6714,19 +7168,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6714 public LSL_String llMD5String(string src, int nonce) 7168 public LSL_String llMD5String(string src, int nonce)
6715 { 7169 {
6716 m_host.AddScriptLPS(1); 7170 m_host.AddScriptLPS(1);
6717 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7171 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6718 } 7172 }
6719 7173
6720 public LSL_String llSHA1String(string src) 7174 public LSL_String llSHA1String(string src)
6721 { 7175 {
6722 m_host.AddScriptLPS(1); 7176 m_host.AddScriptLPS(1);
6723 return Util.SHA1Hash(src).ToLower(); 7177 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6724 } 7178 }
6725 7179
6726 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7180 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6727 { 7181 {
6728 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7182 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6729 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7183 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7184 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7185 return shapeBlock;
6730 7186
6731 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7187 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6732 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7188 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6831,6 +7287,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6831 // Prim type box, cylinder and prism. 7287 // Prim type box, cylinder and prism.
6832 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) 7288 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)
6833 { 7289 {
7290 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7291 return;
7292
6834 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7293 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6835 ObjectShapePacket.ObjectDataBlock shapeBlock; 7294 ObjectShapePacket.ObjectDataBlock shapeBlock;
6836 7295
@@ -6884,6 +7343,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6884 // Prim type sphere. 7343 // Prim type sphere.
6885 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7344 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6886 { 7345 {
7346 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7347 return;
7348
6887 ObjectShapePacket.ObjectDataBlock shapeBlock; 7349 ObjectShapePacket.ObjectDataBlock shapeBlock;
6888 7350
6889 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7351 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6925,6 +7387,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6925 // Prim type torus, tube and ring. 7387 // Prim type torus, tube and ring.
6926 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) 7388 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)
6927 { 7389 {
7390 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7391 return;
7392
6928 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7393 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6929 ObjectShapePacket.ObjectDataBlock shapeBlock; 7394 ObjectShapePacket.ObjectDataBlock shapeBlock;
6930 7395
@@ -7060,6 +7525,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7060 // Prim type sculpt. 7525 // Prim type sculpt.
7061 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7526 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7062 { 7527 {
7528 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7529 return;
7530
7063 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7531 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7064 UUID sculptId; 7532 UUID sculptId;
7065 7533
@@ -7084,7 +7552,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7084 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7552 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7085 { 7553 {
7086 // default 7554 // default
7087 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7555 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7088 } 7556 }
7089 7557
7090 part.Shape.SetSculptProperties((byte)type, sculptId); 7558 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7100,32 +7568,149 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7100 ScriptSleep(200); 7568 ScriptSleep(200);
7101 } 7569 }
7102 7570
7103 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7571 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7104 { 7572 {
7105 m_host.AddScriptLPS(1); 7573 m_host.AddScriptLPS(1);
7106 7574
7107 setLinkPrimParams(linknumber, rules); 7575 setLinkPrimParams(linknumber, rules);
7576 }
7108 7577
7109 ScriptSleep(200); 7578 private void setLinkPrimParams(int linknumber, LSL_List rules)
7579 {
7580 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7581 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7582 if (parts.Count>0)
7583 {
7584 try
7585 {
7586 parts[0].ParentGroup.areUpdatesSuspended = true;
7587 foreach (SceneObjectPart part in parts)
7588 SetPrimParams(part, rules);
7589 }
7590 finally
7591 {
7592 parts[0].ParentGroup.areUpdatesSuspended = false;
7593 }
7594 }
7595 if (avatars.Count > 0)
7596 {
7597 foreach (ScenePresence avatar in avatars)
7598 SetPrimParams(avatar, rules);
7599 }
7110 } 7600 }
7111 7601
7112 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7602 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7603 float material_density, float material_friction,
7604 float material_restitution, float material_gravity_modifier)
7113 { 7605 {
7114 m_host.AddScriptLPS(1); 7606 ExtraPhysicsData physdata = new ExtraPhysicsData();
7607 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7608 physdata.Density = part.Density;
7609 physdata.Friction = part.Friction;
7610 physdata.Bounce = part.Bounciness;
7611 physdata.GravitationModifier = part.GravityModifier;
7115 7612
7116 setLinkPrimParams(linknumber, rules); 7613 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7614 physdata.Density = material_density;
7615 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7616 physdata.Friction = material_friction;
7617 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7618 physdata.Bounce = material_restitution;
7619 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7620 physdata.GravitationModifier = material_gravity_modifier;
7621
7622 part.UpdateExtraPhysics(physdata);
7117 } 7623 }
7118 7624
7119 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7625 public void llSetPhysicsMaterial(int material_bits,
7626 float material_gravity_modifier, float material_restitution,
7627 float material_friction, float material_density)
7120 { 7628 {
7121 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7629 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7630 }
7122 7631
7123 foreach (SceneObjectPart part in parts) 7632 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7124 SetPrimParams(part, rules); 7633 {
7634 llSetLinkPrimitiveParamsFast(linknumber, rules);
7635 ScriptSleep(200);
7636 }
7637
7638 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7639 {
7640 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7641 //We only support PRIM_POSITION and PRIM_ROTATION
7642
7643 int idx = 0;
7644
7645 while (idx < rules.Length)
7646 {
7647 int code = rules.GetLSLIntegerItem(idx++);
7648
7649 int remain = rules.Length - idx;
7650
7651 switch (code)
7652 {
7653 case (int)ScriptBaseClass.PRIM_POSITION:
7654 {
7655 if (remain < 1)
7656 return;
7657 LSL_Vector v;
7658 v = rules.GetVector3Item(idx++);
7659
7660 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7661 if (part == null)
7662 break;
7663
7664 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7665 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7666 if (llGetLinkNumber() > 1)
7667 {
7668 localRot = llGetLocalRot();
7669 localPos = llGetLocalPos();
7670 }
7671
7672 v -= localPos;
7673 v /= localRot;
7674
7675 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
7676
7677 v = v + 2 * sitOffset;
7678
7679 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7680 av.SendAvatarDataToAllAgents();
7681
7682 }
7683 break;
7684
7685 case (int)ScriptBaseClass.PRIM_ROTATION:
7686 {
7687 if (remain < 1)
7688 return;
7689
7690 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7691 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7692 if (llGetLinkNumber() > 1)
7693 {
7694 localRot = llGetLocalRot();
7695 localPos = llGetLocalPos();
7696 }
7697
7698 LSL_Rotation r;
7699 r = rules.GetQuaternionItem(idx++);
7700 r = r * llGetRootRotation() / localRot;
7701 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7702 av.SendAvatarDataToAllAgents();
7703 }
7704 break;
7705 }
7706 }
7125 } 7707 }
7126 7708
7127 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7709 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7128 { 7710 {
7711 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7712 return;
7713
7129 int idx = 0; 7714 int idx = 0;
7130 7715
7131 bool positionChanged = false; 7716 bool positionChanged = false;
@@ -7447,6 +8032,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7447 part.ScriptSetPhysicsStatus(physics); 8032 part.ScriptSetPhysicsStatus(physics);
7448 break; 8033 break;
7449 8034
8035 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
8036 if (remain < 1)
8037 return;
8038
8039 int shape_type = rules.GetLSLIntegerItem(idx++);
8040
8041 ExtraPhysicsData physdata = new ExtraPhysicsData();
8042 physdata.Density = part.Density;
8043 physdata.Bounce = part.Bounciness;
8044 physdata.GravitationModifier = part.GravityModifier;
8045 physdata.PhysShapeType = (PhysShapeType)shape_type;
8046
8047 part.UpdateExtraPhysics(physdata);
8048
8049 break;
8050
8051 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8052 if (remain < 5)
8053 return;
8054
8055 int material_bits = rules.GetLSLIntegerItem(idx++);
8056 float material_density = (float)rules.GetLSLFloatItem(idx++);
8057 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8058 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8059 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8060
8061 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8062
8063 break;
8064
7450 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8065 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7451 if (remain < 1) 8066 if (remain < 1)
7452 return; 8067 return;
@@ -7520,7 +8135,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7520 if (part.ParentGroup.RootPart == part) 8135 if (part.ParentGroup.RootPart == part)
7521 { 8136 {
7522 SceneObjectGroup parent = part.ParentGroup; 8137 SceneObjectGroup parent = part.ParentGroup;
7523 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8138 Util.FireAndForget(delegate(object x) {
8139 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8140 });
7524 } 8141 }
7525 else 8142 else
7526 { 8143 {
@@ -7531,6 +8148,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7531 } 8148 }
7532 } 8149 }
7533 } 8150 }
8151
8152 if (positionChanged)
8153 {
8154 if (part.ParentGroup.RootPart == part)
8155 {
8156 SceneObjectGroup parent = part.ParentGroup;
8157 Util.FireAndForget(delegate(object x) {
8158 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8159 });
8160 }
8161 else
8162 {
8163 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8164 SceneObjectGroup parent = part.ParentGroup;
8165 parent.HasGroupChanged = true;
8166 parent.ScheduleGroupForTerseUpdate();
8167 }
8168 }
7534 } 8169 }
7535 8170
7536 public LSL_String llStringToBase64(string str) 8171 public LSL_String llStringToBase64(string str)
@@ -7691,13 +8326,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7691 public LSL_Integer llGetNumberOfPrims() 8326 public LSL_Integer llGetNumberOfPrims()
7692 { 8327 {
7693 m_host.AddScriptLPS(1); 8328 m_host.AddScriptLPS(1);
7694 int avatarCount = 0; 8329 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7695 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8330
7696 {
7697 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
7698 avatarCount++;
7699 });
7700
7701 return m_host.ParentGroup.PrimCount + avatarCount; 8331 return m_host.ParentGroup.PrimCount + avatarCount;
7702 } 8332 }
7703 8333
@@ -7713,55 +8343,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7713 m_host.AddScriptLPS(1); 8343 m_host.AddScriptLPS(1);
7714 UUID objID = UUID.Zero; 8344 UUID objID = UUID.Zero;
7715 LSL_List result = new LSL_List(); 8345 LSL_List result = new LSL_List();
8346
8347 // If the ID is not valid, return null result
7716 if (!UUID.TryParse(obj, out objID)) 8348 if (!UUID.TryParse(obj, out objID))
7717 { 8349 {
7718 result.Add(new LSL_Vector()); 8350 result.Add(new LSL_Vector());
7719 result.Add(new LSL_Vector()); 8351 result.Add(new LSL_Vector());
7720 return result; 8352 return result;
7721 } 8353 }
8354
8355 // Check if this is an attached prim. If so, replace
8356 // the UUID with the avatar UUID and report it's bounding box
8357 SceneObjectPart part = World.GetSceneObjectPart(objID);
8358 if (part != null && part.ParentGroup.IsAttachment)
8359 objID = part.ParentGroup.AttachedAvatar;
8360
8361 // Find out if this is an avatar ID. If so, return it's box
7722 ScenePresence presence = World.GetScenePresence(objID); 8362 ScenePresence presence = World.GetScenePresence(objID);
7723 if (presence != null) 8363 if (presence != null)
7724 { 8364 {
7725 if (presence.ParentID == 0) // not sat on an object 8365 // As per LSL Wiki, there is no difference between sitting
8366 // and standing avatar since server 1.36
8367 LSL_Vector lower;
8368 LSL_Vector upper;
8369 if (presence.Animator.Animations.DefaultAnimation.AnimID
8370 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7726 { 8371 {
7727 LSL_Vector lower; 8372 // This is for ground sitting avatars
7728 LSL_Vector upper; 8373 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7729 if (presence.Animator.Animations.DefaultAnimation.AnimID 8374 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7730 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8375 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7731 {
7732 // This is for ground sitting avatars
7733 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7734 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7735 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7736 }
7737 else
7738 {
7739 // This is for standing/flying avatars
7740 float height = presence.Appearance.AvatarHeight / 2.0f;
7741 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7742 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7743 }
7744 result.Add(lower);
7745 result.Add(upper);
7746 return result;
7747 } 8376 }
7748 else 8377 else
7749 { 8378 {
7750 // sitting on an object so we need the bounding box of that 8379 // This is for standing/flying avatars
7751 // which should include the avatar so set the UUID to the 8380 float height = presence.Appearance.AvatarHeight / 2.0f;
7752 // UUID of the object the avatar is sat on and allow it to fall through 8381 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7753 // to processing an object 8382 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7754 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7755 objID = p.UUID;
7756 } 8383 }
8384
8385 // Adjust to the documented error offsets (see LSL Wiki)
8386 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8387 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8388
8389 if (lower.x > upper.x)
8390 lower.x = upper.x;
8391 if (lower.y > upper.y)
8392 lower.y = upper.y;
8393 if (lower.z > upper.z)
8394 lower.z = upper.z;
8395
8396 result.Add(lower);
8397 result.Add(upper);
8398 return result;
7757 } 8399 }
7758 SceneObjectPart part = World.GetSceneObjectPart(objID); 8400
8401 part = World.GetSceneObjectPart(objID);
7759 // Currently only works for single prims without a sitting avatar 8402 // Currently only works for single prims without a sitting avatar
7760 if (part != null) 8403 if (part != null)
7761 { 8404 {
7762 Vector3 halfSize = part.Scale / 2.0f; 8405 float minX;
7763 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8406 float maxX;
7764 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8407 float minY;
8408 float maxY;
8409 float minZ;
8410 float maxZ;
8411
8412 // This BBox is in sim coordinates, with the offset being
8413 // a contained point.
8414 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8415 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8416
8417 minX -= offsets[0].X;
8418 maxX -= offsets[0].X;
8419 minY -= offsets[0].Y;
8420 maxY -= offsets[0].Y;
8421 minZ -= offsets[0].Z;
8422 maxZ -= offsets[0].Z;
8423
8424 LSL_Vector lower;
8425 LSL_Vector upper;
8426
8427 // Adjust to the documented error offsets (see LSL Wiki)
8428 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8429 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8430
8431 if (lower.x > upper.x)
8432 lower.x = upper.x;
8433 if (lower.y > upper.y)
8434 lower.y = upper.y;
8435 if (lower.z > upper.z)
8436 lower.z = upper.z;
8437
7765 result.Add(lower); 8438 result.Add(lower);
7766 result.Add(upper); 8439 result.Add(upper);
7767 return result; 8440 return result;
@@ -7775,7 +8448,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7775 8448
7776 public LSL_Vector llGetGeometricCenter() 8449 public LSL_Vector llGetGeometricCenter()
7777 { 8450 {
7778 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 8451 Vector3 tmp = m_host.GetGeometricCenter();
8452 return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
7779 } 8453 }
7780 8454
7781 public LSL_List llGetPrimitiveParams(LSL_List rules) 8455 public LSL_List llGetPrimitiveParams(LSL_List rules)
@@ -7841,13 +8515,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7841 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8515 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7842 part.AbsolutePosition.Y, 8516 part.AbsolutePosition.Y,
7843 part.AbsolutePosition.Z); 8517 part.AbsolutePosition.Z);
7844 // For some reason, the part.AbsolutePosition.* values do not change if the
7845 // linkset is rotated; they always reflect the child prim's world position
7846 // as though the linkset is unrotated. This is incompatible behavior with SL's
7847 // implementation, so will break scripts imported from there (not to mention it
7848 // makes it more difficult to determine a child prim's actual inworld position).
7849 if (part.ParentID != 0)
7850 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7851 res.Add(v); 8518 res.Add(v);
7852 break; 8519 break;
7853 8520
@@ -8018,56 +8685,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8018 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8685 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8019 if (remain < 1) 8686 if (remain < 1)
8020 return res; 8687 return res;
8021 8688 face = (int)rules.GetLSLIntegerItem(idx++);
8022 face=(int)rules.GetLSLIntegerItem(idx++);
8023 8689
8024 tex = part.Shape.Textures; 8690 tex = part.Shape.Textures;
8691 int shiny;
8025 if (face == ScriptBaseClass.ALL_SIDES) 8692 if (face == ScriptBaseClass.ALL_SIDES)
8026 { 8693 {
8027 for (face = 0; face < GetNumberOfSides(part); face++) 8694 for (face = 0; face < GetNumberOfSides(part); face++)
8028 { 8695 {
8029 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8696 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8030 // Convert Shininess to PRIM_SHINY_* 8697 if (shinyness == Shininess.High)
8031 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8698 {
8032 // PRIM_BUMP_* 8699 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8033 res.Add(new LSL_Integer((int)texface.Bump)); 8700 }
8701 else if (shinyness == Shininess.Medium)
8702 {
8703 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8704 }
8705 else if (shinyness == Shininess.Low)
8706 {
8707 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8708 }
8709 else
8710 {
8711 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8712 }
8713 res.Add(new LSL_Integer(shiny));
8714 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8034 } 8715 }
8035 } 8716 }
8036 else 8717 else
8037 { 8718 {
8038 if (face >= 0 && face < GetNumberOfSides(part)) 8719 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8720 if (shinyness == Shininess.High)
8039 { 8721 {
8040 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8722 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8041 // Convert Shininess to PRIM_SHINY_* 8723 }
8042 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8724 else if (shinyness == Shininess.Medium)
8043 // PRIM_BUMP_* 8725 {
8044 res.Add(new LSL_Integer((int)texface.Bump)); 8726 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8727 }
8728 else if (shinyness == Shininess.Low)
8729 {
8730 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8731 }
8732 else
8733 {
8734 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8045 } 8735 }
8736 res.Add(new LSL_Integer(shiny));
8737 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8046 } 8738 }
8047 break; 8739 break;
8048 8740
8049 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8741 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8050 if (remain < 1) 8742 if (remain < 1)
8051 return res; 8743 return res;
8052 8744 face = (int)rules.GetLSLIntegerItem(idx++);
8053 face=(int)rules.GetLSLIntegerItem(idx++);
8054 8745
8055 tex = part.Shape.Textures; 8746 tex = part.Shape.Textures;
8747 int fullbright;
8056 if (face == ScriptBaseClass.ALL_SIDES) 8748 if (face == ScriptBaseClass.ALL_SIDES)
8057 { 8749 {
8058 for (face = 0; face < GetNumberOfSides(part); face++) 8750 for (face = 0; face < GetNumberOfSides(part); face++)
8059 { 8751 {
8060 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8752 if (tex.GetFace((uint)face).Fullbright == true)
8061 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8753 {
8754 fullbright = ScriptBaseClass.TRUE;
8755 }
8756 else
8757 {
8758 fullbright = ScriptBaseClass.FALSE;
8759 }
8760 res.Add(new LSL_Integer(fullbright));
8062 } 8761 }
8063 } 8762 }
8064 else 8763 else
8065 { 8764 {
8066 if (face >= 0 && face < GetNumberOfSides(part)) 8765 if (tex.GetFace((uint)face).Fullbright == true)
8067 { 8766 {
8068 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8767 fullbright = ScriptBaseClass.TRUE;
8069 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8768 }
8769 else
8770 {
8771 fullbright = ScriptBaseClass.FALSE;
8070 } 8772 }
8773 res.Add(new LSL_Integer(fullbright));
8071 } 8774 }
8072 break; 8775 break;
8073 8776
@@ -8089,27 +8792,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8089 break; 8792 break;
8090 8793
8091 case (int)ScriptBaseClass.PRIM_TEXGEN: 8794 case (int)ScriptBaseClass.PRIM_TEXGEN:
8795 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8092 if (remain < 1) 8796 if (remain < 1)
8093 return res; 8797 return res;
8094 8798 face = (int)rules.GetLSLIntegerItem(idx++);
8095 face=(int)rules.GetLSLIntegerItem(idx++);
8096 8799
8097 tex = part.Shape.Textures; 8800 tex = part.Shape.Textures;
8098 if (face == ScriptBaseClass.ALL_SIDES) 8801 if (face == ScriptBaseClass.ALL_SIDES)
8099 { 8802 {
8100 for (face = 0; face < GetNumberOfSides(part); face++) 8803 for (face = 0; face < GetNumberOfSides(part); face++)
8101 { 8804 {
8102 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8805 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8103 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8806 {
8104 res.Add(new LSL_Integer((uint)texgen >> 1)); 8807 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8808 }
8809 else
8810 {
8811 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8812 }
8105 } 8813 }
8106 } 8814 }
8107 else 8815 else
8108 { 8816 {
8109 if (face >= 0 && face < GetNumberOfSides(part)) 8817 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8110 { 8818 {
8111 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8819 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8112 res.Add(new LSL_Integer((uint)texgen >> 1)); 8820 }
8821 else
8822 {
8823 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8113 } 8824 }
8114 } 8825 }
8115 break; 8826 break;
@@ -8132,28 +8843,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8132 case (int)ScriptBaseClass.PRIM_GLOW: 8843 case (int)ScriptBaseClass.PRIM_GLOW:
8133 if (remain < 1) 8844 if (remain < 1)
8134 return res; 8845 return res;
8135 8846 face = (int)rules.GetLSLIntegerItem(idx++);
8136 face=(int)rules.GetLSLIntegerItem(idx++);
8137 8847
8138 tex = part.Shape.Textures; 8848 tex = part.Shape.Textures;
8849 float primglow;
8139 if (face == ScriptBaseClass.ALL_SIDES) 8850 if (face == ScriptBaseClass.ALL_SIDES)
8140 { 8851 {
8141 for (face = 0; face < GetNumberOfSides(part); face++) 8852 for (face = 0; face < GetNumberOfSides(part); face++)
8142 { 8853 {
8143 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8854 primglow = tex.GetFace((uint)face).Glow;
8144 res.Add(new LSL_Float(texface.Glow)); 8855 res.Add(new LSL_Float(primglow));
8145 } 8856 }
8146 } 8857 }
8147 else 8858 else
8148 { 8859 {
8149 if (face >= 0 && face < GetNumberOfSides(part)) 8860 primglow = tex.GetFace((uint)face).Glow;
8150 { 8861 res.Add(new LSL_Float(primglow));
8151 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8152 res.Add(new LSL_Float(texface.Glow));
8153 }
8154 } 8862 }
8155 break; 8863 break;
8156
8157 case (int)ScriptBaseClass.PRIM_TEXT: 8864 case (int)ScriptBaseClass.PRIM_TEXT:
8158 Color4 textColor = part.GetTextColor(); 8865 Color4 textColor = part.GetTextColor();
8159 res.Add(new LSL_String(part.Text)); 8866 res.Add(new LSL_String(part.Text));
@@ -8765,8 +9472,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8765 // The function returns an ordered list 9472 // The function returns an ordered list
8766 // representing the tokens found in the supplied 9473 // representing the tokens found in the supplied
8767 // sources string. If two successive tokenizers 9474 // sources string. If two successive tokenizers
8768 // are encountered, then a NULL entry is added 9475 // are encountered, then a null-string entry is
8769 // to the list. 9476 // added to the list.
8770 // 9477 //
8771 // It is a precondition that the source and 9478 // It is a precondition that the source and
8772 // toekizer lisst are non-null. If they are null, 9479 // toekizer lisst are non-null. If they are null,
@@ -8774,7 +9481,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8774 // while their lengths are being determined. 9481 // while their lengths are being determined.
8775 // 9482 //
8776 // A small amount of working memoryis required 9483 // A small amount of working memoryis required
8777 // of approximately 8*#tokenizers. 9484 // of approximately 8*#tokenizers + 8*srcstrlen.
8778 // 9485 //
8779 // There are many ways in which this function 9486 // There are many ways in which this function
8780 // can be implemented, this implementation is 9487 // can be implemented, this implementation is
@@ -8790,155 +9497,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8790 // and eliminates redundant tokenizers as soon 9497 // and eliminates redundant tokenizers as soon
8791 // as is possible. 9498 // as is possible.
8792 // 9499 //
8793 // The implementation tries to avoid any copying 9500 // The implementation tries to minimize temporary
8794 // of arrays or other objects. 9501 // garbage generation.
8795 // </remarks> 9502 // </remarks>
8796 9503
8797 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9504 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8798 { 9505 {
8799 int beginning = 0; 9506 return ParseString2List(src, separators, spacers, true);
8800 int srclen = src.Length; 9507 }
8801 int seplen = separators.Length;
8802 object[] separray = separators.Data;
8803 int spclen = spacers.Length;
8804 object[] spcarray = spacers.Data;
8805 int mlen = seplen+spclen;
8806
8807 int[] offset = new int[mlen+1];
8808 bool[] active = new bool[mlen];
8809
8810 int best;
8811 int j;
8812
8813 // Initial capacity reduces resize cost
8814 9508
8815 LSL_List tokens = new LSL_List(); 9509 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9510 {
9511 int srclen = src.Length;
9512 int seplen = separators.Length;
9513 object[] separray = separators.Data;
9514 int spclen = spacers.Length;
9515 object[] spcarray = spacers.Data;
9516 int dellen = 0;
9517 string[] delarray = new string[seplen+spclen];
8816 9518
8817 // All entries are initially valid 9519 int outlen = 0;
9520 string[] outarray = new string[srclen*2+1];
8818 9521
8819 for (int i = 0; i < mlen; i++) 9522 int i, j;
8820 active[i] = true; 9523 string d;
8821 9524
8822 offset[mlen] = srclen; 9525 m_host.AddScriptLPS(1);
8823 9526
8824 while (beginning < srclen) 9527 /*
9528 * Convert separator and spacer lists to C# strings.
9529 * Also filter out null strings so we don't hang.
9530 */
9531 for (i = 0; i < seplen; i ++)
8825 { 9532 {
9533 d = separray[i].ToString();
9534 if (d.Length > 0)
9535 {
9536 delarray[dellen++] = d;
9537 }
9538 }
9539 seplen = dellen;
8826 9540
8827 best = mlen; // as bad as it gets 9541 for (i = 0; i < spclen; i ++)
9542 {
9543 d = spcarray[i].ToString();
9544 if (d.Length > 0)
9545 {
9546 delarray[dellen++] = d;
9547 }
9548 }
8828 9549
8829 // Scan for separators 9550 /*
9551 * Scan through source string from beginning to end.
9552 */
9553 for (i = 0;;)
9554 {
8830 9555
8831 for (j = 0; j < seplen; j++) 9556 /*
9557 * Find earliest delimeter in src starting at i (if any).
9558 */
9559 int earliestDel = -1;
9560 int earliestSrc = srclen;
9561 string earliestStr = null;
9562 for (j = 0; j < dellen; j ++)
8832 { 9563 {
8833 if (separray[j].ToString() == String.Empty) 9564 d = delarray[j];
8834 active[j] = false; 9565 if (d != null)
8835
8836 if (active[j])
8837 { 9566 {
8838 // scan all of the markers 9567 int index = src.IndexOf(d, i);
8839 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9568 if (index < 0)
8840 { 9569 {
8841 // not present at all 9570 delarray[j] = null; // delim nowhere in src, don't check it anymore
8842 active[j] = false;
8843 } 9571 }
8844 else 9572 else if (index < earliestSrc)
8845 { 9573 {
8846 // present and correct 9574 earliestSrc = index; // where delimeter starts in source string
8847 if (offset[j] < offset[best]) 9575 earliestDel = j; // where delimeter is in delarray[]
8848 { 9576 earliestStr = d; // the delimeter string from delarray[]
8849 // closest so far 9577 if (index == i) break; // can't do any better than found at beg of string
8850 best = j;
8851 if (offset[best] == beginning)
8852 break;
8853 }
8854 } 9578 }
8855 } 9579 }
8856 } 9580 }
8857 9581
8858 // Scan for spacers 9582 /*
8859 9583 * Output source string starting at i through start of earliest delimeter.
8860 if (offset[best] != beginning) 9584 */
9585 if (keepNulls || (earliestSrc > i))
8861 { 9586 {
8862 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9587 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8863 {
8864 if (spcarray[j-seplen].ToString() == String.Empty)
8865 active[j] = false;
8866
8867 if (active[j])
8868 {
8869 // scan all of the markers
8870 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8871 {
8872 // not present at all
8873 active[j] = false;
8874 }
8875 else
8876 {
8877 // present and correct
8878 if (offset[j] < offset[best])
8879 {
8880 // closest so far
8881 best = j;
8882 }
8883 }
8884 }
8885 }
8886 } 9588 }
8887 9589
8888 // This is the normal exit from the scanning loop 9590 /*
9591 * If no delimeter found at or after i, we're done scanning.
9592 */
9593 if (earliestDel < 0) break;
8889 9594
8890 if (best == mlen) 9595 /*
9596 * If delimeter was a spacer, output the spacer.
9597 */
9598 if (earliestDel >= seplen)
8891 { 9599 {
8892 // no markers were found on this pass 9600 outarray[outlen++] = earliestStr;
8893 // so we're pretty much done
8894 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8895 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8896 break;
8897 } 9601 }
8898 9602
8899 // Otherwise we just add the newly delimited token 9603 /*
8900 // and recalculate where the search should continue. 9604 * Look at rest of src string following delimeter.
8901 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9605 */
8902 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9606 i = earliestSrc + earliestStr.Length;
8903
8904 if (best < seplen)
8905 {
8906 beginning = offset[best] + (separray[best].ToString()).Length;
8907 }
8908 else
8909 {
8910 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8911 string str = spcarray[best - seplen].ToString();
8912 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8913 tokens.Add(new LSL_String(str));
8914 }
8915 } 9607 }
8916 9608
8917 // This an awkward an not very intuitive boundary case. If the 9609 /*
8918 // last substring is a tokenizer, then there is an implied trailing 9610 * Make up an exact-sized output array suitable for an LSL_List object.
8919 // null list entry. Hopefully the single comparison will not be too 9611 */
8920 // arduous. Alternatively the 'break' could be replced with a return 9612 object[] outlist = new object[outlen];
8921 // but that's shabby programming. 9613 for (i = 0; i < outlen; i ++)
8922
8923 if ((beginning == srclen) && (keepNulls))
8924 { 9614 {
8925 if (srclen != 0) 9615 outlist[i] = new LSL_String(outarray[i]);
8926 tokens.Add(new LSL_String(""));
8927 } 9616 }
8928 9617 return new LSL_List(outlist);
8929 return tokens;
8930 }
8931
8932 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8933 {
8934 m_host.AddScriptLPS(1);
8935 return this.ParseString(src, separators, spacers, false);
8936 }
8937
8938 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8939 {
8940 m_host.AddScriptLPS(1);
8941 return this.ParseString(src, separators, spacers, true);
8942 } 9618 }
8943 9619
8944 public LSL_Integer llGetObjectPermMask(int mask) 9620 public LSL_Integer llGetObjectPermMask(int mask)
@@ -9015,28 +9691,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9015 { 9691 {
9016 m_host.AddScriptLPS(1); 9692 m_host.AddScriptLPS(1);
9017 9693
9018 lock (m_host.TaskInventory) 9694 m_host.TaskInventory.LockItemsForRead(true);
9695 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9019 { 9696 {
9020 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9697 if (inv.Value.Name == item)
9021 { 9698 {
9022 if (inv.Value.Name == item) 9699 m_host.TaskInventory.LockItemsForRead(false);
9700 switch (mask)
9023 { 9701 {
9024 switch (mask) 9702 case 0:
9025 { 9703 return (int)inv.Value.BasePermissions;
9026 case 0: 9704 case 1:
9027 return (int)inv.Value.BasePermissions; 9705 return (int)inv.Value.CurrentPermissions;
9028 case 1: 9706 case 2:
9029 return (int)inv.Value.CurrentPermissions; 9707 return (int)inv.Value.GroupPermissions;
9030 case 2: 9708 case 3:
9031 return (int)inv.Value.GroupPermissions; 9709 return (int)inv.Value.EveryonePermissions;
9032 case 3: 9710 case 4:
9033 return (int)inv.Value.EveryonePermissions; 9711 return (int)inv.Value.NextPermissions;
9034 case 4:
9035 return (int)inv.Value.NextPermissions;
9036 }
9037 } 9712 }
9038 } 9713 }
9039 } 9714 }
9715 m_host.TaskInventory.LockItemsForRead(false);
9040 9716
9041 return -1; 9717 return -1;
9042 } 9718 }
@@ -9083,16 +9759,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9083 { 9759 {
9084 m_host.AddScriptLPS(1); 9760 m_host.AddScriptLPS(1);
9085 9761
9086 lock (m_host.TaskInventory) 9762 m_host.TaskInventory.LockItemsForRead(true);
9763 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9087 { 9764 {
9088 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9765 if (inv.Value.Name == item)
9089 { 9766 {
9090 if (inv.Value.Name == item) 9767 m_host.TaskInventory.LockItemsForRead(false);
9091 { 9768 return inv.Value.CreatorID.ToString();
9092 return inv.Value.CreatorID.ToString();
9093 }
9094 } 9769 }
9095 } 9770 }
9771 m_host.TaskInventory.LockItemsForRead(false);
9096 9772
9097 llSay(0, "No item name '" + item + "'"); 9773 llSay(0, "No item name '" + item + "'");
9098 9774
@@ -9218,9 +9894,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9218 { 9894 {
9219 try 9895 try
9220 { 9896 {
9897 /*
9221 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 9898 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
9222 if (obj != null) 9899 if (obj != null)
9223 return (double)obj.GetMass(); 9900 return (double)obj.GetMass();
9901 */
9902 // return total object mass
9903 SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
9904 if (obj != null)
9905 return obj.GetMass();
9906
9224 // the object is null so the key is for an avatar 9907 // the object is null so the key is for an avatar
9225 ScenePresence avatar = World.GetScenePresence(key); 9908 ScenePresence avatar = World.GetScenePresence(key);
9226 if (avatar != null) 9909 if (avatar != null)
@@ -9240,7 +9923,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9240 } 9923 }
9241 9924
9242 /// <summary> 9925 /// <summary>
9243 /// illListReplaceList removes the sub-list defined by the inclusive indices 9926 /// llListReplaceList removes the sub-list defined by the inclusive indices
9244 /// start and end and inserts the src list in its place. The inclusive 9927 /// start and end and inserts the src list in its place. The inclusive
9245 /// nature of the indices means that at least one element must be deleted 9928 /// nature of the indices means that at least one element must be deleted
9246 /// if the indices are within the bounds of the existing list. I.e. 2,2 9929 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9297,16 +9980,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9297 // based upon end. Note that if end exceeds the upper 9980 // based upon end. Note that if end exceeds the upper
9298 // bound in this case, the entire destination list 9981 // bound in this case, the entire destination list
9299 // is removed. 9982 // is removed.
9300 else 9983 else if (start == 0)
9301 { 9984 {
9302 if (end + 1 < dest.Length) 9985 if (end + 1 < dest.Length)
9303 {
9304 return src + dest.GetSublist(end + 1, -1); 9986 return src + dest.GetSublist(end + 1, -1);
9305 }
9306 else 9987 else
9307 {
9308 return src; 9988 return src;
9309 } 9989 }
9990 else // Start < 0
9991 {
9992 if (end + 1 < dest.Length)
9993 return dest.GetSublist(end + 1, -1);
9994 else
9995 return new LSL_List();
9310 } 9996 }
9311 } 9997 }
9312 // Finally, if start > end, we strip away a prefix and 9998 // Finally, if start > end, we strip away a prefix and
@@ -9357,17 +10043,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9357 int width = 0; 10043 int width = 0;
9358 int height = 0; 10044 int height = 0;
9359 10045
9360 ParcelMediaCommandEnum? commandToSend = null; 10046 uint commandToSend = 0;
9361 float time = 0.0f; // default is from start 10047 float time = 0.0f; // default is from start
9362 10048
9363 ScenePresence presence = null; 10049 ScenePresence presence = null;
9364 10050
9365 for (int i = 0; i < commandList.Data.Length; i++) 10051 for (int i = 0; i < commandList.Data.Length; i++)
9366 { 10052 {
9367 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10053 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9368 switch (command) 10054 switch (command)
9369 { 10055 {
9370 case ParcelMediaCommandEnum.Agent: 10056 case (uint)ParcelMediaCommandEnum.Agent:
9371 // we send only to one agent 10057 // we send only to one agent
9372 if ((i + 1) < commandList.Length) 10058 if ((i + 1) < commandList.Length)
9373 { 10059 {
@@ -9384,25 +10070,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9384 } 10070 }
9385 break; 10071 break;
9386 10072
9387 case ParcelMediaCommandEnum.Loop: 10073 case (uint)ParcelMediaCommandEnum.Loop:
9388 loop = 1; 10074 loop = 1;
9389 commandToSend = command; 10075 commandToSend = command;
9390 update = true; //need to send the media update packet to set looping 10076 update = true; //need to send the media update packet to set looping
9391 break; 10077 break;
9392 10078
9393 case ParcelMediaCommandEnum.Play: 10079 case (uint)ParcelMediaCommandEnum.Play:
9394 loop = 0; 10080 loop = 0;
9395 commandToSend = command; 10081 commandToSend = command;
9396 update = true; //need to send the media update packet to make sure it doesn't loop 10082 update = true; //need to send the media update packet to make sure it doesn't loop
9397 break; 10083 break;
9398 10084
9399 case ParcelMediaCommandEnum.Pause: 10085 case (uint)ParcelMediaCommandEnum.Pause:
9400 case ParcelMediaCommandEnum.Stop: 10086 case (uint)ParcelMediaCommandEnum.Stop:
9401 case ParcelMediaCommandEnum.Unload: 10087 case (uint)ParcelMediaCommandEnum.Unload:
9402 commandToSend = command; 10088 commandToSend = command;
9403 break; 10089 break;
9404 10090
9405 case ParcelMediaCommandEnum.Url: 10091 case (uint)ParcelMediaCommandEnum.Url:
9406 if ((i + 1) < commandList.Length) 10092 if ((i + 1) < commandList.Length)
9407 { 10093 {
9408 if (commandList.Data[i + 1] is LSL_String) 10094 if (commandList.Data[i + 1] is LSL_String)
@@ -9415,7 +10101,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9415 } 10101 }
9416 break; 10102 break;
9417 10103
9418 case ParcelMediaCommandEnum.Texture: 10104 case (uint)ParcelMediaCommandEnum.Texture:
9419 if ((i + 1) < commandList.Length) 10105 if ((i + 1) < commandList.Length)
9420 { 10106 {
9421 if (commandList.Data[i + 1] is LSL_String) 10107 if (commandList.Data[i + 1] is LSL_String)
@@ -9428,7 +10114,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9428 } 10114 }
9429 break; 10115 break;
9430 10116
9431 case ParcelMediaCommandEnum.Time: 10117 case (uint)ParcelMediaCommandEnum.Time:
9432 if ((i + 1) < commandList.Length) 10118 if ((i + 1) < commandList.Length)
9433 { 10119 {
9434 if (commandList.Data[i + 1] is LSL_Float) 10120 if (commandList.Data[i + 1] is LSL_Float)
@@ -9440,7 +10126,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9440 } 10126 }
9441 break; 10127 break;
9442 10128
9443 case ParcelMediaCommandEnum.AutoAlign: 10129 case (uint)ParcelMediaCommandEnum.AutoAlign:
9444 if ((i + 1) < commandList.Length) 10130 if ((i + 1) < commandList.Length)
9445 { 10131 {
9446 if (commandList.Data[i + 1] is LSL_Integer) 10132 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9454,7 +10140,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9454 } 10140 }
9455 break; 10141 break;
9456 10142
9457 case ParcelMediaCommandEnum.Type: 10143 case (uint)ParcelMediaCommandEnum.Type:
9458 if ((i + 1) < commandList.Length) 10144 if ((i + 1) < commandList.Length)
9459 { 10145 {
9460 if (commandList.Data[i + 1] is LSL_String) 10146 if (commandList.Data[i + 1] is LSL_String)
@@ -9467,7 +10153,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9467 } 10153 }
9468 break; 10154 break;
9469 10155
9470 case ParcelMediaCommandEnum.Desc: 10156 case (uint)ParcelMediaCommandEnum.Desc:
9471 if ((i + 1) < commandList.Length) 10157 if ((i + 1) < commandList.Length)
9472 { 10158 {
9473 if (commandList.Data[i + 1] is LSL_String) 10159 if (commandList.Data[i + 1] is LSL_String)
@@ -9480,7 +10166,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9480 } 10166 }
9481 break; 10167 break;
9482 10168
9483 case ParcelMediaCommandEnum.Size: 10169 case (uint)ParcelMediaCommandEnum.Size:
9484 if ((i + 2) < commandList.Length) 10170 if ((i + 2) < commandList.Length)
9485 { 10171 {
9486 if (commandList.Data[i + 1] is LSL_Integer) 10172 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9550,7 +10236,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9550 } 10236 }
9551 } 10237 }
9552 10238
9553 if (commandToSend != null) 10239 if (commandToSend != 0)
9554 { 10240 {
9555 // the commandList contained a start/stop/... command, too 10241 // the commandList contained a start/stop/... command, too
9556 if (presence == null) 10242 if (presence == null)
@@ -9587,7 +10273,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9587 10273
9588 if (aList.Data[i] != null) 10274 if (aList.Data[i] != null)
9589 { 10275 {
9590 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10276 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9591 { 10277 {
9592 case ParcelMediaCommandEnum.Url: 10278 case ParcelMediaCommandEnum.Url:
9593 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10279 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9630,16 +10316,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9630 { 10316 {
9631 m_host.AddScriptLPS(1); 10317 m_host.AddScriptLPS(1);
9632 10318
9633 lock (m_host.TaskInventory) 10319 m_host.TaskInventory.LockItemsForRead(true);
10320 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9634 { 10321 {
9635 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10322 if (inv.Value.Name == name)
9636 { 10323 {
9637 if (inv.Value.Name == name) 10324 m_host.TaskInventory.LockItemsForRead(false);
9638 { 10325 return inv.Value.Type;
9639 return inv.Value.Type;
9640 }
9641 } 10326 }
9642 } 10327 }
10328 m_host.TaskInventory.LockItemsForRead(false);
9643 10329
9644 return -1; 10330 return -1;
9645 } 10331 }
@@ -9650,15 +10336,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9650 10336
9651 if (quick_pay_buttons.Data.Length < 4) 10337 if (quick_pay_buttons.Data.Length < 4)
9652 { 10338 {
9653 LSLError("List must have at least 4 elements"); 10339 int x;
9654 return; 10340 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10341 {
10342 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10343 }
9655 } 10344 }
9656 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10345 int[] nPrice = new int[5];
9657 10346 nPrice[0] = price;
9658 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10347 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9659 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10348 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9660 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10349 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9661 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10350 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10351 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9662 m_host.ParentGroup.HasGroupChanged = true; 10352 m_host.ParentGroup.HasGroupChanged = true;
9663 } 10353 }
9664 10354
@@ -9674,8 +10364,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9674 ShoutError("No permissions to track the camera"); 10364 ShoutError("No permissions to track the camera");
9675 return new LSL_Vector(); 10365 return new LSL_Vector();
9676 } 10366 }
10367 m_host.TaskInventory.LockItemsForRead(false);
9677 10368
9678 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10369// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10370 ScenePresence presence = World.GetScenePresence(agentID);
9679 if (presence != null) 10371 if (presence != null)
9680 { 10372 {
9681 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); 10373 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
@@ -9696,8 +10388,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9696 ShoutError("No permissions to track the camera"); 10388 ShoutError("No permissions to track the camera");
9697 return new LSL_Rotation(); 10389 return new LSL_Rotation();
9698 } 10390 }
10391 m_host.TaskInventory.LockItemsForRead(false);
9699 10392
9700 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10393// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10394 ScenePresence presence = World.GetScenePresence(agentID);
9701 if (presence != null) 10395 if (presence != null)
9702 { 10396 {
9703 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); 10397 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W);
@@ -9757,8 +10451,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9757 { 10451 {
9758 m_host.AddScriptLPS(1); 10452 m_host.AddScriptLPS(1);
9759 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 10453 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
9760 if (detectedParams == null) return; // only works on the first detected avatar 10454 if (detectedParams == null)
9761 10455 {
10456 if (m_host.ParentGroup.IsAttachment == true)
10457 {
10458 detectedParams = new DetectParams();
10459 detectedParams.Key = m_host.OwnerID;
10460 }
10461 else
10462 {
10463 return;
10464 }
10465 }
10466
9762 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10467 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9763 if (avatar != null) 10468 if (avatar != null)
9764 { 10469 {
@@ -9766,6 +10471,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9766 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10471 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9767 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10472 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9768 } 10473 }
10474
9769 ScriptSleep(1000); 10475 ScriptSleep(1000);
9770 } 10476 }
9771 10477
@@ -9889,12 +10595,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9889 10595
9890 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10596 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9891 object[] data = rules.Data; 10597 object[] data = rules.Data;
9892 for (int i = 0; i < data.Length; ++i) { 10598 for (int i = 0; i < data.Length; ++i)
10599 {
9893 int type = Convert.ToInt32(data[i++].ToString()); 10600 int type = Convert.ToInt32(data[i++].ToString());
9894 if (i >= data.Length) break; // odd number of entries => ignore the last 10601 if (i >= data.Length) break; // odd number of entries => ignore the last
9895 10602
9896 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10603 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9897 switch (type) { 10604 switch (type)
10605 {
9898 case ScriptBaseClass.CAMERA_FOCUS: 10606 case ScriptBaseClass.CAMERA_FOCUS:
9899 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10607 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9900 case ScriptBaseClass.CAMERA_POSITION: 10608 case ScriptBaseClass.CAMERA_POSITION:
@@ -10000,19 +10708,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10000 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10708 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
10001 { 10709 {
10002 m_host.AddScriptLPS(1); 10710 m_host.AddScriptLPS(1);
10003 string ret = String.Empty; 10711
10004 string src1 = llBase64ToString(str1); 10712 if (str1 == String.Empty)
10005 string src2 = llBase64ToString(str2); 10713 return String.Empty;
10006 int c = 0; 10714 if (str2 == String.Empty)
10007 for (int i = 0; i < src1.Length; i++) 10715 return str1;
10716
10717 int len = str2.Length;
10718 if ((len % 4) != 0) // LL is EVIL!!!!
10008 { 10719 {
10009 ret += (char) (src1[i] ^ src2[c]); 10720 while (str2.EndsWith("="))
10721 str2 = str2.Substring(0, str2.Length - 1);
10010 10722
10011 c++; 10723 len = str2.Length;
10012 if (c >= src2.Length) 10724 int mod = len % 4;
10013 c = 0; 10725
10726 if (mod == 1)
10727 str2 = str2.Substring(0, str2.Length - 1);
10728 else if (mod == 2)
10729 str2 += "==";
10730 else if (mod == 3)
10731 str2 += "=";
10732 }
10733
10734 byte[] data1;
10735 byte[] data2;
10736 try
10737 {
10738 data1 = Convert.FromBase64String(str1);
10739 data2 = Convert.FromBase64String(str2);
10740 }
10741 catch (Exception)
10742 {
10743 return new LSL_String(String.Empty);
10744 }
10745
10746 byte[] d2 = new Byte[data1.Length];
10747 int pos = 0;
10748
10749 if (data1.Length <= data2.Length)
10750 {
10751 Array.Copy(data2, 0, d2, 0, data1.Length);
10014 } 10752 }
10015 return llStringToBase64(ret); 10753 else
10754 {
10755 while (pos < data1.Length)
10756 {
10757 len = data1.Length - pos;
10758 if (len > data2.Length)
10759 len = data2.Length;
10760
10761 Array.Copy(data2, 0, d2, pos, len);
10762 pos += len;
10763 }
10764 }
10765
10766 for (pos = 0 ; pos < data1.Length ; pos++ )
10767 data1[pos] ^= d2[pos];
10768
10769 return Convert.ToBase64String(data1);
10016 } 10770 }
10017 10771
10018 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10772 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10069,12 +10823,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10069 Regex r = new Regex(authregex); 10823 Regex r = new Regex(authregex);
10070 int[] gnums = r.GetGroupNumbers(); 10824 int[] gnums = r.GetGroupNumbers();
10071 Match m = r.Match(url); 10825 Match m = r.Match(url);
10072 if (m.Success) { 10826 if (m.Success)
10073 for (int i = 1; i < gnums.Length; i++) { 10827 {
10828 for (int i = 1; i < gnums.Length; i++)
10829 {
10074 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10830 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10075 //CaptureCollection cc = g.Captures; 10831 //CaptureCollection cc = g.Captures;
10076 } 10832 }
10077 if (m.Groups.Count == 5) { 10833 if (m.Groups.Count == 5)
10834 {
10078 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10835 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10079 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10836 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10080 } 10837 }
@@ -10437,15 +11194,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10437 11194
10438 internal UUID ScriptByName(string name) 11195 internal UUID ScriptByName(string name)
10439 { 11196 {
10440 lock (m_host.TaskInventory) 11197 m_host.TaskInventory.LockItemsForRead(true);
11198
11199 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10441 { 11200 {
10442 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 11201 if (item.Type == 10 && item.Name == name)
10443 { 11202 {
10444 if (item.Type == 10 && item.Name == name) 11203 m_host.TaskInventory.LockItemsForRead(false);
10445 return item.ItemID; 11204 return item.ItemID;
10446 } 11205 }
10447 } 11206 }
10448 11207
11208 m_host.TaskInventory.LockItemsForRead(false);
11209
10449 return UUID.Zero; 11210 return UUID.Zero;
10450 } 11211 }
10451 11212
@@ -10486,6 +11247,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10486 { 11247 {
10487 m_host.AddScriptLPS(1); 11248 m_host.AddScriptLPS(1);
10488 11249
11250 //Clone is thread safe
10489 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11251 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10490 11252
10491 UUID assetID = UUID.Zero; 11253 UUID assetID = UUID.Zero;
@@ -10548,6 +11310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10548 { 11310 {
10549 m_host.AddScriptLPS(1); 11311 m_host.AddScriptLPS(1);
10550 11312
11313 //Clone is thread safe
10551 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11314 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10552 11315
10553 UUID assetID = UUID.Zero; 11316 UUID assetID = UUID.Zero;
@@ -10628,15 +11391,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10628 return GetLinkPrimitiveParams(obj, rules); 11391 return GetLinkPrimitiveParams(obj, rules);
10629 } 11392 }
10630 11393
10631 public void print(string str) 11394 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10632 { 11395 {
10633 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11396 List<SceneObjectPart> parts = GetLinkParts(link);
10634 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11397 if (parts.Count < 1)
10635 if (ossl != null) 11398 return 0;
10636 { 11399
10637 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11400 return GetNumberOfSides(parts[0]);
10638 m_log.Info("LSL print():" + str);
10639 }
10640 } 11401 }
10641 11402
10642 private string Name2Username(string name) 11403 private string Name2Username(string name)
@@ -10682,155 +11443,482 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10682 return rq.ToString(); 11443 return rq.ToString();
10683 } 11444 }
10684 11445
11446 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11447 {
11448 m_SayShoutCount = 0;
11449 }
11450
11451 private struct Tri
11452 {
11453 public Vector3 p1;
11454 public Vector3 p2;
11455 public Vector3 p3;
11456 }
11457
11458 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11459 {
11460 float height = avatar.Appearance.AvatarHeight;
11461 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11462 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11463
11464 if (point.X > b1.X && point.X < b2.X &&
11465 point.Y > b1.Y && point.Y < b2.Y &&
11466 point.Z > b1.Z && point.Z < b2.Z)
11467 return true;
11468 return false;
11469 }
11470
11471 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11472 {
11473 List<ContactResult> contacts = new List<ContactResult>();
11474
11475 Vector3 ab = rayEnd - rayStart;
11476
11477 World.ForEachScenePresence(delegate(ScenePresence sp)
11478 {
11479 Vector3 ac = sp.AbsolutePosition - rayStart;
11480 Vector3 bc = sp.AbsolutePosition - rayEnd;
11481
11482 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11483
11484 if (d > 1.5)
11485 return;
11486
11487 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11488
11489 if (d2 > 0)
11490 return;
11491
11492 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11493 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11494
11495 if (!InBoundingBox(sp, p))
11496 return;
11497
11498 ContactResult result = new ContactResult ();
11499 result.ConsumerID = sp.LocalId;
11500 result.Depth = Vector3.Distance(rayStart, p);
11501 result.Normal = Vector3.Zero;
11502 result.Pos = p;
11503
11504 contacts.Add(result);
11505 });
11506
11507 return contacts.ToArray();
11508 }
11509
11510 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11511 {
11512 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11513 List<ContactResult> contacts = new List<ContactResult>();
11514
11515 Vector3 ab = rayEnd - rayStart;
11516
11517 World.ForEachSOG(delegate(SceneObjectGroup group)
11518 {
11519 if (m_host.ParentGroup == group)
11520 return;
11521
11522 if (group.IsAttachment)
11523 return;
11524
11525 if (group.RootPart.PhysActor == null)
11526 {
11527 if (!includePhantom)
11528 return;
11529 }
11530 else
11531 {
11532 if (group.RootPart.PhysActor.IsPhysical)
11533 {
11534 if (!includePhysical)
11535 return;
11536 }
11537 else
11538 {
11539 if (!includeNonPhysical)
11540 return;
11541 }
11542 }
11543
11544 // Find the radius ouside of which we don't even need to hit test
11545 float minX;
11546 float maxX;
11547 float minY;
11548 float maxY;
11549 float minZ;
11550 float maxZ;
11551
11552 float radius = 0.0f;
11553
11554 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11555
11556 if (Math.Abs(minX) > radius)
11557 radius = Math.Abs(minX);
11558 if (Math.Abs(minY) > radius)
11559 radius = Math.Abs(minY);
11560 if (Math.Abs(minZ) > radius)
11561 radius = Math.Abs(minZ);
11562 if (Math.Abs(maxX) > radius)
11563 radius = Math.Abs(maxX);
11564 if (Math.Abs(maxY) > radius)
11565 radius = Math.Abs(maxY);
11566 if (Math.Abs(maxZ) > radius)
11567 radius = Math.Abs(maxZ);
11568
11569 Vector3 ac = group.AbsolutePosition - rayStart;
11570 Vector3 bc = group.AbsolutePosition - rayEnd;
11571
11572 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11573
11574 // Too far off ray, don't bother
11575 if (d > radius)
11576 return;
11577
11578 // Behind ray, drop
11579 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11580 if (d2 > 0)
11581 return;
11582
11583 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11584 // Miss.
11585 if (!intersection.HitTF)
11586 return;
11587
11588 ContactResult result = new ContactResult ();
11589 result.ConsumerID = group.LocalId;
11590 result.Depth = intersection.distance;
11591 result.Normal = intersection.normal;
11592 result.Pos = intersection.ipoint;
11593
11594 contacts.Add(result);
11595 });
11596
11597 return contacts.ToArray();
11598 }
11599
11600 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11601 {
11602 double[,] heightfield = World.Heightmap.GetDoubles();
11603 List<ContactResult> contacts = new List<ContactResult>();
11604
11605 double min = 2048.0;
11606 double max = 0.0;
11607
11608 // Find the min and max of the heightfield
11609 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11610 {
11611 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11612 {
11613 if (heightfield[x, y] > max)
11614 max = heightfield[x, y];
11615 if (heightfield[x, y] < min)
11616 min = heightfield[x, y];
11617 }
11618 }
11619
11620
11621 // A ray extends past rayEnd, but doesn't go back before
11622 // rayStart. If the start is above the highest point of the ground
11623 // and the ray goes up, we can't hit the ground. Ever.
11624 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11625 return null;
11626
11627 // Same for going down
11628 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11629 return null;
11630
11631 List<Tri> trilist = new List<Tri>();
11632
11633 // Create our triangle list
11634 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11635 {
11636 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11637 {
11638 Tri t1 = new Tri();
11639 Tri t2 = new Tri();
11640
11641 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11642 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11643 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11644 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11645
11646 t1.p1 = p1;
11647 t1.p2 = p2;
11648 t1.p3 = p3;
11649
11650 t2.p1 = p3;
11651 t2.p2 = p4;
11652 t2.p3 = p1;
11653
11654 trilist.Add(t1);
11655 trilist.Add(t2);
11656 }
11657 }
11658
11659 // Ray direction
11660 Vector3 rayDirection = rayEnd - rayStart;
11661
11662 foreach (Tri t in trilist)
11663 {
11664 // Compute triangle plane normal and edges
11665 Vector3 u = t.p2 - t.p1;
11666 Vector3 v = t.p3 - t.p1;
11667 Vector3 n = Vector3.Cross(u, v);
11668
11669 if (n == Vector3.Zero)
11670 continue;
11671
11672 Vector3 w0 = rayStart - t.p1;
11673 double a = -Vector3.Dot(n, w0);
11674 double b = Vector3.Dot(n, rayDirection);
11675
11676 // Not intersecting the plane, or in plane (same thing)
11677 // Ignoring this MAY cause the ground to not be detected
11678 // sometimes
11679 if (Math.Abs(b) < 0.000001)
11680 continue;
11681
11682 double r = a / b;
11683
11684 // ray points away from plane
11685 if (r < 0.0)
11686 continue;
11687
11688 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11689
11690 float uu = Vector3.Dot(u, u);
11691 float uv = Vector3.Dot(u, v);
11692 float vv = Vector3.Dot(v, v);
11693 Vector3 w = ip - t.p1;
11694 float wu = Vector3.Dot(w, u);
11695 float wv = Vector3.Dot(w, v);
11696 float d = uv * uv - uu * vv;
11697
11698 float cs = (uv * wv - vv * wu) / d;
11699 if (cs < 0 || cs > 1.0)
11700 continue;
11701 float ct = (uv * wu - uu * wv) / d;
11702 if (ct < 0 || (cs + ct) > 1.0)
11703 continue;
11704
11705 // Add contact point
11706 ContactResult result = new ContactResult ();
11707 result.ConsumerID = 0;
11708 result.Depth = Vector3.Distance(rayStart, ip);
11709 result.Normal = n;
11710 result.Pos = ip;
11711
11712 contacts.Add(result);
11713 }
11714
11715 if (contacts.Count == 0)
11716 return null;
11717
11718 contacts.Sort(delegate(ContactResult a, ContactResult b)
11719 {
11720 return (int)(a.Depth - b.Depth);
11721 });
11722
11723 return contacts[0];
11724 }
11725/*
11726 // not done:
11727 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
11728 {
11729 ContactResult[] contacts = null;
11730 World.ForEachSOG(delegate(SceneObjectGroup group)
11731 {
11732 if (m_host.ParentGroup == group)
11733 return;
11734
11735 if (group.IsAttachment)
11736 return;
11737
11738 if(group.RootPart.PhysActor != null)
11739 return;
11740
11741 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
11742 });
11743 return contacts;
11744 }
11745*/
11746
10685 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11747 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10686 { 11748 {
11749 LSL_List list = new LSL_List();
11750
10687 m_host.AddScriptLPS(1); 11751 m_host.AddScriptLPS(1);
10688 11752
10689 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11753 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10690 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11754 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10691 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11755 Vector3 dir = rayEnd - rayStart;
10692 11756
10693 int count = 0; 11757 float dist = Vector3.Mag(dir);
10694// int detectPhantom = 0; 11758
11759 int count = 1;
11760 bool detectPhantom = false;
10695 int dataFlags = 0; 11761 int dataFlags = 0;
10696 int rejectTypes = 0; 11762 int rejectTypes = 0;
10697 11763
10698 for (int i = 0; i < options.Length; i += 2) 11764 for (int i = 0; i < options.Length; i += 2)
10699 { 11765 {
10700 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11766 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10701 {
10702 count = options.GetLSLIntegerItem(i + 1); 11767 count = options.GetLSLIntegerItem(i + 1);
10703 } 11768 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10704// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11769 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10705// {
10706// detectPhantom = options.GetLSLIntegerItem(i + 1);
10707// }
10708 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11770 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10709 {
10710 dataFlags = options.GetLSLIntegerItem(i + 1); 11771 dataFlags = options.GetLSLIntegerItem(i + 1);
10711 }
10712 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11772 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10713 {
10714 rejectTypes = options.GetLSLIntegerItem(i + 1); 11773 rejectTypes = options.GetLSLIntegerItem(i + 1);
10715 }
10716 } 11774 }
10717 11775
10718 LSL_List list = new LSL_List(); 11776 if (count > 16)
10719 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11777 count = 16;
10720
10721 double distance = Util.GetDistanceTo(startvector, endvector);
10722
10723 if (distance == 0)
10724 distance = 0.001;
10725 11778
10726 Vector3 posToCheck = startvector; 11779 List<ContactResult> results = new List<ContactResult>();
10727 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10728 11780
10729 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11781 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10730 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11782 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10731 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11783 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10732 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11784 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10733 11785
10734 for (float i = 0; i <= distance; i += 0.1f) 11786
11787 if (World.SuportsRayCastFiltered())
10735 { 11788 {
10736 posToCheck = startvector + (dir * (i / (float)distance)); 11789 if (dist == 0)
11790 return list;
11791
11792 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
11793 if (checkTerrain)
11794 rayfilter |= RayFilterFlags.land;
11795// if (checkAgents)
11796// rayfilter |= RayFilterFlags.agent;
11797 if (checkPhysical)
11798 rayfilter |= RayFilterFlags.physical;
11799 if (checkNonPhysical)
11800 rayfilter |= RayFilterFlags.nonphysical;
11801 if (detectPhantom)
11802 rayfilter |= RayFilterFlags.LSLPhanton;
11803
11804 Vector3 direction = dir * ( 1/dist);
10737 11805
10738 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11806 if(rayfilter == 0)
10739 { 11807 {
10740 ContactResult result = new ContactResult(); 11808 list.Add(new LSL_Integer(0));
10741 result.ConsumerID = 0; 11809 return list;
10742 result.Depth = 0;
10743 result.Normal = Vector3.Zero;
10744 result.Pos = posToCheck;
10745 results.Add(result);
10746 checkTerrain = false;
10747 } 11810 }
10748 11811
10749 if (checkAgents) 11812 // get some more contacts to sort ???
11813 int physcount = 4 * count;
11814 if (physcount > 20)
11815 physcount = 20;
11816
11817 object physresults;
11818 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
11819
11820 if (physresults == null)
10750 { 11821 {
10751 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11822 list.Add(new LSL_Integer(-3)); // timeout error
10752 { 11823 return list;
10753 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X))
10754 {
10755 ContactResult result = new ContactResult ();
10756 result.ConsumerID = sp.LocalId;
10757 result.Depth = 0;
10758 result.Normal = Vector3.Zero;
10759 result.Pos = posToCheck;
10760 results.Add(result);
10761 }
10762 });
10763 } 11824 }
10764 }
10765 11825
10766 int refcount = 0; 11826 results = (List<ContactResult>)physresults;
10767 foreach (ContactResult result in results) 11827
10768 { 11828 // for now physics doesn't detect sitted avatars so do it outside physics
10769 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) 11829 if (checkAgents)
10770 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0) 11830 {
10771 continue; 11831 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11832 foreach (ContactResult r in agentHits)
11833 results.Add(r);
11834 }
10772 11835
10773 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID); 11836 // bug: will not detect phantom unless they are physical
11837 // don't use ObjectIntersection because its also bad
10774 11838
10775 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) 11839 }
10776 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents 11840 else
11841 {
11842 if (checkTerrain)
11843 {
11844 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11845 if (groundContact != null)
11846 results.Add((ContactResult)groundContact);
11847 }
10777 11848
10778 if (entity == null) 11849 if (checkAgents)
10779 { 11850 {
10780 list.Add(UUID.Zero); 11851 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11852 foreach (ContactResult r in agentHits)
11853 results.Add(r);
11854 }
10781 11855
10782 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11856 if (checkPhysical || checkNonPhysical || detectPhantom)
10783 list.Add(0); 11857 {
11858 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
11859 foreach (ContactResult r in objectHits)
11860 results.Add(r);
11861 }
11862 }
10784 11863
10785 list.Add(result.Pos); 11864 results.Sort(delegate(ContactResult a, ContactResult b)
11865 {
11866 return a.Depth.CompareTo(b.Depth);
11867 });
11868
11869 int values = 0;
11870 SceneObjectGroup thisgrp = m_host.ParentGroup;
10786 11871
10787 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11872 foreach (ContactResult result in results)
10788 list.Add(result.Normal); 11873 {
11874 if (result.Depth > dist)
11875 continue;
10789 11876
10790 continue; //Can't find it, so add UUID.Zero 11877 // physics ray can return colisions with host prim
10791 } 11878 if (m_host.LocalId == result.ConsumerID)
11879 continue;
10792 11880
10793 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity && 11881 UUID itemID = UUID.Zero;
10794 ((ISceneChildEntity)intersection.obj).PhysActor == null) 11882 int linkNum = 0;
10795 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
10796 11883
10797 if (entity is SceneObjectPart) 11884 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
11885 // It's a prim!
11886 if (part != null)
10798 { 11887 {
10799 PhysicsActor pa = ((SceneObjectPart)entity).PhysActor; 11888 // dont detect members of same object ???
11889 if (part.ParentGroup == thisgrp)
11890 continue;
10800 11891
10801 if (pa != null && pa.IsPhysical) 11892 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10802 { 11893 itemID = part.ParentGroup.UUID;
10803 if (!checkPhysical)
10804 continue;
10805 }
10806 else 11894 else
10807 { 11895 itemID = part.UUID;
10808 if (!checkNonPhysical)
10809 continue;
10810 }
10811 }
10812 11896
10813 refcount++; 11897 linkNum = part.LinkNum;
10814 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11898 }
10815 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10816 else 11899 else
10817 list.Add(entity.UUID);
10818
10819 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10820 { 11900 {
10821 if (entity is SceneObjectPart) 11901 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10822 list.Add(((SceneObjectPart)entity).LinkNum); 11902 /// It it a boy? a girl?
10823 else 11903 if (sp != null)
10824 list.Add(0); 11904 itemID = sp.UUID;
10825 } 11905 }
10826 11906
10827 list.Add(result.Pos); 11907 list.Add(new LSL_String(itemID.ToString()));
11908 list.Add(new LSL_String(result.Pos.ToString()));
11909
11910 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
11911 list.Add(new LSL_Integer(linkNum));
10828 11912
10829 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11913 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10830 list.Add(result.Normal); 11914 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11915
11916 values++;
11917 if (values >= count)
11918 break;
10831 } 11919 }
10832 11920
10833 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11921 list.Add(new LSL_Integer(values));
10834 11922
10835 return list; 11923 return list;
10836 } 11924 }
@@ -10870,7 +11958,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10870 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 11958 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10871 if (!isAccount) return 0; 11959 if (!isAccount) return 0;
10872 if (estate.HasAccess(id)) return 1; 11960 if (estate.HasAccess(id)) return 1;
10873 if (estate.IsBanned(id)) 11961 if (estate.IsBanned(id, World.GetUserFlags(id)))
10874 estate.RemoveBan(id); 11962 estate.RemoveBan(id);
10875 estate.AddEstateUser(id); 11963 estate.AddEstateUser(id);
10876 break; 11964 break;
@@ -10889,14 +11977,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10889 break; 11977 break;
10890 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 11978 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10891 if (!isAccount) return 0; 11979 if (!isAccount) return 0;
10892 if (estate.IsBanned(id)) return 1; 11980 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10893 EstateBan ban = new EstateBan(); 11981 EstateBan ban = new EstateBan();
10894 ban.EstateID = estate.EstateID; 11982 ban.EstateID = estate.EstateID;
10895 ban.BannedUserID = id; 11983 ban.BannedUserID = id;
10896 estate.AddBan(ban); 11984 estate.AddBan(ban);
10897 break; 11985 break;
10898 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 11986 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10899 if (!isAccount || !estate.IsBanned(id)) return 0; 11987 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10900 estate.RemoveBan(id); 11988 estate.RemoveBan(id);
10901 break; 11989 break;
10902 default: return 0; 11990 default: return 0;
@@ -10925,7 +12013,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10925 return 16384; 12013 return 16384;
10926 } 12014 }
10927 12015
10928 public LSL_Integer llGetUsedMemory() 12016 public virtual LSL_Integer llGetUsedMemory()
10929 { 12017 {
10930 m_host.AddScriptLPS(1); 12018 m_host.AddScriptLPS(1);
10931 // The value returned for LSO scripts in SL 12019 // The value returned for LSO scripts in SL
@@ -10953,7 +12041,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10953 public void llSetSoundQueueing(int queue) 12041 public void llSetSoundQueueing(int queue)
10954 { 12042 {
10955 m_host.AddScriptLPS(1); 12043 m_host.AddScriptLPS(1);
10956 NotImplemented("llSetSoundQueueing");
10957 } 12044 }
10958 12045
10959 public void llCollisionSprite(string impact_sprite) 12046 public void llCollisionSprite(string impact_sprite)
@@ -10965,10 +12052,270 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10965 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12052 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10966 { 12053 {
10967 m_host.AddScriptLPS(1); 12054 m_host.AddScriptLPS(1);
10968 NotImplemented("llGodLikeRezObject"); 12055
12056 if (!World.Permissions.IsGod(m_host.OwnerID))
12057 NotImplemented("llGodLikeRezObject");
12058
12059 AssetBase rezAsset = World.AssetService.Get(inventory);
12060 if (rezAsset == null)
12061 {
12062 llSay(0, "Asset not found");
12063 return;
12064 }
12065
12066 SceneObjectGroup group = null;
12067
12068 try
12069 {
12070 string xmlData = Utils.BytesToString(rezAsset.Data);
12071 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12072 }
12073 catch
12074 {
12075 llSay(0, "Asset not found");
12076 return;
12077 }
12078
12079 if (group == null)
12080 {
12081 llSay(0, "Asset not found");
12082 return;
12083 }
12084
12085 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12086 group.RootPart.AttachOffset = group.AbsolutePosition;
12087
12088 group.ResetIDs();
12089
12090 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12091 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12092 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12093 group.ScheduleGroupForFullUpdate();
12094
12095 // objects rezzed with this method are die_at_edge by default.
12096 group.RootPart.SetDieAtEdge(true);
12097
12098 group.ResumeScripts();
12099
12100 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12101 "object_rez", new Object[] {
12102 new LSL_String(
12103 group.RootPart.UUID.ToString()) },
12104 new DetectParams[0]));
12105 }
12106
12107 public LSL_String llTransferLindenDollars(string destination, int amount)
12108 {
12109 UUID txn = UUID.Random();
12110
12111 Util.FireAndForget(delegate(object x)
12112 {
12113 int replycode = 0;
12114 string replydata = destination + "," + amount.ToString();
12115
12116 try
12117 {
12118 TaskInventoryItem item = m_item;
12119 if (item == null)
12120 {
12121 replydata = "SERVICE_ERROR";
12122 return;
12123 }
12124
12125 m_host.AddScriptLPS(1);
12126
12127 if (item.PermsGranter == UUID.Zero)
12128 {
12129 replydata = "MISSING_PERMISSION_DEBIT";
12130 return;
12131 }
12132
12133 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
12134 {
12135 replydata = "MISSING_PERMISSION_DEBIT";
12136 return;
12137 }
12138
12139 UUID toID = new UUID();
12140
12141 if (!UUID.TryParse(destination, out toID))
12142 {
12143 replydata = "INVALID_AGENT";
12144 return;
12145 }
12146
12147 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
12148
12149 if (money == null)
12150 {
12151 replydata = "TRANSFERS_DISABLED";
12152 return;
12153 }
12154
12155 bool result = money.ObjectGiveMoney(
12156 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
12157
12158 if (result)
12159 {
12160 replycode = 1;
12161 return;
12162 }
12163
12164 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
12165 }
12166 finally
12167 {
12168 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
12169 "transaction_result", new Object[] {
12170 new LSL_String(txn.ToString()),
12171 new LSL_Integer(replycode),
12172 new LSL_String(replydata) },
12173 new DetectParams[0]));
12174 }
12175 });
12176
12177 return txn.ToString();
10969 } 12178 }
10970 12179
10971 #endregion 12180 #endregion
12181
12182 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12183 {
12184 SceneObjectGroup group = m_host.ParentGroup;
12185
12186 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12187 return;
12188 if (group.IsAttachment)
12189 return;
12190
12191 if (frames.Data.Length > 0) // We are getting a new motion
12192 {
12193 if (group.RootPart.KeyframeMotion != null)
12194 group.RootPart.KeyframeMotion.Stop();
12195 group.RootPart.KeyframeMotion = null;
12196
12197 int idx = 0;
12198
12199 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12200 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12201
12202 while (idx < options.Data.Length)
12203 {
12204 int option = (int)options.GetLSLIntegerItem(idx++);
12205 int remain = options.Data.Length - idx;
12206
12207 switch (option)
12208 {
12209 case ScriptBaseClass.KFM_MODE:
12210 if (remain < 1)
12211 break;
12212 int modeval = (int)options.GetLSLIntegerItem(idx++);
12213 switch(modeval)
12214 {
12215 case ScriptBaseClass.KFM_FORWARD:
12216 mode = KeyframeMotion.PlayMode.Forward;
12217 break;
12218 case ScriptBaseClass.KFM_REVERSE:
12219 mode = KeyframeMotion.PlayMode.Reverse;
12220 break;
12221 case ScriptBaseClass.KFM_LOOP:
12222 mode = KeyframeMotion.PlayMode.Loop;
12223 break;
12224 case ScriptBaseClass.KFM_PING_PONG:
12225 mode = KeyframeMotion.PlayMode.PingPong;
12226 break;
12227 }
12228 break;
12229 case ScriptBaseClass.KFM_DATA:
12230 if (remain < 1)
12231 break;
12232 int dataval = (int)options.GetLSLIntegerItem(idx++);
12233 data = (KeyframeMotion.DataFormat)dataval;
12234 break;
12235 }
12236 }
12237
12238 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12239
12240 idx = 0;
12241
12242 int elemLength = 2;
12243 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12244 elemLength = 3;
12245
12246 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12247 while (idx < frames.Data.Length)
12248 {
12249 int remain = frames.Data.Length - idx;
12250
12251 if (remain < elemLength)
12252 break;
12253
12254 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12255 frame.Position = null;
12256 frame.Rotation = null;
12257
12258 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12259 {
12260 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12261 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12262 }
12263 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12264 {
12265 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12266 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12267 }
12268
12269 float tempf = (float)frames.GetLSLFloatItem(idx++);
12270 frame.TimeMS = (int)(tempf * 1000.0f);
12271
12272 keyframes.Add(frame);
12273 }
12274
12275 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12276 group.RootPart.KeyframeMotion.Start();
12277 }
12278 else
12279 {
12280 if (group.RootPart.KeyframeMotion == null)
12281 return;
12282
12283 if (options.Data.Length == 0)
12284 {
12285 group.RootPart.KeyframeMotion.Stop();
12286 return;
12287 }
12288
12289 int code = (int)options.GetLSLIntegerItem(0);
12290
12291 int idx = 0;
12292
12293 while (idx < options.Data.Length)
12294 {
12295 int option = (int)options.GetLSLIntegerItem(idx++);
12296 int remain = options.Data.Length - idx;
12297
12298 switch (option)
12299 {
12300 case ScriptBaseClass.KFM_COMMAND:
12301 int cmd = (int)options.GetLSLIntegerItem(idx++);
12302 switch (cmd)
12303 {
12304 case ScriptBaseClass.KFM_CMD_PLAY:
12305 group.RootPart.KeyframeMotion.Start();
12306 break;
12307 case ScriptBaseClass.KFM_CMD_STOP:
12308 group.RootPart.KeyframeMotion.Stop();
12309 break;
12310 case ScriptBaseClass.KFM_CMD_PAUSE:
12311 group.RootPart.KeyframeMotion.Pause();
12312 break;
12313 }
12314 break;
12315 }
12316 }
12317 }
12318 }
10972 } 12319 }
10973 12320
10974 public class NotecardCache 12321 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 ad1a358..51ace1a 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
@@ -958,18 +966,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
958 if (target != null) 966 if (target != null)
959 { 967 {
960 UUID animID = UUID.Zero; 968 UUID animID = UUID.Zero;
961 lock (m_host.TaskInventory) 969 m_host.TaskInventory.LockItemsForRead(true);
970 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
962 { 971 {
963 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 972 if (inv.Value.Name == animation)
964 { 973 {
965 if (inv.Value.Name == animation) 974 if (inv.Value.Type == (int)AssetType.Animation)
966 { 975 animID = inv.Value.AssetID;
967 if (inv.Value.Type == (int)AssetType.Animation) 976 continue;
968 animID = inv.Value.AssetID;
969 continue;
970 }
971 } 977 }
972 } 978 }
979 m_host.TaskInventory.LockItemsForRead(false);
973 980
974 if (animID == UUID.Zero) 981 if (animID == UUID.Zero)
975 target.Animator.RemoveAnimation(animation); 982 target.Animator.RemoveAnimation(animation);
@@ -1790,6 +1797,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1790 1797
1791 if (!UUID.TryParse(notecardNameOrUuid, out assetID)) 1798 if (!UUID.TryParse(notecardNameOrUuid, out assetID))
1792 { 1799 {
1800 m_host.TaskInventory.LockItemsForRead(true);
1793 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1801 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1794 { 1802 {
1795 if (item.Type == 7 && item.Name == notecardNameOrUuid) 1803 if (item.Type == 7 && item.Name == notecardNameOrUuid)
@@ -1797,6 +1805,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1797 assetID = item.AssetID; 1805 assetID = item.AssetID;
1798 } 1806 }
1799 } 1807 }
1808 m_host.TaskInventory.LockItemsForRead(false);
1800 } 1809 }
1801 1810
1802 if (assetID == UUID.Zero) 1811 if (assetID == UUID.Zero)
@@ -2264,7 +2273,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2264 CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); 2273 CheckThreatLevel(ThreatLevel.High, "osNpcCreate");
2265 m_host.AddScriptLPS(1); 2274 m_host.AddScriptLPS(1);
2266 2275
2267 return NpcCreate(firstname, lastname, position, notecard, false, false); 2276 return NpcCreate(firstname, lastname, position, notecard, true, false);
2268 } 2277 }
2269 2278
2270 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options) 2279 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options)
@@ -2275,24 +2284,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2275 return NpcCreate( 2284 return NpcCreate(
2276 firstname, lastname, position, notecard, 2285 firstname, lastname, position, notecard,
2277 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0, 2286 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0,
2278 (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) != 0); 2287 false);
2288// (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) != 0);
2279 } 2289 }
2280 2290
2281 private LSL_Key NpcCreate( 2291 private LSL_Key NpcCreate(
2282 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent) 2292 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent)
2283 { 2293 {
2294 if (!owned)
2295 OSSLError("Unowned NPCs are unsupported");
2296
2297 string groupTitle = String.Empty;
2298
2299 if (!World.Permissions.CanRezObject(1, m_host.OwnerID, new Vector3((float)position.x, (float)position.y, (float)position.z)))
2300 return new LSL_Key(UUID.Zero.ToString());
2301
2302 if (firstname != String.Empty || lastname != String.Empty)
2303 {
2304 if (firstname != "Shown outfit:")
2305 groupTitle = "- NPC -";
2306 }
2307
2284 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2308 INPCModule module = World.RequestModuleInterface<INPCModule>();
2285 if (module != null) 2309 if (module != null)
2286 { 2310 {
2287 AvatarAppearance appearance = null; 2311 AvatarAppearance appearance = null;
2288 2312
2289 UUID id; 2313// UUID id;
2290 if (UUID.TryParse(notecard, out id)) 2314// if (UUID.TryParse(notecard, out id))
2291 { 2315// {
2292 ScenePresence clonePresence = World.GetScenePresence(id); 2316// ScenePresence clonePresence = World.GetScenePresence(id);
2293 if (clonePresence != null) 2317// if (clonePresence != null)
2294 appearance = clonePresence.Appearance; 2318// appearance = clonePresence.Appearance;
2295 } 2319// }
2296 2320
2297 if (appearance == null) 2321 if (appearance == null)
2298 { 2322 {
@@ -2320,6 +2344,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2320 World, 2344 World,
2321 appearance); 2345 appearance);
2322 2346
2347 ScenePresence sp;
2348 if (World.TryGetScenePresence(x, out sp))
2349 {
2350 sp.Grouptitle = groupTitle;
2351 sp.SendAvatarDataToAllAgents();
2352 }
2323 return new LSL_Key(x.ToString()); 2353 return new LSL_Key(x.ToString());
2324 } 2354 }
2325 2355
@@ -2611,16 +2641,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2611 CheckThreatLevel(ThreatLevel.High, "osNpcRemove"); 2641 CheckThreatLevel(ThreatLevel.High, "osNpcRemove");
2612 m_host.AddScriptLPS(1); 2642 m_host.AddScriptLPS(1);
2613 2643
2614 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2644 ManualResetEvent ev = new ManualResetEvent(false);
2615 if (module != null)
2616 {
2617 UUID npcId = new UUID(npc.m_string);
2618 2645
2619 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2646 Util.FireAndForget(delegate(object x) {
2620 return; 2647 try
2648 {
2649 INPCModule module = World.RequestModuleInterface<INPCModule>();
2650 if (module != null)
2651 {
2652 UUID npcId = new UUID(npc.m_string);
2621 2653
2622 module.DeleteNPC(npcId, World); 2654 ILandObject l = World.LandChannel.GetLandObject(m_host.GroupPosition.X, m_host.GroupPosition.Y);
2623 } 2655 if (l == null || m_host.OwnerID != l.LandData.OwnerID)
2656 {
2657 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2658 return;
2659 }
2660
2661 module.DeleteNPC(npcId, World);
2662 }
2663 }
2664 finally
2665 {
2666 ev.Set();
2667 }
2668 });
2669 ev.WaitOne();
2624 } 2670 }
2625 2671
2626 public void osNpcPlayAnimation(LSL_Key npc, string animation) 2672 public void osNpcPlayAnimation(LSL_Key npc, string animation)
@@ -3154,4 +3200,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3154 ((LSL_Api)m_LSL_Api).DetachFromAvatar(); 3200 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3155 } 3201 }
3156 } 3202 }
3157} \ No newline at end of file 3203}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 3844753..19f3ce1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -319,7 +319,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
319 float dy; 319 float dy;
320 float dz; 320 float dz;
321 321
322 Quaternion q = SensePoint.GetWorldRotation(); 322// Quaternion q = SensePoint.RotationOffset;
323 Quaternion q = SensePoint.GetWorldRotation(); // non-attached prim Sensor *always* uses World rotation!
323 if (SensePoint.ParentGroup.IsAttachment) 324 if (SensePoint.ParentGroup.IsAttachment)
324 { 325 {
325 // In attachments, rotate the sensor cone with the 326 // In attachments, rotate the sensor cone with the
@@ -333,7 +334,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
333 // Position of a sensor in a child prim attached to an avatar 334 // Position of a sensor in a child prim attached to an avatar
334 // will be still wrong. 335 // will be still wrong.
335 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 336 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
336 q = avatar.Rotation * q; 337 fromRegionPos = avatar.AbsolutePosition;
338 q = avatar.Rotation;
337 } 339 }
338 340
339 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 341 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
@@ -463,7 +465,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
463 // Position of a sensor in a child prim attached to an avatar 465 // Position of a sensor in a child prim attached to an avatar
464 // will be still wrong. 466 // will be still wrong.
465 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 467 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
466 q = avatar.Rotation * q; 468 if (avatar == null)
469 return sensedEntities;
470 fromRegionPos = avatar.AbsolutePosition;
471 q = avatar.Rotation;
467 } 472 }
468 473
469 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 474 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
index bc63030..9ee6946 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
@@ -118,25 +118,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
118 if (Timers.Count == 0) 118 if (Timers.Count == 0)
119 return; 119 return;
120 120
121 Dictionary<string, TimerClass>.ValueCollection tvals;
121 lock (TimerListLock) 122 lock (TimerListLock)
122 { 123 {
123 // Go through all timers 124 // Go through all timers
124 Dictionary<string, TimerClass>.ValueCollection tvals = Timers.Values; 125 tvals = Timers.Values;
125 foreach (TimerClass ts in tvals) 126 }
127
128 foreach (TimerClass ts in tvals)
129 {
130 // Time has passed?
131 if (ts.next < DateTime.Now.Ticks)
126 { 132 {
127 // Time has passed? 133 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next);
128 if (ts.next < DateTime.Now.Ticks) 134 // Add it to queue
129 { 135 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
130 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next); 136 new EventParams("timer", new Object[0],
131 // Add it to queue 137 new DetectParams[0]));
132 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, 138 // set next interval
133 new EventParams("timer", new Object[0], 139
134 new DetectParams[0])); 140 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
135 // set next interval 141 ts.next = DateTime.Now.Ticks + ts.interval;
136
137 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
138 ts.next = DateTime.Now.Ticks + ts.interval;
139 }
140 } 142 }
141 } 143 }
142 } 144 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs
new file mode 100644
index 0000000..ab215f3
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs
@@ -0,0 +1,46 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Collections;
29using OpenSim.Region.ScriptEngine.Interfaces;
30
31using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
32using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
33using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
34using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
35using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
36using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
37using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
38
39namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
40{
41 public interface ICM_Api
42 {
43 string cmDetectedCountry(int num);
44 string cmGetAgentCountry(key key);
45 }
46}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index 7f5d1fe..048124d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -126,6 +126,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
126 LSL_Float llGetEnergy(); 126 LSL_Float llGetEnergy();
127 LSL_Vector llGetForce(); 127 LSL_Vector llGetForce();
128 LSL_Integer llGetFreeMemory(); 128 LSL_Integer llGetFreeMemory();
129 LSL_Integer llGetUsedMemory();
129 LSL_Integer llGetFreeURLs(); 130 LSL_Integer llGetFreeURLs();
130 LSL_Vector llGetGeometricCenter(); 131 LSL_Vector llGetGeometricCenter();
131 LSL_Float llGetGMTclock(); 132 LSL_Float llGetGMTclock();
@@ -149,6 +150,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
149 LSL_Vector llGetLocalPos(); 150 LSL_Vector llGetLocalPos();
150 LSL_Rotation llGetLocalRot(); 151 LSL_Rotation llGetLocalRot();
151 LSL_Float llGetMass(); 152 LSL_Float llGetMass();
153 LSL_Float llGetMassMKS();
152 LSL_Integer llGetMemoryLimit(); 154 LSL_Integer llGetMemoryLimit();
153 void llGetNextEmail(string address, string subject); 155 void llGetNextEmail(string address, string subject);
154 LSL_String llGetNotecardLine(string name, int line); 156 LSL_String llGetNotecardLine(string name, int line);
@@ -202,12 +204,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
202 LSL_String llGetTimestamp(); 204 LSL_String llGetTimestamp();
203 LSL_Vector llGetTorque(); 205 LSL_Vector llGetTorque();
204 LSL_Integer llGetUnixTime(); 206 LSL_Integer llGetUnixTime();
205 LSL_Integer llGetUsedMemory();
206 LSL_Vector llGetVel(); 207 LSL_Vector llGetVel();
207 LSL_Float llGetWallclock(); 208 LSL_Float llGetWallclock();
208 void llGiveInventory(string destination, string inventory); 209 void llGiveInventory(string destination, string inventory);
209 void llGiveInventoryList(string destination, string category, LSL_List inventory); 210 void llGiveInventoryList(string destination, string category, LSL_List inventory);
210 LSL_Integer llGiveMoney(string destination, int amount); 211 LSL_Integer llGiveMoney(string destination, int amount);
212 LSL_String llTransferLindenDollars(string destination, int amount);
211 void llGodLikeRezObject(string inventory, LSL_Vector pos); 213 void llGodLikeRezObject(string inventory, LSL_Vector pos);
212 LSL_Float llGround(LSL_Vector offset); 214 LSL_Float llGround(LSL_Vector offset);
213 LSL_Vector llGroundContour(LSL_Vector offset); 215 LSL_Vector llGroundContour(LSL_Vector offset);
@@ -355,6 +357,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
355 void llSetParcelMusicURL(string url); 357 void llSetParcelMusicURL(string url);
356 void llSetPayPrice(int price, LSL_List quick_pay_buttons); 358 void llSetPayPrice(int price, LSL_List quick_pay_buttons);
357 void llSetPos(LSL_Vector pos); 359 void llSetPos(LSL_Vector pos);
360 LSL_Integer llSetRegionPos(LSL_Vector pos);
358 LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules); 361 LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules);
359 void llSetPrimitiveParams(LSL_List rules); 362 void llSetPrimitiveParams(LSL_List rules);
360 void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules); 363 void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules);
@@ -403,6 +406,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
403 void llTargetOmega(LSL_Vector axis, double spinrate, double gain); 406 void llTargetOmega(LSL_Vector axis, double spinrate, double gain);
404 void llTargetRemove(int number); 407 void llTargetRemove(int number);
405 void llTeleportAgentHome(string agent); 408 void llTeleportAgentHome(string agent);
409 void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt);
406 void llTextBox(string avatar, string message, int chat_channel); 410 void llTextBox(string avatar, string message, int chat_channel);
407 LSL_String llToLower(string source); 411 LSL_String llToLower(string source);
408 LSL_String llToUpper(string source); 412 LSL_String llToUpper(string source);
@@ -419,9 +423,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
419 LSL_Vector llWind(LSL_Vector offset); 423 LSL_Vector llWind(LSL_Vector offset);
420 LSL_String llXorBase64Strings(string str1, string str2); 424 LSL_String llXorBase64Strings(string str1, string str2);
421 LSL_String llXorBase64StringsCorrect(string str1, string str2); 425 LSL_String llXorBase64StringsCorrect(string str1, string str2);
422 void print(string str); 426 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link);
427 void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density);
423 428
424 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 429 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
425 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 430 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
431 void llSetKeyframedMotion(LSL_List frames, LSL_List options);
426 } 432 }
427} 433}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index e92518d..7382495 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -85,7 +85,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
85 // Avatar Info Commands 85 // Avatar Info Commands
86 string osGetAgentIP(string agent); 86 string osGetAgentIP(string agent);
87 LSL_List osGetAgents(); 87 LSL_List osGetAgents();
88 88
89 // Teleport commands 89 // Teleport commands
90 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 90 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
91 void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 91 void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs
new file mode 100644
index 0000000..4132dfa
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs
@@ -0,0 +1,71 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Runtime.Remoting.Lifetime;
30using System.Threading;
31using System.Reflection;
32using System.Collections;
33using System.Collections.Generic;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
38using integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
39using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
40using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
41using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
42using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
43using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
44using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
45using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
46
47namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
48{
49 public partial class ScriptBaseClass : MarshalByRefObject
50 {
51 public ICM_Api m_CM_Functions;
52
53 public void ApiTypeCM(IScriptApi api)
54 {
55 if (!(api is ICM_Api))
56 return;
57
58 m_CM_Functions = (ICM_Api)api;
59 }
60
61 public string cmDetectedCountry(int num)
62 {
63 return m_CM_Functions.cmDetectedCountry(num);
64 }
65
66 public string cmGetAgentCountry(key key)
67 {
68 return m_CM_Functions.cmGetAgentCountry(key);
69 }
70 }
71}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
index 9615315..943d7a2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; //for [DebuggerNonUserCode]
30using System.Reflection; 31using System.Reflection;
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using OpenSim.Region.ScriptEngine.Shared; 33using OpenSim.Region.ScriptEngine.Shared;
@@ -132,6 +133,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
132 return (eventFlags); 133 return (eventFlags);
133 } 134 }
134 135
136 [DebuggerNonUserCode]
135 public void ExecuteEvent(string state, string FunctionName, object[] args) 137 public void ExecuteEvent(string state, string FunctionName, object[] args)
136 { 138 {
137 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. 139 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index b6c21e6..5c6ad8a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -94,6 +94,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
94 public const int AGENT_CROUCHING = 1024; 94 public const int AGENT_CROUCHING = 1024;
95 public const int AGENT_BUSY = 2048; 95 public const int AGENT_BUSY = 2048;
96 public const int AGENT_ALWAYS_RUN = 4096; 96 public const int AGENT_ALWAYS_RUN = 4096;
97 public const int AGENT_MALE = 8192;
97 98
98 //Particle Systems 99 //Particle Systems
99 public const int PSYS_PART_INTERP_COLOR_MASK = 1; 100 public const int PSYS_PART_INTERP_COLOR_MASK = 1;
@@ -282,6 +283,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
282 public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART 283 public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART
283 public const int CHANGED_MEDIA = 2048; 284 public const int CHANGED_MEDIA = 2048;
284 public const int CHANGED_ANIMATION = 16384; 285 public const int CHANGED_ANIMATION = 16384;
286 public const int CHANGED_POSITION = 32768;
285 public const int TYPE_INVALID = 0; 287 public const int TYPE_INVALID = 0;
286 public const int TYPE_INTEGER = 1; 288 public const int TYPE_INTEGER = 1;
287 public const int TYPE_FLOAT = 2; 289 public const int TYPE_FLOAT = 2;
@@ -586,6 +588,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
586 public const int PRIM_MEDIA_PERM_OWNER = 1; 588 public const int PRIM_MEDIA_PERM_OWNER = 1;
587 public const int PRIM_MEDIA_PERM_GROUP = 2; 589 public const int PRIM_MEDIA_PERM_GROUP = 2;
588 public const int PRIM_MEDIA_PERM_ANYONE = 4; 590 public const int PRIM_MEDIA_PERM_ANYONE = 4;
591
592 public const int PRIM_PHYSICS_SHAPE_TYPE = 30;
593 public const int PRIM_PHYSICS_SHAPE_PRIM = 0;
594 public const int PRIM_PHYSICS_SHAPE_CONVEX = 2;
595 public const int PRIM_PHYSICS_SHAPE_NONE = 1;
596
597 public const int PRIM_PHYSICS_MATERIAL = 31;
598 public const int DENSITY = 1;
599 public const int FRICTION = 2;
600 public const int RESTITUTION = 4;
601 public const int GRAVITY_MULTIPLIER = 8;
589 602
590 // extra constants for llSetPrimMediaParams 603 // extra constants for llSetPrimMediaParams
591 public static readonly LSLInteger LSL_STATUS_OK = new LSLInteger(0); 604 public static readonly LSLInteger LSL_STATUS_OK = new LSLInteger(0);
@@ -659,5 +672,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
659 public static readonly LSLInteger RCERR_UNKNOWN = -1; 672 public static readonly LSLInteger RCERR_UNKNOWN = -1;
660 public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2; 673 public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2;
661 public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3; 674 public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3;
675
676 public const int KFM_MODE = 1;
677 public const int KFM_LOOP = 1;
678 public const int KFM_REVERSE = 3;
679 public const int KFM_FORWARD = 0;
680 public const int KFM_PING_PONG = 2;
681 public const int KFM_DATA = 2;
682 public const int KFM_TRANSLATION = 2;
683 public const int KFM_ROTATION = 1;
684 public const int KFM_COMMAND = 0;
685 public const int KFM_CMD_PLAY = 0;
686 public const int KFM_CMD_STOP = 1;
687 public const int KFM_CMD_PAUSE = 2;
662 } 688 }
663} 689}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index c0bf29c..2d23d30 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Diagnostics; //for [DebuggerNonUserCode]
29using System.Runtime.Remoting.Lifetime; 30using System.Runtime.Remoting.Lifetime;
30using System.Threading; 31using System.Threading;
31using System.Reflection; 32using System.Reflection;
@@ -164,6 +165,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
164 m_LSL_Functions.llBreakLink(linknum); 165 m_LSL_Functions.llBreakLink(linknum);
165 } 166 }
166 167
168 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
169 {
170 return m_LSL_Functions.llCastRay(start, end, options);
171 }
172
167 public LSL_Integer llCeil(double f) 173 public LSL_Integer llCeil(double f)
168 { 174 {
169 return m_LSL_Functions.llCeil(f); 175 return m_LSL_Functions.llCeil(f);
@@ -314,6 +320,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
314 m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel); 320 m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel);
315 } 321 }
316 322
323 [DebuggerNonUserCode]
317 public void llDie() 324 public void llDie()
318 { 325 {
319 m_LSL_Functions.llDie(); 326 m_LSL_Functions.llDie();
@@ -474,6 +481,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
474 return m_LSL_Functions.llGetFreeMemory(); 481 return m_LSL_Functions.llGetFreeMemory();
475 } 482 }
476 483
484 public LSL_Integer llGetUsedMemory()
485 {
486 return m_LSL_Functions.llGetUsedMemory();
487 }
488
477 public LSL_Integer llGetFreeURLs() 489 public LSL_Integer llGetFreeURLs()
478 { 490 {
479 return m_LSL_Functions.llGetFreeURLs(); 491 return m_LSL_Functions.llGetFreeURLs();
@@ -579,6 +591,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
579 return m_LSL_Functions.llGetMass(); 591 return m_LSL_Functions.llGetMass();
580 } 592 }
581 593
594 public LSL_Float llGetMassMKS()
595 {
596 return m_LSL_Functions.llGetMassMKS();
597 }
598
582 public LSL_Integer llGetMemoryLimit() 599 public LSL_Integer llGetMemoryLimit()
583 { 600 {
584 return m_LSL_Functions.llGetMemoryLimit(); 601 return m_LSL_Functions.llGetMemoryLimit();
@@ -844,11 +861,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
844 return m_LSL_Functions.llGetUnixTime(); 861 return m_LSL_Functions.llGetUnixTime();
845 } 862 }
846 863
847 public LSL_Integer llGetUsedMemory()
848 {
849 return m_LSL_Functions.llGetUsedMemory();
850 }
851
852 public LSL_Vector llGetVel() 864 public LSL_Vector llGetVel()
853 { 865 {
854 return m_LSL_Functions.llGetVel(); 866 return m_LSL_Functions.llGetVel();
@@ -874,6 +886,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
874 return m_LSL_Functions.llGiveMoney(destination, amount); 886 return m_LSL_Functions.llGiveMoney(destination, amount);
875 } 887 }
876 888
889 public LSL_String llTransferLindenDollars(string destination, int amount)
890 {
891 return m_LSL_Functions.llTransferLindenDollars(destination, amount);
892 }
893
877 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 894 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
878 { 895 {
879 m_LSL_Functions.llGodLikeRezObject(inventory, pos); 896 m_LSL_Functions.llGodLikeRezObject(inventory, pos);
@@ -1598,6 +1615,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1598 m_LSL_Functions.llSetPos(pos); 1615 m_LSL_Functions.llSetPos(pos);
1599 } 1616 }
1600 1617
1618 public LSL_Integer llSetRegionPos(LSL_Vector pos)
1619 {
1620 return m_LSL_Functions.llSetRegionPos(pos);
1621 }
1622
1601 public void llSetPrimitiveParams(LSL_List rules) 1623 public void llSetPrimitiveParams(LSL_List rules)
1602 { 1624 {
1603 m_LSL_Functions.llSetPrimitiveParams(rules); 1625 m_LSL_Functions.llSetPrimitiveParams(rules);
@@ -1833,6 +1855,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1833 m_LSL_Functions.llTargetRemove(number); 1855 m_LSL_Functions.llTargetRemove(number);
1834 } 1856 }
1835 1857
1858 public void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt)
1859 {
1860 m_LSL_Functions.llTeleportAgent(agent, simname, pos, lookAt);
1861 }
1862
1836 public void llTeleportAgentHome(string agent) 1863 public void llTeleportAgentHome(string agent)
1837 { 1864 {
1838 m_LSL_Functions.llTeleportAgentHome(agent); 1865 m_LSL_Functions.llTeleportAgentHome(agent);
@@ -1948,9 +1975,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1948 return m_LSL_Functions.llClearLinkMedia(link, face); 1975 return m_LSL_Functions.llClearLinkMedia(link, face);
1949 } 1976 }
1950 1977
1951 public void print(string str) 1978 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
1979 {
1980 return m_LSL_Functions.llGetLinkNumberOfSides(link);
1981 }
1982
1983 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
1984 {
1985 m_LSL_Functions.llSetKeyframedMotion(frames, options);
1986 }
1987
1988 public void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density)
1952 { 1989 {
1953 m_LSL_Functions.print(str); 1990 m_LSL_Functions.llSetPhysicsMaterial(material_bits, material_gravity_modifier, material_restitution, material_friction, material_density);
1954 } 1991 }
1955 } 1992 }
1956} 1993}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
index 143b497..2e27f16 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
@@ -72,9 +72,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
72 { 72 {
73 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target); 73 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target);
74 } 74 }
75
75 public void lsClearWindlightScene() 76 public void lsClearWindlightScene()
76 { 77 {
77 m_LS_Functions.lsClearWindlightScene(); 78 m_LS_Functions.lsClearWindlightScene();
78 } 79 }
80
81 public LSL_List cmGetWindlightScene(LSL_List rules)
82 {
83 return m_LS_Functions.lsGetWindlightScene(rules);
84 }
85
86 public int cmSetWindlightScene(LSL_List rules)
87 {
88 return m_LS_Functions.lsSetWindlightScene(rules);
89 }
90
91 public int cmSetWindlightSceneTargeted(LSL_List rules, key target)
92 {
93 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target);
94 }
95
96 public void cmClearWindlightScene()
97 {
98 m_LS_Functions.lsClearWindlightScene();
99 }
79 } 100 }
80} 101}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
index edbbc2a..b138da3 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
@@ -33,6 +33,7 @@ using System.Threading;
33using System.Reflection; 33using System.Reflection;
34using System.Collections; 34using System.Collections;
35using System.Collections.Generic; 35using System.Collections.Generic;
36using System.Diagnostics; //for [DebuggerNonUserCode]
36using OpenSim.Region.ScriptEngine.Interfaces; 37using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared; 38using OpenSim.Region.ScriptEngine.Shared;
38using OpenSim.Region.ScriptEngine.Shared.Api.Runtime; 39using OpenSim.Region.ScriptEngine.Shared.Api.Runtime;
@@ -90,6 +91,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
90 return (int)m_Executor.GetStateEventFlags(state); 91 return (int)m_Executor.GetStateEventFlags(state);
91 } 92 }
92 93
94 [DebuggerNonUserCode]
93 public void ExecuteEvent(string state, string FunctionName, object[] args) 95 public void ExecuteEvent(string state, string FunctionName, object[] args)
94 { 96 {
95 m_Executor.ExecuteEvent(state, FunctionName, args); 97 m_Executor.ExecuteEvent(state, FunctionName, args);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 8cebb4a..7e7e278 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -35,6 +35,7 @@ using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Region.CoreModules; 36using OpenSim.Region.CoreModules;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces;
38 39
39namespace OpenSim.Region.ScriptEngine.Shared 40namespace OpenSim.Region.ScriptEngine.Shared
40{ 41{
@@ -95,6 +96,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
95 Type = 0; 96 Type = 0;
96 Velocity = new LSL_Types.Vector3(); 97 Velocity = new LSL_Types.Vector3();
97 initializeSurfaceTouch(); 98 initializeSurfaceTouch();
99 Country = String.Empty;
98 } 100 }
99 101
100 public UUID Key; 102 public UUID Key;
@@ -126,6 +128,8 @@ namespace OpenSim.Region.ScriptEngine.Shared
126 private int touchFace; 128 private int touchFace;
127 public int TouchFace { get { return touchFace; } } 129 public int TouchFace { get { return touchFace; } }
128 130
131 public string Country;
132
129 // This can be done in two places including the constructor 133 // This can be done in two places including the constructor
130 // so be carefull what gets added here 134 // so be carefull what gets added here
131 private void initializeSurfaceTouch() 135 private void initializeSurfaceTouch()
@@ -173,6 +177,10 @@ namespace OpenSim.Region.ScriptEngine.Shared
173 return; 177 return;
174 178
175 Name = presence.Firstname + " " + presence.Lastname; 179 Name = presence.Firstname + " " + presence.Lastname;
180 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, Key);
181 if (account != null)
182 Country = account.UserCountry;
183
176 Owner = Key; 184 Owner = Key;
177 Position = new LSL_Types.Vector3( 185 Position = new LSL_Types.Vector3(
178 presence.AbsolutePosition.X, 186 presence.AbsolutePosition.X,
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 329e361..5cad883 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
@@ -859,6 +861,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
859 new Object[0], new DetectParams[0])); 861 new Object[0], new DetectParams[0]));
860 } 862 }
861 863
864 [DebuggerNonUserCode] //Stops the VS debugger from farting in this function
862 public void ApiResetScript() 865 public void ApiResetScript()
863 { 866 {
864 // bool running = Running; 867 // bool running = Running;
@@ -890,10 +893,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
890 893
891 public Dictionary<string, object> GetVars() 894 public Dictionary<string, object> GetVars()
892 { 895 {
893 if (m_Script != null) 896 return m_Script.GetVars();
894 return m_Script.GetVars();
895 else
896 return new Dictionary<string, object>();
897 } 897 }
898 898
899 public void SetVars(Dictionary<string, object> vars) 899 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}