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.cs2987
-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, 2929 insertions, 1077 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 5bff2e9..8c4ee41 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);
@@ -3031,9 +3288,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3031 { 3288 {
3032 m_host.AddScriptLPS(1); 3289 m_host.AddScriptLPS(1);
3033 3290
3034// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3035// return;
3036
3037 if (m_item.PermsGranter != m_host.OwnerID) 3291 if (m_item.PermsGranter != m_host.OwnerID)
3038 return; 3292 return;
3039 3293
@@ -3076,6 +3330,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3076 3330
3077 public void llInstantMessage(string user, string message) 3331 public void llInstantMessage(string user, string message)
3078 { 3332 {
3333 UUID result;
3334 if (!UUID.TryParse(user, out result))
3335 {
3336 ShoutError("An invalid key was passed to llInstantMessage");
3337 ScriptSleep(2000);
3338 return;
3339 }
3340
3341
3079 m_host.AddScriptLPS(1); 3342 m_host.AddScriptLPS(1);
3080 3343
3081 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3344 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3090,14 +3353,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3090 UUID friendTransactionID = UUID.Random(); 3353 UUID friendTransactionID = UUID.Random();
3091 3354
3092 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3355 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3093 3356
3094 GridInstantMessage msg = new GridInstantMessage(); 3357 GridInstantMessage msg = new GridInstantMessage();
3095 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3358 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3096 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3359 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3097 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3360 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3098// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3361// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3099// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3362// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3100 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3363// DateTime dt = DateTime.UtcNow;
3364//
3365// // Ticks from UtcNow, but make it look like local. Evil, huh?
3366// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3367//
3368// try
3369// {
3370// // Convert that to the PST timezone
3371// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3372// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3373// }
3374// catch
3375// {
3376// // No logging here, as it could be VERY spammy
3377// }
3378//
3379// // And make it look local again to fool the unix time util
3380// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3381
3382 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3383
3101 //if (client != null) 3384 //if (client != null)
3102 //{ 3385 //{
3103 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3386 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3111,12 +3394,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3111 msg.message = message.Substring(0, 1024); 3394 msg.message = message.Substring(0, 1024);
3112 else 3395 else
3113 msg.message = message; 3396 msg.message = message;
3114 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3397 msg.dialog = (byte)19; // MessageFromObject
3115 msg.fromGroup = false;// fromGroup; 3398 msg.fromGroup = false;// fromGroup;
3116 msg.offline = (byte)0; //offline; 3399 msg.offline = (byte)0; //offline;
3117 msg.ParentEstateID = 0; //ParentEstateID; 3400 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3118 msg.Position = new Vector3(m_host.AbsolutePosition); 3401 msg.Position = new Vector3(m_host.AbsolutePosition);
3119 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3402 msg.RegionID = World.RegionInfo.RegionID.Guid;
3120 msg.binaryBucket 3403 msg.binaryBucket
3121 = Util.StringToBytes256( 3404 = Util.StringToBytes256(
3122 "{0}/{1}/{2}/{3}", 3405 "{0}/{1}/{2}/{3}",
@@ -3144,7 +3427,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3144 } 3427 }
3145 3428
3146 emailModule.SendEmail(m_host.UUID, address, subject, message); 3429 emailModule.SendEmail(m_host.UUID, address, subject, message);
3147 llSleep(EMAIL_PAUSE_TIME); 3430 ScriptSleep(EMAIL_PAUSE_TIME * 1000);
3148 } 3431 }
3149 3432
3150 public void llGetNextEmail(string address, string subject) 3433 public void llGetNextEmail(string address, string subject)
@@ -3393,15 +3676,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3393 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3676 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3394 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3677 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3395 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3678 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3679 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3396 ScriptBaseClass.PERMISSION_ATTACH; 3680 ScriptBaseClass.PERMISSION_ATTACH;
3397 3681
3398 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3682 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3399 { 3683 {
3400 lock (m_host.TaskInventory) 3684 m_host.TaskInventory.LockItemsForWrite(true);
3401 { 3685 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3402 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3686 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3403 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3687 m_host.TaskInventory.LockItemsForWrite(false);
3404 }
3405 3688
3406 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3689 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3407 "run_time_permissions", new Object[] { 3690 "run_time_permissions", new Object[] {
@@ -3411,28 +3694,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3411 return; 3694 return;
3412 } 3695 }
3413 } 3696 }
3414 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3697 else
3415 { 3698 {
3416 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3699 bool sitting = false;
3417 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3700 if (m_host.SitTargetAvatar == agentID)
3418 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3701 {
3419 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3702 sitting = true;
3420 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3703 }
3704 else
3705 {
3706 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3707 {
3708 if (p.SitTargetAvatar == agentID)
3709 sitting = true;
3710 }
3711 }
3421 3712
3422 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3713 if (sitting)
3423 { 3714 {
3424 lock (m_host.TaskInventory) 3715 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3716 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3717 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3718 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3719 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3720
3721 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3425 { 3722 {
3723 m_host.TaskInventory.LockItemsForWrite(true);
3426 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3724 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3427 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3725 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3428 } 3726 m_host.TaskInventory.LockItemsForWrite(false);
3429 3727
3430 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3728 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3431 "run_time_permissions", new Object[] { 3729 "run_time_permissions", new Object[] {
3432 new LSL_Integer(perm) }, 3730 new LSL_Integer(perm) },
3433 new DetectParams[0])); 3731 new DetectParams[0]));
3434 3732
3435 return; 3733 return;
3734 }
3436 } 3735 }
3437 } 3736 }
3438 3737
@@ -3446,11 +3745,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3446 3745
3447 if (!m_waitingForScriptAnswer) 3746 if (!m_waitingForScriptAnswer)
3448 { 3747 {
3449 lock (m_host.TaskInventory) 3748 m_host.TaskInventory.LockItemsForWrite(true);
3450 { 3749 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3451 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3750 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3452 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 3751 m_host.TaskInventory.LockItemsForWrite(false);
3453 }
3454 3752
3455 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3753 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3456 m_waitingForScriptAnswer=true; 3754 m_waitingForScriptAnswer=true;
@@ -3480,11 +3778,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3480 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3778 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3481 llReleaseControls(); 3779 llReleaseControls();
3482 3780
3483 lock (m_host.TaskInventory) 3781 m_host.TaskInventory.LockItemsForWrite(true);
3484 { 3782 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3485 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 3783 m_host.TaskInventory.LockItemsForWrite(false);
3486 } 3784
3487
3488 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3785 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3489 "run_time_permissions", new Object[] { 3786 "run_time_permissions", new Object[] {
3490 new LSL_Integer(answer) }, 3787 new LSL_Integer(answer) },
@@ -3527,14 +3824,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3527 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3824 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3528 { 3825 {
3529 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3826 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3530 3827 if (parts.Count > 0)
3531 foreach (SceneObjectPart part in parts) 3828 {
3532 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3829 try
3830 {
3831 parts[0].ParentGroup.areUpdatesSuspended = true;
3832 foreach (SceneObjectPart part in parts)
3833 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3834 }
3835 finally
3836 {
3837 parts[0].ParentGroup.areUpdatesSuspended = false;
3838 }
3839 }
3533 } 3840 }
3534 3841
3535 public void llCreateLink(string target, int parent) 3842 public void llCreateLink(string target, int parent)
3536 { 3843 {
3537 m_host.AddScriptLPS(1); 3844 m_host.AddScriptLPS(1);
3845
3538 UUID targetID; 3846 UUID targetID;
3539 3847
3540 if (!UUID.TryParse(target, out targetID)) 3848 if (!UUID.TryParse(target, out targetID))
@@ -3640,10 +3948,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3640 // Restructuring Multiple Prims. 3948 // Restructuring Multiple Prims.
3641 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 3949 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3642 parts.Remove(parentPrim.RootPart); 3950 parts.Remove(parentPrim.RootPart);
3643 foreach (SceneObjectPart part in parts) 3951 if (parts.Count > 0)
3644 { 3952 {
3645 parentPrim.DelinkFromGroup(part.LocalId, true); 3953 try
3954 {
3955 parts[0].ParentGroup.areUpdatesSuspended = true;
3956 foreach (SceneObjectPart part in parts)
3957 {
3958 parentPrim.DelinkFromGroup(part.LocalId, true);
3959 }
3960 }
3961 finally
3962 {
3963 parts[0].ParentGroup.areUpdatesSuspended = false;
3964 }
3646 } 3965 }
3966
3647 parentPrim.HasGroupChanged = true; 3967 parentPrim.HasGroupChanged = true;
3648 parentPrim.ScheduleGroupForFullUpdate(); 3968 parentPrim.ScheduleGroupForFullUpdate();
3649 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3969 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3652,12 +3972,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3652 { 3972 {
3653 SceneObjectPart newRoot = parts[0]; 3973 SceneObjectPart newRoot = parts[0];
3654 parts.Remove(newRoot); 3974 parts.Remove(newRoot);
3655 foreach (SceneObjectPart part in parts) 3975
3976 try
3656 { 3977 {
3657 // Required for linking 3978 parts[0].ParentGroup.areUpdatesSuspended = true;
3658 part.ClearUpdateSchedule(); 3979 foreach (SceneObjectPart part in parts)
3659 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 3980 {
3981 part.ClearUpdateSchedule();
3982 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3983 }
3660 } 3984 }
3985 finally
3986 {
3987 parts[0].ParentGroup.areUpdatesSuspended = false;
3988 }
3989
3990
3661 newRoot.ParentGroup.HasGroupChanged = true; 3991 newRoot.ParentGroup.HasGroupChanged = true;
3662 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 3992 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3663 } 3993 }
@@ -3677,6 +4007,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3677 public void llBreakAllLinks() 4007 public void llBreakAllLinks()
3678 { 4008 {
3679 m_host.AddScriptLPS(1); 4009 m_host.AddScriptLPS(1);
4010
4011 TaskInventoryItem item = m_item;
4012
4013 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4014 && !m_automaticLinkPermission)
4015 {
4016 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4017 return;
4018 }
4019
3680 SceneObjectGroup parentPrim = m_host.ParentGroup; 4020 SceneObjectGroup parentPrim = m_host.ParentGroup;
3681 if (parentPrim.AttachmentPoint != 0) 4021 if (parentPrim.AttachmentPoint != 0)
3682 return; // Fail silently if attached 4022 return; // Fail silently if attached
@@ -3696,25 +4036,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3696 public LSL_String llGetLinkKey(int linknum) 4036 public LSL_String llGetLinkKey(int linknum)
3697 { 4037 {
3698 m_host.AddScriptLPS(1); 4038 m_host.AddScriptLPS(1);
3699 List<UUID> keytable = new List<UUID>();
3700 // parse for sitting avatare-uuids
3701 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3702 {
3703 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
3704 keytable.Add(presence.UUID);
3705 });
3706
3707 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3708 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3709 {
3710 return keytable[totalprims - linknum].ToString();
3711 }
3712
3713 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3714 {
3715 return m_host.UUID.ToString();
3716 }
3717
3718 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4039 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3719 if (part != null) 4040 if (part != null)
3720 { 4041 {
@@ -3722,6 +4043,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3722 } 4043 }
3723 else 4044 else
3724 { 4045 {
4046 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4047 {
4048 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4049
4050 if (linknum < 0)
4051 return UUID.Zero.ToString();
4052
4053 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4054 if (avatars.Count > linknum)
4055 {
4056 return avatars[linknum].UUID.ToString();
4057 }
4058 }
3725 return UUID.Zero.ToString(); 4059 return UUID.Zero.ToString();
3726 } 4060 }
3727 } 4061 }
@@ -3821,17 +4155,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3821 m_host.AddScriptLPS(1); 4155 m_host.AddScriptLPS(1);
3822 int count = 0; 4156 int count = 0;
3823 4157
3824 lock (m_host.TaskInventory) 4158 m_host.TaskInventory.LockItemsForRead(true);
4159 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3825 { 4160 {
3826 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4161 if (inv.Value.Type == type || type == -1)
3827 { 4162 {
3828 if (inv.Value.Type == type || type == -1) 4163 count = count + 1;
3829 {
3830 count = count + 1;
3831 }
3832 } 4164 }
3833 } 4165 }
3834 4166
4167 m_host.TaskInventory.LockItemsForRead(false);
3835 return count; 4168 return count;
3836 } 4169 }
3837 4170
@@ -3840,16 +4173,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3840 m_host.AddScriptLPS(1); 4173 m_host.AddScriptLPS(1);
3841 ArrayList keys = new ArrayList(); 4174 ArrayList keys = new ArrayList();
3842 4175
3843 lock (m_host.TaskInventory) 4176 m_host.TaskInventory.LockItemsForRead(true);
4177 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3844 { 4178 {
3845 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4179 if (inv.Value.Type == type || type == -1)
3846 { 4180 {
3847 if (inv.Value.Type == type || type == -1) 4181 keys.Add(inv.Value.Name);
3848 {
3849 keys.Add(inv.Value.Name);
3850 }
3851 } 4182 }
3852 } 4183 }
4184 m_host.TaskInventory.LockItemsForRead(false);
3853 4185
3854 if (keys.Count == 0) 4186 if (keys.Count == 0)
3855 { 4187 {
@@ -3886,25 +4218,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3886 } 4218 }
3887 4219
3888 // move the first object found with this inventory name 4220 // move the first object found with this inventory name
3889 lock (m_host.TaskInventory) 4221 m_host.TaskInventory.LockItemsForRead(true);
4222 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3890 { 4223 {
3891 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4224 if (inv.Value.Name == inventory)
3892 { 4225 {
3893 if (inv.Value.Name == inventory) 4226 found = true;
3894 { 4227 objId = inv.Key;
3895 found = true; 4228 assetType = inv.Value.Type;
3896 objId = inv.Key; 4229 objName = inv.Value.Name;
3897 assetType = inv.Value.Type; 4230 break;
3898 objName = inv.Value.Name;
3899 break;
3900 }
3901 } 4231 }
3902 } 4232 }
4233 m_host.TaskInventory.LockItemsForRead(false);
3903 4234
3904 if (!found) 4235 if (!found)
3905 { 4236 {
3906 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4237 llSay(0, String.Format("Could not find object '{0}'", inventory));
3907 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4238 return;
4239// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3908 } 4240 }
3909 4241
3910 // check if destination is an object 4242 // check if destination is an object
@@ -3930,48 +4262,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3930 return; 4262 return;
3931 } 4263 }
3932 } 4264 }
4265
3933 // destination is an avatar 4266 // destination is an avatar
3934 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4267 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3935 4268
3936 if (agentItem == null) 4269 if (agentItem == null)
3937 return; 4270 return;
3938 4271
3939 byte[] bucket = new byte[17]; 4272 byte[] bucket = new byte[1];
3940 bucket[0] = (byte)assetType; 4273 bucket[0] = (byte)assetType;
3941 byte[] objBytes = agentItem.ID.GetBytes(); 4274 //byte[] objBytes = agentItem.ID.GetBytes();
3942 Array.Copy(objBytes, 0, bucket, 1, 16); 4275 //Array.Copy(objBytes, 0, bucket, 1, 16);
3943 4276
3944 GridInstantMessage msg = new GridInstantMessage(World, 4277 GridInstantMessage msg = new GridInstantMessage(World,
3945 m_host.UUID, m_host.Name+", an object owned by "+ 4278 m_host.OwnerID, m_host.Name, destId,
3946 resolveName(m_host.OwnerID)+",", destId,
3947 (byte)InstantMessageDialog.TaskInventoryOffered, 4279 (byte)InstantMessageDialog.TaskInventoryOffered,
3948 false, objName+"\n"+m_host.Name+" is located at "+ 4280 false, objName+". "+m_host.Name+" is located at "+
3949 World.RegionInfo.RegionName+" "+ 4281 World.RegionInfo.RegionName+" "+
3950 m_host.AbsolutePosition.ToString(), 4282 m_host.AbsolutePosition.ToString(),
3951 agentItem.ID, true, m_host.AbsolutePosition, 4283 agentItem.ID, true, m_host.AbsolutePosition,
3952 bucket); 4284 bucket);
3953 if (m_TransferModule != null) 4285
3954 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4286 ScenePresence sp;
4287
4288 if (World.TryGetScenePresence(destId, out sp))
4289 {
4290 sp.ControllingClient.SendInstantMessage(msg);
4291 }
4292 else
4293 {
4294 if (m_TransferModule != null)
4295 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4296 }
4297
4298 //This delay should only occur when giving inventory to avatars.
3955 ScriptSleep(3000); 4299 ScriptSleep(3000);
3956 } 4300 }
3957 } 4301 }
3958 4302
4303 [DebuggerNonUserCode]
3959 public void llRemoveInventory(string name) 4304 public void llRemoveInventory(string name)
3960 { 4305 {
3961 m_host.AddScriptLPS(1); 4306 m_host.AddScriptLPS(1);
3962 4307
3963 lock (m_host.TaskInventory) 4308 List<TaskInventoryItem> inv;
4309 try
3964 { 4310 {
3965 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4311 m_host.TaskInventory.LockItemsForRead(true);
4312 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4313 }
4314 finally
4315 {
4316 m_host.TaskInventory.LockItemsForRead(false);
4317 }
4318 foreach (TaskInventoryItem item in inv)
4319 {
4320 if (item.Name == name)
3966 { 4321 {
3967 if (item.Name == name) 4322 if (item.ItemID == m_item.ItemID)
3968 { 4323 throw new ScriptDeleteException();
3969 if (item.ItemID == m_item.ItemID) 4324 else
3970 throw new ScriptDeleteException(); 4325 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3971 else 4326 return;
3972 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3973 return;
3974 }
3975 } 4327 }
3976 } 4328 }
3977 } 4329 }
@@ -4006,115 +4358,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4006 { 4358 {
4007 m_host.AddScriptLPS(1); 4359 m_host.AddScriptLPS(1);
4008 4360
4009 UUID uuid = (UUID)id; 4361 UUID uuid;
4010 PresenceInfo pinfo = null; 4362 if (UUID.TryParse(id, out uuid))
4011 UserAccount account;
4012
4013 UserInfoCacheEntry ce;
4014 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4015 { 4363 {
4016 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4364 PresenceInfo pinfo = null;
4017 if (account == null) 4365 UserAccount account;
4366
4367 UserInfoCacheEntry ce;
4368 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4018 { 4369 {
4019 m_userInfoCache[uuid] = null; // Cache negative 4370 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4020 return UUID.Zero.ToString(); 4371 if (account == null)
4021 } 4372 {
4373 m_userInfoCache[uuid] = null; // Cache negative
4374 return UUID.Zero.ToString();
4375 }
4022 4376
4023 4377
4024 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4378 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4025 if (pinfos != null && pinfos.Length > 0) 4379 if (pinfos != null && pinfos.Length > 0)
4026 {
4027 foreach (PresenceInfo p in pinfos)
4028 { 4380 {
4029 if (p.RegionID != UUID.Zero) 4381 foreach (PresenceInfo p in pinfos)
4030 { 4382 {
4031 pinfo = p; 4383 if (p.RegionID != UUID.Zero)
4384 {
4385 pinfo = p;
4386 }
4032 } 4387 }
4033 } 4388 }
4034 }
4035 4389
4036 ce = new UserInfoCacheEntry(); 4390 ce = new UserInfoCacheEntry();
4037 ce.time = Util.EnvironmentTickCount(); 4391 ce.time = Util.EnvironmentTickCount();
4038 ce.account = account; 4392 ce.account = account;
4039 ce.pinfo = pinfo; 4393 ce.pinfo = pinfo;
4040 } 4394 m_userInfoCache[uuid] = ce;
4041 else 4395 }
4042 { 4396 else
4043 if (ce == null) 4397 {
4044 return UUID.Zero.ToString(); 4398 if (ce == null)
4399 return UUID.Zero.ToString();
4045 4400
4046 account = ce.account; 4401 account = ce.account;
4047 pinfo = ce.pinfo; 4402 pinfo = ce.pinfo;
4048 } 4403 }
4049 4404
4050 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4405 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4051 {
4052 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4053 if (pinfos != null && pinfos.Length > 0)
4054 { 4406 {
4055 foreach (PresenceInfo p in pinfos) 4407 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4408 if (pinfos != null && pinfos.Length > 0)
4056 { 4409 {
4057 if (p.RegionID != UUID.Zero) 4410 foreach (PresenceInfo p in pinfos)
4058 { 4411 {
4059 pinfo = p; 4412 if (p.RegionID != UUID.Zero)
4413 {
4414 pinfo = p;
4415 }
4060 } 4416 }
4061 } 4417 }
4062 } 4418 else
4063 else 4419 pinfo = null;
4064 pinfo = null;
4065 4420
4066 ce.time = Util.EnvironmentTickCount(); 4421 ce.time = Util.EnvironmentTickCount();
4067 ce.pinfo = pinfo; 4422 ce.pinfo = pinfo;
4068 } 4423 }
4069 4424
4070 string reply = String.Empty; 4425 string reply = String.Empty;
4071 4426
4072 switch (data) 4427 switch (data)
4073 { 4428 {
4074 case 1: // DATA_ONLINE (0|1) 4429 case 1: // DATA_ONLINE (0|1)
4075 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4430 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4076 reply = "1"; 4431 reply = "1";
4077 else 4432 else
4078 reply = "0"; 4433 reply = "0";
4079 break; 4434 break;
4080 case 2: // DATA_NAME (First Last) 4435 case 2: // DATA_NAME (First Last)
4081 reply = account.FirstName + " " + account.LastName; 4436 reply = account.FirstName + " " + account.LastName;
4082 break; 4437 break;
4083 case 3: // DATA_BORN (YYYY-MM-DD) 4438 case 3: // DATA_BORN (YYYY-MM-DD)
4084 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4439 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4085 born = born.AddSeconds(account.Created); 4440 born = born.AddSeconds(account.Created);
4086 reply = born.ToString("yyyy-MM-dd"); 4441 reply = born.ToString("yyyy-MM-dd");
4087 break; 4442 break;
4088 case 4: // DATA_RATING (0,0,0,0,0,0) 4443 case 4: // DATA_RATING (0,0,0,0,0,0)
4089 reply = "0,0,0,0,0,0"; 4444 reply = "0,0,0,0,0,0";
4090 break; 4445 break;
4091 case 7: // DATA_USERLEVEL (integer) 4446 case 8: // DATA_PAYINFO (0|1|2|3)
4092 reply = account.UserLevel.ToString(); 4447 reply = "0";
4093 break; 4448 break;
4094 case 8: // DATA_PAYINFO (0|1|2|3) 4449 default:
4095 reply = "0"; 4450 return UUID.Zero.ToString(); // Raise no event
4096 break; 4451 }
4097 default:
4098 return UUID.Zero.ToString(); // Raise no event
4099 }
4100 4452
4101 UUID rq = UUID.Random(); 4453 UUID rq = UUID.Random();
4102 4454
4103 UUID tid = AsyncCommands. 4455 UUID tid = AsyncCommands.
4104 DataserverPlugin.RegisterRequest(m_host.LocalId, 4456 DataserverPlugin.RegisterRequest(m_host.LocalId,
4105 m_item.ItemID, rq.ToString()); 4457 m_item.ItemID, rq.ToString());
4106 4458
4107 AsyncCommands. 4459 AsyncCommands.
4108 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4460 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4109 4461
4110 ScriptSleep(100); 4462 ScriptSleep(100);
4111 return tid.ToString(); 4463 return tid.ToString();
4464 }
4465 else
4466 {
4467 ShoutError("Invalid UUID passed to llRequestAgentData.");
4468 }
4469 return "";
4112 } 4470 }
4113 4471
4114 public LSL_String llRequestInventoryData(string name) 4472 public LSL_String llRequestInventoryData(string name)
4115 { 4473 {
4116 m_host.AddScriptLPS(1); 4474 m_host.AddScriptLPS(1);
4117 4475
4476 //Clone is thread safe
4118 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4477 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4119 4478
4120 foreach (TaskInventoryItem item in itemDictionary.Values) 4479 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4166,19 +4525,64 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4166 if (UUID.TryParse(agent, out agentId)) 4525 if (UUID.TryParse(agent, out agentId))
4167 { 4526 {
4168 ScenePresence presence = World.GetScenePresence(agentId); 4527 ScenePresence presence = World.GetScenePresence(agentId);
4169 if (presence != null) 4528 if (presence != null && presence.PresenceType != PresenceType.Npc)
4170 { 4529 {
4530 // agent must not be a god
4531 if (presence.UserLevel >= 200) return;
4532
4171 // agent must be over the owners land 4533 // agent must be over the owners land
4172 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4534 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4173 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4535 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4174 { 4536 {
4175 World.TeleportClientHome(agentId, presence.ControllingClient); 4537 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4538 {
4539 // They can't be teleported home for some reason
4540 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4541 if (regionInfo != null)
4542 {
4543 World.RequestTeleportLocation(
4544 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4545 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4546 }
4547 }
4176 } 4548 }
4177 } 4549 }
4178 } 4550 }
4179 ScriptSleep(5000); 4551 ScriptSleep(5000);
4180 } 4552 }
4181 4553
4554 public void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt)
4555 {
4556 m_host.AddScriptLPS(1);
4557 UUID agentId = new UUID();
4558 if (UUID.TryParse(agent, out agentId))
4559 {
4560 ScenePresence presence = World.GetScenePresence(agentId);
4561 if (presence != null && presence.PresenceType != PresenceType.Npc)
4562 {
4563 // agent must not be a god
4564 if (presence.GodLevel >= 200) return;
4565
4566 if (simname == String.Empty)
4567 simname = World.RegionInfo.RegionName;
4568
4569 // agent must be over the owners land
4570 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4571 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4572 {
4573 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);
4574 }
4575 else // or must be wearing the prim
4576 {
4577 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4578 {
4579 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);
4580 }
4581 }
4582 }
4583 }
4584 }
4585
4182 public void llTextBox(string agent, string message, int chatChannel) 4586 public void llTextBox(string agent, string message, int chatChannel)
4183 { 4587 {
4184 IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); 4588 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
@@ -4190,7 +4594,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4190 UUID av = new UUID(); 4594 UUID av = new UUID();
4191 if (!UUID.TryParse(agent,out av)) 4595 if (!UUID.TryParse(agent,out av))
4192 { 4596 {
4193 LSLError("First parameter to llDialog needs to be a key"); 4597 //LSLError("First parameter to llDialog needs to be a key");
4194 return; 4598 return;
4195 } 4599 }
4196 4600
@@ -4227,17 +4631,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4227 UUID soundId = UUID.Zero; 4631 UUID soundId = UUID.Zero;
4228 if (!UUID.TryParse(impact_sound, out soundId)) 4632 if (!UUID.TryParse(impact_sound, out soundId))
4229 { 4633 {
4230 lock (m_host.TaskInventory) 4634 m_host.TaskInventory.LockItemsForRead(true);
4635 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4231 { 4636 {
4232 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4637 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4233 { 4638 {
4234 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4639 soundId = item.AssetID;
4235 { 4640 break;
4236 soundId = item.AssetID;
4237 break;
4238 }
4239 } 4641 }
4240 } 4642 }
4643 m_host.TaskInventory.LockItemsForRead(false);
4241 } 4644 }
4242 m_host.CollisionSound = soundId; 4645 m_host.CollisionSound = soundId;
4243 m_host.CollisionSoundVolume = (float)impact_volume; 4646 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4277,6 +4680,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4277 UUID partItemID; 4680 UUID partItemID;
4278 foreach (SceneObjectPart part in parts) 4681 foreach (SceneObjectPart part in parts)
4279 { 4682 {
4683 //Clone is thread safe
4280 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4684 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4281 4685
4282 foreach (TaskInventoryItem item in itemsDictionary.Values) 4686 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4410,7 +4814,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4410 { 4814 {
4411 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4815 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4412 float distance_term = distance * distance * distance; // Script Energy 4816 float distance_term = distance * distance * distance; // Script Energy
4413 float pusher_mass = m_host.GetMass(); 4817 // use total object mass and not part
4818 float pusher_mass = m_host.ParentGroup.GetMass();
4414 4819
4415 float PUSH_ATTENUATION_DISTANCE = 17f; 4820 float PUSH_ATTENUATION_DISTANCE = 17f;
4416 float PUSH_ATTENUATION_SCALE = 5f; 4821 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4649,23 +5054,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4649 { 5054 {
4650 m_host.AddScriptLPS(1); 5055 m_host.AddScriptLPS(1);
4651 5056
4652 lock (m_host.TaskInventory) 5057 m_host.TaskInventory.LockItemsForRead(true);
5058 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4653 { 5059 {
4654 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5060 if (inv.Value.Name == name)
4655 { 5061 {
4656 if (inv.Value.Name == name) 5062 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4657 { 5063 {
4658 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5064 m_host.TaskInventory.LockItemsForRead(false);
4659 { 5065 return inv.Value.AssetID.ToString();
4660 return inv.Value.AssetID.ToString(); 5066 }
4661 } 5067 else
4662 else 5068 {
4663 { 5069 m_host.TaskInventory.LockItemsForRead(false);
4664 return UUID.Zero.ToString(); 5070 return UUID.Zero.ToString();
4665 }
4666 } 5071 }
4667 } 5072 }
4668 } 5073 }
5074 m_host.TaskInventory.LockItemsForRead(false);
4669 5075
4670 return UUID.Zero.ToString(); 5076 return UUID.Zero.ToString();
4671 } 5077 }
@@ -4799,7 +5205,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4799 public LSL_Vector llGetCenterOfMass() 5205 public LSL_Vector llGetCenterOfMass()
4800 { 5206 {
4801 m_host.AddScriptLPS(1); 5207 m_host.AddScriptLPS(1);
4802 Vector3 center = m_host.GetGeometricCenter(); 5208 Vector3 center = m_host.GetCenterOfMass();
4803 return new LSL_Vector(center.X,center.Y,center.Z); 5209 return new LSL_Vector(center.X,center.Y,center.Z);
4804 } 5210 }
4805 5211
@@ -4818,14 +5224,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4818 { 5224 {
4819 m_host.AddScriptLPS(1); 5225 m_host.AddScriptLPS(1);
4820 5226
4821 if (src == null) 5227 return src.Length;
4822 {
4823 return 0;
4824 }
4825 else
4826 {
4827 return src.Length;
4828 }
4829 } 5228 }
4830 5229
4831 public LSL_Integer llList2Integer(LSL_List src, int index) 5230 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4871,7 +5270,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4871 else if (src.Data[index] is LSL_Float) 5270 else if (src.Data[index] is LSL_Float)
4872 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5271 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4873 else if (src.Data[index] is LSL_String) 5272 else if (src.Data[index] is LSL_String)
4874 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5273 {
5274 string str = ((LSL_String) src.Data[index]).m_string;
5275 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5276 if (m != Match.Empty)
5277 {
5278 str = m.Value;
5279 double d = 0.0;
5280 if (!Double.TryParse(str, out d))
5281 return 0.0;
5282
5283 return d;
5284 }
5285 return 0.0;
5286 }
4875 return Convert.ToDouble(src.Data[index]); 5287 return Convert.ToDouble(src.Data[index]);
4876 } 5288 }
4877 catch (FormatException) 5289 catch (FormatException)
@@ -5144,7 +5556,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5144 } 5556 }
5145 } 5557 }
5146 } 5558 }
5147 else { 5559 else
5560 {
5148 object[] array = new object[src.Length]; 5561 object[] array = new object[src.Length];
5149 Array.Copy(src.Data, 0, array, 0, src.Length); 5562 Array.Copy(src.Data, 0, array, 0, src.Length);
5150 result = new LSL_List(array); 5563 result = new LSL_List(array);
@@ -5251,7 +5664,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5251 public LSL_Integer llGetRegionAgentCount() 5664 public LSL_Integer llGetRegionAgentCount()
5252 { 5665 {
5253 m_host.AddScriptLPS(1); 5666 m_host.AddScriptLPS(1);
5254 return new LSL_Integer(World.GetRootAgentCount()); 5667
5668 int count = 0;
5669 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5670 count++;
5671 });
5672
5673 return new LSL_Integer(count);
5255 } 5674 }
5256 5675
5257 public LSL_Vector llGetRegionCorner() 5676 public LSL_Vector llGetRegionCorner()
@@ -5531,6 +5950,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5531 flags |= ScriptBaseClass.AGENT_SITTING; 5950 flags |= ScriptBaseClass.AGENT_SITTING;
5532 } 5951 }
5533 5952
5953 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
5954 {
5955 flags |= ScriptBaseClass.AGENT_MALE;
5956 }
5957
5534 return flags; 5958 return flags;
5535 } 5959 }
5536 5960
@@ -5678,10 +6102,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5678 m_host.AddScriptLPS(1); 6102 m_host.AddScriptLPS(1);
5679 6103
5680 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6104 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5681 6105 if (parts.Count > 0)
5682 foreach (var part in parts)
5683 { 6106 {
5684 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6107 try
6108 {
6109 parts[0].ParentGroup.areUpdatesSuspended = true;
6110 foreach (var part in parts)
6111 {
6112 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6113 }
6114 }
6115 finally
6116 {
6117 parts[0].ParentGroup.areUpdatesSuspended = false;
6118 }
5685 } 6119 }
5686 } 6120 }
5687 6121
@@ -5733,13 +6167,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5733 6167
5734 if (m_host.OwnerID == land.LandData.OwnerID) 6168 if (m_host.OwnerID == land.LandData.OwnerID)
5735 { 6169 {
5736 World.TeleportClientHome(agentID, presence.ControllingClient); 6170 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6171 presence.TeleportWithMomentum(pos, null);
6172 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5737 } 6173 }
5738 } 6174 }
5739 } 6175 }
5740 ScriptSleep(5000); 6176 ScriptSleep(5000);
5741 } 6177 }
5742 6178
6179 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6180 {
6181 return ParseString2List(str, separators, in_spacers, false);
6182 }
6183
5743 public LSL_Integer llOverMyLand(string id) 6184 public LSL_Integer llOverMyLand(string id)
5744 { 6185 {
5745 m_host.AddScriptLPS(1); 6186 m_host.AddScriptLPS(1);
@@ -5804,8 +6245,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5804 UUID agentId = new UUID(); 6245 UUID agentId = new UUID();
5805 if (!UUID.TryParse(agent, out agentId)) 6246 if (!UUID.TryParse(agent, out agentId))
5806 return new LSL_Integer(0); 6247 return new LSL_Integer(0);
6248 if (agentId == m_host.GroupID)
6249 return new LSL_Integer(1);
5807 ScenePresence presence = World.GetScenePresence(agentId); 6250 ScenePresence presence = World.GetScenePresence(agentId);
5808 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6251 if (presence == null || presence.IsChildAgent) // Return false for child agents
5809 return new LSL_Integer(0); 6252 return new LSL_Integer(0);
5810 IClientAPI client = presence.ControllingClient; 6253 IClientAPI client = presence.ControllingClient;
5811 if (m_host.GroupID == client.ActiveGroupId) 6254 if (m_host.GroupID == client.ActiveGroupId)
@@ -5940,7 +6383,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5940 return m_host.ParentGroup.AttachmentPoint; 6383 return m_host.ParentGroup.AttachmentPoint;
5941 } 6384 }
5942 6385
5943 public LSL_Integer llGetFreeMemory() 6386 public virtual LSL_Integer llGetFreeMemory()
5944 { 6387 {
5945 m_host.AddScriptLPS(1); 6388 m_host.AddScriptLPS(1);
5946 // Make scripts designed for LSO happy 6389 // Make scripts designed for LSO happy
@@ -6057,7 +6500,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6057 SetParticleSystem(m_host, rules); 6500 SetParticleSystem(m_host, rules);
6058 } 6501 }
6059 6502
6060 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6503 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6504 {
6061 6505
6062 6506
6063 if (rules.Length == 0) 6507 if (rules.Length == 0)
@@ -6251,14 +6695,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6251 6695
6252 protected UUID GetTaskInventoryItem(string name) 6696 protected UUID GetTaskInventoryItem(string name)
6253 { 6697 {
6254 lock (m_host.TaskInventory) 6698 m_host.TaskInventory.LockItemsForRead(true);
6699 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6255 { 6700 {
6256 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6701 if (inv.Value.Name == name)
6257 { 6702 {
6258 if (inv.Value.Name == name) 6703 m_host.TaskInventory.LockItemsForRead(false);
6259 return inv.Key; 6704 return inv.Key;
6260 } 6705 }
6261 } 6706 }
6707 m_host.TaskInventory.LockItemsForRead(false);
6262 6708
6263 return UUID.Zero; 6709 return UUID.Zero;
6264 } 6710 }
@@ -6296,16 +6742,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6296 if (folderID == UUID.Zero) 6742 if (folderID == UUID.Zero)
6297 return; 6743 return;
6298 6744
6299 byte[] bucket = new byte[17]; 6745 byte[] bucket = new byte[1];
6300 bucket[0] = (byte)AssetType.Folder; 6746 bucket[0] = (byte)AssetType.Folder;
6301 byte[] objBytes = folderID.GetBytes(); 6747 //byte[] objBytes = folderID.GetBytes();
6302 Array.Copy(objBytes, 0, bucket, 1, 16); 6748 //Array.Copy(objBytes, 0, bucket, 1, 16);
6303 6749
6304 GridInstantMessage msg = new GridInstantMessage(World, 6750 GridInstantMessage msg = new GridInstantMessage(World,
6305 m_host.UUID, m_host.Name+", an object owned by "+ 6751 m_host.OwnerID, m_host.Name, destID,
6306 resolveName(m_host.OwnerID)+",", destID, 6752 (byte)InstantMessageDialog.TaskInventoryOffered,
6307 (byte)InstantMessageDialog.InventoryOffered, 6753 false, category+". "+m_host.Name+" is located at "+
6308 false, category+"\n"+m_host.Name+" is located at "+
6309 World.RegionInfo.RegionName+" "+ 6754 World.RegionInfo.RegionName+" "+
6310 m_host.AbsolutePosition.ToString(), 6755 m_host.AbsolutePosition.ToString(),
6311 folderID, true, m_host.AbsolutePosition, 6756 folderID, true, m_host.AbsolutePosition,
@@ -6543,13 +6988,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6543 UUID av = new UUID(); 6988 UUID av = new UUID();
6544 if (!UUID.TryParse(avatar,out av)) 6989 if (!UUID.TryParse(avatar,out av))
6545 { 6990 {
6546 LSLError("First parameter to llDialog needs to be a key"); 6991 //LSLError("First parameter to llDialog needs to be a key");
6547 return; 6992 return;
6548 } 6993 }
6549 if (buttons.Length < 1) 6994 if (buttons.Length < 1)
6550 { 6995 {
6551 LSLError("No less than 1 button can be shown"); 6996 buttons.Add("OK");
6552 return;
6553 } 6997 }
6554 if (buttons.Length > 12) 6998 if (buttons.Length > 12)
6555 { 6999 {
@@ -6566,7 +7010,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6566 } 7010 }
6567 if (buttons.Data[i].ToString().Length > 24) 7011 if (buttons.Data[i].ToString().Length > 24)
6568 { 7012 {
6569 LSLError("button label cannot be longer than 24 characters"); 7013 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6570 return; 7014 return;
6571 } 7015 }
6572 buts[i] = buttons.Data[i].ToString(); 7016 buts[i] = buttons.Data[i].ToString();
@@ -6625,22 +7069,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6625 } 7069 }
6626 7070
6627 // copy the first script found with this inventory name 7071 // copy the first script found with this inventory name
6628 lock (m_host.TaskInventory) 7072 TaskInventoryItem scriptItem = null;
7073 m_host.TaskInventory.LockItemsForRead(true);
7074 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6629 { 7075 {
6630 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 7076 if (inv.Value.Name == name)
6631 { 7077 {
6632 if (inv.Value.Name == name) 7078 // make sure the object is a script
7079 if (10 == inv.Value.Type)
6633 { 7080 {
6634 // make sure the object is a script 7081 found = true;
6635 if (10 == inv.Value.Type) 7082 srcId = inv.Key;
6636 { 7083 scriptItem = inv.Value;
6637 found = true; 7084 break;
6638 srcId = inv.Key;
6639 break;
6640 }
6641 } 7085 }
6642 } 7086 }
6643 } 7087 }
7088 m_host.TaskInventory.LockItemsForRead(false);
6644 7089
6645 if (!found) 7090 if (!found)
6646 { 7091 {
@@ -6648,9 +7093,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6648 return; 7093 return;
6649 } 7094 }
6650 7095
6651 // the rest of the permission checks are done in RezScript, so check the pin there as well 7096 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6652 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7097 if (dest != null)
7098 {
7099 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7100 {
7101 // the rest of the permission checks are done in RezScript, so check the pin there as well
7102 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6653 7103
7104 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7105 m_host.Inventory.RemoveInventoryItem(srcId);
7106 }
7107 }
6654 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7108 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6655 ScriptSleep(3000); 7109 ScriptSleep(3000);
6656 } 7110 }
@@ -6713,19 +7167,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6713 public LSL_String llMD5String(string src, int nonce) 7167 public LSL_String llMD5String(string src, int nonce)
6714 { 7168 {
6715 m_host.AddScriptLPS(1); 7169 m_host.AddScriptLPS(1);
6716 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7170 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6717 } 7171 }
6718 7172
6719 public LSL_String llSHA1String(string src) 7173 public LSL_String llSHA1String(string src)
6720 { 7174 {
6721 m_host.AddScriptLPS(1); 7175 m_host.AddScriptLPS(1);
6722 return Util.SHA1Hash(src).ToLower(); 7176 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6723 } 7177 }
6724 7178
6725 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7179 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6726 { 7180 {
6727 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7181 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6728 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7182 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7183 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7184 return shapeBlock;
6729 7185
6730 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7186 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6731 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7187 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6830,6 +7286,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6830 // Prim type box, cylinder and prism. 7286 // Prim type box, cylinder and prism.
6831 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) 7287 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)
6832 { 7288 {
7289 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7290 return;
7291
6833 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7292 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6834 ObjectShapePacket.ObjectDataBlock shapeBlock; 7293 ObjectShapePacket.ObjectDataBlock shapeBlock;
6835 7294
@@ -6883,6 +7342,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6883 // Prim type sphere. 7342 // Prim type sphere.
6884 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7343 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6885 { 7344 {
7345 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7346 return;
7347
6886 ObjectShapePacket.ObjectDataBlock shapeBlock; 7348 ObjectShapePacket.ObjectDataBlock shapeBlock;
6887 7349
6888 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7350 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6924,6 +7386,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6924 // Prim type torus, tube and ring. 7386 // Prim type torus, tube and ring.
6925 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) 7387 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)
6926 { 7388 {
7389 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7390 return;
7391
6927 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7392 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6928 ObjectShapePacket.ObjectDataBlock shapeBlock; 7393 ObjectShapePacket.ObjectDataBlock shapeBlock;
6929 7394
@@ -7059,6 +7524,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7059 // Prim type sculpt. 7524 // Prim type sculpt.
7060 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7525 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7061 { 7526 {
7527 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7528 return;
7529
7062 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7530 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7063 UUID sculptId; 7531 UUID sculptId;
7064 7532
@@ -7083,7 +7551,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7083 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7551 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7084 { 7552 {
7085 // default 7553 // default
7086 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7554 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7087 } 7555 }
7088 7556
7089 part.Shape.SetSculptProperties((byte)type, sculptId); 7557 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7099,32 +7567,149 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7099 ScriptSleep(200); 7567 ScriptSleep(200);
7100 } 7568 }
7101 7569
7102 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7570 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7103 { 7571 {
7104 m_host.AddScriptLPS(1); 7572 m_host.AddScriptLPS(1);
7105 7573
7106 setLinkPrimParams(linknumber, rules); 7574 setLinkPrimParams(linknumber, rules);
7575 }
7107 7576
7108 ScriptSleep(200); 7577 private void setLinkPrimParams(int linknumber, LSL_List rules)
7578 {
7579 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7580 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7581 if (parts.Count>0)
7582 {
7583 try
7584 {
7585 parts[0].ParentGroup.areUpdatesSuspended = true;
7586 foreach (SceneObjectPart part in parts)
7587 SetPrimParams(part, rules);
7588 }
7589 finally
7590 {
7591 parts[0].ParentGroup.areUpdatesSuspended = false;
7592 }
7593 }
7594 if (avatars.Count > 0)
7595 {
7596 foreach (ScenePresence avatar in avatars)
7597 SetPrimParams(avatar, rules);
7598 }
7109 } 7599 }
7110 7600
7111 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7601 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7602 float material_density, float material_friction,
7603 float material_restitution, float material_gravity_modifier)
7112 { 7604 {
7113 m_host.AddScriptLPS(1); 7605 ExtraPhysicsData physdata = new ExtraPhysicsData();
7606 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7607 physdata.Density = part.Density;
7608 physdata.Friction = part.Friction;
7609 physdata.Bounce = part.Bounciness;
7610 physdata.GravitationModifier = part.GravityModifier;
7114 7611
7115 setLinkPrimParams(linknumber, rules); 7612 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7613 physdata.Density = material_density;
7614 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7615 physdata.Friction = material_friction;
7616 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7617 physdata.Bounce = material_restitution;
7618 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7619 physdata.GravitationModifier = material_gravity_modifier;
7620
7621 part.UpdateExtraPhysics(physdata);
7116 } 7622 }
7117 7623
7118 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7624 public void llSetPhysicsMaterial(int material_bits,
7625 float material_gravity_modifier, float material_restitution,
7626 float material_friction, float material_density)
7119 { 7627 {
7120 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7628 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7629 }
7121 7630
7122 foreach (SceneObjectPart part in parts) 7631 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7123 SetPrimParams(part, rules); 7632 {
7633 llSetLinkPrimitiveParamsFast(linknumber, rules);
7634 ScriptSleep(200);
7635 }
7636
7637 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7638 {
7639 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7640 //We only support PRIM_POSITION and PRIM_ROTATION
7641
7642 int idx = 0;
7643
7644 while (idx < rules.Length)
7645 {
7646 int code = rules.GetLSLIntegerItem(idx++);
7647
7648 int remain = rules.Length - idx;
7649
7650 switch (code)
7651 {
7652 case (int)ScriptBaseClass.PRIM_POSITION:
7653 {
7654 if (remain < 1)
7655 return;
7656 LSL_Vector v;
7657 v = rules.GetVector3Item(idx++);
7658
7659 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7660 if (part == null)
7661 break;
7662
7663 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7664 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7665 if (llGetLinkNumber() > 1)
7666 {
7667 localRot = llGetLocalRot();
7668 localPos = llGetLocalPos();
7669 }
7670
7671 v -= localPos;
7672 v /= localRot;
7673
7674 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
7675
7676 v = v + 2 * sitOffset;
7677
7678 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7679 av.SendAvatarDataToAllAgents();
7680
7681 }
7682 break;
7683
7684 case (int)ScriptBaseClass.PRIM_ROTATION:
7685 {
7686 if (remain < 1)
7687 return;
7688
7689 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7690 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7691 if (llGetLinkNumber() > 1)
7692 {
7693 localRot = llGetLocalRot();
7694 localPos = llGetLocalPos();
7695 }
7696
7697 LSL_Rotation r;
7698 r = rules.GetQuaternionItem(idx++);
7699 r = r * llGetRootRotation() / localRot;
7700 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7701 av.SendAvatarDataToAllAgents();
7702 }
7703 break;
7704 }
7705 }
7124 } 7706 }
7125 7707
7126 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7708 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7127 { 7709 {
7710 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7711 return;
7712
7128 int idx = 0; 7713 int idx = 0;
7129 7714
7130 bool positionChanged = false; 7715 bool positionChanged = false;
@@ -7446,6 +8031,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7446 part.ScriptSetPhysicsStatus(physics); 8031 part.ScriptSetPhysicsStatus(physics);
7447 break; 8032 break;
7448 8033
8034 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
8035 if (remain < 1)
8036 return;
8037
8038 int shape_type = rules.GetLSLIntegerItem(idx++);
8039
8040 ExtraPhysicsData physdata = new ExtraPhysicsData();
8041 physdata.Density = part.Density;
8042 physdata.Bounce = part.Bounciness;
8043 physdata.GravitationModifier = part.GravityModifier;
8044 physdata.PhysShapeType = (PhysShapeType)shape_type;
8045
8046 part.UpdateExtraPhysics(physdata);
8047
8048 break;
8049
8050 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8051 if (remain < 5)
8052 return;
8053
8054 int material_bits = rules.GetLSLIntegerItem(idx++);
8055 float material_density = (float)rules.GetLSLFloatItem(idx++);
8056 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8057 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8058 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8059
8060 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8061
8062 break;
8063
7449 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8064 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7450 if (remain < 1) 8065 if (remain < 1)
7451 return; 8066 return;
@@ -7519,7 +8134,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7519 if (part.ParentGroup.RootPart == part) 8134 if (part.ParentGroup.RootPart == part)
7520 { 8135 {
7521 SceneObjectGroup parent = part.ParentGroup; 8136 SceneObjectGroup parent = part.ParentGroup;
7522 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8137 Util.FireAndForget(delegate(object x) {
8138 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8139 });
7523 } 8140 }
7524 else 8141 else
7525 { 8142 {
@@ -7530,6 +8147,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7530 } 8147 }
7531 } 8148 }
7532 } 8149 }
8150
8151 if (positionChanged)
8152 {
8153 if (part.ParentGroup.RootPart == part)
8154 {
8155 SceneObjectGroup parent = part.ParentGroup;
8156 Util.FireAndForget(delegate(object x) {
8157 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8158 });
8159 }
8160 else
8161 {
8162 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8163 SceneObjectGroup parent = part.ParentGroup;
8164 parent.HasGroupChanged = true;
8165 parent.ScheduleGroupForTerseUpdate();
8166 }
8167 }
7533 } 8168 }
7534 8169
7535 public LSL_String llStringToBase64(string str) 8170 public LSL_String llStringToBase64(string str)
@@ -7690,13 +8325,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7690 public LSL_Integer llGetNumberOfPrims() 8325 public LSL_Integer llGetNumberOfPrims()
7691 { 8326 {
7692 m_host.AddScriptLPS(1); 8327 m_host.AddScriptLPS(1);
7693 int avatarCount = 0; 8328 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7694 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8329
7695 {
7696 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
7697 avatarCount++;
7698 });
7699
7700 return m_host.ParentGroup.PrimCount + avatarCount; 8330 return m_host.ParentGroup.PrimCount + avatarCount;
7701 } 8331 }
7702 8332
@@ -7712,55 +8342,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7712 m_host.AddScriptLPS(1); 8342 m_host.AddScriptLPS(1);
7713 UUID objID = UUID.Zero; 8343 UUID objID = UUID.Zero;
7714 LSL_List result = new LSL_List(); 8344 LSL_List result = new LSL_List();
8345
8346 // If the ID is not valid, return null result
7715 if (!UUID.TryParse(obj, out objID)) 8347 if (!UUID.TryParse(obj, out objID))
7716 { 8348 {
7717 result.Add(new LSL_Vector()); 8349 result.Add(new LSL_Vector());
7718 result.Add(new LSL_Vector()); 8350 result.Add(new LSL_Vector());
7719 return result; 8351 return result;
7720 } 8352 }
8353
8354 // Check if this is an attached prim. If so, replace
8355 // the UUID with the avatar UUID and report it's bounding box
8356 SceneObjectPart part = World.GetSceneObjectPart(objID);
8357 if (part != null && part.ParentGroup.IsAttachment)
8358 objID = part.ParentGroup.AttachedAvatar;
8359
8360 // Find out if this is an avatar ID. If so, return it's box
7721 ScenePresence presence = World.GetScenePresence(objID); 8361 ScenePresence presence = World.GetScenePresence(objID);
7722 if (presence != null) 8362 if (presence != null)
7723 { 8363 {
7724 if (presence.ParentID == 0) // not sat on an object 8364 // As per LSL Wiki, there is no difference between sitting
8365 // and standing avatar since server 1.36
8366 LSL_Vector lower;
8367 LSL_Vector upper;
8368 if (presence.Animator.Animations.DefaultAnimation.AnimID
8369 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7725 { 8370 {
7726 LSL_Vector lower; 8371 // This is for ground sitting avatars
7727 LSL_Vector upper; 8372 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7728 if (presence.Animator.Animations.DefaultAnimation.AnimID 8373 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7729 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8374 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7730 {
7731 // This is for ground sitting avatars
7732 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7733 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7734 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7735 }
7736 else
7737 {
7738 // This is for standing/flying avatars
7739 float height = presence.Appearance.AvatarHeight / 2.0f;
7740 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7741 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7742 }
7743 result.Add(lower);
7744 result.Add(upper);
7745 return result;
7746 } 8375 }
7747 else 8376 else
7748 { 8377 {
7749 // sitting on an object so we need the bounding box of that 8378 // This is for standing/flying avatars
7750 // which should include the avatar so set the UUID to the 8379 float height = presence.Appearance.AvatarHeight / 2.0f;
7751 // UUID of the object the avatar is sat on and allow it to fall through 8380 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7752 // to processing an object 8381 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7753 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7754 objID = p.UUID;
7755 } 8382 }
8383
8384 // Adjust to the documented error offsets (see LSL Wiki)
8385 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8386 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8387
8388 if (lower.x > upper.x)
8389 lower.x = upper.x;
8390 if (lower.y > upper.y)
8391 lower.y = upper.y;
8392 if (lower.z > upper.z)
8393 lower.z = upper.z;
8394
8395 result.Add(lower);
8396 result.Add(upper);
8397 return result;
7756 } 8398 }
7757 SceneObjectPart part = World.GetSceneObjectPart(objID); 8399
8400 part = World.GetSceneObjectPart(objID);
7758 // Currently only works for single prims without a sitting avatar 8401 // Currently only works for single prims without a sitting avatar
7759 if (part != null) 8402 if (part != null)
7760 { 8403 {
7761 Vector3 halfSize = part.Scale / 2.0f; 8404 float minX;
7762 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8405 float maxX;
7763 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8406 float minY;
8407 float maxY;
8408 float minZ;
8409 float maxZ;
8410
8411 // This BBox is in sim coordinates, with the offset being
8412 // a contained point.
8413 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8414 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8415
8416 minX -= offsets[0].X;
8417 maxX -= offsets[0].X;
8418 minY -= offsets[0].Y;
8419 maxY -= offsets[0].Y;
8420 minZ -= offsets[0].Z;
8421 maxZ -= offsets[0].Z;
8422
8423 LSL_Vector lower;
8424 LSL_Vector upper;
8425
8426 // Adjust to the documented error offsets (see LSL Wiki)
8427 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8428 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8429
8430 if (lower.x > upper.x)
8431 lower.x = upper.x;
8432 if (lower.y > upper.y)
8433 lower.y = upper.y;
8434 if (lower.z > upper.z)
8435 lower.z = upper.z;
8436
7764 result.Add(lower); 8437 result.Add(lower);
7765 result.Add(upper); 8438 result.Add(upper);
7766 return result; 8439 return result;
@@ -7774,7 +8447,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7774 8447
7775 public LSL_Vector llGetGeometricCenter() 8448 public LSL_Vector llGetGeometricCenter()
7776 { 8449 {
7777 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 8450 Vector3 tmp = m_host.GetGeometricCenter();
8451 return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
7778 } 8452 }
7779 8453
7780 public LSL_List llGetPrimitiveParams(LSL_List rules) 8454 public LSL_List llGetPrimitiveParams(LSL_List rules)
@@ -7840,13 +8514,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7840 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8514 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7841 part.AbsolutePosition.Y, 8515 part.AbsolutePosition.Y,
7842 part.AbsolutePosition.Z); 8516 part.AbsolutePosition.Z);
7843 // For some reason, the part.AbsolutePosition.* values do not change if the
7844 // linkset is rotated; they always reflect the child prim's world position
7845 // as though the linkset is unrotated. This is incompatible behavior with SL's
7846 // implementation, so will break scripts imported from there (not to mention it
7847 // makes it more difficult to determine a child prim's actual inworld position).
7848 if (part.ParentID != 0)
7849 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7850 res.Add(v); 8517 res.Add(v);
7851 break; 8518 break;
7852 8519
@@ -8017,56 +8684,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8017 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8684 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8018 if (remain < 1) 8685 if (remain < 1)
8019 return res; 8686 return res;
8020 8687 face = (int)rules.GetLSLIntegerItem(idx++);
8021 face=(int)rules.GetLSLIntegerItem(idx++);
8022 8688
8023 tex = part.Shape.Textures; 8689 tex = part.Shape.Textures;
8690 int shiny;
8024 if (face == ScriptBaseClass.ALL_SIDES) 8691 if (face == ScriptBaseClass.ALL_SIDES)
8025 { 8692 {
8026 for (face = 0; face < GetNumberOfSides(part); face++) 8693 for (face = 0; face < GetNumberOfSides(part); face++)
8027 { 8694 {
8028 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8695 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8029 // Convert Shininess to PRIM_SHINY_* 8696 if (shinyness == Shininess.High)
8030 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8697 {
8031 // PRIM_BUMP_* 8698 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8032 res.Add(new LSL_Integer((int)texface.Bump)); 8699 }
8700 else if (shinyness == Shininess.Medium)
8701 {
8702 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8703 }
8704 else if (shinyness == Shininess.Low)
8705 {
8706 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8707 }
8708 else
8709 {
8710 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8711 }
8712 res.Add(new LSL_Integer(shiny));
8713 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8033 } 8714 }
8034 } 8715 }
8035 else 8716 else
8036 { 8717 {
8037 if (face >= 0 && face < GetNumberOfSides(part)) 8718 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8719 if (shinyness == Shininess.High)
8038 { 8720 {
8039 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8721 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8040 // Convert Shininess to PRIM_SHINY_* 8722 }
8041 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8723 else if (shinyness == Shininess.Medium)
8042 // PRIM_BUMP_* 8724 {
8043 res.Add(new LSL_Integer((int)texface.Bump)); 8725 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8726 }
8727 else if (shinyness == Shininess.Low)
8728 {
8729 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8044 } 8730 }
8731 else
8732 {
8733 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8734 }
8735 res.Add(new LSL_Integer(shiny));
8736 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8045 } 8737 }
8046 break; 8738 break;
8047 8739
8048 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8740 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8049 if (remain < 1) 8741 if (remain < 1)
8050 return res; 8742 return res;
8051 8743 face = (int)rules.GetLSLIntegerItem(idx++);
8052 face=(int)rules.GetLSLIntegerItem(idx++);
8053 8744
8054 tex = part.Shape.Textures; 8745 tex = part.Shape.Textures;
8746 int fullbright;
8055 if (face == ScriptBaseClass.ALL_SIDES) 8747 if (face == ScriptBaseClass.ALL_SIDES)
8056 { 8748 {
8057 for (face = 0; face < GetNumberOfSides(part); face++) 8749 for (face = 0; face < GetNumberOfSides(part); face++)
8058 { 8750 {
8059 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8751 if (tex.GetFace((uint)face).Fullbright == true)
8060 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8752 {
8753 fullbright = ScriptBaseClass.TRUE;
8754 }
8755 else
8756 {
8757 fullbright = ScriptBaseClass.FALSE;
8758 }
8759 res.Add(new LSL_Integer(fullbright));
8061 } 8760 }
8062 } 8761 }
8063 else 8762 else
8064 { 8763 {
8065 if (face >= 0 && face < GetNumberOfSides(part)) 8764 if (tex.GetFace((uint)face).Fullbright == true)
8066 { 8765 {
8067 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8766 fullbright = ScriptBaseClass.TRUE;
8068 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
8069 } 8767 }
8768 else
8769 {
8770 fullbright = ScriptBaseClass.FALSE;
8771 }
8772 res.Add(new LSL_Integer(fullbright));
8070 } 8773 }
8071 break; 8774 break;
8072 8775
@@ -8088,27 +8791,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8088 break; 8791 break;
8089 8792
8090 case (int)ScriptBaseClass.PRIM_TEXGEN: 8793 case (int)ScriptBaseClass.PRIM_TEXGEN:
8794 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8091 if (remain < 1) 8795 if (remain < 1)
8092 return res; 8796 return res;
8093 8797 face = (int)rules.GetLSLIntegerItem(idx++);
8094 face=(int)rules.GetLSLIntegerItem(idx++);
8095 8798
8096 tex = part.Shape.Textures; 8799 tex = part.Shape.Textures;
8097 if (face == ScriptBaseClass.ALL_SIDES) 8800 if (face == ScriptBaseClass.ALL_SIDES)
8098 { 8801 {
8099 for (face = 0; face < GetNumberOfSides(part); face++) 8802 for (face = 0; face < GetNumberOfSides(part); face++)
8100 { 8803 {
8101 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8804 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8102 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8805 {
8103 res.Add(new LSL_Integer((uint)texgen >> 1)); 8806 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8807 }
8808 else
8809 {
8810 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8811 }
8104 } 8812 }
8105 } 8813 }
8106 else 8814 else
8107 { 8815 {
8108 if (face >= 0 && face < GetNumberOfSides(part)) 8816 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8109 { 8817 {
8110 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8818 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8111 res.Add(new LSL_Integer((uint)texgen >> 1)); 8819 }
8820 else
8821 {
8822 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8112 } 8823 }
8113 } 8824 }
8114 break; 8825 break;
@@ -8131,28 +8842,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8131 case (int)ScriptBaseClass.PRIM_GLOW: 8842 case (int)ScriptBaseClass.PRIM_GLOW:
8132 if (remain < 1) 8843 if (remain < 1)
8133 return res; 8844 return res;
8134 8845 face = (int)rules.GetLSLIntegerItem(idx++);
8135 face=(int)rules.GetLSLIntegerItem(idx++);
8136 8846
8137 tex = part.Shape.Textures; 8847 tex = part.Shape.Textures;
8848 float primglow;
8138 if (face == ScriptBaseClass.ALL_SIDES) 8849 if (face == ScriptBaseClass.ALL_SIDES)
8139 { 8850 {
8140 for (face = 0; face < GetNumberOfSides(part); face++) 8851 for (face = 0; face < GetNumberOfSides(part); face++)
8141 { 8852 {
8142 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8853 primglow = tex.GetFace((uint)face).Glow;
8143 res.Add(new LSL_Float(texface.Glow)); 8854 res.Add(new LSL_Float(primglow));
8144 } 8855 }
8145 } 8856 }
8146 else 8857 else
8147 { 8858 {
8148 if (face >= 0 && face < GetNumberOfSides(part)) 8859 primglow = tex.GetFace((uint)face).Glow;
8149 { 8860 res.Add(new LSL_Float(primglow));
8150 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8151 res.Add(new LSL_Float(texface.Glow));
8152 }
8153 } 8861 }
8154 break; 8862 break;
8155
8156 case (int)ScriptBaseClass.PRIM_TEXT: 8863 case (int)ScriptBaseClass.PRIM_TEXT:
8157 Color4 textColor = part.GetTextColor(); 8864 Color4 textColor = part.GetTextColor();
8158 res.Add(new LSL_String(part.Text)); 8865 res.Add(new LSL_String(part.Text));
@@ -8764,8 +9471,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8764 // The function returns an ordered list 9471 // The function returns an ordered list
8765 // representing the tokens found in the supplied 9472 // representing the tokens found in the supplied
8766 // sources string. If two successive tokenizers 9473 // sources string. If two successive tokenizers
8767 // are encountered, then a NULL entry is added 9474 // are encountered, then a null-string entry is
8768 // to the list. 9475 // added to the list.
8769 // 9476 //
8770 // It is a precondition that the source and 9477 // It is a precondition that the source and
8771 // toekizer lisst are non-null. If they are null, 9478 // toekizer lisst are non-null. If they are null,
@@ -8773,7 +9480,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8773 // while their lengths are being determined. 9480 // while their lengths are being determined.
8774 // 9481 //
8775 // A small amount of working memoryis required 9482 // A small amount of working memoryis required
8776 // of approximately 8*#tokenizers. 9483 // of approximately 8*#tokenizers + 8*srcstrlen.
8777 // 9484 //
8778 // There are many ways in which this function 9485 // There are many ways in which this function
8779 // can be implemented, this implementation is 9486 // can be implemented, this implementation is
@@ -8789,155 +9496,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8789 // and eliminates redundant tokenizers as soon 9496 // and eliminates redundant tokenizers as soon
8790 // as is possible. 9497 // as is possible.
8791 // 9498 //
8792 // The implementation tries to avoid any copying 9499 // The implementation tries to minimize temporary
8793 // of arrays or other objects. 9500 // garbage generation.
8794 // </remarks> 9501 // </remarks>
8795 9502
8796 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9503 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8797 { 9504 {
8798 int beginning = 0; 9505 return ParseString2List(src, separators, spacers, true);
8799 int srclen = src.Length; 9506 }
8800 int seplen = separators.Length;
8801 object[] separray = separators.Data;
8802 int spclen = spacers.Length;
8803 object[] spcarray = spacers.Data;
8804 int mlen = seplen+spclen;
8805
8806 int[] offset = new int[mlen+1];
8807 bool[] active = new bool[mlen];
8808
8809 int best;
8810 int j;
8811
8812 // Initial capacity reduces resize cost
8813 9507
8814 LSL_List tokens = new LSL_List(); 9508 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9509 {
9510 int srclen = src.Length;
9511 int seplen = separators.Length;
9512 object[] separray = separators.Data;
9513 int spclen = spacers.Length;
9514 object[] spcarray = spacers.Data;
9515 int dellen = 0;
9516 string[] delarray = new string[seplen+spclen];
8815 9517
8816 // All entries are initially valid 9518 int outlen = 0;
9519 string[] outarray = new string[srclen*2+1];
8817 9520
8818 for (int i = 0; i < mlen; i++) 9521 int i, j;
8819 active[i] = true; 9522 string d;
8820 9523
8821 offset[mlen] = srclen; 9524 m_host.AddScriptLPS(1);
8822 9525
8823 while (beginning < srclen) 9526 /*
9527 * Convert separator and spacer lists to C# strings.
9528 * Also filter out null strings so we don't hang.
9529 */
9530 for (i = 0; i < seplen; i ++)
8824 { 9531 {
9532 d = separray[i].ToString();
9533 if (d.Length > 0)
9534 {
9535 delarray[dellen++] = d;
9536 }
9537 }
9538 seplen = dellen;
8825 9539
8826 best = mlen; // as bad as it gets 9540 for (i = 0; i < spclen; i ++)
9541 {
9542 d = spcarray[i].ToString();
9543 if (d.Length > 0)
9544 {
9545 delarray[dellen++] = d;
9546 }
9547 }
8827 9548
8828 // Scan for separators 9549 /*
9550 * Scan through source string from beginning to end.
9551 */
9552 for (i = 0;;)
9553 {
8829 9554
8830 for (j = 0; j < seplen; j++) 9555 /*
9556 * Find earliest delimeter in src starting at i (if any).
9557 */
9558 int earliestDel = -1;
9559 int earliestSrc = srclen;
9560 string earliestStr = null;
9561 for (j = 0; j < dellen; j ++)
8831 { 9562 {
8832 if (separray[j].ToString() == String.Empty) 9563 d = delarray[j];
8833 active[j] = false; 9564 if (d != null)
8834
8835 if (active[j])
8836 { 9565 {
8837 // scan all of the markers 9566 int index = src.IndexOf(d, i);
8838 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9567 if (index < 0)
8839 { 9568 {
8840 // not present at all 9569 delarray[j] = null; // delim nowhere in src, don't check it anymore
8841 active[j] = false;
8842 } 9570 }
8843 else 9571 else if (index < earliestSrc)
8844 { 9572 {
8845 // present and correct 9573 earliestSrc = index; // where delimeter starts in source string
8846 if (offset[j] < offset[best]) 9574 earliestDel = j; // where delimeter is in delarray[]
8847 { 9575 earliestStr = d; // the delimeter string from delarray[]
8848 // closest so far 9576 if (index == i) break; // can't do any better than found at beg of string
8849 best = j;
8850 if (offset[best] == beginning)
8851 break;
8852 }
8853 } 9577 }
8854 } 9578 }
8855 } 9579 }
8856 9580
8857 // Scan for spacers 9581 /*
8858 9582 * Output source string starting at i through start of earliest delimeter.
8859 if (offset[best] != beginning) 9583 */
9584 if (keepNulls || (earliestSrc > i))
8860 { 9585 {
8861 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9586 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8862 {
8863 if (spcarray[j-seplen].ToString() == String.Empty)
8864 active[j] = false;
8865
8866 if (active[j])
8867 {
8868 // scan all of the markers
8869 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8870 {
8871 // not present at all
8872 active[j] = false;
8873 }
8874 else
8875 {
8876 // present and correct
8877 if (offset[j] < offset[best])
8878 {
8879 // closest so far
8880 best = j;
8881 }
8882 }
8883 }
8884 }
8885 } 9587 }
8886 9588
8887 // This is the normal exit from the scanning loop 9589 /*
9590 * If no delimeter found at or after i, we're done scanning.
9591 */
9592 if (earliestDel < 0) break;
8888 9593
8889 if (best == mlen) 9594 /*
9595 * If delimeter was a spacer, output the spacer.
9596 */
9597 if (earliestDel >= seplen)
8890 { 9598 {
8891 // no markers were found on this pass 9599 outarray[outlen++] = earliestStr;
8892 // so we're pretty much done
8893 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8894 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8895 break;
8896 } 9600 }
8897 9601
8898 // Otherwise we just add the newly delimited token 9602 /*
8899 // and recalculate where the search should continue. 9603 * Look at rest of src string following delimeter.
8900 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9604 */
8901 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9605 i = earliestSrc + earliestStr.Length;
8902
8903 if (best < seplen)
8904 {
8905 beginning = offset[best] + (separray[best].ToString()).Length;
8906 }
8907 else
8908 {
8909 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8910 string str = spcarray[best - seplen].ToString();
8911 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8912 tokens.Add(new LSL_String(str));
8913 }
8914 } 9606 }
8915 9607
8916 // This an awkward an not very intuitive boundary case. If the 9608 /*
8917 // last substring is a tokenizer, then there is an implied trailing 9609 * Make up an exact-sized output array suitable for an LSL_List object.
8918 // null list entry. Hopefully the single comparison will not be too 9610 */
8919 // arduous. Alternatively the 'break' could be replced with a return 9611 object[] outlist = new object[outlen];
8920 // but that's shabby programming. 9612 for (i = 0; i < outlen; i ++)
8921
8922 if ((beginning == srclen) && (keepNulls))
8923 { 9613 {
8924 if (srclen != 0) 9614 outlist[i] = new LSL_String(outarray[i]);
8925 tokens.Add(new LSL_String(""));
8926 } 9615 }
8927 9616 return new LSL_List(outlist);
8928 return tokens;
8929 }
8930
8931 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8932 {
8933 m_host.AddScriptLPS(1);
8934 return this.ParseString(src, separators, spacers, false);
8935 }
8936
8937 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8938 {
8939 m_host.AddScriptLPS(1);
8940 return this.ParseString(src, separators, spacers, true);
8941 } 9617 }
8942 9618
8943 public LSL_Integer llGetObjectPermMask(int mask) 9619 public LSL_Integer llGetObjectPermMask(int mask)
@@ -9014,28 +9690,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9014 { 9690 {
9015 m_host.AddScriptLPS(1); 9691 m_host.AddScriptLPS(1);
9016 9692
9017 lock (m_host.TaskInventory) 9693 m_host.TaskInventory.LockItemsForRead(true);
9694 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9018 { 9695 {
9019 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9696 if (inv.Value.Name == item)
9020 { 9697 {
9021 if (inv.Value.Name == item) 9698 m_host.TaskInventory.LockItemsForRead(false);
9699 switch (mask)
9022 { 9700 {
9023 switch (mask) 9701 case 0:
9024 { 9702 return (int)inv.Value.BasePermissions;
9025 case 0: 9703 case 1:
9026 return (int)inv.Value.BasePermissions; 9704 return (int)inv.Value.CurrentPermissions;
9027 case 1: 9705 case 2:
9028 return (int)inv.Value.CurrentPermissions; 9706 return (int)inv.Value.GroupPermissions;
9029 case 2: 9707 case 3:
9030 return (int)inv.Value.GroupPermissions; 9708 return (int)inv.Value.EveryonePermissions;
9031 case 3: 9709 case 4:
9032 return (int)inv.Value.EveryonePermissions; 9710 return (int)inv.Value.NextPermissions;
9033 case 4:
9034 return (int)inv.Value.NextPermissions;
9035 }
9036 } 9711 }
9037 } 9712 }
9038 } 9713 }
9714 m_host.TaskInventory.LockItemsForRead(false);
9039 9715
9040 return -1; 9716 return -1;
9041 } 9717 }
@@ -9082,16 +9758,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9082 { 9758 {
9083 m_host.AddScriptLPS(1); 9759 m_host.AddScriptLPS(1);
9084 9760
9085 lock (m_host.TaskInventory) 9761 m_host.TaskInventory.LockItemsForRead(true);
9762 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9086 { 9763 {
9087 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9764 if (inv.Value.Name == item)
9088 { 9765 {
9089 if (inv.Value.Name == item) 9766 m_host.TaskInventory.LockItemsForRead(false);
9090 { 9767 return inv.Value.CreatorID.ToString();
9091 return inv.Value.CreatorID.ToString();
9092 }
9093 } 9768 }
9094 } 9769 }
9770 m_host.TaskInventory.LockItemsForRead(false);
9095 9771
9096 llSay(0, "No item name '" + item + "'"); 9772 llSay(0, "No item name '" + item + "'");
9097 9773
@@ -9217,9 +9893,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9217 { 9893 {
9218 try 9894 try
9219 { 9895 {
9896 /*
9220 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 9897 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
9221 if (obj != null) 9898 if (obj != null)
9222 return (double)obj.GetMass(); 9899 return (double)obj.GetMass();
9900 */
9901 // return total object mass
9902 SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
9903 if (obj != null)
9904 return obj.GetMass();
9905
9223 // the object is null so the key is for an avatar 9906 // the object is null so the key is for an avatar
9224 ScenePresence avatar = World.GetScenePresence(key); 9907 ScenePresence avatar = World.GetScenePresence(key);
9225 if (avatar != null) 9908 if (avatar != null)
@@ -9239,7 +9922,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9239 } 9922 }
9240 9923
9241 /// <summary> 9924 /// <summary>
9242 /// illListReplaceList removes the sub-list defined by the inclusive indices 9925 /// llListReplaceList removes the sub-list defined by the inclusive indices
9243 /// start and end and inserts the src list in its place. The inclusive 9926 /// start and end and inserts the src list in its place. The inclusive
9244 /// nature of the indices means that at least one element must be deleted 9927 /// nature of the indices means that at least one element must be deleted
9245 /// if the indices are within the bounds of the existing list. I.e. 2,2 9928 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9296,16 +9979,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9296 // based upon end. Note that if end exceeds the upper 9979 // based upon end. Note that if end exceeds the upper
9297 // bound in this case, the entire destination list 9980 // bound in this case, the entire destination list
9298 // is removed. 9981 // is removed.
9299 else 9982 else if (start == 0)
9300 { 9983 {
9301 if (end + 1 < dest.Length) 9984 if (end + 1 < dest.Length)
9302 {
9303 return src + dest.GetSublist(end + 1, -1); 9985 return src + dest.GetSublist(end + 1, -1);
9304 }
9305 else 9986 else
9306 {
9307 return src; 9987 return src;
9308 } 9988 }
9989 else // Start < 0
9990 {
9991 if (end + 1 < dest.Length)
9992 return dest.GetSublist(end + 1, -1);
9993 else
9994 return new LSL_List();
9309 } 9995 }
9310 } 9996 }
9311 // Finally, if start > end, we strip away a prefix and 9997 // Finally, if start > end, we strip away a prefix and
@@ -9356,17 +10042,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9356 int width = 0; 10042 int width = 0;
9357 int height = 0; 10043 int height = 0;
9358 10044
9359 ParcelMediaCommandEnum? commandToSend = null; 10045 uint commandToSend = 0;
9360 float time = 0.0f; // default is from start 10046 float time = 0.0f; // default is from start
9361 10047
9362 ScenePresence presence = null; 10048 ScenePresence presence = null;
9363 10049
9364 for (int i = 0; i < commandList.Data.Length; i++) 10050 for (int i = 0; i < commandList.Data.Length; i++)
9365 { 10051 {
9366 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10052 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9367 switch (command) 10053 switch (command)
9368 { 10054 {
9369 case ParcelMediaCommandEnum.Agent: 10055 case (uint)ParcelMediaCommandEnum.Agent:
9370 // we send only to one agent 10056 // we send only to one agent
9371 if ((i + 1) < commandList.Length) 10057 if ((i + 1) < commandList.Length)
9372 { 10058 {
@@ -9383,25 +10069,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9383 } 10069 }
9384 break; 10070 break;
9385 10071
9386 case ParcelMediaCommandEnum.Loop: 10072 case (uint)ParcelMediaCommandEnum.Loop:
9387 loop = 1; 10073 loop = 1;
9388 commandToSend = command; 10074 commandToSend = command;
9389 update = true; //need to send the media update packet to set looping 10075 update = true; //need to send the media update packet to set looping
9390 break; 10076 break;
9391 10077
9392 case ParcelMediaCommandEnum.Play: 10078 case (uint)ParcelMediaCommandEnum.Play:
9393 loop = 0; 10079 loop = 0;
9394 commandToSend = command; 10080 commandToSend = command;
9395 update = true; //need to send the media update packet to make sure it doesn't loop 10081 update = true; //need to send the media update packet to make sure it doesn't loop
9396 break; 10082 break;
9397 10083
9398 case ParcelMediaCommandEnum.Pause: 10084 case (uint)ParcelMediaCommandEnum.Pause:
9399 case ParcelMediaCommandEnum.Stop: 10085 case (uint)ParcelMediaCommandEnum.Stop:
9400 case ParcelMediaCommandEnum.Unload: 10086 case (uint)ParcelMediaCommandEnum.Unload:
9401 commandToSend = command; 10087 commandToSend = command;
9402 break; 10088 break;
9403 10089
9404 case ParcelMediaCommandEnum.Url: 10090 case (uint)ParcelMediaCommandEnum.Url:
9405 if ((i + 1) < commandList.Length) 10091 if ((i + 1) < commandList.Length)
9406 { 10092 {
9407 if (commandList.Data[i + 1] is LSL_String) 10093 if (commandList.Data[i + 1] is LSL_String)
@@ -9414,7 +10100,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9414 } 10100 }
9415 break; 10101 break;
9416 10102
9417 case ParcelMediaCommandEnum.Texture: 10103 case (uint)ParcelMediaCommandEnum.Texture:
9418 if ((i + 1) < commandList.Length) 10104 if ((i + 1) < commandList.Length)
9419 { 10105 {
9420 if (commandList.Data[i + 1] is LSL_String) 10106 if (commandList.Data[i + 1] is LSL_String)
@@ -9427,7 +10113,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9427 } 10113 }
9428 break; 10114 break;
9429 10115
9430 case ParcelMediaCommandEnum.Time: 10116 case (uint)ParcelMediaCommandEnum.Time:
9431 if ((i + 1) < commandList.Length) 10117 if ((i + 1) < commandList.Length)
9432 { 10118 {
9433 if (commandList.Data[i + 1] is LSL_Float) 10119 if (commandList.Data[i + 1] is LSL_Float)
@@ -9439,7 +10125,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9439 } 10125 }
9440 break; 10126 break;
9441 10127
9442 case ParcelMediaCommandEnum.AutoAlign: 10128 case (uint)ParcelMediaCommandEnum.AutoAlign:
9443 if ((i + 1) < commandList.Length) 10129 if ((i + 1) < commandList.Length)
9444 { 10130 {
9445 if (commandList.Data[i + 1] is LSL_Integer) 10131 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9453,7 +10139,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9453 } 10139 }
9454 break; 10140 break;
9455 10141
9456 case ParcelMediaCommandEnum.Type: 10142 case (uint)ParcelMediaCommandEnum.Type:
9457 if ((i + 1) < commandList.Length) 10143 if ((i + 1) < commandList.Length)
9458 { 10144 {
9459 if (commandList.Data[i + 1] is LSL_String) 10145 if (commandList.Data[i + 1] is LSL_String)
@@ -9466,7 +10152,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9466 } 10152 }
9467 break; 10153 break;
9468 10154
9469 case ParcelMediaCommandEnum.Desc: 10155 case (uint)ParcelMediaCommandEnum.Desc:
9470 if ((i + 1) < commandList.Length) 10156 if ((i + 1) < commandList.Length)
9471 { 10157 {
9472 if (commandList.Data[i + 1] is LSL_String) 10158 if (commandList.Data[i + 1] is LSL_String)
@@ -9479,7 +10165,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9479 } 10165 }
9480 break; 10166 break;
9481 10167
9482 case ParcelMediaCommandEnum.Size: 10168 case (uint)ParcelMediaCommandEnum.Size:
9483 if ((i + 2) < commandList.Length) 10169 if ((i + 2) < commandList.Length)
9484 { 10170 {
9485 if (commandList.Data[i + 1] is LSL_Integer) 10171 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9549,7 +10235,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9549 } 10235 }
9550 } 10236 }
9551 10237
9552 if (commandToSend != null) 10238 if (commandToSend != 0)
9553 { 10239 {
9554 // the commandList contained a start/stop/... command, too 10240 // the commandList contained a start/stop/... command, too
9555 if (presence == null) 10241 if (presence == null)
@@ -9586,7 +10272,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9586 10272
9587 if (aList.Data[i] != null) 10273 if (aList.Data[i] != null)
9588 { 10274 {
9589 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10275 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9590 { 10276 {
9591 case ParcelMediaCommandEnum.Url: 10277 case ParcelMediaCommandEnum.Url:
9592 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10278 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9629,16 +10315,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9629 { 10315 {
9630 m_host.AddScriptLPS(1); 10316 m_host.AddScriptLPS(1);
9631 10317
9632 lock (m_host.TaskInventory) 10318 m_host.TaskInventory.LockItemsForRead(true);
10319 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9633 { 10320 {
9634 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10321 if (inv.Value.Name == name)
9635 { 10322 {
9636 if (inv.Value.Name == name) 10323 m_host.TaskInventory.LockItemsForRead(false);
9637 { 10324 return inv.Value.Type;
9638 return inv.Value.Type;
9639 }
9640 } 10325 }
9641 } 10326 }
10327 m_host.TaskInventory.LockItemsForRead(false);
9642 10328
9643 return -1; 10329 return -1;
9644 } 10330 }
@@ -9649,15 +10335,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9649 10335
9650 if (quick_pay_buttons.Data.Length < 4) 10336 if (quick_pay_buttons.Data.Length < 4)
9651 { 10337 {
9652 LSLError("List must have at least 4 elements"); 10338 int x;
9653 return; 10339 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10340 {
10341 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10342 }
9654 } 10343 }
9655 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10344 int[] nPrice = new int[5];
9656 10345 nPrice[0] = price;
9657 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10346 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9658 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10347 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9659 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10348 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9660 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10349 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10350 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9661 m_host.ParentGroup.HasGroupChanged = true; 10351 m_host.ParentGroup.HasGroupChanged = true;
9662 } 10352 }
9663 10353
@@ -9673,6 +10363,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9673 ShoutError("No permissions to track the camera"); 10363 ShoutError("No permissions to track the camera");
9674 return new LSL_Vector(); 10364 return new LSL_Vector();
9675 } 10365 }
10366 m_host.TaskInventory.LockItemsForRead(false);
9676 10367
9677 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10368 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9678 if (presence != null) 10369 if (presence != null)
@@ -9695,6 +10386,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9695 ShoutError("No permissions to track the camera"); 10386 ShoutError("No permissions to track the camera");
9696 return new LSL_Rotation(); 10387 return new LSL_Rotation();
9697 } 10388 }
10389 m_host.TaskInventory.LockItemsForRead(false);
9698 10390
9699 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10391 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9700 if (presence != null) 10392 if (presence != null)
@@ -9756,8 +10448,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9756 { 10448 {
9757 m_host.AddScriptLPS(1); 10449 m_host.AddScriptLPS(1);
9758 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 10450 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
9759 if (detectedParams == null) return; // only works on the first detected avatar 10451 if (detectedParams == null)
9760 10452 {
10453 if (m_host.ParentGroup.IsAttachment == true)
10454 {
10455 detectedParams = new DetectParams();
10456 detectedParams.Key = m_host.OwnerID;
10457 }
10458 else
10459 {
10460 return;
10461 }
10462 }
10463
9761 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10464 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9762 if (avatar != null) 10465 if (avatar != null)
9763 { 10466 {
@@ -9765,6 +10468,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9765 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10468 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9766 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10469 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9767 } 10470 }
10471
9768 ScriptSleep(1000); 10472 ScriptSleep(1000);
9769 } 10473 }
9770 10474
@@ -9888,12 +10592,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9888 10592
9889 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10593 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9890 object[] data = rules.Data; 10594 object[] data = rules.Data;
9891 for (int i = 0; i < data.Length; ++i) { 10595 for (int i = 0; i < data.Length; ++i)
10596 {
9892 int type = Convert.ToInt32(data[i++].ToString()); 10597 int type = Convert.ToInt32(data[i++].ToString());
9893 if (i >= data.Length) break; // odd number of entries => ignore the last 10598 if (i >= data.Length) break; // odd number of entries => ignore the last
9894 10599
9895 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10600 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9896 switch (type) { 10601 switch (type)
10602 {
9897 case ScriptBaseClass.CAMERA_FOCUS: 10603 case ScriptBaseClass.CAMERA_FOCUS:
9898 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10604 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9899 case ScriptBaseClass.CAMERA_POSITION: 10605 case ScriptBaseClass.CAMERA_POSITION:
@@ -9999,19 +10705,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9999 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10705 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
10000 { 10706 {
10001 m_host.AddScriptLPS(1); 10707 m_host.AddScriptLPS(1);
10002 string ret = String.Empty; 10708
10003 string src1 = llBase64ToString(str1); 10709 if (str1 == String.Empty)
10004 string src2 = llBase64ToString(str2); 10710 return String.Empty;
10005 int c = 0; 10711 if (str2 == String.Empty)
10006 for (int i = 0; i < src1.Length; i++) 10712 return str1;
10713
10714 int len = str2.Length;
10715 if ((len % 4) != 0) // LL is EVIL!!!!
10007 { 10716 {
10008 ret += (char) (src1[i] ^ src2[c]); 10717 while (str2.EndsWith("="))
10718 str2 = str2.Substring(0, str2.Length - 1);
10719
10720 len = str2.Length;
10721 int mod = len % 4;
10009 10722
10010 c++; 10723 if (mod == 1)
10011 if (c >= src2.Length) 10724 str2 = str2.Substring(0, str2.Length - 1);
10012 c = 0; 10725 else if (mod == 2)
10726 str2 += "==";
10727 else if (mod == 3)
10728 str2 += "=";
10013 } 10729 }
10014 return llStringToBase64(ret); 10730
10731 byte[] data1;
10732 byte[] data2;
10733 try
10734 {
10735 data1 = Convert.FromBase64String(str1);
10736 data2 = Convert.FromBase64String(str2);
10737 }
10738 catch (Exception)
10739 {
10740 return new LSL_String(String.Empty);
10741 }
10742
10743 byte[] d2 = new Byte[data1.Length];
10744 int pos = 0;
10745
10746 if (data1.Length <= data2.Length)
10747 {
10748 Array.Copy(data2, 0, d2, 0, data1.Length);
10749 }
10750 else
10751 {
10752 while (pos < data1.Length)
10753 {
10754 len = data1.Length - pos;
10755 if (len > data2.Length)
10756 len = data2.Length;
10757
10758 Array.Copy(data2, 0, d2, pos, len);
10759 pos += len;
10760 }
10761 }
10762
10763 for (pos = 0 ; pos < data1.Length ; pos++ )
10764 data1[pos] ^= d2[pos];
10765
10766 return Convert.ToBase64String(data1);
10015 } 10767 }
10016 10768
10017 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10769 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10068,12 +10820,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10068 Regex r = new Regex(authregex); 10820 Regex r = new Regex(authregex);
10069 int[] gnums = r.GetGroupNumbers(); 10821 int[] gnums = r.GetGroupNumbers();
10070 Match m = r.Match(url); 10822 Match m = r.Match(url);
10071 if (m.Success) { 10823 if (m.Success)
10072 for (int i = 1; i < gnums.Length; i++) { 10824 {
10825 for (int i = 1; i < gnums.Length; i++)
10826 {
10073 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10827 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10074 //CaptureCollection cc = g.Captures; 10828 //CaptureCollection cc = g.Captures;
10075 } 10829 }
10076 if (m.Groups.Count == 5) { 10830 if (m.Groups.Count == 5)
10831 {
10077 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10832 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10078 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10833 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10079 } 10834 }
@@ -10436,15 +11191,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10436 11191
10437 internal UUID ScriptByName(string name) 11192 internal UUID ScriptByName(string name)
10438 { 11193 {
10439 lock (m_host.TaskInventory) 11194 m_host.TaskInventory.LockItemsForRead(true);
11195
11196 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10440 { 11197 {
10441 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 11198 if (item.Type == 10 && item.Name == name)
10442 { 11199 {
10443 if (item.Type == 10 && item.Name == name) 11200 m_host.TaskInventory.LockItemsForRead(false);
10444 return item.ItemID; 11201 return item.ItemID;
10445 } 11202 }
10446 } 11203 }
10447 11204
11205 m_host.TaskInventory.LockItemsForRead(false);
11206
10448 return UUID.Zero; 11207 return UUID.Zero;
10449 } 11208 }
10450 11209
@@ -10485,6 +11244,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10485 { 11244 {
10486 m_host.AddScriptLPS(1); 11245 m_host.AddScriptLPS(1);
10487 11246
11247 //Clone is thread safe
10488 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11248 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10489 11249
10490 UUID assetID = UUID.Zero; 11250 UUID assetID = UUID.Zero;
@@ -10547,6 +11307,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10547 { 11307 {
10548 m_host.AddScriptLPS(1); 11308 m_host.AddScriptLPS(1);
10549 11309
11310 //Clone is thread safe
10550 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11311 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10551 11312
10552 UUID assetID = UUID.Zero; 11313 UUID assetID = UUID.Zero;
@@ -10627,15 +11388,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10627 return GetLinkPrimitiveParams(obj, rules); 11388 return GetLinkPrimitiveParams(obj, rules);
10628 } 11389 }
10629 11390
10630 public void print(string str) 11391 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10631 { 11392 {
10632 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11393 List<SceneObjectPart> parts = GetLinkParts(link);
10633 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11394 if (parts.Count < 1)
10634 if (ossl != null) 11395 return 0;
10635 { 11396
10636 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11397 return GetNumberOfSides(parts[0]);
10637 m_log.Info("LSL print():" + str);
10638 }
10639 } 11398 }
10640 11399
10641 private string Name2Username(string name) 11400 private string Name2Username(string name)
@@ -10681,155 +11440,482 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10681 return rq.ToString(); 11440 return rq.ToString();
10682 } 11441 }
10683 11442
11443 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11444 {
11445 m_SayShoutCount = 0;
11446 }
11447
11448 private struct Tri
11449 {
11450 public Vector3 p1;
11451 public Vector3 p2;
11452 public Vector3 p3;
11453 }
11454
11455 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11456 {
11457 float height = avatar.Appearance.AvatarHeight;
11458 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11459 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11460
11461 if (point.X > b1.X && point.X < b2.X &&
11462 point.Y > b1.Y && point.Y < b2.Y &&
11463 point.Z > b1.Z && point.Z < b2.Z)
11464 return true;
11465 return false;
11466 }
11467
11468 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11469 {
11470 List<ContactResult> contacts = new List<ContactResult>();
11471
11472 Vector3 ab = rayEnd - rayStart;
11473
11474 World.ForEachScenePresence(delegate(ScenePresence sp)
11475 {
11476 Vector3 ac = sp.AbsolutePosition - rayStart;
11477 Vector3 bc = sp.AbsolutePosition - rayEnd;
11478
11479 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11480
11481 if (d > 1.5)
11482 return;
11483
11484 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11485
11486 if (d2 > 0)
11487 return;
11488
11489 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11490 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11491
11492 if (!InBoundingBox(sp, p))
11493 return;
11494
11495 ContactResult result = new ContactResult ();
11496 result.ConsumerID = sp.LocalId;
11497 result.Depth = Vector3.Distance(rayStart, p);
11498 result.Normal = Vector3.Zero;
11499 result.Pos = p;
11500
11501 contacts.Add(result);
11502 });
11503
11504 return contacts.ToArray();
11505 }
11506
11507 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11508 {
11509 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11510 List<ContactResult> contacts = new List<ContactResult>();
11511
11512 Vector3 ab = rayEnd - rayStart;
11513
11514 World.ForEachSOG(delegate(SceneObjectGroup group)
11515 {
11516 if (m_host.ParentGroup == group)
11517 return;
11518
11519 if (group.IsAttachment)
11520 return;
11521
11522 if (group.RootPart.PhysActor == null)
11523 {
11524 if (!includePhantom)
11525 return;
11526 }
11527 else
11528 {
11529 if (group.RootPart.PhysActor.IsPhysical)
11530 {
11531 if (!includePhysical)
11532 return;
11533 }
11534 else
11535 {
11536 if (!includeNonPhysical)
11537 return;
11538 }
11539 }
11540
11541 // Find the radius ouside of which we don't even need to hit test
11542 float minX;
11543 float maxX;
11544 float minY;
11545 float maxY;
11546 float minZ;
11547 float maxZ;
11548
11549 float radius = 0.0f;
11550
11551 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11552
11553 if (Math.Abs(minX) > radius)
11554 radius = Math.Abs(minX);
11555 if (Math.Abs(minY) > radius)
11556 radius = Math.Abs(minY);
11557 if (Math.Abs(minZ) > radius)
11558 radius = Math.Abs(minZ);
11559 if (Math.Abs(maxX) > radius)
11560 radius = Math.Abs(maxX);
11561 if (Math.Abs(maxY) > radius)
11562 radius = Math.Abs(maxY);
11563 if (Math.Abs(maxZ) > radius)
11564 radius = Math.Abs(maxZ);
11565
11566 Vector3 ac = group.AbsolutePosition - rayStart;
11567 Vector3 bc = group.AbsolutePosition - rayEnd;
11568
11569 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11570
11571 // Too far off ray, don't bother
11572 if (d > radius)
11573 return;
11574
11575 // Behind ray, drop
11576 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11577 if (d2 > 0)
11578 return;
11579
11580 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11581 // Miss.
11582 if (!intersection.HitTF)
11583 return;
11584
11585 ContactResult result = new ContactResult ();
11586 result.ConsumerID = group.LocalId;
11587 result.Depth = intersection.distance;
11588 result.Normal = intersection.normal;
11589 result.Pos = intersection.ipoint;
11590
11591 contacts.Add(result);
11592 });
11593
11594 return contacts.ToArray();
11595 }
11596
11597 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11598 {
11599 double[,] heightfield = World.Heightmap.GetDoubles();
11600 List<ContactResult> contacts = new List<ContactResult>();
11601
11602 double min = 2048.0;
11603 double max = 0.0;
11604
11605 // Find the min and max of the heightfield
11606 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11607 {
11608 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11609 {
11610 if (heightfield[x, y] > max)
11611 max = heightfield[x, y];
11612 if (heightfield[x, y] < min)
11613 min = heightfield[x, y];
11614 }
11615 }
11616
11617
11618 // A ray extends past rayEnd, but doesn't go back before
11619 // rayStart. If the start is above the highest point of the ground
11620 // and the ray goes up, we can't hit the ground. Ever.
11621 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11622 return null;
11623
11624 // Same for going down
11625 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11626 return null;
11627
11628 List<Tri> trilist = new List<Tri>();
11629
11630 // Create our triangle list
11631 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11632 {
11633 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11634 {
11635 Tri t1 = new Tri();
11636 Tri t2 = new Tri();
11637
11638 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11639 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11640 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11641 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11642
11643 t1.p1 = p1;
11644 t1.p2 = p2;
11645 t1.p3 = p3;
11646
11647 t2.p1 = p3;
11648 t2.p2 = p4;
11649 t2.p3 = p1;
11650
11651 trilist.Add(t1);
11652 trilist.Add(t2);
11653 }
11654 }
11655
11656 // Ray direction
11657 Vector3 rayDirection = rayEnd - rayStart;
11658
11659 foreach (Tri t in trilist)
11660 {
11661 // Compute triangle plane normal and edges
11662 Vector3 u = t.p2 - t.p1;
11663 Vector3 v = t.p3 - t.p1;
11664 Vector3 n = Vector3.Cross(u, v);
11665
11666 if (n == Vector3.Zero)
11667 continue;
11668
11669 Vector3 w0 = rayStart - t.p1;
11670 double a = -Vector3.Dot(n, w0);
11671 double b = Vector3.Dot(n, rayDirection);
11672
11673 // Not intersecting the plane, or in plane (same thing)
11674 // Ignoring this MAY cause the ground to not be detected
11675 // sometimes
11676 if (Math.Abs(b) < 0.000001)
11677 continue;
11678
11679 double r = a / b;
11680
11681 // ray points away from plane
11682 if (r < 0.0)
11683 continue;
11684
11685 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11686
11687 float uu = Vector3.Dot(u, u);
11688 float uv = Vector3.Dot(u, v);
11689 float vv = Vector3.Dot(v, v);
11690 Vector3 w = ip - t.p1;
11691 float wu = Vector3.Dot(w, u);
11692 float wv = Vector3.Dot(w, v);
11693 float d = uv * uv - uu * vv;
11694
11695 float cs = (uv * wv - vv * wu) / d;
11696 if (cs < 0 || cs > 1.0)
11697 continue;
11698 float ct = (uv * wu - uu * wv) / d;
11699 if (ct < 0 || (cs + ct) > 1.0)
11700 continue;
11701
11702 // Add contact point
11703 ContactResult result = new ContactResult ();
11704 result.ConsumerID = 0;
11705 result.Depth = Vector3.Distance(rayStart, ip);
11706 result.Normal = n;
11707 result.Pos = ip;
11708
11709 contacts.Add(result);
11710 }
11711
11712 if (contacts.Count == 0)
11713 return null;
11714
11715 contacts.Sort(delegate(ContactResult a, ContactResult b)
11716 {
11717 return (int)(a.Depth - b.Depth);
11718 });
11719
11720 return contacts[0];
11721 }
11722/*
11723 // not done:
11724 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
11725 {
11726 ContactResult[] contacts = null;
11727 World.ForEachSOG(delegate(SceneObjectGroup group)
11728 {
11729 if (m_host.ParentGroup == group)
11730 return;
11731
11732 if (group.IsAttachment)
11733 return;
11734
11735 if(group.RootPart.PhysActor != null)
11736 return;
11737
11738 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
11739 });
11740 return contacts;
11741 }
11742*/
11743
10684 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11744 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10685 { 11745 {
11746 LSL_List list = new LSL_List();
11747
10686 m_host.AddScriptLPS(1); 11748 m_host.AddScriptLPS(1);
10687 11749
10688 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11750 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10689 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11751 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10690 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11752 Vector3 dir = rayEnd - rayStart;
10691 11753
10692 int count = 0; 11754 float dist = Vector3.Mag(dir);
10693// int detectPhantom = 0; 11755
11756 int count = 1;
11757 bool detectPhantom = false;
10694 int dataFlags = 0; 11758 int dataFlags = 0;
10695 int rejectTypes = 0; 11759 int rejectTypes = 0;
10696 11760
10697 for (int i = 0; i < options.Length; i += 2) 11761 for (int i = 0; i < options.Length; i += 2)
10698 { 11762 {
10699 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11763 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10700 {
10701 count = options.GetLSLIntegerItem(i + 1); 11764 count = options.GetLSLIntegerItem(i + 1);
10702 } 11765 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10703// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11766 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10704// {
10705// detectPhantom = options.GetLSLIntegerItem(i + 1);
10706// }
10707 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11767 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10708 {
10709 dataFlags = options.GetLSLIntegerItem(i + 1); 11768 dataFlags = options.GetLSLIntegerItem(i + 1);
10710 }
10711 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11769 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10712 {
10713 rejectTypes = options.GetLSLIntegerItem(i + 1); 11770 rejectTypes = options.GetLSLIntegerItem(i + 1);
10714 }
10715 } 11771 }
10716 11772
10717 LSL_List list = new LSL_List(); 11773 if (count > 16)
10718 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11774 count = 16;
10719
10720 double distance = Util.GetDistanceTo(startvector, endvector);
10721 11775
10722 if (distance == 0) 11776 List<ContactResult> results = new List<ContactResult>();
10723 distance = 0.001;
10724
10725 Vector3 posToCheck = startvector;
10726 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10727 11777
10728 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11778 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10729 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11779 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10730 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11780 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10731 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11781 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10732 11782
10733 for (float i = 0; i <= distance; i += 0.1f) 11783
11784 if (World.SuportsRayCastFiltered())
10734 { 11785 {
10735 posToCheck = startvector + (dir * (i / (float)distance)); 11786 if (dist == 0)
11787 return list;
11788
11789 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
11790 if (checkTerrain)
11791 rayfilter |= RayFilterFlags.land;
11792// if (checkAgents)
11793// rayfilter |= RayFilterFlags.agent;
11794 if (checkPhysical)
11795 rayfilter |= RayFilterFlags.physical;
11796 if (checkNonPhysical)
11797 rayfilter |= RayFilterFlags.nonphysical;
11798 if (detectPhantom)
11799 rayfilter |= RayFilterFlags.LSLPhanton;
10736 11800
10737 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11801 Vector3 direction = dir * ( 1/dist);
11802
11803 if(rayfilter == 0)
10738 { 11804 {
10739 ContactResult result = new ContactResult(); 11805 list.Add(new LSL_Integer(0));
10740 result.ConsumerID = 0; 11806 return list;
10741 result.Depth = 0;
10742 result.Normal = Vector3.Zero;
10743 result.Pos = posToCheck;
10744 results.Add(result);
10745 checkTerrain = false;
10746 } 11807 }
10747 11808
10748 if (checkAgents) 11809 // get some more contacts to sort ???
11810 int physcount = 4 * count;
11811 if (physcount > 20)
11812 physcount = 20;
11813
11814 object physresults;
11815 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
11816
11817 if (physresults == null)
10749 { 11818 {
10750 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11819 list.Add(new LSL_Integer(-3)); // timeout error
10751 { 11820 return list;
10752 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X))
10753 {
10754 ContactResult result = new ContactResult ();
10755 result.ConsumerID = sp.LocalId;
10756 result.Depth = 0;
10757 result.Normal = Vector3.Zero;
10758 result.Pos = posToCheck;
10759 results.Add(result);
10760 }
10761 });
10762 } 11821 }
10763 }
10764 11822
10765 int refcount = 0; 11823 results = (List<ContactResult>)physresults;
10766 foreach (ContactResult result in results)
10767 {
10768 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND)
10769 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0)
10770 continue;
10771 11824
10772 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID); 11825 // for now physics doesn't detect sitted avatars so do it outside physics
11826 if (checkAgents)
11827 {
11828 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11829 foreach (ContactResult r in agentHits)
11830 results.Add(r);
11831 }
10773 11832
10774 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) 11833 // bug: will not detect phantom unless they are physical
10775 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents 11834 // don't use ObjectIntersection because its also bad
10776 11835
10777 if (entity == null) 11836 }
11837 else
11838 {
11839 if (checkTerrain)
10778 { 11840 {
10779 list.Add(UUID.Zero); 11841 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11842 if (groundContact != null)
11843 results.Add((ContactResult)groundContact);
11844 }
10780 11845
10781 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11846 if (checkAgents)
10782 list.Add(0); 11847 {
11848 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11849 foreach (ContactResult r in agentHits)
11850 results.Add(r);
11851 }
10783 11852
10784 list.Add(result.Pos); 11853 if (checkPhysical || checkNonPhysical || detectPhantom)
11854 {
11855 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
11856 foreach (ContactResult r in objectHits)
11857 results.Add(r);
11858 }
11859 }
10785 11860
10786 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11861 results.Sort(delegate(ContactResult a, ContactResult b)
10787 list.Add(result.Normal); 11862 {
11863 return a.Depth.CompareTo(b.Depth);
11864 });
11865
11866 int values = 0;
11867 SceneObjectGroup thisgrp = m_host.ParentGroup;
10788 11868
10789 continue; //Can't find it, so add UUID.Zero 11869 foreach (ContactResult result in results)
10790 } 11870 {
11871 if (result.Depth > dist)
11872 continue;
10791 11873
10792 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity && 11874 // physics ray can return colisions with host prim
10793 ((ISceneChildEntity)intersection.obj).PhysActor == null) 11875 if (m_host.LocalId == result.ConsumerID)
10794 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects 11876 continue;
11877
11878 UUID itemID = UUID.Zero;
11879 int linkNum = 0;
10795 11880
10796 if (entity is SceneObjectPart) 11881 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
11882 // It's a prim!
11883 if (part != null)
10797 { 11884 {
10798 PhysicsActor pa = ((SceneObjectPart)entity).PhysActor; 11885 // dont detect members of same object ???
11886 if (part.ParentGroup == thisgrp)
11887 continue;
10799 11888
10800 if (pa != null && pa.IsPhysical) 11889 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10801 { 11890 itemID = part.ParentGroup.UUID;
10802 if (!checkPhysical)
10803 continue;
10804 }
10805 else 11891 else
10806 { 11892 itemID = part.UUID;
10807 if (!checkNonPhysical)
10808 continue;
10809 }
10810 }
10811 11893
10812 refcount++; 11894 linkNum = part.LinkNum;
10813 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11895 }
10814 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10815 else 11896 else
10816 list.Add(entity.UUID);
10817
10818 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10819 { 11897 {
10820 if (entity is SceneObjectPart) 11898 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10821 list.Add(((SceneObjectPart)entity).LinkNum); 11899 /// It it a boy? a girl?
10822 else 11900 if (sp != null)
10823 list.Add(0); 11901 itemID = sp.UUID;
10824 } 11902 }
10825 11903
10826 list.Add(result.Pos); 11904 list.Add(new LSL_String(itemID.ToString()));
11905 list.Add(new LSL_String(result.Pos.ToString()));
11906
11907 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
11908 list.Add(new LSL_Integer(linkNum));
10827 11909
10828 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11910 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10829 list.Add(result.Normal); 11911 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11912
11913 values++;
11914 if (values >= count)
11915 break;
10830 } 11916 }
10831 11917
10832 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11918 list.Add(new LSL_Integer(values));
10833 11919
10834 return list; 11920 return list;
10835 } 11921 }
@@ -10869,7 +11955,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10869 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 11955 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10870 if (!isAccount) return 0; 11956 if (!isAccount) return 0;
10871 if (estate.HasAccess(id)) return 1; 11957 if (estate.HasAccess(id)) return 1;
10872 if (estate.IsBanned(id)) 11958 if (estate.IsBanned(id, World.GetUserFlags(id)))
10873 estate.RemoveBan(id); 11959 estate.RemoveBan(id);
10874 estate.AddEstateUser(id); 11960 estate.AddEstateUser(id);
10875 break; 11961 break;
@@ -10888,14 +11974,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10888 break; 11974 break;
10889 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 11975 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10890 if (!isAccount) return 0; 11976 if (!isAccount) return 0;
10891 if (estate.IsBanned(id)) return 1; 11977 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10892 EstateBan ban = new EstateBan(); 11978 EstateBan ban = new EstateBan();
10893 ban.EstateID = estate.EstateID; 11979 ban.EstateID = estate.EstateID;
10894 ban.BannedUserID = id; 11980 ban.BannedUserID = id;
10895 estate.AddBan(ban); 11981 estate.AddBan(ban);
10896 break; 11982 break;
10897 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 11983 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10898 if (!isAccount || !estate.IsBanned(id)) return 0; 11984 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10899 estate.RemoveBan(id); 11985 estate.RemoveBan(id);
10900 break; 11986 break;
10901 default: return 0; 11987 default: return 0;
@@ -10924,7 +12010,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10924 return 16384; 12010 return 16384;
10925 } 12011 }
10926 12012
10927 public LSL_Integer llGetUsedMemory() 12013 public virtual LSL_Integer llGetUsedMemory()
10928 { 12014 {
10929 m_host.AddScriptLPS(1); 12015 m_host.AddScriptLPS(1);
10930 // The value returned for LSO scripts in SL 12016 // The value returned for LSO scripts in SL
@@ -10952,7 +12038,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10952 public void llSetSoundQueueing(int queue) 12038 public void llSetSoundQueueing(int queue)
10953 { 12039 {
10954 m_host.AddScriptLPS(1); 12040 m_host.AddScriptLPS(1);
10955 NotImplemented("llSetSoundQueueing");
10956 } 12041 }
10957 12042
10958 public void llCollisionSprite(string impact_sprite) 12043 public void llCollisionSprite(string impact_sprite)
@@ -10964,10 +12049,270 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10964 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12049 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10965 { 12050 {
10966 m_host.AddScriptLPS(1); 12051 m_host.AddScriptLPS(1);
10967 NotImplemented("llGodLikeRezObject"); 12052
12053 if (!World.Permissions.IsGod(m_host.OwnerID))
12054 NotImplemented("llGodLikeRezObject");
12055
12056 AssetBase rezAsset = World.AssetService.Get(inventory);
12057 if (rezAsset == null)
12058 {
12059 llSay(0, "Asset not found");
12060 return;
12061 }
12062
12063 SceneObjectGroup group = null;
12064
12065 try
12066 {
12067 string xmlData = Utils.BytesToString(rezAsset.Data);
12068 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12069 }
12070 catch
12071 {
12072 llSay(0, "Asset not found");
12073 return;
12074 }
12075
12076 if (group == null)
12077 {
12078 llSay(0, "Asset not found");
12079 return;
12080 }
12081
12082 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12083 group.RootPart.AttachOffset = group.AbsolutePosition;
12084
12085 group.ResetIDs();
12086
12087 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12088 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12089 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12090 group.ScheduleGroupForFullUpdate();
12091
12092 // objects rezzed with this method are die_at_edge by default.
12093 group.RootPart.SetDieAtEdge(true);
12094
12095 group.ResumeScripts();
12096
12097 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12098 "object_rez", new Object[] {
12099 new LSL_String(
12100 group.RootPart.UUID.ToString()) },
12101 new DetectParams[0]));
12102 }
12103
12104 public LSL_String llTransferLindenDollars(string destination, int amount)
12105 {
12106 UUID txn = UUID.Random();
12107
12108 Util.FireAndForget(delegate(object x)
12109 {
12110 int replycode = 0;
12111 string replydata = destination + "," + amount.ToString();
12112
12113 try
12114 {
12115 TaskInventoryItem item = m_item;
12116 if (item == null)
12117 {
12118 replydata = "SERVICE_ERROR";
12119 return;
12120 }
12121
12122 m_host.AddScriptLPS(1);
12123
12124 if (item.PermsGranter == UUID.Zero)
12125 {
12126 replydata = "MISSING_PERMISSION_DEBIT";
12127 return;
12128 }
12129
12130 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
12131 {
12132 replydata = "MISSING_PERMISSION_DEBIT";
12133 return;
12134 }
12135
12136 UUID toID = new UUID();
12137
12138 if (!UUID.TryParse(destination, out toID))
12139 {
12140 replydata = "INVALID_AGENT";
12141 return;
12142 }
12143
12144 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
12145
12146 if (money == null)
12147 {
12148 replydata = "TRANSFERS_DISABLED";
12149 return;
12150 }
12151
12152 bool result = money.ObjectGiveMoney(
12153 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
12154
12155 if (result)
12156 {
12157 replycode = 1;
12158 return;
12159 }
12160
12161 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
12162 }
12163 finally
12164 {
12165 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
12166 "transaction_result", new Object[] {
12167 new LSL_String(txn.ToString()),
12168 new LSL_Integer(replycode),
12169 new LSL_String(replydata) },
12170 new DetectParams[0]));
12171 }
12172 });
12173
12174 return txn.ToString();
10968 } 12175 }
10969 12176
10970 #endregion 12177 #endregion
12178
12179 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12180 {
12181 SceneObjectGroup group = m_host.ParentGroup;
12182
12183 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12184 return;
12185 if (group.IsAttachment)
12186 return;
12187
12188 if (frames.Data.Length > 0) // We are getting a new motion
12189 {
12190 if (group.RootPart.KeyframeMotion != null)
12191 group.RootPart.KeyframeMotion.Stop();
12192 group.RootPart.KeyframeMotion = null;
12193
12194 int idx = 0;
12195
12196 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12197 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12198
12199 while (idx < options.Data.Length)
12200 {
12201 int option = (int)options.GetLSLIntegerItem(idx++);
12202 int remain = options.Data.Length - idx;
12203
12204 switch (option)
12205 {
12206 case ScriptBaseClass.KFM_MODE:
12207 if (remain < 1)
12208 break;
12209 int modeval = (int)options.GetLSLIntegerItem(idx++);
12210 switch(modeval)
12211 {
12212 case ScriptBaseClass.KFM_FORWARD:
12213 mode = KeyframeMotion.PlayMode.Forward;
12214 break;
12215 case ScriptBaseClass.KFM_REVERSE:
12216 mode = KeyframeMotion.PlayMode.Reverse;
12217 break;
12218 case ScriptBaseClass.KFM_LOOP:
12219 mode = KeyframeMotion.PlayMode.Loop;
12220 break;
12221 case ScriptBaseClass.KFM_PING_PONG:
12222 mode = KeyframeMotion.PlayMode.PingPong;
12223 break;
12224 }
12225 break;
12226 case ScriptBaseClass.KFM_DATA:
12227 if (remain < 1)
12228 break;
12229 int dataval = (int)options.GetLSLIntegerItem(idx++);
12230 data = (KeyframeMotion.DataFormat)dataval;
12231 break;
12232 }
12233 }
12234
12235 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12236
12237 idx = 0;
12238
12239 int elemLength = 2;
12240 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12241 elemLength = 3;
12242
12243 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12244 while (idx < frames.Data.Length)
12245 {
12246 int remain = frames.Data.Length - idx;
12247
12248 if (remain < elemLength)
12249 break;
12250
12251 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12252 frame.Position = null;
12253 frame.Rotation = null;
12254
12255 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12256 {
12257 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12258 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12259 }
12260 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12261 {
12262 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12263 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12264 }
12265
12266 float tempf = (float)frames.GetLSLFloatItem(idx++);
12267 frame.TimeMS = (int)(tempf * 1000.0f);
12268
12269 keyframes.Add(frame);
12270 }
12271
12272 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12273 group.RootPart.KeyframeMotion.Start();
12274 }
12275 else
12276 {
12277 if (group.RootPart.KeyframeMotion == null)
12278 return;
12279
12280 if (options.Data.Length == 0)
12281 {
12282 group.RootPart.KeyframeMotion.Stop();
12283 return;
12284 }
12285
12286 int code = (int)options.GetLSLIntegerItem(0);
12287
12288 int idx = 0;
12289
12290 while (idx < options.Data.Length)
12291 {
12292 int option = (int)options.GetLSLIntegerItem(idx++);
12293 int remain = options.Data.Length - idx;
12294
12295 switch (option)
12296 {
12297 case ScriptBaseClass.KFM_COMMAND:
12298 int cmd = (int)options.GetLSLIntegerItem(idx++);
12299 switch (cmd)
12300 {
12301 case ScriptBaseClass.KFM_CMD_PLAY:
12302 group.RootPart.KeyframeMotion.Start();
12303 break;
12304 case ScriptBaseClass.KFM_CMD_STOP:
12305 group.RootPart.KeyframeMotion.Stop();
12306 break;
12307 case ScriptBaseClass.KFM_CMD_PAUSE:
12308 group.RootPart.KeyframeMotion.Pause();
12309 break;
12310 }
12311 break;
12312 }
12313 }
12314 }
12315 }
10971 } 12316 }
10972 12317
10973 public class NotecardCache 12318 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}