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.cs118
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs3001
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs116
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs9
-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, 2945 insertions, 1075 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 993d10f..3cbdde5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -301,6 +301,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
301 return null; 301 return null;
302 } 302 }
303 303
304 public static void StateChange(IScriptEngine engine, uint localID, UUID itemID)
305 {
306 // Remove a specific script
307
308 // Remove dataserver events
309 m_Dataserver[engine].RemoveEvents(localID, itemID);
310
311 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>();
312 if (comms != null)
313 comms.DeleteListener(itemID);
314
315 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>();
316 xmlrpc.DeleteChannels(itemID);
317 xmlrpc.CancelSRDRequests(itemID);
318
319 // Remove Sensors
320 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID);
321
322 }
323
304 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID) 324 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID)
305 { 325 {
306 List<Object> data = new List<Object>(); 326 List<Object> data = new List<Object>();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
new file mode 100644
index 0000000..489c1c6
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
@@ -0,0 +1,118 @@
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 uint m_localID;
63 internal UUID m_itemID;
64 internal bool m_CMFunctionsEnabled = false;
65
66 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
67 {
68 m_ScriptEngine = ScriptEngine;
69 m_host = host;
70 m_localID = localID;
71 m_itemID = itemID;
72
73 if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false))
74 m_CMFunctionsEnabled = true;
75 }
76
77 public override Object InitializeLifetimeService()
78 {
79 ILease lease = (ILease)base.InitializeLifetimeService();
80
81 if (lease.CurrentState == LeaseState.Initial)
82 {
83 lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
84 // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
85 // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
86 }
87 return lease;
88 }
89
90 public Scene World
91 {
92 get { return m_ScriptEngine.World; }
93 }
94
95 public string cmDetectedCountry(int number)
96 {
97 m_host.AddScriptLPS(1);
98 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number);
99 if (detectedParams == null)
100 return String.Empty;
101 return detectedParams.Country;
102 }
103
104 public string cmGetAgentCountry(LSL_Key key)
105 {
106 if (!World.Permissions.IsGod(m_host.OwnerID))
107 return String.Empty;
108
109 UUID uuid;
110
111 if (!UUID.TryParse(key, out uuid))
112 return String.Empty;
113
114 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
115 return account.UserCountry;
116 }
117 }
118}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index d641958..5a5f2e1 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{
@@ -104,16 +108,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
104 protected int m_notecardLineReadCharsMax = 255; 108 protected int m_notecardLineReadCharsMax = 255;
105 protected int m_scriptConsoleChannel = 0; 109 protected int m_scriptConsoleChannel = 0;
106 protected bool m_scriptConsoleChannelEnabled = false; 110 protected bool m_scriptConsoleChannelEnabled = false;
111 protected bool m_debuggerSafe = false;
107 protected IUrlModule m_UrlModule = null; 112 protected IUrlModule m_UrlModule = null;
108 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 113 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
109 new Dictionary<UUID, UserInfoCacheEntry>(); 114 new Dictionary<UUID, UserInfoCacheEntry>();
110 115
116 protected Timer m_ShoutSayTimer;
117 protected int m_SayShoutCount = 0;
118
111 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 119 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
112 { 120 {
121 m_ShoutSayTimer = new Timer(1000);
122 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
123 m_ShoutSayTimer.AutoReset = true;
124 m_ShoutSayTimer.Start();
125
113 m_ScriptEngine = ScriptEngine; 126 m_ScriptEngine = ScriptEngine;
114 m_host = host; 127 m_host = host;
115 m_localID = localID; 128 m_localID = localID;
116 m_itemID = itemID; 129 m_itemID = itemID;
130 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
117 131
118 m_ScriptDelayFactor = 132 m_ScriptDelayFactor =
119 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 133 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
@@ -161,6 +175,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
161 get { return m_ScriptEngine.World; } 175 get { return m_ScriptEngine.World; }
162 } 176 }
163 177
178 [DebuggerNonUserCode]
164 public void state(string newState) 179 public void state(string newState)
165 { 180 {
166 m_ScriptEngine.SetState(m_itemID, newState); 181 m_ScriptEngine.SetState(m_itemID, newState);
@@ -170,6 +185,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
170 /// Reset the named script. The script must be present 185 /// Reset the named script. The script must be present
171 /// in the same prim. 186 /// in the same prim.
172 /// </summary> 187 /// </summary>
188 [DebuggerNonUserCode]
173 public void llResetScript() 189 public void llResetScript()
174 { 190 {
175 m_host.AddScriptLPS(1); 191 m_host.AddScriptLPS(1);
@@ -226,9 +242,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
226 } 242 }
227 } 243 }
228 244
245 public List<ScenePresence> GetLinkAvatars(int linkType)
246 {
247 List<ScenePresence> ret = new List<ScenePresence>();
248 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
249 return ret;
250
251 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
252
253 switch (linkType)
254 {
255 case ScriptBaseClass.LINK_SET:
256 return avs;
257
258 case ScriptBaseClass.LINK_ROOT:
259 return ret;
260
261 case ScriptBaseClass.LINK_ALL_OTHERS:
262 return avs;
263
264 case ScriptBaseClass.LINK_ALL_CHILDREN:
265 return avs;
266
267 case ScriptBaseClass.LINK_THIS:
268 return ret;
269
270 default:
271 if (linkType < 0)
272 return ret;
273
274 int partCount = m_host.ParentGroup.GetPartCount();
275
276 if (linkType <= partCount)
277 {
278 return ret;
279 }
280 else
281 {
282 linkType = linkType - partCount;
283 if (linkType > avs.Count)
284 {
285 return ret;
286 }
287 else
288 {
289 ret.Add(avs[linkType-1]);
290 return ret;
291 }
292 }
293 }
294 }
295
229 public List<SceneObjectPart> GetLinkParts(int linkType) 296 public List<SceneObjectPart> GetLinkParts(int linkType)
230 { 297 {
231 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 298 List<SceneObjectPart> ret = new List<SceneObjectPart>();
299 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
300 return ret;
232 ret.Add(m_host); 301 ret.Add(m_host);
233 302
234 switch (linkType) 303 switch (linkType)
@@ -282,28 +351,46 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
282 /// <returns></returns> 351 /// <returns></returns>
283 protected TaskInventoryItem GetSelfInventoryItem() 352 protected TaskInventoryItem GetSelfInventoryItem()
284 { 353 {
285 lock (m_host.TaskInventory) 354 TaskInventoryItem invItem = null;
286 return m_host.TaskInventory[m_itemID]; 355
356 bool unlock = false;
357 if (!m_host.TaskInventory.IsReadLockedByMe())
358 {
359 m_host.TaskInventory.LockItemsForRead(true);
360 unlock = true;
361 }
362
363 invItem = m_host.TaskInventory[m_itemID];
364
365 if (unlock)
366 {
367 m_host.TaskInventory.LockItemsForRead(false);
368 }
369
370 return invItem;
287 } 371 }
288 372
289 protected UUID InventoryKey(string name, int type) 373 protected UUID InventoryKey(string name, int type)
290 { 374 {
291 m_host.AddScriptLPS(1); 375 m_host.AddScriptLPS(1);
292 376 m_host.TaskInventory.LockItemsForRead(true);
293 lock (m_host.TaskInventory) 377
378 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
294 { 379 {
295 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 380 if (inv.Value.Name == name)
296 { 381 {
297 if (inv.Value.Name == name) 382 m_host.TaskInventory.LockItemsForRead(false);
383
384 if (inv.Value.Type != type)
298 { 385 {
299 if (inv.Value.Type != type) 386 return UUID.Zero;
300 return UUID.Zero;
301
302 return inv.Value.AssetID;
303 } 387 }
388
389 return inv.Value.AssetID;
304 } 390 }
305 } 391 }
306 392
393 m_host.TaskInventory.LockItemsForRead(false);
307 return UUID.Zero; 394 return UUID.Zero;
308 } 395 }
309 396
@@ -311,17 +398,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
311 { 398 {
312 m_host.AddScriptLPS(1); 399 m_host.AddScriptLPS(1);
313 400
314 lock (m_host.TaskInventory) 401
402 m_host.TaskInventory.LockItemsForRead(true);
403
404 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
315 { 405 {
316 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 406 if (inv.Value.Name == name)
317 { 407 {
318 if (inv.Value.Name == name) 408 m_host.TaskInventory.LockItemsForRead(false);
319 { 409 return inv.Value.AssetID;
320 return inv.Value.AssetID;
321 }
322 } 410 }
323 } 411 }
324 412
413 m_host.TaskInventory.LockItemsForRead(false);
414
415
325 return UUID.Zero; 416 return UUID.Zero;
326 } 417 }
327 418
@@ -463,31 +554,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
463 554
464 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 555 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
465 556
466 /// <summary> 557 // Utility function for llRot2Euler
467 /// Convert an LSL rotation to a Euler vector. 558
468 /// </summary> 559 // normalize an angle between -PI and PI (-180 to +180 degrees)
469 /// <remarks> 560 protected double NormalizeAngle(double angle)
470 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
471 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
472 /// </remarks>
473 /// <param name="r"></param>
474 /// <returns></returns>
475 public LSL_Vector llRot2Euler(LSL_Rotation r)
476 { 561 {
477 m_host.AddScriptLPS(1); 562 if (angle > -Math.PI && angle < Math.PI)
563 return angle;
564
565 int numPis = (int)(Math.PI / angle);
566 double remainder = angle - Math.PI * numPis;
567 if (numPis % 2 == 1)
568 return Math.PI - angle;
569 return remainder;
570 }
478 571
479 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 572 public LSL_Vector llRot2Euler(LSL_Rotation q1)
480 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 573 {
481 if (m == 0.0) return new LSL_Vector(); 574 m_host.AddScriptLPS(1);
482 double x = Math.Atan2(-v.y, v.z); 575 LSL_Vector eul = new LSL_Vector();
483 double sin = v.x / m;
484 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities.
485 double y = Math.Asin(sin);
486 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
487 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)));
488 double z = Math.Atan2(v.y, v.x);
489 576
490 return new LSL_Vector(x, y, z); 577 double sqw = q1.s*q1.s;
578 double sqx = q1.x*q1.x;
579 double sqy = q1.z*q1.z;
580 double sqz = q1.y*q1.y;
581 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
582 double test = q1.x*q1.z + q1.y*q1.s;
583 if (test > 0.4999*unit) { // singularity at north pole
584 eul.z = 2 * Math.Atan2(q1.x,q1.s);
585 eul.y = Math.PI/2;
586 eul.x = 0;
587 return eul;
588 }
589 if (test < -0.4999*unit) { // singularity at south pole
590 eul.z = -2 * Math.Atan2(q1.x,q1.s);
591 eul.y = -Math.PI/2;
592 eul.x = 0;
593 return eul;
594 }
595 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
596 eul.y = Math.Asin(2*test/unit);
597 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
598 return eul;
491 } 599 }
492 600
493 /* From wiki: 601 /* From wiki:
@@ -689,77 +797,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
689 { 797 {
690 //A and B should both be normalized 798 //A and B should both be normalized
691 m_host.AddScriptLPS(1); 799 m_host.AddScriptLPS(1);
692 LSL_Rotation rotBetween; 800 /* This method is more accurate than the SL one, and thus causes problems
693 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 801 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
694 // continue calculation. 802
695 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 803 double dotProduct = LSL_Vector.Dot(a, b);
804 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
805 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
806 double angle = Math.Acos(dotProduct / magProduct);
807 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
808 double s = Math.Sin(angle / 2);
809
810 double x = axis.x * s;
811 double y = axis.y * s;
812 double z = axis.z * s;
813 double w = Math.Cos(angle / 2);
814
815 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
816 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
817
818 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
819 */
820
821 // This method mimics the 180 errors found in SL
822 // See www.euclideanspace.com... angleBetween
823 LSL_Vector vec_a = a;
824 LSL_Vector vec_b = b;
825
826 // Eliminate zero length
827 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
828 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
829 if (vec_a_mag < 0.00001 ||
830 vec_b_mag < 0.00001)
696 { 831 {
697 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 832 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
698 } 833 }
699 else 834
835 // Normalize
836 vec_a = llVecNorm(vec_a);
837 vec_b = llVecNorm(vec_b);
838
839 // Calculate axis and rotation angle
840 LSL_Vector axis = vec_a % vec_b;
841 LSL_Float cos_theta = vec_a * vec_b;
842
843 // Check if parallel
844 if (cos_theta > 0.99999)
700 { 845 {
701 a = LSL_Vector.Norm(a); 846 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
702 b = LSL_Vector.Norm(b); 847 }
703 double dotProduct = LSL_Vector.Dot(a, b); 848
704 // There are two degenerate cases possible. These are for vectors 180 or 849 // Check if anti-parallel
705 // 0 degrees apart. These have to be detected and handled individually. 850 else if (cos_theta < -0.99999)
706 // 851 {
707 // Check for vectors 180 degrees apart. 852 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
708 // A dot product of -1 would mean the angle between vectors is 180 degrees. 853 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
709 if (dotProduct < -0.9999999f) 854 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
710 { 855 }
711 // First assume X axis is orthogonal to the vectors. 856 else // other rotation
712 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 857 {
713 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 858 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
714 // Check for near zero vector. A very small non-zero number here will create 859 axis = llVecNorm(axis);
715 // a rotation in an undesired direction. 860 double x, y, z, s, t;
716 if (LSL_Vector.Mag(orthoVector) > 0.0001) 861 s = Math.Cos(theta);
717 { 862 t = Math.Sin(theta);
718 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 863 x = axis.x * t;
719 } 864 y = axis.y * t;
720 // If the magnitude of the vector was near zero, then assume the X axis is not 865 z = axis.z * t;
721 // orthogonal and use the Z axis instead. 866 return new LSL_Rotation(x,y,z,s);
722 else
723 {
724 // Set 180 z rotation.
725 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
726 }
727 }
728 // Check for parallel vectors.
729 // A dot product of 1 would mean the angle between vectors is 0 degrees.
730 else if (dotProduct > 0.9999999f)
731 {
732 // Set zero rotation.
733 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
734 }
735 else
736 {
737 // All special checks have been performed so get the axis of rotation.
738 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
739 // Quarternion s value is the length of the unit vector + dot product.
740 double qs = 1.0 + dotProduct;
741 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
742 // Normalize the rotation.
743 double mag = LSL_Rotation.Mag(rotBetween);
744 // We shouldn't have to worry about a divide by zero here. The qs value will be
745 // non-zero because we already know if we're here, then the dotProduct is not -1 so
746 // qs will not be zero. Also, we've already handled the input vectors being zero so the
747 // crossProduct vector should also not be zero.
748 rotBetween.x = rotBetween.x / mag;
749 rotBetween.y = rotBetween.y / mag;
750 rotBetween.z = rotBetween.z / mag;
751 rotBetween.s = rotBetween.s / mag;
752 // Check for undefined values and set zero rotation if any found. This code might not actually be required
753 // any longer since zero vectors are checked for at the top.
754 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
755 {
756 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
757 }
758 }
759 } 867 }
760 return rotBetween;
761 } 868 }
762 869
763 public void llWhisper(int channelID, string text) 870 public void llWhisper(int channelID, string text)
764 { 871 {
765 m_host.AddScriptLPS(1); 872 m_host.AddScriptLPS(1);
@@ -779,6 +886,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
779 { 886 {
780 m_host.AddScriptLPS(1); 887 m_host.AddScriptLPS(1);
781 888
889 if (channelID == 0)
890 m_SayShoutCount++;
891
892 if (m_SayShoutCount >= 11)
893 ScriptSleep(2000);
894
782 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 895 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
783 { 896 {
784 Console.WriteLine(text); 897 Console.WriteLine(text);
@@ -801,6 +914,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
801 { 914 {
802 m_host.AddScriptLPS(1); 915 m_host.AddScriptLPS(1);
803 916
917 if (channelID == 0)
918 m_SayShoutCount++;
919
920 if (m_SayShoutCount >= 11)
921 ScriptSleep(2000);
922
804 if (text.Length > 1023) 923 if (text.Length > 1023)
805 text = text.Substring(0, 1023); 924 text = text.Substring(0, 1023);
806 925
@@ -1103,10 +1222,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1103 return detectedParams.TouchUV; 1222 return detectedParams.TouchUV;
1104 } 1223 }
1105 1224
1225 [DebuggerNonUserCode]
1106 public virtual void llDie() 1226 public virtual void llDie()
1107 { 1227 {
1108 m_host.AddScriptLPS(1); 1228 m_host.AddScriptLPS(1);
1109 throw new SelfDeleteException(); 1229 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1110 } 1230 }
1111 1231
1112 public LSL_Float llGround(LSL_Vector offset) 1232 public LSL_Float llGround(LSL_Vector offset)
@@ -1179,6 +1299,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1179 1299
1180 public void llSetStatus(int status, int value) 1300 public void llSetStatus(int status, int value)
1181 { 1301 {
1302 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1303 return;
1182 m_host.AddScriptLPS(1); 1304 m_host.AddScriptLPS(1);
1183 1305
1184 int statusrotationaxis = 0; 1306 int statusrotationaxis = 0;
@@ -1410,6 +1532,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1410 { 1532 {
1411 m_host.AddScriptLPS(1); 1533 m_host.AddScriptLPS(1);
1412 1534
1535 SetColor(m_host, color, face);
1536 }
1537
1538 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1539 {
1540 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1541 return;
1542
1543 Primitive.TextureEntry tex = part.Shape.Textures;
1544 Color4 texcolor;
1545 if (face >= 0 && face < GetNumberOfSides(part))
1546 {
1547 texcolor = tex.CreateFace((uint)face).RGBA;
1548 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1549 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1550 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1551 tex.FaceTextures[face].RGBA = texcolor;
1552 part.UpdateTextureEntry(tex.GetBytes());
1553 return;
1554 }
1555 else if (face == ScriptBaseClass.ALL_SIDES)
1556 {
1557 for (uint i = 0; i < GetNumberOfSides(part); i++)
1558 {
1559 if (tex.FaceTextures[i] != null)
1560 {
1561 texcolor = tex.FaceTextures[i].RGBA;
1562 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1563 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1564 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1565 tex.FaceTextures[i].RGBA = texcolor;
1566 }
1567 texcolor = tex.DefaultTexture.RGBA;
1568 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1569 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1570 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1571 tex.DefaultTexture.RGBA = texcolor;
1572 }
1573 part.UpdateTextureEntry(tex.GetBytes());
1574 return;
1575 }
1576
1413 if (face == ScriptBaseClass.ALL_SIDES) 1577 if (face == ScriptBaseClass.ALL_SIDES)
1414 face = SceneObjectPart.ALL_SIDES; 1578 face = SceneObjectPart.ALL_SIDES;
1415 1579
@@ -1418,6 +1582,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1418 1582
1419 public void SetTexGen(SceneObjectPart part, int face,int style) 1583 public void SetTexGen(SceneObjectPart part, int face,int style)
1420 { 1584 {
1585 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1586 return;
1587
1421 Primitive.TextureEntry tex = part.Shape.Textures; 1588 Primitive.TextureEntry tex = part.Shape.Textures;
1422 MappingType textype; 1589 MappingType textype;
1423 textype = MappingType.Default; 1590 textype = MappingType.Default;
@@ -1448,6 +1615,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1448 1615
1449 public void SetGlow(SceneObjectPart part, int face, float glow) 1616 public void SetGlow(SceneObjectPart part, int face, float glow)
1450 { 1617 {
1618 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1619 return;
1620
1451 Primitive.TextureEntry tex = part.Shape.Textures; 1621 Primitive.TextureEntry tex = part.Shape.Textures;
1452 if (face >= 0 && face < GetNumberOfSides(part)) 1622 if (face >= 0 && face < GetNumberOfSides(part))
1453 { 1623 {
@@ -1473,6 +1643,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1473 1643
1474 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1644 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1475 { 1645 {
1646 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1647 return;
1476 1648
1477 Shininess sval = new Shininess(); 1649 Shininess sval = new Shininess();
1478 1650
@@ -1523,6 +1695,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1523 1695
1524 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1696 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1525 { 1697 {
1698 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1699 return;
1700
1526 Primitive.TextureEntry tex = part.Shape.Textures; 1701 Primitive.TextureEntry tex = part.Shape.Textures;
1527 if (face >= 0 && face < GetNumberOfSides(part)) 1702 if (face >= 0 && face < GetNumberOfSides(part))
1528 { 1703 {
@@ -1583,13 +1758,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1583 m_host.AddScriptLPS(1); 1758 m_host.AddScriptLPS(1);
1584 1759
1585 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1760 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1586 1761 if (parts.Count > 0)
1587 foreach (SceneObjectPart part in parts) 1762 {
1588 SetAlpha(part, alpha, face); 1763 try
1764 {
1765 parts[0].ParentGroup.areUpdatesSuspended = true;
1766 foreach (SceneObjectPart part in parts)
1767 SetAlpha(part, alpha, face);
1768 }
1769 finally
1770 {
1771 parts[0].ParentGroup.areUpdatesSuspended = false;
1772 }
1773 }
1589 } 1774 }
1590 1775
1591 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1776 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1592 { 1777 {
1778 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1779 return;
1780
1593 Primitive.TextureEntry tex = part.Shape.Textures; 1781 Primitive.TextureEntry tex = part.Shape.Textures;
1594 Color4 texcolor; 1782 Color4 texcolor;
1595 if (face >= 0 && face < GetNumberOfSides(part)) 1783 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1642,7 +1830,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1642 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1830 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1643 float wind, float tension, LSL_Vector Force) 1831 float wind, float tension, LSL_Vector Force)
1644 { 1832 {
1645 if (part == null) 1833 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1646 return; 1834 return;
1647 1835
1648 if (flexi) 1836 if (flexi)
@@ -1676,7 +1864,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1676 /// <param name="falloff"></param> 1864 /// <param name="falloff"></param>
1677 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1865 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1678 { 1866 {
1679 if (part == null) 1867 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1680 return; 1868 return;
1681 1869
1682 if (light) 1870 if (light)
@@ -1753,15 +1941,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1753 m_host.AddScriptLPS(1); 1941 m_host.AddScriptLPS(1);
1754 1942
1755 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1943 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1756 1944 if (parts.Count > 0)
1757 foreach (SceneObjectPart part in parts) 1945 {
1758 SetTexture(part, texture, face); 1946 try
1759 1947 {
1948 parts[0].ParentGroup.areUpdatesSuspended = true;
1949 foreach (SceneObjectPart part in parts)
1950 SetTexture(part, texture, face);
1951 }
1952 finally
1953 {
1954 parts[0].ParentGroup.areUpdatesSuspended = false;
1955 }
1956 }
1760 ScriptSleep(200); 1957 ScriptSleep(200);
1761 } 1958 }
1762 1959
1763 protected void SetTexture(SceneObjectPart part, string texture, int face) 1960 protected void SetTexture(SceneObjectPart part, string texture, int face)
1764 { 1961 {
1962 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1963 return;
1964
1765 UUID textureID = new UUID(); 1965 UUID textureID = new UUID();
1766 1966
1767 textureID = InventoryKey(texture, (int)AssetType.Texture); 1967 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1806,6 +2006,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1806 2006
1807 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 2007 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1808 { 2008 {
2009 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2010 return;
2011
1809 Primitive.TextureEntry tex = part.Shape.Textures; 2012 Primitive.TextureEntry tex = part.Shape.Textures;
1810 if (face >= 0 && face < GetNumberOfSides(part)) 2013 if (face >= 0 && face < GetNumberOfSides(part))
1811 { 2014 {
@@ -1842,6 +2045,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1842 2045
1843 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2046 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1844 { 2047 {
2048 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2049 return;
2050
1845 Primitive.TextureEntry tex = part.Shape.Textures; 2051 Primitive.TextureEntry tex = part.Shape.Textures;
1846 if (face >= 0 && face < GetNumberOfSides(part)) 2052 if (face >= 0 && face < GetNumberOfSides(part))
1847 { 2053 {
@@ -1878,6 +2084,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1878 2084
1879 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2085 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1880 { 2086 {
2087 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2088 return;
2089
1881 Primitive.TextureEntry tex = part.Shape.Textures; 2090 Primitive.TextureEntry tex = part.Shape.Textures;
1882 if (face >= 0 && face < GetNumberOfSides(part)) 2091 if (face >= 0 && face < GetNumberOfSides(part))
1883 { 2092 {
@@ -1982,26 +2191,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1982 return real_vec; 2191 return real_vec;
1983 } 2192 }
1984 2193
2194 public LSL_Integer llSetRegionPos(LSL_Vector pos)
2195 {
2196 return new LSL_Integer(SetRegionPos(m_host, pos));
2197 }
2198
2199 protected int SetRegionPos(SceneObjectPart part, LSL_Vector targetPos)
2200 {
2201 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2202 return 0;
2203
2204 SceneObjectGroup grp = part.ParentGroup;
2205
2206 if (grp.IsAttachment)
2207 return 0;
2208
2209 if (grp.RootPart.PhysActor != null && grp.RootPart.PhysActor.IsPhysical)
2210 return 0;
2211
2212 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)
2213 return 0;
2214
2215 float constrainedX = (float)targetPos.x;
2216 float constrainedY = (float)targetPos.y;
2217
2218 if (constrainedX < 0.0f)
2219 constrainedX = 0.0f;
2220 if (constrainedY < 0.0f)
2221 constrainedY = 0.0f;
2222 if (constrainedX >= (float)Constants.RegionSize)
2223 constrainedX = (float)Constants.RegionSize - 0.1f;
2224 if (constrainedY >= (float)Constants.RegionSize)
2225 constrainedY = (float)Constants.RegionSize -0.1f;
2226
2227 float ground = World.GetGroundHeight(constrainedX, constrainedY);
2228
2229 if (targetPos.z < ground)
2230 targetPos.z = ground;
2231
2232 Vector3 dest = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z);
2233
2234 if (!World.Permissions.CanObjectEntry(grp.UUID, false, dest))
2235 return 0;
2236
2237 grp.UpdateGroupPosition(dest);
2238
2239 return 1;
2240 }
2241
1985 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2242 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1986 { 2243 {
1987 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2244 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2245 return;
2246
1988 LSL_Vector currentPos = GetPartLocalPos(part); 2247 LSL_Vector currentPos = GetPartLocalPos(part);
2248 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
1989 2249
1990 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
1991 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
1992 2250
1993 if (part.ParentGroup.RootPart == part) 2251 if (part.ParentGroup.RootPart == part)
1994 { 2252 {
1995 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
1996 targetPos.z = ground;
1997 SceneObjectGroup parent = part.ParentGroup; 2253 SceneObjectGroup parent = part.ParentGroup;
1998 LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); 2254 Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
1999 parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z)); 2255 if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest))
2256 return;
2257 Util.FireAndForget(delegate(object x) {
2258 parent.UpdateGroupPosition(dest);
2259 });
2000 } 2260 }
2001 else 2261 else
2002 { 2262 {
2003 LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); 2263 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
2004 part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z);
2005 SceneObjectGroup parent = part.ParentGroup; 2264 SceneObjectGroup parent = part.ParentGroup;
2006 parent.HasGroupChanged = true; 2265 parent.HasGroupChanged = true;
2007 parent.ScheduleGroupForTerseUpdate(); 2266 parent.ScheduleGroupForTerseUpdate();
@@ -2034,17 +2293,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2034 else 2293 else
2035 { 2294 {
2036 if (part.ParentGroup.IsAttachment) 2295 if (part.ParentGroup.IsAttachment)
2037 {
2038 pos = part.AttachedPos; 2296 pos = part.AttachedPos;
2039 }
2040 else 2297 else
2041 {
2042 pos = part.AbsolutePosition; 2298 pos = part.AbsolutePosition;
2043 }
2044 } 2299 }
2045 2300
2046// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2047
2048 return new LSL_Vector(pos.X, pos.Y, pos.Z); 2301 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2049 } 2302 }
2050 2303
@@ -2053,9 +2306,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2053 m_host.AddScriptLPS(1); 2306 m_host.AddScriptLPS(1);
2054 2307
2055 // try to let this work as in SL... 2308 // try to let this work as in SL...
2056 if (m_host.ParentID == 0) 2309 if (m_host.LinkNum < 2)
2057 { 2310 {
2058 // special case: If we are root, rotate complete SOG to new rotation 2311 // Special case: If we are root, rotate complete SOG to new
2312 // rotation.
2313 // We are root if the link number is 0 (single prim) or 1
2314 // (root prim). ParentID may be nonzero in attachments and
2315 // using it would cause attachments and HUDs to rotate
2316 // to the wrong positions.
2059 SetRot(m_host, Rot2Quaternion(rot)); 2317 SetRot(m_host, Rot2Quaternion(rot));
2060 } 2318 }
2061 else 2319 else
@@ -2080,6 +2338,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2080 2338
2081 protected void SetRot(SceneObjectPart part, Quaternion rot) 2339 protected void SetRot(SceneObjectPart part, Quaternion rot)
2082 { 2340 {
2341 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2342 return;
2343
2083 part.UpdateRotation(rot); 2344 part.UpdateRotation(rot);
2084 // Update rotation does not move the object in the physics scene if it's a linkset. 2345 // Update rotation does not move the object in the physics scene if it's a linkset.
2085 2346
@@ -2234,13 +2495,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2234 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2495 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2235 { 2496 {
2236 m_host.AddScriptLPS(1); 2497 m_host.AddScriptLPS(1);
2237 m_host.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); 2498 m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
2238 } 2499 }
2239 2500
2240 public void llSetTorque(LSL_Vector torque, int local) 2501 public void llSetTorque(LSL_Vector torque, int local)
2241 { 2502 {
2242 m_host.AddScriptLPS(1); 2503 m_host.AddScriptLPS(1);
2243 m_host.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); 2504 m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0);
2244 } 2505 }
2245 2506
2246 public LSL_Vector llGetTorque() 2507 public LSL_Vector llGetTorque()
@@ -2844,35 +3105,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2844 public void llLookAt(LSL_Vector target, double strength, double damping) 3105 public void llLookAt(LSL_Vector target, double strength, double damping)
2845 { 3106 {
2846 m_host.AddScriptLPS(1); 3107 m_host.AddScriptLPS(1);
2847 // Determine where we are looking from
2848 LSL_Vector from = llGetPos();
2849 3108
2850 // Work out the normalised vector from the source to the target 3109 // Get the normalized vector to the target
2851 LSL_Vector delta = llVecNorm(target - from); 3110 LSL_Vector d1 = llVecNorm(target - llGetPos());
2852 LSL_Vector angle = new LSL_Vector(0,0,0);
2853 3111
2854 // Calculate the yaw 3112 // Get the bearing (yaw)
2855 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3113 LSL_Vector a1 = new LSL_Vector(0,0,0);
2856 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3114 a1.z = llAtan2(d1.y, d1.x);
2857 3115
2858 // Calculate pitch 3116 // Get the elevation (pitch)
2859 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3117 LSL_Vector a2 = new LSL_Vector(0,0,0);
3118 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2860 3119
2861 // we need to convert from a vector describing 3120 LSL_Rotation r1 = llEuler2Rot(a1);
2862 // the angles of rotation in radians into rotation value 3121 LSL_Rotation r2 = llEuler2Rot(a2);
2863 LSL_Rotation rot = llEuler2Rot(angle); 3122 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2864
2865 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2866 // set the rotation of the object, copy that behavior
2867 PhysicsActor pa = m_host.PhysActor;
2868 3123
2869 if (strength == 0 || pa == null || !pa.IsPhysical) 3124 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2870 { 3125 {
2871 llSetRot(rot); 3126 // Do nothing if either value is 0 (this has been checked in SL)
3127 if (strength <= 0.0 || damping <= 0.0)
3128 return;
3129
3130 llSetRot(r3 * r2 * r1);
2872 } 3131 }
2873 else 3132 else
2874 { 3133 {
2875 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3134 if (strength == 0)
3135 {
3136 llSetRot(r3 * r2 * r1);
3137 return;
3138 }
3139
3140 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2876 } 3141 }
2877 } 3142 }
2878 3143
@@ -2917,17 +3182,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2917 } 3182 }
2918 else 3183 else
2919 { 3184 {
2920 if (m_host.IsRoot) 3185 // new SL always returns object mass
2921 { 3186// if (m_host.IsRoot)
3187// {
2922 return m_host.ParentGroup.GetMass(); 3188 return m_host.ParentGroup.GetMass();
2923 } 3189// }
2924 else 3190// else
2925 { 3191// {
2926 return m_host.GetMass(); 3192// return m_host.GetMass();
2927 } 3193// }
2928 } 3194 }
2929 } 3195 }
2930 3196
3197
3198 public LSL_Float llGetMassMKS()
3199 {
3200 return 100f * llGetMass();
3201 }
3202
2931 public void llCollisionFilter(string name, string id, int accept) 3203 public void llCollisionFilter(string name, string id, int accept)
2932 { 3204 {
2933 m_host.AddScriptLPS(1); 3205 m_host.AddScriptLPS(1);
@@ -3038,11 +3310,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3038 { 3310 {
3039 m_host.AddScriptLPS(1); 3311 m_host.AddScriptLPS(1);
3040 3312
3041// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3042// return;
3043
3044 TaskInventoryItem item = GetSelfInventoryItem(); 3313 TaskInventoryItem item = GetSelfInventoryItem();
3045 3314
3315 m_host.TaskInventory.LockItemsForRead(false);
3316
3046 if (item.PermsGranter != m_host.OwnerID) 3317 if (item.PermsGranter != m_host.OwnerID)
3047 return; 3318 return;
3048 3319
@@ -3087,6 +3358,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3087 3358
3088 public void llInstantMessage(string user, string message) 3359 public void llInstantMessage(string user, string message)
3089 { 3360 {
3361 UUID result;
3362 if (!UUID.TryParse(user, out result))
3363 {
3364 ShoutError("An invalid key was passed to llInstantMessage");
3365 ScriptSleep(2000);
3366 return;
3367 }
3368
3369
3090 m_host.AddScriptLPS(1); 3370 m_host.AddScriptLPS(1);
3091 3371
3092 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3372 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3101,14 +3381,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3101 UUID friendTransactionID = UUID.Random(); 3381 UUID friendTransactionID = UUID.Random();
3102 3382
3103 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3383 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3104 3384
3105 GridInstantMessage msg = new GridInstantMessage(); 3385 GridInstantMessage msg = new GridInstantMessage();
3106 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3386 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3107 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3387 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3108 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3388 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3109// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3389// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3110// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3390// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3111 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3391// DateTime dt = DateTime.UtcNow;
3392//
3393// // Ticks from UtcNow, but make it look like local. Evil, huh?
3394// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3395//
3396// try
3397// {
3398// // Convert that to the PST timezone
3399// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3400// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3401// }
3402// catch
3403// {
3404// // No logging here, as it could be VERY spammy
3405// }
3406//
3407// // And make it look local again to fool the unix time util
3408// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3409
3410 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3411
3112 //if (client != null) 3412 //if (client != null)
3113 //{ 3413 //{
3114 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3414 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3122,12 +3422,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3122 msg.message = message.Substring(0, 1024); 3422 msg.message = message.Substring(0, 1024);
3123 else 3423 else
3124 msg.message = message; 3424 msg.message = message;
3125 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3425 msg.dialog = (byte)19; // MessageFromObject
3126 msg.fromGroup = false;// fromGroup; 3426 msg.fromGroup = false;// fromGroup;
3127 msg.offline = (byte)0; //offline; 3427 msg.offline = (byte)0; //offline;
3128 msg.ParentEstateID = 0; //ParentEstateID; 3428 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3129 msg.Position = new Vector3(m_host.AbsolutePosition); 3429 msg.Position = new Vector3(m_host.AbsolutePosition);
3130 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3430 msg.RegionID = World.RegionInfo.RegionID.Guid;
3131 msg.binaryBucket 3431 msg.binaryBucket
3132 = Util.StringToBytes256( 3432 = Util.StringToBytes256(
3133 "{0}/{1}/{2}/{3}", 3433 "{0}/{1}/{2}/{3}",
@@ -3155,7 +3455,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3155 } 3455 }
3156 3456
3157 emailModule.SendEmail(m_host.UUID, address, subject, message); 3457 emailModule.SendEmail(m_host.UUID, address, subject, message);
3158 ScriptSleep(20000); 3458 ScriptSleep(15000);
3159 } 3459 }
3160 3460
3161 public void llGetNextEmail(string address, string subject) 3461 public void llGetNextEmail(string address, string subject)
@@ -3404,15 +3704,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3404 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3704 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3405 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3705 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3406 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3706 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3707 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3407 ScriptBaseClass.PERMISSION_ATTACH; 3708 ScriptBaseClass.PERMISSION_ATTACH;
3408 3709
3409 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3710 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3410 { 3711 {
3411 lock (m_host.TaskInventory) 3712 m_host.TaskInventory.LockItemsForWrite(true);
3412 { 3713 m_host.TaskInventory[m_itemID].PermsGranter = agentID;
3413 m_host.TaskInventory[m_itemID].PermsGranter = agentID; 3714 m_host.TaskInventory[m_itemID].PermsMask = perm;
3414 m_host.TaskInventory[m_itemID].PermsMask = perm; 3715 m_host.TaskInventory.LockItemsForWrite(false);
3415 }
3416 3716
3417 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3717 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3418 "run_time_permissions", new Object[] { 3718 "run_time_permissions", new Object[] {
@@ -3422,28 +3722,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3422 return; 3722 return;
3423 } 3723 }
3424 } 3724 }
3425 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3725 else
3426 { 3726 {
3427 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3727 bool sitting = false;
3428 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3728 if (m_host.SitTargetAvatar == agentID)
3429 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3729 {
3430 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3730 sitting = true;
3431 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3731 }
3732 else
3733 {
3734 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3735 {
3736 if (p.SitTargetAvatar == agentID)
3737 sitting = true;
3738 }
3739 }
3432 3740
3433 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3741 if (sitting)
3434 { 3742 {
3435 lock (m_host.TaskInventory) 3743 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3744 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3745 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3746 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3747 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3748
3749 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3436 { 3750 {
3751 m_host.TaskInventory.LockItemsForWrite(true);
3437 m_host.TaskInventory[m_itemID].PermsGranter = agentID; 3752 m_host.TaskInventory[m_itemID].PermsGranter = agentID;
3438 m_host.TaskInventory[m_itemID].PermsMask = perm; 3753 m_host.TaskInventory[m_itemID].PermsMask = perm;
3439 } 3754 m_host.TaskInventory.LockItemsForWrite(false);
3440 3755
3441 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3756 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3442 "run_time_permissions", new Object[] { 3757 "run_time_permissions", new Object[] {
3443 new LSL_Integer(perm) }, 3758 new LSL_Integer(perm) },
3444 new DetectParams[0])); 3759 new DetectParams[0]));
3445 3760
3446 return; 3761 return;
3762 }
3447 } 3763 }
3448 } 3764 }
3449 3765
@@ -3457,11 +3773,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3457 3773
3458 if (!m_waitingForScriptAnswer) 3774 if (!m_waitingForScriptAnswer)
3459 { 3775 {
3460 lock (m_host.TaskInventory) 3776 m_host.TaskInventory.LockItemsForWrite(true);
3461 { 3777 m_host.TaskInventory[m_itemID].PermsGranter = agentID;
3462 m_host.TaskInventory[m_itemID].PermsGranter = agentID; 3778 m_host.TaskInventory[m_itemID].PermsMask = 0;
3463 m_host.TaskInventory[m_itemID].PermsMask = 0; 3779 m_host.TaskInventory.LockItemsForWrite(false);
3464 }
3465 3780
3466 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3781 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3467 m_waitingForScriptAnswer=true; 3782 m_waitingForScriptAnswer=true;
@@ -3491,11 +3806,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3491 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3806 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3492 llReleaseControls(); 3807 llReleaseControls();
3493 3808
3494 lock (m_host.TaskInventory) 3809 m_host.TaskInventory.LockItemsForWrite(true);
3495 { 3810 m_host.TaskInventory[m_itemID].PermsMask = answer;
3496 m_host.TaskInventory[m_itemID].PermsMask = answer; 3811 m_host.TaskInventory.LockItemsForWrite(false);
3497 } 3812
3498
3499 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3813 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3500 "run_time_permissions", new Object[] { 3814 "run_time_permissions", new Object[] {
3501 new LSL_Integer(answer) }, 3815 new LSL_Integer(answer) },
@@ -3538,14 +3852,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3538 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3852 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3539 { 3853 {
3540 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3854 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3541 3855 if (parts.Count > 0)
3542 foreach (SceneObjectPart part in parts) 3856 {
3543 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3857 try
3858 {
3859 parts[0].ParentGroup.areUpdatesSuspended = true;
3860 foreach (SceneObjectPart part in parts)
3861 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3862 }
3863 finally
3864 {
3865 parts[0].ParentGroup.areUpdatesSuspended = false;
3866 }
3867 }
3544 } 3868 }
3545 3869
3546 public void llCreateLink(string target, int parent) 3870 public void llCreateLink(string target, int parent)
3547 { 3871 {
3548 m_host.AddScriptLPS(1); 3872 m_host.AddScriptLPS(1);
3873
3549 UUID targetID; 3874 UUID targetID;
3550 3875
3551 if (!UUID.TryParse(target, out targetID)) 3876 if (!UUID.TryParse(target, out targetID))
@@ -3653,10 +3978,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3653 // Restructuring Multiple Prims. 3978 // Restructuring Multiple Prims.
3654 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 3979 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3655 parts.Remove(parentPrim.RootPart); 3980 parts.Remove(parentPrim.RootPart);
3656 foreach (SceneObjectPart part in parts) 3981 if (parts.Count > 0)
3657 { 3982 {
3658 parentPrim.DelinkFromGroup(part.LocalId, true); 3983 try
3984 {
3985 parts[0].ParentGroup.areUpdatesSuspended = true;
3986 foreach (SceneObjectPart part in parts)
3987 {
3988 parentPrim.DelinkFromGroup(part.LocalId, true);
3989 }
3990 }
3991 finally
3992 {
3993 parts[0].ParentGroup.areUpdatesSuspended = false;
3994 }
3659 } 3995 }
3996
3660 parentPrim.HasGroupChanged = true; 3997 parentPrim.HasGroupChanged = true;
3661 parentPrim.ScheduleGroupForFullUpdate(); 3998 parentPrim.ScheduleGroupForFullUpdate();
3662 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3999 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3665,12 +4002,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3665 { 4002 {
3666 SceneObjectPart newRoot = parts[0]; 4003 SceneObjectPart newRoot = parts[0];
3667 parts.Remove(newRoot); 4004 parts.Remove(newRoot);
3668 foreach (SceneObjectPart part in parts) 4005
4006 try
3669 { 4007 {
3670 // Required for linking 4008 parts[0].ParentGroup.areUpdatesSuspended = true;
3671 part.ClearUpdateSchedule(); 4009 foreach (SceneObjectPart part in parts)
3672 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4010 {
4011 part.ClearUpdateSchedule();
4012 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4013 }
3673 } 4014 }
4015 finally
4016 {
4017 parts[0].ParentGroup.areUpdatesSuspended = false;
4018 }
4019
4020
3674 newRoot.ParentGroup.HasGroupChanged = true; 4021 newRoot.ParentGroup.HasGroupChanged = true;
3675 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4022 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3676 } 4023 }
@@ -3690,6 +4037,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3690 public void llBreakAllLinks() 4037 public void llBreakAllLinks()
3691 { 4038 {
3692 m_host.AddScriptLPS(1); 4039 m_host.AddScriptLPS(1);
4040
4041 TaskInventoryItem item = GetSelfInventoryItem();
4042
4043 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4044 && !m_automaticLinkPermission)
4045 {
4046 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4047 return;
4048 }
4049
3693 SceneObjectGroup parentPrim = m_host.ParentGroup; 4050 SceneObjectGroup parentPrim = m_host.ParentGroup;
3694 if (parentPrim.AttachmentPoint != 0) 4051 if (parentPrim.AttachmentPoint != 0)
3695 return; // Fail silently if attached 4052 return; // Fail silently if attached
@@ -3709,25 +4066,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3709 public LSL_String llGetLinkKey(int linknum) 4066 public LSL_String llGetLinkKey(int linknum)
3710 { 4067 {
3711 m_host.AddScriptLPS(1); 4068 m_host.AddScriptLPS(1);
3712 List<UUID> keytable = new List<UUID>();
3713 // parse for sitting avatare-uuids
3714 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3715 {
3716 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
3717 keytable.Add(presence.UUID);
3718 });
3719
3720 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3721 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3722 {
3723 return keytable[totalprims - linknum].ToString();
3724 }
3725
3726 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3727 {
3728 return m_host.UUID.ToString();
3729 }
3730
3731 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4069 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3732 if (part != null) 4070 if (part != null)
3733 { 4071 {
@@ -3735,6 +4073,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3735 } 4073 }
3736 else 4074 else
3737 { 4075 {
4076 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4077 {
4078 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4079
4080 if (linknum < 0)
4081 return UUID.Zero.ToString();
4082
4083 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4084 if (avatars.Count > linknum)
4085 {
4086 return avatars[linknum].UUID.ToString();
4087 }
4088 }
3738 return UUID.Zero.ToString(); 4089 return UUID.Zero.ToString();
3739 } 4090 }
3740 } 4091 }
@@ -3834,17 +4185,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3834 m_host.AddScriptLPS(1); 4185 m_host.AddScriptLPS(1);
3835 int count = 0; 4186 int count = 0;
3836 4187
3837 lock (m_host.TaskInventory) 4188 m_host.TaskInventory.LockItemsForRead(true);
4189 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3838 { 4190 {
3839 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4191 if (inv.Value.Type == type || type == -1)
3840 { 4192 {
3841 if (inv.Value.Type == type || type == -1) 4193 count = count + 1;
3842 {
3843 count = count + 1;
3844 }
3845 } 4194 }
3846 } 4195 }
3847 4196
4197 m_host.TaskInventory.LockItemsForRead(false);
3848 return count; 4198 return count;
3849 } 4199 }
3850 4200
@@ -3853,16 +4203,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3853 m_host.AddScriptLPS(1); 4203 m_host.AddScriptLPS(1);
3854 ArrayList keys = new ArrayList(); 4204 ArrayList keys = new ArrayList();
3855 4205
3856 lock (m_host.TaskInventory) 4206 m_host.TaskInventory.LockItemsForRead(true);
4207 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3857 { 4208 {
3858 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4209 if (inv.Value.Type == type || type == -1)
3859 { 4210 {
3860 if (inv.Value.Type == type || type == -1) 4211 keys.Add(inv.Value.Name);
3861 {
3862 keys.Add(inv.Value.Name);
3863 }
3864 } 4212 }
3865 } 4213 }
4214 m_host.TaskInventory.LockItemsForRead(false);
3866 4215
3867 if (keys.Count == 0) 4216 if (keys.Count == 0)
3868 { 4217 {
@@ -3899,25 +4248,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3899 } 4248 }
3900 4249
3901 // move the first object found with this inventory name 4250 // move the first object found with this inventory name
3902 lock (m_host.TaskInventory) 4251 m_host.TaskInventory.LockItemsForRead(true);
4252 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3903 { 4253 {
3904 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4254 if (inv.Value.Name == inventory)
3905 { 4255 {
3906 if (inv.Value.Name == inventory) 4256 found = true;
3907 { 4257 objId = inv.Key;
3908 found = true; 4258 assetType = inv.Value.Type;
3909 objId = inv.Key; 4259 objName = inv.Value.Name;
3910 assetType = inv.Value.Type; 4260 break;
3911 objName = inv.Value.Name;
3912 break;
3913 }
3914 } 4261 }
3915 } 4262 }
4263 m_host.TaskInventory.LockItemsForRead(false);
3916 4264
3917 if (!found) 4265 if (!found)
3918 { 4266 {
3919 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4267 llSay(0, String.Format("Could not find object '{0}'", inventory));
3920 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4268 return;
4269// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3921 } 4270 }
3922 4271
3923 // check if destination is an object 4272 // check if destination is an object
@@ -3943,48 +4292,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3943 return; 4292 return;
3944 } 4293 }
3945 } 4294 }
4295
3946 // destination is an avatar 4296 // destination is an avatar
3947 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4297 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3948 4298
3949 if (agentItem == null) 4299 if (agentItem == null)
3950 return; 4300 return;
3951 4301
3952 byte[] bucket = new byte[17]; 4302 byte[] bucket = new byte[1];
3953 bucket[0] = (byte)assetType; 4303 bucket[0] = (byte)assetType;
3954 byte[] objBytes = agentItem.ID.GetBytes(); 4304 //byte[] objBytes = agentItem.ID.GetBytes();
3955 Array.Copy(objBytes, 0, bucket, 1, 16); 4305 //Array.Copy(objBytes, 0, bucket, 1, 16);
3956 4306
3957 GridInstantMessage msg = new GridInstantMessage(World, 4307 GridInstantMessage msg = new GridInstantMessage(World,
3958 m_host.UUID, m_host.Name+", an object owned by "+ 4308 m_host.OwnerID, m_host.Name, destId,
3959 resolveName(m_host.OwnerID)+",", destId,
3960 (byte)InstantMessageDialog.TaskInventoryOffered, 4309 (byte)InstantMessageDialog.TaskInventoryOffered,
3961 false, objName+"\n"+m_host.Name+" is located at "+ 4310 false, objName+". "+m_host.Name+" is located at "+
3962 World.RegionInfo.RegionName+" "+ 4311 World.RegionInfo.RegionName+" "+
3963 m_host.AbsolutePosition.ToString(), 4312 m_host.AbsolutePosition.ToString(),
3964 agentItem.ID, true, m_host.AbsolutePosition, 4313 agentItem.ID, true, m_host.AbsolutePosition,
3965 bucket); 4314 bucket);
3966 if (m_TransferModule != null) 4315
3967 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4316 ScenePresence sp;
4317
4318 if (World.TryGetScenePresence(destId, out sp))
4319 {
4320 sp.ControllingClient.SendInstantMessage(msg);
4321 }
4322 else
4323 {
4324 if (m_TransferModule != null)
4325 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4326 }
4327
4328 //This delay should only occur when giving inventory to avatars.
3968 ScriptSleep(3000); 4329 ScriptSleep(3000);
3969 } 4330 }
3970 } 4331 }
3971 4332
4333 [DebuggerNonUserCode]
3972 public void llRemoveInventory(string name) 4334 public void llRemoveInventory(string name)
3973 { 4335 {
3974 m_host.AddScriptLPS(1); 4336 m_host.AddScriptLPS(1);
3975 4337
3976 lock (m_host.TaskInventory) 4338 List<TaskInventoryItem> inv;
4339 try
3977 { 4340 {
3978 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4341 m_host.TaskInventory.LockItemsForRead(true);
4342 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4343 }
4344 finally
4345 {
4346 m_host.TaskInventory.LockItemsForRead(false);
4347 }
4348 foreach (TaskInventoryItem item in inv)
4349 {
4350 if (item.Name == name)
3979 { 4351 {
3980 if (item.Name == name) 4352 if (item.ItemID == m_itemID)
3981 { 4353 throw new ScriptDeleteException();
3982 if (item.ItemID == m_itemID) 4354 else
3983 throw new ScriptDeleteException(); 4355 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3984 else 4356 return;
3985 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3986 return;
3987 }
3988 } 4357 }
3989 } 4358 }
3990 } 4359 }
@@ -4019,115 +4388,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4019 { 4388 {
4020 m_host.AddScriptLPS(1); 4389 m_host.AddScriptLPS(1);
4021 4390
4022 UUID uuid = (UUID)id; 4391 UUID uuid;
4023 PresenceInfo pinfo = null; 4392 if (UUID.TryParse(id, out uuid))
4024 UserAccount account;
4025
4026 UserInfoCacheEntry ce;
4027 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4028 { 4393 {
4029 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4394 PresenceInfo pinfo = null;
4030 if (account == null) 4395 UserAccount account;
4396
4397 UserInfoCacheEntry ce;
4398 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4031 { 4399 {
4032 m_userInfoCache[uuid] = null; // Cache negative 4400 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4033 return UUID.Zero.ToString(); 4401 if (account == null)
4034 } 4402 {
4403 m_userInfoCache[uuid] = null; // Cache negative
4404 return UUID.Zero.ToString();
4405 }
4035 4406
4036 4407
4037 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4408 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4038 if (pinfos != null && pinfos.Length > 0) 4409 if (pinfos != null && pinfos.Length > 0)
4039 {
4040 foreach (PresenceInfo p in pinfos)
4041 { 4410 {
4042 if (p.RegionID != UUID.Zero) 4411 foreach (PresenceInfo p in pinfos)
4043 { 4412 {
4044 pinfo = p; 4413 if (p.RegionID != UUID.Zero)
4414 {
4415 pinfo = p;
4416 }
4045 } 4417 }
4046 } 4418 }
4047 }
4048 4419
4049 ce = new UserInfoCacheEntry(); 4420 ce = new UserInfoCacheEntry();
4050 ce.time = Util.EnvironmentTickCount(); 4421 ce.time = Util.EnvironmentTickCount();
4051 ce.account = account; 4422 ce.account = account;
4052 ce.pinfo = pinfo; 4423 ce.pinfo = pinfo;
4053 } 4424 m_userInfoCache[uuid] = ce;
4054 else 4425 }
4055 { 4426 else
4056 if (ce == null) 4427 {
4057 return UUID.Zero.ToString(); 4428 if (ce == null)
4429 return UUID.Zero.ToString();
4058 4430
4059 account = ce.account; 4431 account = ce.account;
4060 pinfo = ce.pinfo; 4432 pinfo = ce.pinfo;
4061 } 4433 }
4062 4434
4063 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4435 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4064 {
4065 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4066 if (pinfos != null && pinfos.Length > 0)
4067 { 4436 {
4068 foreach (PresenceInfo p in pinfos) 4437 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4438 if (pinfos != null && pinfos.Length > 0)
4069 { 4439 {
4070 if (p.RegionID != UUID.Zero) 4440 foreach (PresenceInfo p in pinfos)
4071 { 4441 {
4072 pinfo = p; 4442 if (p.RegionID != UUID.Zero)
4443 {
4444 pinfo = p;
4445 }
4073 } 4446 }
4074 } 4447 }
4075 } 4448 else
4076 else 4449 pinfo = null;
4077 pinfo = null;
4078 4450
4079 ce.time = Util.EnvironmentTickCount(); 4451 ce.time = Util.EnvironmentTickCount();
4080 ce.pinfo = pinfo; 4452 ce.pinfo = pinfo;
4081 } 4453 }
4082 4454
4083 string reply = String.Empty; 4455 string reply = String.Empty;
4084 4456
4085 switch (data) 4457 switch (data)
4086 { 4458 {
4087 case 1: // DATA_ONLINE (0|1) 4459 case 1: // DATA_ONLINE (0|1)
4088 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4460 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4089 reply = "1"; 4461 reply = "1";
4090 else 4462 else
4091 reply = "0"; 4463 reply = "0";
4092 break; 4464 break;
4093 case 2: // DATA_NAME (First Last) 4465 case 2: // DATA_NAME (First Last)
4094 reply = account.FirstName + " " + account.LastName; 4466 reply = account.FirstName + " " + account.LastName;
4095 break; 4467 break;
4096 case 3: // DATA_BORN (YYYY-MM-DD) 4468 case 3: // DATA_BORN (YYYY-MM-DD)
4097 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4469 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4098 born = born.AddSeconds(account.Created); 4470 born = born.AddSeconds(account.Created);
4099 reply = born.ToString("yyyy-MM-dd"); 4471 reply = born.ToString("yyyy-MM-dd");
4100 break; 4472 break;
4101 case 4: // DATA_RATING (0,0,0,0,0,0) 4473 case 4: // DATA_RATING (0,0,0,0,0,0)
4102 reply = "0,0,0,0,0,0"; 4474 reply = "0,0,0,0,0,0";
4103 break; 4475 break;
4104 case 7: // DATA_USERLEVEL (integer) 4476 case 8: // DATA_PAYINFO (0|1|2|3)
4105 reply = account.UserLevel.ToString(); 4477 reply = "0";
4106 break; 4478 break;
4107 case 8: // DATA_PAYINFO (0|1|2|3) 4479 default:
4108 reply = "0"; 4480 return UUID.Zero.ToString(); // Raise no event
4109 break; 4481 }
4110 default:
4111 return UUID.Zero.ToString(); // Raise no event
4112 }
4113 4482
4114 UUID rq = UUID.Random(); 4483 UUID rq = UUID.Random();
4115 4484
4116 UUID tid = AsyncCommands. 4485 UUID tid = AsyncCommands.
4117 DataserverPlugin.RegisterRequest(m_localID, 4486 DataserverPlugin.RegisterRequest(m_localID,
4118 m_itemID, rq.ToString()); 4487 m_itemID, rq.ToString());
4119 4488
4120 AsyncCommands. 4489 AsyncCommands.
4121 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4490 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4122 4491
4123 ScriptSleep(100); 4492 ScriptSleep(100);
4124 return tid.ToString(); 4493 return tid.ToString();
4494 }
4495 else
4496 {
4497 ShoutError("Invalid UUID passed to llRequestAgentData.");
4498 }
4499 return "";
4125 } 4500 }
4126 4501
4127 public LSL_String llRequestInventoryData(string name) 4502 public LSL_String llRequestInventoryData(string name)
4128 { 4503 {
4129 m_host.AddScriptLPS(1); 4504 m_host.AddScriptLPS(1);
4130 4505
4506 //Clone is thread safe
4131 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4507 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4132 4508
4133 foreach (TaskInventoryItem item in itemDictionary.Values) 4509 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4179,19 +4555,64 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4179 if (UUID.TryParse(agent, out agentId)) 4555 if (UUID.TryParse(agent, out agentId))
4180 { 4556 {
4181 ScenePresence presence = World.GetScenePresence(agentId); 4557 ScenePresence presence = World.GetScenePresence(agentId);
4182 if (presence != null) 4558 if (presence != null && presence.PresenceType != PresenceType.Npc)
4183 { 4559 {
4560 // agent must not be a god
4561 if (presence.UserLevel >= 200) return;
4562
4184 // agent must be over the owners land 4563 // agent must be over the owners land
4185 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4564 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4186 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4565 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4187 { 4566 {
4188 World.TeleportClientHome(agentId, presence.ControllingClient); 4567 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4568 {
4569 // They can't be teleported home for some reason
4570 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4571 if (regionInfo != null)
4572 {
4573 World.RequestTeleportLocation(
4574 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4575 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4576 }
4577 }
4189 } 4578 }
4190 } 4579 }
4191 } 4580 }
4192 ScriptSleep(5000); 4581 ScriptSleep(5000);
4193 } 4582 }
4194 4583
4584 public void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt)
4585 {
4586 m_host.AddScriptLPS(1);
4587 UUID agentId = new UUID();
4588 if (UUID.TryParse(agent, out agentId))
4589 {
4590 ScenePresence presence = World.GetScenePresence(agentId);
4591 if (presence != null && presence.PresenceType != PresenceType.Npc)
4592 {
4593 // agent must not be a god
4594 if (presence.GodLevel >= 200) return;
4595
4596 if (simname == String.Empty)
4597 simname = World.RegionInfo.RegionName;
4598
4599 // agent must be over the owners land
4600 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4601 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4602 {
4603 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);
4604 }
4605 else // or must be wearing the prim
4606 {
4607 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4608 {
4609 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);
4610 }
4611 }
4612 }
4613 }
4614 }
4615
4195 public void llTextBox(string agent, string message, int chatChannel) 4616 public void llTextBox(string agent, string message, int chatChannel)
4196 { 4617 {
4197 IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); 4618 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
@@ -4203,7 +4624,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4203 UUID av = new UUID(); 4624 UUID av = new UUID();
4204 if (!UUID.TryParse(agent,out av)) 4625 if (!UUID.TryParse(agent,out av))
4205 { 4626 {
4206 LSLError("First parameter to llDialog needs to be a key"); 4627 //LSLError("First parameter to llDialog needs to be a key");
4207 return; 4628 return;
4208 } 4629 }
4209 4630
@@ -4240,17 +4661,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4240 UUID soundId = UUID.Zero; 4661 UUID soundId = UUID.Zero;
4241 if (!UUID.TryParse(impact_sound, out soundId)) 4662 if (!UUID.TryParse(impact_sound, out soundId))
4242 { 4663 {
4243 lock (m_host.TaskInventory) 4664 m_host.TaskInventory.LockItemsForRead(true);
4665 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4244 { 4666 {
4245 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4667 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4246 { 4668 {
4247 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4669 soundId = item.AssetID;
4248 { 4670 break;
4249 soundId = item.AssetID;
4250 break;
4251 }
4252 } 4671 }
4253 } 4672 }
4673 m_host.TaskInventory.LockItemsForRead(false);
4254 } 4674 }
4255 m_host.CollisionSound = soundId; 4675 m_host.CollisionSound = soundId;
4256 m_host.CollisionSoundVolume = (float)impact_volume; 4676 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4290,6 +4710,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4290 UUID partItemID; 4710 UUID partItemID;
4291 foreach (SceneObjectPart part in parts) 4711 foreach (SceneObjectPart part in parts)
4292 { 4712 {
4713 //Clone is thread safe
4293 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4714 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4294 4715
4295 foreach (TaskInventoryItem item in itemsDictionary.Values) 4716 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4423,7 +4844,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4423 { 4844 {
4424 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4845 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4425 float distance_term = distance * distance * distance; // Script Energy 4846 float distance_term = distance * distance * distance; // Script Energy
4426 float pusher_mass = m_host.GetMass(); 4847 // use total object mass and not part
4848 float pusher_mass = m_host.ParentGroup.GetMass();
4427 4849
4428 float PUSH_ATTENUATION_DISTANCE = 17f; 4850 float PUSH_ATTENUATION_DISTANCE = 17f;
4429 float PUSH_ATTENUATION_SCALE = 5f; 4851 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4664,23 +5086,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4664 { 5086 {
4665 m_host.AddScriptLPS(1); 5087 m_host.AddScriptLPS(1);
4666 5088
4667 lock (m_host.TaskInventory) 5089 m_host.TaskInventory.LockItemsForRead(true);
5090 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4668 { 5091 {
4669 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5092 if (inv.Value.Name == name)
4670 { 5093 {
4671 if (inv.Value.Name == name) 5094 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4672 { 5095 {
4673 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5096 m_host.TaskInventory.LockItemsForRead(false);
4674 { 5097 return inv.Value.AssetID.ToString();
4675 return inv.Value.AssetID.ToString(); 5098 }
4676 } 5099 else
4677 else 5100 {
4678 { 5101 m_host.TaskInventory.LockItemsForRead(false);
4679 return UUID.Zero.ToString(); 5102 return UUID.Zero.ToString();
4680 }
4681 } 5103 }
4682 } 5104 }
4683 } 5105 }
5106 m_host.TaskInventory.LockItemsForRead(false);
4684 5107
4685 return UUID.Zero.ToString(); 5108 return UUID.Zero.ToString();
4686 } 5109 }
@@ -4833,14 +5256,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4833 { 5256 {
4834 m_host.AddScriptLPS(1); 5257 m_host.AddScriptLPS(1);
4835 5258
4836 if (src == null) 5259 return src.Length;
4837 {
4838 return 0;
4839 }
4840 else
4841 {
4842 return src.Length;
4843 }
4844 } 5260 }
4845 5261
4846 public LSL_Integer llList2Integer(LSL_List src, int index) 5262 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4886,7 +5302,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4886 else if (src.Data[index] is LSL_Float) 5302 else if (src.Data[index] is LSL_Float)
4887 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5303 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4888 else if (src.Data[index] is LSL_String) 5304 else if (src.Data[index] is LSL_String)
4889 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5305 {
5306 string str = ((LSL_String) src.Data[index]).m_string;
5307 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5308 if (m != Match.Empty)
5309 {
5310 str = m.Value;
5311 double d = 0.0;
5312 if (!Double.TryParse(str, out d))
5313 return 0.0;
5314
5315 return d;
5316 }
5317 return 0.0;
5318 }
4890 return Convert.ToDouble(src.Data[index]); 5319 return Convert.ToDouble(src.Data[index]);
4891 } 5320 }
4892 catch (FormatException) 5321 catch (FormatException)
@@ -5159,7 +5588,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5159 } 5588 }
5160 } 5589 }
5161 } 5590 }
5162 else { 5591 else
5592 {
5163 object[] array = new object[src.Length]; 5593 object[] array = new object[src.Length];
5164 Array.Copy(src.Data, 0, array, 0, src.Length); 5594 Array.Copy(src.Data, 0, array, 0, src.Length);
5165 result = new LSL_List(array); 5595 result = new LSL_List(array);
@@ -5266,7 +5696,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5266 public LSL_Integer llGetRegionAgentCount() 5696 public LSL_Integer llGetRegionAgentCount()
5267 { 5697 {
5268 m_host.AddScriptLPS(1); 5698 m_host.AddScriptLPS(1);
5269 return new LSL_Integer(World.GetRootAgentCount()); 5699
5700 int count = 0;
5701 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5702 count++;
5703 });
5704
5705 return new LSL_Integer(count);
5270 } 5706 }
5271 5707
5272 public LSL_Vector llGetRegionCorner() 5708 public LSL_Vector llGetRegionCorner()
@@ -5546,6 +5982,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5546 flags |= ScriptBaseClass.AGENT_SITTING; 5982 flags |= ScriptBaseClass.AGENT_SITTING;
5547 } 5983 }
5548 5984
5985 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
5986 {
5987 flags |= ScriptBaseClass.AGENT_MALE;
5988 }
5989
5549 return flags; 5990 return flags;
5550 } 5991 }
5551 5992
@@ -5608,10 +6049,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5608 m_host.AddScriptLPS(1); 6049 m_host.AddScriptLPS(1);
5609 6050
5610 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6051 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5611 6052 if (parts.Count > 0)
5612 foreach (var part in parts)
5613 { 6053 {
5614 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6054 try
6055 {
6056 parts[0].ParentGroup.areUpdatesSuspended = true;
6057 foreach (var part in parts)
6058 {
6059 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6060 }
6061 }
6062 finally
6063 {
6064 parts[0].ParentGroup.areUpdatesSuspended = false;
6065 }
5615 } 6066 }
5616 } 6067 }
5617 6068
@@ -5663,13 +6114,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5663 6114
5664 if (m_host.OwnerID == land.LandData.OwnerID) 6115 if (m_host.OwnerID == land.LandData.OwnerID)
5665 { 6116 {
5666 World.TeleportClientHome(agentID, presence.ControllingClient); 6117 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6118 presence.TeleportWithMomentum(pos, null);
6119 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5667 } 6120 }
5668 } 6121 }
5669 } 6122 }
5670 ScriptSleep(5000); 6123 ScriptSleep(5000);
5671 } 6124 }
5672 6125
6126 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6127 {
6128 return ParseString2List(str, separators, in_spacers, false);
6129 }
6130
5673 public LSL_Integer llOverMyLand(string id) 6131 public LSL_Integer llOverMyLand(string id)
5674 { 6132 {
5675 m_host.AddScriptLPS(1); 6133 m_host.AddScriptLPS(1);
@@ -5734,8 +6192,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5734 UUID agentId = new UUID(); 6192 UUID agentId = new UUID();
5735 if (!UUID.TryParse(agent, out agentId)) 6193 if (!UUID.TryParse(agent, out agentId))
5736 return new LSL_Integer(0); 6194 return new LSL_Integer(0);
6195 if (agentId == m_host.GroupID)
6196 return new LSL_Integer(1);
5737 ScenePresence presence = World.GetScenePresence(agentId); 6197 ScenePresence presence = World.GetScenePresence(agentId);
5738 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6198 if (presence == null || presence.IsChildAgent) // Return false for child agents
5739 return new LSL_Integer(0); 6199 return new LSL_Integer(0);
5740 IClientAPI client = presence.ControllingClient; 6200 IClientAPI client = presence.ControllingClient;
5741 if (m_host.GroupID == client.ActiveGroupId) 6201 if (m_host.GroupID == client.ActiveGroupId)
@@ -5870,7 +6330,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5870 return m_host.ParentGroup.AttachmentPoint; 6330 return m_host.ParentGroup.AttachmentPoint;
5871 } 6331 }
5872 6332
5873 public LSL_Integer llGetFreeMemory() 6333 public virtual LSL_Integer llGetFreeMemory()
5874 { 6334 {
5875 m_host.AddScriptLPS(1); 6335 m_host.AddScriptLPS(1);
5876 // Make scripts designed for LSO happy 6336 // Make scripts designed for LSO happy
@@ -5987,7 +6447,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5987 SetParticleSystem(m_host, rules); 6447 SetParticleSystem(m_host, rules);
5988 } 6448 }
5989 6449
5990 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6450 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6451 {
5991 6452
5992 6453
5993 if (rules.Length == 0) 6454 if (rules.Length == 0)
@@ -6181,14 +6642,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6181 6642
6182 protected UUID GetTaskInventoryItem(string name) 6643 protected UUID GetTaskInventoryItem(string name)
6183 { 6644 {
6184 lock (m_host.TaskInventory) 6645 m_host.TaskInventory.LockItemsForRead(true);
6646 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6185 { 6647 {
6186 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6648 if (inv.Value.Name == name)
6187 { 6649 {
6188 if (inv.Value.Name == name) 6650 m_host.TaskInventory.LockItemsForRead(false);
6189 return inv.Key; 6651 return inv.Key;
6190 } 6652 }
6191 } 6653 }
6654 m_host.TaskInventory.LockItemsForRead(false);
6192 6655
6193 return UUID.Zero; 6656 return UUID.Zero;
6194 } 6657 }
@@ -6226,16 +6689,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6226 if (folderID == UUID.Zero) 6689 if (folderID == UUID.Zero)
6227 return; 6690 return;
6228 6691
6229 byte[] bucket = new byte[17]; 6692 byte[] bucket = new byte[1];
6230 bucket[0] = (byte)AssetType.Folder; 6693 bucket[0] = (byte)AssetType.Folder;
6231 byte[] objBytes = folderID.GetBytes(); 6694 //byte[] objBytes = folderID.GetBytes();
6232 Array.Copy(objBytes, 0, bucket, 1, 16); 6695 //Array.Copy(objBytes, 0, bucket, 1, 16);
6233 6696
6234 GridInstantMessage msg = new GridInstantMessage(World, 6697 GridInstantMessage msg = new GridInstantMessage(World,
6235 m_host.UUID, m_host.Name+", an object owned by "+ 6698 m_host.OwnerID, m_host.Name, destID,
6236 resolveName(m_host.OwnerID)+",", destID, 6699 (byte)InstantMessageDialog.TaskInventoryOffered,
6237 (byte)InstantMessageDialog.InventoryOffered, 6700 false, category+". "+m_host.Name+" is located at "+
6238 false, category+"\n"+m_host.Name+" is located at "+
6239 World.RegionInfo.RegionName+" "+ 6701 World.RegionInfo.RegionName+" "+
6240 m_host.AbsolutePosition.ToString(), 6702 m_host.AbsolutePosition.ToString(),
6241 folderID, true, m_host.AbsolutePosition, 6703 folderID, true, m_host.AbsolutePosition,
@@ -6473,13 +6935,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6473 UUID av = new UUID(); 6935 UUID av = new UUID();
6474 if (!UUID.TryParse(avatar,out av)) 6936 if (!UUID.TryParse(avatar,out av))
6475 { 6937 {
6476 LSLError("First parameter to llDialog needs to be a key"); 6938 //LSLError("First parameter to llDialog needs to be a key");
6477 return; 6939 return;
6478 } 6940 }
6479 if (buttons.Length < 1) 6941 if (buttons.Length < 1)
6480 { 6942 {
6481 LSLError("No less than 1 button can be shown"); 6943 buttons.Add("OK");
6482 return;
6483 } 6944 }
6484 if (buttons.Length > 12) 6945 if (buttons.Length > 12)
6485 { 6946 {
@@ -6496,7 +6957,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6496 } 6957 }
6497 if (buttons.Data[i].ToString().Length > 24) 6958 if (buttons.Data[i].ToString().Length > 24)
6498 { 6959 {
6499 LSLError("button label cannot be longer than 24 characters"); 6960 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6500 return; 6961 return;
6501 } 6962 }
6502 buts[i] = buttons.Data[i].ToString(); 6963 buts[i] = buttons.Data[i].ToString();
@@ -6555,22 +7016,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6555 } 7016 }
6556 7017
6557 // copy the first script found with this inventory name 7018 // copy the first script found with this inventory name
6558 lock (m_host.TaskInventory) 7019 TaskInventoryItem scriptItem = null;
7020 m_host.TaskInventory.LockItemsForRead(true);
7021 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6559 { 7022 {
6560 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 7023 if (inv.Value.Name == name)
6561 { 7024 {
6562 if (inv.Value.Name == name) 7025 // make sure the object is a script
7026 if (10 == inv.Value.Type)
6563 { 7027 {
6564 // make sure the object is a script 7028 found = true;
6565 if (10 == inv.Value.Type) 7029 srcId = inv.Key;
6566 { 7030 scriptItem = inv.Value;
6567 found = true; 7031 break;
6568 srcId = inv.Key;
6569 break;
6570 }
6571 } 7032 }
6572 } 7033 }
6573 } 7034 }
7035 m_host.TaskInventory.LockItemsForRead(false);
6574 7036
6575 if (!found) 7037 if (!found)
6576 { 7038 {
@@ -6578,9 +7040,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6578 return; 7040 return;
6579 } 7041 }
6580 7042
6581 // the rest of the permission checks are done in RezScript, so check the pin there as well 7043 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6582 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7044 if (dest != null)
7045 {
7046 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7047 {
7048 // the rest of the permission checks are done in RezScript, so check the pin there as well
7049 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6583 7050
7051 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7052 m_host.Inventory.RemoveInventoryItem(srcId);
7053 }
7054 }
6584 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7055 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6585 ScriptSleep(3000); 7056 ScriptSleep(3000);
6586 } 7057 }
@@ -6643,19 +7114,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6643 public LSL_String llMD5String(string src, int nonce) 7114 public LSL_String llMD5String(string src, int nonce)
6644 { 7115 {
6645 m_host.AddScriptLPS(1); 7116 m_host.AddScriptLPS(1);
6646 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7117 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6647 } 7118 }
6648 7119
6649 public LSL_String llSHA1String(string src) 7120 public LSL_String llSHA1String(string src)
6650 { 7121 {
6651 m_host.AddScriptLPS(1); 7122 m_host.AddScriptLPS(1);
6652 return Util.SHA1Hash(src).ToLower(); 7123 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6653 } 7124 }
6654 7125
6655 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7126 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6656 { 7127 {
6657 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7128 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6658 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7129 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7130 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7131 return shapeBlock;
6659 7132
6660 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7133 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6661 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7134 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6760,6 +7233,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6760 // Prim type box, cylinder and prism. 7233 // Prim type box, cylinder and prism.
6761 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) 7234 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)
6762 { 7235 {
7236 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7237 return;
7238
6763 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7239 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6764 ObjectShapePacket.ObjectDataBlock shapeBlock; 7240 ObjectShapePacket.ObjectDataBlock shapeBlock;
6765 7241
@@ -6813,6 +7289,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6813 // Prim type sphere. 7289 // Prim type sphere.
6814 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7290 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6815 { 7291 {
7292 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7293 return;
7294
6816 ObjectShapePacket.ObjectDataBlock shapeBlock; 7295 ObjectShapePacket.ObjectDataBlock shapeBlock;
6817 7296
6818 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7297 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6854,6 +7333,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6854 // Prim type torus, tube and ring. 7333 // Prim type torus, tube and ring.
6855 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) 7334 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)
6856 { 7335 {
7336 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7337 return;
7338
6857 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7339 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6858 ObjectShapePacket.ObjectDataBlock shapeBlock; 7340 ObjectShapePacket.ObjectDataBlock shapeBlock;
6859 7341
@@ -6989,6 +7471,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6989 // Prim type sculpt. 7471 // Prim type sculpt.
6990 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7472 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
6991 { 7473 {
7474 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7475 return;
7476
6992 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7477 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
6993 UUID sculptId; 7478 UUID sculptId;
6994 7479
@@ -7013,7 +7498,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7013 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7498 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7014 { 7499 {
7015 // default 7500 // default
7016 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7501 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7017 } 7502 }
7018 7503
7019 part.Shape.SetSculptProperties((byte)type, sculptId); 7504 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7029,32 +7514,149 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7029 ScriptSleep(200); 7514 ScriptSleep(200);
7030 } 7515 }
7031 7516
7032 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7517 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7033 { 7518 {
7034 m_host.AddScriptLPS(1); 7519 m_host.AddScriptLPS(1);
7035 7520
7036 setLinkPrimParams(linknumber, rules); 7521 setLinkPrimParams(linknumber, rules);
7522 }
7037 7523
7038 ScriptSleep(200); 7524 private void setLinkPrimParams(int linknumber, LSL_List rules)
7525 {
7526 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7527 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7528 if (parts.Count>0)
7529 {
7530 try
7531 {
7532 parts[0].ParentGroup.areUpdatesSuspended = true;
7533 foreach (SceneObjectPart part in parts)
7534 SetPrimParams(part, rules);
7535 }
7536 finally
7537 {
7538 parts[0].ParentGroup.areUpdatesSuspended = false;
7539 }
7540 }
7541 if (avatars.Count > 0)
7542 {
7543 foreach (ScenePresence avatar in avatars)
7544 SetPrimParams(avatar, rules);
7545 }
7039 } 7546 }
7040 7547
7041 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7548 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7549 float material_density, float material_friction,
7550 float material_restitution, float material_gravity_modifier)
7042 { 7551 {
7043 m_host.AddScriptLPS(1); 7552 ExtraPhysicsData physdata = new ExtraPhysicsData();
7553 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7554 physdata.Density = part.Density;
7555 physdata.Friction = part.Friction;
7556 physdata.Bounce = part.Bounciness;
7557 physdata.GravitationModifier = part.GravityModifier;
7044 7558
7045 setLinkPrimParams(linknumber, rules); 7559 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7560 physdata.Density = material_density;
7561 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7562 physdata.Friction = material_friction;
7563 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7564 physdata.Bounce = material_restitution;
7565 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7566 physdata.GravitationModifier = material_gravity_modifier;
7567
7568 part.UpdateExtraPhysics(physdata);
7046 } 7569 }
7047 7570
7048 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7571 public void llSetPhysicsMaterial(int material_bits,
7572 float material_gravity_modifier, float material_restitution,
7573 float material_friction, float material_density)
7049 { 7574 {
7050 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7575 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7576 }
7051 7577
7052 foreach (SceneObjectPart part in parts) 7578 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7053 SetPrimParams(part, rules); 7579 {
7580 llSetLinkPrimitiveParamsFast(linknumber, rules);
7581 ScriptSleep(200);
7582 }
7583
7584 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7585 {
7586 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7587 //We only support PRIM_POSITION and PRIM_ROTATION
7588
7589 int idx = 0;
7590
7591 while (idx < rules.Length)
7592 {
7593 int code = rules.GetLSLIntegerItem(idx++);
7594
7595 int remain = rules.Length - idx;
7596
7597 switch (code)
7598 {
7599 case (int)ScriptBaseClass.PRIM_POSITION:
7600 {
7601 if (remain < 1)
7602 return;
7603 LSL_Vector v;
7604 v = rules.GetVector3Item(idx++);
7605
7606 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7607 if (part == null)
7608 break;
7609
7610 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7611 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7612 if (llGetLinkNumber() > 1)
7613 {
7614 localRot = llGetLocalRot();
7615 localPos = llGetLocalPos();
7616 }
7617
7618 v -= localPos;
7619 v /= localRot;
7620
7621 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
7622
7623 v = v + 2 * sitOffset;
7624
7625 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7626 av.SendAvatarDataToAllAgents();
7627
7628 }
7629 break;
7630
7631 case (int)ScriptBaseClass.PRIM_ROTATION:
7632 {
7633 if (remain < 1)
7634 return;
7635
7636 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7637 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7638 if (llGetLinkNumber() > 1)
7639 {
7640 localRot = llGetLocalRot();
7641 localPos = llGetLocalPos();
7642 }
7643
7644 LSL_Rotation r;
7645 r = rules.GetQuaternionItem(idx++);
7646 r = r * llGetRootRotation() / localRot;
7647 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7648 av.SendAvatarDataToAllAgents();
7649 }
7650 break;
7651 }
7652 }
7054 } 7653 }
7055 7654
7056 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7655 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7057 { 7656 {
7657 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7658 return;
7659
7058 int idx = 0; 7660 int idx = 0;
7059 7661
7060 bool positionChanged = false; 7662 bool positionChanged = false;
@@ -7376,6 +7978,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7376 part.ScriptSetPhysicsStatus(physics); 7978 part.ScriptSetPhysicsStatus(physics);
7377 break; 7979 break;
7378 7980
7981 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
7982 if (remain < 1)
7983 return;
7984
7985 int shape_type = rules.GetLSLIntegerItem(idx++);
7986
7987 ExtraPhysicsData physdata = new ExtraPhysicsData();
7988 physdata.Density = part.Density;
7989 physdata.Bounce = part.Bounciness;
7990 physdata.GravitationModifier = part.GravityModifier;
7991 physdata.PhysShapeType = (PhysShapeType)shape_type;
7992
7993 part.UpdateExtraPhysics(physdata);
7994
7995 break;
7996
7997 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
7998 if (remain < 5)
7999 return;
8000
8001 int material_bits = rules.GetLSLIntegerItem(idx++);
8002 float material_density = (float)rules.GetLSLFloatItem(idx++);
8003 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8004 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8005 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8006
8007 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8008
8009 break;
8010
7379 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8011 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7380 if (remain < 1) 8012 if (remain < 1)
7381 return; 8013 return;
@@ -7449,7 +8081,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7449 if (part.ParentGroup.RootPart == part) 8081 if (part.ParentGroup.RootPart == part)
7450 { 8082 {
7451 SceneObjectGroup parent = part.ParentGroup; 8083 SceneObjectGroup parent = part.ParentGroup;
7452 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8084 Util.FireAndForget(delegate(object x) {
8085 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8086 });
7453 } 8087 }
7454 else 8088 else
7455 { 8089 {
@@ -7460,6 +8094,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7460 } 8094 }
7461 } 8095 }
7462 } 8096 }
8097
8098 if (positionChanged)
8099 {
8100 if (part.ParentGroup.RootPart == part)
8101 {
8102 SceneObjectGroup parent = part.ParentGroup;
8103 Util.FireAndForget(delegate(object x) {
8104 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8105 });
8106 }
8107 else
8108 {
8109 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8110 SceneObjectGroup parent = part.ParentGroup;
8111 parent.HasGroupChanged = true;
8112 parent.ScheduleGroupForTerseUpdate();
8113 }
8114 }
7463 } 8115 }
7464 8116
7465 public LSL_String llStringToBase64(string str) 8117 public LSL_String llStringToBase64(string str)
@@ -7620,13 +8272,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7620 public LSL_Integer llGetNumberOfPrims() 8272 public LSL_Integer llGetNumberOfPrims()
7621 { 8273 {
7622 m_host.AddScriptLPS(1); 8274 m_host.AddScriptLPS(1);
7623 int avatarCount = 0; 8275 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7624 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8276
7625 {
7626 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
7627 avatarCount++;
7628 });
7629
7630 return m_host.ParentGroup.PrimCount + avatarCount; 8277 return m_host.ParentGroup.PrimCount + avatarCount;
7631 } 8278 }
7632 8279
@@ -7642,55 +8289,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7642 m_host.AddScriptLPS(1); 8289 m_host.AddScriptLPS(1);
7643 UUID objID = UUID.Zero; 8290 UUID objID = UUID.Zero;
7644 LSL_List result = new LSL_List(); 8291 LSL_List result = new LSL_List();
8292
8293 // If the ID is not valid, return null result
7645 if (!UUID.TryParse(obj, out objID)) 8294 if (!UUID.TryParse(obj, out objID))
7646 { 8295 {
7647 result.Add(new LSL_Vector()); 8296 result.Add(new LSL_Vector());
7648 result.Add(new LSL_Vector()); 8297 result.Add(new LSL_Vector());
7649 return result; 8298 return result;
7650 } 8299 }
8300
8301 // Check if this is an attached prim. If so, replace
8302 // the UUID with the avatar UUID and report it's bounding box
8303 SceneObjectPart part = World.GetSceneObjectPart(objID);
8304 if (part != null && part.ParentGroup.IsAttachment)
8305 objID = part.ParentGroup.AttachedAvatar;
8306
8307 // Find out if this is an avatar ID. If so, return it's box
7651 ScenePresence presence = World.GetScenePresence(objID); 8308 ScenePresence presence = World.GetScenePresence(objID);
7652 if (presence != null) 8309 if (presence != null)
7653 { 8310 {
7654 if (presence.ParentID == 0) // not sat on an object 8311 // As per LSL Wiki, there is no difference between sitting
8312 // and standing avatar since server 1.36
8313 LSL_Vector lower;
8314 LSL_Vector upper;
8315 if (presence.Animator.Animations.DefaultAnimation.AnimID
8316 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7655 { 8317 {
7656 LSL_Vector lower; 8318 // This is for ground sitting avatars
7657 LSL_Vector upper; 8319 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7658 if (presence.Animator.Animations.DefaultAnimation.AnimID 8320 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7659 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8321 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7660 {
7661 // This is for ground sitting avatars
7662 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7663 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7664 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7665 }
7666 else
7667 {
7668 // This is for standing/flying avatars
7669 float height = presence.Appearance.AvatarHeight / 2.0f;
7670 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7671 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7672 }
7673 result.Add(lower);
7674 result.Add(upper);
7675 return result;
7676 } 8322 }
7677 else 8323 else
7678 { 8324 {
7679 // sitting on an object so we need the bounding box of that 8325 // This is for standing/flying avatars
7680 // which should include the avatar so set the UUID to the 8326 float height = presence.Appearance.AvatarHeight / 2.0f;
7681 // UUID of the object the avatar is sat on and allow it to fall through 8327 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7682 // to processing an object 8328 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7683 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7684 objID = p.UUID;
7685 } 8329 }
8330
8331 // Adjust to the documented error offsets (see LSL Wiki)
8332 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8333 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8334
8335 if (lower.x > upper.x)
8336 lower.x = upper.x;
8337 if (lower.y > upper.y)
8338 lower.y = upper.y;
8339 if (lower.z > upper.z)
8340 lower.z = upper.z;
8341
8342 result.Add(lower);
8343 result.Add(upper);
8344 return result;
7686 } 8345 }
7687 SceneObjectPart part = World.GetSceneObjectPart(objID); 8346
8347 part = World.GetSceneObjectPart(objID);
7688 // Currently only works for single prims without a sitting avatar 8348 // Currently only works for single prims without a sitting avatar
7689 if (part != null) 8349 if (part != null)
7690 { 8350 {
7691 Vector3 halfSize = part.Scale / 2.0f; 8351 float minX;
7692 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8352 float maxX;
7693 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8353 float minY;
8354 float maxY;
8355 float minZ;
8356 float maxZ;
8357
8358 // This BBox is in sim coordinates, with the offset being
8359 // a contained point.
8360 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8361 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8362
8363 minX -= offsets[0].X;
8364 maxX -= offsets[0].X;
8365 minY -= offsets[0].Y;
8366 maxY -= offsets[0].Y;
8367 minZ -= offsets[0].Z;
8368 maxZ -= offsets[0].Z;
8369
8370 LSL_Vector lower;
8371 LSL_Vector upper;
8372
8373 // Adjust to the documented error offsets (see LSL Wiki)
8374 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8375 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8376
8377 if (lower.x > upper.x)
8378 lower.x = upper.x;
8379 if (lower.y > upper.y)
8380 lower.y = upper.y;
8381 if (lower.z > upper.z)
8382 lower.z = upper.z;
8383
7694 result.Add(lower); 8384 result.Add(lower);
7695 result.Add(upper); 8385 result.Add(upper);
7696 return result; 8386 return result;
@@ -7770,13 +8460,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7770 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8460 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7771 part.AbsolutePosition.Y, 8461 part.AbsolutePosition.Y,
7772 part.AbsolutePosition.Z); 8462 part.AbsolutePosition.Z);
7773 // For some reason, the part.AbsolutePosition.* values do not change if the
7774 // linkset is rotated; they always reflect the child prim's world position
7775 // as though the linkset is unrotated. This is incompatible behavior with SL's
7776 // implementation, so will break scripts imported from there (not to mention it
7777 // makes it more difficult to determine a child prim's actual inworld position).
7778 if (part.ParentID != 0)
7779 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7780 res.Add(v); 8463 res.Add(v);
7781 break; 8464 break;
7782 8465
@@ -7947,56 +8630,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7947 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8630 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7948 if (remain < 1) 8631 if (remain < 1)
7949 return res; 8632 return res;
7950 8633 face = (int)rules.GetLSLIntegerItem(idx++);
7951 face=(int)rules.GetLSLIntegerItem(idx++);
7952 8634
7953 tex = part.Shape.Textures; 8635 tex = part.Shape.Textures;
8636 int shiny;
7954 if (face == ScriptBaseClass.ALL_SIDES) 8637 if (face == ScriptBaseClass.ALL_SIDES)
7955 { 8638 {
7956 for (face = 0; face < GetNumberOfSides(part); face++) 8639 for (face = 0; face < GetNumberOfSides(part); face++)
7957 { 8640 {
7958 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8641 Shininess shinyness = tex.GetFace((uint)face).Shiny;
7959 // Convert Shininess to PRIM_SHINY_* 8642 if (shinyness == Shininess.High)
7960 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8643 {
7961 // PRIM_BUMP_* 8644 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7962 res.Add(new LSL_Integer((int)texface.Bump)); 8645 }
8646 else if (shinyness == Shininess.Medium)
8647 {
8648 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8649 }
8650 else if (shinyness == Shininess.Low)
8651 {
8652 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8653 }
8654 else
8655 {
8656 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8657 }
8658 res.Add(new LSL_Integer(shiny));
8659 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7963 } 8660 }
7964 } 8661 }
7965 else 8662 else
7966 { 8663 {
7967 if (face >= 0 && face < GetNumberOfSides(part)) 8664 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8665 if (shinyness == Shininess.High)
7968 { 8666 {
7969 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8667 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7970 // Convert Shininess to PRIM_SHINY_* 8668 }
7971 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8669 else if (shinyness == Shininess.Medium)
7972 // PRIM_BUMP_* 8670 {
7973 res.Add(new LSL_Integer((int)texface.Bump)); 8671 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8672 }
8673 else if (shinyness == Shininess.Low)
8674 {
8675 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8676 }
8677 else
8678 {
8679 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
7974 } 8680 }
8681 res.Add(new LSL_Integer(shiny));
8682 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7975 } 8683 }
7976 break; 8684 break;
7977 8685
7978 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8686 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
7979 if (remain < 1) 8687 if (remain < 1)
7980 return res; 8688 return res;
7981 8689 face = (int)rules.GetLSLIntegerItem(idx++);
7982 face=(int)rules.GetLSLIntegerItem(idx++);
7983 8690
7984 tex = part.Shape.Textures; 8691 tex = part.Shape.Textures;
8692 int fullbright;
7985 if (face == ScriptBaseClass.ALL_SIDES) 8693 if (face == ScriptBaseClass.ALL_SIDES)
7986 { 8694 {
7987 for (face = 0; face < GetNumberOfSides(part); face++) 8695 for (face = 0; face < GetNumberOfSides(part); face++)
7988 { 8696 {
7989 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8697 if (tex.GetFace((uint)face).Fullbright == true)
7990 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8698 {
8699 fullbright = ScriptBaseClass.TRUE;
8700 }
8701 else
8702 {
8703 fullbright = ScriptBaseClass.FALSE;
8704 }
8705 res.Add(new LSL_Integer(fullbright));
7991 } 8706 }
7992 } 8707 }
7993 else 8708 else
7994 { 8709 {
7995 if (face >= 0 && face < GetNumberOfSides(part)) 8710 if (tex.GetFace((uint)face).Fullbright == true)
7996 { 8711 {
7997 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8712 fullbright = ScriptBaseClass.TRUE;
7998 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
7999 } 8713 }
8714 else
8715 {
8716 fullbright = ScriptBaseClass.FALSE;
8717 }
8718 res.Add(new LSL_Integer(fullbright));
8000 } 8719 }
8001 break; 8720 break;
8002 8721
@@ -8018,27 +8737,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8018 break; 8737 break;
8019 8738
8020 case (int)ScriptBaseClass.PRIM_TEXGEN: 8739 case (int)ScriptBaseClass.PRIM_TEXGEN:
8740 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8021 if (remain < 1) 8741 if (remain < 1)
8022 return res; 8742 return res;
8023 8743 face = (int)rules.GetLSLIntegerItem(idx++);
8024 face=(int)rules.GetLSLIntegerItem(idx++);
8025 8744
8026 tex = part.Shape.Textures; 8745 tex = part.Shape.Textures;
8027 if (face == ScriptBaseClass.ALL_SIDES) 8746 if (face == ScriptBaseClass.ALL_SIDES)
8028 { 8747 {
8029 for (face = 0; face < GetNumberOfSides(part); face++) 8748 for (face = 0; face < GetNumberOfSides(part); face++)
8030 { 8749 {
8031 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8750 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8032 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8751 {
8033 res.Add(new LSL_Integer((uint)texgen >> 1)); 8752 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8753 }
8754 else
8755 {
8756 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8757 }
8034 } 8758 }
8035 } 8759 }
8036 else 8760 else
8037 { 8761 {
8038 if (face >= 0 && face < GetNumberOfSides(part)) 8762 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8039 { 8763 {
8040 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8764 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8041 res.Add(new LSL_Integer((uint)texgen >> 1)); 8765 }
8766 else
8767 {
8768 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8042 } 8769 }
8043 } 8770 }
8044 break; 8771 break;
@@ -8061,28 +8788,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8061 case (int)ScriptBaseClass.PRIM_GLOW: 8788 case (int)ScriptBaseClass.PRIM_GLOW:
8062 if (remain < 1) 8789 if (remain < 1)
8063 return res; 8790 return res;
8064 8791 face = (int)rules.GetLSLIntegerItem(idx++);
8065 face=(int)rules.GetLSLIntegerItem(idx++);
8066 8792
8067 tex = part.Shape.Textures; 8793 tex = part.Shape.Textures;
8794 float primglow;
8068 if (face == ScriptBaseClass.ALL_SIDES) 8795 if (face == ScriptBaseClass.ALL_SIDES)
8069 { 8796 {
8070 for (face = 0; face < GetNumberOfSides(part); face++) 8797 for (face = 0; face < GetNumberOfSides(part); face++)
8071 { 8798 {
8072 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8799 primglow = tex.GetFace((uint)face).Glow;
8073 res.Add(new LSL_Float(texface.Glow)); 8800 res.Add(new LSL_Float(primglow));
8074 } 8801 }
8075 } 8802 }
8076 else 8803 else
8077 { 8804 {
8078 if (face >= 0 && face < GetNumberOfSides(part)) 8805 primglow = tex.GetFace((uint)face).Glow;
8079 { 8806 res.Add(new LSL_Float(primglow));
8080 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8081 res.Add(new LSL_Float(texface.Glow));
8082 }
8083 } 8807 }
8084 break; 8808 break;
8085
8086 case (int)ScriptBaseClass.PRIM_TEXT: 8809 case (int)ScriptBaseClass.PRIM_TEXT:
8087 Color4 textColor = part.GetTextColor(); 8810 Color4 textColor = part.GetTextColor();
8088 res.Add(new LSL_String(part.Text)); 8811 res.Add(new LSL_String(part.Text));
@@ -8694,8 +9417,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8694 // The function returns an ordered list 9417 // The function returns an ordered list
8695 // representing the tokens found in the supplied 9418 // representing the tokens found in the supplied
8696 // sources string. If two successive tokenizers 9419 // sources string. If two successive tokenizers
8697 // are encountered, then a NULL entry is added 9420 // are encountered, then a null-string entry is
8698 // to the list. 9421 // added to the list.
8699 // 9422 //
8700 // It is a precondition that the source and 9423 // It is a precondition that the source and
8701 // toekizer lisst are non-null. If they are null, 9424 // toekizer lisst are non-null. If they are null,
@@ -8703,7 +9426,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8703 // while their lengths are being determined. 9426 // while their lengths are being determined.
8704 // 9427 //
8705 // A small amount of working memoryis required 9428 // A small amount of working memoryis required
8706 // of approximately 8*#tokenizers. 9429 // of approximately 8*#tokenizers + 8*srcstrlen.
8707 // 9430 //
8708 // There are many ways in which this function 9431 // There are many ways in which this function
8709 // can be implemented, this implementation is 9432 // can be implemented, this implementation is
@@ -8719,155 +9442,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8719 // and eliminates redundant tokenizers as soon 9442 // and eliminates redundant tokenizers as soon
8720 // as is possible. 9443 // as is possible.
8721 // 9444 //
8722 // The implementation tries to avoid any copying 9445 // The implementation tries to minimize temporary
8723 // of arrays or other objects. 9446 // garbage generation.
8724 // </remarks> 9447 // </remarks>
8725 9448
8726 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9449 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8727 { 9450 {
8728 int beginning = 0; 9451 return ParseString2List(src, separators, spacers, true);
8729 int srclen = src.Length; 9452 }
8730 int seplen = separators.Length;
8731 object[] separray = separators.Data;
8732 int spclen = spacers.Length;
8733 object[] spcarray = spacers.Data;
8734 int mlen = seplen+spclen;
8735
8736 int[] offset = new int[mlen+1];
8737 bool[] active = new bool[mlen];
8738
8739 int best;
8740 int j;
8741
8742 // Initial capacity reduces resize cost
8743 9453
8744 LSL_List tokens = new LSL_List(); 9454 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9455 {
9456 int srclen = src.Length;
9457 int seplen = separators.Length;
9458 object[] separray = separators.Data;
9459 int spclen = spacers.Length;
9460 object[] spcarray = spacers.Data;
9461 int dellen = 0;
9462 string[] delarray = new string[seplen+spclen];
8745 9463
8746 // All entries are initially valid 9464 int outlen = 0;
9465 string[] outarray = new string[srclen*2+1];
8747 9466
8748 for (int i = 0; i < mlen; i++) 9467 int i, j;
8749 active[i] = true; 9468 string d;
8750 9469
8751 offset[mlen] = srclen; 9470 m_host.AddScriptLPS(1);
8752 9471
8753 while (beginning < srclen) 9472 /*
9473 * Convert separator and spacer lists to C# strings.
9474 * Also filter out null strings so we don't hang.
9475 */
9476 for (i = 0; i < seplen; i ++)
8754 { 9477 {
9478 d = separray[i].ToString();
9479 if (d.Length > 0)
9480 {
9481 delarray[dellen++] = d;
9482 }
9483 }
9484 seplen = dellen;
8755 9485
8756 best = mlen; // as bad as it gets 9486 for (i = 0; i < spclen; i ++)
9487 {
9488 d = spcarray[i].ToString();
9489 if (d.Length > 0)
9490 {
9491 delarray[dellen++] = d;
9492 }
9493 }
8757 9494
8758 // Scan for separators 9495 /*
9496 * Scan through source string from beginning to end.
9497 */
9498 for (i = 0;;)
9499 {
8759 9500
8760 for (j = 0; j < seplen; j++) 9501 /*
9502 * Find earliest delimeter in src starting at i (if any).
9503 */
9504 int earliestDel = -1;
9505 int earliestSrc = srclen;
9506 string earliestStr = null;
9507 for (j = 0; j < dellen; j ++)
8761 { 9508 {
8762 if (separray[j].ToString() == String.Empty) 9509 d = delarray[j];
8763 active[j] = false; 9510 if (d != null)
8764
8765 if (active[j])
8766 { 9511 {
8767 // scan all of the markers 9512 int index = src.IndexOf(d, i);
8768 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9513 if (index < 0)
8769 { 9514 {
8770 // not present at all 9515 delarray[j] = null; // delim nowhere in src, don't check it anymore
8771 active[j] = false;
8772 } 9516 }
8773 else 9517 else if (index < earliestSrc)
8774 { 9518 {
8775 // present and correct 9519 earliestSrc = index; // where delimeter starts in source string
8776 if (offset[j] < offset[best]) 9520 earliestDel = j; // where delimeter is in delarray[]
8777 { 9521 earliestStr = d; // the delimeter string from delarray[]
8778 // closest so far 9522 if (index == i) break; // can't do any better than found at beg of string
8779 best = j;
8780 if (offset[best] == beginning)
8781 break;
8782 }
8783 } 9523 }
8784 } 9524 }
8785 } 9525 }
8786 9526
8787 // Scan for spacers 9527 /*
8788 9528 * Output source string starting at i through start of earliest delimeter.
8789 if (offset[best] != beginning) 9529 */
9530 if (keepNulls || (earliestSrc > i))
8790 { 9531 {
8791 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9532 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8792 {
8793 if (spcarray[j-seplen].ToString() == String.Empty)
8794 active[j] = false;
8795
8796 if (active[j])
8797 {
8798 // scan all of the markers
8799 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8800 {
8801 // not present at all
8802 active[j] = false;
8803 }
8804 else
8805 {
8806 // present and correct
8807 if (offset[j] < offset[best])
8808 {
8809 // closest so far
8810 best = j;
8811 }
8812 }
8813 }
8814 }
8815 } 9533 }
8816 9534
8817 // This is the normal exit from the scanning loop 9535 /*
9536 * If no delimeter found at or after i, we're done scanning.
9537 */
9538 if (earliestDel < 0) break;
8818 9539
8819 if (best == mlen) 9540 /*
9541 * If delimeter was a spacer, output the spacer.
9542 */
9543 if (earliestDel >= seplen)
8820 { 9544 {
8821 // no markers were found on this pass 9545 outarray[outlen++] = earliestStr;
8822 // so we're pretty much done
8823 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8824 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8825 break;
8826 } 9546 }
8827 9547
8828 // Otherwise we just add the newly delimited token 9548 /*
8829 // and recalculate where the search should continue. 9549 * Look at rest of src string following delimeter.
8830 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9550 */
8831 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9551 i = earliestSrc + earliestStr.Length;
8832
8833 if (best < seplen)
8834 {
8835 beginning = offset[best] + (separray[best].ToString()).Length;
8836 }
8837 else
8838 {
8839 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8840 string str = spcarray[best - seplen].ToString();
8841 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8842 tokens.Add(new LSL_String(str));
8843 }
8844 } 9552 }
8845 9553
8846 // This an awkward an not very intuitive boundary case. If the 9554 /*
8847 // last substring is a tokenizer, then there is an implied trailing 9555 * Make up an exact-sized output array suitable for an LSL_List object.
8848 // null list entry. Hopefully the single comparison will not be too 9556 */
8849 // arduous. Alternatively the 'break' could be replced with a return 9557 object[] outlist = new object[outlen];
8850 // but that's shabby programming. 9558 for (i = 0; i < outlen; i ++)
8851
8852 if ((beginning == srclen) && (keepNulls))
8853 { 9559 {
8854 if (srclen != 0) 9560 outlist[i] = new LSL_String(outarray[i]);
8855 tokens.Add(new LSL_String(""));
8856 } 9561 }
8857 9562 return new LSL_List(outlist);
8858 return tokens;
8859 }
8860
8861 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8862 {
8863 m_host.AddScriptLPS(1);
8864 return this.ParseString(src, separators, spacers, false);
8865 }
8866
8867 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8868 {
8869 m_host.AddScriptLPS(1);
8870 return this.ParseString(src, separators, spacers, true);
8871 } 9563 }
8872 9564
8873 public LSL_Integer llGetObjectPermMask(int mask) 9565 public LSL_Integer llGetObjectPermMask(int mask)
@@ -8944,28 +9636,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8944 { 9636 {
8945 m_host.AddScriptLPS(1); 9637 m_host.AddScriptLPS(1);
8946 9638
8947 lock (m_host.TaskInventory) 9639 m_host.TaskInventory.LockItemsForRead(true);
9640 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8948 { 9641 {
8949 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9642 if (inv.Value.Name == item)
8950 { 9643 {
8951 if (inv.Value.Name == item) 9644 m_host.TaskInventory.LockItemsForRead(false);
9645 switch (mask)
8952 { 9646 {
8953 switch (mask) 9647 case 0:
8954 { 9648 return (int)inv.Value.BasePermissions;
8955 case 0: 9649 case 1:
8956 return (int)inv.Value.BasePermissions; 9650 return (int)inv.Value.CurrentPermissions;
8957 case 1: 9651 case 2:
8958 return (int)inv.Value.CurrentPermissions; 9652 return (int)inv.Value.GroupPermissions;
8959 case 2: 9653 case 3:
8960 return (int)inv.Value.GroupPermissions; 9654 return (int)inv.Value.EveryonePermissions;
8961 case 3: 9655 case 4:
8962 return (int)inv.Value.EveryonePermissions; 9656 return (int)inv.Value.NextPermissions;
8963 case 4:
8964 return (int)inv.Value.NextPermissions;
8965 }
8966 } 9657 }
8967 } 9658 }
8968 } 9659 }
9660 m_host.TaskInventory.LockItemsForRead(false);
8969 9661
8970 return -1; 9662 return -1;
8971 } 9663 }
@@ -9012,16 +9704,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9012 { 9704 {
9013 m_host.AddScriptLPS(1); 9705 m_host.AddScriptLPS(1);
9014 9706
9015 lock (m_host.TaskInventory) 9707 m_host.TaskInventory.LockItemsForRead(true);
9708 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9016 { 9709 {
9017 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9710 if (inv.Value.Name == item)
9018 { 9711 {
9019 if (inv.Value.Name == item) 9712 m_host.TaskInventory.LockItemsForRead(false);
9020 { 9713 return inv.Value.CreatorID.ToString();
9021 return inv.Value.CreatorID.ToString();
9022 }
9023 } 9714 }
9024 } 9715 }
9716 m_host.TaskInventory.LockItemsForRead(false);
9025 9717
9026 llSay(0, "No item name '" + item + "'"); 9718 llSay(0, "No item name '" + item + "'");
9027 9719
@@ -9147,9 +9839,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9147 { 9839 {
9148 try 9840 try
9149 { 9841 {
9842 /*
9150 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 9843 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
9151 if (obj != null) 9844 if (obj != null)
9152 return (double)obj.GetMass(); 9845 return (double)obj.GetMass();
9846 */
9847 // return total object mass
9848 SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
9849 if (obj != null)
9850 return obj.GetMass();
9851
9153 // the object is null so the key is for an avatar 9852 // the object is null so the key is for an avatar
9154 ScenePresence avatar = World.GetScenePresence(key); 9853 ScenePresence avatar = World.GetScenePresence(key);
9155 if (avatar != null) 9854 if (avatar != null)
@@ -9169,7 +9868,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9169 } 9868 }
9170 9869
9171 /// <summary> 9870 /// <summary>
9172 /// illListReplaceList removes the sub-list defined by the inclusive indices 9871 /// llListReplaceList removes the sub-list defined by the inclusive indices
9173 /// start and end and inserts the src list in its place. The inclusive 9872 /// start and end and inserts the src list in its place. The inclusive
9174 /// nature of the indices means that at least one element must be deleted 9873 /// nature of the indices means that at least one element must be deleted
9175 /// if the indices are within the bounds of the existing list. I.e. 2,2 9874 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9226,16 +9925,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9226 // based upon end. Note that if end exceeds the upper 9925 // based upon end. Note that if end exceeds the upper
9227 // bound in this case, the entire destination list 9926 // bound in this case, the entire destination list
9228 // is removed. 9927 // is removed.
9229 else 9928 else if (start == 0)
9230 { 9929 {
9231 if (end + 1 < dest.Length) 9930 if (end + 1 < dest.Length)
9232 {
9233 return src + dest.GetSublist(end + 1, -1); 9931 return src + dest.GetSublist(end + 1, -1);
9234 }
9235 else 9932 else
9236 {
9237 return src; 9933 return src;
9238 } 9934 }
9935 else // Start < 0
9936 {
9937 if (end + 1 < dest.Length)
9938 return dest.GetSublist(end + 1, -1);
9939 else
9940 return new LSL_List();
9239 } 9941 }
9240 } 9942 }
9241 // Finally, if start > end, we strip away a prefix and 9943 // Finally, if start > end, we strip away a prefix and
@@ -9286,17 +9988,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9286 int width = 0; 9988 int width = 0;
9287 int height = 0; 9989 int height = 0;
9288 9990
9289 ParcelMediaCommandEnum? commandToSend = null; 9991 uint commandToSend = 0;
9290 float time = 0.0f; // default is from start 9992 float time = 0.0f; // default is from start
9291 9993
9292 ScenePresence presence = null; 9994 ScenePresence presence = null;
9293 9995
9294 for (int i = 0; i < commandList.Data.Length; i++) 9996 for (int i = 0; i < commandList.Data.Length; i++)
9295 { 9997 {
9296 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 9998 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9297 switch (command) 9999 switch (command)
9298 { 10000 {
9299 case ParcelMediaCommandEnum.Agent: 10001 case (uint)ParcelMediaCommandEnum.Agent:
9300 // we send only to one agent 10002 // we send only to one agent
9301 if ((i + 1) < commandList.Length) 10003 if ((i + 1) < commandList.Length)
9302 { 10004 {
@@ -9313,25 +10015,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9313 } 10015 }
9314 break; 10016 break;
9315 10017
9316 case ParcelMediaCommandEnum.Loop: 10018 case (uint)ParcelMediaCommandEnum.Loop:
9317 loop = 1; 10019 loop = 1;
9318 commandToSend = command; 10020 commandToSend = command;
9319 update = true; //need to send the media update packet to set looping 10021 update = true; //need to send the media update packet to set looping
9320 break; 10022 break;
9321 10023
9322 case ParcelMediaCommandEnum.Play: 10024 case (uint)ParcelMediaCommandEnum.Play:
9323 loop = 0; 10025 loop = 0;
9324 commandToSend = command; 10026 commandToSend = command;
9325 update = true; //need to send the media update packet to make sure it doesn't loop 10027 update = true; //need to send the media update packet to make sure it doesn't loop
9326 break; 10028 break;
9327 10029
9328 case ParcelMediaCommandEnum.Pause: 10030 case (uint)ParcelMediaCommandEnum.Pause:
9329 case ParcelMediaCommandEnum.Stop: 10031 case (uint)ParcelMediaCommandEnum.Stop:
9330 case ParcelMediaCommandEnum.Unload: 10032 case (uint)ParcelMediaCommandEnum.Unload:
9331 commandToSend = command; 10033 commandToSend = command;
9332 break; 10034 break;
9333 10035
9334 case ParcelMediaCommandEnum.Url: 10036 case (uint)ParcelMediaCommandEnum.Url:
9335 if ((i + 1) < commandList.Length) 10037 if ((i + 1) < commandList.Length)
9336 { 10038 {
9337 if (commandList.Data[i + 1] is LSL_String) 10039 if (commandList.Data[i + 1] is LSL_String)
@@ -9344,7 +10046,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9344 } 10046 }
9345 break; 10047 break;
9346 10048
9347 case ParcelMediaCommandEnum.Texture: 10049 case (uint)ParcelMediaCommandEnum.Texture:
9348 if ((i + 1) < commandList.Length) 10050 if ((i + 1) < commandList.Length)
9349 { 10051 {
9350 if (commandList.Data[i + 1] is LSL_String) 10052 if (commandList.Data[i + 1] is LSL_String)
@@ -9357,7 +10059,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9357 } 10059 }
9358 break; 10060 break;
9359 10061
9360 case ParcelMediaCommandEnum.Time: 10062 case (uint)ParcelMediaCommandEnum.Time:
9361 if ((i + 1) < commandList.Length) 10063 if ((i + 1) < commandList.Length)
9362 { 10064 {
9363 if (commandList.Data[i + 1] is LSL_Float) 10065 if (commandList.Data[i + 1] is LSL_Float)
@@ -9369,7 +10071,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9369 } 10071 }
9370 break; 10072 break;
9371 10073
9372 case ParcelMediaCommandEnum.AutoAlign: 10074 case (uint)ParcelMediaCommandEnum.AutoAlign:
9373 if ((i + 1) < commandList.Length) 10075 if ((i + 1) < commandList.Length)
9374 { 10076 {
9375 if (commandList.Data[i + 1] is LSL_Integer) 10077 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9383,7 +10085,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9383 } 10085 }
9384 break; 10086 break;
9385 10087
9386 case ParcelMediaCommandEnum.Type: 10088 case (uint)ParcelMediaCommandEnum.Type:
9387 if ((i + 1) < commandList.Length) 10089 if ((i + 1) < commandList.Length)
9388 { 10090 {
9389 if (commandList.Data[i + 1] is LSL_String) 10091 if (commandList.Data[i + 1] is LSL_String)
@@ -9396,7 +10098,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9396 } 10098 }
9397 break; 10099 break;
9398 10100
9399 case ParcelMediaCommandEnum.Desc: 10101 case (uint)ParcelMediaCommandEnum.Desc:
9400 if ((i + 1) < commandList.Length) 10102 if ((i + 1) < commandList.Length)
9401 { 10103 {
9402 if (commandList.Data[i + 1] is LSL_String) 10104 if (commandList.Data[i + 1] is LSL_String)
@@ -9409,7 +10111,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9409 } 10111 }
9410 break; 10112 break;
9411 10113
9412 case ParcelMediaCommandEnum.Size: 10114 case (uint)ParcelMediaCommandEnum.Size:
9413 if ((i + 2) < commandList.Length) 10115 if ((i + 2) < commandList.Length)
9414 { 10116 {
9415 if (commandList.Data[i + 1] is LSL_Integer) 10117 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9479,7 +10181,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9479 } 10181 }
9480 } 10182 }
9481 10183
9482 if (commandToSend != null) 10184 if (commandToSend != 0)
9483 { 10185 {
9484 // the commandList contained a start/stop/... command, too 10186 // the commandList contained a start/stop/... command, too
9485 if (presence == null) 10187 if (presence == null)
@@ -9516,7 +10218,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9516 10218
9517 if (aList.Data[i] != null) 10219 if (aList.Data[i] != null)
9518 { 10220 {
9519 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10221 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9520 { 10222 {
9521 case ParcelMediaCommandEnum.Url: 10223 case ParcelMediaCommandEnum.Url:
9522 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10224 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9559,16 +10261,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9559 { 10261 {
9560 m_host.AddScriptLPS(1); 10262 m_host.AddScriptLPS(1);
9561 10263
9562 lock (m_host.TaskInventory) 10264 m_host.TaskInventory.LockItemsForRead(true);
10265 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9563 { 10266 {
9564 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10267 if (inv.Value.Name == name)
9565 { 10268 {
9566 if (inv.Value.Name == name) 10269 m_host.TaskInventory.LockItemsForRead(false);
9567 { 10270 return inv.Value.Type;
9568 return inv.Value.Type;
9569 }
9570 } 10271 }
9571 } 10272 }
10273 m_host.TaskInventory.LockItemsForRead(false);
9572 10274
9573 return -1; 10275 return -1;
9574 } 10276 }
@@ -9579,15 +10281,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9579 10281
9580 if (quick_pay_buttons.Data.Length < 4) 10282 if (quick_pay_buttons.Data.Length < 4)
9581 { 10283 {
9582 LSLError("List must have at least 4 elements"); 10284 int x;
9583 return; 10285 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10286 {
10287 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10288 }
9584 } 10289 }
9585 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10290 int[] nPrice = new int[5];
9586 10291 nPrice[0] = price;
9587 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10292 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9588 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10293 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9589 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10294 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9590 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10295 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10296 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9591 m_host.ParentGroup.HasGroupChanged = true; 10297 m_host.ParentGroup.HasGroupChanged = true;
9592 } 10298 }
9593 10299
@@ -9605,6 +10311,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9605 ShoutError("No permissions to track the camera"); 10311 ShoutError("No permissions to track the camera");
9606 return new LSL_Vector(); 10312 return new LSL_Vector();
9607 } 10313 }
10314 m_host.TaskInventory.LockItemsForRead(false);
9608 10315
9609 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10316 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9610 if (presence != null) 10317 if (presence != null)
@@ -9629,6 +10336,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9629 ShoutError("No permissions to track the camera"); 10336 ShoutError("No permissions to track the camera");
9630 return new LSL_Rotation(); 10337 return new LSL_Rotation();
9631 } 10338 }
10339 m_host.TaskInventory.LockItemsForRead(false);
9632 10340
9633 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10341 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9634 if (presence != null) 10342 if (presence != null)
@@ -9690,8 +10398,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9690 { 10398 {
9691 m_host.AddScriptLPS(1); 10399 m_host.AddScriptLPS(1);
9692 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0); 10400 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0);
9693 if (detectedParams == null) return; // only works on the first detected avatar 10401 if (detectedParams == null)
9694 10402 {
10403 if (m_host.ParentGroup.IsAttachment == true)
10404 {
10405 detectedParams = new DetectParams();
10406 detectedParams.Key = m_host.OwnerID;
10407 }
10408 else
10409 {
10410 return;
10411 }
10412 }
10413
9695 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10414 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9696 if (avatar != null) 10415 if (avatar != null)
9697 { 10416 {
@@ -9699,6 +10418,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9699 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10418 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9700 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10419 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9701 } 10420 }
10421
9702 ScriptSleep(1000); 10422 ScriptSleep(1000);
9703 } 10423 }
9704 10424
@@ -9824,12 +10544,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9824 10544
9825 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10545 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9826 object[] data = rules.Data; 10546 object[] data = rules.Data;
9827 for (int i = 0; i < data.Length; ++i) { 10547 for (int i = 0; i < data.Length; ++i)
10548 {
9828 int type = Convert.ToInt32(data[i++].ToString()); 10549 int type = Convert.ToInt32(data[i++].ToString());
9829 if (i >= data.Length) break; // odd number of entries => ignore the last 10550 if (i >= data.Length) break; // odd number of entries => ignore the last
9830 10551
9831 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10552 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9832 switch (type) { 10553 switch (type)
10554 {
9833 case ScriptBaseClass.CAMERA_FOCUS: 10555 case ScriptBaseClass.CAMERA_FOCUS:
9834 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10556 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9835 case ScriptBaseClass.CAMERA_POSITION: 10557 case ScriptBaseClass.CAMERA_POSITION:
@@ -9937,19 +10659,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9937 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10659 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
9938 { 10660 {
9939 m_host.AddScriptLPS(1); 10661 m_host.AddScriptLPS(1);
9940 string ret = String.Empty; 10662
9941 string src1 = llBase64ToString(str1); 10663 if (str1 == String.Empty)
9942 string src2 = llBase64ToString(str2); 10664 return String.Empty;
9943 int c = 0; 10665 if (str2 == String.Empty)
9944 for (int i = 0; i < src1.Length; i++) 10666 return str1;
10667
10668 int len = str2.Length;
10669 if ((len % 4) != 0) // LL is EVIL!!!!
10670 {
10671 while (str2.EndsWith("="))
10672 str2 = str2.Substring(0, str2.Length - 1);
10673
10674 len = str2.Length;
10675 int mod = len % 4;
10676
10677 if (mod == 1)
10678 str2 = str2.Substring(0, str2.Length - 1);
10679 else if (mod == 2)
10680 str2 += "==";
10681 else if (mod == 3)
10682 str2 += "=";
10683 }
10684
10685 byte[] data1;
10686 byte[] data2;
10687 try
10688 {
10689 data1 = Convert.FromBase64String(str1);
10690 data2 = Convert.FromBase64String(str2);
10691 }
10692 catch (Exception)
10693 {
10694 return new LSL_String(String.Empty);
10695 }
10696
10697 byte[] d2 = new Byte[data1.Length];
10698 int pos = 0;
10699
10700 if (data1.Length <= data2.Length)
10701 {
10702 Array.Copy(data2, 0, d2, 0, data1.Length);
10703 }
10704 else
9945 { 10705 {
9946 ret += (char) (src1[i] ^ src2[c]); 10706 while (pos < data1.Length)
10707 {
10708 len = data1.Length - pos;
10709 if (len > data2.Length)
10710 len = data2.Length;
9947 10711
9948 c++; 10712 Array.Copy(data2, 0, d2, pos, len);
9949 if (c >= src2.Length) 10713 pos += len;
9950 c = 0; 10714 }
9951 } 10715 }
9952 return llStringToBase64(ret); 10716
10717 for (pos = 0 ; pos < data1.Length ; pos++ )
10718 data1[pos] ^= d2[pos];
10719
10720 return Convert.ToBase64String(data1);
9953 } 10721 }
9954 10722
9955 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10723 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10006,12 +10774,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10006 Regex r = new Regex(authregex); 10774 Regex r = new Regex(authregex);
10007 int[] gnums = r.GetGroupNumbers(); 10775 int[] gnums = r.GetGroupNumbers();
10008 Match m = r.Match(url); 10776 Match m = r.Match(url);
10009 if (m.Success) { 10777 if (m.Success)
10010 for (int i = 1; i < gnums.Length; i++) { 10778 {
10779 for (int i = 1; i < gnums.Length; i++)
10780 {
10011 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10781 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10012 //CaptureCollection cc = g.Captures; 10782 //CaptureCollection cc = g.Captures;
10013 } 10783 }
10014 if (m.Groups.Count == 5) { 10784 if (m.Groups.Count == 5)
10785 {
10015 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10786 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10016 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10787 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10017 } 10788 }
@@ -10374,15 +11145,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10374 11145
10375 internal UUID ScriptByName(string name) 11146 internal UUID ScriptByName(string name)
10376 { 11147 {
10377 lock (m_host.TaskInventory) 11148 m_host.TaskInventory.LockItemsForRead(true);
11149
11150 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10378 { 11151 {
10379 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 11152 if (item.Type == 10 && item.Name == name)
10380 { 11153 {
10381 if (item.Type == 10 && item.Name == name) 11154 m_host.TaskInventory.LockItemsForRead(false);
10382 return item.ItemID; 11155 return item.ItemID;
10383 } 11156 }
10384 } 11157 }
10385 11158
11159 m_host.TaskInventory.LockItemsForRead(false);
11160
10386 return UUID.Zero; 11161 return UUID.Zero;
10387 } 11162 }
10388 11163
@@ -10423,6 +11198,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10423 { 11198 {
10424 m_host.AddScriptLPS(1); 11199 m_host.AddScriptLPS(1);
10425 11200
11201 //Clone is thread safe
10426 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11202 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10427 11203
10428 UUID assetID = UUID.Zero; 11204 UUID assetID = UUID.Zero;
@@ -10485,6 +11261,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10485 { 11261 {
10486 m_host.AddScriptLPS(1); 11262 m_host.AddScriptLPS(1);
10487 11263
11264 //Clone is thread safe
10488 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11265 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10489 11266
10490 UUID assetID = UUID.Zero; 11267 UUID assetID = UUID.Zero;
@@ -10565,15 +11342,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10565 return GetLinkPrimitiveParams(obj, rules); 11342 return GetLinkPrimitiveParams(obj, rules);
10566 } 11343 }
10567 11344
10568 public void print(string str) 11345 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10569 { 11346 {
10570 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11347 List<SceneObjectPart> parts = GetLinkParts(link);
10571 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_itemID, "OSSL"); 11348 if (parts.Count < 1)
10572 if (ossl != null) 11349 return 0;
10573 { 11350
10574 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11351 return GetNumberOfSides(parts[0]);
10575 m_log.Info("LSL print():" + str);
10576 }
10577 } 11352 }
10578 11353
10579 private string Name2Username(string name) 11354 private string Name2Username(string name)
@@ -10619,155 +11394,482 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10619 return rq.ToString(); 11394 return rq.ToString();
10620 } 11395 }
10621 11396
11397 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11398 {
11399 m_SayShoutCount = 0;
11400 }
11401
11402 private struct Tri
11403 {
11404 public Vector3 p1;
11405 public Vector3 p2;
11406 public Vector3 p3;
11407 }
11408
11409 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11410 {
11411 float height = avatar.Appearance.AvatarHeight;
11412 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11413 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11414
11415 if (point.X > b1.X && point.X < b2.X &&
11416 point.Y > b1.Y && point.Y < b2.Y &&
11417 point.Z > b1.Z && point.Z < b2.Z)
11418 return true;
11419 return false;
11420 }
11421
11422 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11423 {
11424 List<ContactResult> contacts = new List<ContactResult>();
11425
11426 Vector3 ab = rayEnd - rayStart;
11427
11428 World.ForEachScenePresence(delegate(ScenePresence sp)
11429 {
11430 Vector3 ac = sp.AbsolutePosition - rayStart;
11431 Vector3 bc = sp.AbsolutePosition - rayEnd;
11432
11433 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11434
11435 if (d > 1.5)
11436 return;
11437
11438 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11439
11440 if (d2 > 0)
11441 return;
11442
11443 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11444 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11445
11446 if (!InBoundingBox(sp, p))
11447 return;
11448
11449 ContactResult result = new ContactResult ();
11450 result.ConsumerID = sp.LocalId;
11451 result.Depth = Vector3.Distance(rayStart, p);
11452 result.Normal = Vector3.Zero;
11453 result.Pos = p;
11454
11455 contacts.Add(result);
11456 });
11457
11458 return contacts.ToArray();
11459 }
11460
11461 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11462 {
11463 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11464 List<ContactResult> contacts = new List<ContactResult>();
11465
11466 Vector3 ab = rayEnd - rayStart;
11467
11468 World.ForEachSOG(delegate(SceneObjectGroup group)
11469 {
11470 if (m_host.ParentGroup == group)
11471 return;
11472
11473 if (group.IsAttachment)
11474 return;
11475
11476 if (group.RootPart.PhysActor == null)
11477 {
11478 if (!includePhantom)
11479 return;
11480 }
11481 else
11482 {
11483 if (group.RootPart.PhysActor.IsPhysical)
11484 {
11485 if (!includePhysical)
11486 return;
11487 }
11488 else
11489 {
11490 if (!includeNonPhysical)
11491 return;
11492 }
11493 }
11494
11495 // Find the radius ouside of which we don't even need to hit test
11496 float minX;
11497 float maxX;
11498 float minY;
11499 float maxY;
11500 float minZ;
11501 float maxZ;
11502
11503 float radius = 0.0f;
11504
11505 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11506
11507 if (Math.Abs(minX) > radius)
11508 radius = Math.Abs(minX);
11509 if (Math.Abs(minY) > radius)
11510 radius = Math.Abs(minY);
11511 if (Math.Abs(minZ) > radius)
11512 radius = Math.Abs(minZ);
11513 if (Math.Abs(maxX) > radius)
11514 radius = Math.Abs(maxX);
11515 if (Math.Abs(maxY) > radius)
11516 radius = Math.Abs(maxY);
11517 if (Math.Abs(maxZ) > radius)
11518 radius = Math.Abs(maxZ);
11519
11520 Vector3 ac = group.AbsolutePosition - rayStart;
11521 Vector3 bc = group.AbsolutePosition - rayEnd;
11522
11523 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11524
11525 // Too far off ray, don't bother
11526 if (d > radius)
11527 return;
11528
11529 // Behind ray, drop
11530 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11531 if (d2 > 0)
11532 return;
11533
11534 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11535 // Miss.
11536 if (!intersection.HitTF)
11537 return;
11538
11539 ContactResult result = new ContactResult ();
11540 result.ConsumerID = group.LocalId;
11541 result.Depth = intersection.distance;
11542 result.Normal = intersection.normal;
11543 result.Pos = intersection.ipoint;
11544
11545 contacts.Add(result);
11546 });
11547
11548 return contacts.ToArray();
11549 }
11550
11551 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11552 {
11553 double[,] heightfield = World.Heightmap.GetDoubles();
11554 List<ContactResult> contacts = new List<ContactResult>();
11555
11556 double min = 2048.0;
11557 double max = 0.0;
11558
11559 // Find the min and max of the heightfield
11560 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11561 {
11562 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11563 {
11564 if (heightfield[x, y] > max)
11565 max = heightfield[x, y];
11566 if (heightfield[x, y] < min)
11567 min = heightfield[x, y];
11568 }
11569 }
11570
11571
11572 // A ray extends past rayEnd, but doesn't go back before
11573 // rayStart. If the start is above the highest point of the ground
11574 // and the ray goes up, we can't hit the ground. Ever.
11575 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11576 return null;
11577
11578 // Same for going down
11579 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11580 return null;
11581
11582 List<Tri> trilist = new List<Tri>();
11583
11584 // Create our triangle list
11585 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11586 {
11587 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11588 {
11589 Tri t1 = new Tri();
11590 Tri t2 = new Tri();
11591
11592 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11593 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11594 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11595 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11596
11597 t1.p1 = p1;
11598 t1.p2 = p2;
11599 t1.p3 = p3;
11600
11601 t2.p1 = p3;
11602 t2.p2 = p4;
11603 t2.p3 = p1;
11604
11605 trilist.Add(t1);
11606 trilist.Add(t2);
11607 }
11608 }
11609
11610 // Ray direction
11611 Vector3 rayDirection = rayEnd - rayStart;
11612
11613 foreach (Tri t in trilist)
11614 {
11615 // Compute triangle plane normal and edges
11616 Vector3 u = t.p2 - t.p1;
11617 Vector3 v = t.p3 - t.p1;
11618 Vector3 n = Vector3.Cross(u, v);
11619
11620 if (n == Vector3.Zero)
11621 continue;
11622
11623 Vector3 w0 = rayStart - t.p1;
11624 double a = -Vector3.Dot(n, w0);
11625 double b = Vector3.Dot(n, rayDirection);
11626
11627 // Not intersecting the plane, or in plane (same thing)
11628 // Ignoring this MAY cause the ground to not be detected
11629 // sometimes
11630 if (Math.Abs(b) < 0.000001)
11631 continue;
11632
11633 double r = a / b;
11634
11635 // ray points away from plane
11636 if (r < 0.0)
11637 continue;
11638
11639 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11640
11641 float uu = Vector3.Dot(u, u);
11642 float uv = Vector3.Dot(u, v);
11643 float vv = Vector3.Dot(v, v);
11644 Vector3 w = ip - t.p1;
11645 float wu = Vector3.Dot(w, u);
11646 float wv = Vector3.Dot(w, v);
11647 float d = uv * uv - uu * vv;
11648
11649 float cs = (uv * wv - vv * wu) / d;
11650 if (cs < 0 || cs > 1.0)
11651 continue;
11652 float ct = (uv * wu - uu * wv) / d;
11653 if (ct < 0 || (cs + ct) > 1.0)
11654 continue;
11655
11656 // Add contact point
11657 ContactResult result = new ContactResult ();
11658 result.ConsumerID = 0;
11659 result.Depth = Vector3.Distance(rayStart, ip);
11660 result.Normal = n;
11661 result.Pos = ip;
11662
11663 contacts.Add(result);
11664 }
11665
11666 if (contacts.Count == 0)
11667 return null;
11668
11669 contacts.Sort(delegate(ContactResult a, ContactResult b)
11670 {
11671 return (int)(a.Depth - b.Depth);
11672 });
11673
11674 return contacts[0];
11675 }
11676/*
11677 // not done:
11678 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
11679 {
11680 ContactResult[] contacts = null;
11681 World.ForEachSOG(delegate(SceneObjectGroup group)
11682 {
11683 if (m_host.ParentGroup == group)
11684 return;
11685
11686 if (group.IsAttachment)
11687 return;
11688
11689 if(group.RootPart.PhysActor != null)
11690 return;
11691
11692 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
11693 });
11694 return contacts;
11695 }
11696*/
11697
10622 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11698 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10623 { 11699 {
11700 LSL_List list = new LSL_List();
11701
10624 m_host.AddScriptLPS(1); 11702 m_host.AddScriptLPS(1);
10625 11703
10626 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11704 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10627 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11705 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10628 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11706 Vector3 dir = rayEnd - rayStart;
10629 11707
10630 int count = 0; 11708 float dist = Vector3.Mag(dir);
10631// int detectPhantom = 0; 11709
11710 int count = 1;
11711 bool detectPhantom = false;
10632 int dataFlags = 0; 11712 int dataFlags = 0;
10633 int rejectTypes = 0; 11713 int rejectTypes = 0;
10634 11714
10635 for (int i = 0; i < options.Length; i += 2) 11715 for (int i = 0; i < options.Length; i += 2)
10636 { 11716 {
10637 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11717 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10638 {
10639 count = options.GetLSLIntegerItem(i + 1); 11718 count = options.GetLSLIntegerItem(i + 1);
10640 } 11719 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10641// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11720 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10642// {
10643// detectPhantom = options.GetLSLIntegerItem(i + 1);
10644// }
10645 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11721 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10646 {
10647 dataFlags = options.GetLSLIntegerItem(i + 1); 11722 dataFlags = options.GetLSLIntegerItem(i + 1);
10648 }
10649 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11723 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10650 {
10651 rejectTypes = options.GetLSLIntegerItem(i + 1); 11724 rejectTypes = options.GetLSLIntegerItem(i + 1);
10652 }
10653 } 11725 }
10654 11726
10655 LSL_List list = new LSL_List(); 11727 if (count > 16)
10656 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11728 count = 16;
10657
10658 double distance = Util.GetDistanceTo(startvector, endvector);
10659
10660 if (distance == 0)
10661 distance = 0.001;
10662 11729
10663 Vector3 posToCheck = startvector; 11730 List<ContactResult> results = new List<ContactResult>();
10664 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10665 11731
10666 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11732 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10667 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11733 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10668 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11734 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10669 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11735 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10670 11736
10671 for (float i = 0; i <= distance; i += 0.1f) 11737
11738 if (World.SuportsRayCastFiltered())
10672 { 11739 {
10673 posToCheck = startvector + (dir * (i / (float)distance)); 11740 if (dist == 0)
11741 return list;
11742
11743 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
11744 if (checkTerrain)
11745 rayfilter |= RayFilterFlags.land;
11746// if (checkAgents)
11747// rayfilter |= RayFilterFlags.agent;
11748 if (checkPhysical)
11749 rayfilter |= RayFilterFlags.physical;
11750 if (checkNonPhysical)
11751 rayfilter |= RayFilterFlags.nonphysical;
11752 if (detectPhantom)
11753 rayfilter |= RayFilterFlags.LSLPhanton;
10674 11754
10675 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11755 Vector3 direction = dir * ( 1/dist);
11756
11757 if(rayfilter == 0)
10676 { 11758 {
10677 ContactResult result = new ContactResult(); 11759 list.Add(new LSL_Integer(0));
10678 result.ConsumerID = 0; 11760 return list;
10679 result.Depth = 0;
10680 result.Normal = Vector3.Zero;
10681 result.Pos = posToCheck;
10682 results.Add(result);
10683 checkTerrain = false;
10684 } 11761 }
10685 11762
10686 if (checkAgents) 11763 // get some more contacts to sort ???
11764 int physcount = 4 * count;
11765 if (physcount > 20)
11766 physcount = 20;
11767
11768 object physresults;
11769 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
11770
11771 if (physresults == null)
10687 { 11772 {
10688 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11773 list.Add(new LSL_Integer(-3)); // timeout error
10689 { 11774 return list;
10690 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X))
10691 {
10692 ContactResult result = new ContactResult ();
10693 result.ConsumerID = sp.LocalId;
10694 result.Depth = 0;
10695 result.Normal = Vector3.Zero;
10696 result.Pos = posToCheck;
10697 results.Add(result);
10698 }
10699 });
10700 } 11775 }
10701 }
10702 11776
10703 int refcount = 0; 11777 results = (List<ContactResult>)physresults;
10704 foreach (ContactResult result in results)
10705 {
10706 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND)
10707 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0)
10708 continue;
10709 11778
10710 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID); 11779 // for now physics doesn't detect sitted avatars so do it outside physics
11780 if (checkAgents)
11781 {
11782 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11783 foreach (ContactResult r in agentHits)
11784 results.Add(r);
11785 }
10711 11786
10712 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) 11787 // bug: will not detect phantom unless they are physical
10713 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents 11788 // don't use ObjectIntersection because its also bad
11789
11790 }
11791 else
11792 {
11793 if (checkTerrain)
11794 {
11795 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11796 if (groundContact != null)
11797 results.Add((ContactResult)groundContact);
11798 }
10714 11799
10715 if (entity == null) 11800 if (checkAgents)
10716 { 11801 {
10717 list.Add(UUID.Zero); 11802 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11803 foreach (ContactResult r in agentHits)
11804 results.Add(r);
11805 }
10718 11806
10719 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11807 if (checkPhysical || checkNonPhysical || detectPhantom)
10720 list.Add(0); 11808 {
11809 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
11810 foreach (ContactResult r in objectHits)
11811 results.Add(r);
11812 }
11813 }
10721 11814
10722 list.Add(result.Pos); 11815 results.Sort(delegate(ContactResult a, ContactResult b)
11816 {
11817 return a.Depth.CompareTo(b.Depth);
11818 });
11819
11820 int values = 0;
11821 SceneObjectGroup thisgrp = m_host.ParentGroup;
10723 11822
10724 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11823 foreach (ContactResult result in results)
10725 list.Add(result.Normal); 11824 {
11825 if (result.Depth > dist)
11826 continue;
10726 11827
10727 continue; //Can't find it, so add UUID.Zero 11828 // physics ray can return colisions with host prim
10728 } 11829 if (m_host.LocalId == result.ConsumerID)
11830 continue;
10729 11831
10730 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity && 11832 UUID itemID = UUID.Zero;
10731 ((ISceneChildEntity)intersection.obj).PhysActor == null) 11833 int linkNum = 0;
10732 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
10733 11834
10734 if (entity is SceneObjectPart) 11835 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
11836 // It's a prim!
11837 if (part != null)
10735 { 11838 {
10736 PhysicsActor pa = ((SceneObjectPart)entity).PhysActor; 11839 // dont detect members of same object ???
11840 if (part.ParentGroup == thisgrp)
11841 continue;
10737 11842
10738 if (pa != null && pa.IsPhysical) 11843 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10739 { 11844 itemID = part.ParentGroup.UUID;
10740 if (!checkPhysical)
10741 continue;
10742 }
10743 else 11845 else
10744 { 11846 itemID = part.UUID;
10745 if (!checkNonPhysical)
10746 continue;
10747 }
10748 }
10749 11847
10750 refcount++; 11848 linkNum = part.LinkNum;
10751 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11849 }
10752 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10753 else 11850 else
10754 list.Add(entity.UUID);
10755
10756 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10757 { 11851 {
10758 if (entity is SceneObjectPart) 11852 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10759 list.Add(((SceneObjectPart)entity).LinkNum); 11853 /// It it a boy? a girl?
10760 else 11854 if (sp != null)
10761 list.Add(0); 11855 itemID = sp.UUID;
10762 } 11856 }
10763 11857
10764 list.Add(result.Pos); 11858 list.Add(new LSL_String(itemID.ToString()));
11859 list.Add(new LSL_String(result.Pos.ToString()));
11860
11861 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
11862 list.Add(new LSL_Integer(linkNum));
10765 11863
10766 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11864 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10767 list.Add(result.Normal); 11865 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11866
11867 values++;
11868 if (values >= count)
11869 break;
10768 } 11870 }
10769 11871
10770 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11872 list.Add(new LSL_Integer(values));
10771 11873
10772 return list; 11874 return list;
10773 } 11875 }
@@ -10807,7 +11909,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10807 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 11909 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10808 if (!isAccount) return 0; 11910 if (!isAccount) return 0;
10809 if (estate.HasAccess(id)) return 1; 11911 if (estate.HasAccess(id)) return 1;
10810 if (estate.IsBanned(id)) 11912 if (estate.IsBanned(id, World.GetUserFlags(id)))
10811 estate.RemoveBan(id); 11913 estate.RemoveBan(id);
10812 estate.AddEstateUser(id); 11914 estate.AddEstateUser(id);
10813 break; 11915 break;
@@ -10826,14 +11928,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10826 break; 11928 break;
10827 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 11929 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10828 if (!isAccount) return 0; 11930 if (!isAccount) return 0;
10829 if (estate.IsBanned(id)) return 1; 11931 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10830 EstateBan ban = new EstateBan(); 11932 EstateBan ban = new EstateBan();
10831 ban.EstateID = estate.EstateID; 11933 ban.EstateID = estate.EstateID;
10832 ban.BannedUserID = id; 11934 ban.BannedUserID = id;
10833 estate.AddBan(ban); 11935 estate.AddBan(ban);
10834 break; 11936 break;
10835 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 11937 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10836 if (!isAccount || !estate.IsBanned(id)) return 0; 11938 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10837 estate.RemoveBan(id); 11939 estate.RemoveBan(id);
10838 break; 11940 break;
10839 default: return 0; 11941 default: return 0;
@@ -10862,7 +11964,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10862 return 16384; 11964 return 16384;
10863 } 11965 }
10864 11966
10865 public LSL_Integer llGetUsedMemory() 11967 public virtual LSL_Integer llGetUsedMemory()
10866 { 11968 {
10867 m_host.AddScriptLPS(1); 11969 m_host.AddScriptLPS(1);
10868 // The value returned for LSO scripts in SL 11970 // The value returned for LSO scripts in SL
@@ -10890,7 +11992,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10890 public void llSetSoundQueueing(int queue) 11992 public void llSetSoundQueueing(int queue)
10891 { 11993 {
10892 m_host.AddScriptLPS(1); 11994 m_host.AddScriptLPS(1);
10893 NotImplemented("llSetSoundQueueing");
10894 } 11995 }
10895 11996
10896 public void llCollisionSprite(string impact_sprite) 11997 public void llCollisionSprite(string impact_sprite)
@@ -10902,10 +12003,270 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10902 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12003 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10903 { 12004 {
10904 m_host.AddScriptLPS(1); 12005 m_host.AddScriptLPS(1);
10905 NotImplemented("llGodLikeRezObject"); 12006
12007 if (!World.Permissions.IsGod(m_host.OwnerID))
12008 NotImplemented("llGodLikeRezObject");
12009
12010 AssetBase rezAsset = World.AssetService.Get(inventory);
12011 if (rezAsset == null)
12012 {
12013 llSay(0, "Asset not found");
12014 return;
12015 }
12016
12017 SceneObjectGroup group = null;
12018
12019 try
12020 {
12021 string xmlData = Utils.BytesToString(rezAsset.Data);
12022 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12023 }
12024 catch
12025 {
12026 llSay(0, "Asset not found");
12027 return;
12028 }
12029
12030 if (group == null)
12031 {
12032 llSay(0, "Asset not found");
12033 return;
12034 }
12035
12036 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12037 group.RootPart.AttachOffset = group.AbsolutePosition;
12038
12039 group.ResetIDs();
12040
12041 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12042 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12043 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12044 group.ScheduleGroupForFullUpdate();
12045
12046 // objects rezzed with this method are die_at_edge by default.
12047 group.RootPart.SetDieAtEdge(true);
12048
12049 group.ResumeScripts();
12050
12051 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12052 "object_rez", new Object[] {
12053 new LSL_String(
12054 group.RootPart.UUID.ToString()) },
12055 new DetectParams[0]));
12056 }
12057
12058 public LSL_String llTransferLindenDollars(string destination, int amount)
12059 {
12060 UUID txn = UUID.Random();
12061
12062 Util.FireAndForget(delegate(object x)
12063 {
12064 int replycode = 0;
12065 string replydata = destination + "," + amount.ToString();
12066
12067 try
12068 {
12069 TaskInventoryItem item = GetSelfInventoryItem();
12070 if (item == null)
12071 {
12072 replydata = "SERVICE_ERROR";
12073 return;
12074 }
12075
12076 m_host.AddScriptLPS(1);
12077
12078 if (item.PermsGranter == UUID.Zero)
12079 {
12080 replydata = "MISSING_PERMISSION_DEBIT";
12081 return;
12082 }
12083
12084 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
12085 {
12086 replydata = "MISSING_PERMISSION_DEBIT";
12087 return;
12088 }
12089
12090 UUID toID = new UUID();
12091
12092 if (!UUID.TryParse(destination, out toID))
12093 {
12094 replydata = "INVALID_AGENT";
12095 return;
12096 }
12097
12098 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
12099
12100 if (money == null)
12101 {
12102 replydata = "TRANSFERS_DISABLED";
12103 return;
12104 }
12105
12106 bool result = money.ObjectGiveMoney(
12107 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
12108
12109 if (result)
12110 {
12111 replycode = 1;
12112 return;
12113 }
12114
12115 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
12116 }
12117 finally
12118 {
12119 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
12120 "transaction_result", new Object[] {
12121 new LSL_String(txn.ToString()),
12122 new LSL_Integer(replycode),
12123 new LSL_String(replydata) },
12124 new DetectParams[0]));
12125 }
12126 });
12127
12128 return txn.ToString();
10906 } 12129 }
10907 12130
10908 #endregion 12131 #endregion
12132
12133 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12134 {
12135 SceneObjectGroup group = m_host.ParentGroup;
12136
12137 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12138 return;
12139 if (group.IsAttachment)
12140 return;
12141
12142 if (frames.Data.Length > 0) // We are getting a new motion
12143 {
12144 if (group.RootPart.KeyframeMotion != null)
12145 group.RootPart.KeyframeMotion.Stop();
12146 group.RootPart.KeyframeMotion = null;
12147
12148 int idx = 0;
12149
12150 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12151 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12152
12153 while (idx < options.Data.Length)
12154 {
12155 int option = (int)options.GetLSLIntegerItem(idx++);
12156 int remain = options.Data.Length - idx;
12157
12158 switch (option)
12159 {
12160 case ScriptBaseClass.KFM_MODE:
12161 if (remain < 1)
12162 break;
12163 int modeval = (int)options.GetLSLIntegerItem(idx++);
12164 switch(modeval)
12165 {
12166 case ScriptBaseClass.KFM_FORWARD:
12167 mode = KeyframeMotion.PlayMode.Forward;
12168 break;
12169 case ScriptBaseClass.KFM_REVERSE:
12170 mode = KeyframeMotion.PlayMode.Reverse;
12171 break;
12172 case ScriptBaseClass.KFM_LOOP:
12173 mode = KeyframeMotion.PlayMode.Loop;
12174 break;
12175 case ScriptBaseClass.KFM_PING_PONG:
12176 mode = KeyframeMotion.PlayMode.PingPong;
12177 break;
12178 }
12179 break;
12180 case ScriptBaseClass.KFM_DATA:
12181 if (remain < 1)
12182 break;
12183 int dataval = (int)options.GetLSLIntegerItem(idx++);
12184 data = (KeyframeMotion.DataFormat)dataval;
12185 break;
12186 }
12187 }
12188
12189 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12190
12191 idx = 0;
12192
12193 int elemLength = 2;
12194 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12195 elemLength = 3;
12196
12197 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12198 while (idx < frames.Data.Length)
12199 {
12200 int remain = frames.Data.Length - idx;
12201
12202 if (remain < elemLength)
12203 break;
12204
12205 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12206 frame.Position = null;
12207 frame.Rotation = null;
12208
12209 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12210 {
12211 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12212 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12213 }
12214 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12215 {
12216 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12217 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12218 }
12219
12220 float tempf = (float)frames.GetLSLFloatItem(idx++);
12221 frame.TimeMS = (int)(tempf * 1000.0f);
12222
12223 keyframes.Add(frame);
12224 }
12225
12226 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12227 group.RootPart.KeyframeMotion.Start();
12228 }
12229 else
12230 {
12231 if (group.RootPart.KeyframeMotion == null)
12232 return;
12233
12234 if (options.Data.Length == 0)
12235 {
12236 group.RootPart.KeyframeMotion.Stop();
12237 return;
12238 }
12239
12240 int code = (int)options.GetLSLIntegerItem(0);
12241
12242 int idx = 0;
12243
12244 while (idx < options.Data.Length)
12245 {
12246 int option = (int)options.GetLSLIntegerItem(idx++);
12247 int remain = options.Data.Length - idx;
12248
12249 switch (option)
12250 {
12251 case ScriptBaseClass.KFM_COMMAND:
12252 int cmd = (int)options.GetLSLIntegerItem(idx++);
12253 switch (cmd)
12254 {
12255 case ScriptBaseClass.KFM_CMD_PLAY:
12256 group.RootPart.KeyframeMotion.Start();
12257 break;
12258 case ScriptBaseClass.KFM_CMD_STOP:
12259 group.RootPart.KeyframeMotion.Stop();
12260 break;
12261 case ScriptBaseClass.KFM_CMD_PAUSE:
12262 group.RootPart.KeyframeMotion.Pause();
12263 break;
12264 }
12265 break;
12266 }
12267 }
12268 }
12269 }
10909 } 12270 }
10910 12271
10911 public class NotecardCache 12272 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 0d4ea19..60568a8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -137,6 +137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
137 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow; 137 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow;
138 internal float m_ScriptDelayFactor = 1.0f; 138 internal float m_ScriptDelayFactor = 1.0f;
139 internal float m_ScriptDistanceFactor = 1.0f; 139 internal float m_ScriptDistanceFactor = 1.0f;
140 internal bool m_debuggerSafe = false;
140 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); 141 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
141 142
142 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 143 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
@@ -145,6 +146,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
145 m_host = host; 146 m_host = host;
146 m_localID = localID; 147 m_localID = localID;
147 m_itemID = itemID; 148 m_itemID = itemID;
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>
@@ -927,18 +936,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
927 if (target != null) 936 if (target != null)
928 { 937 {
929 UUID animID=UUID.Zero; 938 UUID animID=UUID.Zero;
930 lock (m_host.TaskInventory) 939 m_host.TaskInventory.LockItemsForRead(true);
940 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
931 { 941 {
932 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 942 if (inv.Value.Name == animation)
933 { 943 {
934 if (inv.Value.Name == animation) 944 if (inv.Value.Type == (int)AssetType.Animation)
935 { 945 animID = inv.Value.AssetID;
936 if (inv.Value.Type == (int)AssetType.Animation) 946 continue;
937 animID = inv.Value.AssetID;
938 continue;
939 }
940 } 947 }
941 } 948 }
949 m_host.TaskInventory.LockItemsForRead(false);
942 if (animID == UUID.Zero) 950 if (animID == UUID.Zero)
943 target.Animator.AddAnimation(animation, m_host.UUID); 951 target.Animator.AddAnimation(animation, m_host.UUID);
944 else 952 else
@@ -965,18 +973,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
965 if (target != null) 973 if (target != null)
966 { 974 {
967 UUID animID = UUID.Zero; 975 UUID animID = UUID.Zero;
968 lock (m_host.TaskInventory) 976 m_host.TaskInventory.LockItemsForRead(true);
977 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
969 { 978 {
970 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 979 if (inv.Value.Name == animation)
971 { 980 {
972 if (inv.Value.Name == animation) 981 if (inv.Value.Type == (int)AssetType.Animation)
973 { 982 animID = inv.Value.AssetID;
974 if (inv.Value.Type == (int)AssetType.Animation) 983 continue;
975 animID = inv.Value.AssetID;
976 continue;
977 }
978 } 984 }
979 } 985 }
986 m_host.TaskInventory.LockItemsForRead(false);
980 987
981 if (animID == UUID.Zero) 988 if (animID == UUID.Zero)
982 target.Animator.RemoveAnimation(animation); 989 target.Animator.RemoveAnimation(animation);
@@ -1797,6 +1804,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1797 1804
1798 if (!UUID.TryParse(notecardNameOrUuid, out assetID)) 1805 if (!UUID.TryParse(notecardNameOrUuid, out assetID))
1799 { 1806 {
1807 m_host.TaskInventory.LockItemsForRead(true);
1800 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1808 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1801 { 1809 {
1802 if (item.Type == 7 && item.Name == notecardNameOrUuid) 1810 if (item.Type == 7 && item.Name == notecardNameOrUuid)
@@ -1804,6 +1812,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1804 assetID = item.AssetID; 1812 assetID = item.AssetID;
1805 } 1813 }
1806 } 1814 }
1815 m_host.TaskInventory.LockItemsForRead(false);
1807 } 1816 }
1808 1817
1809 if (assetID == UUID.Zero) 1818 if (assetID == UUID.Zero)
@@ -2271,7 +2280,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2271 CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); 2280 CheckThreatLevel(ThreatLevel.High, "osNpcCreate");
2272 m_host.AddScriptLPS(1); 2281 m_host.AddScriptLPS(1);
2273 2282
2274 return NpcCreate(firstname, lastname, position, notecard, false, false); 2283 return NpcCreate(firstname, lastname, position, notecard, true, false);
2275 } 2284 }
2276 2285
2277 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options) 2286 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options)
@@ -2282,24 +2291,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2282 return NpcCreate( 2291 return NpcCreate(
2283 firstname, lastname, position, notecard, 2292 firstname, lastname, position, notecard,
2284 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0, 2293 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0,
2285 (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) != 0); 2294 false);
2295// (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) != 0);
2286 } 2296 }
2287 2297
2288 private LSL_Key NpcCreate( 2298 private LSL_Key NpcCreate(
2289 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent) 2299 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent)
2290 { 2300 {
2301 if (!owned)
2302 OSSLError("Unowned NPCs are unsupported");
2303
2304 string groupTitle = String.Empty;
2305
2306 if (!World.Permissions.CanRezObject(1, m_host.OwnerID, new Vector3((float)position.x, (float)position.y, (float)position.z)))
2307 return new LSL_Key(UUID.Zero.ToString());
2308
2309 if (firstname != String.Empty || lastname != String.Empty)
2310 {
2311 if (firstname != "Shown outfit:")
2312 groupTitle = "- NPC -";
2313 }
2314
2291 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2315 INPCModule module = World.RequestModuleInterface<INPCModule>();
2292 if (module != null) 2316 if (module != null)
2293 { 2317 {
2294 AvatarAppearance appearance = null; 2318 AvatarAppearance appearance = null;
2295 2319
2296 UUID id; 2320// UUID id;
2297 if (UUID.TryParse(notecard, out id)) 2321// if (UUID.TryParse(notecard, out id))
2298 { 2322// {
2299 ScenePresence clonePresence = World.GetScenePresence(id); 2323// ScenePresence clonePresence = World.GetScenePresence(id);
2300 if (clonePresence != null) 2324// if (clonePresence != null)
2301 appearance = clonePresence.Appearance; 2325// appearance = clonePresence.Appearance;
2302 } 2326// }
2303 2327
2304 if (appearance == null) 2328 if (appearance == null)
2305 { 2329 {
@@ -2327,6 +2351,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2327 World, 2351 World,
2328 appearance); 2352 appearance);
2329 2353
2354 ScenePresence sp;
2355 if (World.TryGetScenePresence(x, out sp))
2356 {
2357 sp.Grouptitle = groupTitle;
2358 sp.SendAvatarDataToAllAgents();
2359 }
2330 return new LSL_Key(x.ToString()); 2360 return new LSL_Key(x.ToString());
2331 } 2361 }
2332 2362
@@ -2617,16 +2647,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2617 CheckThreatLevel(ThreatLevel.High, "osNpcRemove"); 2647 CheckThreatLevel(ThreatLevel.High, "osNpcRemove");
2618 m_host.AddScriptLPS(1); 2648 m_host.AddScriptLPS(1);
2619 2649
2620 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2650 ManualResetEvent ev = new ManualResetEvent(false);
2621 if (module != null)
2622 {
2623 UUID npcId = new UUID(npc.m_string);
2624 2651
2625 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2652 Util.FireAndForget(delegate(object x) {
2626 return; 2653 try
2654 {
2655 INPCModule module = World.RequestModuleInterface<INPCModule>();
2656 if (module != null)
2657 {
2658 UUID npcId = new UUID(npc.m_string);
2627 2659
2628 module.DeleteNPC(npcId, World); 2660 ILandObject l = World.LandChannel.GetLandObject(m_host.GroupPosition.X, m_host.GroupPosition.Y);
2629 } 2661 if (l == null || m_host.OwnerID != l.LandData.OwnerID)
2662 {
2663 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2664 return;
2665 }
2666
2667 module.DeleteNPC(npcId, World);
2668 }
2669 }
2670 finally
2671 {
2672 ev.Set();
2673 }
2674 });
2675 ev.WaitOne();
2630 } 2676 }
2631 2677
2632 public void osNpcPlayAnimation(LSL_Key npc, string animation) 2678 public void osNpcPlayAnimation(LSL_Key npc, string animation)
@@ -3160,4 +3206,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3160 ((LSL_Api)m_LSL_Api).DetachFromAvatar(); 3206 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3161 } 3207 }
3162 } 3208 }
3163} \ No newline at end of file 3209}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 1c272f8..1373971 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -222,7 +222,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
222 // Is the sensor type is AGENT and not SCRIPTED then include agents 222 // Is the sensor type is AGENT and not SCRIPTED then include agents
223 if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC)) != 0 && (ts.type & SCRIPTED) == 0) 223 if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC)) != 0 && (ts.type & SCRIPTED) == 0)
224 { 224 {
225 sensedEntities.AddRange(doAgentSensor(ts)); 225 sensedEntities.AddRange(doAgentSensor(ts));
226 } 226 }
227 227
228 // If SCRIPTED or PASSIVE or ACTIVE check objects 228 // If SCRIPTED or PASSIVE or ACTIVE check objects
@@ -319,13 +319,15 @@ 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.RotationOffset; 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, the sensor cone always orients with the 326 // In attachments, the sensor cone always orients with the
326 // avatar rotation. This may include a nonzero elevation if 327 // avatar rotation. This may include a nonzero elevation if
327 // in mouselook. 328 // in mouselook.
328 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 329 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
330 fromRegionPos = avatar.AbsolutePosition;
329 q = avatar.Rotation; 331 q = avatar.Rotation;
330 } 332 }
331 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 333 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
@@ -448,6 +450,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
448 // avatar rotation. This may include a nonzero elevation if 450 // avatar rotation. This may include a nonzero elevation if
449 // in mouselook. 451 // in mouselook.
450 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 452 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
453 if (avatar == null)
454 return sensedEntities;
455 fromRegionPos = avatar.AbsolutePosition;
451 q = avatar.Rotation; 456 q = avatar.Rotation;
452 } 457 }
453 458
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 69df392..eab6851 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -124,6 +124,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
124 LSL_Float llGetEnergy(); 124 LSL_Float llGetEnergy();
125 LSL_Vector llGetForce(); 125 LSL_Vector llGetForce();
126 LSL_Integer llGetFreeMemory(); 126 LSL_Integer llGetFreeMemory();
127 LSL_Integer llGetUsedMemory();
127 LSL_Integer llGetFreeURLs(); 128 LSL_Integer llGetFreeURLs();
128 LSL_Vector llGetGeometricCenter(); 129 LSL_Vector llGetGeometricCenter();
129 LSL_Float llGetGMTclock(); 130 LSL_Float llGetGMTclock();
@@ -147,6 +148,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
147 LSL_Vector llGetLocalPos(); 148 LSL_Vector llGetLocalPos();
148 LSL_Rotation llGetLocalRot(); 149 LSL_Rotation llGetLocalRot();
149 LSL_Float llGetMass(); 150 LSL_Float llGetMass();
151 LSL_Float llGetMassMKS();
150 LSL_Integer llGetMemoryLimit(); 152 LSL_Integer llGetMemoryLimit();
151 void llGetNextEmail(string address, string subject); 153 void llGetNextEmail(string address, string subject);
152 LSL_String llGetNotecardLine(string name, int line); 154 LSL_String llGetNotecardLine(string name, int line);
@@ -200,12 +202,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
200 LSL_String llGetTimestamp(); 202 LSL_String llGetTimestamp();
201 LSL_Vector llGetTorque(); 203 LSL_Vector llGetTorque();
202 LSL_Integer llGetUnixTime(); 204 LSL_Integer llGetUnixTime();
203 LSL_Integer llGetUsedMemory();
204 LSL_Vector llGetVel(); 205 LSL_Vector llGetVel();
205 LSL_Float llGetWallclock(); 206 LSL_Float llGetWallclock();
206 void llGiveInventory(string destination, string inventory); 207 void llGiveInventory(string destination, string inventory);
207 void llGiveInventoryList(string destination, string category, LSL_List inventory); 208 void llGiveInventoryList(string destination, string category, LSL_List inventory);
208 LSL_Integer llGiveMoney(string destination, int amount); 209 LSL_Integer llGiveMoney(string destination, int amount);
210 LSL_String llTransferLindenDollars(string destination, int amount);
209 void llGodLikeRezObject(string inventory, LSL_Vector pos); 211 void llGodLikeRezObject(string inventory, LSL_Vector pos);
210 LSL_Float llGround(LSL_Vector offset); 212 LSL_Float llGround(LSL_Vector offset);
211 LSL_Vector llGroundContour(LSL_Vector offset); 213 LSL_Vector llGroundContour(LSL_Vector offset);
@@ -353,6 +355,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
353 void llSetParcelMusicURL(string url); 355 void llSetParcelMusicURL(string url);
354 void llSetPayPrice(int price, LSL_List quick_pay_buttons); 356 void llSetPayPrice(int price, LSL_List quick_pay_buttons);
355 void llSetPos(LSL_Vector pos); 357 void llSetPos(LSL_Vector pos);
358 LSL_Integer llSetRegionPos(LSL_Vector pos);
356 LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules); 359 LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules);
357 void llSetPrimitiveParams(LSL_List rules); 360 void llSetPrimitiveParams(LSL_List rules);
358 void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules); 361 void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules);
@@ -401,6 +404,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
401 void llTargetOmega(LSL_Vector axis, double spinrate, double gain); 404 void llTargetOmega(LSL_Vector axis, double spinrate, double gain);
402 void llTargetRemove(int number); 405 void llTargetRemove(int number);
403 void llTeleportAgentHome(string agent); 406 void llTeleportAgentHome(string agent);
407 void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt);
404 void llTextBox(string avatar, string message, int chat_channel); 408 void llTextBox(string avatar, string message, int chat_channel);
405 LSL_String llToLower(string source); 409 LSL_String llToLower(string source);
406 LSL_String llToUpper(string source); 410 LSL_String llToUpper(string source);
@@ -417,9 +421,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
417 LSL_Vector llWind(LSL_Vector offset); 421 LSL_Vector llWind(LSL_Vector offset);
418 LSL_String llXorBase64Strings(string str1, string str2); 422 LSL_String llXorBase64Strings(string str1, string str2);
419 LSL_String llXorBase64StringsCorrect(string str1, string str2); 423 LSL_String llXorBase64StringsCorrect(string str1, string str2);
420 void print(string str); 424 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link);
425 void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density);
421 426
422 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 427 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
423 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 428 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
429 void llSetKeyframedMotion(LSL_List frames, LSL_List options);
424 } 430 }
425} 431}
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 fd7c41e..23b4336 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;
@@ -581,6 +583,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
581 public const int PRIM_MEDIA_PERM_OWNER = 1; 583 public const int PRIM_MEDIA_PERM_OWNER = 1;
582 public const int PRIM_MEDIA_PERM_GROUP = 2; 584 public const int PRIM_MEDIA_PERM_GROUP = 2;
583 public const int PRIM_MEDIA_PERM_ANYONE = 4; 585 public const int PRIM_MEDIA_PERM_ANYONE = 4;
586
587 public const int PRIM_PHYSICS_SHAPE_TYPE = 30;
588 public const int PRIM_PHYSICS_SHAPE_PRIM = 0;
589 public const int PRIM_PHYSICS_SHAPE_CONVEX = 2;
590 public const int PRIM_PHYSICS_SHAPE_NONE = 1;
591
592 public const int PRIM_PHYSICS_MATERIAL = 31;
593 public const int DENSITY = 1;
594 public const int FRICTION = 2;
595 public const int RESTITUTION = 4;
596 public const int GRAVITY_MULTIPLIER = 8;
584 597
585 // extra constants for llSetPrimMediaParams 598 // extra constants for llSetPrimMediaParams
586 public static readonly LSLInteger LSL_STATUS_OK = new LSLInteger(0); 599 public static readonly LSLInteger LSL_STATUS_OK = new LSLInteger(0);
@@ -653,5 +666,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
653 public static readonly LSLInteger RCERR_UNKNOWN = -1; 666 public static readonly LSLInteger RCERR_UNKNOWN = -1;
654 public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2; 667 public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2;
655 public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3; 668 public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3;
669
670 public const int KFM_MODE = 1;
671 public const int KFM_LOOP = 1;
672 public const int KFM_REVERSE = 3;
673 public const int KFM_FORWARD = 0;
674 public const int KFM_PING_PONG = 2;
675 public const int KFM_DATA = 2;
676 public const int KFM_TRANSLATION = 2;
677 public const int KFM_ROTATION = 1;
678 public const int KFM_COMMAND = 0;
679 public const int KFM_CMD_PLAY = 0;
680 public const int KFM_CMD_STOP = 1;
681 public const int KFM_CMD_PAUSE = 2;
656 } 682 }
657} 683}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 3c2f7bd..9446099 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();
@@ -464,6 +471,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
464 return m_LSL_Functions.llGetFreeMemory(); 471 return m_LSL_Functions.llGetFreeMemory();
465 } 472 }
466 473
474 public LSL_Integer llGetUsedMemory()
475 {
476 return m_LSL_Functions.llGetUsedMemory();
477 }
478
467 public LSL_Integer llGetFreeURLs() 479 public LSL_Integer llGetFreeURLs()
468 { 480 {
469 return m_LSL_Functions.llGetFreeURLs(); 481 return m_LSL_Functions.llGetFreeURLs();
@@ -569,6 +581,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
569 return m_LSL_Functions.llGetMass(); 581 return m_LSL_Functions.llGetMass();
570 } 582 }
571 583
584 public LSL_Float llGetMassMKS()
585 {
586 return m_LSL_Functions.llGetMassMKS();
587 }
588
572 public LSL_Integer llGetMemoryLimit() 589 public LSL_Integer llGetMemoryLimit()
573 { 590 {
574 return m_LSL_Functions.llGetMemoryLimit(); 591 return m_LSL_Functions.llGetMemoryLimit();
@@ -834,11 +851,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
834 return m_LSL_Functions.llGetUnixTime(); 851 return m_LSL_Functions.llGetUnixTime();
835 } 852 }
836 853
837 public LSL_Integer llGetUsedMemory()
838 {
839 return m_LSL_Functions.llGetUsedMemory();
840 }
841
842 public LSL_Vector llGetVel() 854 public LSL_Vector llGetVel()
843 { 855 {
844 return m_LSL_Functions.llGetVel(); 856 return m_LSL_Functions.llGetVel();
@@ -864,6 +876,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
864 return m_LSL_Functions.llGiveMoney(destination, amount); 876 return m_LSL_Functions.llGiveMoney(destination, amount);
865 } 877 }
866 878
879 public LSL_String llTransferLindenDollars(string destination, int amount)
880 {
881 return m_LSL_Functions.llTransferLindenDollars(destination, amount);
882 }
883
867 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 884 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
868 { 885 {
869 m_LSL_Functions.llGodLikeRezObject(inventory, pos); 886 m_LSL_Functions.llGodLikeRezObject(inventory, pos);
@@ -1588,6 +1605,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1588 m_LSL_Functions.llSetPos(pos); 1605 m_LSL_Functions.llSetPos(pos);
1589 } 1606 }
1590 1607
1608 public LSL_Integer llSetRegionPos(LSL_Vector pos)
1609 {
1610 return m_LSL_Functions.llSetRegionPos(pos);
1611 }
1612
1591 public void llSetPrimitiveParams(LSL_List rules) 1613 public void llSetPrimitiveParams(LSL_List rules)
1592 { 1614 {
1593 m_LSL_Functions.llSetPrimitiveParams(rules); 1615 m_LSL_Functions.llSetPrimitiveParams(rules);
@@ -1823,6 +1845,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1823 m_LSL_Functions.llTargetRemove(number); 1845 m_LSL_Functions.llTargetRemove(number);
1824 } 1846 }
1825 1847
1848 public void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt)
1849 {
1850 m_LSL_Functions.llTeleportAgent(agent, simname, pos, lookAt);
1851 }
1852
1826 public void llTeleportAgentHome(string agent) 1853 public void llTeleportAgentHome(string agent)
1827 { 1854 {
1828 m_LSL_Functions.llTeleportAgentHome(agent); 1855 m_LSL_Functions.llTeleportAgentHome(agent);
@@ -1938,9 +1965,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1938 return m_LSL_Functions.llClearLinkMedia(link, face); 1965 return m_LSL_Functions.llClearLinkMedia(link, face);
1939 } 1966 }
1940 1967
1941 public void print(string str) 1968 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
1969 {
1970 return m_LSL_Functions.llGetLinkNumberOfSides(link);
1971 }
1972
1973 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
1974 {
1975 m_LSL_Functions.llSetKeyframedMotion(frames, options);
1976 }
1977
1978 public void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density)
1942 { 1979 {
1943 m_LSL_Functions.print(str); 1980 m_LSL_Functions.llSetPhysicsMaterial(material_bits, material_gravity_modifier, material_restitution, material_friction, material_density);
1944 } 1981 }
1945 } 1982 }
1946} 1983}
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 2c8af81..0f763f1 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}