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.cs2985
-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, 2928 insertions, 1076 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 5b5cab8..5bd781c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -28,10 +28,12 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode]
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using System.Text; 33using System.Text;
33using System.Threading; 34using System.Threading;
34using System.Text.RegularExpressions; 35using System.Text.RegularExpressions;
36using System.Timers;
35using Nini.Config; 37using Nini.Config;
36using log4net; 38using log4net;
37using OpenMetaverse; 39using OpenMetaverse;
@@ -44,6 +46,7 @@ using OpenSim.Region.CoreModules.World.Land;
44using OpenSim.Region.CoreModules.World.Terrain; 46using OpenSim.Region.CoreModules.World.Terrain;
45using OpenSim.Region.Framework.Interfaces; 47using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Framework.Scenes.Serialization;
47using OpenSim.Region.Framework.Scenes.Animation; 50using OpenSim.Region.Framework.Scenes.Animation;
48using OpenSim.Region.Physics.Manager; 51using OpenSim.Region.Physics.Manager;
49using OpenSim.Region.ScriptEngine.Shared; 52using OpenSim.Region.ScriptEngine.Shared;
@@ -65,6 +68,7 @@ using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
65using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 68using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
66using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; 69using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
67using System.Reflection; 70using System.Reflection;
71using Timer = System.Timers.Timer;
68 72
69namespace OpenSim.Region.ScriptEngine.Shared.Api 73namespace OpenSim.Region.ScriptEngine.Shared.Api
70{ 74{
@@ -103,15 +107,25 @@ 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 114
115 protected Timer m_ShoutSayTimer;
116 protected int m_SayShoutCount = 0;
117
110 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 118 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
111 { 119 {
120 m_ShoutSayTimer = new Timer(1000);
121 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
122 m_ShoutSayTimer.AutoReset = true;
123 m_ShoutSayTimer.Start();
124
112 m_ScriptEngine = ScriptEngine; 125 m_ScriptEngine = ScriptEngine;
113 m_host = host; 126 m_host = host;
114 m_item = item; 127 m_item = item;
128 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
115 129
116 m_ScriptDelayFactor = 130 m_ScriptDelayFactor =
117 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 131 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
@@ -159,6 +173,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
159 get { return m_ScriptEngine.World; } 173 get { return m_ScriptEngine.World; }
160 } 174 }
161 175
176 [DebuggerNonUserCode]
162 public void state(string newState) 177 public void state(string newState)
163 { 178 {
164 m_ScriptEngine.SetState(m_item.ItemID, newState); 179 m_ScriptEngine.SetState(m_item.ItemID, newState);
@@ -168,6 +183,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
168 /// Reset the named script. The script must be present 183 /// Reset the named script. The script must be present
169 /// in the same prim. 184 /// in the same prim.
170 /// </summary> 185 /// </summary>
186 [DebuggerNonUserCode]
171 public void llResetScript() 187 public void llResetScript()
172 { 188 {
173 m_host.AddScriptLPS(1); 189 m_host.AddScriptLPS(1);
@@ -224,9 +240,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
224 } 240 }
225 } 241 }
226 242
243 public List<ScenePresence> GetLinkAvatars(int linkType)
244 {
245 List<ScenePresence> ret = new List<ScenePresence>();
246 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
247 return ret;
248
249 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
250
251 switch (linkType)
252 {
253 case ScriptBaseClass.LINK_SET:
254 return avs;
255
256 case ScriptBaseClass.LINK_ROOT:
257 return ret;
258
259 case ScriptBaseClass.LINK_ALL_OTHERS:
260 return avs;
261
262 case ScriptBaseClass.LINK_ALL_CHILDREN:
263 return avs;
264
265 case ScriptBaseClass.LINK_THIS:
266 return ret;
267
268 default:
269 if (linkType < 0)
270 return ret;
271
272 int partCount = m_host.ParentGroup.GetPartCount();
273
274 if (linkType <= partCount)
275 {
276 return ret;
277 }
278 else
279 {
280 linkType = linkType - partCount;
281 if (linkType > avs.Count)
282 {
283 return ret;
284 }
285 else
286 {
287 ret.Add(avs[linkType-1]);
288 return ret;
289 }
290 }
291 }
292 }
293
227 public List<SceneObjectPart> GetLinkParts(int linkType) 294 public List<SceneObjectPart> GetLinkParts(int linkType)
228 { 295 {
229 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 296 List<SceneObjectPart> ret = new List<SceneObjectPart>();
297 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
298 return ret;
230 ret.Add(m_host); 299 ret.Add(m_host);
231 300
232 switch (linkType) 301 switch (linkType)
@@ -273,21 +342,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
273 protected UUID InventoryKey(string name, int type) 342 protected UUID InventoryKey(string name, int type)
274 { 343 {
275 m_host.AddScriptLPS(1); 344 m_host.AddScriptLPS(1);
276 345 m_host.TaskInventory.LockItemsForRead(true);
277 lock (m_host.TaskInventory) 346
347 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
278 { 348 {
279 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 349 if (inv.Value.Name == name)
280 { 350 {
281 if (inv.Value.Name == name) 351 m_host.TaskInventory.LockItemsForRead(false);
352
353 if (inv.Value.Type != type)
282 { 354 {
283 if (inv.Value.Type != type) 355 return UUID.Zero;
284 return UUID.Zero;
285
286 return inv.Value.AssetID;
287 } 356 }
357
358 return inv.Value.AssetID;
288 } 359 }
289 } 360 }
290 361
362 m_host.TaskInventory.LockItemsForRead(false);
291 return UUID.Zero; 363 return UUID.Zero;
292 } 364 }
293 365
@@ -295,17 +367,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
295 { 367 {
296 m_host.AddScriptLPS(1); 368 m_host.AddScriptLPS(1);
297 369
298 lock (m_host.TaskInventory) 370
371 m_host.TaskInventory.LockItemsForRead(true);
372
373 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
299 { 374 {
300 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 375 if (inv.Value.Name == name)
301 { 376 {
302 if (inv.Value.Name == name) 377 m_host.TaskInventory.LockItemsForRead(false);
303 { 378 return inv.Value.AssetID;
304 return inv.Value.AssetID;
305 }
306 } 379 }
307 } 380 }
308 381
382 m_host.TaskInventory.LockItemsForRead(false);
383
384
309 return UUID.Zero; 385 return UUID.Zero;
310 } 386 }
311 387
@@ -447,31 +523,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
447 523
448 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 524 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
449 525
450 /// <summary> 526 // Utility function for llRot2Euler
451 /// Convert an LSL rotation to a Euler vector. 527
452 /// </summary> 528 // normalize an angle between -PI and PI (-180 to +180 degrees)
453 /// <remarks> 529 protected double NormalizeAngle(double angle)
454 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
455 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
456 /// </remarks>
457 /// <param name="r"></param>
458 /// <returns></returns>
459 public LSL_Vector llRot2Euler(LSL_Rotation r)
460 { 530 {
461 m_host.AddScriptLPS(1); 531 if (angle > -Math.PI && angle < Math.PI)
532 return angle;
462 533
463 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 534 int numPis = (int)(Math.PI / angle);
464 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 535 double remainder = angle - Math.PI * numPis;
465 if (m == 0.0) return new LSL_Vector(); 536 if (numPis % 2 == 1)
466 double x = Math.Atan2(-v.y, v.z); 537 return Math.PI - angle;
467 double sin = v.x / m; 538 return remainder;
468 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. 539 }
469 double y = Math.Asin(sin);
470 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
471 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)));
472 double z = Math.Atan2(v.y, v.x);
473 540
474 return new LSL_Vector(x, y, z); 541 public LSL_Vector llRot2Euler(LSL_Rotation q1)
542 {
543 m_host.AddScriptLPS(1);
544 LSL_Vector eul = new LSL_Vector();
545
546 double sqw = q1.s*q1.s;
547 double sqx = q1.x*q1.x;
548 double sqy = q1.z*q1.z;
549 double sqz = q1.y*q1.y;
550 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
551 double test = q1.x*q1.z + q1.y*q1.s;
552 if (test > 0.4999*unit) { // singularity at north pole
553 eul.z = 2 * Math.Atan2(q1.x,q1.s);
554 eul.y = Math.PI/2;
555 eul.x = 0;
556 return eul;
557 }
558 if (test < -0.4999*unit) { // singularity at south pole
559 eul.z = -2 * Math.Atan2(q1.x,q1.s);
560 eul.y = -Math.PI/2;
561 eul.x = 0;
562 return eul;
563 }
564 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
565 eul.y = Math.Asin(2*test/unit);
566 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
567 return eul;
475 } 568 }
476 569
477 /* From wiki: 570 /* From wiki:
@@ -673,77 +766,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
673 { 766 {
674 //A and B should both be normalized 767 //A and B should both be normalized
675 m_host.AddScriptLPS(1); 768 m_host.AddScriptLPS(1);
676 LSL_Rotation rotBetween; 769 /* This method is more accurate than the SL one, and thus causes problems
677 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 770 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
678 // continue calculation. 771
679 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 772 double dotProduct = LSL_Vector.Dot(a, b);
773 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
774 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
775 double angle = Math.Acos(dotProduct / magProduct);
776 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
777 double s = Math.Sin(angle / 2);
778
779 double x = axis.x * s;
780 double y = axis.y * s;
781 double z = axis.z * s;
782 double w = Math.Cos(angle / 2);
783
784 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
785 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
786
787 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
788 */
789
790 // This method mimics the 180 errors found in SL
791 // See www.euclideanspace.com... angleBetween
792 LSL_Vector vec_a = a;
793 LSL_Vector vec_b = b;
794
795 // Eliminate zero length
796 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
797 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
798 if (vec_a_mag < 0.00001 ||
799 vec_b_mag < 0.00001)
680 { 800 {
681 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 801 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
682 } 802 }
683 else 803
804 // Normalize
805 vec_a = llVecNorm(vec_a);
806 vec_b = llVecNorm(vec_b);
807
808 // Calculate axis and rotation angle
809 LSL_Vector axis = vec_a % vec_b;
810 LSL_Float cos_theta = vec_a * vec_b;
811
812 // Check if parallel
813 if (cos_theta > 0.99999)
684 { 814 {
685 a = LSL_Vector.Norm(a); 815 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
686 b = LSL_Vector.Norm(b); 816 }
687 double dotProduct = LSL_Vector.Dot(a, b); 817
688 // There are two degenerate cases possible. These are for vectors 180 or 818 // Check if anti-parallel
689 // 0 degrees apart. These have to be detected and handled individually. 819 else if (cos_theta < -0.99999)
690 // 820 {
691 // Check for vectors 180 degrees apart. 821 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
692 // A dot product of -1 would mean the angle between vectors is 180 degrees. 822 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
693 if (dotProduct < -0.9999999f) 823 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
694 { 824 }
695 // First assume X axis is orthogonal to the vectors. 825 else // other rotation
696 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 826 {
697 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 827 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
698 // Check for near zero vector. A very small non-zero number here will create 828 axis = llVecNorm(axis);
699 // a rotation in an undesired direction. 829 double x, y, z, s, t;
700 if (LSL_Vector.Mag(orthoVector) > 0.0001) 830 s = Math.Cos(theta);
701 { 831 t = Math.Sin(theta);
702 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 832 x = axis.x * t;
703 } 833 y = axis.y * t;
704 // If the magnitude of the vector was near zero, then assume the X axis is not 834 z = axis.z * t;
705 // orthogonal and use the Z axis instead. 835 return new LSL_Rotation(x,y,z,s);
706 else
707 {
708 // Set 180 z rotation.
709 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
710 }
711 }
712 // Check for parallel vectors.
713 // A dot product of 1 would mean the angle between vectors is 0 degrees.
714 else if (dotProduct > 0.9999999f)
715 {
716 // Set zero rotation.
717 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
718 }
719 else
720 {
721 // All special checks have been performed so get the axis of rotation.
722 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
723 // Quarternion s value is the length of the unit vector + dot product.
724 double qs = 1.0 + dotProduct;
725 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
726 // Normalize the rotation.
727 double mag = LSL_Rotation.Mag(rotBetween);
728 // We shouldn't have to worry about a divide by zero here. The qs value will be
729 // non-zero because we already know if we're here, then the dotProduct is not -1 so
730 // qs will not be zero. Also, we've already handled the input vectors being zero so the
731 // crossProduct vector should also not be zero.
732 rotBetween.x = rotBetween.x / mag;
733 rotBetween.y = rotBetween.y / mag;
734 rotBetween.z = rotBetween.z / mag;
735 rotBetween.s = rotBetween.s / mag;
736 // Check for undefined values and set zero rotation if any found. This code might not actually be required
737 // any longer since zero vectors are checked for at the top.
738 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
739 {
740 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
741 }
742 }
743 } 836 }
744 return rotBetween;
745 } 837 }
746 838
747 public void llWhisper(int channelID, string text) 839 public void llWhisper(int channelID, string text)
748 { 840 {
749 m_host.AddScriptLPS(1); 841 m_host.AddScriptLPS(1);
@@ -763,6 +855,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
763 { 855 {
764 m_host.AddScriptLPS(1); 856 m_host.AddScriptLPS(1);
765 857
858 if (channelID == 0)
859 m_SayShoutCount++;
860
861 if (m_SayShoutCount >= 11)
862 ScriptSleep(2000);
863
766 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 864 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
767 { 865 {
768 Console.WriteLine(text); 866 Console.WriteLine(text);
@@ -785,6 +883,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
785 { 883 {
786 m_host.AddScriptLPS(1); 884 m_host.AddScriptLPS(1);
787 885
886 if (channelID == 0)
887 m_SayShoutCount++;
888
889 if (m_SayShoutCount >= 11)
890 ScriptSleep(2000);
891
788 if (text.Length > 1023) 892 if (text.Length > 1023)
789 text = text.Substring(0, 1023); 893 text = text.Substring(0, 1023);
790 894
@@ -1087,10 +1191,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1087 return detectedParams.TouchUV; 1191 return detectedParams.TouchUV;
1088 } 1192 }
1089 1193
1194 [DebuggerNonUserCode]
1090 public virtual void llDie() 1195 public virtual void llDie()
1091 { 1196 {
1092 m_host.AddScriptLPS(1); 1197 m_host.AddScriptLPS(1);
1093 throw new SelfDeleteException(); 1198 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1094 } 1199 }
1095 1200
1096 public LSL_Float llGround(LSL_Vector offset) 1201 public LSL_Float llGround(LSL_Vector offset)
@@ -1163,6 +1268,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1163 1268
1164 public void llSetStatus(int status, int value) 1269 public void llSetStatus(int status, int value)
1165 { 1270 {
1271 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1272 return;
1166 m_host.AddScriptLPS(1); 1273 m_host.AddScriptLPS(1);
1167 1274
1168 int statusrotationaxis = 0; 1275 int statusrotationaxis = 0;
@@ -1394,6 +1501,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1394 { 1501 {
1395 m_host.AddScriptLPS(1); 1502 m_host.AddScriptLPS(1);
1396 1503
1504 SetColor(m_host, color, face);
1505 }
1506
1507 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1508 {
1509 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1510 return;
1511
1512 Primitive.TextureEntry tex = part.Shape.Textures;
1513 Color4 texcolor;
1514 if (face >= 0 && face < GetNumberOfSides(part))
1515 {
1516 texcolor = tex.CreateFace((uint)face).RGBA;
1517 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1518 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1519 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1520 tex.FaceTextures[face].RGBA = texcolor;
1521 part.UpdateTextureEntry(tex.GetBytes());
1522 return;
1523 }
1524 else if (face == ScriptBaseClass.ALL_SIDES)
1525 {
1526 for (uint i = 0; i < GetNumberOfSides(part); i++)
1527 {
1528 if (tex.FaceTextures[i] != null)
1529 {
1530 texcolor = tex.FaceTextures[i].RGBA;
1531 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1532 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1533 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1534 tex.FaceTextures[i].RGBA = texcolor;
1535 }
1536 texcolor = tex.DefaultTexture.RGBA;
1537 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1538 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1539 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1540 tex.DefaultTexture.RGBA = texcolor;
1541 }
1542 part.UpdateTextureEntry(tex.GetBytes());
1543 return;
1544 }
1545
1397 if (face == ScriptBaseClass.ALL_SIDES) 1546 if (face == ScriptBaseClass.ALL_SIDES)
1398 face = SceneObjectPart.ALL_SIDES; 1547 face = SceneObjectPart.ALL_SIDES;
1399 1548
@@ -1402,6 +1551,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1402 1551
1403 public void SetTexGen(SceneObjectPart part, int face,int style) 1552 public void SetTexGen(SceneObjectPart part, int face,int style)
1404 { 1553 {
1554 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1555 return;
1556
1405 Primitive.TextureEntry tex = part.Shape.Textures; 1557 Primitive.TextureEntry tex = part.Shape.Textures;
1406 MappingType textype; 1558 MappingType textype;
1407 textype = MappingType.Default; 1559 textype = MappingType.Default;
@@ -1432,6 +1584,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1432 1584
1433 public void SetGlow(SceneObjectPart part, int face, float glow) 1585 public void SetGlow(SceneObjectPart part, int face, float glow)
1434 { 1586 {
1587 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1588 return;
1589
1435 Primitive.TextureEntry tex = part.Shape.Textures; 1590 Primitive.TextureEntry tex = part.Shape.Textures;
1436 if (face >= 0 && face < GetNumberOfSides(part)) 1591 if (face >= 0 && face < GetNumberOfSides(part))
1437 { 1592 {
@@ -1457,6 +1612,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1457 1612
1458 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1613 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1459 { 1614 {
1615 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1616 return;
1460 1617
1461 Shininess sval = new Shininess(); 1618 Shininess sval = new Shininess();
1462 1619
@@ -1507,6 +1664,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1507 1664
1508 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1665 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1509 { 1666 {
1667 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1668 return;
1669
1510 Primitive.TextureEntry tex = part.Shape.Textures; 1670 Primitive.TextureEntry tex = part.Shape.Textures;
1511 if (face >= 0 && face < GetNumberOfSides(part)) 1671 if (face >= 0 && face < GetNumberOfSides(part))
1512 { 1672 {
@@ -1567,13 +1727,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1567 m_host.AddScriptLPS(1); 1727 m_host.AddScriptLPS(1);
1568 1728
1569 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1729 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1570 1730 if (parts.Count > 0)
1571 foreach (SceneObjectPart part in parts) 1731 {
1572 SetAlpha(part, alpha, face); 1732 try
1733 {
1734 parts[0].ParentGroup.areUpdatesSuspended = true;
1735 foreach (SceneObjectPart part in parts)
1736 SetAlpha(part, alpha, face);
1737 }
1738 finally
1739 {
1740 parts[0].ParentGroup.areUpdatesSuspended = false;
1741 }
1742 }
1573 } 1743 }
1574 1744
1575 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1745 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1576 { 1746 {
1747 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1748 return;
1749
1577 Primitive.TextureEntry tex = part.Shape.Textures; 1750 Primitive.TextureEntry tex = part.Shape.Textures;
1578 Color4 texcolor; 1751 Color4 texcolor;
1579 if (face >= 0 && face < GetNumberOfSides(part)) 1752 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1626,7 +1799,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1626 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1799 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1627 float wind, float tension, LSL_Vector Force) 1800 float wind, float tension, LSL_Vector Force)
1628 { 1801 {
1629 if (part == null) 1802 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1630 return; 1803 return;
1631 1804
1632 if (flexi) 1805 if (flexi)
@@ -1660,7 +1833,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1660 /// <param name="falloff"></param> 1833 /// <param name="falloff"></param>
1661 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1834 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1662 { 1835 {
1663 if (part == null) 1836 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1664 return; 1837 return;
1665 1838
1666 if (light) 1839 if (light)
@@ -1738,15 +1911,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1738 m_host.AddScriptLPS(1); 1911 m_host.AddScriptLPS(1);
1739 1912
1740 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1913 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1741 1914 if (parts.Count > 0)
1742 foreach (SceneObjectPart part in parts) 1915 {
1743 SetTexture(part, texture, face); 1916 try
1744 1917 {
1918 parts[0].ParentGroup.areUpdatesSuspended = true;
1919 foreach (SceneObjectPart part in parts)
1920 SetTexture(part, texture, face);
1921 }
1922 finally
1923 {
1924 parts[0].ParentGroup.areUpdatesSuspended = false;
1925 }
1926 }
1745 ScriptSleep(200); 1927 ScriptSleep(200);
1746 } 1928 }
1747 1929
1748 protected void SetTexture(SceneObjectPart part, string texture, int face) 1930 protected void SetTexture(SceneObjectPart part, string texture, int face)
1749 { 1931 {
1932 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1933 return;
1934
1750 UUID textureID = new UUID(); 1935 UUID textureID = new UUID();
1751 1936
1752 textureID = InventoryKey(texture, (int)AssetType.Texture); 1937 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1791,6 +1976,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1791 1976
1792 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 1977 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1793 { 1978 {
1979 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1980 return;
1981
1794 Primitive.TextureEntry tex = part.Shape.Textures; 1982 Primitive.TextureEntry tex = part.Shape.Textures;
1795 if (face >= 0 && face < GetNumberOfSides(part)) 1983 if (face >= 0 && face < GetNumberOfSides(part))
1796 { 1984 {
@@ -1827,6 +2015,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1827 2015
1828 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2016 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1829 { 2017 {
2018 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2019 return;
2020
1830 Primitive.TextureEntry tex = part.Shape.Textures; 2021 Primitive.TextureEntry tex = part.Shape.Textures;
1831 if (face >= 0 && face < GetNumberOfSides(part)) 2022 if (face >= 0 && face < GetNumberOfSides(part))
1832 { 2023 {
@@ -1863,6 +2054,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1863 2054
1864 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2055 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1865 { 2056 {
2057 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2058 return;
2059
1866 Primitive.TextureEntry tex = part.Shape.Textures; 2060 Primitive.TextureEntry tex = part.Shape.Textures;
1867 if (face >= 0 && face < GetNumberOfSides(part)) 2061 if (face >= 0 && face < GetNumberOfSides(part))
1868 { 2062 {
@@ -1967,26 +2161,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1967 return real_vec; 2161 return real_vec;
1968 } 2162 }
1969 2163
2164 public LSL_Integer llSetRegionPos(LSL_Vector pos)
2165 {
2166 return new LSL_Integer(SetRegionPos(m_host, pos));
2167 }
2168
2169 protected int SetRegionPos(SceneObjectPart part, LSL_Vector targetPos)
2170 {
2171 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2172 return 0;
2173
2174 SceneObjectGroup grp = part.ParentGroup;
2175
2176 if (grp.IsAttachment)
2177 return 0;
2178
2179 if (grp.RootPart.PhysActor != null && grp.RootPart.PhysActor.IsPhysical)
2180 return 0;
2181
2182 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)
2183 return 0;
2184
2185 float constrainedX = (float)targetPos.x;
2186 float constrainedY = (float)targetPos.y;
2187
2188 if (constrainedX < 0.0f)
2189 constrainedX = 0.0f;
2190 if (constrainedY < 0.0f)
2191 constrainedY = 0.0f;
2192 if (constrainedX >= (float)Constants.RegionSize)
2193 constrainedX = (float)Constants.RegionSize - 0.1f;
2194 if (constrainedY >= (float)Constants.RegionSize)
2195 constrainedY = (float)Constants.RegionSize -0.1f;
2196
2197 float ground = World.GetGroundHeight(constrainedX, constrainedY);
2198
2199 if (targetPos.z < ground)
2200 targetPos.z = ground;
2201
2202 Vector3 dest = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z);
2203
2204 if (!World.Permissions.CanObjectEntry(grp.UUID, false, dest))
2205 return 0;
2206
2207 grp.UpdateGroupPosition(dest);
2208
2209 return 1;
2210 }
2211
1970 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2212 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1971 { 2213 {
1972 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2214 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2215 return;
2216
1973 LSL_Vector currentPos = GetPartLocalPos(part); 2217 LSL_Vector currentPos = GetPartLocalPos(part);
2218 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
1974 2219
1975 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
1976 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
1977 2220
1978 if (part.ParentGroup.RootPart == part) 2221 if (part.ParentGroup.RootPart == part)
1979 { 2222 {
1980 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
1981 targetPos.z = ground;
1982 SceneObjectGroup parent = part.ParentGroup; 2223 SceneObjectGroup parent = part.ParentGroup;
1983 LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); 2224 Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
1984 parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z)); 2225 if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest))
2226 return;
2227 Util.FireAndForget(delegate(object x) {
2228 parent.UpdateGroupPosition(dest);
2229 });
1985 } 2230 }
1986 else 2231 else
1987 { 2232 {
1988 LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); 2233 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
1989 part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z);
1990 SceneObjectGroup parent = part.ParentGroup; 2234 SceneObjectGroup parent = part.ParentGroup;
1991 parent.HasGroupChanged = true; 2235 parent.HasGroupChanged = true;
1992 parent.ScheduleGroupForTerseUpdate(); 2236 parent.ScheduleGroupForTerseUpdate();
@@ -2019,17 +2263,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2019 else 2263 else
2020 { 2264 {
2021 if (part.ParentGroup.IsAttachment) 2265 if (part.ParentGroup.IsAttachment)
2022 {
2023 pos = part.AttachedPos; 2266 pos = part.AttachedPos;
2024 }
2025 else 2267 else
2026 {
2027 pos = part.AbsolutePosition; 2268 pos = part.AbsolutePosition;
2028 }
2029 } 2269 }
2030 2270
2031// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2032
2033 return new LSL_Vector(pos.X, pos.Y, pos.Z); 2271 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2034 } 2272 }
2035 2273
@@ -2038,9 +2276,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2038 m_host.AddScriptLPS(1); 2276 m_host.AddScriptLPS(1);
2039 2277
2040 // try to let this work as in SL... 2278 // try to let this work as in SL...
2041 if (m_host.ParentID == 0) 2279 if (m_host.LinkNum < 2)
2042 { 2280 {
2043 // special case: If we are root, rotate complete SOG to new rotation 2281 // Special case: If we are root, rotate complete SOG to new
2282 // rotation.
2283 // We are root if the link number is 0 (single prim) or 1
2284 // (root prim). ParentID may be nonzero in attachments and
2285 // using it would cause attachments and HUDs to rotate
2286 // to the wrong positions.
2044 SetRot(m_host, Rot2Quaternion(rot)); 2287 SetRot(m_host, Rot2Quaternion(rot));
2045 } 2288 }
2046 else 2289 else
@@ -2065,6 +2308,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2065 2308
2066 protected void SetRot(SceneObjectPart part, Quaternion rot) 2309 protected void SetRot(SceneObjectPart part, Quaternion rot)
2067 { 2310 {
2311 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2312 return;
2313
2068 part.UpdateRotation(rot); 2314 part.UpdateRotation(rot);
2069 // Update rotation does not move the object in the physics scene if it's a linkset. 2315 // Update rotation does not move the object in the physics scene if it's a linkset.
2070 2316
@@ -2219,13 +2465,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2219 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2465 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2220 { 2466 {
2221 m_host.AddScriptLPS(1); 2467 m_host.AddScriptLPS(1);
2222 m_host.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); 2468 m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
2223 } 2469 }
2224 2470
2225 public void llSetTorque(LSL_Vector torque, int local) 2471 public void llSetTorque(LSL_Vector torque, int local)
2226 { 2472 {
2227 m_host.AddScriptLPS(1); 2473 m_host.AddScriptLPS(1);
2228 m_host.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); 2474 m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0);
2229 } 2475 }
2230 2476
2231 public LSL_Vector llGetTorque() 2477 public LSL_Vector llGetTorque()
@@ -2827,35 +3073,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2827 public void llLookAt(LSL_Vector target, double strength, double damping) 3073 public void llLookAt(LSL_Vector target, double strength, double damping)
2828 { 3074 {
2829 m_host.AddScriptLPS(1); 3075 m_host.AddScriptLPS(1);
2830 // Determine where we are looking from
2831 LSL_Vector from = llGetPos();
2832 3076
2833 // Work out the normalised vector from the source to the target 3077 // Get the normalized vector to the target
2834 LSL_Vector delta = llVecNorm(target - from); 3078 LSL_Vector d1 = llVecNorm(target - llGetPos());
2835 LSL_Vector angle = new LSL_Vector(0,0,0);
2836 3079
2837 // Calculate the yaw 3080 // Get the bearing (yaw)
2838 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3081 LSL_Vector a1 = new LSL_Vector(0,0,0);
2839 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3082 a1.z = llAtan2(d1.y, d1.x);
2840 3083
2841 // Calculate pitch 3084 // Get the elevation (pitch)
2842 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3085 LSL_Vector a2 = new LSL_Vector(0,0,0);
3086 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2843 3087
2844 // we need to convert from a vector describing 3088 LSL_Rotation r1 = llEuler2Rot(a1);
2845 // the angles of rotation in radians into rotation value 3089 LSL_Rotation r2 = llEuler2Rot(a2);
2846 LSL_Rotation rot = llEuler2Rot(angle); 3090 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2847
2848 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2849 // set the rotation of the object, copy that behavior
2850 PhysicsActor pa = m_host.PhysActor;
2851 3091
2852 if (strength == 0 || pa == null || !pa.IsPhysical) 3092 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2853 { 3093 {
2854 llSetRot(rot); 3094 // Do nothing if either value is 0 (this has been checked in SL)
3095 if (strength <= 0.0 || damping <= 0.0)
3096 return;
3097
3098 llSetRot(r3 * r2 * r1);
2855 } 3099 }
2856 else 3100 else
2857 { 3101 {
2858 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3102 if (strength == 0)
3103 {
3104 llSetRot(r3 * r2 * r1);
3105 return;
3106 }
3107
3108 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2859 } 3109 }
2860 } 3110 }
2861 3111
@@ -2900,17 +3150,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2900 } 3150 }
2901 else 3151 else
2902 { 3152 {
2903 if (m_host.IsRoot) 3153 // new SL always returns object mass
2904 { 3154// if (m_host.IsRoot)
3155// {
2905 return m_host.ParentGroup.GetMass(); 3156 return m_host.ParentGroup.GetMass();
2906 } 3157// }
2907 else 3158// else
2908 { 3159// {
2909 return m_host.GetMass(); 3160// return m_host.GetMass();
2910 } 3161// }
2911 } 3162 }
2912 } 3163 }
2913 3164
3165
3166 public LSL_Float llGetMassMKS()
3167 {
3168 return 100f * llGetMass();
3169 }
3170
2914 public void llCollisionFilter(string name, string id, int accept) 3171 public void llCollisionFilter(string name, string id, int accept)
2915 { 3172 {
2916 m_host.AddScriptLPS(1); 3173 m_host.AddScriptLPS(1);
@@ -3017,9 +3274,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3017 { 3274 {
3018 m_host.AddScriptLPS(1); 3275 m_host.AddScriptLPS(1);
3019 3276
3020// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3021// return;
3022
3023 if (m_item.PermsGranter != m_host.OwnerID) 3277 if (m_item.PermsGranter != m_host.OwnerID)
3024 return; 3278 return;
3025 3279
@@ -3062,6 +3316,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3062 3316
3063 public void llInstantMessage(string user, string message) 3317 public void llInstantMessage(string user, string message)
3064 { 3318 {
3319 UUID result;
3320 if (!UUID.TryParse(user, out result))
3321 {
3322 ShoutError("An invalid key was passed to llInstantMessage");
3323 ScriptSleep(2000);
3324 return;
3325 }
3326
3327
3065 m_host.AddScriptLPS(1); 3328 m_host.AddScriptLPS(1);
3066 3329
3067 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3330 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3076,14 +3339,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3076 UUID friendTransactionID = UUID.Random(); 3339 UUID friendTransactionID = UUID.Random();
3077 3340
3078 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3341 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3079 3342
3080 GridInstantMessage msg = new GridInstantMessage(); 3343 GridInstantMessage msg = new GridInstantMessage();
3081 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3344 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3082 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3345 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3083 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3346 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3084// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3347// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3085// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3348// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3086 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3349// DateTime dt = DateTime.UtcNow;
3350//
3351// // Ticks from UtcNow, but make it look like local. Evil, huh?
3352// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3353//
3354// try
3355// {
3356// // Convert that to the PST timezone
3357// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3358// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3359// }
3360// catch
3361// {
3362// // No logging here, as it could be VERY spammy
3363// }
3364//
3365// // And make it look local again to fool the unix time util
3366// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3367
3368 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3369
3087 //if (client != null) 3370 //if (client != null)
3088 //{ 3371 //{
3089 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3372 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3097,12 +3380,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3097 msg.message = message.Substring(0, 1024); 3380 msg.message = message.Substring(0, 1024);
3098 else 3381 else
3099 msg.message = message; 3382 msg.message = message;
3100 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3383 msg.dialog = (byte)19; // MessageFromObject
3101 msg.fromGroup = false;// fromGroup; 3384 msg.fromGroup = false;// fromGroup;
3102 msg.offline = (byte)0; //offline; 3385 msg.offline = (byte)0; //offline;
3103 msg.ParentEstateID = 0; //ParentEstateID; 3386 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3104 msg.Position = new Vector3(m_host.AbsolutePosition); 3387 msg.Position = new Vector3(m_host.AbsolutePosition);
3105 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3388 msg.RegionID = World.RegionInfo.RegionID.Guid;
3106 msg.binaryBucket 3389 msg.binaryBucket
3107 = Util.StringToBytes256( 3390 = Util.StringToBytes256(
3108 "{0}/{1}/{2}/{3}", 3391 "{0}/{1}/{2}/{3}",
@@ -3130,7 +3413,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3130 } 3413 }
3131 3414
3132 emailModule.SendEmail(m_host.UUID, address, subject, message); 3415 emailModule.SendEmail(m_host.UUID, address, subject, message);
3133 ScriptSleep(20000); 3416 ScriptSleep(15000);
3134 } 3417 }
3135 3418
3136 public void llGetNextEmail(string address, string subject) 3419 public void llGetNextEmail(string address, string subject)
@@ -3379,15 +3662,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3379 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3662 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3380 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3663 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3381 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3664 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3665 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3382 ScriptBaseClass.PERMISSION_ATTACH; 3666 ScriptBaseClass.PERMISSION_ATTACH;
3383 3667
3384 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3668 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3385 { 3669 {
3386 lock (m_host.TaskInventory) 3670 m_host.TaskInventory.LockItemsForWrite(true);
3387 { 3671 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3388 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3672 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3389 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3673 m_host.TaskInventory.LockItemsForWrite(false);
3390 }
3391 3674
3392 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3675 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3393 "run_time_permissions", new Object[] { 3676 "run_time_permissions", new Object[] {
@@ -3397,28 +3680,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3397 return; 3680 return;
3398 } 3681 }
3399 } 3682 }
3400 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3683 else
3401 { 3684 {
3402 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3685 bool sitting = false;
3403 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3686 if (m_host.SitTargetAvatar == agentID)
3404 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3687 {
3405 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3688 sitting = true;
3406 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3689 }
3690 else
3691 {
3692 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3693 {
3694 if (p.SitTargetAvatar == agentID)
3695 sitting = true;
3696 }
3697 }
3407 3698
3408 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3699 if (sitting)
3409 { 3700 {
3410 lock (m_host.TaskInventory) 3701 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3702 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3703 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3704 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3705 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3706
3707 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3411 { 3708 {
3709 m_host.TaskInventory.LockItemsForWrite(true);
3412 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3710 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3413 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3711 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3414 } 3712 m_host.TaskInventory.LockItemsForWrite(false);
3415 3713
3416 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3714 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3417 "run_time_permissions", new Object[] { 3715 "run_time_permissions", new Object[] {
3418 new LSL_Integer(perm) }, 3716 new LSL_Integer(perm) },
3419 new DetectParams[0])); 3717 new DetectParams[0]));
3420 3718
3421 return; 3719 return;
3720 }
3422 } 3721 }
3423 } 3722 }
3424 3723
@@ -3432,11 +3731,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3432 3731
3433 if (!m_waitingForScriptAnswer) 3732 if (!m_waitingForScriptAnswer)
3434 { 3733 {
3435 lock (m_host.TaskInventory) 3734 m_host.TaskInventory.LockItemsForWrite(true);
3436 { 3735 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3437 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3736 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3438 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 3737 m_host.TaskInventory.LockItemsForWrite(false);
3439 }
3440 3738
3441 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3739 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3442 m_waitingForScriptAnswer=true; 3740 m_waitingForScriptAnswer=true;
@@ -3466,11 +3764,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3466 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3764 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3467 llReleaseControls(); 3765 llReleaseControls();
3468 3766
3469 lock (m_host.TaskInventory) 3767 m_host.TaskInventory.LockItemsForWrite(true);
3470 { 3768 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3471 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 3769 m_host.TaskInventory.LockItemsForWrite(false);
3472 } 3770
3473
3474 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3771 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3475 "run_time_permissions", new Object[] { 3772 "run_time_permissions", new Object[] {
3476 new LSL_Integer(answer) }, 3773 new LSL_Integer(answer) },
@@ -3513,14 +3810,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3513 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3810 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3514 { 3811 {
3515 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3812 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3516 3813 if (parts.Count > 0)
3517 foreach (SceneObjectPart part in parts) 3814 {
3518 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3815 try
3816 {
3817 parts[0].ParentGroup.areUpdatesSuspended = true;
3818 foreach (SceneObjectPart part in parts)
3819 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3820 }
3821 finally
3822 {
3823 parts[0].ParentGroup.areUpdatesSuspended = false;
3824 }
3825 }
3519 } 3826 }
3520 3827
3521 public void llCreateLink(string target, int parent) 3828 public void llCreateLink(string target, int parent)
3522 { 3829 {
3523 m_host.AddScriptLPS(1); 3830 m_host.AddScriptLPS(1);
3831
3524 UUID targetID; 3832 UUID targetID;
3525 3833
3526 if (!UUID.TryParse(target, out targetID)) 3834 if (!UUID.TryParse(target, out targetID))
@@ -3626,10 +3934,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3626 // Restructuring Multiple Prims. 3934 // Restructuring Multiple Prims.
3627 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 3935 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3628 parts.Remove(parentPrim.RootPart); 3936 parts.Remove(parentPrim.RootPart);
3629 foreach (SceneObjectPart part in parts) 3937 if (parts.Count > 0)
3630 { 3938 {
3631 parentPrim.DelinkFromGroup(part.LocalId, true); 3939 try
3940 {
3941 parts[0].ParentGroup.areUpdatesSuspended = true;
3942 foreach (SceneObjectPart part in parts)
3943 {
3944 parentPrim.DelinkFromGroup(part.LocalId, true);
3945 }
3946 }
3947 finally
3948 {
3949 parts[0].ParentGroup.areUpdatesSuspended = false;
3950 }
3632 } 3951 }
3952
3633 parentPrim.HasGroupChanged = true; 3953 parentPrim.HasGroupChanged = true;
3634 parentPrim.ScheduleGroupForFullUpdate(); 3954 parentPrim.ScheduleGroupForFullUpdate();
3635 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3955 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3638,12 +3958,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3638 { 3958 {
3639 SceneObjectPart newRoot = parts[0]; 3959 SceneObjectPart newRoot = parts[0];
3640 parts.Remove(newRoot); 3960 parts.Remove(newRoot);
3641 foreach (SceneObjectPart part in parts) 3961
3962 try
3642 { 3963 {
3643 // Required for linking 3964 parts[0].ParentGroup.areUpdatesSuspended = true;
3644 part.ClearUpdateSchedule(); 3965 foreach (SceneObjectPart part in parts)
3645 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 3966 {
3967 part.ClearUpdateSchedule();
3968 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3969 }
3646 } 3970 }
3971 finally
3972 {
3973 parts[0].ParentGroup.areUpdatesSuspended = false;
3974 }
3975
3976
3647 newRoot.ParentGroup.HasGroupChanged = true; 3977 newRoot.ParentGroup.HasGroupChanged = true;
3648 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 3978 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3649 } 3979 }
@@ -3663,6 +3993,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3663 public void llBreakAllLinks() 3993 public void llBreakAllLinks()
3664 { 3994 {
3665 m_host.AddScriptLPS(1); 3995 m_host.AddScriptLPS(1);
3996
3997 TaskInventoryItem item = m_item;
3998
3999 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4000 && !m_automaticLinkPermission)
4001 {
4002 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4003 return;
4004 }
4005
3666 SceneObjectGroup parentPrim = m_host.ParentGroup; 4006 SceneObjectGroup parentPrim = m_host.ParentGroup;
3667 if (parentPrim.AttachmentPoint != 0) 4007 if (parentPrim.AttachmentPoint != 0)
3668 return; // Fail silently if attached 4008 return; // Fail silently if attached
@@ -3682,25 +4022,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3682 public LSL_String llGetLinkKey(int linknum) 4022 public LSL_String llGetLinkKey(int linknum)
3683 { 4023 {
3684 m_host.AddScriptLPS(1); 4024 m_host.AddScriptLPS(1);
3685 List<UUID> keytable = new List<UUID>();
3686 // parse for sitting avatare-uuids
3687 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3688 {
3689 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
3690 keytable.Add(presence.UUID);
3691 });
3692
3693 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3694 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3695 {
3696 return keytable[totalprims - linknum].ToString();
3697 }
3698
3699 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3700 {
3701 return m_host.UUID.ToString();
3702 }
3703
3704 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4025 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3705 if (part != null) 4026 if (part != null)
3706 { 4027 {
@@ -3708,6 +4029,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3708 } 4029 }
3709 else 4030 else
3710 { 4031 {
4032 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4033 {
4034 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4035
4036 if (linknum < 0)
4037 return UUID.Zero.ToString();
4038
4039 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4040 if (avatars.Count > linknum)
4041 {
4042 return avatars[linknum].UUID.ToString();
4043 }
4044 }
3711 return UUID.Zero.ToString(); 4045 return UUID.Zero.ToString();
3712 } 4046 }
3713 } 4047 }
@@ -3807,17 +4141,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3807 m_host.AddScriptLPS(1); 4141 m_host.AddScriptLPS(1);
3808 int count = 0; 4142 int count = 0;
3809 4143
3810 lock (m_host.TaskInventory) 4144 m_host.TaskInventory.LockItemsForRead(true);
4145 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3811 { 4146 {
3812 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4147 if (inv.Value.Type == type || type == -1)
3813 { 4148 {
3814 if (inv.Value.Type == type || type == -1) 4149 count = count + 1;
3815 {
3816 count = count + 1;
3817 }
3818 } 4150 }
3819 } 4151 }
3820 4152
4153 m_host.TaskInventory.LockItemsForRead(false);
3821 return count; 4154 return count;
3822 } 4155 }
3823 4156
@@ -3826,16 +4159,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3826 m_host.AddScriptLPS(1); 4159 m_host.AddScriptLPS(1);
3827 ArrayList keys = new ArrayList(); 4160 ArrayList keys = new ArrayList();
3828 4161
3829 lock (m_host.TaskInventory) 4162 m_host.TaskInventory.LockItemsForRead(true);
4163 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3830 { 4164 {
3831 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4165 if (inv.Value.Type == type || type == -1)
3832 { 4166 {
3833 if (inv.Value.Type == type || type == -1) 4167 keys.Add(inv.Value.Name);
3834 {
3835 keys.Add(inv.Value.Name);
3836 }
3837 } 4168 }
3838 } 4169 }
4170 m_host.TaskInventory.LockItemsForRead(false);
3839 4171
3840 if (keys.Count == 0) 4172 if (keys.Count == 0)
3841 { 4173 {
@@ -3872,25 +4204,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3872 } 4204 }
3873 4205
3874 // move the first object found with this inventory name 4206 // move the first object found with this inventory name
3875 lock (m_host.TaskInventory) 4207 m_host.TaskInventory.LockItemsForRead(true);
4208 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3876 { 4209 {
3877 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4210 if (inv.Value.Name == inventory)
3878 { 4211 {
3879 if (inv.Value.Name == inventory) 4212 found = true;
3880 { 4213 objId = inv.Key;
3881 found = true; 4214 assetType = inv.Value.Type;
3882 objId = inv.Key; 4215 objName = inv.Value.Name;
3883 assetType = inv.Value.Type; 4216 break;
3884 objName = inv.Value.Name;
3885 break;
3886 }
3887 } 4217 }
3888 } 4218 }
4219 m_host.TaskInventory.LockItemsForRead(false);
3889 4220
3890 if (!found) 4221 if (!found)
3891 { 4222 {
3892 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4223 llSay(0, String.Format("Could not find object '{0}'", inventory));
3893 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4224 return;
4225// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3894 } 4226 }
3895 4227
3896 // check if destination is an object 4228 // check if destination is an object
@@ -3916,48 +4248,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3916 return; 4248 return;
3917 } 4249 }
3918 } 4250 }
4251
3919 // destination is an avatar 4252 // destination is an avatar
3920 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4253 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3921 4254
3922 if (agentItem == null) 4255 if (agentItem == null)
3923 return; 4256 return;
3924 4257
3925 byte[] bucket = new byte[17]; 4258 byte[] bucket = new byte[1];
3926 bucket[0] = (byte)assetType; 4259 bucket[0] = (byte)assetType;
3927 byte[] objBytes = agentItem.ID.GetBytes(); 4260 //byte[] objBytes = agentItem.ID.GetBytes();
3928 Array.Copy(objBytes, 0, bucket, 1, 16); 4261 //Array.Copy(objBytes, 0, bucket, 1, 16);
3929 4262
3930 GridInstantMessage msg = new GridInstantMessage(World, 4263 GridInstantMessage msg = new GridInstantMessage(World,
3931 m_host.UUID, m_host.Name+", an object owned by "+ 4264 m_host.OwnerID, m_host.Name, destId,
3932 resolveName(m_host.OwnerID)+",", destId,
3933 (byte)InstantMessageDialog.TaskInventoryOffered, 4265 (byte)InstantMessageDialog.TaskInventoryOffered,
3934 false, objName+"\n"+m_host.Name+" is located at "+ 4266 false, objName+". "+m_host.Name+" is located at "+
3935 World.RegionInfo.RegionName+" "+ 4267 World.RegionInfo.RegionName+" "+
3936 m_host.AbsolutePosition.ToString(), 4268 m_host.AbsolutePosition.ToString(),
3937 agentItem.ID, true, m_host.AbsolutePosition, 4269 agentItem.ID, true, m_host.AbsolutePosition,
3938 bucket); 4270 bucket);
3939 if (m_TransferModule != null) 4271
3940 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4272 ScenePresence sp;
4273
4274 if (World.TryGetScenePresence(destId, out sp))
4275 {
4276 sp.ControllingClient.SendInstantMessage(msg);
4277 }
4278 else
4279 {
4280 if (m_TransferModule != null)
4281 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4282 }
4283
4284 //This delay should only occur when giving inventory to avatars.
3941 ScriptSleep(3000); 4285 ScriptSleep(3000);
3942 } 4286 }
3943 } 4287 }
3944 4288
4289 [DebuggerNonUserCode]
3945 public void llRemoveInventory(string name) 4290 public void llRemoveInventory(string name)
3946 { 4291 {
3947 m_host.AddScriptLPS(1); 4292 m_host.AddScriptLPS(1);
3948 4293
3949 lock (m_host.TaskInventory) 4294 List<TaskInventoryItem> inv;
4295 try
3950 { 4296 {
3951 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4297 m_host.TaskInventory.LockItemsForRead(true);
4298 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4299 }
4300 finally
4301 {
4302 m_host.TaskInventory.LockItemsForRead(false);
4303 }
4304 foreach (TaskInventoryItem item in inv)
4305 {
4306 if (item.Name == name)
3952 { 4307 {
3953 if (item.Name == name) 4308 if (item.ItemID == m_item.ItemID)
3954 { 4309 throw new ScriptDeleteException();
3955 if (item.ItemID == m_item.ItemID) 4310 else
3956 throw new ScriptDeleteException(); 4311 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3957 else 4312 return;
3958 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3959 return;
3960 }
3961 } 4313 }
3962 } 4314 }
3963 } 4315 }
@@ -3992,115 +4344,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3992 { 4344 {
3993 m_host.AddScriptLPS(1); 4345 m_host.AddScriptLPS(1);
3994 4346
3995 UUID uuid = (UUID)id; 4347 UUID uuid;
3996 PresenceInfo pinfo = null; 4348 if (UUID.TryParse(id, out uuid))
3997 UserAccount account;
3998
3999 UserInfoCacheEntry ce;
4000 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4001 { 4349 {
4002 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4350 PresenceInfo pinfo = null;
4003 if (account == null) 4351 UserAccount account;
4352
4353 UserInfoCacheEntry ce;
4354 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4004 { 4355 {
4005 m_userInfoCache[uuid] = null; // Cache negative 4356 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4006 return UUID.Zero.ToString(); 4357 if (account == null)
4007 } 4358 {
4359 m_userInfoCache[uuid] = null; // Cache negative
4360 return UUID.Zero.ToString();
4361 }
4008 4362
4009 4363
4010 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4364 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4011 if (pinfos != null && pinfos.Length > 0) 4365 if (pinfos != null && pinfos.Length > 0)
4012 {
4013 foreach (PresenceInfo p in pinfos)
4014 { 4366 {
4015 if (p.RegionID != UUID.Zero) 4367 foreach (PresenceInfo p in pinfos)
4016 { 4368 {
4017 pinfo = p; 4369 if (p.RegionID != UUID.Zero)
4370 {
4371 pinfo = p;
4372 }
4018 } 4373 }
4019 } 4374 }
4020 }
4021 4375
4022 ce = new UserInfoCacheEntry(); 4376 ce = new UserInfoCacheEntry();
4023 ce.time = Util.EnvironmentTickCount(); 4377 ce.time = Util.EnvironmentTickCount();
4024 ce.account = account; 4378 ce.account = account;
4025 ce.pinfo = pinfo; 4379 ce.pinfo = pinfo;
4026 } 4380 m_userInfoCache[uuid] = ce;
4027 else 4381 }
4028 { 4382 else
4029 if (ce == null) 4383 {
4030 return UUID.Zero.ToString(); 4384 if (ce == null)
4385 return UUID.Zero.ToString();
4031 4386
4032 account = ce.account; 4387 account = ce.account;
4033 pinfo = ce.pinfo; 4388 pinfo = ce.pinfo;
4034 } 4389 }
4035 4390
4036 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4391 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4037 {
4038 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4039 if (pinfos != null && pinfos.Length > 0)
4040 { 4392 {
4041 foreach (PresenceInfo p in pinfos) 4393 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4394 if (pinfos != null && pinfos.Length > 0)
4042 { 4395 {
4043 if (p.RegionID != UUID.Zero) 4396 foreach (PresenceInfo p in pinfos)
4044 { 4397 {
4045 pinfo = p; 4398 if (p.RegionID != UUID.Zero)
4399 {
4400 pinfo = p;
4401 }
4046 } 4402 }
4047 } 4403 }
4048 } 4404 else
4049 else 4405 pinfo = null;
4050 pinfo = null;
4051 4406
4052 ce.time = Util.EnvironmentTickCount(); 4407 ce.time = Util.EnvironmentTickCount();
4053 ce.pinfo = pinfo; 4408 ce.pinfo = pinfo;
4054 } 4409 }
4055 4410
4056 string reply = String.Empty; 4411 string reply = String.Empty;
4057 4412
4058 switch (data) 4413 switch (data)
4059 { 4414 {
4060 case 1: // DATA_ONLINE (0|1) 4415 case 1: // DATA_ONLINE (0|1)
4061 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4416 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4062 reply = "1"; 4417 reply = "1";
4063 else 4418 else
4064 reply = "0"; 4419 reply = "0";
4065 break; 4420 break;
4066 case 2: // DATA_NAME (First Last) 4421 case 2: // DATA_NAME (First Last)
4067 reply = account.FirstName + " " + account.LastName; 4422 reply = account.FirstName + " " + account.LastName;
4068 break; 4423 break;
4069 case 3: // DATA_BORN (YYYY-MM-DD) 4424 case 3: // DATA_BORN (YYYY-MM-DD)
4070 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4425 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4071 born = born.AddSeconds(account.Created); 4426 born = born.AddSeconds(account.Created);
4072 reply = born.ToString("yyyy-MM-dd"); 4427 reply = born.ToString("yyyy-MM-dd");
4073 break; 4428 break;
4074 case 4: // DATA_RATING (0,0,0,0,0,0) 4429 case 4: // DATA_RATING (0,0,0,0,0,0)
4075 reply = "0,0,0,0,0,0"; 4430 reply = "0,0,0,0,0,0";
4076 break; 4431 break;
4077 case 7: // DATA_USERLEVEL (integer) 4432 case 8: // DATA_PAYINFO (0|1|2|3)
4078 reply = account.UserLevel.ToString(); 4433 reply = "0";
4079 break; 4434 break;
4080 case 8: // DATA_PAYINFO (0|1|2|3) 4435 default:
4081 reply = "0"; 4436 return UUID.Zero.ToString(); // Raise no event
4082 break; 4437 }
4083 default:
4084 return UUID.Zero.ToString(); // Raise no event
4085 }
4086 4438
4087 UUID rq = UUID.Random(); 4439 UUID rq = UUID.Random();
4088 4440
4089 UUID tid = AsyncCommands. 4441 UUID tid = AsyncCommands.
4090 DataserverPlugin.RegisterRequest(m_host.LocalId, 4442 DataserverPlugin.RegisterRequest(m_host.LocalId,
4091 m_item.ItemID, rq.ToString()); 4443 m_item.ItemID, rq.ToString());
4092 4444
4093 AsyncCommands. 4445 AsyncCommands.
4094 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4446 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4095 4447
4096 ScriptSleep(100); 4448 ScriptSleep(100);
4097 return tid.ToString(); 4449 return tid.ToString();
4450 }
4451 else
4452 {
4453 ShoutError("Invalid UUID passed to llRequestAgentData.");
4454 }
4455 return "";
4098 } 4456 }
4099 4457
4100 public LSL_String llRequestInventoryData(string name) 4458 public LSL_String llRequestInventoryData(string name)
4101 { 4459 {
4102 m_host.AddScriptLPS(1); 4460 m_host.AddScriptLPS(1);
4103 4461
4462 //Clone is thread safe
4104 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4463 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4105 4464
4106 foreach (TaskInventoryItem item in itemDictionary.Values) 4465 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4152,19 +4511,64 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4152 if (UUID.TryParse(agent, out agentId)) 4511 if (UUID.TryParse(agent, out agentId))
4153 { 4512 {
4154 ScenePresence presence = World.GetScenePresence(agentId); 4513 ScenePresence presence = World.GetScenePresence(agentId);
4155 if (presence != null) 4514 if (presence != null && presence.PresenceType != PresenceType.Npc)
4156 { 4515 {
4516 // agent must not be a god
4517 if (presence.UserLevel >= 200) return;
4518
4157 // agent must be over the owners land 4519 // agent must be over the owners land
4158 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4520 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4159 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4521 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4160 { 4522 {
4161 World.TeleportClientHome(agentId, presence.ControllingClient); 4523 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4524 {
4525 // They can't be teleported home for some reason
4526 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4527 if (regionInfo != null)
4528 {
4529 World.RequestTeleportLocation(
4530 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4531 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4532 }
4533 }
4162 } 4534 }
4163 } 4535 }
4164 } 4536 }
4165 ScriptSleep(5000); 4537 ScriptSleep(5000);
4166 } 4538 }
4167 4539
4540 public void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt)
4541 {
4542 m_host.AddScriptLPS(1);
4543 UUID agentId = new UUID();
4544 if (UUID.TryParse(agent, out agentId))
4545 {
4546 ScenePresence presence = World.GetScenePresence(agentId);
4547 if (presence != null && presence.PresenceType != PresenceType.Npc)
4548 {
4549 // agent must not be a god
4550 if (presence.GodLevel >= 200) return;
4551
4552 if (simname == String.Empty)
4553 simname = World.RegionInfo.RegionName;
4554
4555 // agent must be over the owners land
4556 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4557 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4558 {
4559 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);
4560 }
4561 else // or must be wearing the prim
4562 {
4563 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4564 {
4565 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);
4566 }
4567 }
4568 }
4569 }
4570 }
4571
4168 public void llTextBox(string agent, string message, int chatChannel) 4572 public void llTextBox(string agent, string message, int chatChannel)
4169 { 4573 {
4170 IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); 4574 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
@@ -4176,7 +4580,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4176 UUID av = new UUID(); 4580 UUID av = new UUID();
4177 if (!UUID.TryParse(agent,out av)) 4581 if (!UUID.TryParse(agent,out av))
4178 { 4582 {
4179 LSLError("First parameter to llDialog needs to be a key"); 4583 //LSLError("First parameter to llDialog needs to be a key");
4180 return; 4584 return;
4181 } 4585 }
4182 4586
@@ -4213,17 +4617,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4213 UUID soundId = UUID.Zero; 4617 UUID soundId = UUID.Zero;
4214 if (!UUID.TryParse(impact_sound, out soundId)) 4618 if (!UUID.TryParse(impact_sound, out soundId))
4215 { 4619 {
4216 lock (m_host.TaskInventory) 4620 m_host.TaskInventory.LockItemsForRead(true);
4621 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4217 { 4622 {
4218 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4623 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4219 { 4624 {
4220 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4625 soundId = item.AssetID;
4221 { 4626 break;
4222 soundId = item.AssetID;
4223 break;
4224 }
4225 } 4627 }
4226 } 4628 }
4629 m_host.TaskInventory.LockItemsForRead(false);
4227 } 4630 }
4228 m_host.CollisionSound = soundId; 4631 m_host.CollisionSound = soundId;
4229 m_host.CollisionSoundVolume = (float)impact_volume; 4632 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4263,6 +4666,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4263 UUID partItemID; 4666 UUID partItemID;
4264 foreach (SceneObjectPart part in parts) 4667 foreach (SceneObjectPart part in parts)
4265 { 4668 {
4669 //Clone is thread safe
4266 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4670 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4267 4671
4268 foreach (TaskInventoryItem item in itemsDictionary.Values) 4672 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4396,7 +4800,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4396 { 4800 {
4397 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4801 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4398 float distance_term = distance * distance * distance; // Script Energy 4802 float distance_term = distance * distance * distance; // Script Energy
4399 float pusher_mass = m_host.GetMass(); 4803 // use total object mass and not part
4804 float pusher_mass = m_host.ParentGroup.GetMass();
4400 4805
4401 float PUSH_ATTENUATION_DISTANCE = 17f; 4806 float PUSH_ATTENUATION_DISTANCE = 17f;
4402 float PUSH_ATTENUATION_SCALE = 5f; 4807 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4635,23 +5040,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4635 { 5040 {
4636 m_host.AddScriptLPS(1); 5041 m_host.AddScriptLPS(1);
4637 5042
4638 lock (m_host.TaskInventory) 5043 m_host.TaskInventory.LockItemsForRead(true);
5044 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4639 { 5045 {
4640 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5046 if (inv.Value.Name == name)
4641 { 5047 {
4642 if (inv.Value.Name == name) 5048 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4643 { 5049 {
4644 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5050 m_host.TaskInventory.LockItemsForRead(false);
4645 { 5051 return inv.Value.AssetID.ToString();
4646 return inv.Value.AssetID.ToString(); 5052 }
4647 } 5053 else
4648 else 5054 {
4649 { 5055 m_host.TaskInventory.LockItemsForRead(false);
4650 return UUID.Zero.ToString(); 5056 return UUID.Zero.ToString();
4651 }
4652 } 5057 }
4653 } 5058 }
4654 } 5059 }
5060 m_host.TaskInventory.LockItemsForRead(false);
4655 5061
4656 return UUID.Zero.ToString(); 5062 return UUID.Zero.ToString();
4657 } 5063 }
@@ -4785,7 +5191,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4785 public LSL_Vector llGetCenterOfMass() 5191 public LSL_Vector llGetCenterOfMass()
4786 { 5192 {
4787 m_host.AddScriptLPS(1); 5193 m_host.AddScriptLPS(1);
4788 Vector3 center = m_host.GetGeometricCenter(); 5194 Vector3 center = m_host.GetCenterOfMass();
4789 return new LSL_Vector(center.X,center.Y,center.Z); 5195 return new LSL_Vector(center.X,center.Y,center.Z);
4790 } 5196 }
4791 5197
@@ -4804,14 +5210,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4804 { 5210 {
4805 m_host.AddScriptLPS(1); 5211 m_host.AddScriptLPS(1);
4806 5212
4807 if (src == null) 5213 return src.Length;
4808 {
4809 return 0;
4810 }
4811 else
4812 {
4813 return src.Length;
4814 }
4815 } 5214 }
4816 5215
4817 public LSL_Integer llList2Integer(LSL_List src, int index) 5216 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4857,7 +5256,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4857 else if (src.Data[index] is LSL_Float) 5256 else if (src.Data[index] is LSL_Float)
4858 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5257 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4859 else if (src.Data[index] is LSL_String) 5258 else if (src.Data[index] is LSL_String)
4860 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5259 {
5260 string str = ((LSL_String) src.Data[index]).m_string;
5261 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5262 if (m != Match.Empty)
5263 {
5264 str = m.Value;
5265 double d = 0.0;
5266 if (!Double.TryParse(str, out d))
5267 return 0.0;
5268
5269 return d;
5270 }
5271 return 0.0;
5272 }
4861 return Convert.ToDouble(src.Data[index]); 5273 return Convert.ToDouble(src.Data[index]);
4862 } 5274 }
4863 catch (FormatException) 5275 catch (FormatException)
@@ -5130,7 +5542,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5130 } 5542 }
5131 } 5543 }
5132 } 5544 }
5133 else { 5545 else
5546 {
5134 object[] array = new object[src.Length]; 5547 object[] array = new object[src.Length];
5135 Array.Copy(src.Data, 0, array, 0, src.Length); 5548 Array.Copy(src.Data, 0, array, 0, src.Length);
5136 result = new LSL_List(array); 5549 result = new LSL_List(array);
@@ -5237,7 +5650,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5237 public LSL_Integer llGetRegionAgentCount() 5650 public LSL_Integer llGetRegionAgentCount()
5238 { 5651 {
5239 m_host.AddScriptLPS(1); 5652 m_host.AddScriptLPS(1);
5240 return new LSL_Integer(World.GetRootAgentCount()); 5653
5654 int count = 0;
5655 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5656 count++;
5657 });
5658
5659 return new LSL_Integer(count);
5241 } 5660 }
5242 5661
5243 public LSL_Vector llGetRegionCorner() 5662 public LSL_Vector llGetRegionCorner()
@@ -5517,6 +5936,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5517 flags |= ScriptBaseClass.AGENT_SITTING; 5936 flags |= ScriptBaseClass.AGENT_SITTING;
5518 } 5937 }
5519 5938
5939 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
5940 {
5941 flags |= ScriptBaseClass.AGENT_MALE;
5942 }
5943
5520 return flags; 5944 return flags;
5521 } 5945 }
5522 5946
@@ -5664,10 +6088,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5664 m_host.AddScriptLPS(1); 6088 m_host.AddScriptLPS(1);
5665 6089
5666 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6090 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5667 6091 if (parts.Count > 0)
5668 foreach (var part in parts)
5669 { 6092 {
5670 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6093 try
6094 {
6095 parts[0].ParentGroup.areUpdatesSuspended = true;
6096 foreach (var part in parts)
6097 {
6098 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6099 }
6100 }
6101 finally
6102 {
6103 parts[0].ParentGroup.areUpdatesSuspended = false;
6104 }
5671 } 6105 }
5672 } 6106 }
5673 6107
@@ -5719,13 +6153,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5719 6153
5720 if (m_host.OwnerID == land.LandData.OwnerID) 6154 if (m_host.OwnerID == land.LandData.OwnerID)
5721 { 6155 {
5722 World.TeleportClientHome(agentID, presence.ControllingClient); 6156 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6157 presence.TeleportWithMomentum(pos, null);
6158 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5723 } 6159 }
5724 } 6160 }
5725 } 6161 }
5726 ScriptSleep(5000); 6162 ScriptSleep(5000);
5727 } 6163 }
5728 6164
6165 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6166 {
6167 return ParseString2List(str, separators, in_spacers, false);
6168 }
6169
5729 public LSL_Integer llOverMyLand(string id) 6170 public LSL_Integer llOverMyLand(string id)
5730 { 6171 {
5731 m_host.AddScriptLPS(1); 6172 m_host.AddScriptLPS(1);
@@ -5790,8 +6231,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5790 UUID agentId = new UUID(); 6231 UUID agentId = new UUID();
5791 if (!UUID.TryParse(agent, out agentId)) 6232 if (!UUID.TryParse(agent, out agentId))
5792 return new LSL_Integer(0); 6233 return new LSL_Integer(0);
6234 if (agentId == m_host.GroupID)
6235 return new LSL_Integer(1);
5793 ScenePresence presence = World.GetScenePresence(agentId); 6236 ScenePresence presence = World.GetScenePresence(agentId);
5794 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6237 if (presence == null || presence.IsChildAgent) // Return false for child agents
5795 return new LSL_Integer(0); 6238 return new LSL_Integer(0);
5796 IClientAPI client = presence.ControllingClient; 6239 IClientAPI client = presence.ControllingClient;
5797 if (m_host.GroupID == client.ActiveGroupId) 6240 if (m_host.GroupID == client.ActiveGroupId)
@@ -5926,7 +6369,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5926 return m_host.ParentGroup.AttachmentPoint; 6369 return m_host.ParentGroup.AttachmentPoint;
5927 } 6370 }
5928 6371
5929 public LSL_Integer llGetFreeMemory() 6372 public virtual LSL_Integer llGetFreeMemory()
5930 { 6373 {
5931 m_host.AddScriptLPS(1); 6374 m_host.AddScriptLPS(1);
5932 // Make scripts designed for LSO happy 6375 // Make scripts designed for LSO happy
@@ -6043,7 +6486,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6043 SetParticleSystem(m_host, rules); 6486 SetParticleSystem(m_host, rules);
6044 } 6487 }
6045 6488
6046 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6489 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6490 {
6047 6491
6048 6492
6049 if (rules.Length == 0) 6493 if (rules.Length == 0)
@@ -6237,14 +6681,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6237 6681
6238 protected UUID GetTaskInventoryItem(string name) 6682 protected UUID GetTaskInventoryItem(string name)
6239 { 6683 {
6240 lock (m_host.TaskInventory) 6684 m_host.TaskInventory.LockItemsForRead(true);
6685 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6241 { 6686 {
6242 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6687 if (inv.Value.Name == name)
6243 { 6688 {
6244 if (inv.Value.Name == name) 6689 m_host.TaskInventory.LockItemsForRead(false);
6245 return inv.Key; 6690 return inv.Key;
6246 } 6691 }
6247 } 6692 }
6693 m_host.TaskInventory.LockItemsForRead(false);
6248 6694
6249 return UUID.Zero; 6695 return UUID.Zero;
6250 } 6696 }
@@ -6282,16 +6728,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6282 if (folderID == UUID.Zero) 6728 if (folderID == UUID.Zero)
6283 return; 6729 return;
6284 6730
6285 byte[] bucket = new byte[17]; 6731 byte[] bucket = new byte[1];
6286 bucket[0] = (byte)AssetType.Folder; 6732 bucket[0] = (byte)AssetType.Folder;
6287 byte[] objBytes = folderID.GetBytes(); 6733 //byte[] objBytes = folderID.GetBytes();
6288 Array.Copy(objBytes, 0, bucket, 1, 16); 6734 //Array.Copy(objBytes, 0, bucket, 1, 16);
6289 6735
6290 GridInstantMessage msg = new GridInstantMessage(World, 6736 GridInstantMessage msg = new GridInstantMessage(World,
6291 m_host.UUID, m_host.Name+", an object owned by "+ 6737 m_host.OwnerID, m_host.Name, destID,
6292 resolveName(m_host.OwnerID)+",", destID, 6738 (byte)InstantMessageDialog.TaskInventoryOffered,
6293 (byte)InstantMessageDialog.InventoryOffered, 6739 false, category+". "+m_host.Name+" is located at "+
6294 false, category+"\n"+m_host.Name+" is located at "+
6295 World.RegionInfo.RegionName+" "+ 6740 World.RegionInfo.RegionName+" "+
6296 m_host.AbsolutePosition.ToString(), 6741 m_host.AbsolutePosition.ToString(),
6297 folderID, true, m_host.AbsolutePosition, 6742 folderID, true, m_host.AbsolutePosition,
@@ -6529,13 +6974,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6529 UUID av = new UUID(); 6974 UUID av = new UUID();
6530 if (!UUID.TryParse(avatar,out av)) 6975 if (!UUID.TryParse(avatar,out av))
6531 { 6976 {
6532 LSLError("First parameter to llDialog needs to be a key"); 6977 //LSLError("First parameter to llDialog needs to be a key");
6533 return; 6978 return;
6534 } 6979 }
6535 if (buttons.Length < 1) 6980 if (buttons.Length < 1)
6536 { 6981 {
6537 LSLError("No less than 1 button can be shown"); 6982 buttons.Add("OK");
6538 return;
6539 } 6983 }
6540 if (buttons.Length > 12) 6984 if (buttons.Length > 12)
6541 { 6985 {
@@ -6552,7 +6996,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6552 } 6996 }
6553 if (buttons.Data[i].ToString().Length > 24) 6997 if (buttons.Data[i].ToString().Length > 24)
6554 { 6998 {
6555 LSLError("button label cannot be longer than 24 characters"); 6999 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6556 return; 7000 return;
6557 } 7001 }
6558 buts[i] = buttons.Data[i].ToString(); 7002 buts[i] = buttons.Data[i].ToString();
@@ -6611,22 +7055,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6611 } 7055 }
6612 7056
6613 // copy the first script found with this inventory name 7057 // copy the first script found with this inventory name
6614 lock (m_host.TaskInventory) 7058 TaskInventoryItem scriptItem = null;
7059 m_host.TaskInventory.LockItemsForRead(true);
7060 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6615 { 7061 {
6616 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 7062 if (inv.Value.Name == name)
6617 { 7063 {
6618 if (inv.Value.Name == name) 7064 // make sure the object is a script
7065 if (10 == inv.Value.Type)
6619 { 7066 {
6620 // make sure the object is a script 7067 found = true;
6621 if (10 == inv.Value.Type) 7068 srcId = inv.Key;
6622 { 7069 scriptItem = inv.Value;
6623 found = true; 7070 break;
6624 srcId = inv.Key;
6625 break;
6626 }
6627 } 7071 }
6628 } 7072 }
6629 } 7073 }
7074 m_host.TaskInventory.LockItemsForRead(false);
6630 7075
6631 if (!found) 7076 if (!found)
6632 { 7077 {
@@ -6634,9 +7079,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6634 return; 7079 return;
6635 } 7080 }
6636 7081
6637 // the rest of the permission checks are done in RezScript, so check the pin there as well 7082 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6638 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7083 if (dest != null)
7084 {
7085 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7086 {
7087 // the rest of the permission checks are done in RezScript, so check the pin there as well
7088 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6639 7089
7090 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7091 m_host.Inventory.RemoveInventoryItem(srcId);
7092 }
7093 }
6640 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7094 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6641 ScriptSleep(3000); 7095 ScriptSleep(3000);
6642 } 7096 }
@@ -6699,19 +7153,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6699 public LSL_String llMD5String(string src, int nonce) 7153 public LSL_String llMD5String(string src, int nonce)
6700 { 7154 {
6701 m_host.AddScriptLPS(1); 7155 m_host.AddScriptLPS(1);
6702 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7156 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6703 } 7157 }
6704 7158
6705 public LSL_String llSHA1String(string src) 7159 public LSL_String llSHA1String(string src)
6706 { 7160 {
6707 m_host.AddScriptLPS(1); 7161 m_host.AddScriptLPS(1);
6708 return Util.SHA1Hash(src).ToLower(); 7162 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6709 } 7163 }
6710 7164
6711 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7165 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6712 { 7166 {
6713 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7167 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6714 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7168 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7169 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7170 return shapeBlock;
6715 7171
6716 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7172 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6717 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7173 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6816,6 +7272,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6816 // Prim type box, cylinder and prism. 7272 // Prim type box, cylinder and prism.
6817 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) 7273 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)
6818 { 7274 {
7275 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7276 return;
7277
6819 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7278 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6820 ObjectShapePacket.ObjectDataBlock shapeBlock; 7279 ObjectShapePacket.ObjectDataBlock shapeBlock;
6821 7280
@@ -6869,6 +7328,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6869 // Prim type sphere. 7328 // Prim type sphere.
6870 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7329 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6871 { 7330 {
7331 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7332 return;
7333
6872 ObjectShapePacket.ObjectDataBlock shapeBlock; 7334 ObjectShapePacket.ObjectDataBlock shapeBlock;
6873 7335
6874 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7336 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6910,6 +7372,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6910 // Prim type torus, tube and ring. 7372 // Prim type torus, tube and ring.
6911 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) 7373 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)
6912 { 7374 {
7375 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7376 return;
7377
6913 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7378 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6914 ObjectShapePacket.ObjectDataBlock shapeBlock; 7379 ObjectShapePacket.ObjectDataBlock shapeBlock;
6915 7380
@@ -7045,6 +7510,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7045 // Prim type sculpt. 7510 // Prim type sculpt.
7046 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7511 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7047 { 7512 {
7513 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7514 return;
7515
7048 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7516 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7049 UUID sculptId; 7517 UUID sculptId;
7050 7518
@@ -7069,7 +7537,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7069 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7537 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7070 { 7538 {
7071 // default 7539 // default
7072 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7540 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7073 } 7541 }
7074 7542
7075 part.Shape.SetSculptProperties((byte)type, sculptId); 7543 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7085,32 +7553,149 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7085 ScriptSleep(200); 7553 ScriptSleep(200);
7086 } 7554 }
7087 7555
7088 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7556 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7089 { 7557 {
7090 m_host.AddScriptLPS(1); 7558 m_host.AddScriptLPS(1);
7091 7559
7092 setLinkPrimParams(linknumber, rules); 7560 setLinkPrimParams(linknumber, rules);
7561 }
7093 7562
7094 ScriptSleep(200); 7563 private void setLinkPrimParams(int linknumber, LSL_List rules)
7564 {
7565 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7566 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7567 if (parts.Count>0)
7568 {
7569 try
7570 {
7571 parts[0].ParentGroup.areUpdatesSuspended = true;
7572 foreach (SceneObjectPart part in parts)
7573 SetPrimParams(part, rules);
7574 }
7575 finally
7576 {
7577 parts[0].ParentGroup.areUpdatesSuspended = false;
7578 }
7579 }
7580 if (avatars.Count > 0)
7581 {
7582 foreach (ScenePresence avatar in avatars)
7583 SetPrimParams(avatar, rules);
7584 }
7095 } 7585 }
7096 7586
7097 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7587 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7588 float material_density, float material_friction,
7589 float material_restitution, float material_gravity_modifier)
7098 { 7590 {
7099 m_host.AddScriptLPS(1); 7591 ExtraPhysicsData physdata = new ExtraPhysicsData();
7592 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7593 physdata.Density = part.Density;
7594 physdata.Friction = part.Friction;
7595 physdata.Bounce = part.Bounciness;
7596 physdata.GravitationModifier = part.GravityModifier;
7100 7597
7101 setLinkPrimParams(linknumber, rules); 7598 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7599 physdata.Density = material_density;
7600 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7601 physdata.Friction = material_friction;
7602 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7603 physdata.Bounce = material_restitution;
7604 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7605 physdata.GravitationModifier = material_gravity_modifier;
7606
7607 part.UpdateExtraPhysics(physdata);
7102 } 7608 }
7103 7609
7104 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7610 public void llSetPhysicsMaterial(int material_bits,
7611 float material_gravity_modifier, float material_restitution,
7612 float material_friction, float material_density)
7105 { 7613 {
7106 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7614 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7615 }
7107 7616
7108 foreach (SceneObjectPart part in parts) 7617 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7109 SetPrimParams(part, rules); 7618 {
7619 llSetLinkPrimitiveParamsFast(linknumber, rules);
7620 ScriptSleep(200);
7621 }
7622
7623 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7624 {
7625 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7626 //We only support PRIM_POSITION and PRIM_ROTATION
7627
7628 int idx = 0;
7629
7630 while (idx < rules.Length)
7631 {
7632 int code = rules.GetLSLIntegerItem(idx++);
7633
7634 int remain = rules.Length - idx;
7635
7636 switch (code)
7637 {
7638 case (int)ScriptBaseClass.PRIM_POSITION:
7639 {
7640 if (remain < 1)
7641 return;
7642 LSL_Vector v;
7643 v = rules.GetVector3Item(idx++);
7644
7645 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7646 if (part == null)
7647 break;
7648
7649 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7650 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7651 if (llGetLinkNumber() > 1)
7652 {
7653 localRot = llGetLocalRot();
7654 localPos = llGetLocalPos();
7655 }
7656
7657 v -= localPos;
7658 v /= localRot;
7659
7660 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
7661
7662 v = v + 2 * sitOffset;
7663
7664 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7665 av.SendAvatarDataToAllAgents();
7666
7667 }
7668 break;
7669
7670 case (int)ScriptBaseClass.PRIM_ROTATION:
7671 {
7672 if (remain < 1)
7673 return;
7674
7675 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7676 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7677 if (llGetLinkNumber() > 1)
7678 {
7679 localRot = llGetLocalRot();
7680 localPos = llGetLocalPos();
7681 }
7682
7683 LSL_Rotation r;
7684 r = rules.GetQuaternionItem(idx++);
7685 r = r * llGetRootRotation() / localRot;
7686 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7687 av.SendAvatarDataToAllAgents();
7688 }
7689 break;
7690 }
7691 }
7110 } 7692 }
7111 7693
7112 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7694 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7113 { 7695 {
7696 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7697 return;
7698
7114 int idx = 0; 7699 int idx = 0;
7115 7700
7116 bool positionChanged = false; 7701 bool positionChanged = false;
@@ -7432,6 +8017,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7432 part.ScriptSetPhysicsStatus(physics); 8017 part.ScriptSetPhysicsStatus(physics);
7433 break; 8018 break;
7434 8019
8020 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
8021 if (remain < 1)
8022 return;
8023
8024 int shape_type = rules.GetLSLIntegerItem(idx++);
8025
8026 ExtraPhysicsData physdata = new ExtraPhysicsData();
8027 physdata.Density = part.Density;
8028 physdata.Bounce = part.Bounciness;
8029 physdata.GravitationModifier = part.GravityModifier;
8030 physdata.PhysShapeType = (PhysShapeType)shape_type;
8031
8032 part.UpdateExtraPhysics(physdata);
8033
8034 break;
8035
8036 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8037 if (remain < 5)
8038 return;
8039
8040 int material_bits = rules.GetLSLIntegerItem(idx++);
8041 float material_density = (float)rules.GetLSLFloatItem(idx++);
8042 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8043 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8044 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8045
8046 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8047
8048 break;
8049
7435 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8050 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7436 if (remain < 1) 8051 if (remain < 1)
7437 return; 8052 return;
@@ -7505,7 +8120,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7505 if (part.ParentGroup.RootPart == part) 8120 if (part.ParentGroup.RootPart == part)
7506 { 8121 {
7507 SceneObjectGroup parent = part.ParentGroup; 8122 SceneObjectGroup parent = part.ParentGroup;
7508 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8123 Util.FireAndForget(delegate(object x) {
8124 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8125 });
7509 } 8126 }
7510 else 8127 else
7511 { 8128 {
@@ -7516,6 +8133,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7516 } 8133 }
7517 } 8134 }
7518 } 8135 }
8136
8137 if (positionChanged)
8138 {
8139 if (part.ParentGroup.RootPart == part)
8140 {
8141 SceneObjectGroup parent = part.ParentGroup;
8142 Util.FireAndForget(delegate(object x) {
8143 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8144 });
8145 }
8146 else
8147 {
8148 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8149 SceneObjectGroup parent = part.ParentGroup;
8150 parent.HasGroupChanged = true;
8151 parent.ScheduleGroupForTerseUpdate();
8152 }
8153 }
7519 } 8154 }
7520 8155
7521 public LSL_String llStringToBase64(string str) 8156 public LSL_String llStringToBase64(string str)
@@ -7676,13 +8311,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7676 public LSL_Integer llGetNumberOfPrims() 8311 public LSL_Integer llGetNumberOfPrims()
7677 { 8312 {
7678 m_host.AddScriptLPS(1); 8313 m_host.AddScriptLPS(1);
7679 int avatarCount = 0; 8314 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7680 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8315
7681 {
7682 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
7683 avatarCount++;
7684 });
7685
7686 return m_host.ParentGroup.PrimCount + avatarCount; 8316 return m_host.ParentGroup.PrimCount + avatarCount;
7687 } 8317 }
7688 8318
@@ -7698,55 +8328,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7698 m_host.AddScriptLPS(1); 8328 m_host.AddScriptLPS(1);
7699 UUID objID = UUID.Zero; 8329 UUID objID = UUID.Zero;
7700 LSL_List result = new LSL_List(); 8330 LSL_List result = new LSL_List();
8331
8332 // If the ID is not valid, return null result
7701 if (!UUID.TryParse(obj, out objID)) 8333 if (!UUID.TryParse(obj, out objID))
7702 { 8334 {
7703 result.Add(new LSL_Vector()); 8335 result.Add(new LSL_Vector());
7704 result.Add(new LSL_Vector()); 8336 result.Add(new LSL_Vector());
7705 return result; 8337 return result;
7706 } 8338 }
8339
8340 // Check if this is an attached prim. If so, replace
8341 // the UUID with the avatar UUID and report it's bounding box
8342 SceneObjectPart part = World.GetSceneObjectPart(objID);
8343 if (part != null && part.ParentGroup.IsAttachment)
8344 objID = part.ParentGroup.AttachedAvatar;
8345
8346 // Find out if this is an avatar ID. If so, return it's box
7707 ScenePresence presence = World.GetScenePresence(objID); 8347 ScenePresence presence = World.GetScenePresence(objID);
7708 if (presence != null) 8348 if (presence != null)
7709 { 8349 {
7710 if (presence.ParentID == 0) // not sat on an object 8350 // As per LSL Wiki, there is no difference between sitting
8351 // and standing avatar since server 1.36
8352 LSL_Vector lower;
8353 LSL_Vector upper;
8354 if (presence.Animator.Animations.DefaultAnimation.AnimID
8355 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7711 { 8356 {
7712 LSL_Vector lower; 8357 // This is for ground sitting avatars
7713 LSL_Vector upper; 8358 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7714 if (presence.Animator.Animations.DefaultAnimation.AnimID 8359 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7715 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8360 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7716 {
7717 // This is for ground sitting avatars
7718 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7719 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7720 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7721 }
7722 else
7723 {
7724 // This is for standing/flying avatars
7725 float height = presence.Appearance.AvatarHeight / 2.0f;
7726 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7727 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7728 }
7729 result.Add(lower);
7730 result.Add(upper);
7731 return result;
7732 } 8361 }
7733 else 8362 else
7734 { 8363 {
7735 // sitting on an object so we need the bounding box of that 8364 // This is for standing/flying avatars
7736 // which should include the avatar so set the UUID to the 8365 float height = presence.Appearance.AvatarHeight / 2.0f;
7737 // UUID of the object the avatar is sat on and allow it to fall through 8366 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7738 // to processing an object 8367 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7739 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7740 objID = p.UUID;
7741 } 8368 }
8369
8370 // Adjust to the documented error offsets (see LSL Wiki)
8371 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8372 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8373
8374 if (lower.x > upper.x)
8375 lower.x = upper.x;
8376 if (lower.y > upper.y)
8377 lower.y = upper.y;
8378 if (lower.z > upper.z)
8379 lower.z = upper.z;
8380
8381 result.Add(lower);
8382 result.Add(upper);
8383 return result;
7742 } 8384 }
7743 SceneObjectPart part = World.GetSceneObjectPart(objID); 8385
8386 part = World.GetSceneObjectPart(objID);
7744 // Currently only works for single prims without a sitting avatar 8387 // Currently only works for single prims without a sitting avatar
7745 if (part != null) 8388 if (part != null)
7746 { 8389 {
7747 Vector3 halfSize = part.Scale / 2.0f; 8390 float minX;
7748 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8391 float maxX;
7749 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8392 float minY;
8393 float maxY;
8394 float minZ;
8395 float maxZ;
8396
8397 // This BBox is in sim coordinates, with the offset being
8398 // a contained point.
8399 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8400 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8401
8402 minX -= offsets[0].X;
8403 maxX -= offsets[0].X;
8404 minY -= offsets[0].Y;
8405 maxY -= offsets[0].Y;
8406 minZ -= offsets[0].Z;
8407 maxZ -= offsets[0].Z;
8408
8409 LSL_Vector lower;
8410 LSL_Vector upper;
8411
8412 // Adjust to the documented error offsets (see LSL Wiki)
8413 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8414 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8415
8416 if (lower.x > upper.x)
8417 lower.x = upper.x;
8418 if (lower.y > upper.y)
8419 lower.y = upper.y;
8420 if (lower.z > upper.z)
8421 lower.z = upper.z;
8422
7750 result.Add(lower); 8423 result.Add(lower);
7751 result.Add(upper); 8424 result.Add(upper);
7752 return result; 8425 return result;
@@ -7760,7 +8433,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7760 8433
7761 public LSL_Vector llGetGeometricCenter() 8434 public LSL_Vector llGetGeometricCenter()
7762 { 8435 {
7763 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 8436 Vector3 tmp = m_host.GetGeometricCenter();
8437 return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
7764 } 8438 }
7765 8439
7766 public LSL_List llGetPrimitiveParams(LSL_List rules) 8440 public LSL_List llGetPrimitiveParams(LSL_List rules)
@@ -7826,13 +8500,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7826 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8500 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7827 part.AbsolutePosition.Y, 8501 part.AbsolutePosition.Y,
7828 part.AbsolutePosition.Z); 8502 part.AbsolutePosition.Z);
7829 // For some reason, the part.AbsolutePosition.* values do not change if the
7830 // linkset is rotated; they always reflect the child prim's world position
7831 // as though the linkset is unrotated. This is incompatible behavior with SL's
7832 // implementation, so will break scripts imported from there (not to mention it
7833 // makes it more difficult to determine a child prim's actual inworld position).
7834 if (part.ParentID != 0)
7835 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7836 res.Add(v); 8503 res.Add(v);
7837 break; 8504 break;
7838 8505
@@ -8003,56 +8670,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8003 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8670 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8004 if (remain < 1) 8671 if (remain < 1)
8005 return res; 8672 return res;
8006 8673 face = (int)rules.GetLSLIntegerItem(idx++);
8007 face=(int)rules.GetLSLIntegerItem(idx++);
8008 8674
8009 tex = part.Shape.Textures; 8675 tex = part.Shape.Textures;
8676 int shiny;
8010 if (face == ScriptBaseClass.ALL_SIDES) 8677 if (face == ScriptBaseClass.ALL_SIDES)
8011 { 8678 {
8012 for (face = 0; face < GetNumberOfSides(part); face++) 8679 for (face = 0; face < GetNumberOfSides(part); face++)
8013 { 8680 {
8014 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8681 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8015 // Convert Shininess to PRIM_SHINY_* 8682 if (shinyness == Shininess.High)
8016 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8683 {
8017 // PRIM_BUMP_* 8684 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8018 res.Add(new LSL_Integer((int)texface.Bump)); 8685 }
8686 else if (shinyness == Shininess.Medium)
8687 {
8688 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8689 }
8690 else if (shinyness == Shininess.Low)
8691 {
8692 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8693 }
8694 else
8695 {
8696 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8697 }
8698 res.Add(new LSL_Integer(shiny));
8699 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8019 } 8700 }
8020 } 8701 }
8021 else 8702 else
8022 { 8703 {
8023 if (face >= 0 && face < GetNumberOfSides(part)) 8704 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8705 if (shinyness == Shininess.High)
8024 { 8706 {
8025 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8707 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8026 // Convert Shininess to PRIM_SHINY_* 8708 }
8027 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8709 else if (shinyness == Shininess.Medium)
8028 // PRIM_BUMP_* 8710 {
8029 res.Add(new LSL_Integer((int)texface.Bump)); 8711 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8030 } 8712 }
8713 else if (shinyness == Shininess.Low)
8714 {
8715 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8716 }
8717 else
8718 {
8719 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8720 }
8721 res.Add(new LSL_Integer(shiny));
8722 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8031 } 8723 }
8032 break; 8724 break;
8033 8725
8034 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8726 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8035 if (remain < 1) 8727 if (remain < 1)
8036 return res; 8728 return res;
8037 8729 face = (int)rules.GetLSLIntegerItem(idx++);
8038 face=(int)rules.GetLSLIntegerItem(idx++);
8039 8730
8040 tex = part.Shape.Textures; 8731 tex = part.Shape.Textures;
8732 int fullbright;
8041 if (face == ScriptBaseClass.ALL_SIDES) 8733 if (face == ScriptBaseClass.ALL_SIDES)
8042 { 8734 {
8043 for (face = 0; face < GetNumberOfSides(part); face++) 8735 for (face = 0; face < GetNumberOfSides(part); face++)
8044 { 8736 {
8045 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8737 if (tex.GetFace((uint)face).Fullbright == true)
8046 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8738 {
8739 fullbright = ScriptBaseClass.TRUE;
8740 }
8741 else
8742 {
8743 fullbright = ScriptBaseClass.FALSE;
8744 }
8745 res.Add(new LSL_Integer(fullbright));
8047 } 8746 }
8048 } 8747 }
8049 else 8748 else
8050 { 8749 {
8051 if (face >= 0 && face < GetNumberOfSides(part)) 8750 if (tex.GetFace((uint)face).Fullbright == true)
8052 { 8751 {
8053 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8752 fullbright = ScriptBaseClass.TRUE;
8054 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
8055 } 8753 }
8754 else
8755 {
8756 fullbright = ScriptBaseClass.FALSE;
8757 }
8758 res.Add(new LSL_Integer(fullbright));
8056 } 8759 }
8057 break; 8760 break;
8058 8761
@@ -8074,27 +8777,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8074 break; 8777 break;
8075 8778
8076 case (int)ScriptBaseClass.PRIM_TEXGEN: 8779 case (int)ScriptBaseClass.PRIM_TEXGEN:
8780 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8077 if (remain < 1) 8781 if (remain < 1)
8078 return res; 8782 return res;
8079 8783 face = (int)rules.GetLSLIntegerItem(idx++);
8080 face=(int)rules.GetLSLIntegerItem(idx++);
8081 8784
8082 tex = part.Shape.Textures; 8785 tex = part.Shape.Textures;
8083 if (face == ScriptBaseClass.ALL_SIDES) 8786 if (face == ScriptBaseClass.ALL_SIDES)
8084 { 8787 {
8085 for (face = 0; face < GetNumberOfSides(part); face++) 8788 for (face = 0; face < GetNumberOfSides(part); face++)
8086 { 8789 {
8087 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8790 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8088 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8791 {
8089 res.Add(new LSL_Integer((uint)texgen >> 1)); 8792 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8793 }
8794 else
8795 {
8796 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8797 }
8090 } 8798 }
8091 } 8799 }
8092 else 8800 else
8093 { 8801 {
8094 if (face >= 0 && face < GetNumberOfSides(part)) 8802 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8803 {
8804 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8805 }
8806 else
8095 { 8807 {
8096 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8808 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8097 res.Add(new LSL_Integer((uint)texgen >> 1));
8098 } 8809 }
8099 } 8810 }
8100 break; 8811 break;
@@ -8117,28 +8828,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8117 case (int)ScriptBaseClass.PRIM_GLOW: 8828 case (int)ScriptBaseClass.PRIM_GLOW:
8118 if (remain < 1) 8829 if (remain < 1)
8119 return res; 8830 return res;
8120 8831 face = (int)rules.GetLSLIntegerItem(idx++);
8121 face=(int)rules.GetLSLIntegerItem(idx++);
8122 8832
8123 tex = part.Shape.Textures; 8833 tex = part.Shape.Textures;
8834 float primglow;
8124 if (face == ScriptBaseClass.ALL_SIDES) 8835 if (face == ScriptBaseClass.ALL_SIDES)
8125 { 8836 {
8126 for (face = 0; face < GetNumberOfSides(part); face++) 8837 for (face = 0; face < GetNumberOfSides(part); face++)
8127 { 8838 {
8128 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8839 primglow = tex.GetFace((uint)face).Glow;
8129 res.Add(new LSL_Float(texface.Glow)); 8840 res.Add(new LSL_Float(primglow));
8130 } 8841 }
8131 } 8842 }
8132 else 8843 else
8133 { 8844 {
8134 if (face >= 0 && face < GetNumberOfSides(part)) 8845 primglow = tex.GetFace((uint)face).Glow;
8135 { 8846 res.Add(new LSL_Float(primglow));
8136 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8137 res.Add(new LSL_Float(texface.Glow));
8138 }
8139 } 8847 }
8140 break; 8848 break;
8141
8142 case (int)ScriptBaseClass.PRIM_TEXT: 8849 case (int)ScriptBaseClass.PRIM_TEXT:
8143 Color4 textColor = part.GetTextColor(); 8850 Color4 textColor = part.GetTextColor();
8144 res.Add(new LSL_String(part.Text)); 8851 res.Add(new LSL_String(part.Text));
@@ -8750,8 +9457,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8750 // The function returns an ordered list 9457 // The function returns an ordered list
8751 // representing the tokens found in the supplied 9458 // representing the tokens found in the supplied
8752 // sources string. If two successive tokenizers 9459 // sources string. If two successive tokenizers
8753 // are encountered, then a NULL entry is added 9460 // are encountered, then a null-string entry is
8754 // to the list. 9461 // added to the list.
8755 // 9462 //
8756 // It is a precondition that the source and 9463 // It is a precondition that the source and
8757 // toekizer lisst are non-null. If they are null, 9464 // toekizer lisst are non-null. If they are null,
@@ -8759,7 +9466,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8759 // while their lengths are being determined. 9466 // while their lengths are being determined.
8760 // 9467 //
8761 // A small amount of working memoryis required 9468 // A small amount of working memoryis required
8762 // of approximately 8*#tokenizers. 9469 // of approximately 8*#tokenizers + 8*srcstrlen.
8763 // 9470 //
8764 // There are many ways in which this function 9471 // There are many ways in which this function
8765 // can be implemented, this implementation is 9472 // can be implemented, this implementation is
@@ -8775,155 +9482,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8775 // and eliminates redundant tokenizers as soon 9482 // and eliminates redundant tokenizers as soon
8776 // as is possible. 9483 // as is possible.
8777 // 9484 //
8778 // The implementation tries to avoid any copying 9485 // The implementation tries to minimize temporary
8779 // of arrays or other objects. 9486 // garbage generation.
8780 // </remarks> 9487 // </remarks>
8781 9488
8782 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9489 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8783 { 9490 {
8784 int beginning = 0; 9491 return ParseString2List(src, separators, spacers, true);
8785 int srclen = src.Length; 9492 }
8786 int seplen = separators.Length;
8787 object[] separray = separators.Data;
8788 int spclen = spacers.Length;
8789 object[] spcarray = spacers.Data;
8790 int mlen = seplen+spclen;
8791
8792 int[] offset = new int[mlen+1];
8793 bool[] active = new bool[mlen];
8794
8795 int best;
8796 int j;
8797
8798 // Initial capacity reduces resize cost
8799 9493
8800 LSL_List tokens = new LSL_List(); 9494 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9495 {
9496 int srclen = src.Length;
9497 int seplen = separators.Length;
9498 object[] separray = separators.Data;
9499 int spclen = spacers.Length;
9500 object[] spcarray = spacers.Data;
9501 int dellen = 0;
9502 string[] delarray = new string[seplen+spclen];
8801 9503
8802 // All entries are initially valid 9504 int outlen = 0;
9505 string[] outarray = new string[srclen*2+1];
8803 9506
8804 for (int i = 0; i < mlen; i++) 9507 int i, j;
8805 active[i] = true; 9508 string d;
8806 9509
8807 offset[mlen] = srclen; 9510 m_host.AddScriptLPS(1);
8808 9511
8809 while (beginning < srclen) 9512 /*
9513 * Convert separator and spacer lists to C# strings.
9514 * Also filter out null strings so we don't hang.
9515 */
9516 for (i = 0; i < seplen; i ++)
8810 { 9517 {
9518 d = separray[i].ToString();
9519 if (d.Length > 0)
9520 {
9521 delarray[dellen++] = d;
9522 }
9523 }
9524 seplen = dellen;
8811 9525
8812 best = mlen; // as bad as it gets 9526 for (i = 0; i < spclen; i ++)
9527 {
9528 d = spcarray[i].ToString();
9529 if (d.Length > 0)
9530 {
9531 delarray[dellen++] = d;
9532 }
9533 }
8813 9534
8814 // Scan for separators 9535 /*
9536 * Scan through source string from beginning to end.
9537 */
9538 for (i = 0;;)
9539 {
8815 9540
8816 for (j = 0; j < seplen; j++) 9541 /*
9542 * Find earliest delimeter in src starting at i (if any).
9543 */
9544 int earliestDel = -1;
9545 int earliestSrc = srclen;
9546 string earliestStr = null;
9547 for (j = 0; j < dellen; j ++)
8817 { 9548 {
8818 if (separray[j].ToString() == String.Empty) 9549 d = delarray[j];
8819 active[j] = false; 9550 if (d != null)
8820
8821 if (active[j])
8822 { 9551 {
8823 // scan all of the markers 9552 int index = src.IndexOf(d, i);
8824 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9553 if (index < 0)
8825 { 9554 {
8826 // not present at all 9555 delarray[j] = null; // delim nowhere in src, don't check it anymore
8827 active[j] = false;
8828 } 9556 }
8829 else 9557 else if (index < earliestSrc)
8830 { 9558 {
8831 // present and correct 9559 earliestSrc = index; // where delimeter starts in source string
8832 if (offset[j] < offset[best]) 9560 earliestDel = j; // where delimeter is in delarray[]
8833 { 9561 earliestStr = d; // the delimeter string from delarray[]
8834 // closest so far 9562 if (index == i) break; // can't do any better than found at beg of string
8835 best = j;
8836 if (offset[best] == beginning)
8837 break;
8838 }
8839 } 9563 }
8840 } 9564 }
8841 } 9565 }
8842 9566
8843 // Scan for spacers 9567 /*
8844 9568 * Output source string starting at i through start of earliest delimeter.
8845 if (offset[best] != beginning) 9569 */
9570 if (keepNulls || (earliestSrc > i))
8846 { 9571 {
8847 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9572 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8848 {
8849 if (spcarray[j-seplen].ToString() == String.Empty)
8850 active[j] = false;
8851
8852 if (active[j])
8853 {
8854 // scan all of the markers
8855 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8856 {
8857 // not present at all
8858 active[j] = false;
8859 }
8860 else
8861 {
8862 // present and correct
8863 if (offset[j] < offset[best])
8864 {
8865 // closest so far
8866 best = j;
8867 }
8868 }
8869 }
8870 }
8871 } 9573 }
8872 9574
8873 // This is the normal exit from the scanning loop 9575 /*
9576 * If no delimeter found at or after i, we're done scanning.
9577 */
9578 if (earliestDel < 0) break;
8874 9579
8875 if (best == mlen) 9580 /*
9581 * If delimeter was a spacer, output the spacer.
9582 */
9583 if (earliestDel >= seplen)
8876 { 9584 {
8877 // no markers were found on this pass 9585 outarray[outlen++] = earliestStr;
8878 // so we're pretty much done
8879 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8880 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8881 break;
8882 } 9586 }
8883 9587
8884 // Otherwise we just add the newly delimited token 9588 /*
8885 // and recalculate where the search should continue. 9589 * Look at rest of src string following delimeter.
8886 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9590 */
8887 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9591 i = earliestSrc + earliestStr.Length;
8888
8889 if (best < seplen)
8890 {
8891 beginning = offset[best] + (separray[best].ToString()).Length;
8892 }
8893 else
8894 {
8895 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8896 string str = spcarray[best - seplen].ToString();
8897 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8898 tokens.Add(new LSL_String(str));
8899 }
8900 } 9592 }
8901 9593
8902 // This an awkward an not very intuitive boundary case. If the 9594 /*
8903 // last substring is a tokenizer, then there is an implied trailing 9595 * Make up an exact-sized output array suitable for an LSL_List object.
8904 // null list entry. Hopefully the single comparison will not be too 9596 */
8905 // arduous. Alternatively the 'break' could be replced with a return 9597 object[] outlist = new object[outlen];
8906 // but that's shabby programming. 9598 for (i = 0; i < outlen; i ++)
8907
8908 if ((beginning == srclen) && (keepNulls))
8909 { 9599 {
8910 if (srclen != 0) 9600 outlist[i] = new LSL_String(outarray[i]);
8911 tokens.Add(new LSL_String(""));
8912 } 9601 }
8913 9602 return new LSL_List(outlist);
8914 return tokens;
8915 }
8916
8917 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8918 {
8919 m_host.AddScriptLPS(1);
8920 return this.ParseString(src, separators, spacers, false);
8921 }
8922
8923 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8924 {
8925 m_host.AddScriptLPS(1);
8926 return this.ParseString(src, separators, spacers, true);
8927 } 9603 }
8928 9604
8929 public LSL_Integer llGetObjectPermMask(int mask) 9605 public LSL_Integer llGetObjectPermMask(int mask)
@@ -9000,28 +9676,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9000 { 9676 {
9001 m_host.AddScriptLPS(1); 9677 m_host.AddScriptLPS(1);
9002 9678
9003 lock (m_host.TaskInventory) 9679 m_host.TaskInventory.LockItemsForRead(true);
9680 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9004 { 9681 {
9005 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9682 if (inv.Value.Name == item)
9006 { 9683 {
9007 if (inv.Value.Name == item) 9684 m_host.TaskInventory.LockItemsForRead(false);
9685 switch (mask)
9008 { 9686 {
9009 switch (mask) 9687 case 0:
9010 { 9688 return (int)inv.Value.BasePermissions;
9011 case 0: 9689 case 1:
9012 return (int)inv.Value.BasePermissions; 9690 return (int)inv.Value.CurrentPermissions;
9013 case 1: 9691 case 2:
9014 return (int)inv.Value.CurrentPermissions; 9692 return (int)inv.Value.GroupPermissions;
9015 case 2: 9693 case 3:
9016 return (int)inv.Value.GroupPermissions; 9694 return (int)inv.Value.EveryonePermissions;
9017 case 3: 9695 case 4:
9018 return (int)inv.Value.EveryonePermissions; 9696 return (int)inv.Value.NextPermissions;
9019 case 4:
9020 return (int)inv.Value.NextPermissions;
9021 }
9022 } 9697 }
9023 } 9698 }
9024 } 9699 }
9700 m_host.TaskInventory.LockItemsForRead(false);
9025 9701
9026 return -1; 9702 return -1;
9027 } 9703 }
@@ -9068,16 +9744,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9068 { 9744 {
9069 m_host.AddScriptLPS(1); 9745 m_host.AddScriptLPS(1);
9070 9746
9071 lock (m_host.TaskInventory) 9747 m_host.TaskInventory.LockItemsForRead(true);
9748 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9072 { 9749 {
9073 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9750 if (inv.Value.Name == item)
9074 { 9751 {
9075 if (inv.Value.Name == item) 9752 m_host.TaskInventory.LockItemsForRead(false);
9076 { 9753 return inv.Value.CreatorID.ToString();
9077 return inv.Value.CreatorID.ToString();
9078 }
9079 } 9754 }
9080 } 9755 }
9756 m_host.TaskInventory.LockItemsForRead(false);
9081 9757
9082 llSay(0, "No item name '" + item + "'"); 9758 llSay(0, "No item name '" + item + "'");
9083 9759
@@ -9203,9 +9879,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9203 { 9879 {
9204 try 9880 try
9205 { 9881 {
9882 /*
9206 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 9883 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
9207 if (obj != null) 9884 if (obj != null)
9208 return (double)obj.GetMass(); 9885 return (double)obj.GetMass();
9886 */
9887 // return total object mass
9888 SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
9889 if (obj != null)
9890 return obj.GetMass();
9891
9209 // the object is null so the key is for an avatar 9892 // the object is null so the key is for an avatar
9210 ScenePresence avatar = World.GetScenePresence(key); 9893 ScenePresence avatar = World.GetScenePresence(key);
9211 if (avatar != null) 9894 if (avatar != null)
@@ -9225,7 +9908,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9225 } 9908 }
9226 9909
9227 /// <summary> 9910 /// <summary>
9228 /// illListReplaceList removes the sub-list defined by the inclusive indices 9911 /// llListReplaceList removes the sub-list defined by the inclusive indices
9229 /// start and end and inserts the src list in its place. The inclusive 9912 /// start and end and inserts the src list in its place. The inclusive
9230 /// nature of the indices means that at least one element must be deleted 9913 /// nature of the indices means that at least one element must be deleted
9231 /// if the indices are within the bounds of the existing list. I.e. 2,2 9914 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9282,16 +9965,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9282 // based upon end. Note that if end exceeds the upper 9965 // based upon end. Note that if end exceeds the upper
9283 // bound in this case, the entire destination list 9966 // bound in this case, the entire destination list
9284 // is removed. 9967 // is removed.
9285 else 9968 else if (start == 0)
9286 { 9969 {
9287 if (end + 1 < dest.Length) 9970 if (end + 1 < dest.Length)
9288 {
9289 return src + dest.GetSublist(end + 1, -1); 9971 return src + dest.GetSublist(end + 1, -1);
9290 }
9291 else 9972 else
9292 {
9293 return src; 9973 return src;
9294 } 9974 }
9975 else // Start < 0
9976 {
9977 if (end + 1 < dest.Length)
9978 return dest.GetSublist(end + 1, -1);
9979 else
9980 return new LSL_List();
9295 } 9981 }
9296 } 9982 }
9297 // Finally, if start > end, we strip away a prefix and 9983 // Finally, if start > end, we strip away a prefix and
@@ -9342,17 +10028,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9342 int width = 0; 10028 int width = 0;
9343 int height = 0; 10029 int height = 0;
9344 10030
9345 ParcelMediaCommandEnum? commandToSend = null; 10031 uint commandToSend = 0;
9346 float time = 0.0f; // default is from start 10032 float time = 0.0f; // default is from start
9347 10033
9348 ScenePresence presence = null; 10034 ScenePresence presence = null;
9349 10035
9350 for (int i = 0; i < commandList.Data.Length; i++) 10036 for (int i = 0; i < commandList.Data.Length; i++)
9351 { 10037 {
9352 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10038 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9353 switch (command) 10039 switch (command)
9354 { 10040 {
9355 case ParcelMediaCommandEnum.Agent: 10041 case (uint)ParcelMediaCommandEnum.Agent:
9356 // we send only to one agent 10042 // we send only to one agent
9357 if ((i + 1) < commandList.Length) 10043 if ((i + 1) < commandList.Length)
9358 { 10044 {
@@ -9369,25 +10055,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9369 } 10055 }
9370 break; 10056 break;
9371 10057
9372 case ParcelMediaCommandEnum.Loop: 10058 case (uint)ParcelMediaCommandEnum.Loop:
9373 loop = 1; 10059 loop = 1;
9374 commandToSend = command; 10060 commandToSend = command;
9375 update = true; //need to send the media update packet to set looping 10061 update = true; //need to send the media update packet to set looping
9376 break; 10062 break;
9377 10063
9378 case ParcelMediaCommandEnum.Play: 10064 case (uint)ParcelMediaCommandEnum.Play:
9379 loop = 0; 10065 loop = 0;
9380 commandToSend = command; 10066 commandToSend = command;
9381 update = true; //need to send the media update packet to make sure it doesn't loop 10067 update = true; //need to send the media update packet to make sure it doesn't loop
9382 break; 10068 break;
9383 10069
9384 case ParcelMediaCommandEnum.Pause: 10070 case (uint)ParcelMediaCommandEnum.Pause:
9385 case ParcelMediaCommandEnum.Stop: 10071 case (uint)ParcelMediaCommandEnum.Stop:
9386 case ParcelMediaCommandEnum.Unload: 10072 case (uint)ParcelMediaCommandEnum.Unload:
9387 commandToSend = command; 10073 commandToSend = command;
9388 break; 10074 break;
9389 10075
9390 case ParcelMediaCommandEnum.Url: 10076 case (uint)ParcelMediaCommandEnum.Url:
9391 if ((i + 1) < commandList.Length) 10077 if ((i + 1) < commandList.Length)
9392 { 10078 {
9393 if (commandList.Data[i + 1] is LSL_String) 10079 if (commandList.Data[i + 1] is LSL_String)
@@ -9400,7 +10086,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9400 } 10086 }
9401 break; 10087 break;
9402 10088
9403 case ParcelMediaCommandEnum.Texture: 10089 case (uint)ParcelMediaCommandEnum.Texture:
9404 if ((i + 1) < commandList.Length) 10090 if ((i + 1) < commandList.Length)
9405 { 10091 {
9406 if (commandList.Data[i + 1] is LSL_String) 10092 if (commandList.Data[i + 1] is LSL_String)
@@ -9413,7 +10099,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9413 } 10099 }
9414 break; 10100 break;
9415 10101
9416 case ParcelMediaCommandEnum.Time: 10102 case (uint)ParcelMediaCommandEnum.Time:
9417 if ((i + 1) < commandList.Length) 10103 if ((i + 1) < commandList.Length)
9418 { 10104 {
9419 if (commandList.Data[i + 1] is LSL_Float) 10105 if (commandList.Data[i + 1] is LSL_Float)
@@ -9425,7 +10111,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9425 } 10111 }
9426 break; 10112 break;
9427 10113
9428 case ParcelMediaCommandEnum.AutoAlign: 10114 case (uint)ParcelMediaCommandEnum.AutoAlign:
9429 if ((i + 1) < commandList.Length) 10115 if ((i + 1) < commandList.Length)
9430 { 10116 {
9431 if (commandList.Data[i + 1] is LSL_Integer) 10117 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9439,7 +10125,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9439 } 10125 }
9440 break; 10126 break;
9441 10127
9442 case ParcelMediaCommandEnum.Type: 10128 case (uint)ParcelMediaCommandEnum.Type:
9443 if ((i + 1) < commandList.Length) 10129 if ((i + 1) < commandList.Length)
9444 { 10130 {
9445 if (commandList.Data[i + 1] is LSL_String) 10131 if (commandList.Data[i + 1] is LSL_String)
@@ -9452,7 +10138,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9452 } 10138 }
9453 break; 10139 break;
9454 10140
9455 case ParcelMediaCommandEnum.Desc: 10141 case (uint)ParcelMediaCommandEnum.Desc:
9456 if ((i + 1) < commandList.Length) 10142 if ((i + 1) < commandList.Length)
9457 { 10143 {
9458 if (commandList.Data[i + 1] is LSL_String) 10144 if (commandList.Data[i + 1] is LSL_String)
@@ -9465,7 +10151,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9465 } 10151 }
9466 break; 10152 break;
9467 10153
9468 case ParcelMediaCommandEnum.Size: 10154 case (uint)ParcelMediaCommandEnum.Size:
9469 if ((i + 2) < commandList.Length) 10155 if ((i + 2) < commandList.Length)
9470 { 10156 {
9471 if (commandList.Data[i + 1] is LSL_Integer) 10157 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9535,7 +10221,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9535 } 10221 }
9536 } 10222 }
9537 10223
9538 if (commandToSend != null) 10224 if (commandToSend != 0)
9539 { 10225 {
9540 // the commandList contained a start/stop/... command, too 10226 // the commandList contained a start/stop/... command, too
9541 if (presence == null) 10227 if (presence == null)
@@ -9572,7 +10258,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9572 10258
9573 if (aList.Data[i] != null) 10259 if (aList.Data[i] != null)
9574 { 10260 {
9575 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10261 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9576 { 10262 {
9577 case ParcelMediaCommandEnum.Url: 10263 case ParcelMediaCommandEnum.Url:
9578 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10264 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9615,16 +10301,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9615 { 10301 {
9616 m_host.AddScriptLPS(1); 10302 m_host.AddScriptLPS(1);
9617 10303
9618 lock (m_host.TaskInventory) 10304 m_host.TaskInventory.LockItemsForRead(true);
10305 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9619 { 10306 {
9620 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10307 if (inv.Value.Name == name)
9621 { 10308 {
9622 if (inv.Value.Name == name) 10309 m_host.TaskInventory.LockItemsForRead(false);
9623 { 10310 return inv.Value.Type;
9624 return inv.Value.Type;
9625 }
9626 } 10311 }
9627 } 10312 }
10313 m_host.TaskInventory.LockItemsForRead(false);
9628 10314
9629 return -1; 10315 return -1;
9630 } 10316 }
@@ -9635,15 +10321,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9635 10321
9636 if (quick_pay_buttons.Data.Length < 4) 10322 if (quick_pay_buttons.Data.Length < 4)
9637 { 10323 {
9638 LSLError("List must have at least 4 elements"); 10324 int x;
9639 return; 10325 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10326 {
10327 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10328 }
9640 } 10329 }
9641 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10330 int[] nPrice = new int[5];
9642 10331 nPrice[0] = price;
9643 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10332 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9644 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10333 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9645 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10334 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9646 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10335 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10336 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9647 m_host.ParentGroup.HasGroupChanged = true; 10337 m_host.ParentGroup.HasGroupChanged = true;
9648 } 10338 }
9649 10339
@@ -9659,6 +10349,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9659 ShoutError("No permissions to track the camera"); 10349 ShoutError("No permissions to track the camera");
9660 return new LSL_Vector(); 10350 return new LSL_Vector();
9661 } 10351 }
10352 m_host.TaskInventory.LockItemsForRead(false);
9662 10353
9663 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10354 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9664 if (presence != null) 10355 if (presence != null)
@@ -9681,6 +10372,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9681 ShoutError("No permissions to track the camera"); 10372 ShoutError("No permissions to track the camera");
9682 return new LSL_Rotation(); 10373 return new LSL_Rotation();
9683 } 10374 }
10375 m_host.TaskInventory.LockItemsForRead(false);
9684 10376
9685 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10377 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9686 if (presence != null) 10378 if (presence != null)
@@ -9742,8 +10434,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9742 { 10434 {
9743 m_host.AddScriptLPS(1); 10435 m_host.AddScriptLPS(1);
9744 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 10436 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
9745 if (detectedParams == null) return; // only works on the first detected avatar 10437 if (detectedParams == null)
9746 10438 {
10439 if (m_host.ParentGroup.IsAttachment == true)
10440 {
10441 detectedParams = new DetectParams();
10442 detectedParams.Key = m_host.OwnerID;
10443 }
10444 else
10445 {
10446 return;
10447 }
10448 }
10449
9747 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10450 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9748 if (avatar != null) 10451 if (avatar != null)
9749 { 10452 {
@@ -9751,6 +10454,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9751 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10454 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9752 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10455 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9753 } 10456 }
10457
9754 ScriptSleep(1000); 10458 ScriptSleep(1000);
9755 } 10459 }
9756 10460
@@ -9874,12 +10578,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9874 10578
9875 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10579 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9876 object[] data = rules.Data; 10580 object[] data = rules.Data;
9877 for (int i = 0; i < data.Length; ++i) { 10581 for (int i = 0; i < data.Length; ++i)
10582 {
9878 int type = Convert.ToInt32(data[i++].ToString()); 10583 int type = Convert.ToInt32(data[i++].ToString());
9879 if (i >= data.Length) break; // odd number of entries => ignore the last 10584 if (i >= data.Length) break; // odd number of entries => ignore the last
9880 10585
9881 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10586 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9882 switch (type) { 10587 switch (type)
10588 {
9883 case ScriptBaseClass.CAMERA_FOCUS: 10589 case ScriptBaseClass.CAMERA_FOCUS:
9884 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10590 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9885 case ScriptBaseClass.CAMERA_POSITION: 10591 case ScriptBaseClass.CAMERA_POSITION:
@@ -9985,19 +10691,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9985 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10691 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
9986 { 10692 {
9987 m_host.AddScriptLPS(1); 10693 m_host.AddScriptLPS(1);
9988 string ret = String.Empty; 10694
9989 string src1 = llBase64ToString(str1); 10695 if (str1 == String.Empty)
9990 string src2 = llBase64ToString(str2); 10696 return String.Empty;
9991 int c = 0; 10697 if (str2 == String.Empty)
9992 for (int i = 0; i < src1.Length; i++) 10698 return str1;
10699
10700 int len = str2.Length;
10701 if ((len % 4) != 0) // LL is EVIL!!!!
9993 { 10702 {
9994 ret += (char) (src1[i] ^ src2[c]); 10703 while (str2.EndsWith("="))
10704 str2 = str2.Substring(0, str2.Length - 1);
10705
10706 len = str2.Length;
10707 int mod = len % 4;
9995 10708
9996 c++; 10709 if (mod == 1)
9997 if (c >= src2.Length) 10710 str2 = str2.Substring(0, str2.Length - 1);
9998 c = 0; 10711 else if (mod == 2)
10712 str2 += "==";
10713 else if (mod == 3)
10714 str2 += "=";
9999 } 10715 }
10000 return llStringToBase64(ret); 10716
10717 byte[] data1;
10718 byte[] data2;
10719 try
10720 {
10721 data1 = Convert.FromBase64String(str1);
10722 data2 = Convert.FromBase64String(str2);
10723 }
10724 catch (Exception)
10725 {
10726 return new LSL_String(String.Empty);
10727 }
10728
10729 byte[] d2 = new Byte[data1.Length];
10730 int pos = 0;
10731
10732 if (data1.Length <= data2.Length)
10733 {
10734 Array.Copy(data2, 0, d2, 0, data1.Length);
10735 }
10736 else
10737 {
10738 while (pos < data1.Length)
10739 {
10740 len = data1.Length - pos;
10741 if (len > data2.Length)
10742 len = data2.Length;
10743
10744 Array.Copy(data2, 0, d2, pos, len);
10745 pos += len;
10746 }
10747 }
10748
10749 for (pos = 0 ; pos < data1.Length ; pos++ )
10750 data1[pos] ^= d2[pos];
10751
10752 return Convert.ToBase64String(data1);
10001 } 10753 }
10002 10754
10003 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10755 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10054,12 +10806,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10054 Regex r = new Regex(authregex); 10806 Regex r = new Regex(authregex);
10055 int[] gnums = r.GetGroupNumbers(); 10807 int[] gnums = r.GetGroupNumbers();
10056 Match m = r.Match(url); 10808 Match m = r.Match(url);
10057 if (m.Success) { 10809 if (m.Success)
10058 for (int i = 1; i < gnums.Length; i++) { 10810 {
10811 for (int i = 1; i < gnums.Length; i++)
10812 {
10059 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10813 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10060 //CaptureCollection cc = g.Captures; 10814 //CaptureCollection cc = g.Captures;
10061 } 10815 }
10062 if (m.Groups.Count == 5) { 10816 if (m.Groups.Count == 5)
10817 {
10063 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10818 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10064 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10819 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10065 } 10820 }
@@ -10422,15 +11177,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10422 11177
10423 internal UUID ScriptByName(string name) 11178 internal UUID ScriptByName(string name)
10424 { 11179 {
10425 lock (m_host.TaskInventory) 11180 m_host.TaskInventory.LockItemsForRead(true);
11181
11182 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10426 { 11183 {
10427 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 11184 if (item.Type == 10 && item.Name == name)
10428 { 11185 {
10429 if (item.Type == 10 && item.Name == name) 11186 m_host.TaskInventory.LockItemsForRead(false);
10430 return item.ItemID; 11187 return item.ItemID;
10431 } 11188 }
10432 } 11189 }
10433 11190
11191 m_host.TaskInventory.LockItemsForRead(false);
11192
10434 return UUID.Zero; 11193 return UUID.Zero;
10435 } 11194 }
10436 11195
@@ -10471,6 +11230,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10471 { 11230 {
10472 m_host.AddScriptLPS(1); 11231 m_host.AddScriptLPS(1);
10473 11232
11233 //Clone is thread safe
10474 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11234 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10475 11235
10476 UUID assetID = UUID.Zero; 11236 UUID assetID = UUID.Zero;
@@ -10533,6 +11293,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10533 { 11293 {
10534 m_host.AddScriptLPS(1); 11294 m_host.AddScriptLPS(1);
10535 11295
11296 //Clone is thread safe
10536 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11297 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10537 11298
10538 UUID assetID = UUID.Zero; 11299 UUID assetID = UUID.Zero;
@@ -10613,15 +11374,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10613 return GetLinkPrimitiveParams(obj, rules); 11374 return GetLinkPrimitiveParams(obj, rules);
10614 } 11375 }
10615 11376
10616 public void print(string str) 11377 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10617 { 11378 {
10618 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11379 List<SceneObjectPart> parts = GetLinkParts(link);
10619 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11380 if (parts.Count < 1)
10620 if (ossl != null) 11381 return 0;
10621 { 11382
10622 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11383 return GetNumberOfSides(parts[0]);
10623 m_log.Info("LSL print():" + str);
10624 }
10625 } 11384 }
10626 11385
10627 private string Name2Username(string name) 11386 private string Name2Username(string name)
@@ -10667,155 +11426,482 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10667 return rq.ToString(); 11426 return rq.ToString();
10668 } 11427 }
10669 11428
11429 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11430 {
11431 m_SayShoutCount = 0;
11432 }
11433
11434 private struct Tri
11435 {
11436 public Vector3 p1;
11437 public Vector3 p2;
11438 public Vector3 p3;
11439 }
11440
11441 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11442 {
11443 float height = avatar.Appearance.AvatarHeight;
11444 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11445 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11446
11447 if (point.X > b1.X && point.X < b2.X &&
11448 point.Y > b1.Y && point.Y < b2.Y &&
11449 point.Z > b1.Z && point.Z < b2.Z)
11450 return true;
11451 return false;
11452 }
11453
11454 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11455 {
11456 List<ContactResult> contacts = new List<ContactResult>();
11457
11458 Vector3 ab = rayEnd - rayStart;
11459
11460 World.ForEachScenePresence(delegate(ScenePresence sp)
11461 {
11462 Vector3 ac = sp.AbsolutePosition - rayStart;
11463 Vector3 bc = sp.AbsolutePosition - rayEnd;
11464
11465 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11466
11467 if (d > 1.5)
11468 return;
11469
11470 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11471
11472 if (d2 > 0)
11473 return;
11474
11475 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11476 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11477
11478 if (!InBoundingBox(sp, p))
11479 return;
11480
11481 ContactResult result = new ContactResult ();
11482 result.ConsumerID = sp.LocalId;
11483 result.Depth = Vector3.Distance(rayStart, p);
11484 result.Normal = Vector3.Zero;
11485 result.Pos = p;
11486
11487 contacts.Add(result);
11488 });
11489
11490 return contacts.ToArray();
11491 }
11492
11493 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11494 {
11495 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11496 List<ContactResult> contacts = new List<ContactResult>();
11497
11498 Vector3 ab = rayEnd - rayStart;
11499
11500 World.ForEachSOG(delegate(SceneObjectGroup group)
11501 {
11502 if (m_host.ParentGroup == group)
11503 return;
11504
11505 if (group.IsAttachment)
11506 return;
11507
11508 if (group.RootPart.PhysActor == null)
11509 {
11510 if (!includePhantom)
11511 return;
11512 }
11513 else
11514 {
11515 if (group.RootPart.PhysActor.IsPhysical)
11516 {
11517 if (!includePhysical)
11518 return;
11519 }
11520 else
11521 {
11522 if (!includeNonPhysical)
11523 return;
11524 }
11525 }
11526
11527 // Find the radius ouside of which we don't even need to hit test
11528 float minX;
11529 float maxX;
11530 float minY;
11531 float maxY;
11532 float minZ;
11533 float maxZ;
11534
11535 float radius = 0.0f;
11536
11537 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11538
11539 if (Math.Abs(minX) > radius)
11540 radius = Math.Abs(minX);
11541 if (Math.Abs(minY) > radius)
11542 radius = Math.Abs(minY);
11543 if (Math.Abs(minZ) > radius)
11544 radius = Math.Abs(minZ);
11545 if (Math.Abs(maxX) > radius)
11546 radius = Math.Abs(maxX);
11547 if (Math.Abs(maxY) > radius)
11548 radius = Math.Abs(maxY);
11549 if (Math.Abs(maxZ) > radius)
11550 radius = Math.Abs(maxZ);
11551
11552 Vector3 ac = group.AbsolutePosition - rayStart;
11553 Vector3 bc = group.AbsolutePosition - rayEnd;
11554
11555 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11556
11557 // Too far off ray, don't bother
11558 if (d > radius)
11559 return;
11560
11561 // Behind ray, drop
11562 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11563 if (d2 > 0)
11564 return;
11565
11566 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11567 // Miss.
11568 if (!intersection.HitTF)
11569 return;
11570
11571 ContactResult result = new ContactResult ();
11572 result.ConsumerID = group.LocalId;
11573 result.Depth = intersection.distance;
11574 result.Normal = intersection.normal;
11575 result.Pos = intersection.ipoint;
11576
11577 contacts.Add(result);
11578 });
11579
11580 return contacts.ToArray();
11581 }
11582
11583 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11584 {
11585 double[,] heightfield = World.Heightmap.GetDoubles();
11586 List<ContactResult> contacts = new List<ContactResult>();
11587
11588 double min = 2048.0;
11589 double max = 0.0;
11590
11591 // Find the min and max of the heightfield
11592 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11593 {
11594 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11595 {
11596 if (heightfield[x, y] > max)
11597 max = heightfield[x, y];
11598 if (heightfield[x, y] < min)
11599 min = heightfield[x, y];
11600 }
11601 }
11602
11603
11604 // A ray extends past rayEnd, but doesn't go back before
11605 // rayStart. If the start is above the highest point of the ground
11606 // and the ray goes up, we can't hit the ground. Ever.
11607 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11608 return null;
11609
11610 // Same for going down
11611 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11612 return null;
11613
11614 List<Tri> trilist = new List<Tri>();
11615
11616 // Create our triangle list
11617 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11618 {
11619 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11620 {
11621 Tri t1 = new Tri();
11622 Tri t2 = new Tri();
11623
11624 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11625 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11626 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11627 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11628
11629 t1.p1 = p1;
11630 t1.p2 = p2;
11631 t1.p3 = p3;
11632
11633 t2.p1 = p3;
11634 t2.p2 = p4;
11635 t2.p3 = p1;
11636
11637 trilist.Add(t1);
11638 trilist.Add(t2);
11639 }
11640 }
11641
11642 // Ray direction
11643 Vector3 rayDirection = rayEnd - rayStart;
11644
11645 foreach (Tri t in trilist)
11646 {
11647 // Compute triangle plane normal and edges
11648 Vector3 u = t.p2 - t.p1;
11649 Vector3 v = t.p3 - t.p1;
11650 Vector3 n = Vector3.Cross(u, v);
11651
11652 if (n == Vector3.Zero)
11653 continue;
11654
11655 Vector3 w0 = rayStart - t.p1;
11656 double a = -Vector3.Dot(n, w0);
11657 double b = Vector3.Dot(n, rayDirection);
11658
11659 // Not intersecting the plane, or in plane (same thing)
11660 // Ignoring this MAY cause the ground to not be detected
11661 // sometimes
11662 if (Math.Abs(b) < 0.000001)
11663 continue;
11664
11665 double r = a / b;
11666
11667 // ray points away from plane
11668 if (r < 0.0)
11669 continue;
11670
11671 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11672
11673 float uu = Vector3.Dot(u, u);
11674 float uv = Vector3.Dot(u, v);
11675 float vv = Vector3.Dot(v, v);
11676 Vector3 w = ip - t.p1;
11677 float wu = Vector3.Dot(w, u);
11678 float wv = Vector3.Dot(w, v);
11679 float d = uv * uv - uu * vv;
11680
11681 float cs = (uv * wv - vv * wu) / d;
11682 if (cs < 0 || cs > 1.0)
11683 continue;
11684 float ct = (uv * wu - uu * wv) / d;
11685 if (ct < 0 || (cs + ct) > 1.0)
11686 continue;
11687
11688 // Add contact point
11689 ContactResult result = new ContactResult ();
11690 result.ConsumerID = 0;
11691 result.Depth = Vector3.Distance(rayStart, ip);
11692 result.Normal = n;
11693 result.Pos = ip;
11694
11695 contacts.Add(result);
11696 }
11697
11698 if (contacts.Count == 0)
11699 return null;
11700
11701 contacts.Sort(delegate(ContactResult a, ContactResult b)
11702 {
11703 return (int)(a.Depth - b.Depth);
11704 });
11705
11706 return contacts[0];
11707 }
11708/*
11709 // not done:
11710 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
11711 {
11712 ContactResult[] contacts = null;
11713 World.ForEachSOG(delegate(SceneObjectGroup group)
11714 {
11715 if (m_host.ParentGroup == group)
11716 return;
11717
11718 if (group.IsAttachment)
11719 return;
11720
11721 if(group.RootPart.PhysActor != null)
11722 return;
11723
11724 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
11725 });
11726 return contacts;
11727 }
11728*/
11729
10670 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11730 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10671 { 11731 {
11732 LSL_List list = new LSL_List();
11733
10672 m_host.AddScriptLPS(1); 11734 m_host.AddScriptLPS(1);
10673 11735
10674 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11736 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10675 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11737 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10676 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11738 Vector3 dir = rayEnd - rayStart;
10677 11739
10678 int count = 0; 11740 float dist = Vector3.Mag(dir);
10679// int detectPhantom = 0; 11741
11742 int count = 1;
11743 bool detectPhantom = false;
10680 int dataFlags = 0; 11744 int dataFlags = 0;
10681 int rejectTypes = 0; 11745 int rejectTypes = 0;
10682 11746
10683 for (int i = 0; i < options.Length; i += 2) 11747 for (int i = 0; i < options.Length; i += 2)
10684 { 11748 {
10685 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11749 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10686 {
10687 count = options.GetLSLIntegerItem(i + 1); 11750 count = options.GetLSLIntegerItem(i + 1);
10688 } 11751 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10689// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11752 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10690// {
10691// detectPhantom = options.GetLSLIntegerItem(i + 1);
10692// }
10693 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11753 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10694 {
10695 dataFlags = options.GetLSLIntegerItem(i + 1); 11754 dataFlags = options.GetLSLIntegerItem(i + 1);
10696 }
10697 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11755 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10698 {
10699 rejectTypes = options.GetLSLIntegerItem(i + 1); 11756 rejectTypes = options.GetLSLIntegerItem(i + 1);
10700 }
10701 } 11757 }
10702 11758
10703 LSL_List list = new LSL_List(); 11759 if (count > 16)
10704 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11760 count = 16;
10705
10706 double distance = Util.GetDistanceTo(startvector, endvector);
10707 11761
10708 if (distance == 0) 11762 List<ContactResult> results = new List<ContactResult>();
10709 distance = 0.001;
10710
10711 Vector3 posToCheck = startvector;
10712 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10713 11763
10714 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11764 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10715 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11765 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10716 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11766 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10717 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11767 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10718 11768
10719 for (float i = 0; i <= distance; i += 0.1f) 11769
11770 if (World.SuportsRayCastFiltered())
10720 { 11771 {
10721 posToCheck = startvector + (dir * (i / (float)distance)); 11772 if (dist == 0)
11773 return list;
11774
11775 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
11776 if (checkTerrain)
11777 rayfilter |= RayFilterFlags.land;
11778// if (checkAgents)
11779// rayfilter |= RayFilterFlags.agent;
11780 if (checkPhysical)
11781 rayfilter |= RayFilterFlags.physical;
11782 if (checkNonPhysical)
11783 rayfilter |= RayFilterFlags.nonphysical;
11784 if (detectPhantom)
11785 rayfilter |= RayFilterFlags.LSLPhanton;
10722 11786
10723 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11787 Vector3 direction = dir * ( 1/dist);
11788
11789 if(rayfilter == 0)
10724 { 11790 {
10725 ContactResult result = new ContactResult(); 11791 list.Add(new LSL_Integer(0));
10726 result.ConsumerID = 0; 11792 return list;
10727 result.Depth = 0;
10728 result.Normal = Vector3.Zero;
10729 result.Pos = posToCheck;
10730 results.Add(result);
10731 checkTerrain = false;
10732 } 11793 }
10733 11794
10734 if (checkAgents) 11795 // get some more contacts to sort ???
11796 int physcount = 4 * count;
11797 if (physcount > 20)
11798 physcount = 20;
11799
11800 object physresults;
11801 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
11802
11803 if (physresults == null)
10735 { 11804 {
10736 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11805 list.Add(new LSL_Integer(-3)); // timeout error
10737 { 11806 return list;
10738 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X))
10739 {
10740 ContactResult result = new ContactResult ();
10741 result.ConsumerID = sp.LocalId;
10742 result.Depth = 0;
10743 result.Normal = Vector3.Zero;
10744 result.Pos = posToCheck;
10745 results.Add(result);
10746 }
10747 });
10748 } 11807 }
10749 }
10750 11808
10751 int refcount = 0; 11809 results = (List<ContactResult>)physresults;
10752 foreach (ContactResult result in results)
10753 {
10754 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND)
10755 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0)
10756 continue;
10757 11810
10758 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID); 11811 // for now physics doesn't detect sitted avatars so do it outside physics
11812 if (checkAgents)
11813 {
11814 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11815 foreach (ContactResult r in agentHits)
11816 results.Add(r);
11817 }
10759 11818
10760 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) 11819 // bug: will not detect phantom unless they are physical
10761 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents 11820 // don't use ObjectIntersection because its also bad
10762 11821
10763 if (entity == null) 11822 }
11823 else
11824 {
11825 if (checkTerrain)
10764 { 11826 {
10765 list.Add(UUID.Zero); 11827 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11828 if (groundContact != null)
11829 results.Add((ContactResult)groundContact);
11830 }
10766 11831
10767 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11832 if (checkAgents)
10768 list.Add(0); 11833 {
11834 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11835 foreach (ContactResult r in agentHits)
11836 results.Add(r);
11837 }
10769 11838
10770 list.Add(result.Pos); 11839 if (checkPhysical || checkNonPhysical || detectPhantom)
11840 {
11841 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
11842 foreach (ContactResult r in objectHits)
11843 results.Add(r);
11844 }
11845 }
10771 11846
10772 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11847 results.Sort(delegate(ContactResult a, ContactResult b)
10773 list.Add(result.Normal); 11848 {
11849 return a.Depth.CompareTo(b.Depth);
11850 });
11851
11852 int values = 0;
11853 SceneObjectGroup thisgrp = m_host.ParentGroup;
10774 11854
10775 continue; //Can't find it, so add UUID.Zero 11855 foreach (ContactResult result in results)
10776 } 11856 {
11857 if (result.Depth > dist)
11858 continue;
10777 11859
10778 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity && 11860 // physics ray can return colisions with host prim
10779 ((ISceneChildEntity)intersection.obj).PhysActor == null) 11861 if (m_host.LocalId == result.ConsumerID)
10780 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects 11862 continue;
11863
11864 UUID itemID = UUID.Zero;
11865 int linkNum = 0;
10781 11866
10782 if (entity is SceneObjectPart) 11867 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
11868 // It's a prim!
11869 if (part != null)
10783 { 11870 {
10784 PhysicsActor pa = ((SceneObjectPart)entity).PhysActor; 11871 // dont detect members of same object ???
11872 if (part.ParentGroup == thisgrp)
11873 continue;
10785 11874
10786 if (pa != null && pa.IsPhysical) 11875 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10787 { 11876 itemID = part.ParentGroup.UUID;
10788 if (!checkPhysical)
10789 continue;
10790 }
10791 else 11877 else
10792 { 11878 itemID = part.UUID;
10793 if (!checkNonPhysical)
10794 continue;
10795 }
10796 }
10797 11879
10798 refcount++; 11880 linkNum = part.LinkNum;
10799 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11881 }
10800 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10801 else 11882 else
10802 list.Add(entity.UUID);
10803
10804 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10805 { 11883 {
10806 if (entity is SceneObjectPart) 11884 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10807 list.Add(((SceneObjectPart)entity).LinkNum); 11885 /// It it a boy? a girl?
10808 else 11886 if (sp != null)
10809 list.Add(0); 11887 itemID = sp.UUID;
10810 } 11888 }
10811 11889
10812 list.Add(result.Pos); 11890 list.Add(new LSL_String(itemID.ToString()));
11891 list.Add(new LSL_String(result.Pos.ToString()));
11892
11893 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
11894 list.Add(new LSL_Integer(linkNum));
10813 11895
10814 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11896 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10815 list.Add(result.Normal); 11897 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11898
11899 values++;
11900 if (values >= count)
11901 break;
10816 } 11902 }
10817 11903
10818 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11904 list.Add(new LSL_Integer(values));
10819 11905
10820 return list; 11906 return list;
10821 } 11907 }
@@ -10855,7 +11941,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10855 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 11941 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10856 if (!isAccount) return 0; 11942 if (!isAccount) return 0;
10857 if (estate.HasAccess(id)) return 1; 11943 if (estate.HasAccess(id)) return 1;
10858 if (estate.IsBanned(id)) 11944 if (estate.IsBanned(id, World.GetUserFlags(id)))
10859 estate.RemoveBan(id); 11945 estate.RemoveBan(id);
10860 estate.AddEstateUser(id); 11946 estate.AddEstateUser(id);
10861 break; 11947 break;
@@ -10874,14 +11960,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10874 break; 11960 break;
10875 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 11961 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10876 if (!isAccount) return 0; 11962 if (!isAccount) return 0;
10877 if (estate.IsBanned(id)) return 1; 11963 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10878 EstateBan ban = new EstateBan(); 11964 EstateBan ban = new EstateBan();
10879 ban.EstateID = estate.EstateID; 11965 ban.EstateID = estate.EstateID;
10880 ban.BannedUserID = id; 11966 ban.BannedUserID = id;
10881 estate.AddBan(ban); 11967 estate.AddBan(ban);
10882 break; 11968 break;
10883 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 11969 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10884 if (!isAccount || !estate.IsBanned(id)) return 0; 11970 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10885 estate.RemoveBan(id); 11971 estate.RemoveBan(id);
10886 break; 11972 break;
10887 default: return 0; 11973 default: return 0;
@@ -10910,7 +11996,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10910 return 16384; 11996 return 16384;
10911 } 11997 }
10912 11998
10913 public LSL_Integer llGetUsedMemory() 11999 public virtual LSL_Integer llGetUsedMemory()
10914 { 12000 {
10915 m_host.AddScriptLPS(1); 12001 m_host.AddScriptLPS(1);
10916 // The value returned for LSO scripts in SL 12002 // The value returned for LSO scripts in SL
@@ -10938,7 +12024,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10938 public void llSetSoundQueueing(int queue) 12024 public void llSetSoundQueueing(int queue)
10939 { 12025 {
10940 m_host.AddScriptLPS(1); 12026 m_host.AddScriptLPS(1);
10941 NotImplemented("llSetSoundQueueing");
10942 } 12027 }
10943 12028
10944 public void llCollisionSprite(string impact_sprite) 12029 public void llCollisionSprite(string impact_sprite)
@@ -10950,10 +12035,270 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10950 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12035 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10951 { 12036 {
10952 m_host.AddScriptLPS(1); 12037 m_host.AddScriptLPS(1);
10953 NotImplemented("llGodLikeRezObject"); 12038
12039 if (!World.Permissions.IsGod(m_host.OwnerID))
12040 NotImplemented("llGodLikeRezObject");
12041
12042 AssetBase rezAsset = World.AssetService.Get(inventory);
12043 if (rezAsset == null)
12044 {
12045 llSay(0, "Asset not found");
12046 return;
12047 }
12048
12049 SceneObjectGroup group = null;
12050
12051 try
12052 {
12053 string xmlData = Utils.BytesToString(rezAsset.Data);
12054 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12055 }
12056 catch
12057 {
12058 llSay(0, "Asset not found");
12059 return;
12060 }
12061
12062 if (group == null)
12063 {
12064 llSay(0, "Asset not found");
12065 return;
12066 }
12067
12068 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12069 group.RootPart.AttachOffset = group.AbsolutePosition;
12070
12071 group.ResetIDs();
12072
12073 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12074 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12075 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12076 group.ScheduleGroupForFullUpdate();
12077
12078 // objects rezzed with this method are die_at_edge by default.
12079 group.RootPart.SetDieAtEdge(true);
12080
12081 group.ResumeScripts();
12082
12083 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12084 "object_rez", new Object[] {
12085 new LSL_String(
12086 group.RootPart.UUID.ToString()) },
12087 new DetectParams[0]));
12088 }
12089
12090 public LSL_String llTransferLindenDollars(string destination, int amount)
12091 {
12092 UUID txn = UUID.Random();
12093
12094 Util.FireAndForget(delegate(object x)
12095 {
12096 int replycode = 0;
12097 string replydata = destination + "," + amount.ToString();
12098
12099 try
12100 {
12101 TaskInventoryItem item = m_item;
12102 if (item == null)
12103 {
12104 replydata = "SERVICE_ERROR";
12105 return;
12106 }
12107
12108 m_host.AddScriptLPS(1);
12109
12110 if (item.PermsGranter == UUID.Zero)
12111 {
12112 replydata = "MISSING_PERMISSION_DEBIT";
12113 return;
12114 }
12115
12116 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
12117 {
12118 replydata = "MISSING_PERMISSION_DEBIT";
12119 return;
12120 }
12121
12122 UUID toID = new UUID();
12123
12124 if (!UUID.TryParse(destination, out toID))
12125 {
12126 replydata = "INVALID_AGENT";
12127 return;
12128 }
12129
12130 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
12131
12132 if (money == null)
12133 {
12134 replydata = "TRANSFERS_DISABLED";
12135 return;
12136 }
12137
12138 bool result = money.ObjectGiveMoney(
12139 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
12140
12141 if (result)
12142 {
12143 replycode = 1;
12144 return;
12145 }
12146
12147 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
12148 }
12149 finally
12150 {
12151 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
12152 "transaction_result", new Object[] {
12153 new LSL_String(txn.ToString()),
12154 new LSL_Integer(replycode),
12155 new LSL_String(replydata) },
12156 new DetectParams[0]));
12157 }
12158 });
12159
12160 return txn.ToString();
10954 } 12161 }
10955 12162
10956 #endregion 12163 #endregion
12164
12165 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12166 {
12167 SceneObjectGroup group = m_host.ParentGroup;
12168
12169 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12170 return;
12171 if (group.IsAttachment)
12172 return;
12173
12174 if (frames.Data.Length > 0) // We are getting a new motion
12175 {
12176 if (group.RootPart.KeyframeMotion != null)
12177 group.RootPart.KeyframeMotion.Stop();
12178 group.RootPart.KeyframeMotion = null;
12179
12180 int idx = 0;
12181
12182 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12183 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12184
12185 while (idx < options.Data.Length)
12186 {
12187 int option = (int)options.GetLSLIntegerItem(idx++);
12188 int remain = options.Data.Length - idx;
12189
12190 switch (option)
12191 {
12192 case ScriptBaseClass.KFM_MODE:
12193 if (remain < 1)
12194 break;
12195 int modeval = (int)options.GetLSLIntegerItem(idx++);
12196 switch(modeval)
12197 {
12198 case ScriptBaseClass.KFM_FORWARD:
12199 mode = KeyframeMotion.PlayMode.Forward;
12200 break;
12201 case ScriptBaseClass.KFM_REVERSE:
12202 mode = KeyframeMotion.PlayMode.Reverse;
12203 break;
12204 case ScriptBaseClass.KFM_LOOP:
12205 mode = KeyframeMotion.PlayMode.Loop;
12206 break;
12207 case ScriptBaseClass.KFM_PING_PONG:
12208 mode = KeyframeMotion.PlayMode.PingPong;
12209 break;
12210 }
12211 break;
12212 case ScriptBaseClass.KFM_DATA:
12213 if (remain < 1)
12214 break;
12215 int dataval = (int)options.GetLSLIntegerItem(idx++);
12216 data = (KeyframeMotion.DataFormat)dataval;
12217 break;
12218 }
12219 }
12220
12221 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12222
12223 idx = 0;
12224
12225 int elemLength = 2;
12226 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12227 elemLength = 3;
12228
12229 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12230 while (idx < frames.Data.Length)
12231 {
12232 int remain = frames.Data.Length - idx;
12233
12234 if (remain < elemLength)
12235 break;
12236
12237 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12238 frame.Position = null;
12239 frame.Rotation = null;
12240
12241 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12242 {
12243 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12244 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12245 }
12246 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12247 {
12248 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12249 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12250 }
12251
12252 float tempf = (float)frames.GetLSLFloatItem(idx++);
12253 frame.TimeMS = (int)(tempf * 1000.0f);
12254
12255 keyframes.Add(frame);
12256 }
12257
12258 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12259 group.RootPart.KeyframeMotion.Start();
12260 }
12261 else
12262 {
12263 if (group.RootPart.KeyframeMotion == null)
12264 return;
12265
12266 if (options.Data.Length == 0)
12267 {
12268 group.RootPart.KeyframeMotion.Stop();
12269 return;
12270 }
12271
12272 int code = (int)options.GetLSLIntegerItem(0);
12273
12274 int idx = 0;
12275
12276 while (idx < options.Data.Length)
12277 {
12278 int option = (int)options.GetLSLIntegerItem(idx++);
12279 int remain = options.Data.Length - idx;
12280
12281 switch (option)
12282 {
12283 case ScriptBaseClass.KFM_COMMAND:
12284 int cmd = (int)options.GetLSLIntegerItem(idx++);
12285 switch (cmd)
12286 {
12287 case ScriptBaseClass.KFM_CMD_PLAY:
12288 group.RootPart.KeyframeMotion.Start();
12289 break;
12290 case ScriptBaseClass.KFM_CMD_STOP:
12291 group.RootPart.KeyframeMotion.Stop();
12292 break;
12293 case ScriptBaseClass.KFM_CMD_PAUSE:
12294 group.RootPart.KeyframeMotion.Pause();
12295 break;
12296 }
12297 break;
12298 }
12299 }
12300 }
12301 }
10957 } 12302 }
10958 12303
10959 public class NotecardCache 12304 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}