aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Api/Implementation
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation')
-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.cs2905
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs109
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs32
6 files changed, 2188 insertions, 1005 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index ee32755..61e4934 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -248,6 +248,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
248 248
249 } 249 }
250 250
251 public static void StateChange(IScriptEngine engine, uint localID, UUID itemID)
252 {
253 // Remove a specific script
254
255 // Remove dataserver events
256 m_Dataserver[engine].RemoveEvents(localID, itemID);
257
258 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>();
259 if (comms != null)
260 comms.DeleteListener(itemID);
261
262 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>();
263 xmlrpc.DeleteChannels(itemID);
264 xmlrpc.CancelSRDRequests(itemID);
265
266 // Remove Sensors
267 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID);
268
269 }
270
251 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID) 271 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID)
252 { 272 {
253 List<Object> data = new List<Object>(); 273 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 0bdd84a..b0b1b16 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{
@@ -99,16 +103,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
99 protected int m_notecardLineReadCharsMax = 255; 103 protected int m_notecardLineReadCharsMax = 255;
100 protected int m_scriptConsoleChannel = 0; 104 protected int m_scriptConsoleChannel = 0;
101 protected bool m_scriptConsoleChannelEnabled = false; 105 protected bool m_scriptConsoleChannelEnabled = false;
106 protected bool m_debuggerSafe = false;
102 protected IUrlModule m_UrlModule = null; 107 protected IUrlModule m_UrlModule = null;
103 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 108 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
104 new Dictionary<UUID, UserInfoCacheEntry>(); 109 new Dictionary<UUID, UserInfoCacheEntry>();
105 110
111 protected Timer m_ShoutSayTimer;
112 protected int m_SayShoutCount = 0;
113
106 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 114 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
107 { 115 {
116 m_ShoutSayTimer = new Timer(1000);
117 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
118 m_ShoutSayTimer.AutoReset = true;
119 m_ShoutSayTimer.Start();
120
108 m_ScriptEngine = ScriptEngine; 121 m_ScriptEngine = ScriptEngine;
109 m_host = host; 122 m_host = host;
110 m_localID = localID; 123 m_localID = localID;
111 m_itemID = itemID; 124 m_itemID = itemID;
125 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
112 126
113 m_ScriptDelayFactor = 127 m_ScriptDelayFactor =
114 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 128 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
@@ -156,6 +170,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
156 get { return m_ScriptEngine.World; } 170 get { return m_ScriptEngine.World; }
157 } 171 }
158 172
173 [DebuggerNonUserCode]
159 public void state(string newState) 174 public void state(string newState)
160 { 175 {
161 m_ScriptEngine.SetState(m_itemID, newState); 176 m_ScriptEngine.SetState(m_itemID, newState);
@@ -165,6 +180,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
165 /// Reset the named script. The script must be present 180 /// Reset the named script. The script must be present
166 /// in the same prim. 181 /// in the same prim.
167 /// </summary> 182 /// </summary>
183 [DebuggerNonUserCode]
168 public void llResetScript() 184 public void llResetScript()
169 { 185 {
170 m_host.AddScriptLPS(1); 186 m_host.AddScriptLPS(1);
@@ -221,9 +237,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
221 } 237 }
222 } 238 }
223 239
240 public List<ScenePresence> GetLinkAvatars(int linkType)
241 {
242 List<ScenePresence> ret = new List<ScenePresence>();
243 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
244 return ret;
245
246 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
247
248 switch (linkType)
249 {
250 case ScriptBaseClass.LINK_SET:
251 return avs;
252
253 case ScriptBaseClass.LINK_ROOT:
254 return ret;
255
256 case ScriptBaseClass.LINK_ALL_OTHERS:
257 return avs;
258
259 case ScriptBaseClass.LINK_ALL_CHILDREN:
260 return avs;
261
262 case ScriptBaseClass.LINK_THIS:
263 return ret;
264
265 default:
266 if (linkType < 0)
267 return ret;
268
269 int partCount = m_host.ParentGroup.GetPartCount();
270
271 if (linkType <= partCount)
272 {
273 return ret;
274 }
275 else
276 {
277 linkType = linkType - partCount;
278 if (linkType > avs.Count)
279 {
280 return ret;
281 }
282 else
283 {
284 ret.Add(avs[linkType-1]);
285 return ret;
286 }
287 }
288 }
289 }
290
224 public List<SceneObjectPart> GetLinkParts(int linkType) 291 public List<SceneObjectPart> GetLinkParts(int linkType)
225 { 292 {
226 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 293 List<SceneObjectPart> ret = new List<SceneObjectPart>();
294 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
295 return ret;
227 ret.Add(m_host); 296 ret.Add(m_host);
228 297
229 switch (linkType) 298 switch (linkType)
@@ -270,40 +339,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
270 protected UUID InventorySelf() 339 protected UUID InventorySelf()
271 { 340 {
272 UUID invItemID = new UUID(); 341 UUID invItemID = new UUID();
273 342 bool unlock = false;
274 lock (m_host.TaskInventory) 343 if (!m_host.TaskInventory.IsReadLockedByMe())
275 { 344 {
276 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 345 m_host.TaskInventory.LockItemsForRead(true);
346 unlock = true;
347 }
348 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
349 {
350 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
277 { 351 {
278 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) 352 invItemID = inv.Key;
279 { 353 break;
280 invItemID = inv.Key;
281 break;
282 }
283 } 354 }
284 } 355 }
285 356 if (unlock)
357 {
358 m_host.TaskInventory.LockItemsForRead(false);
359 }
286 return invItemID; 360 return invItemID;
287 } 361 }
288 362
289 protected UUID InventoryKey(string name, int type) 363 protected UUID InventoryKey(string name, int type)
290 { 364 {
291 m_host.AddScriptLPS(1); 365 m_host.AddScriptLPS(1);
292 366 m_host.TaskInventory.LockItemsForRead(true);
293 lock (m_host.TaskInventory) 367
368 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
294 { 369 {
295 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 370 if (inv.Value.Name == name)
296 { 371 {
297 if (inv.Value.Name == name) 372 m_host.TaskInventory.LockItemsForRead(false);
373
374 if (inv.Value.Type != type)
298 { 375 {
299 if (inv.Value.Type != type) 376 return UUID.Zero;
300 return UUID.Zero;
301
302 return inv.Value.AssetID;
303 } 377 }
378
379 return inv.Value.AssetID;
304 } 380 }
305 } 381 }
306 382
383 m_host.TaskInventory.LockItemsForRead(false);
307 return UUID.Zero; 384 return UUID.Zero;
308 } 385 }
309 386
@@ -311,17 +388,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
311 { 388 {
312 m_host.AddScriptLPS(1); 389 m_host.AddScriptLPS(1);
313 390
314 lock (m_host.TaskInventory) 391
392 m_host.TaskInventory.LockItemsForRead(true);
393
394 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
315 { 395 {
316 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 396 if (inv.Value.Name == name)
317 { 397 {
318 if (inv.Value.Name == name) 398 m_host.TaskInventory.LockItemsForRead(false);
319 { 399 return inv.Value.AssetID;
320 return inv.Value.AssetID;
321 }
322 } 400 }
323 } 401 }
324 402
403 m_host.TaskInventory.LockItemsForRead(false);
404
405
325 return UUID.Zero; 406 return UUID.Zero;
326 } 407 }
327 408
@@ -463,31 +544,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
463 544
464 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 545 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
465 546
466 /// <summary> 547 // Utility function for llRot2Euler
467 /// Convert an LSL rotation to a Euler vector. 548
468 /// </summary> 549 // normalize an angle between -PI and PI (-180 to +180 degrees)
469 /// <remarks> 550 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 { 551 {
477 m_host.AddScriptLPS(1); 552 if (angle > -Math.PI && angle < Math.PI)
553 return angle;
554
555 int numPis = (int)(Math.PI / angle);
556 double remainder = angle - Math.PI * numPis;
557 if (numPis % 2 == 1)
558 return Math.PI - angle;
559 return remainder;
560 }
478 561
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. 562 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. 563 {
481 if (m == 0.0) return new LSL_Vector(); 564 m_host.AddScriptLPS(1);
482 double x = Math.Atan2(-v.y, v.z); 565 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 566
490 return new LSL_Vector(x, y, z); 567 double sqw = q1.s*q1.s;
568 double sqx = q1.x*q1.x;
569 double sqy = q1.z*q1.z;
570 double sqz = q1.y*q1.y;
571 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
572 double test = q1.x*q1.z + q1.y*q1.s;
573 if (test > 0.4999*unit) { // singularity at north pole
574 eul.z = 2 * Math.Atan2(q1.x,q1.s);
575 eul.y = Math.PI/2;
576 eul.x = 0;
577 return eul;
578 }
579 if (test < -0.4999*unit) { // singularity at south pole
580 eul.z = -2 * Math.Atan2(q1.x,q1.s);
581 eul.y = -Math.PI/2;
582 eul.x = 0;
583 return eul;
584 }
585 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
586 eul.y = Math.Asin(2*test/unit);
587 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
588 return eul;
491 } 589 }
492 590
493 /* From wiki: 591 /* From wiki:
@@ -689,77 +787,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
689 { 787 {
690 //A and B should both be normalized 788 //A and B should both be normalized
691 m_host.AddScriptLPS(1); 789 m_host.AddScriptLPS(1);
692 LSL_Rotation rotBetween; 790 /* 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, 791 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
694 // continue calculation. 792
695 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 793 double dotProduct = LSL_Vector.Dot(a, b);
794 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
795 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
796 double angle = Math.Acos(dotProduct / magProduct);
797 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
798 double s = Math.Sin(angle / 2);
799
800 double x = axis.x * s;
801 double y = axis.y * s;
802 double z = axis.z * s;
803 double w = Math.Cos(angle / 2);
804
805 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
806 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
807
808 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
809 */
810
811 // This method mimics the 180 errors found in SL
812 // See www.euclideanspace.com... angleBetween
813 LSL_Vector vec_a = a;
814 LSL_Vector vec_b = b;
815
816 // Eliminate zero length
817 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
818 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
819 if (vec_a_mag < 0.00001 ||
820 vec_b_mag < 0.00001)
696 { 821 {
697 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 822 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
698 } 823 }
699 else 824
825 // Normalize
826 vec_a = llVecNorm(vec_a);
827 vec_b = llVecNorm(vec_b);
828
829 // Calculate axis and rotation angle
830 LSL_Vector axis = vec_a % vec_b;
831 LSL_Float cos_theta = vec_a * vec_b;
832
833 // Check if parallel
834 if (cos_theta > 0.99999)
700 { 835 {
701 a = LSL_Vector.Norm(a); 836 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
702 b = LSL_Vector.Norm(b); 837 }
703 double dotProduct = LSL_Vector.Dot(a, b); 838
704 // There are two degenerate cases possible. These are for vectors 180 or 839 // Check if anti-parallel
705 // 0 degrees apart. These have to be detected and handled individually. 840 else if (cos_theta < -0.99999)
706 // 841 {
707 // Check for vectors 180 degrees apart. 842 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. 843 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
709 if (dotProduct < -0.9999999f) 844 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
710 { 845 }
711 // First assume X axis is orthogonal to the vectors. 846 else // other rotation
712 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 847 {
713 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 848 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 849 axis = llVecNorm(axis);
715 // a rotation in an undesired direction. 850 double x, y, z, s, t;
716 if (LSL_Vector.Mag(orthoVector) > 0.0001) 851 s = Math.Cos(theta);
717 { 852 t = Math.Sin(theta);
718 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 853 x = axis.x * t;
719 } 854 y = axis.y * t;
720 // If the magnitude of the vector was near zero, then assume the X axis is not 855 z = axis.z * t;
721 // orthogonal and use the Z axis instead. 856 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 } 857 }
760 return rotBetween;
761 } 858 }
762 859
763 public void llWhisper(int channelID, string text) 860 public void llWhisper(int channelID, string text)
764 { 861 {
765 m_host.AddScriptLPS(1); 862 m_host.AddScriptLPS(1);
@@ -779,6 +876,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
779 { 876 {
780 m_host.AddScriptLPS(1); 877 m_host.AddScriptLPS(1);
781 878
879 if (channelID == 0)
880 m_SayShoutCount++;
881
882 if (m_SayShoutCount >= 11)
883 ScriptSleep(2000);
884
782 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 885 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
783 { 886 {
784 Console.WriteLine(text); 887 Console.WriteLine(text);
@@ -801,6 +904,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
801 { 904 {
802 m_host.AddScriptLPS(1); 905 m_host.AddScriptLPS(1);
803 906
907 if (channelID == 0)
908 m_SayShoutCount++;
909
910 if (m_SayShoutCount >= 11)
911 ScriptSleep(2000);
912
804 if (text.Length > 1023) 913 if (text.Length > 1023)
805 text = text.Substring(0, 1023); 914 text = text.Substring(0, 1023);
806 915
@@ -1101,10 +1210,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1101 return detectedParams.TouchUV; 1210 return detectedParams.TouchUV;
1102 } 1211 }
1103 1212
1213 [DebuggerNonUserCode]
1104 public virtual void llDie() 1214 public virtual void llDie()
1105 { 1215 {
1106 m_host.AddScriptLPS(1); 1216 m_host.AddScriptLPS(1);
1107 throw new SelfDeleteException(); 1217 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1108 } 1218 }
1109 1219
1110 public LSL_Float llGround(LSL_Vector offset) 1220 public LSL_Float llGround(LSL_Vector offset)
@@ -1177,6 +1287,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1177 1287
1178 public void llSetStatus(int status, int value) 1288 public void llSetStatus(int status, int value)
1179 { 1289 {
1290 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1291 return;
1180 m_host.AddScriptLPS(1); 1292 m_host.AddScriptLPS(1);
1181 1293
1182 int statusrotationaxis = 0; 1294 int statusrotationaxis = 0;
@@ -1406,6 +1518,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1406 { 1518 {
1407 m_host.AddScriptLPS(1); 1519 m_host.AddScriptLPS(1);
1408 1520
1521 SetColor(m_host, color, face);
1522 }
1523
1524 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1525 {
1526 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1527 return;
1528
1529 Primitive.TextureEntry tex = part.Shape.Textures;
1530 Color4 texcolor;
1531 if (face >= 0 && face < GetNumberOfSides(part))
1532 {
1533 texcolor = tex.CreateFace((uint)face).RGBA;
1534 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1535 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1536 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1537 tex.FaceTextures[face].RGBA = texcolor;
1538 part.UpdateTextureEntry(tex.GetBytes());
1539 return;
1540 }
1541 else if (face == ScriptBaseClass.ALL_SIDES)
1542 {
1543 for (uint i = 0; i < GetNumberOfSides(part); i++)
1544 {
1545 if (tex.FaceTextures[i] != null)
1546 {
1547 texcolor = tex.FaceTextures[i].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[i].RGBA = texcolor;
1552 }
1553 texcolor = tex.DefaultTexture.RGBA;
1554 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1555 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1556 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1557 tex.DefaultTexture.RGBA = texcolor;
1558 }
1559 part.UpdateTextureEntry(tex.GetBytes());
1560 return;
1561 }
1562
1409 if (face == ScriptBaseClass.ALL_SIDES) 1563 if (face == ScriptBaseClass.ALL_SIDES)
1410 face = SceneObjectPart.ALL_SIDES; 1564 face = SceneObjectPart.ALL_SIDES;
1411 1565
@@ -1414,6 +1568,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1414 1568
1415 public void SetTexGen(SceneObjectPart part, int face,int style) 1569 public void SetTexGen(SceneObjectPart part, int face,int style)
1416 { 1570 {
1571 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1572 return;
1573
1417 Primitive.TextureEntry tex = part.Shape.Textures; 1574 Primitive.TextureEntry tex = part.Shape.Textures;
1418 MappingType textype; 1575 MappingType textype;
1419 textype = MappingType.Default; 1576 textype = MappingType.Default;
@@ -1444,6 +1601,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1444 1601
1445 public void SetGlow(SceneObjectPart part, int face, float glow) 1602 public void SetGlow(SceneObjectPart part, int face, float glow)
1446 { 1603 {
1604 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1605 return;
1606
1447 Primitive.TextureEntry tex = part.Shape.Textures; 1607 Primitive.TextureEntry tex = part.Shape.Textures;
1448 if (face >= 0 && face < GetNumberOfSides(part)) 1608 if (face >= 0 && face < GetNumberOfSides(part))
1449 { 1609 {
@@ -1469,6 +1629,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1469 1629
1470 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1630 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1471 { 1631 {
1632 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1633 return;
1472 1634
1473 Shininess sval = new Shininess(); 1635 Shininess sval = new Shininess();
1474 1636
@@ -1519,6 +1681,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1519 1681
1520 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1682 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1521 { 1683 {
1684 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1685 return;
1686
1522 Primitive.TextureEntry tex = part.Shape.Textures; 1687 Primitive.TextureEntry tex = part.Shape.Textures;
1523 if (face >= 0 && face < GetNumberOfSides(part)) 1688 if (face >= 0 && face < GetNumberOfSides(part))
1524 { 1689 {
@@ -1579,13 +1744,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1579 m_host.AddScriptLPS(1); 1744 m_host.AddScriptLPS(1);
1580 1745
1581 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1746 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1582 1747 if (parts.Count > 0)
1583 foreach (SceneObjectPart part in parts) 1748 {
1584 SetAlpha(part, alpha, face); 1749 try
1750 {
1751 parts[0].ParentGroup.areUpdatesSuspended = true;
1752 foreach (SceneObjectPart part in parts)
1753 SetAlpha(part, alpha, face);
1754 }
1755 finally
1756 {
1757 parts[0].ParentGroup.areUpdatesSuspended = false;
1758 }
1759 }
1585 } 1760 }
1586 1761
1587 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1762 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1588 { 1763 {
1764 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1765 return;
1766
1589 Primitive.TextureEntry tex = part.Shape.Textures; 1767 Primitive.TextureEntry tex = part.Shape.Textures;
1590 Color4 texcolor; 1768 Color4 texcolor;
1591 if (face >= 0 && face < GetNumberOfSides(part)) 1769 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1638,7 +1816,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1638 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1816 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1639 float wind, float tension, LSL_Vector Force) 1817 float wind, float tension, LSL_Vector Force)
1640 { 1818 {
1641 if (part == null) 1819 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1642 return; 1820 return;
1643 1821
1644 if (flexi) 1822 if (flexi)
@@ -1672,7 +1850,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1672 /// <param name="falloff"></param> 1850 /// <param name="falloff"></param>
1673 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1851 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1674 { 1852 {
1675 if (part == null) 1853 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1676 return; 1854 return;
1677 1855
1678 if (light) 1856 if (light)
@@ -1749,15 +1927,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1749 m_host.AddScriptLPS(1); 1927 m_host.AddScriptLPS(1);
1750 1928
1751 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1929 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1752 1930 if (parts.Count > 0)
1753 foreach (SceneObjectPart part in parts) 1931 {
1754 SetTexture(part, texture, face); 1932 try
1755 1933 {
1934 parts[0].ParentGroup.areUpdatesSuspended = true;
1935 foreach (SceneObjectPart part in parts)
1936 SetTexture(part, texture, face);
1937 }
1938 finally
1939 {
1940 parts[0].ParentGroup.areUpdatesSuspended = false;
1941 }
1942 }
1756 ScriptSleep(200); 1943 ScriptSleep(200);
1757 } 1944 }
1758 1945
1759 protected void SetTexture(SceneObjectPart part, string texture, int face) 1946 protected void SetTexture(SceneObjectPart part, string texture, int face)
1760 { 1947 {
1948 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1949 return;
1950
1761 UUID textureID = new UUID(); 1951 UUID textureID = new UUID();
1762 1952
1763 textureID = InventoryKey(texture, (int)AssetType.Texture); 1953 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1802,6 +1992,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1802 1992
1803 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 1993 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1804 { 1994 {
1995 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1996 return;
1997
1805 Primitive.TextureEntry tex = part.Shape.Textures; 1998 Primitive.TextureEntry tex = part.Shape.Textures;
1806 if (face >= 0 && face < GetNumberOfSides(part)) 1999 if (face >= 0 && face < GetNumberOfSides(part))
1807 { 2000 {
@@ -1838,6 +2031,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1838 2031
1839 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2032 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1840 { 2033 {
2034 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2035 return;
2036
1841 Primitive.TextureEntry tex = part.Shape.Textures; 2037 Primitive.TextureEntry tex = part.Shape.Textures;
1842 if (face >= 0 && face < GetNumberOfSides(part)) 2038 if (face >= 0 && face < GetNumberOfSides(part))
1843 { 2039 {
@@ -1874,6 +2070,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1874 2070
1875 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2071 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1876 { 2072 {
2073 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2074 return;
2075
1877 Primitive.TextureEntry tex = part.Shape.Textures; 2076 Primitive.TextureEntry tex = part.Shape.Textures;
1878 if (face >= 0 && face < GetNumberOfSides(part)) 2077 if (face >= 0 && face < GetNumberOfSides(part))
1879 { 2078 {
@@ -1980,24 +2179,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1980 2179
1981 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2180 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1982 { 2181 {
1983 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2182 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1984 LSL_Vector currentPos = GetPartLocalPos(part); 2183 return;
1985 2184
1986 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); 2185 LSL_Vector currentPos = GetPartLocalPos(part);
1987 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); 2186 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
1988 2187
1989 if (part.ParentGroup.RootPart == part) 2188 if (part.ParentGroup.RootPart == part)
1990 { 2189 {
1991 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
1992 targetPos.z = ground;
1993 SceneObjectGroup parent = part.ParentGroup; 2190 SceneObjectGroup parent = part.ParentGroup;
1994 LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); 2191 parent.UpdateGroupPosition(new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z));
1995 parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z));
1996 } 2192 }
1997 else 2193 else
1998 { 2194 {
1999 LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); 2195 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
2000 part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z);
2001 SceneObjectGroup parent = part.ParentGroup; 2196 SceneObjectGroup parent = part.ParentGroup;
2002 parent.HasGroupChanged = true; 2197 parent.HasGroupChanged = true;
2003 parent.ScheduleGroupForTerseUpdate(); 2198 parent.ScheduleGroupForTerseUpdate();
@@ -2028,11 +2223,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2028 } 2223 }
2029 else 2224 else
2030 { 2225 {
2031 if (m_host.IsRoot) 2226 if (part.IsRoot)
2032 { 2227 {
2033 return new LSL_Vector(m_host.AttachedPos.X, 2228 return new LSL_Vector(part.AttachedPos.X,
2034 m_host.AttachedPos.Y, 2229 part.AttachedPos.Y,
2035 m_host.AttachedPos.Z); 2230 part.AttachedPos.Z);
2036 } 2231 }
2037 else 2232 else
2038 { 2233 {
@@ -2048,9 +2243,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2048 m_host.AddScriptLPS(1); 2243 m_host.AddScriptLPS(1);
2049 2244
2050 // try to let this work as in SL... 2245 // try to let this work as in SL...
2051 if (m_host.ParentID == 0) 2246 if (m_host.LinkNum < 2)
2052 { 2247 {
2053 // special case: If we are root, rotate complete SOG to new rotation 2248 // Special case: If we are root, rotate complete SOG to new
2249 // rotation.
2250 // We are root if the link number is 0 (single prim) or 1
2251 // (root prim). ParentID may be nonzero in attachments and
2252 // using it would cause attachments and HUDs to rotate
2253 // to the wrong positions.
2054 SetRot(m_host, Rot2Quaternion(rot)); 2254 SetRot(m_host, Rot2Quaternion(rot));
2055 } 2255 }
2056 else 2256 else
@@ -2075,6 +2275,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2075 2275
2076 protected void SetRot(SceneObjectPart part, Quaternion rot) 2276 protected void SetRot(SceneObjectPart part, Quaternion rot)
2077 { 2277 {
2278 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2279 return;
2280
2078 part.UpdateRotation(rot); 2281 part.UpdateRotation(rot);
2079 // Update rotation does not move the object in the physics scene if it's a linkset. 2282 // Update rotation does not move the object in the physics scene if it's a linkset.
2080 2283
@@ -2698,12 +2901,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2698 2901
2699 m_host.AddScriptLPS(1); 2902 m_host.AddScriptLPS(1);
2700 2903
2904 m_host.TaskInventory.LockItemsForRead(true);
2701 TaskInventoryItem item = m_host.TaskInventory[invItemID]; 2905 TaskInventoryItem item = m_host.TaskInventory[invItemID];
2702 2906 m_host.TaskInventory.LockItemsForRead(false);
2703 lock (m_host.TaskInventory)
2704 {
2705 item = m_host.TaskInventory[invItemID];
2706 }
2707 2907
2708 if (item.PermsGranter == UUID.Zero) 2908 if (item.PermsGranter == UUID.Zero)
2709 return 0; 2909 return 0;
@@ -2771,64 +2971,69 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2771 { 2971 {
2772 m_host.AddScriptLPS(1); 2972 m_host.AddScriptLPS(1);
2773 2973
2774 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) 2974 Util.FireAndForget(delegate (object x)
2775 return; 2975 {
2776 float dist = (float)llVecDist(llGetPos(), pos); 2976 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
2977 return;
2978 float dist = (float)llVecDist(llGetPos(), pos);
2777 2979
2778 if (dist > m_ScriptDistanceFactor * 10.0f) 2980 if (dist > m_ScriptDistanceFactor * 10.0f)
2779 return; 2981 return;
2780 2982
2781 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 2983 //Clone is thread-safe
2984 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
2782 2985
2783 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory) 2986 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
2784 {
2785 if (inv.Value.Name == inventory)
2786 { 2987 {
2787 // make sure we're an object. 2988 if (inv.Value.Name == inventory)
2788 if (inv.Value.InvType != (int)InventoryType.Object)
2789 { 2989 {
2790 llSay(0, "Unable to create requested object. Object is missing from database."); 2990 // make sure we're an object.
2791 return; 2991 if (inv.Value.InvType != (int)InventoryType.Object)
2792 } 2992 {
2993 llSay(0, "Unable to create requested object. Object is missing from database.");
2994 return;
2995 }
2793 2996
2794 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); 2997 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
2795 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); 2998 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z);
2796 2999
2797 // need the magnitude later 3000 // need the magnitude later
2798 float velmag = (float)Util.GetMagnitude(llvel); 3001 // float velmag = (float)Util.GetMagnitude(llvel);
2799 3002
2800 SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, Rot2Quaternion(rot), llvel, param); 3003 SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, Rot2Quaternion(rot), llvel, param);
2801 3004
2802 // If either of these are null, then there was an unknown error. 3005 // If either of these are null, then there was an unknown error.
2803 if (new_group == null) 3006 if (new_group == null)
2804 continue; 3007 continue;
2805 3008
2806 // objects rezzed with this method are die_at_edge by default. 3009 // objects rezzed with this method are die_at_edge by default.
2807 new_group.RootPart.SetDieAtEdge(true); 3010 new_group.RootPart.SetDieAtEdge(true);
2808 3011
2809 new_group.ResumeScripts(); 3012 new_group.ResumeScripts();
2810 3013
2811 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 3014 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
2812 "object_rez", new Object[] { 3015 "object_rez", new Object[] {
2813 new LSL_String( 3016 new LSL_String(
2814 new_group.RootPart.UUID.ToString()) }, 3017 new_group.RootPart.UUID.ToString()) },
2815 new DetectParams[0])); 3018 new DetectParams[0]));
2816 3019
2817 float groupmass = new_group.GetMass(); 3020 float groupmass = new_group.GetMass();
2818 3021
2819 if (new_group.RootPart.PhysActor != null && new_group.RootPart.PhysActor.IsPhysical && llvel != Vector3.Zero) 3022 if (new_group.RootPart.PhysActor != null && new_group.RootPart.PhysActor.IsPhysical && llvel != Vector3.Zero)
2820 { 3023 {
2821 //Recoil. 3024 //Recoil.
2822 llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); 3025 llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0);
3026 }
3027 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3028 return;
2823 } 3029 }
2824 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
2825 ScriptSleep((int)((groupmass * velmag) / 10));
2826 ScriptSleep(100);
2827 return;
2828 } 3030 }
2829 }
2830 3031
2831 llSay(0, "Could not find object " + inventory); 3032 llSay(0, "Could not find object " + inventory);
3033 });
3034
3035 //ScriptSleep((int)((groupmass * velmag) / 10));
3036 ScriptSleep(100);
2832 } 3037 }
2833 3038
2834 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) 3039 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
@@ -2839,34 +3044,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2839 public void llLookAt(LSL_Vector target, double strength, double damping) 3044 public void llLookAt(LSL_Vector target, double strength, double damping)
2840 { 3045 {
2841 m_host.AddScriptLPS(1); 3046 m_host.AddScriptLPS(1);
2842 // Determine where we are looking from
2843 LSL_Vector from = llGetPos();
2844 3047
2845 // Work out the normalised vector from the source to the target 3048 // Get the normalized vector to the target
2846 LSL_Vector delta = llVecNorm(target - from); 3049 LSL_Vector d1 = llVecNorm(target - llGetPos());
2847 LSL_Vector angle = new LSL_Vector(0,0,0);
2848 3050
2849 // Calculate the yaw 3051 // Get the bearing (yaw)
2850 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3052 LSL_Vector a1 = new LSL_Vector(0,0,0);
2851 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3053 a1.z = llAtan2(d1.y, d1.x);
2852 3054
2853 // Calculate pitch 3055 // Get the elevation (pitch)
2854 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3056 LSL_Vector a2 = new LSL_Vector(0,0,0);
3057 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2855 3058
2856 // we need to convert from a vector describing 3059 LSL_Rotation r1 = llEuler2Rot(a1);
2857 // the angles of rotation in radians into rotation value 3060 LSL_Rotation r2 = llEuler2Rot(a2);
3061 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2858 3062
2859 LSL_Rotation rot = llEuler2Rot(angle); 3063 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2860
2861 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2862 // set the rotation of the object, copy that behavior
2863 if (strength == 0 || m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2864 { 3064 {
2865 llSetRot(rot); 3065 // Do nothing if either value is 0 (this has been checked in SL)
3066 if (strength <= 0.0 || damping <= 0.0)
3067 return;
3068
3069 llSetRot(r3 * r2 * r1);
2866 } 3070 }
2867 else 3071 else
2868 { 3072 {
2869 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3073 if (strength == 0)
3074 {
3075 llSetRot(r3 * r2 * r1);
3076 return;
3077 }
3078
3079 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2870 } 3080 }
2871 } 3081 }
2872 3082
@@ -2916,13 +3126,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2916 { 3126 {
2917 TaskInventoryItem item; 3127 TaskInventoryItem item;
2918 3128
2919 lock (m_host.TaskInventory) 3129 m_host.TaskInventory.LockItemsForRead(true);
3130 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2920 { 3131 {
2921 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3132 m_host.TaskInventory.LockItemsForRead(false);
2922 return; 3133 return;
2923 else 3134 }
2924 item = m_host.TaskInventory[InventorySelf()]; 3135 else
3136 {
3137 item = m_host.TaskInventory[InventorySelf()];
2925 } 3138 }
3139 m_host.TaskInventory.LockItemsForRead(false);
2926 3140
2927 if (item.PermsGranter != UUID.Zero) 3141 if (item.PermsGranter != UUID.Zero)
2928 { 3142 {
@@ -2944,13 +3158,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2944 { 3158 {
2945 TaskInventoryItem item; 3159 TaskInventoryItem item;
2946 3160
3161 m_host.TaskInventory.LockItemsForRead(true);
2947 lock (m_host.TaskInventory) 3162 lock (m_host.TaskInventory)
2948 { 3163 {
3164
2949 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3165 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3166 {
3167 m_host.TaskInventory.LockItemsForRead(false);
2950 return; 3168 return;
3169 }
2951 else 3170 else
3171 {
2952 item = m_host.TaskInventory[InventorySelf()]; 3172 item = m_host.TaskInventory[InventorySelf()];
3173 }
2953 } 3174 }
3175 m_host.TaskInventory.LockItemsForRead(false);
2954 3176
2955 m_host.AddScriptLPS(1); 3177 m_host.AddScriptLPS(1);
2956 3178
@@ -2982,19 +3204,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2982 { 3204 {
2983 m_host.AddScriptLPS(1); 3205 m_host.AddScriptLPS(1);
2984 3206
2985// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
2986// return;
2987
2988 TaskInventoryItem item; 3207 TaskInventoryItem item;
2989 3208
2990 lock (m_host.TaskInventory) 3209 m_host.TaskInventory.LockItemsForRead(true);
3210
3211 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2991 { 3212 {
2992 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3213 m_host.TaskInventory.LockItemsForRead(false);
2993 return; 3214 return;
2994 else 3215 }
2995 item = m_host.TaskInventory[InventorySelf()]; 3216 else
3217 {
3218 item = m_host.TaskInventory[InventorySelf()];
2996 } 3219 }
2997 3220
3221 m_host.TaskInventory.LockItemsForRead(false);
3222
2998 if (item.PermsGranter != m_host.OwnerID) 3223 if (item.PermsGranter != m_host.OwnerID)
2999 return; 3224 return;
3000 3225
@@ -3019,13 +3244,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3019 3244
3020 TaskInventoryItem item; 3245 TaskInventoryItem item;
3021 3246
3022 lock (m_host.TaskInventory) 3247 m_host.TaskInventory.LockItemsForRead(true);
3248
3249 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3023 { 3250 {
3024 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3251 m_host.TaskInventory.LockItemsForRead(false);
3025 return; 3252 return;
3026 else
3027 item = m_host.TaskInventory[InventorySelf()];
3028 } 3253 }
3254 else
3255 {
3256 item = m_host.TaskInventory[InventorySelf()];
3257 }
3258 m_host.TaskInventory.LockItemsForRead(false);
3259
3029 3260
3030 if (item.PermsGranter != m_host.OwnerID) 3261 if (item.PermsGranter != m_host.OwnerID)
3031 return; 3262 return;
@@ -3072,6 +3303,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3072 3303
3073 public void llInstantMessage(string user, string message) 3304 public void llInstantMessage(string user, string message)
3074 { 3305 {
3306 UUID result;
3307 if (!UUID.TryParse(user, out result))
3308 {
3309 ShoutError("An invalid key was passed to llInstantMessage");
3310 ScriptSleep(2000);
3311 return;
3312 }
3313
3314
3075 m_host.AddScriptLPS(1); 3315 m_host.AddScriptLPS(1);
3076 3316
3077 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3317 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3086,14 +3326,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3086 UUID friendTransactionID = UUID.Random(); 3326 UUID friendTransactionID = UUID.Random();
3087 3327
3088 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3328 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3089 3329
3090 GridInstantMessage msg = new GridInstantMessage(); 3330 GridInstantMessage msg = new GridInstantMessage();
3091 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3331 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3092 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3332 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3093 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3333 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3094// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3334// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3095// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3335// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3096 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3336// DateTime dt = DateTime.UtcNow;
3337//
3338// // Ticks from UtcNow, but make it look like local. Evil, huh?
3339// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3340//
3341// try
3342// {
3343// // Convert that to the PST timezone
3344// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3345// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3346// }
3347// catch
3348// {
3349// // No logging here, as it could be VERY spammy
3350// }
3351//
3352// // And make it look local again to fool the unix time util
3353// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3354
3355 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3356
3097 //if (client != null) 3357 //if (client != null)
3098 //{ 3358 //{
3099 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3359 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3107,12 +3367,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3107 msg.message = message.Substring(0, 1024); 3367 msg.message = message.Substring(0, 1024);
3108 else 3368 else
3109 msg.message = message; 3369 msg.message = message;
3110 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3370 msg.dialog = (byte)19; // MessageFromObject
3111 msg.fromGroup = false;// fromGroup; 3371 msg.fromGroup = false;// fromGroup;
3112 msg.offline = (byte)0; //offline; 3372 msg.offline = (byte)0; //offline;
3113 msg.ParentEstateID = 0; //ParentEstateID; 3373 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3114 msg.Position = new Vector3(m_host.AbsolutePosition); 3374 msg.Position = new Vector3(m_host.AbsolutePosition);
3115 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3375 msg.RegionID = World.RegionInfo.RegionID.Guid;
3116 msg.binaryBucket 3376 msg.binaryBucket
3117 = Util.StringToBytes256( 3377 = Util.StringToBytes256(
3118 "{0}/{1}/{2}/{3}", 3378 "{0}/{1}/{2}/{3}",
@@ -3140,7 +3400,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3140 } 3400 }
3141 3401
3142 emailModule.SendEmail(m_host.UUID, address, subject, message); 3402 emailModule.SendEmail(m_host.UUID, address, subject, message);
3143 ScriptSleep(20000); 3403 ScriptSleep(15000);
3144 } 3404 }
3145 3405
3146 public void llGetNextEmail(string address, string subject) 3406 public void llGetNextEmail(string address, string subject)
@@ -3279,14 +3539,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3279 3539
3280 TaskInventoryItem item; 3540 TaskInventoryItem item;
3281 3541
3282 lock (m_host.TaskInventory) 3542 m_host.TaskInventory.LockItemsForRead(true);
3543 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3283 { 3544 {
3284 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3545 m_host.TaskInventory.LockItemsForRead(false);
3285 return; 3546 return;
3286 else
3287 item = m_host.TaskInventory[InventorySelf()];
3288 } 3547 }
3289 3548 else
3549 {
3550 item = m_host.TaskInventory[InventorySelf()];
3551 }
3552 m_host.TaskInventory.LockItemsForRead(false);
3290 if (item.PermsGranter == UUID.Zero) 3553 if (item.PermsGranter == UUID.Zero)
3291 return; 3554 return;
3292 3555
@@ -3316,13 +3579,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3316 3579
3317 TaskInventoryItem item; 3580 TaskInventoryItem item;
3318 3581
3319 lock (m_host.TaskInventory) 3582 m_host.TaskInventory.LockItemsForRead(true);
3583 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3320 { 3584 {
3321 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3585 m_host.TaskInventory.LockItemsForRead(false);
3322 return; 3586 return;
3323 else 3587 }
3324 item = m_host.TaskInventory[InventorySelf()]; 3588 else
3589 {
3590 item = m_host.TaskInventory[InventorySelf()];
3325 } 3591 }
3592 m_host.TaskInventory.LockItemsForRead(false);
3593
3326 3594
3327 if (item.PermsGranter == UUID.Zero) 3595 if (item.PermsGranter == UUID.Zero)
3328 return; 3596 return;
@@ -3389,10 +3657,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3389 3657
3390 TaskInventoryItem item; 3658 TaskInventoryItem item;
3391 3659
3392 lock (m_host.TaskInventory) 3660
3661 m_host.TaskInventory.LockItemsForRead(true);
3662 if (!m_host.TaskInventory.ContainsKey(invItemID))
3663 {
3664 m_host.TaskInventory.LockItemsForRead(false);
3665 return;
3666 }
3667 else
3393 { 3668 {
3394 item = m_host.TaskInventory[invItemID]; 3669 item = m_host.TaskInventory[invItemID];
3395 } 3670 }
3671 m_host.TaskInventory.LockItemsForRead(false);
3396 3672
3397 if (agentID == UUID.Zero || perm == 0) // Releasing permissions 3673 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
3398 { 3674 {
@@ -3420,15 +3696,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3420 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3696 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3421 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3697 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3422 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3698 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3699 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3423 ScriptBaseClass.PERMISSION_ATTACH; 3700 ScriptBaseClass.PERMISSION_ATTACH;
3424 3701
3425 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3702 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3426 { 3703 {
3427 lock (m_host.TaskInventory) 3704 m_host.TaskInventory.LockItemsForWrite(true);
3428 { 3705 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3429 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3706 m_host.TaskInventory[invItemID].PermsMask = perm;
3430 m_host.TaskInventory[invItemID].PermsMask = perm; 3707 m_host.TaskInventory.LockItemsForWrite(false);
3431 }
3432 3708
3433 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3709 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3434 "run_time_permissions", new Object[] { 3710 "run_time_permissions", new Object[] {
@@ -3438,28 +3714,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3438 return; 3714 return;
3439 } 3715 }
3440 } 3716 }
3441 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3717 else
3442 { 3718 {
3443 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3719 bool sitting = false;
3444 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3720 if (m_host.SitTargetAvatar == agentID)
3445 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3721 {
3446 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3722 sitting = true;
3447 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3723 }
3724 else
3725 {
3726 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3727 {
3728 if (p.SitTargetAvatar == agentID)
3729 sitting = true;
3730 }
3731 }
3448 3732
3449 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3733 if (sitting)
3450 { 3734 {
3451 lock (m_host.TaskInventory) 3735 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3736 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3737 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3738 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3739 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3740
3741 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3452 { 3742 {
3743 m_host.TaskInventory.LockItemsForWrite(true);
3453 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3744 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3454 m_host.TaskInventory[invItemID].PermsMask = perm; 3745 m_host.TaskInventory[invItemID].PermsMask = perm;
3455 } 3746 m_host.TaskInventory.LockItemsForWrite(false);
3456 3747
3457 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3748 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3458 "run_time_permissions", new Object[] { 3749 "run_time_permissions", new Object[] {
3459 new LSL_Integer(perm) }, 3750 new LSL_Integer(perm) },
3460 new DetectParams[0])); 3751 new DetectParams[0]));
3461 3752
3462 return; 3753 return;
3754 }
3463 } 3755 }
3464 } 3756 }
3465 3757
@@ -3473,11 +3765,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3473 3765
3474 if (!m_waitingForScriptAnswer) 3766 if (!m_waitingForScriptAnswer)
3475 { 3767 {
3476 lock (m_host.TaskInventory) 3768 m_host.TaskInventory.LockItemsForWrite(true);
3477 { 3769 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3478 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3770 m_host.TaskInventory[invItemID].PermsMask = 0;
3479 m_host.TaskInventory[invItemID].PermsMask = 0; 3771 m_host.TaskInventory.LockItemsForWrite(false);
3480 }
3481 3772
3482 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3773 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3483 m_waitingForScriptAnswer=true; 3774 m_waitingForScriptAnswer=true;
@@ -3512,10 +3803,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3512 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3803 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3513 llReleaseControls(); 3804 llReleaseControls();
3514 3805
3515 lock (m_host.TaskInventory) 3806
3516 { 3807 m_host.TaskInventory.LockItemsForWrite(true);
3517 m_host.TaskInventory[invItemID].PermsMask = answer; 3808 m_host.TaskInventory[invItemID].PermsMask = answer;
3518 } 3809 m_host.TaskInventory.LockItemsForWrite(false);
3810
3519 3811
3520 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3812 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3521 "run_time_permissions", new Object[] { 3813 "run_time_permissions", new Object[] {
@@ -3527,16 +3819,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3527 { 3819 {
3528 m_host.AddScriptLPS(1); 3820 m_host.AddScriptLPS(1);
3529 3821
3530 lock (m_host.TaskInventory) 3822 m_host.TaskInventory.LockItemsForRead(true);
3823
3824 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3531 { 3825 {
3532 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3826 if (item.Type == 10 && item.ItemID == m_itemID)
3533 { 3827 {
3534 if (item.Type == 10 && item.ItemID == m_itemID) 3828 m_host.TaskInventory.LockItemsForRead(false);
3535 { 3829 return item.PermsGranter.ToString();
3536 return item.PermsGranter.ToString();
3537 }
3538 } 3830 }
3539 } 3831 }
3832 m_host.TaskInventory.LockItemsForRead(false);
3540 3833
3541 return UUID.Zero.ToString(); 3834 return UUID.Zero.ToString();
3542 } 3835 }
@@ -3545,19 +3838,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3545 { 3838 {
3546 m_host.AddScriptLPS(1); 3839 m_host.AddScriptLPS(1);
3547 3840
3548 lock (m_host.TaskInventory) 3841 m_host.TaskInventory.LockItemsForRead(true);
3842
3843 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3549 { 3844 {
3550 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3845 if (item.Type == 10 && item.ItemID == m_itemID)
3551 { 3846 {
3552 if (item.Type == 10 && item.ItemID == m_itemID) 3847 int perms = item.PermsMask;
3553 { 3848 if (m_automaticLinkPermission)
3554 int perms = item.PermsMask; 3849 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
3555 if (m_automaticLinkPermission) 3850 m_host.TaskInventory.LockItemsForRead(false);
3556 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 3851 return perms;
3557 return perms;
3558 }
3559 } 3852 }
3560 } 3853 }
3854 m_host.TaskInventory.LockItemsForRead(false);
3561 3855
3562 return 0; 3856 return 0;
3563 } 3857 }
@@ -3579,9 +3873,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3579 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3873 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3580 { 3874 {
3581 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3875 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3582 3876 if (parts.Count > 0)
3583 foreach (SceneObjectPart part in parts) 3877 {
3584 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3878 try
3879 {
3880 parts[0].ParentGroup.areUpdatesSuspended = true;
3881 foreach (SceneObjectPart part in parts)
3882 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3883 }
3884 finally
3885 {
3886 parts[0].ParentGroup.areUpdatesSuspended = false;
3887 }
3888 }
3585 } 3889 }
3586 3890
3587 public void llCreateLink(string target, int parent) 3891 public void llCreateLink(string target, int parent)
@@ -3594,11 +3898,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3594 return; 3898 return;
3595 3899
3596 TaskInventoryItem item; 3900 TaskInventoryItem item;
3597 lock (m_host.TaskInventory) 3901 m_host.TaskInventory.LockItemsForRead(true);
3598 { 3902 item = m_host.TaskInventory[invItemID];
3599 item = m_host.TaskInventory[invItemID]; 3903 m_host.TaskInventory.LockItemsForRead(false);
3600 } 3904
3601
3602 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3905 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3603 && !m_automaticLinkPermission) 3906 && !m_automaticLinkPermission)
3604 { 3907 {
@@ -3615,11 +3918,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3615 3918
3616 if (targetPart.ParentGroup.AttachmentPoint != 0) 3919 if (targetPart.ParentGroup.AttachmentPoint != 0)
3617 return; // Fail silently if attached 3920 return; // Fail silently if attached
3921
3922 if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID)
3923 return;
3924
3618 SceneObjectGroup parentPrim = null, childPrim = null; 3925 SceneObjectGroup parentPrim = null, childPrim = null;
3619 3926
3620 if (targetPart != null) 3927 if (targetPart != null)
3621 { 3928 {
3622 if (parent != 0) { 3929 if (parent != 0)
3930 {
3623 parentPrim = m_host.ParentGroup; 3931 parentPrim = m_host.ParentGroup;
3624 childPrim = targetPart.ParentGroup; 3932 childPrim = targetPart.ParentGroup;
3625 } 3933 }
@@ -3631,7 +3939,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3631 3939
3632 // Required for linking 3940 // Required for linking
3633 childPrim.RootPart.ClearUpdateSchedule(); 3941 childPrim.RootPart.ClearUpdateSchedule();
3634 parentPrim.LinkToGroup(childPrim); 3942 parentPrim.LinkToGroup(childPrim, true);
3635 } 3943 }
3636 3944
3637 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3945 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3650,16 +3958,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3650 m_host.AddScriptLPS(1); 3958 m_host.AddScriptLPS(1);
3651 UUID invItemID = InventorySelf(); 3959 UUID invItemID = InventorySelf();
3652 3960
3653 lock (m_host.TaskInventory) 3961 m_host.TaskInventory.LockItemsForRead(true);
3654 {
3655 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3962 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3656 && !m_automaticLinkPermission) 3963 && !m_automaticLinkPermission)
3657 { 3964 {
3658 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 3965 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
3966 m_host.TaskInventory.LockItemsForRead(false);
3659 return; 3967 return;
3660 } 3968 }
3661 } 3969 m_host.TaskInventory.LockItemsForRead(false);
3662 3970
3663 if (linknum < ScriptBaseClass.LINK_THIS) 3971 if (linknum < ScriptBaseClass.LINK_THIS)
3664 return; 3972 return;
3665 3973
@@ -3698,10 +4006,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3698 // Restructuring Multiple Prims. 4006 // Restructuring Multiple Prims.
3699 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4007 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3700 parts.Remove(parentPrim.RootPart); 4008 parts.Remove(parentPrim.RootPart);
3701 foreach (SceneObjectPart part in parts) 4009 if (parts.Count > 0)
3702 { 4010 {
3703 parentPrim.DelinkFromGroup(part.LocalId, true); 4011 try
4012 {
4013 parts[0].ParentGroup.areUpdatesSuspended = true;
4014 foreach (SceneObjectPart part in parts)
4015 {
4016 parentPrim.DelinkFromGroup(part.LocalId, true);
4017 }
4018 }
4019 finally
4020 {
4021 parts[0].ParentGroup.areUpdatesSuspended = false;
4022 }
3704 } 4023 }
4024
3705 parentPrim.HasGroupChanged = true; 4025 parentPrim.HasGroupChanged = true;
3706 parentPrim.ScheduleGroupForFullUpdate(); 4026 parentPrim.ScheduleGroupForFullUpdate();
3707 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4027 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3710,12 +4030,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3710 { 4030 {
3711 SceneObjectPart newRoot = parts[0]; 4031 SceneObjectPart newRoot = parts[0];
3712 parts.Remove(newRoot); 4032 parts.Remove(newRoot);
3713 foreach (SceneObjectPart part in parts) 4033
4034 try
3714 { 4035 {
3715 // Required for linking 4036 parts[0].ParentGroup.areUpdatesSuspended = true;
3716 part.ClearUpdateSchedule(); 4037 foreach (SceneObjectPart part in parts)
3717 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4038 {
4039 part.ClearUpdateSchedule();
4040 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4041 }
3718 } 4042 }
4043 finally
4044 {
4045 parts[0].ParentGroup.areUpdatesSuspended = false;
4046 }
4047
4048
3719 newRoot.ParentGroup.HasGroupChanged = true; 4049 newRoot.ParentGroup.HasGroupChanged = true;
3720 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4050 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3721 } 4051 }
@@ -3735,6 +4065,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3735 public void llBreakAllLinks() 4065 public void llBreakAllLinks()
3736 { 4066 {
3737 m_host.AddScriptLPS(1); 4067 m_host.AddScriptLPS(1);
4068
4069 UUID invItemID = InventorySelf();
4070
4071 TaskInventoryItem item;
4072 m_host.TaskInventory.LockItemsForRead(true);
4073 item = m_host.TaskInventory[invItemID];
4074 m_host.TaskInventory.LockItemsForRead(false);
4075
4076 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4077 && !m_automaticLinkPermission)
4078 {
4079 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4080 return;
4081 }
4082
3738 SceneObjectGroup parentPrim = m_host.ParentGroup; 4083 SceneObjectGroup parentPrim = m_host.ParentGroup;
3739 if (parentPrim.AttachmentPoint != 0) 4084 if (parentPrim.AttachmentPoint != 0)
3740 return; // Fail silently if attached 4085 return; // Fail silently if attached
@@ -3754,25 +4099,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3754 public LSL_String llGetLinkKey(int linknum) 4099 public LSL_String llGetLinkKey(int linknum)
3755 { 4100 {
3756 m_host.AddScriptLPS(1); 4101 m_host.AddScriptLPS(1);
3757 List<UUID> keytable = new List<UUID>();
3758 // parse for sitting avatare-uuids
3759 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3760 {
3761 if (presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID))
3762 keytable.Add(presence.UUID);
3763 });
3764
3765 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3766 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3767 {
3768 return keytable[totalprims - linknum].ToString();
3769 }
3770
3771 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3772 {
3773 return m_host.UUID.ToString();
3774 }
3775
3776 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4102 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3777 if (part != null) 4103 if (part != null)
3778 { 4104 {
@@ -3780,6 +4106,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3780 } 4106 }
3781 else 4107 else
3782 { 4108 {
4109 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4110 {
4111 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4112
4113 if (linknum < 0)
4114 return UUID.Zero.ToString();
4115
4116 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4117 if (avatars.Count > linknum)
4118 {
4119 return avatars[linknum].UUID.ToString();
4120 }
4121 }
3783 return UUID.Zero.ToString(); 4122 return UUID.Zero.ToString();
3784 } 4123 }
3785 } 4124 }
@@ -3878,17 +4217,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3878 m_host.AddScriptLPS(1); 4217 m_host.AddScriptLPS(1);
3879 int count = 0; 4218 int count = 0;
3880 4219
3881 lock (m_host.TaskInventory) 4220 m_host.TaskInventory.LockItemsForRead(true);
4221 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3882 { 4222 {
3883 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4223 if (inv.Value.Type == type || type == -1)
3884 { 4224 {
3885 if (inv.Value.Type == type || type == -1) 4225 count = count + 1;
3886 {
3887 count = count + 1;
3888 }
3889 } 4226 }
3890 } 4227 }
3891 4228
4229 m_host.TaskInventory.LockItemsForRead(false);
3892 return count; 4230 return count;
3893 } 4231 }
3894 4232
@@ -3897,16 +4235,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3897 m_host.AddScriptLPS(1); 4235 m_host.AddScriptLPS(1);
3898 ArrayList keys = new ArrayList(); 4236 ArrayList keys = new ArrayList();
3899 4237
3900 lock (m_host.TaskInventory) 4238 m_host.TaskInventory.LockItemsForRead(true);
4239 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3901 { 4240 {
3902 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4241 if (inv.Value.Type == type || type == -1)
3903 { 4242 {
3904 if (inv.Value.Type == type || type == -1) 4243 keys.Add(inv.Value.Name);
3905 {
3906 keys.Add(inv.Value.Name);
3907 }
3908 } 4244 }
3909 } 4245 }
4246 m_host.TaskInventory.LockItemsForRead(false);
3910 4247
3911 if (keys.Count == 0) 4248 if (keys.Count == 0)
3912 { 4249 {
@@ -3943,25 +4280,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3943 } 4280 }
3944 4281
3945 // move the first object found with this inventory name 4282 // move the first object found with this inventory name
3946 lock (m_host.TaskInventory) 4283 m_host.TaskInventory.LockItemsForRead(true);
4284 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3947 { 4285 {
3948 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4286 if (inv.Value.Name == inventory)
3949 { 4287 {
3950 if (inv.Value.Name == inventory) 4288 found = true;
3951 { 4289 objId = inv.Key;
3952 found = true; 4290 assetType = inv.Value.Type;
3953 objId = inv.Key; 4291 objName = inv.Value.Name;
3954 assetType = inv.Value.Type; 4292 break;
3955 objName = inv.Value.Name;
3956 break;
3957 }
3958 } 4293 }
3959 } 4294 }
4295 m_host.TaskInventory.LockItemsForRead(false);
3960 4296
3961 if (!found) 4297 if (!found)
3962 { 4298 {
3963 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4299 llSay(0, String.Format("Could not find object '{0}'", inventory));
3964 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4300 return;
4301// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3965 } 4302 }
3966 4303
3967 // check if destination is an object 4304 // check if destination is an object
@@ -3987,48 +4324,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3987 return; 4324 return;
3988 } 4325 }
3989 } 4326 }
4327
3990 // destination is an avatar 4328 // destination is an avatar
3991 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4329 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3992 4330
3993 if (agentItem == null) 4331 if (agentItem == null)
3994 return; 4332 return;
3995 4333
3996 byte[] bucket = new byte[17]; 4334 byte[] bucket = new byte[1];
3997 bucket[0] = (byte)assetType; 4335 bucket[0] = (byte)assetType;
3998 byte[] objBytes = agentItem.ID.GetBytes(); 4336 //byte[] objBytes = agentItem.ID.GetBytes();
3999 Array.Copy(objBytes, 0, bucket, 1, 16); 4337 //Array.Copy(objBytes, 0, bucket, 1, 16);
4000 4338
4001 GridInstantMessage msg = new GridInstantMessage(World, 4339 GridInstantMessage msg = new GridInstantMessage(World,
4002 m_host.UUID, m_host.Name+", an object owned by "+ 4340 m_host.OwnerID, m_host.Name, destId,
4003 resolveName(m_host.OwnerID)+",", destId,
4004 (byte)InstantMessageDialog.TaskInventoryOffered, 4341 (byte)InstantMessageDialog.TaskInventoryOffered,
4005 false, objName+"\n"+m_host.Name+" is located at "+ 4342 false, objName+". "+m_host.Name+" is located at "+
4006 World.RegionInfo.RegionName+" "+ 4343 World.RegionInfo.RegionName+" "+
4007 m_host.AbsolutePosition.ToString(), 4344 m_host.AbsolutePosition.ToString(),
4008 agentItem.ID, true, m_host.AbsolutePosition, 4345 agentItem.ID, true, m_host.AbsolutePosition,
4009 bucket); 4346 bucket);
4010 if (m_TransferModule != null) 4347
4011 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4348 ScenePresence sp;
4349
4350 if (World.TryGetScenePresence(destId, out sp))
4351 {
4352 sp.ControllingClient.SendInstantMessage(msg);
4353 }
4354 else
4355 {
4356 if (m_TransferModule != null)
4357 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4358 }
4359
4360 //This delay should only occur when giving inventory to avatars.
4012 ScriptSleep(3000); 4361 ScriptSleep(3000);
4013 } 4362 }
4014 } 4363 }
4015 4364
4365 [DebuggerNonUserCode]
4016 public void llRemoveInventory(string name) 4366 public void llRemoveInventory(string name)
4017 { 4367 {
4018 m_host.AddScriptLPS(1); 4368 m_host.AddScriptLPS(1);
4019 4369
4020 lock (m_host.TaskInventory) 4370 List<TaskInventoryItem> inv;
4371 try
4021 { 4372 {
4022 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4373 m_host.TaskInventory.LockItemsForRead(true);
4374 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4375 }
4376 finally
4377 {
4378 m_host.TaskInventory.LockItemsForRead(false);
4379 }
4380 foreach (TaskInventoryItem item in inv)
4381 {
4382 if (item.Name == name)
4023 { 4383 {
4024 if (item.Name == name) 4384 if (item.ItemID == m_itemID)
4025 { 4385 throw new ScriptDeleteException();
4026 if (item.ItemID == m_itemID) 4386 else
4027 throw new ScriptDeleteException(); 4387 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4028 else 4388 return;
4029 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4030 return;
4031 }
4032 } 4389 }
4033 } 4390 }
4034 } 4391 }
@@ -4063,112 +4420,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4063 { 4420 {
4064 m_host.AddScriptLPS(1); 4421 m_host.AddScriptLPS(1);
4065 4422
4066 UUID uuid = (UUID)id; 4423 UUID uuid;
4067 PresenceInfo pinfo = null; 4424 if (UUID.TryParse(id, out uuid))
4068 UserAccount account;
4069
4070 UserInfoCacheEntry ce;
4071 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4072 { 4425 {
4073 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4426 PresenceInfo pinfo = null;
4074 if (account == null) 4427 UserAccount account;
4428
4429 UserInfoCacheEntry ce;
4430 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4075 { 4431 {
4076 m_userInfoCache[uuid] = null; // Cache negative 4432 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4077 return UUID.Zero.ToString(); 4433 if (account == null)
4078 } 4434 {
4435 m_userInfoCache[uuid] = null; // Cache negative
4436 return UUID.Zero.ToString();
4437 }
4079 4438
4080 4439
4081 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4440 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4082 if (pinfos != null && pinfos.Length > 0) 4441 if (pinfos != null && pinfos.Length > 0)
4083 {
4084 foreach (PresenceInfo p in pinfos)
4085 { 4442 {
4086 if (p.RegionID != UUID.Zero) 4443 foreach (PresenceInfo p in pinfos)
4087 { 4444 {
4088 pinfo = p; 4445 if (p.RegionID != UUID.Zero)
4446 {
4447 pinfo = p;
4448 }
4089 } 4449 }
4090 } 4450 }
4091 }
4092 4451
4093 ce = new UserInfoCacheEntry(); 4452 ce = new UserInfoCacheEntry();
4094 ce.time = Util.EnvironmentTickCount(); 4453 ce.time = Util.EnvironmentTickCount();
4095 ce.account = account; 4454 ce.account = account;
4096 ce.pinfo = pinfo; 4455 ce.pinfo = pinfo;
4097 } 4456 m_userInfoCache[uuid] = ce;
4098 else 4457 }
4099 { 4458 else
4100 if (ce == null) 4459 {
4101 return UUID.Zero.ToString(); 4460 if (ce == null)
4461 return UUID.Zero.ToString();
4102 4462
4103 account = ce.account; 4463 account = ce.account;
4104 pinfo = ce.pinfo; 4464 pinfo = ce.pinfo;
4105 } 4465 }
4106 4466
4107 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4467 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4108 {
4109 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4110 if (pinfos != null && pinfos.Length > 0)
4111 { 4468 {
4112 foreach (PresenceInfo p in pinfos) 4469 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4470 if (pinfos != null && pinfos.Length > 0)
4113 { 4471 {
4114 if (p.RegionID != UUID.Zero) 4472 foreach (PresenceInfo p in pinfos)
4115 { 4473 {
4116 pinfo = p; 4474 if (p.RegionID != UUID.Zero)
4475 {
4476 pinfo = p;
4477 }
4117 } 4478 }
4118 } 4479 }
4119 } 4480 else
4120 else 4481 pinfo = null;
4121 pinfo = null;
4122 4482
4123 ce.time = Util.EnvironmentTickCount(); 4483 ce.time = Util.EnvironmentTickCount();
4124 ce.pinfo = pinfo; 4484 ce.pinfo = pinfo;
4125 } 4485 }
4126 4486
4127 string reply = String.Empty; 4487 string reply = String.Empty;
4128 4488
4129 switch (data) 4489 switch (data)
4130 { 4490 {
4131 case 1: // DATA_ONLINE (0|1) 4491 case 1: // DATA_ONLINE (0|1)
4132 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4492 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4133 reply = "1"; 4493 reply = "1";
4134 else 4494 else
4135 reply = "0"; 4495 reply = "0";
4136 break; 4496 break;
4137 case 2: // DATA_NAME (First Last) 4497 case 2: // DATA_NAME (First Last)
4138 reply = account.FirstName + " " + account.LastName; 4498 reply = account.FirstName + " " + account.LastName;
4139 break; 4499 break;
4140 case 3: // DATA_BORN (YYYY-MM-DD) 4500 case 3: // DATA_BORN (YYYY-MM-DD)
4141 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4501 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4142 born = born.AddSeconds(account.Created); 4502 born = born.AddSeconds(account.Created);
4143 reply = born.ToString("yyyy-MM-dd"); 4503 reply = born.ToString("yyyy-MM-dd");
4144 break; 4504 break;
4145 case 4: // DATA_RATING (0,0,0,0,0,0) 4505 case 4: // DATA_RATING (0,0,0,0,0,0)
4146 reply = "0,0,0,0,0,0"; 4506 reply = "0,0,0,0,0,0";
4147 break; 4507 break;
4148 case 8: // DATA_PAYINFO (0|1|2|3) 4508 case 8: // DATA_PAYINFO (0|1|2|3)
4149 reply = "0"; 4509 reply = "0";
4150 break; 4510 break;
4151 default: 4511 default:
4152 return UUID.Zero.ToString(); // Raise no event 4512 return UUID.Zero.ToString(); // Raise no event
4153 } 4513 }
4154 4514
4155 UUID rq = UUID.Random(); 4515 UUID rq = UUID.Random();
4156 4516
4157 UUID tid = AsyncCommands. 4517 UUID tid = AsyncCommands.
4158 DataserverPlugin.RegisterRequest(m_localID, 4518 DataserverPlugin.RegisterRequest(m_localID,
4159 m_itemID, rq.ToString()); 4519 m_itemID, rq.ToString());
4160 4520
4161 AsyncCommands. 4521 AsyncCommands.
4162 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4522 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4163 4523
4164 ScriptSleep(100); 4524 ScriptSleep(100);
4165 return tid.ToString(); 4525 return tid.ToString();
4526 }
4527 else
4528 {
4529 ShoutError("Invalid UUID passed to llRequestAgentData.");
4530 }
4531 return "";
4166 } 4532 }
4167 4533
4168 public LSL_String llRequestInventoryData(string name) 4534 public LSL_String llRequestInventoryData(string name)
4169 { 4535 {
4170 m_host.AddScriptLPS(1); 4536 m_host.AddScriptLPS(1);
4171 4537
4538 //Clone is thread safe
4172 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4539 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4173 4540
4174 foreach (TaskInventoryItem item in itemDictionary.Values) 4541 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4222,6 +4589,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4222 ScenePresence presence = World.GetScenePresence(agentId); 4589 ScenePresence presence = World.GetScenePresence(agentId);
4223 if (presence != null) 4590 if (presence != null)
4224 { 4591 {
4592 // agent must not be a god
4593 if (presence.UserLevel >= 200) return;
4594
4225 // agent must be over the owners land 4595 // agent must be over the owners land
4226 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4596 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4227 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4597 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
@@ -4244,7 +4614,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4244 UUID av = new UUID(); 4614 UUID av = new UUID();
4245 if (!UUID.TryParse(agent,out av)) 4615 if (!UUID.TryParse(agent,out av))
4246 { 4616 {
4247 LSLError("First parameter to llDialog needs to be a key"); 4617 //LSLError("First parameter to llDialog needs to be a key");
4248 return; 4618 return;
4249 } 4619 }
4250 4620
@@ -4281,17 +4651,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4281 UUID soundId = UUID.Zero; 4651 UUID soundId = UUID.Zero;
4282 if (!UUID.TryParse(impact_sound, out soundId)) 4652 if (!UUID.TryParse(impact_sound, out soundId))
4283 { 4653 {
4284 lock (m_host.TaskInventory) 4654 m_host.TaskInventory.LockItemsForRead(true);
4655 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4285 { 4656 {
4286 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4657 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4287 { 4658 {
4288 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4659 soundId = item.AssetID;
4289 { 4660 break;
4290 soundId = item.AssetID;
4291 break;
4292 }
4293 } 4661 }
4294 } 4662 }
4663 m_host.TaskInventory.LockItemsForRead(false);
4295 } 4664 }
4296 m_host.CollisionSound = soundId; 4665 m_host.CollisionSound = soundId;
4297 m_host.CollisionSoundVolume = (float)impact_volume; 4666 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4331,6 +4700,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4331 UUID partItemID; 4700 UUID partItemID;
4332 foreach (SceneObjectPart part in parts) 4701 foreach (SceneObjectPart part in parts)
4333 { 4702 {
4703 //Clone is thread safe
4334 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4704 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4335 4705
4336 foreach (TaskInventoryItem item in itemsDictionary.Values) 4706 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4545,17 +4915,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4545 4915
4546 m_host.AddScriptLPS(1); 4916 m_host.AddScriptLPS(1);
4547 4917
4548 lock (m_host.TaskInventory) 4918 m_host.TaskInventory.LockItemsForRead(true);
4919 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4549 { 4920 {
4550 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4921 if (item.Type == 10 && item.ItemID == m_itemID)
4551 { 4922 {
4552 if (item.Type == 10 && item.ItemID == m_itemID) 4923 result = item.Name!=null?item.Name:String.Empty;
4553 { 4924 break;
4554 result = item.Name != null ? item.Name : String.Empty;
4555 break;
4556 }
4557 } 4925 }
4558 } 4926 }
4927 m_host.TaskInventory.LockItemsForRead(false);
4559 4928
4560 return result; 4929 return result;
4561 } 4930 }
@@ -4728,23 +5097,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4728 { 5097 {
4729 m_host.AddScriptLPS(1); 5098 m_host.AddScriptLPS(1);
4730 5099
4731 lock (m_host.TaskInventory) 5100 m_host.TaskInventory.LockItemsForRead(true);
5101 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4732 { 5102 {
4733 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5103 if (inv.Value.Name == name)
4734 { 5104 {
4735 if (inv.Value.Name == name) 5105 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4736 { 5106 {
4737 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5107 m_host.TaskInventory.LockItemsForRead(false);
4738 { 5108 return inv.Value.AssetID.ToString();
4739 return inv.Value.AssetID.ToString(); 5109 }
4740 } 5110 else
4741 else 5111 {
4742 { 5112 m_host.TaskInventory.LockItemsForRead(false);
4743 return UUID.Zero.ToString(); 5113 return UUID.Zero.ToString();
4744 }
4745 } 5114 }
4746 } 5115 }
4747 } 5116 }
5117 m_host.TaskInventory.LockItemsForRead(false);
4748 5118
4749 return UUID.Zero.ToString(); 5119 return UUID.Zero.ToString();
4750 } 5120 }
@@ -4897,14 +5267,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4897 { 5267 {
4898 m_host.AddScriptLPS(1); 5268 m_host.AddScriptLPS(1);
4899 5269
4900 if (src == null) 5270 return src.Length;
4901 {
4902 return 0;
4903 }
4904 else
4905 {
4906 return src.Length;
4907 }
4908 } 5271 }
4909 5272
4910 public LSL_Integer llList2Integer(LSL_List src, int index) 5273 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4950,7 +5313,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4950 else if (src.Data[index] is LSL_Float) 5313 else if (src.Data[index] is LSL_Float)
4951 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5314 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4952 else if (src.Data[index] is LSL_String) 5315 else if (src.Data[index] is LSL_String)
4953 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5316 {
5317 string str = ((LSL_String) src.Data[index]).m_string;
5318 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5319 if (m != Match.Empty)
5320 {
5321 str = m.Value;
5322 double d = 0.0;
5323 if (!Double.TryParse(str, out d))
5324 return 0.0;
5325
5326 return d;
5327 }
5328 return 0.0;
5329 }
4954 return Convert.ToDouble(src.Data[index]); 5330 return Convert.ToDouble(src.Data[index]);
4955 } 5331 }
4956 catch (FormatException) 5332 catch (FormatException)
@@ -5223,7 +5599,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5223 } 5599 }
5224 } 5600 }
5225 } 5601 }
5226 else { 5602 else
5603 {
5227 object[] array = new object[src.Length]; 5604 object[] array = new object[src.Length];
5228 Array.Copy(src.Data, 0, array, 0, src.Length); 5605 Array.Copy(src.Data, 0, array, 0, src.Length);
5229 result = new LSL_List(array); 5606 result = new LSL_List(array);
@@ -5672,10 +6049,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5672 m_host.AddScriptLPS(1); 6049 m_host.AddScriptLPS(1);
5673 6050
5674 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6051 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5675 6052 if (parts.Count > 0)
5676 foreach (var part in parts)
5677 { 6053 {
5678 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 }
5679 } 6066 }
5680 } 6067 }
5681 6068
@@ -5727,13 +6114,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5727 6114
5728 if (m_host.OwnerID == land.LandData.OwnerID) 6115 if (m_host.OwnerID == land.LandData.OwnerID)
5729 { 6116 {
5730 World.TeleportClientHome(agentID, presence.ControllingClient); 6117 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6118 presence.TeleportWithMomentum(pos);
6119 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5731 } 6120 }
5732 } 6121 }
5733 } 6122 }
5734 ScriptSleep(5000); 6123 ScriptSleep(5000);
5735 } 6124 }
5736 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
5737 public LSL_Integer llOverMyLand(string id) 6131 public LSL_Integer llOverMyLand(string id)
5738 { 6132 {
5739 m_host.AddScriptLPS(1); 6133 m_host.AddScriptLPS(1);
@@ -5798,8 +6192,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5798 UUID agentId = new UUID(); 6192 UUID agentId = new UUID();
5799 if (!UUID.TryParse(agent, out agentId)) 6193 if (!UUID.TryParse(agent, out agentId))
5800 return new LSL_Integer(0); 6194 return new LSL_Integer(0);
6195 if (agentId == m_host.GroupID)
6196 return new LSL_Integer(1);
5801 ScenePresence presence = World.GetScenePresence(agentId); 6197 ScenePresence presence = World.GetScenePresence(agentId);
5802 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6198 if (presence == null || presence.IsChildAgent) // Return false for child agents
5803 return new LSL_Integer(0); 6199 return new LSL_Integer(0);
5804 IClientAPI client = presence.ControllingClient; 6200 IClientAPI client = presence.ControllingClient;
5805 if (m_host.GroupID == client.ActiveGroupId) 6201 if (m_host.GroupID == client.ActiveGroupId)
@@ -5934,7 +6330,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5934 return m_host.ParentGroup.AttachmentPoint; 6330 return m_host.ParentGroup.AttachmentPoint;
5935 } 6331 }
5936 6332
5937 public LSL_Integer llGetFreeMemory() 6333 public virtual LSL_Integer llGetFreeMemory()
5938 { 6334 {
5939 m_host.AddScriptLPS(1); 6335 m_host.AddScriptLPS(1);
5940 // Make scripts designed for LSO happy 6336 // Make scripts designed for LSO happy
@@ -6051,7 +6447,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6051 SetParticleSystem(m_host, rules); 6447 SetParticleSystem(m_host, rules);
6052 } 6448 }
6053 6449
6054 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6450 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6451 {
6055 6452
6056 6453
6057 if (rules.Length == 0) 6454 if (rules.Length == 0)
@@ -6245,14 +6642,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6245 6642
6246 protected UUID GetTaskInventoryItem(string name) 6643 protected UUID GetTaskInventoryItem(string name)
6247 { 6644 {
6248 lock (m_host.TaskInventory) 6645 m_host.TaskInventory.LockItemsForRead(true);
6646 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6249 { 6647 {
6250 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6648 if (inv.Value.Name == name)
6251 { 6649 {
6252 if (inv.Value.Name == name) 6650 m_host.TaskInventory.LockItemsForRead(false);
6253 return inv.Key; 6651 return inv.Key;
6254 } 6652 }
6255 } 6653 }
6654 m_host.TaskInventory.LockItemsForRead(false);
6256 6655
6257 return UUID.Zero; 6656 return UUID.Zero;
6258 } 6657 }
@@ -6290,16 +6689,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6290 if (folderID == UUID.Zero) 6689 if (folderID == UUID.Zero)
6291 return; 6690 return;
6292 6691
6293 byte[] bucket = new byte[17]; 6692 byte[] bucket = new byte[1];
6294 bucket[0] = (byte)AssetType.Folder; 6693 bucket[0] = (byte)AssetType.Folder;
6295 byte[] objBytes = folderID.GetBytes(); 6694 //byte[] objBytes = folderID.GetBytes();
6296 Array.Copy(objBytes, 0, bucket, 1, 16); 6695 //Array.Copy(objBytes, 0, bucket, 1, 16);
6297 6696
6298 GridInstantMessage msg = new GridInstantMessage(World, 6697 GridInstantMessage msg = new GridInstantMessage(World,
6299 m_host.UUID, m_host.Name+", an object owned by "+ 6698 m_host.OwnerID, m_host.Name, destID,
6300 resolveName(m_host.OwnerID)+",", destID, 6699 (byte)InstantMessageDialog.TaskInventoryOffered,
6301 (byte)InstantMessageDialog.InventoryOffered, 6700 false, category+". "+m_host.Name+" is located at "+
6302 false, category+"\n"+m_host.Name+" is located at "+
6303 World.RegionInfo.RegionName+" "+ 6701 World.RegionInfo.RegionName+" "+
6304 m_host.AbsolutePosition.ToString(), 6702 m_host.AbsolutePosition.ToString(),
6305 folderID, true, m_host.AbsolutePosition, 6703 folderID, true, m_host.AbsolutePosition,
@@ -6515,13 +6913,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6515 UUID av = new UUID(); 6913 UUID av = new UUID();
6516 if (!UUID.TryParse(avatar,out av)) 6914 if (!UUID.TryParse(avatar,out av))
6517 { 6915 {
6518 LSLError("First parameter to llDialog needs to be a key"); 6916 //LSLError("First parameter to llDialog needs to be a key");
6519 return; 6917 return;
6520 } 6918 }
6521 if (buttons.Length < 1) 6919 if (buttons.Length < 1)
6522 { 6920 {
6523 LSLError("No less than 1 button can be shown"); 6921 buttons.Add("OK");
6524 return;
6525 } 6922 }
6526 if (buttons.Length > 12) 6923 if (buttons.Length > 12)
6527 { 6924 {
@@ -6538,7 +6935,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6538 } 6935 }
6539 if (buttons.Data[i].ToString().Length > 24) 6936 if (buttons.Data[i].ToString().Length > 24)
6540 { 6937 {
6541 LSLError("button label cannot be longer than 24 characters"); 6938 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6542 return; 6939 return;
6543 } 6940 }
6544 buts[i] = buttons.Data[i].ToString(); 6941 buts[i] = buttons.Data[i].ToString();
@@ -6597,22 +6994,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6597 } 6994 }
6598 6995
6599 // copy the first script found with this inventory name 6996 // copy the first script found with this inventory name
6600 lock (m_host.TaskInventory) 6997 TaskInventoryItem scriptItem = null;
6998 m_host.TaskInventory.LockItemsForRead(true);
6999 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6601 { 7000 {
6602 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 7001 if (inv.Value.Name == name)
6603 { 7002 {
6604 if (inv.Value.Name == name) 7003 // make sure the object is a script
7004 if (10 == inv.Value.Type)
6605 { 7005 {
6606 // make sure the object is a script 7006 found = true;
6607 if (10 == inv.Value.Type) 7007 srcId = inv.Key;
6608 { 7008 scriptItem = inv.Value;
6609 found = true; 7009 break;
6610 srcId = inv.Key;
6611 break;
6612 }
6613 } 7010 }
6614 } 7011 }
6615 } 7012 }
7013 m_host.TaskInventory.LockItemsForRead(false);
6616 7014
6617 if (!found) 7015 if (!found)
6618 { 7016 {
@@ -6620,9 +7018,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6620 return; 7018 return;
6621 } 7019 }
6622 7020
6623 // the rest of the permission checks are done in RezScript, so check the pin there as well 7021 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6624 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7022 if (dest != null)
7023 {
7024 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7025 {
7026 // the rest of the permission checks are done in RezScript, so check the pin there as well
7027 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6625 7028
7029 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7030 m_host.Inventory.RemoveInventoryItem(srcId);
7031 }
7032 }
6626 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7033 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6627 ScriptSleep(3000); 7034 ScriptSleep(3000);
6628 } 7035 }
@@ -6685,19 +7092,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6685 public LSL_String llMD5String(string src, int nonce) 7092 public LSL_String llMD5String(string src, int nonce)
6686 { 7093 {
6687 m_host.AddScriptLPS(1); 7094 m_host.AddScriptLPS(1);
6688 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7095 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6689 } 7096 }
6690 7097
6691 public LSL_String llSHA1String(string src) 7098 public LSL_String llSHA1String(string src)
6692 { 7099 {
6693 m_host.AddScriptLPS(1); 7100 m_host.AddScriptLPS(1);
6694 return Util.SHA1Hash(src).ToLower(); 7101 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6695 } 7102 }
6696 7103
6697 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7104 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6698 { 7105 {
6699 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7106 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6700 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7107 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7108 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7109 return shapeBlock;
6701 7110
6702 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7111 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6703 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7112 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6802,6 +7211,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6802 // Prim type box, cylinder and prism. 7211 // Prim type box, cylinder and prism.
6803 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) 7212 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)
6804 { 7213 {
7214 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7215 return;
7216
6805 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7217 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6806 ObjectShapePacket.ObjectDataBlock shapeBlock; 7218 ObjectShapePacket.ObjectDataBlock shapeBlock;
6807 7219
@@ -6855,6 +7267,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6855 // Prim type sphere. 7267 // Prim type sphere.
6856 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7268 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6857 { 7269 {
7270 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7271 return;
7272
6858 ObjectShapePacket.ObjectDataBlock shapeBlock; 7273 ObjectShapePacket.ObjectDataBlock shapeBlock;
6859 7274
6860 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7275 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6896,6 +7311,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6896 // Prim type torus, tube and ring. 7311 // Prim type torus, tube and ring.
6897 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) 7312 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)
6898 { 7313 {
7314 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7315 return;
7316
6899 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7317 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6900 ObjectShapePacket.ObjectDataBlock shapeBlock; 7318 ObjectShapePacket.ObjectDataBlock shapeBlock;
6901 7319
@@ -7031,6 +7449,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7031 // Prim type sculpt. 7449 // Prim type sculpt.
7032 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7450 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7033 { 7451 {
7452 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7453 return;
7454
7034 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7455 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7035 UUID sculptId; 7456 UUID sculptId;
7036 7457
@@ -7047,13 +7468,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7047 shapeBlock.PathScaleX = 100; 7468 shapeBlock.PathScaleX = 100;
7048 shapeBlock.PathScaleY = 150; 7469 shapeBlock.PathScaleY = 150;
7049 7470
7050 if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER && 7471 if ((type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER) == 0 &&
7051 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE && 7472 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE) == 0 &&
7052 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE && 7473 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE) == 0 &&
7053 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) 7474 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) == 0)
7054 { 7475 {
7055 // default 7476 // default
7056 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7477 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7057 } 7478 }
7058 7479
7059 part.Shape.SetSculptProperties((byte)type, sculptId); 7480 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7069,32 +7490,87 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7069 ScriptSleep(200); 7490 ScriptSleep(200);
7070 } 7491 }
7071 7492
7072 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7493 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7073 { 7494 {
7074 m_host.AddScriptLPS(1); 7495 m_host.AddScriptLPS(1);
7075 7496
7076 setLinkPrimParams(linknumber, rules); 7497 setLinkPrimParams(linknumber, rules);
7077
7078 ScriptSleep(200);
7079 } 7498 }
7080 7499
7081 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7500 private void setLinkPrimParams(int linknumber, LSL_List rules)
7082 { 7501 {
7083 m_host.AddScriptLPS(1); 7502 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7503 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7504 if (parts.Count>0)
7505 {
7506 try
7507 {
7508 parts[0].ParentGroup.areUpdatesSuspended = true;
7509 foreach (SceneObjectPart part in parts)
7510 SetPrimParams(part, rules);
7511 }
7512 finally
7513 {
7514 parts[0].ParentGroup.areUpdatesSuspended = false;
7515 }
7516 }
7517 if (avatars.Count > 0)
7518 {
7519 foreach (ScenePresence avatar in avatars)
7520 SetPrimParams(avatar, rules);
7521 }
7522 }
7084 7523
7085 setLinkPrimParams(linknumber, rules); 7524 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7525 {
7526 llSetLinkPrimitiveParamsFast(linknumber, rules);
7527 ScriptSleep(200);
7086 } 7528 }
7087 7529
7088 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7530 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7089 { 7531 {
7090 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7532 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7533 //We only support PRIM_POSITION and PRIM_ROTATION
7091 7534
7092 foreach (SceneObjectPart part in parts) 7535 int idx = 0;
7093 SetPrimParams(part, rules); 7536
7537 while (idx < rules.Length)
7538 {
7539 int code = rules.GetLSLIntegerItem(idx++);
7540
7541 int remain = rules.Length - idx;
7542
7543
7544
7545 switch (code)
7546 {
7547 case (int)ScriptBaseClass.PRIM_POSITION:
7548 if (remain < 1)
7549 return;
7550 LSL_Vector v;
7551 v = rules.GetVector3Item(idx++);
7552 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7553 av.SendAvatarDataToAllAgents();
7554
7555 break;
7556
7557 case (int)ScriptBaseClass.PRIM_ROTATION:
7558 if (remain < 1)
7559 return;
7560 LSL_Rotation r;
7561 r = rules.GetQuaternionItem(idx++);
7562 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7563 av.SendAvatarDataToAllAgents();
7564 break;
7565 }
7566 }
7094 } 7567 }
7095 7568
7096 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7569 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7097 { 7570 {
7571 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7572 return;
7573
7098 int idx = 0; 7574 int idx = 0;
7099 7575
7100 bool positionChanged = false; 7576 bool positionChanged = false;
@@ -7122,6 +7598,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7122 currentPosition = GetSetPosTarget(part, v, currentPosition); 7598 currentPosition = GetSetPosTarget(part, v, currentPosition);
7123 7599
7124 break; 7600 break;
7601 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
7602 if (remain < 1)
7603 return;
7604
7605 v=rules.GetVector3Item(idx++);
7606 positionChanged = true;
7607 currentPosition = GetSetPosTarget(part, v, currentPosition);
7608
7609 break;
7125 case (int)ScriptBaseClass.PRIM_SIZE: 7610 case (int)ScriptBaseClass.PRIM_SIZE:
7126 if (remain < 1) 7611 if (remain < 1)
7127 return; 7612 return;
@@ -7499,6 +7984,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7499 } 7984 }
7500 } 7985 }
7501 } 7986 }
7987
7988 if (positionChanged)
7989 {
7990 if (part.ParentGroup.RootPart == part)
7991 {
7992 SceneObjectGroup parent = part.ParentGroup;
7993 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
7994 }
7995 else
7996 {
7997 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
7998 SceneObjectGroup parent = part.ParentGroup;
7999 parent.HasGroupChanged = true;
8000 parent.ScheduleGroupForTerseUpdate();
8001 }
8002 }
7502 } 8003 }
7503 8004
7504 public LSL_String llStringToBase64(string str) 8005 public LSL_String llStringToBase64(string str)
@@ -7659,13 +8160,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7659 public LSL_Integer llGetNumberOfPrims() 8160 public LSL_Integer llGetNumberOfPrims()
7660 { 8161 {
7661 m_host.AddScriptLPS(1); 8162 m_host.AddScriptLPS(1);
7662 int avatarCount = 0; 8163 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7663 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8164
7664 {
7665 if (presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID))
7666 avatarCount++;
7667 });
7668
7669 return m_host.ParentGroup.PrimCount + avatarCount; 8165 return m_host.ParentGroup.PrimCount + avatarCount;
7670 } 8166 }
7671 8167
@@ -7681,55 +8177,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7681 m_host.AddScriptLPS(1); 8177 m_host.AddScriptLPS(1);
7682 UUID objID = UUID.Zero; 8178 UUID objID = UUID.Zero;
7683 LSL_List result = new LSL_List(); 8179 LSL_List result = new LSL_List();
8180
8181 // If the ID is not valid, return null result
7684 if (!UUID.TryParse(obj, out objID)) 8182 if (!UUID.TryParse(obj, out objID))
7685 { 8183 {
7686 result.Add(new LSL_Vector()); 8184 result.Add(new LSL_Vector());
7687 result.Add(new LSL_Vector()); 8185 result.Add(new LSL_Vector());
7688 return result; 8186 return result;
7689 } 8187 }
8188
8189 // Check if this is an attached prim. If so, replace
8190 // the UUID with the avatar UUID and report it's bounding box
8191 SceneObjectPart part = World.GetSceneObjectPart(objID);
8192 if (part != null && part.ParentGroup.IsAttachment)
8193 objID = part.ParentGroup.AttachedAvatar;
8194
8195 // Find out if this is an avatar ID. If so, return it's box
7690 ScenePresence presence = World.GetScenePresence(objID); 8196 ScenePresence presence = World.GetScenePresence(objID);
7691 if (presence != null) 8197 if (presence != null)
7692 { 8198 {
7693 if (presence.ParentID == 0) // not sat on an object 8199 // As per LSL Wiki, there is no difference between sitting
8200 // and standing avatar since server 1.36
8201 LSL_Vector lower;
8202 LSL_Vector upper;
8203 if (presence.Animator.Animations.DefaultAnimation.AnimID
8204 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7694 { 8205 {
7695 LSL_Vector lower; 8206 // This is for ground sitting avatars
7696 LSL_Vector upper; 8207 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7697 if (presence.Animator.Animations.DefaultAnimation.AnimID 8208 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7698 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8209 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7699 {
7700 // This is for ground sitting avatars
7701 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7702 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7703 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7704 }
7705 else
7706 {
7707 // This is for standing/flying avatars
7708 float height = presence.Appearance.AvatarHeight / 2.0f;
7709 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7710 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7711 }
7712 result.Add(lower);
7713 result.Add(upper);
7714 return result;
7715 } 8210 }
7716 else 8211 else
7717 { 8212 {
7718 // sitting on an object so we need the bounding box of that 8213 // This is for standing/flying avatars
7719 // which should include the avatar so set the UUID to the 8214 float height = presence.Appearance.AvatarHeight / 2.0f;
7720 // UUID of the object the avatar is sat on and allow it to fall through 8215 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7721 // to processing an object 8216 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7722 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7723 objID = p.UUID;
7724 } 8217 }
8218
8219 // Adjust to the documented error offsets (see LSL Wiki)
8220 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8221 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8222
8223 if (lower.x > upper.x)
8224 lower.x = upper.x;
8225 if (lower.y > upper.y)
8226 lower.y = upper.y;
8227 if (lower.z > upper.z)
8228 lower.z = upper.z;
8229
8230 result.Add(lower);
8231 result.Add(upper);
8232 return result;
7725 } 8233 }
7726 SceneObjectPart part = World.GetSceneObjectPart(objID); 8234
8235 part = World.GetSceneObjectPart(objID);
7727 // Currently only works for single prims without a sitting avatar 8236 // Currently only works for single prims without a sitting avatar
7728 if (part != null) 8237 if (part != null)
7729 { 8238 {
7730 Vector3 halfSize = part.Scale / 2.0f; 8239 float minX;
7731 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8240 float maxX;
7732 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8241 float minY;
8242 float maxY;
8243 float minZ;
8244 float maxZ;
8245
8246 // This BBox is in sim coordinates, with the offset being
8247 // a contained point.
8248 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8249 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8250
8251 minX -= offsets[0].X;
8252 maxX -= offsets[0].X;
8253 minY -= offsets[0].Y;
8254 maxY -= offsets[0].Y;
8255 minZ -= offsets[0].Z;
8256 maxZ -= offsets[0].Z;
8257
8258 LSL_Vector lower;
8259 LSL_Vector upper;
8260
8261 // Adjust to the documented error offsets (see LSL Wiki)
8262 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8263 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8264
8265 if (lower.x > upper.x)
8266 lower.x = upper.x;
8267 if (lower.y > upper.y)
8268 lower.y = upper.y;
8269 if (lower.z > upper.z)
8270 lower.z = upper.z;
8271
7733 result.Add(lower); 8272 result.Add(lower);
7734 result.Add(upper); 8273 result.Add(upper);
7735 return result; 8274 return result;
@@ -7809,13 +8348,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7809 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8348 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7810 part.AbsolutePosition.Y, 8349 part.AbsolutePosition.Y,
7811 part.AbsolutePosition.Z); 8350 part.AbsolutePosition.Z);
7812 // For some reason, the part.AbsolutePosition.* values do not change if the
7813 // linkset is rotated; they always reflect the child prim's world position
7814 // as though the linkset is unrotated. This is incompatible behavior with SL's
7815 // implementation, so will break scripts imported from there (not to mention it
7816 // makes it more difficult to determine a child prim's actual inworld position).
7817 if (part.ParentID != 0)
7818 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7819 res.Add(v); 8351 res.Add(v);
7820 break; 8352 break;
7821 8353
@@ -7986,56 +8518,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7986 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8518 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7987 if (remain < 1) 8519 if (remain < 1)
7988 return res; 8520 return res;
7989 8521 face = (int)rules.GetLSLIntegerItem(idx++);
7990 face=(int)rules.GetLSLIntegerItem(idx++);
7991 8522
7992 tex = part.Shape.Textures; 8523 tex = part.Shape.Textures;
8524 int shiny;
7993 if (face == ScriptBaseClass.ALL_SIDES) 8525 if (face == ScriptBaseClass.ALL_SIDES)
7994 { 8526 {
7995 for (face = 0; face < GetNumberOfSides(part); face++) 8527 for (face = 0; face < GetNumberOfSides(part); face++)
7996 { 8528 {
7997 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8529 Shininess shinyness = tex.GetFace((uint)face).Shiny;
7998 // Convert Shininess to PRIM_SHINY_* 8530 if (shinyness == Shininess.High)
7999 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8531 {
8000 // PRIM_BUMP_* 8532 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8001 res.Add(new LSL_Integer((int)texface.Bump)); 8533 }
8534 else if (shinyness == Shininess.Medium)
8535 {
8536 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8537 }
8538 else if (shinyness == Shininess.Low)
8539 {
8540 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8541 }
8542 else
8543 {
8544 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8545 }
8546 res.Add(new LSL_Integer(shiny));
8547 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8002 } 8548 }
8003 } 8549 }
8004 else 8550 else
8005 { 8551 {
8006 if (face >= 0 && face < GetNumberOfSides(part)) 8552 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8553 if (shinyness == Shininess.High)
8007 { 8554 {
8008 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8555 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8009 // Convert Shininess to PRIM_SHINY_* 8556 }
8010 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8557 else if (shinyness == Shininess.Medium)
8011 // PRIM_BUMP_* 8558 {
8012 res.Add(new LSL_Integer((int)texface.Bump)); 8559 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8560 }
8561 else if (shinyness == Shininess.Low)
8562 {
8563 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8013 } 8564 }
8565 else
8566 {
8567 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8568 }
8569 res.Add(new LSL_Integer(shiny));
8570 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8014 } 8571 }
8015 break; 8572 break;
8016 8573
8017 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8574 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8018 if (remain < 1) 8575 if (remain < 1)
8019 return res; 8576 return res;
8020 8577 face = (int)rules.GetLSLIntegerItem(idx++);
8021 face=(int)rules.GetLSLIntegerItem(idx++);
8022 8578
8023 tex = part.Shape.Textures; 8579 tex = part.Shape.Textures;
8580 int fullbright;
8024 if (face == ScriptBaseClass.ALL_SIDES) 8581 if (face == ScriptBaseClass.ALL_SIDES)
8025 { 8582 {
8026 for (face = 0; face < GetNumberOfSides(part); face++) 8583 for (face = 0; face < GetNumberOfSides(part); face++)
8027 { 8584 {
8028 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8585 if (tex.GetFace((uint)face).Fullbright == true)
8029 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8586 {
8587 fullbright = ScriptBaseClass.TRUE;
8588 }
8589 else
8590 {
8591 fullbright = ScriptBaseClass.FALSE;
8592 }
8593 res.Add(new LSL_Integer(fullbright));
8030 } 8594 }
8031 } 8595 }
8032 else 8596 else
8033 { 8597 {
8034 if (face >= 0 && face < GetNumberOfSides(part)) 8598 if (tex.GetFace((uint)face).Fullbright == true)
8035 { 8599 {
8036 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8600 fullbright = ScriptBaseClass.TRUE;
8037 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
8038 } 8601 }
8602 else
8603 {
8604 fullbright = ScriptBaseClass.FALSE;
8605 }
8606 res.Add(new LSL_Integer(fullbright));
8039 } 8607 }
8040 break; 8608 break;
8041 8609
@@ -8057,27 +8625,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8057 break; 8625 break;
8058 8626
8059 case (int)ScriptBaseClass.PRIM_TEXGEN: 8627 case (int)ScriptBaseClass.PRIM_TEXGEN:
8628 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8060 if (remain < 1) 8629 if (remain < 1)
8061 return res; 8630 return res;
8062 8631 face = (int)rules.GetLSLIntegerItem(idx++);
8063 face=(int)rules.GetLSLIntegerItem(idx++);
8064 8632
8065 tex = part.Shape.Textures; 8633 tex = part.Shape.Textures;
8066 if (face == ScriptBaseClass.ALL_SIDES) 8634 if (face == ScriptBaseClass.ALL_SIDES)
8067 { 8635 {
8068 for (face = 0; face < GetNumberOfSides(part); face++) 8636 for (face = 0; face < GetNumberOfSides(part); face++)
8069 { 8637 {
8070 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8638 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8071 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8639 {
8072 res.Add(new LSL_Integer((uint)texgen >> 1)); 8640 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8641 }
8642 else
8643 {
8644 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8645 }
8073 } 8646 }
8074 } 8647 }
8075 else 8648 else
8076 { 8649 {
8077 if (face >= 0 && face < GetNumberOfSides(part)) 8650 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8078 { 8651 {
8079 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8652 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8080 res.Add(new LSL_Integer((uint)texgen >> 1)); 8653 }
8654 else
8655 {
8656 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8081 } 8657 }
8082 } 8658 }
8083 break; 8659 break;
@@ -8100,28 +8676,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8100 case (int)ScriptBaseClass.PRIM_GLOW: 8676 case (int)ScriptBaseClass.PRIM_GLOW:
8101 if (remain < 1) 8677 if (remain < 1)
8102 return res; 8678 return res;
8103 8679 face = (int)rules.GetLSLIntegerItem(idx++);
8104 face=(int)rules.GetLSLIntegerItem(idx++);
8105 8680
8106 tex = part.Shape.Textures; 8681 tex = part.Shape.Textures;
8682 float primglow;
8107 if (face == ScriptBaseClass.ALL_SIDES) 8683 if (face == ScriptBaseClass.ALL_SIDES)
8108 { 8684 {
8109 for (face = 0; face < GetNumberOfSides(part); face++) 8685 for (face = 0; face < GetNumberOfSides(part); face++)
8110 { 8686 {
8111 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8687 primglow = tex.GetFace((uint)face).Glow;
8112 res.Add(new LSL_Float(texface.Glow)); 8688 res.Add(new LSL_Float(primglow));
8113 } 8689 }
8114 } 8690 }
8115 else 8691 else
8116 { 8692 {
8117 if (face >= 0 && face < GetNumberOfSides(part)) 8693 primglow = tex.GetFace((uint)face).Glow;
8118 { 8694 res.Add(new LSL_Float(primglow));
8119 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8120 res.Add(new LSL_Float(texface.Glow));
8121 }
8122 } 8695 }
8123 break; 8696 break;
8124
8125 case (int)ScriptBaseClass.PRIM_TEXT: 8697 case (int)ScriptBaseClass.PRIM_TEXT:
8126 Color4 textColor = part.GetTextColor(); 8698 Color4 textColor = part.GetTextColor();
8127 res.Add(new LSL_String(part.Text)); 8699 res.Add(new LSL_String(part.Text));
@@ -8673,8 +9245,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8673 // The function returns an ordered list 9245 // The function returns an ordered list
8674 // representing the tokens found in the supplied 9246 // representing the tokens found in the supplied
8675 // sources string. If two successive tokenizers 9247 // sources string. If two successive tokenizers
8676 // are encountered, then a NULL entry is added 9248 // are encountered, then a null-string entry is
8677 // to the list. 9249 // added to the list.
8678 // 9250 //
8679 // It is a precondition that the source and 9251 // It is a precondition that the source and
8680 // toekizer lisst are non-null. If they are null, 9252 // toekizer lisst are non-null. If they are null,
@@ -8682,7 +9254,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8682 // while their lengths are being determined. 9254 // while their lengths are being determined.
8683 // 9255 //
8684 // A small amount of working memoryis required 9256 // A small amount of working memoryis required
8685 // of approximately 8*#tokenizers. 9257 // of approximately 8*#tokenizers + 8*srcstrlen.
8686 // 9258 //
8687 // There are many ways in which this function 9259 // There are many ways in which this function
8688 // can be implemented, this implementation is 9260 // can be implemented, this implementation is
@@ -8698,155 +9270,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8698 // and eliminates redundant tokenizers as soon 9270 // and eliminates redundant tokenizers as soon
8699 // as is possible. 9271 // as is possible.
8700 // 9272 //
8701 // The implementation tries to avoid any copying 9273 // The implementation tries to minimize temporary
8702 // of arrays or other objects. 9274 // garbage generation.
8703 // </remarks> 9275 // </remarks>
8704 9276
8705 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9277 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8706 { 9278 {
8707 int beginning = 0; 9279 return ParseString2List(src, separators, spacers, true);
8708 int srclen = src.Length; 9280 }
8709 int seplen = separators.Length;
8710 object[] separray = separators.Data;
8711 int spclen = spacers.Length;
8712 object[] spcarray = spacers.Data;
8713 int mlen = seplen+spclen;
8714
8715 int[] offset = new int[mlen+1];
8716 bool[] active = new bool[mlen];
8717
8718 int best;
8719 int j;
8720
8721 // Initial capacity reduces resize cost
8722 9281
8723 LSL_List tokens = new LSL_List(); 9282 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9283 {
9284 int srclen = src.Length;
9285 int seplen = separators.Length;
9286 object[] separray = separators.Data;
9287 int spclen = spacers.Length;
9288 object[] spcarray = spacers.Data;
9289 int dellen = 0;
9290 string[] delarray = new string[seplen+spclen];
8724 9291
8725 // All entries are initially valid 9292 int outlen = 0;
9293 string[] outarray = new string[srclen*2+1];
8726 9294
8727 for (int i = 0; i < mlen; i++) 9295 int i, j;
8728 active[i] = true; 9296 string d;
8729 9297
8730 offset[mlen] = srclen; 9298 m_host.AddScriptLPS(1);
8731 9299
8732 while (beginning < srclen) 9300 /*
9301 * Convert separator and spacer lists to C# strings.
9302 * Also filter out null strings so we don't hang.
9303 */
9304 for (i = 0; i < seplen; i ++)
8733 { 9305 {
9306 d = separray[i].ToString();
9307 if (d.Length > 0)
9308 {
9309 delarray[dellen++] = d;
9310 }
9311 }
9312 seplen = dellen;
8734 9313
8735 best = mlen; // as bad as it gets 9314 for (i = 0; i < spclen; i ++)
9315 {
9316 d = spcarray[i].ToString();
9317 if (d.Length > 0)
9318 {
9319 delarray[dellen++] = d;
9320 }
9321 }
8736 9322
8737 // Scan for separators 9323 /*
9324 * Scan through source string from beginning to end.
9325 */
9326 for (i = 0;;)
9327 {
8738 9328
8739 for (j = 0; j < seplen; j++) 9329 /*
9330 * Find earliest delimeter in src starting at i (if any).
9331 */
9332 int earliestDel = -1;
9333 int earliestSrc = srclen;
9334 string earliestStr = null;
9335 for (j = 0; j < dellen; j ++)
8740 { 9336 {
8741 if (separray[j].ToString() == String.Empty) 9337 d = delarray[j];
8742 active[j] = false; 9338 if (d != null)
8743
8744 if (active[j])
8745 { 9339 {
8746 // scan all of the markers 9340 int index = src.IndexOf(d, i);
8747 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9341 if (index < 0)
8748 { 9342 {
8749 // not present at all 9343 delarray[j] = null; // delim nowhere in src, don't check it anymore
8750 active[j] = false;
8751 } 9344 }
8752 else 9345 else if (index < earliestSrc)
8753 { 9346 {
8754 // present and correct 9347 earliestSrc = index; // where delimeter starts in source string
8755 if (offset[j] < offset[best]) 9348 earliestDel = j; // where delimeter is in delarray[]
8756 { 9349 earliestStr = d; // the delimeter string from delarray[]
8757 // closest so far 9350 if (index == i) break; // can't do any better than found at beg of string
8758 best = j;
8759 if (offset[best] == beginning)
8760 break;
8761 }
8762 } 9351 }
8763 } 9352 }
8764 } 9353 }
8765 9354
8766 // Scan for spacers 9355 /*
8767 9356 * Output source string starting at i through start of earliest delimeter.
8768 if (offset[best] != beginning) 9357 */
9358 if (keepNulls || (earliestSrc > i))
8769 { 9359 {
8770 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9360 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8771 {
8772 if (spcarray[j-seplen].ToString() == String.Empty)
8773 active[j] = false;
8774
8775 if (active[j])
8776 {
8777 // scan all of the markers
8778 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8779 {
8780 // not present at all
8781 active[j] = false;
8782 }
8783 else
8784 {
8785 // present and correct
8786 if (offset[j] < offset[best])
8787 {
8788 // closest so far
8789 best = j;
8790 }
8791 }
8792 }
8793 }
8794 } 9361 }
8795 9362
8796 // This is the normal exit from the scanning loop 9363 /*
9364 * If no delimeter found at or after i, we're done scanning.
9365 */
9366 if (earliestDel < 0) break;
8797 9367
8798 if (best == mlen) 9368 /*
9369 * If delimeter was a spacer, output the spacer.
9370 */
9371 if (earliestDel >= seplen)
8799 { 9372 {
8800 // no markers were found on this pass 9373 outarray[outlen++] = earliestStr;
8801 // so we're pretty much done
8802 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8803 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8804 break;
8805 } 9374 }
8806 9375
8807 // Otherwise we just add the newly delimited token 9376 /*
8808 // and recalculate where the search should continue. 9377 * Look at rest of src string following delimeter.
8809 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9378 */
8810 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9379 i = earliestSrc + earliestStr.Length;
8811
8812 if (best < seplen)
8813 {
8814 beginning = offset[best] + (separray[best].ToString()).Length;
8815 }
8816 else
8817 {
8818 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8819 string str = spcarray[best - seplen].ToString();
8820 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8821 tokens.Add(new LSL_String(str));
8822 }
8823 } 9380 }
8824 9381
8825 // This an awkward an not very intuitive boundary case. If the 9382 /*
8826 // last substring is a tokenizer, then there is an implied trailing 9383 * Make up an exact-sized output array suitable for an LSL_List object.
8827 // null list entry. Hopefully the single comparison will not be too 9384 */
8828 // arduous. Alternatively the 'break' could be replced with a return 9385 object[] outlist = new object[outlen];
8829 // but that's shabby programming. 9386 for (i = 0; i < outlen; i ++)
8830
8831 if ((beginning == srclen) && (keepNulls))
8832 { 9387 {
8833 if (srclen != 0) 9388 outlist[i] = new LSL_String(outarray[i]);
8834 tokens.Add(new LSL_String(""));
8835 } 9389 }
8836 9390 return new LSL_List(outlist);
8837 return tokens;
8838 }
8839
8840 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8841 {
8842 m_host.AddScriptLPS(1);
8843 return this.ParseString(src, separators, spacers, false);
8844 }
8845
8846 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8847 {
8848 m_host.AddScriptLPS(1);
8849 return this.ParseString(src, separators, spacers, true);
8850 } 9391 }
8851 9392
8852 public LSL_Integer llGetObjectPermMask(int mask) 9393 public LSL_Integer llGetObjectPermMask(int mask)
@@ -8923,28 +9464,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8923 { 9464 {
8924 m_host.AddScriptLPS(1); 9465 m_host.AddScriptLPS(1);
8925 9466
8926 lock (m_host.TaskInventory) 9467 m_host.TaskInventory.LockItemsForRead(true);
9468 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8927 { 9469 {
8928 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9470 if (inv.Value.Name == item)
8929 { 9471 {
8930 if (inv.Value.Name == item) 9472 m_host.TaskInventory.LockItemsForRead(false);
9473 switch (mask)
8931 { 9474 {
8932 switch (mask) 9475 case 0:
8933 { 9476 return (int)inv.Value.BasePermissions;
8934 case 0: 9477 case 1:
8935 return (int)inv.Value.BasePermissions; 9478 return (int)inv.Value.CurrentPermissions;
8936 case 1: 9479 case 2:
8937 return (int)inv.Value.CurrentPermissions; 9480 return (int)inv.Value.GroupPermissions;
8938 case 2: 9481 case 3:
8939 return (int)inv.Value.GroupPermissions; 9482 return (int)inv.Value.EveryonePermissions;
8940 case 3: 9483 case 4:
8941 return (int)inv.Value.EveryonePermissions; 9484 return (int)inv.Value.NextPermissions;
8942 case 4:
8943 return (int)inv.Value.NextPermissions;
8944 }
8945 } 9485 }
8946 } 9486 }
8947 } 9487 }
9488 m_host.TaskInventory.LockItemsForRead(false);
8948 9489
8949 return -1; 9490 return -1;
8950 } 9491 }
@@ -8991,16 +9532,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8991 { 9532 {
8992 m_host.AddScriptLPS(1); 9533 m_host.AddScriptLPS(1);
8993 9534
8994 lock (m_host.TaskInventory) 9535 m_host.TaskInventory.LockItemsForRead(true);
9536 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8995 { 9537 {
8996 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9538 if (inv.Value.Name == item)
8997 { 9539 {
8998 if (inv.Value.Name == item) 9540 m_host.TaskInventory.LockItemsForRead(false);
8999 { 9541 return inv.Value.CreatorID.ToString();
9000 return inv.Value.CreatorID.ToString();
9001 }
9002 } 9542 }
9003 } 9543 }
9544 m_host.TaskInventory.LockItemsForRead(false);
9004 9545
9005 llSay(0, "No item name '" + item + "'"); 9546 llSay(0, "No item name '" + item + "'");
9006 9547
@@ -9148,7 +9689,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9148 } 9689 }
9149 9690
9150 /// <summary> 9691 /// <summary>
9151 /// illListReplaceList removes the sub-list defined by the inclusive indices 9692 /// llListReplaceList removes the sub-list defined by the inclusive indices
9152 /// start and end and inserts the src list in its place. The inclusive 9693 /// start and end and inserts the src list in its place. The inclusive
9153 /// nature of the indices means that at least one element must be deleted 9694 /// nature of the indices means that at least one element must be deleted
9154 /// if the indices are within the bounds of the existing list. I.e. 2,2 9695 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9205,16 +9746,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9205 // based upon end. Note that if end exceeds the upper 9746 // based upon end. Note that if end exceeds the upper
9206 // bound in this case, the entire destination list 9747 // bound in this case, the entire destination list
9207 // is removed. 9748 // is removed.
9208 else 9749 else if (start == 0)
9209 { 9750 {
9210 if (end + 1 < dest.Length) 9751 if (end + 1 < dest.Length)
9211 {
9212 return src + dest.GetSublist(end + 1, -1); 9752 return src + dest.GetSublist(end + 1, -1);
9213 }
9214 else 9753 else
9215 {
9216 return src; 9754 return src;
9217 } 9755 }
9756 else // Start < 0
9757 {
9758 if (end + 1 < dest.Length)
9759 return dest.GetSublist(end + 1, -1);
9760 else
9761 return new LSL_List();
9218 } 9762 }
9219 } 9763 }
9220 // Finally, if start > end, we strip away a prefix and 9764 // Finally, if start > end, we strip away a prefix and
@@ -9265,17 +9809,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9265 int width = 0; 9809 int width = 0;
9266 int height = 0; 9810 int height = 0;
9267 9811
9268 ParcelMediaCommandEnum? commandToSend = null; 9812 uint commandToSend = 0;
9269 float time = 0.0f; // default is from start 9813 float time = 0.0f; // default is from start
9270 9814
9271 ScenePresence presence = null; 9815 ScenePresence presence = null;
9272 9816
9273 for (int i = 0; i < commandList.Data.Length; i++) 9817 for (int i = 0; i < commandList.Data.Length; i++)
9274 { 9818 {
9275 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 9819 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9276 switch (command) 9820 switch (command)
9277 { 9821 {
9278 case ParcelMediaCommandEnum.Agent: 9822 case (uint)ParcelMediaCommandEnum.Agent:
9279 // we send only to one agent 9823 // we send only to one agent
9280 if ((i + 1) < commandList.Length) 9824 if ((i + 1) < commandList.Length)
9281 { 9825 {
@@ -9292,25 +9836,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9292 } 9836 }
9293 break; 9837 break;
9294 9838
9295 case ParcelMediaCommandEnum.Loop: 9839 case (uint)ParcelMediaCommandEnum.Loop:
9296 loop = 1; 9840 loop = 1;
9297 commandToSend = command; 9841 commandToSend = command;
9298 update = true; //need to send the media update packet to set looping 9842 update = true; //need to send the media update packet to set looping
9299 break; 9843 break;
9300 9844
9301 case ParcelMediaCommandEnum.Play: 9845 case (uint)ParcelMediaCommandEnum.Play:
9302 loop = 0; 9846 loop = 0;
9303 commandToSend = command; 9847 commandToSend = command;
9304 update = true; //need to send the media update packet to make sure it doesn't loop 9848 update = true; //need to send the media update packet to make sure it doesn't loop
9305 break; 9849 break;
9306 9850
9307 case ParcelMediaCommandEnum.Pause: 9851 case (uint)ParcelMediaCommandEnum.Pause:
9308 case ParcelMediaCommandEnum.Stop: 9852 case (uint)ParcelMediaCommandEnum.Stop:
9309 case ParcelMediaCommandEnum.Unload: 9853 case (uint)ParcelMediaCommandEnum.Unload:
9310 commandToSend = command; 9854 commandToSend = command;
9311 break; 9855 break;
9312 9856
9313 case ParcelMediaCommandEnum.Url: 9857 case (uint)ParcelMediaCommandEnum.Url:
9314 if ((i + 1) < commandList.Length) 9858 if ((i + 1) < commandList.Length)
9315 { 9859 {
9316 if (commandList.Data[i + 1] is LSL_String) 9860 if (commandList.Data[i + 1] is LSL_String)
@@ -9323,7 +9867,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9323 } 9867 }
9324 break; 9868 break;
9325 9869
9326 case ParcelMediaCommandEnum.Texture: 9870 case (uint)ParcelMediaCommandEnum.Texture:
9327 if ((i + 1) < commandList.Length) 9871 if ((i + 1) < commandList.Length)
9328 { 9872 {
9329 if (commandList.Data[i + 1] is LSL_String) 9873 if (commandList.Data[i + 1] is LSL_String)
@@ -9336,7 +9880,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9336 } 9880 }
9337 break; 9881 break;
9338 9882
9339 case ParcelMediaCommandEnum.Time: 9883 case (uint)ParcelMediaCommandEnum.Time:
9340 if ((i + 1) < commandList.Length) 9884 if ((i + 1) < commandList.Length)
9341 { 9885 {
9342 if (commandList.Data[i + 1] is LSL_Float) 9886 if (commandList.Data[i + 1] is LSL_Float)
@@ -9348,7 +9892,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9348 } 9892 }
9349 break; 9893 break;
9350 9894
9351 case ParcelMediaCommandEnum.AutoAlign: 9895 case (uint)ParcelMediaCommandEnum.AutoAlign:
9352 if ((i + 1) < commandList.Length) 9896 if ((i + 1) < commandList.Length)
9353 { 9897 {
9354 if (commandList.Data[i + 1] is LSL_Integer) 9898 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9362,7 +9906,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9362 } 9906 }
9363 break; 9907 break;
9364 9908
9365 case ParcelMediaCommandEnum.Type: 9909 case (uint)ParcelMediaCommandEnum.Type:
9366 if ((i + 1) < commandList.Length) 9910 if ((i + 1) < commandList.Length)
9367 { 9911 {
9368 if (commandList.Data[i + 1] is LSL_String) 9912 if (commandList.Data[i + 1] is LSL_String)
@@ -9375,7 +9919,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9375 } 9919 }
9376 break; 9920 break;
9377 9921
9378 case ParcelMediaCommandEnum.Desc: 9922 case (uint)ParcelMediaCommandEnum.Desc:
9379 if ((i + 1) < commandList.Length) 9923 if ((i + 1) < commandList.Length)
9380 { 9924 {
9381 if (commandList.Data[i + 1] is LSL_String) 9925 if (commandList.Data[i + 1] is LSL_String)
@@ -9388,7 +9932,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9388 } 9932 }
9389 break; 9933 break;
9390 9934
9391 case ParcelMediaCommandEnum.Size: 9935 case (uint)ParcelMediaCommandEnum.Size:
9392 if ((i + 2) < commandList.Length) 9936 if ((i + 2) < commandList.Length)
9393 { 9937 {
9394 if (commandList.Data[i + 1] is LSL_Integer) 9938 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9458,7 +10002,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9458 } 10002 }
9459 } 10003 }
9460 10004
9461 if (commandToSend != null) 10005 if (commandToSend != 0)
9462 { 10006 {
9463 // the commandList contained a start/stop/... command, too 10007 // the commandList contained a start/stop/... command, too
9464 if (presence == null) 10008 if (presence == null)
@@ -9495,7 +10039,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9495 10039
9496 if (aList.Data[i] != null) 10040 if (aList.Data[i] != null)
9497 { 10041 {
9498 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10042 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9499 { 10043 {
9500 case ParcelMediaCommandEnum.Url: 10044 case ParcelMediaCommandEnum.Url:
9501 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10045 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9538,16 +10082,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9538 { 10082 {
9539 m_host.AddScriptLPS(1); 10083 m_host.AddScriptLPS(1);
9540 10084
9541 lock (m_host.TaskInventory) 10085 m_host.TaskInventory.LockItemsForRead(true);
10086 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9542 { 10087 {
9543 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10088 if (inv.Value.Name == name)
9544 { 10089 {
9545 if (inv.Value.Name == name) 10090 m_host.TaskInventory.LockItemsForRead(false);
9546 { 10091 return inv.Value.Type;
9547 return inv.Value.Type;
9548 }
9549 } 10092 }
9550 } 10093 }
10094 m_host.TaskInventory.LockItemsForRead(false);
9551 10095
9552 return -1; 10096 return -1;
9553 } 10097 }
@@ -9558,15 +10102,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9558 10102
9559 if (quick_pay_buttons.Data.Length < 4) 10103 if (quick_pay_buttons.Data.Length < 4)
9560 { 10104 {
9561 LSLError("List must have at least 4 elements"); 10105 int x;
9562 return; 10106 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10107 {
10108 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10109 }
9563 } 10110 }
9564 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10111 int[] nPrice = new int[5];
9565 10112 nPrice[0] = price;
9566 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10113 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9567 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10114 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9568 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10115 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9569 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10116 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10117 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9570 m_host.ParentGroup.HasGroupChanged = true; 10118 m_host.ParentGroup.HasGroupChanged = true;
9571 } 10119 }
9572 10120
@@ -9578,17 +10126,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9578 if (invItemID == UUID.Zero) 10126 if (invItemID == UUID.Zero)
9579 return new LSL_Vector(); 10127 return new LSL_Vector();
9580 10128
9581 lock (m_host.TaskInventory) 10129 m_host.TaskInventory.LockItemsForRead(true);
10130 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9582 { 10131 {
9583 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10132 m_host.TaskInventory.LockItemsForRead(false);
9584 return new LSL_Vector(); 10133 return new LSL_Vector();
10134 }
9585 10135
9586 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 10136 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9587 { 10137 {
9588 ShoutError("No permissions to track the camera"); 10138 ShoutError("No permissions to track the camera");
9589 return new LSL_Vector(); 10139 m_host.TaskInventory.LockItemsForRead(false);
9590 } 10140 return new LSL_Vector();
9591 } 10141 }
10142 m_host.TaskInventory.LockItemsForRead(false);
9592 10143
9593 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10144 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9594 if (presence != null) 10145 if (presence != null)
@@ -9606,17 +10157,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9606 if (invItemID == UUID.Zero) 10157 if (invItemID == UUID.Zero)
9607 return new LSL_Rotation(); 10158 return new LSL_Rotation();
9608 10159
9609 lock (m_host.TaskInventory) 10160 m_host.TaskInventory.LockItemsForRead(true);
10161 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9610 { 10162 {
9611 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10163 m_host.TaskInventory.LockItemsForRead(false);
9612 return new LSL_Rotation(); 10164 return new LSL_Rotation();
9613
9614 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9615 {
9616 ShoutError("No permissions to track the camera");
9617 return new LSL_Rotation();
9618 }
9619 } 10165 }
10166 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
10167 {
10168 ShoutError("No permissions to track the camera");
10169 m_host.TaskInventory.LockItemsForRead(false);
10170 return new LSL_Rotation();
10171 }
10172 m_host.TaskInventory.LockItemsForRead(false);
9620 10173
9621 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10174 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9622 if (presence != null) 10175 if (presence != null)
@@ -9678,8 +10231,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9678 { 10231 {
9679 m_host.AddScriptLPS(1); 10232 m_host.AddScriptLPS(1);
9680 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0); 10233 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0);
9681 if (detectedParams == null) return; // only works on the first detected avatar 10234 if (detectedParams == null)
9682 10235 {
10236 if (m_host.ParentGroup.IsAttachment == true)
10237 {
10238 detectedParams = new DetectParams();
10239 detectedParams.Key = m_host.OwnerID;
10240 }
10241 else
10242 {
10243 return;
10244 }
10245 }
10246
9683 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10247 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9684 if (avatar != null) 10248 if (avatar != null)
9685 { 10249 {
@@ -9687,6 +10251,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9687 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10251 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9688 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10252 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9689 } 10253 }
10254
9690 ScriptSleep(1000); 10255 ScriptSleep(1000);
9691 } 10256 }
9692 10257
@@ -9798,14 +10363,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9798 if (objectID == UUID.Zero) return; 10363 if (objectID == UUID.Zero) return;
9799 10364
9800 UUID agentID; 10365 UUID agentID;
9801 lock (m_host.TaskInventory) 10366 m_host.TaskInventory.LockItemsForRead(true);
9802 { 10367 // we need the permission first, to know which avatar we want to set the camera for
9803 // we need the permission first, to know which avatar we want to set the camera for 10368 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9804 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9805 10369
9806 if (agentID == UUID.Zero) return; 10370 if (agentID == UUID.Zero)
9807 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 10371 {
10372 m_host.TaskInventory.LockItemsForRead(false);
10373 return;
10374 }
10375 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10376 {
10377 m_host.TaskInventory.LockItemsForRead(false);
10378 return;
9808 } 10379 }
10380 m_host.TaskInventory.LockItemsForRead(false);
9809 10381
9810 ScenePresence presence = World.GetScenePresence(agentID); 10382 ScenePresence presence = World.GetScenePresence(agentID);
9811 10383
@@ -9814,12 +10386,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9814 10386
9815 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10387 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9816 object[] data = rules.Data; 10388 object[] data = rules.Data;
9817 for (int i = 0; i < data.Length; ++i) { 10389 for (int i = 0; i < data.Length; ++i)
10390 {
9818 int type = Convert.ToInt32(data[i++].ToString()); 10391 int type = Convert.ToInt32(data[i++].ToString());
9819 if (i >= data.Length) break; // odd number of entries => ignore the last 10392 if (i >= data.Length) break; // odd number of entries => ignore the last
9820 10393
9821 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10394 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9822 switch (type) { 10395 switch (type)
10396 {
9823 case ScriptBaseClass.CAMERA_FOCUS: 10397 case ScriptBaseClass.CAMERA_FOCUS:
9824 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10398 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9825 case ScriptBaseClass.CAMERA_POSITION: 10399 case ScriptBaseClass.CAMERA_POSITION:
@@ -9855,12 +10429,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9855 10429
9856 // we need the permission first, to know which avatar we want to clear the camera for 10430 // we need the permission first, to know which avatar we want to clear the camera for
9857 UUID agentID; 10431 UUID agentID;
9858 lock (m_host.TaskInventory) 10432 m_host.TaskInventory.LockItemsForRead(true);
10433 agentID = m_host.TaskInventory[invItemID].PermsGranter;
10434 if (agentID == UUID.Zero)
9859 { 10435 {
9860 agentID = m_host.TaskInventory[invItemID].PermsGranter; 10436 m_host.TaskInventory.LockItemsForRead(false);
9861 if (agentID == UUID.Zero) return; 10437 return;
9862 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
9863 } 10438 }
10439 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10440 {
10441 m_host.TaskInventory.LockItemsForRead(false);
10442 return;
10443 }
10444 m_host.TaskInventory.LockItemsForRead(false);
9864 10445
9865 ScenePresence presence = World.GetScenePresence(agentID); 10446 ScenePresence presence = World.GetScenePresence(agentID);
9866 10447
@@ -9927,19 +10508,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9927 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10508 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
9928 { 10509 {
9929 m_host.AddScriptLPS(1); 10510 m_host.AddScriptLPS(1);
9930 string ret = String.Empty; 10511
9931 string src1 = llBase64ToString(str1); 10512 if (str1 == String.Empty)
9932 string src2 = llBase64ToString(str2); 10513 return String.Empty;
9933 int c = 0; 10514 if (str2 == String.Empty)
9934 for (int i = 0; i < src1.Length; i++) 10515 return str1;
10516
10517 int len = str2.Length;
10518 if ((len % 4) != 0) // LL is EVIL!!!!
9935 { 10519 {
9936 ret += (char) (src1[i] ^ src2[c]); 10520 while (str2.EndsWith("="))
10521 str2 = str2.Substring(0, str2.Length - 1);
10522
10523 len = str2.Length;
10524 int mod = len % 4;
10525
10526 if (mod == 1)
10527 str2 = str2.Substring(0, str2.Length - 1);
10528 else if (mod == 2)
10529 str2 += "==";
10530 else if (mod == 3)
10531 str2 += "=";
10532 }
9937 10533
9938 c++; 10534 byte[] data1;
9939 if (c >= src2.Length) 10535 byte[] data2;
9940 c = 0; 10536 try
10537 {
10538 data1 = Convert.FromBase64String(str1);
10539 data2 = Convert.FromBase64String(str2);
10540 }
10541 catch (Exception)
10542 {
10543 return new LSL_String(String.Empty);
9941 } 10544 }
9942 return llStringToBase64(ret); 10545
10546 byte[] d2 = new Byte[data1.Length];
10547 int pos = 0;
10548
10549 if (data1.Length <= data2.Length)
10550 {
10551 Array.Copy(data2, 0, d2, 0, data1.Length);
10552 }
10553 else
10554 {
10555 while (pos < data1.Length)
10556 {
10557 len = data1.Length - pos;
10558 if (len > data2.Length)
10559 len = data2.Length;
10560
10561 Array.Copy(data2, 0, d2, pos, len);
10562 pos += len;
10563 }
10564 }
10565
10566 for (pos = 0 ; pos < data1.Length ; pos++ )
10567 data1[pos] ^= d2[pos];
10568
10569 return Convert.ToBase64String(data1);
9943 } 10570 }
9944 10571
9945 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10572 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -9996,12 +10623,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9996 Regex r = new Regex(authregex); 10623 Regex r = new Regex(authregex);
9997 int[] gnums = r.GetGroupNumbers(); 10624 int[] gnums = r.GetGroupNumbers();
9998 Match m = r.Match(url); 10625 Match m = r.Match(url);
9999 if (m.Success) { 10626 if (m.Success)
10000 for (int i = 1; i < gnums.Length; i++) { 10627 {
10628 for (int i = 1; i < gnums.Length; i++)
10629 {
10001 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10630 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10002 //CaptureCollection cc = g.Captures; 10631 //CaptureCollection cc = g.Captures;
10003 } 10632 }
10004 if (m.Groups.Count == 5) { 10633 if (m.Groups.Count == 5)
10634 {
10005 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10635 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10006 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10636 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10007 } 10637 }
@@ -10287,15 +10917,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10287 10917
10288 internal UUID ScriptByName(string name) 10918 internal UUID ScriptByName(string name)
10289 { 10919 {
10290 lock (m_host.TaskInventory) 10920 m_host.TaskInventory.LockItemsForRead(true);
10921
10922 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10291 { 10923 {
10292 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 10924 if (item.Type == 10 && item.Name == name)
10293 { 10925 {
10294 if (item.Type == 10 && item.Name == name) 10926 m_host.TaskInventory.LockItemsForRead(false);
10295 return item.ItemID; 10927 return item.ItemID;
10296 } 10928 }
10297 } 10929 }
10298 10930
10931 m_host.TaskInventory.LockItemsForRead(false);
10932
10299 return UUID.Zero; 10933 return UUID.Zero;
10300 } 10934 }
10301 10935
@@ -10336,6 +10970,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10336 { 10970 {
10337 m_host.AddScriptLPS(1); 10971 m_host.AddScriptLPS(1);
10338 10972
10973 //Clone is thread safe
10339 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10974 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10340 10975
10341 UUID assetID = UUID.Zero; 10976 UUID assetID = UUID.Zero;
@@ -10398,6 +11033,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10398 { 11033 {
10399 m_host.AddScriptLPS(1); 11034 m_host.AddScriptLPS(1);
10400 11035
11036 //Clone is thread safe
10401 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11037 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10402 11038
10403 UUID assetID = UUID.Zero; 11039 UUID assetID = UUID.Zero;
@@ -10478,15 +11114,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10478 return GetLinkPrimitiveParams(obj, rules); 11114 return GetLinkPrimitiveParams(obj, rules);
10479 } 11115 }
10480 11116
10481 public void print(string str) 11117 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10482 { 11118 {
10483 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11119 List<SceneObjectPart> parts = GetLinkParts(link);
10484 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_itemID, "OSSL"); 11120 if (parts.Count < 1)
10485 if (ossl != null) 11121 return 0;
10486 { 11122
10487 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11123 return GetNumberOfSides(parts[0]);
10488 m_log.Info("LSL print():" + str);
10489 }
10490 } 11124 }
10491 11125
10492 private string Name2Username(string name) 11126 private string Name2Username(string name)
@@ -10532,153 +11166,392 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10532 return rq.ToString(); 11166 return rq.ToString();
10533 } 11167 }
10534 11168
11169 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11170 {
11171 m_SayShoutCount = 0;
11172 }
11173
11174 private struct Tri
11175 {
11176 public Vector3 p1;
11177 public Vector3 p2;
11178 public Vector3 p3;
11179 }
11180
11181 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11182 {
11183 float height = avatar.Appearance.AvatarHeight;
11184 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11185 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11186
11187 if (point.X > b1.X && point.X < b2.X &&
11188 point.Y > b1.Y && point.Y < b2.Y &&
11189 point.Z > b1.Z && point.Z < b2.Z)
11190 return true;
11191 return false;
11192 }
11193
11194 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11195 {
11196 List<ContactResult> contacts = new List<ContactResult>();
11197
11198 Vector3 ab = rayEnd - rayStart;
11199
11200 World.ForEachScenePresence(delegate(ScenePresence sp)
11201 {
11202 Vector3 ac = sp.AbsolutePosition - rayStart;
11203 Vector3 bc = sp.AbsolutePosition - rayEnd;
11204
11205 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11206
11207 if (d > 1.5)
11208 return;
11209
11210 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11211
11212 if (d2 > 0)
11213 return;
11214
11215 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11216 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11217
11218 if (!InBoundingBox(sp, p))
11219 return;
11220
11221 ContactResult result = new ContactResult ();
11222 result.ConsumerID = sp.LocalId;
11223 result.Depth = Vector3.Distance(rayStart, p);
11224 result.Normal = Vector3.Zero;
11225 result.Pos = p;
11226
11227 contacts.Add(result);
11228 });
11229
11230 return contacts.ToArray();
11231 }
11232
11233 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11234 {
11235 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11236 List<ContactResult> contacts = new List<ContactResult>();
11237
11238 Vector3 ab = rayEnd - rayStart;
11239
11240 World.ForEachSOG(delegate(SceneObjectGroup group)
11241 {
11242 if (m_host.ParentGroup == group)
11243 return;
11244
11245 if (group.IsAttachment)
11246 return;
11247
11248 if (group.RootPart.PhysActor == null)
11249 {
11250 if (!includePhantom)
11251 return;
11252 }
11253 else
11254 {
11255 if (group.RootPart.PhysActor.IsPhysical)
11256 {
11257 if (!includePhysical)
11258 return;
11259 }
11260 else
11261 {
11262 if (!includeNonPhysical)
11263 return;
11264 }
11265 }
11266
11267 // Find the radius ouside of which we don't even need to hit test
11268 float minX;
11269 float maxX;
11270 float minY;
11271 float maxY;
11272 float minZ;
11273 float maxZ;
11274
11275 float radius = 0.0f;
11276
11277 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11278
11279 if (Math.Abs(minX) > radius)
11280 radius = Math.Abs(minX);
11281 if (Math.Abs(minY) > radius)
11282 radius = Math.Abs(minY);
11283 if (Math.Abs(minZ) > radius)
11284 radius = Math.Abs(minZ);
11285 if (Math.Abs(maxX) > radius)
11286 radius = Math.Abs(maxX);
11287 if (Math.Abs(maxY) > radius)
11288 radius = Math.Abs(maxY);
11289 if (Math.Abs(maxZ) > radius)
11290 radius = Math.Abs(maxZ);
11291
11292 Vector3 ac = group.AbsolutePosition - rayStart;
11293 Vector3 bc = group.AbsolutePosition - rayEnd;
11294
11295 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11296
11297 // Too far off ray, don't bother
11298 if (d > radius)
11299 return;
11300
11301 // Behind ray, drop
11302 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11303 if (d2 > 0)
11304 return;
11305
11306 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11307 // Miss.
11308 if (!intersection.HitTF)
11309 return;
11310
11311 ContactResult result = new ContactResult ();
11312 result.ConsumerID = group.LocalId;
11313 result.Depth = intersection.distance;
11314 result.Normal = intersection.normal;
11315 result.Pos = intersection.ipoint;
11316
11317 contacts.Add(result);
11318 });
11319
11320 return contacts.ToArray();
11321 }
11322
11323 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11324 {
11325 double[,] heightfield = World.Heightmap.GetDoubles();
11326 List<ContactResult> contacts = new List<ContactResult>();
11327
11328 double min = 2048.0;
11329 double max = 0.0;
11330
11331 // Find the min and max of the heightfield
11332 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11333 {
11334 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11335 {
11336 if (heightfield[x, y] > max)
11337 max = heightfield[x, y];
11338 if (heightfield[x, y] < min)
11339 min = heightfield[x, y];
11340 }
11341 }
11342
11343
11344 // A ray extends past rayEnd, but doesn't go back before
11345 // rayStart. If the start is above the highest point of the ground
11346 // and the ray goes up, we can't hit the ground. Ever.
11347 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11348 return null;
11349
11350 // Same for going down
11351 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11352 return null;
11353
11354 List<Tri> trilist = new List<Tri>();
11355
11356 // Create our triangle list
11357 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11358 {
11359 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11360 {
11361 Tri t1 = new Tri();
11362 Tri t2 = new Tri();
11363
11364 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11365 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11366 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11367 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11368
11369 t1.p1 = p1;
11370 t1.p2 = p2;
11371 t1.p3 = p3;
11372
11373 t2.p1 = p3;
11374 t2.p2 = p4;
11375 t2.p3 = p1;
11376
11377 trilist.Add(t1);
11378 trilist.Add(t2);
11379 }
11380 }
11381
11382 // Ray direction
11383 Vector3 rayDirection = rayEnd - rayStart;
11384
11385 foreach (Tri t in trilist)
11386 {
11387 // Compute triangle plane normal and edges
11388 Vector3 u = t.p2 - t.p1;
11389 Vector3 v = t.p3 - t.p1;
11390 Vector3 n = Vector3.Cross(u, v);
11391
11392 if (n == Vector3.Zero)
11393 continue;
11394
11395 Vector3 w0 = rayStart - t.p1;
11396 double a = -Vector3.Dot(n, w0);
11397 double b = Vector3.Dot(n, rayDirection);
11398
11399 // Not intersecting the plane, or in plane (same thing)
11400 // Ignoring this MAY cause the ground to not be detected
11401 // sometimes
11402 if (Math.Abs(b) < 0.000001)
11403 continue;
11404
11405 double r = a / b;
11406
11407 // ray points away from plane
11408 if (r < 0.0)
11409 continue;
11410
11411 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11412
11413 float uu = Vector3.Dot(u, u);
11414 float uv = Vector3.Dot(u, v);
11415 float vv = Vector3.Dot(v, v);
11416 Vector3 w = ip - t.p1;
11417 float wu = Vector3.Dot(w, u);
11418 float wv = Vector3.Dot(w, v);
11419 float d = uv * uv - uu * vv;
11420
11421 float cs = (uv * wv - vv * wu) / d;
11422 if (cs < 0 || cs > 1.0)
11423 continue;
11424 float ct = (uv * wu - uu * wv) / d;
11425 if (ct < 0 || (cs + ct) > 1.0)
11426 continue;
11427
11428 // Add contact point
11429 ContactResult result = new ContactResult ();
11430 result.ConsumerID = 0;
11431 result.Depth = Vector3.Distance(rayStart, ip);
11432 result.Normal = n;
11433 result.Pos = ip;
11434
11435 contacts.Add(result);
11436 }
11437
11438 if (contacts.Count == 0)
11439 return null;
11440
11441 contacts.Sort(delegate(ContactResult a, ContactResult b)
11442 {
11443 return (int)(a.Depth - b.Depth);
11444 });
11445
11446 return contacts[0];
11447 }
11448
10535 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11449 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10536 { 11450 {
11451 LSL_List list = new LSL_List();
11452
10537 m_host.AddScriptLPS(1); 11453 m_host.AddScriptLPS(1);
10538 11454
10539 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11455 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10540 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11456 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10541 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11457 Vector3 dir = rayEnd - rayStart;
10542 11458
10543 int count = 0; 11459 int count = 1;
10544// int detectPhantom = 0; 11460 bool detectPhantom = false;
10545 int dataFlags = 0; 11461 int dataFlags = 0;
10546 int rejectTypes = 0; 11462 int rejectTypes = 0;
10547 11463
10548 for (int i = 0; i < options.Length; i += 2) 11464 for (int i = 0; i < options.Length; i += 2)
10549 { 11465 {
10550 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11466 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10551 {
10552 count = options.GetLSLIntegerItem(i + 1); 11467 count = options.GetLSLIntegerItem(i + 1);
10553 } 11468 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10554// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11469 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10555// {
10556// detectPhantom = options.GetLSLIntegerItem(i + 1);
10557// }
10558 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11470 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10559 {
10560 dataFlags = options.GetLSLIntegerItem(i + 1); 11471 dataFlags = options.GetLSLIntegerItem(i + 1);
10561 }
10562 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11472 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10563 {
10564 rejectTypes = options.GetLSLIntegerItem(i + 1); 11473 rejectTypes = options.GetLSLIntegerItem(i + 1);
10565 }
10566 } 11474 }
10567 11475
10568 LSL_List list = new LSL_List(); 11476 if (count > 16)
10569 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11477 count = 16;
10570
10571 double distance = Util.GetDistanceTo(startvector, endvector);
10572 11478
10573 if (distance == 0) 11479 List<ContactResult> results = new List<ContactResult>();
10574 distance = 0.001;
10575
10576 Vector3 posToCheck = startvector;
10577 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10578 11480
10579 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11481 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10580 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11482 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10581 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11483 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10582 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11484 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10583 11485
10584 for (float i = 0; i <= distance; i += 0.1f) 11486 if (checkTerrain)
10585 { 11487 {
10586 posToCheck = startvector + (dir * (i / (float)distance)); 11488 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11489 if (groundContact != null)
11490 results.Add((ContactResult)groundContact);
11491 }
10587 11492
10588 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11493 if (checkAgents)
10589 { 11494 {
10590 ContactResult result = new ContactResult(); 11495 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
10591 result.ConsumerID = 0; 11496 foreach (ContactResult r in agentHits)
10592 result.Depth = 0; 11497 results.Add(r);
10593 result.Normal = Vector3.Zero; 11498 }
10594 result.Pos = posToCheck;
10595 results.Add(result);
10596 checkTerrain = false;
10597 }
10598 11499
10599 if (checkAgents) 11500 if (checkPhysical || checkNonPhysical)
10600 { 11501 {
10601 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11502 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
10602 { 11503 foreach (ContactResult r in objectHits)
10603 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X)) 11504 results.Add(r);
10604 {
10605 ContactResult result = new ContactResult ();
10606 result.ConsumerID = sp.LocalId;
10607 result.Depth = 0;
10608 result.Normal = Vector3.Zero;
10609 result.Pos = posToCheck;
10610 results.Add(result);
10611 }
10612 });
10613 }
10614 } 11505 }
10615 11506
10616 int refcount = 0; 11507 results.Sort(delegate(ContactResult a, ContactResult b)
11508 {
11509 return (int)(a.Depth - b.Depth);
11510 });
11511
11512 int values = 0;
10617 foreach (ContactResult result in results) 11513 foreach (ContactResult result in results)
10618 { 11514 {
10619 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) 11515 UUID itemID = UUID.Zero;
10620 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0) 11516 int linkNum = 0;
10621 continue;
10622
10623 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID);
10624
10625 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS)
10626 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents
10627 11517
10628 if (entity == null) 11518 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
11519 // It's a prim!
11520 if (part != null)
10629 { 11521 {
10630 list.Add(UUID.Zero); 11522 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10631 11523 itemID = part.ParentGroup.UUID;
10632 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11524 else
10633 list.Add(0); 11525 itemID = part.UUID;
10634
10635 list.Add(result.Pos);
10636
10637 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10638 list.Add(result.Normal);
10639 11526
10640 continue; //Can't find it, so add UUID.Zero 11527 linkNum = part.LinkNum;
10641 } 11528 }
10642 11529 else
10643 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity &&
10644 ((ISceneChildEntity)intersection.obj).PhysActor == null)
10645 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
10646
10647 if (entity is SceneObjectPart)
10648 { 11530 {
10649 if (((SceneObjectPart)entity).PhysActor != null && ((SceneObjectPart)entity).PhysActor.IsPhysical) 11531 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10650 { 11532 /// It it a boy? a girl?
10651 if (!checkPhysical) 11533 if (sp != null)
10652 continue; 11534 itemID = sp.UUID;
10653 }
10654 else
10655 {
10656 if (!checkNonPhysical)
10657 continue;
10658 }
10659 } 11535 }
10660 11536
10661 refcount++; 11537 list.Add(new LSL_String(itemID.ToString()));
10662 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11538 list.Add(new LSL_String(result.Pos.ToString()));
10663 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10664 else
10665 list.Add(entity.UUID);
10666 11539
10667 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11540 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10668 { 11541 list.Add(new LSL_Integer(linkNum));
10669 if (entity is SceneObjectPart)
10670 list.Add(((SceneObjectPart)entity).LinkNum);
10671 else
10672 list.Add(0);
10673 }
10674 11542
10675 list.Add(result.Pos);
10676 11543
10677 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11544 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10678 list.Add(result.Normal); 11545 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11546
11547 values++;
11548 count--;
11549
11550 if (count == 0)
11551 break;
10679 } 11552 }
10680 11553
10681 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11554 list.Add(new LSL_Integer(values));
10682 11555
10683 return list; 11556 return list;
10684 } 11557 }
@@ -10718,7 +11591,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10718 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 11591 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10719 if (!isAccount) return 0; 11592 if (!isAccount) return 0;
10720 if (estate.HasAccess(id)) return 1; 11593 if (estate.HasAccess(id)) return 1;
10721 if (estate.IsBanned(id)) 11594 if (estate.IsBanned(id, World.GetUserFlags(id)))
10722 estate.RemoveBan(id); 11595 estate.RemoveBan(id);
10723 estate.AddEstateUser(id); 11596 estate.AddEstateUser(id);
10724 break; 11597 break;
@@ -10737,14 +11610,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10737 break; 11610 break;
10738 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 11611 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10739 if (!isAccount) return 0; 11612 if (!isAccount) return 0;
10740 if (estate.IsBanned(id)) return 1; 11613 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10741 EstateBan ban = new EstateBan(); 11614 EstateBan ban = new EstateBan();
10742 ban.EstateID = estate.EstateID; 11615 ban.EstateID = estate.EstateID;
10743 ban.BannedUserID = id; 11616 ban.BannedUserID = id;
10744 estate.AddBan(ban); 11617 estate.AddBan(ban);
10745 break; 11618 break;
10746 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 11619 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10747 if (!isAccount || !estate.IsBanned(id)) return 0; 11620 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10748 estate.RemoveBan(id); 11621 estate.RemoveBan(id);
10749 break; 11622 break;
10750 default: return 0; 11623 default: return 0;
@@ -10770,22 +11643,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10770 NotImplemented("llGetSPMaxMemory"); 11643 NotImplemented("llGetSPMaxMemory");
10771 } 11644 }
10772 11645
10773 public void llGetUsedMemory() 11646 public virtual LSL_Integer llGetUsedMemory()
10774 { 11647 {
10775 m_host.AddScriptLPS(1); 11648 m_host.AddScriptLPS(1);
10776 NotImplemented("llGetUsedMemory"); 11649 NotImplemented("llGetUsedMemory");
11650 return 0;
10777 } 11651 }
10778 11652
10779 public void llScriptProfiler(LSL_Integer flags) 11653 public void llScriptProfiler(LSL_Integer flags)
10780 { 11654 {
10781 m_host.AddScriptLPS(1); 11655 m_host.AddScriptLPS(1);
10782 NotImplemented("llScriptProfiler"); 11656 //NotImplemented("llScriptProfiler");
10783 } 11657 }
10784 11658
10785 public void llSetSoundQueueing(int queue) 11659 public void llSetSoundQueueing(int queue)
10786 { 11660 {
10787 m_host.AddScriptLPS(1); 11661 m_host.AddScriptLPS(1);
10788 NotImplemented("llSetSoundQueueing");
10789 } 11662 }
10790 11663
10791 public void llCollisionSprite(string impact_sprite) 11664 public void llCollisionSprite(string impact_sprite)
@@ -10797,7 +11670,133 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10797 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 11670 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10798 { 11671 {
10799 m_host.AddScriptLPS(1); 11672 m_host.AddScriptLPS(1);
10800 NotImplemented("llGodLikeRezObject"); 11673
11674 if (!World.Permissions.IsGod(m_host.OwnerID))
11675 NotImplemented("llGodLikeRezObject");
11676
11677 AssetBase rezAsset = World.AssetService.Get(inventory);
11678 if (rezAsset == null)
11679 {
11680 llSay(0, "Asset not found");
11681 return;
11682 }
11683
11684 SceneObjectGroup group = null;
11685
11686 try
11687 {
11688 string xmlData = Utils.BytesToString(rezAsset.Data);
11689 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
11690 }
11691 catch
11692 {
11693 llSay(0, "Asset not found");
11694 return;
11695 }
11696
11697 if (group == null)
11698 {
11699 llSay(0, "Asset not found");
11700 return;
11701 }
11702
11703 group.RootPart.AttachPoint = group.RootPart.Shape.State;
11704 group.RootPart.AttachOffset = group.AbsolutePosition;
11705
11706 group.ResetIDs();
11707
11708 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
11709 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
11710 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
11711 group.ScheduleGroupForFullUpdate();
11712
11713 // objects rezzed with this method are die_at_edge by default.
11714 group.RootPart.SetDieAtEdge(true);
11715
11716 group.ResumeScripts();
11717
11718 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
11719 "object_rez", new Object[] {
11720 new LSL_String(
11721 group.RootPart.UUID.ToString()) },
11722 new DetectParams[0]));
11723 }
11724
11725 public LSL_String llTransferLindenDollars(string destination, int amount)
11726 {
11727 UUID txn = UUID.Random();
11728
11729 Util.FireAndForget(delegate(object x)
11730 {
11731 int replycode = 0;
11732 string replydata = destination + "," + amount.ToString();
11733
11734 try
11735 {
11736 UUID invItemID=InventorySelf();
11737 if (invItemID == UUID.Zero)
11738 {
11739 replydata = "SERVICE_ERROR";
11740 return;
11741 }
11742
11743 m_host.AddScriptLPS(1);
11744
11745 m_host.TaskInventory.LockItemsForRead(true);
11746 TaskInventoryItem item = m_host.TaskInventory[invItemID];
11747 m_host.TaskInventory.LockItemsForRead(false);
11748
11749 if (item.PermsGranter == UUID.Zero)
11750 {
11751 replydata = "MISSING_PERMISSION_DEBIT";
11752 return;
11753 }
11754
11755 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
11756 {
11757 replydata = "MISSING_PERMISSION_DEBIT";
11758 return;
11759 }
11760
11761 UUID toID = new UUID();
11762
11763 if (!UUID.TryParse(destination, out toID))
11764 {
11765 replydata = "INVALID_AGENT";
11766 return;
11767 }
11768
11769 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
11770
11771 if (money == null)
11772 {
11773 replydata = "TRANSFERS_DISABLED";
11774 return;
11775 }
11776
11777 bool result = money.ObjectGiveMoney(
11778 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
11779
11780 if (result)
11781 {
11782 replycode = 1;
11783 return;
11784 }
11785
11786 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
11787 }
11788 finally
11789 {
11790 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
11791 "transaction_result", new Object[] {
11792 new LSL_String(txn.ToString()),
11793 new LSL_Integer(replycode),
11794 new LSL_String(replydata) },
11795 new DetectParams[0]));
11796 }
11797 });
11798
11799 return txn.ToString();
10801 } 11800 }
10802 11801
10803 #endregion 11802 #endregion
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index b1583eb..c83df4e 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 private void InitLSL() 221 private void InitLSL()
@@ -917,18 +926,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
917 if (target != null) 926 if (target != null)
918 { 927 {
919 UUID animID=UUID.Zero; 928 UUID animID=UUID.Zero;
920 lock (m_host.TaskInventory) 929 m_host.TaskInventory.LockItemsForRead(true);
930 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
921 { 931 {
922 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 932 if (inv.Value.Name == animation)
923 { 933 {
924 if (inv.Value.Name == animation) 934 if (inv.Value.Type == (int)AssetType.Animation)
925 { 935 animID = inv.Value.AssetID;
926 if (inv.Value.Type == (int)AssetType.Animation) 936 continue;
927 animID = inv.Value.AssetID;
928 continue;
929 }
930 } 937 }
931 } 938 }
939 m_host.TaskInventory.LockItemsForRead(false);
932 if (animID == UUID.Zero) 940 if (animID == UUID.Zero)
933 target.Animator.AddAnimation(animation, m_host.UUID); 941 target.Animator.AddAnimation(animation, m_host.UUID);
934 else 942 else
@@ -955,18 +963,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
955 if (target != null) 963 if (target != null)
956 { 964 {
957 UUID animID = UUID.Zero; 965 UUID animID = UUID.Zero;
958 lock (m_host.TaskInventory) 966 m_host.TaskInventory.LockItemsForRead(true);
967 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
959 { 968 {
960 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 969 if (inv.Value.Name == animation)
961 { 970 {
962 if (inv.Value.Name == animation) 971 if (inv.Value.Type == (int)AssetType.Animation)
963 { 972 animID = inv.Value.AssetID;
964 if (inv.Value.Type == (int)AssetType.Animation) 973 continue;
965 animID = inv.Value.AssetID;
966 continue;
967 }
968 } 974 }
969 } 975 }
976 m_host.TaskInventory.LockItemsForRead(false);
970 977
971 if (animID == UUID.Zero) 978 if (animID == UUID.Zero)
972 target.Animator.RemoveAnimation(animation); 979 target.Animator.RemoveAnimation(animation);
@@ -1798,6 +1805,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1798 1805
1799 if (!UUID.TryParse(notecardNameOrUuid, out assetID)) 1806 if (!UUID.TryParse(notecardNameOrUuid, out assetID))
1800 { 1807 {
1808 m_host.TaskInventory.LockItemsForRead(true);
1801 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1809 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1802 { 1810 {
1803 if (item.Type == 7 && item.Name == notecardNameOrUuid) 1811 if (item.Type == 7 && item.Name == notecardNameOrUuid)
@@ -1805,6 +1813,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1805 assetID = item.AssetID; 1813 assetID = item.AssetID;
1806 } 1814 }
1807 } 1815 }
1816 m_host.TaskInventory.LockItemsForRead(false);
1808 } 1817 }
1809 1818
1810 if (assetID == UUID.Zero) 1819 if (assetID == UUID.Zero)
@@ -2233,7 +2242,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2233 CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); 2242 CheckThreatLevel(ThreatLevel.High, "osNpcCreate");
2234 m_host.AddScriptLPS(1); 2243 m_host.AddScriptLPS(1);
2235 2244
2236 return NpcCreate(firstname, lastname, position, notecard, false, true); 2245 return NpcCreate(firstname, lastname, position, notecard, true, false);
2237 } 2246 }
2238 2247
2239 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options) 2248 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options)
@@ -2244,24 +2253,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2244 return NpcCreate( 2253 return NpcCreate(
2245 firstname, lastname, position, notecard, 2254 firstname, lastname, position, notecard,
2246 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0, 2255 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0,
2247 (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) == 0); 2256 false);
2257// (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) == 0);
2248 } 2258 }
2249 2259
2250 private LSL_Key NpcCreate( 2260 private LSL_Key NpcCreate(
2251 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent) 2261 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent)
2252 { 2262 {
2263 if (!owned)
2264 OSSLError("Unowned NPCs are unsupported");
2265
2266 string groupTitle = String.Empty;
2267
2268 if (firstname != String.Empty || lastname != String.Empty)
2269 {
2270 if (firstname != "Shown outfit:")
2271 groupTitle = "- NPC -";
2272 }
2273
2253 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2274 INPCModule module = World.RequestModuleInterface<INPCModule>();
2254 if (module != null) 2275 if (module != null)
2255 { 2276 {
2256 AvatarAppearance appearance = null; 2277 AvatarAppearance appearance = null;
2257 2278
2258 UUID id; 2279// UUID id;
2259 if (UUID.TryParse(notecard, out id)) 2280// if (UUID.TryParse(notecard, out id))
2260 { 2281// {
2261 ScenePresence clonePresence = World.GetScenePresence(id); 2282// ScenePresence clonePresence = World.GetScenePresence(id);
2262 if (clonePresence != null) 2283// if (clonePresence != null)
2263 appearance = clonePresence.Appearance; 2284// appearance = clonePresence.Appearance;
2264 } 2285// }
2265 2286
2266 if (appearance == null) 2287 if (appearance == null)
2267 { 2288 {
@@ -2289,6 +2310,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2289 World, 2310 World,
2290 appearance); 2311 appearance);
2291 2312
2313 ScenePresence sp;
2314 if (World.TryGetScenePresence(x, out sp))
2315 {
2316 sp.Grouptitle = groupTitle;
2317 sp.SendAvatarDataToAllAgents();
2318 }
2292 return new LSL_Key(x.ToString()); 2319 return new LSL_Key(x.ToString());
2293 } 2320 }
2294 2321
@@ -2557,16 +2584,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2557 CheckThreatLevel(ThreatLevel.High, "osNpcRemove"); 2584 CheckThreatLevel(ThreatLevel.High, "osNpcRemove");
2558 m_host.AddScriptLPS(1); 2585 m_host.AddScriptLPS(1);
2559 2586
2560 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2587 ManualResetEvent ev = new ManualResetEvent(false);
2561 if (module != null)
2562 {
2563 UUID npcId = new UUID(npc.m_string);
2564 2588
2565 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2589 Util.FireAndForget(delegate(object x) {
2566 return; 2590 try
2591 {
2592 INPCModule module = World.RequestModuleInterface<INPCModule>();
2593 if (module != null)
2594 {
2595 UUID npcId = new UUID(npc.m_string);
2567 2596
2568 module.DeleteNPC(npcId, World); 2597 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2569 } 2598 return;
2599
2600 module.DeleteNPC(npcId, World);
2601 }
2602 }
2603 finally
2604 {
2605 ev.Set();
2606 }
2607 });
2608 ev.WaitOne();
2570 } 2609 }
2571 2610
2572 public void osNpcPlayAnimation(LSL_Key npc, string animation) 2611 public void osNpcPlayAnimation(LSL_Key npc, string animation)
@@ -2917,4 +2956,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2917 return date.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); 2956 return date.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
2918 } 2957 }
2919 } 2958 }
2920} \ No newline at end of file 2959}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 850f50b..5c200d6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -209,7 +209,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
209 // Is the sensor type is AGENT and not SCRIPTED then include agents 209 // Is the sensor type is AGENT and not SCRIPTED then include agents
210 if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC)) != 0 && (ts.type & SCRIPTED) == 0) 210 if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC)) != 0 && (ts.type & SCRIPTED) == 0)
211 { 211 {
212 sensedEntities.AddRange(doAgentSensor(ts)); 212 sensedEntities.AddRange(doAgentSensor(ts));
213 } 213 }
214 214
215 // If SCRIPTED or PASSIVE or ACTIVE check objects 215 // If SCRIPTED or PASSIVE or ACTIVE check objects
@@ -306,13 +306,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
306 float dy; 306 float dy;
307 float dz; 307 float dz;
308 308
309 Quaternion q = SensePoint.RotationOffset; 309// Quaternion q = SensePoint.RotationOffset;
310 Quaternion q = SensePoint.GetWorldRotation(); // non-attached prim Sensor *always* uses World rotation!
310 if (SensePoint.ParentGroup.IsAttachment) 311 if (SensePoint.ParentGroup.IsAttachment)
311 { 312 {
312 // In attachments, the sensor cone always orients with the 313 // In attachments, the sensor cone always orients with the
313 // avatar rotation. This may include a nonzero elevation if 314 // avatar rotation. This may include a nonzero elevation if
314 // in mouselook. 315 // in mouselook.
315 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 316 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
317 fromRegionPos = avatar.AbsolutePosition;
316 q = avatar.Rotation; 318 q = avatar.Rotation;
317 } 319 }
318 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 320 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
@@ -435,6 +437,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
435 // avatar rotation. This may include a nonzero elevation if 437 // avatar rotation. This may include a nonzero elevation if
436 // in mouselook. 438 // in mouselook.
437 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 439 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
440 if (avatar == null)
441 return sensedEntities;
442 fromRegionPos = avatar.AbsolutePosition;
438 q = avatar.Rotation; 443 q = avatar.Rotation;
439 } 444 }
440 445
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
index eeb59d9..2fd33fe 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
@@ -109,25 +109,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
109 if (Timers.Count == 0) 109 if (Timers.Count == 0)
110 return; 110 return;
111 111
112 Dictionary<string, TimerClass>.ValueCollection tvals;
112 lock (TimerListLock) 113 lock (TimerListLock)
113 { 114 {
114 // Go through all timers 115 // Go through all timers
115 Dictionary<string, TimerClass>.ValueCollection tvals = Timers.Values; 116 tvals = Timers.Values;
116 foreach (TimerClass ts in tvals) 117 }
118
119 foreach (TimerClass ts in tvals)
120 {
121 // Time has passed?
122 if (ts.next < DateTime.Now.Ticks)
117 { 123 {
118 // Time has passed? 124 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next);
119 if (ts.next < DateTime.Now.Ticks) 125 // Add it to queue
120 { 126 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
121 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next); 127 new EventParams("timer", new Object[0],
122 // Add it to queue 128 new DetectParams[0]));
123 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, 129 // set next interval
124 new EventParams("timer", new Object[0], 130
125 new DetectParams[0])); 131 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
126 // set next interval 132 ts.next = DateTime.Now.Ticks + ts.interval;
127
128 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
129 ts.next = DateTime.Now.Ticks + ts.interval;
130 }
131 } 133 }
132 } 134 }
133 } 135 }