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.cs2810
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs78
-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, 2118 insertions, 949 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 fb5fd45..9c4bfb6 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;
478 554
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. 555 int numPis = (int)(Math.PI / angle);
480 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 556 double remainder = angle - Math.PI * numPis;
481 if (m == 0.0) return new LSL_Vector(); 557 if (numPis % 2 == 1)
482 double x = Math.Atan2(-v.y, v.z); 558 return Math.PI - angle;
483 double sin = v.x / m; 559 return remainder;
484 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. 560 }
485 double y = Math.Asin(sin); 561
486 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation 562 public LSL_Vector llRot2Euler(LSL_Rotation q1)
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))); 563 {
488 double z = Math.Atan2(v.y, v.x); 564 m_host.AddScriptLPS(1);
565 LSL_Vector eul = new LSL_Vector();
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();
@@ -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;
@@ -2778,6 +2978,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2778 if (dist > m_ScriptDistanceFactor * 10.0f) 2978 if (dist > m_ScriptDistanceFactor * 10.0f)
2779 return; 2979 return;
2780 2980
2981 //Clone is thread-safe
2781 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 2982 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
2782 2983
2783 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory) 2984 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
@@ -2806,7 +3007,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2806 // objects rezzed with this method are die_at_edge by default. 3007 // objects rezzed with this method are die_at_edge by default.
2807 new_group.RootPart.SetDieAtEdge(true); 3008 new_group.RootPart.SetDieAtEdge(true);
2808 3009
2809 new_group.ResumeScripts(); 3010 Util.FireAndForget(delegate (object x)
3011 {
3012 new_group.ResumeScripts();
3013 });
2810 3014
2811 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 3015 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
2812 "object_rez", new Object[] { 3016 "object_rez", new Object[] {
@@ -2839,34 +3043,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2839 public void llLookAt(LSL_Vector target, double strength, double damping) 3043 public void llLookAt(LSL_Vector target, double strength, double damping)
2840 { 3044 {
2841 m_host.AddScriptLPS(1); 3045 m_host.AddScriptLPS(1);
2842 // Determine where we are looking from
2843 LSL_Vector from = llGetPos();
2844 3046
2845 // Work out the normalised vector from the source to the target 3047 // Get the normalized vector to the target
2846 LSL_Vector delta = llVecNorm(target - from); 3048 LSL_Vector d1 = llVecNorm(target - llGetPos());
2847 LSL_Vector angle = new LSL_Vector(0,0,0);
2848 3049
2849 // Calculate the yaw 3050 // Get the bearing (yaw)
2850 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3051 LSL_Vector a1 = new LSL_Vector(0,0,0);
2851 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3052 a1.z = llAtan2(d1.y, d1.x);
2852 3053
2853 // Calculate pitch 3054 // Get the elevation (pitch)
2854 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3055 LSL_Vector a2 = new LSL_Vector(0,0,0);
3056 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2855 3057
2856 // we need to convert from a vector describing 3058 LSL_Rotation r1 = llEuler2Rot(a1);
2857 // the angles of rotation in radians into rotation value 3059 LSL_Rotation r2 = llEuler2Rot(a2);
3060 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2858 3061
2859 LSL_Rotation rot = llEuler2Rot(angle); 3062 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 { 3063 {
2865 llSetRot(rot); 3064 // Do nothing if either value is 0 (this has been checked in SL)
3065 if (strength <= 0.0 || damping <= 0.0)
3066 return;
3067
3068 llSetRot(r3 * r2 * r1);
2866 } 3069 }
2867 else 3070 else
2868 { 3071 {
2869 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3072 if (strength == 0)
3073 {
3074 llSetRot(r3 * r2 * r1);
3075 return;
3076 }
3077
3078 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2870 } 3079 }
2871 } 3080 }
2872 3081
@@ -2916,13 +3125,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2916 { 3125 {
2917 TaskInventoryItem item; 3126 TaskInventoryItem item;
2918 3127
2919 lock (m_host.TaskInventory) 3128 m_host.TaskInventory.LockItemsForRead(true);
3129 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2920 { 3130 {
2921 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3131 m_host.TaskInventory.LockItemsForRead(false);
2922 return; 3132 return;
2923 else 3133 }
2924 item = m_host.TaskInventory[InventorySelf()]; 3134 else
3135 {
3136 item = m_host.TaskInventory[InventorySelf()];
2925 } 3137 }
3138 m_host.TaskInventory.LockItemsForRead(false);
2926 3139
2927 if (item.PermsGranter != UUID.Zero) 3140 if (item.PermsGranter != UUID.Zero)
2928 { 3141 {
@@ -2944,13 +3157,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2944 { 3157 {
2945 TaskInventoryItem item; 3158 TaskInventoryItem item;
2946 3159
3160 m_host.TaskInventory.LockItemsForRead(true);
2947 lock (m_host.TaskInventory) 3161 lock (m_host.TaskInventory)
2948 { 3162 {
3163
2949 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3164 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3165 {
3166 m_host.TaskInventory.LockItemsForRead(false);
2950 return; 3167 return;
3168 }
2951 else 3169 else
3170 {
2952 item = m_host.TaskInventory[InventorySelf()]; 3171 item = m_host.TaskInventory[InventorySelf()];
3172 }
2953 } 3173 }
3174 m_host.TaskInventory.LockItemsForRead(false);
2954 3175
2955 m_host.AddScriptLPS(1); 3176 m_host.AddScriptLPS(1);
2956 3177
@@ -2982,19 +3203,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2982 { 3203 {
2983 m_host.AddScriptLPS(1); 3204 m_host.AddScriptLPS(1);
2984 3205
2985// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
2986// return;
2987
2988 TaskInventoryItem item; 3206 TaskInventoryItem item;
2989 3207
2990 lock (m_host.TaskInventory) 3208 m_host.TaskInventory.LockItemsForRead(true);
3209
3210 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2991 { 3211 {
2992 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3212 m_host.TaskInventory.LockItemsForRead(false);
2993 return; 3213 return;
2994 else 3214 }
2995 item = m_host.TaskInventory[InventorySelf()]; 3215 else
3216 {
3217 item = m_host.TaskInventory[InventorySelf()];
2996 } 3218 }
2997 3219
3220 m_host.TaskInventory.LockItemsForRead(false);
3221
2998 if (item.PermsGranter != m_host.OwnerID) 3222 if (item.PermsGranter != m_host.OwnerID)
2999 return; 3223 return;
3000 3224
@@ -3019,13 +3243,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3019 3243
3020 TaskInventoryItem item; 3244 TaskInventoryItem item;
3021 3245
3022 lock (m_host.TaskInventory) 3246 m_host.TaskInventory.LockItemsForRead(true);
3247
3248 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3023 { 3249 {
3024 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3250 m_host.TaskInventory.LockItemsForRead(false);
3025 return; 3251 return;
3026 else
3027 item = m_host.TaskInventory[InventorySelf()];
3028 } 3252 }
3253 else
3254 {
3255 item = m_host.TaskInventory[InventorySelf()];
3256 }
3257 m_host.TaskInventory.LockItemsForRead(false);
3258
3029 3259
3030 if (item.PermsGranter != m_host.OwnerID) 3260 if (item.PermsGranter != m_host.OwnerID)
3031 return; 3261 return;
@@ -3072,6 +3302,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3072 3302
3073 public void llInstantMessage(string user, string message) 3303 public void llInstantMessage(string user, string message)
3074 { 3304 {
3305 UUID result;
3306 if (!UUID.TryParse(user, out result))
3307 {
3308 ShoutError("An invalid key was passed to llInstantMessage");
3309 ScriptSleep(2000);
3310 return;
3311 }
3312
3313
3075 m_host.AddScriptLPS(1); 3314 m_host.AddScriptLPS(1);
3076 3315
3077 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3316 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3086,14 +3325,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3086 UUID friendTransactionID = UUID.Random(); 3325 UUID friendTransactionID = UUID.Random();
3087 3326
3088 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3327 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3089 3328
3090 GridInstantMessage msg = new GridInstantMessage(); 3329 GridInstantMessage msg = new GridInstantMessage();
3091 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3330 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3092 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3331 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3093 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3332 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); 3333// 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()); 3334// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3096 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3335// DateTime dt = DateTime.UtcNow;
3336//
3337// // Ticks from UtcNow, but make it look like local. Evil, huh?
3338// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3339//
3340// try
3341// {
3342// // Convert that to the PST timezone
3343// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3344// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3345// }
3346// catch
3347// {
3348// // No logging here, as it could be VERY spammy
3349// }
3350//
3351// // And make it look local again to fool the unix time util
3352// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3353
3354 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3355
3097 //if (client != null) 3356 //if (client != null)
3098 //{ 3357 //{
3099 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3358 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3107,12 +3366,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3107 msg.message = message.Substring(0, 1024); 3366 msg.message = message.Substring(0, 1024);
3108 else 3367 else
3109 msg.message = message; 3368 msg.message = message;
3110 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3369 msg.dialog = (byte)19; // MessageFromObject
3111 msg.fromGroup = false;// fromGroup; 3370 msg.fromGroup = false;// fromGroup;
3112 msg.offline = (byte)0; //offline; 3371 msg.offline = (byte)0; //offline;
3113 msg.ParentEstateID = 0; //ParentEstateID; 3372 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3114 msg.Position = new Vector3(m_host.AbsolutePosition); 3373 msg.Position = new Vector3(m_host.AbsolutePosition);
3115 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3374 msg.RegionID = World.RegionInfo.RegionID.Guid;
3116 msg.binaryBucket 3375 msg.binaryBucket
3117 = Util.StringToBytes256( 3376 = Util.StringToBytes256(
3118 "{0}/{1}/{2}/{3}", 3377 "{0}/{1}/{2}/{3}",
@@ -3140,7 +3399,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3140 } 3399 }
3141 3400
3142 emailModule.SendEmail(m_host.UUID, address, subject, message); 3401 emailModule.SendEmail(m_host.UUID, address, subject, message);
3143 ScriptSleep(20000); 3402 ScriptSleep(15000);
3144 } 3403 }
3145 3404
3146 public void llGetNextEmail(string address, string subject) 3405 public void llGetNextEmail(string address, string subject)
@@ -3279,14 +3538,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3279 3538
3280 TaskInventoryItem item; 3539 TaskInventoryItem item;
3281 3540
3282 lock (m_host.TaskInventory) 3541 m_host.TaskInventory.LockItemsForRead(true);
3542 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3283 { 3543 {
3284 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3544 m_host.TaskInventory.LockItemsForRead(false);
3285 return; 3545 return;
3286 else
3287 item = m_host.TaskInventory[InventorySelf()];
3288 } 3546 }
3289 3547 else
3548 {
3549 item = m_host.TaskInventory[InventorySelf()];
3550 }
3551 m_host.TaskInventory.LockItemsForRead(false);
3290 if (item.PermsGranter == UUID.Zero) 3552 if (item.PermsGranter == UUID.Zero)
3291 return; 3553 return;
3292 3554
@@ -3316,13 +3578,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3316 3578
3317 TaskInventoryItem item; 3579 TaskInventoryItem item;
3318 3580
3319 lock (m_host.TaskInventory) 3581 m_host.TaskInventory.LockItemsForRead(true);
3582 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3320 { 3583 {
3321 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3584 m_host.TaskInventory.LockItemsForRead(false);
3322 return; 3585 return;
3323 else
3324 item = m_host.TaskInventory[InventorySelf()];
3325 } 3586 }
3587 else
3588 {
3589 item = m_host.TaskInventory[InventorySelf()];
3590 }
3591 m_host.TaskInventory.LockItemsForRead(false);
3592
3326 3593
3327 if (item.PermsGranter == UUID.Zero) 3594 if (item.PermsGranter == UUID.Zero)
3328 return; 3595 return;
@@ -3389,10 +3656,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3389 3656
3390 TaskInventoryItem item; 3657 TaskInventoryItem item;
3391 3658
3392 lock (m_host.TaskInventory) 3659
3660 m_host.TaskInventory.LockItemsForRead(true);
3661 if (!m_host.TaskInventory.ContainsKey(invItemID))
3662 {
3663 m_host.TaskInventory.LockItemsForRead(false);
3664 return;
3665 }
3666 else
3393 { 3667 {
3394 item = m_host.TaskInventory[invItemID]; 3668 item = m_host.TaskInventory[invItemID];
3395 } 3669 }
3670 m_host.TaskInventory.LockItemsForRead(false);
3396 3671
3397 if (agentID == UUID.Zero || perm == 0) // Releasing permissions 3672 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
3398 { 3673 {
@@ -3420,15 +3695,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3420 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3695 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3421 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3696 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3422 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3697 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3698 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3423 ScriptBaseClass.PERMISSION_ATTACH; 3699 ScriptBaseClass.PERMISSION_ATTACH;
3424 3700
3425 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3701 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3426 { 3702 {
3427 lock (m_host.TaskInventory) 3703 m_host.TaskInventory.LockItemsForWrite(true);
3428 { 3704 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3429 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3705 m_host.TaskInventory[invItemID].PermsMask = perm;
3430 m_host.TaskInventory[invItemID].PermsMask = perm; 3706 m_host.TaskInventory.LockItemsForWrite(false);
3431 }
3432 3707
3433 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3708 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3434 "run_time_permissions", new Object[] { 3709 "run_time_permissions", new Object[] {
@@ -3438,28 +3713,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3438 return; 3713 return;
3439 } 3714 }
3440 } 3715 }
3441 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3716 else
3442 { 3717 {
3443 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3718 bool sitting = false;
3444 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3719 if (m_host.SitTargetAvatar == agentID)
3445 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3720 {
3446 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3721 sitting = true;
3447 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3722 }
3723 else
3724 {
3725 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3726 {
3727 if (p.SitTargetAvatar == agentID)
3728 sitting = true;
3729 }
3730 }
3448 3731
3449 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3732 if (sitting)
3450 { 3733 {
3451 lock (m_host.TaskInventory) 3734 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3735 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3736 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3737 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3738 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3739
3740 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3452 { 3741 {
3742 m_host.TaskInventory.LockItemsForWrite(true);
3453 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3743 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3454 m_host.TaskInventory[invItemID].PermsMask = perm; 3744 m_host.TaskInventory[invItemID].PermsMask = perm;
3455 } 3745 m_host.TaskInventory.LockItemsForWrite(false);
3456 3746
3457 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3747 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3458 "run_time_permissions", new Object[] { 3748 "run_time_permissions", new Object[] {
3459 new LSL_Integer(perm) }, 3749 new LSL_Integer(perm) },
3460 new DetectParams[0])); 3750 new DetectParams[0]));
3461 3751
3462 return; 3752 return;
3753 }
3463 } 3754 }
3464 } 3755 }
3465 3756
@@ -3473,11 +3764,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3473 3764
3474 if (!m_waitingForScriptAnswer) 3765 if (!m_waitingForScriptAnswer)
3475 { 3766 {
3476 lock (m_host.TaskInventory) 3767 m_host.TaskInventory.LockItemsForWrite(true);
3477 { 3768 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3478 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3769 m_host.TaskInventory[invItemID].PermsMask = 0;
3479 m_host.TaskInventory[invItemID].PermsMask = 0; 3770 m_host.TaskInventory.LockItemsForWrite(false);
3480 }
3481 3771
3482 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3772 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3483 m_waitingForScriptAnswer=true; 3773 m_waitingForScriptAnswer=true;
@@ -3512,10 +3802,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3512 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3802 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3513 llReleaseControls(); 3803 llReleaseControls();
3514 3804
3515 lock (m_host.TaskInventory) 3805
3516 { 3806 m_host.TaskInventory.LockItemsForWrite(true);
3517 m_host.TaskInventory[invItemID].PermsMask = answer; 3807 m_host.TaskInventory[invItemID].PermsMask = answer;
3518 } 3808 m_host.TaskInventory.LockItemsForWrite(false);
3809
3519 3810
3520 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3811 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3521 "run_time_permissions", new Object[] { 3812 "run_time_permissions", new Object[] {
@@ -3527,16 +3818,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3527 { 3818 {
3528 m_host.AddScriptLPS(1); 3819 m_host.AddScriptLPS(1);
3529 3820
3530 lock (m_host.TaskInventory) 3821 m_host.TaskInventory.LockItemsForRead(true);
3822
3823 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3531 { 3824 {
3532 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3825 if (item.Type == 10 && item.ItemID == m_itemID)
3533 { 3826 {
3534 if (item.Type == 10 && item.ItemID == m_itemID) 3827 m_host.TaskInventory.LockItemsForRead(false);
3535 { 3828 return item.PermsGranter.ToString();
3536 return item.PermsGranter.ToString();
3537 }
3538 } 3829 }
3539 } 3830 }
3831 m_host.TaskInventory.LockItemsForRead(false);
3540 3832
3541 return UUID.Zero.ToString(); 3833 return UUID.Zero.ToString();
3542 } 3834 }
@@ -3545,19 +3837,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3545 { 3837 {
3546 m_host.AddScriptLPS(1); 3838 m_host.AddScriptLPS(1);
3547 3839
3548 lock (m_host.TaskInventory) 3840 m_host.TaskInventory.LockItemsForRead(true);
3841
3842 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3549 { 3843 {
3550 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3844 if (item.Type == 10 && item.ItemID == m_itemID)
3551 { 3845 {
3552 if (item.Type == 10 && item.ItemID == m_itemID) 3846 int perms = item.PermsMask;
3553 { 3847 if (m_automaticLinkPermission)
3554 int perms = item.PermsMask; 3848 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
3555 if (m_automaticLinkPermission) 3849 m_host.TaskInventory.LockItemsForRead(false);
3556 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 3850 return perms;
3557 return perms;
3558 }
3559 } 3851 }
3560 } 3852 }
3853 m_host.TaskInventory.LockItemsForRead(false);
3561 3854
3562 return 0; 3855 return 0;
3563 } 3856 }
@@ -3579,9 +3872,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3579 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3872 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3580 { 3873 {
3581 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3874 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3582 3875 if (parts.Count > 0)
3583 foreach (SceneObjectPart part in parts) 3876 {
3584 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3877 try
3878 {
3879 parts[0].ParentGroup.areUpdatesSuspended = true;
3880 foreach (SceneObjectPart part in parts)
3881 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3882 }
3883 finally
3884 {
3885 parts[0].ParentGroup.areUpdatesSuspended = false;
3886 }
3887 }
3585 } 3888 }
3586 3889
3587 public void llCreateLink(string target, int parent) 3890 public void llCreateLink(string target, int parent)
@@ -3594,11 +3897,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3594 return; 3897 return;
3595 3898
3596 TaskInventoryItem item; 3899 TaskInventoryItem item;
3597 lock (m_host.TaskInventory) 3900 m_host.TaskInventory.LockItemsForRead(true);
3598 { 3901 item = m_host.TaskInventory[invItemID];
3599 item = m_host.TaskInventory[invItemID]; 3902 m_host.TaskInventory.LockItemsForRead(false);
3600 } 3903
3601
3602 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3904 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3603 && !m_automaticLinkPermission) 3905 && !m_automaticLinkPermission)
3604 { 3906 {
@@ -3615,11 +3917,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3615 3917
3616 if (targetPart.ParentGroup.AttachmentPoint != 0) 3918 if (targetPart.ParentGroup.AttachmentPoint != 0)
3617 return; // Fail silently if attached 3919 return; // Fail silently if attached
3920
3921 if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID)
3922 return;
3923
3618 SceneObjectGroup parentPrim = null, childPrim = null; 3924 SceneObjectGroup parentPrim = null, childPrim = null;
3619 3925
3620 if (targetPart != null) 3926 if (targetPart != null)
3621 { 3927 {
3622 if (parent != 0) { 3928 if (parent != 0)
3929 {
3623 parentPrim = m_host.ParentGroup; 3930 parentPrim = m_host.ParentGroup;
3624 childPrim = targetPart.ParentGroup; 3931 childPrim = targetPart.ParentGroup;
3625 } 3932 }
@@ -3650,16 +3957,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3650 m_host.AddScriptLPS(1); 3957 m_host.AddScriptLPS(1);
3651 UUID invItemID = InventorySelf(); 3958 UUID invItemID = InventorySelf();
3652 3959
3653 lock (m_host.TaskInventory) 3960 m_host.TaskInventory.LockItemsForRead(true);
3654 {
3655 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3961 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3656 && !m_automaticLinkPermission) 3962 && !m_automaticLinkPermission)
3657 { 3963 {
3658 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 3964 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
3965 m_host.TaskInventory.LockItemsForRead(false);
3659 return; 3966 return;
3660 } 3967 }
3661 } 3968 m_host.TaskInventory.LockItemsForRead(false);
3662 3969
3663 if (linknum < ScriptBaseClass.LINK_THIS) 3970 if (linknum < ScriptBaseClass.LINK_THIS)
3664 return; 3971 return;
3665 3972
@@ -3698,10 +4005,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3698 // Restructuring Multiple Prims. 4005 // Restructuring Multiple Prims.
3699 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4006 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3700 parts.Remove(parentPrim.RootPart); 4007 parts.Remove(parentPrim.RootPart);
3701 foreach (SceneObjectPart part in parts) 4008 if (parts.Count > 0)
3702 { 4009 {
3703 parentPrim.DelinkFromGroup(part.LocalId, true); 4010 try
4011 {
4012 parts[0].ParentGroup.areUpdatesSuspended = true;
4013 foreach (SceneObjectPart part in parts)
4014 {
4015 parentPrim.DelinkFromGroup(part.LocalId, true);
4016 }
4017 }
4018 finally
4019 {
4020 parts[0].ParentGroup.areUpdatesSuspended = false;
4021 }
3704 } 4022 }
4023
3705 parentPrim.HasGroupChanged = true; 4024 parentPrim.HasGroupChanged = true;
3706 parentPrim.ScheduleGroupForFullUpdate(); 4025 parentPrim.ScheduleGroupForFullUpdate();
3707 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4026 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3710,12 +4029,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3710 { 4029 {
3711 SceneObjectPart newRoot = parts[0]; 4030 SceneObjectPart newRoot = parts[0];
3712 parts.Remove(newRoot); 4031 parts.Remove(newRoot);
3713 foreach (SceneObjectPart part in parts) 4032
4033 try
3714 { 4034 {
3715 // Required for linking 4035 parts[0].ParentGroup.areUpdatesSuspended = true;
3716 part.ClearUpdateSchedule(); 4036 foreach (SceneObjectPart part in parts)
3717 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4037 {
4038 part.ClearUpdateSchedule();
4039 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4040 }
3718 } 4041 }
4042 finally
4043 {
4044 parts[0].ParentGroup.areUpdatesSuspended = false;
4045 }
4046
4047
3719 newRoot.ParentGroup.HasGroupChanged = true; 4048 newRoot.ParentGroup.HasGroupChanged = true;
3720 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4049 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3721 } 4050 }
@@ -3735,6 +4064,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3735 public void llBreakAllLinks() 4064 public void llBreakAllLinks()
3736 { 4065 {
3737 m_host.AddScriptLPS(1); 4066 m_host.AddScriptLPS(1);
4067
4068 UUID invItemID = InventorySelf();
4069
4070 TaskInventoryItem item;
4071 m_host.TaskInventory.LockItemsForRead(true);
4072 item = m_host.TaskInventory[invItemID];
4073 m_host.TaskInventory.LockItemsForRead(false);
4074
4075 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4076 && !m_automaticLinkPermission)
4077 {
4078 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4079 return;
4080 }
4081
3738 SceneObjectGroup parentPrim = m_host.ParentGroup; 4082 SceneObjectGroup parentPrim = m_host.ParentGroup;
3739 if (parentPrim.AttachmentPoint != 0) 4083 if (parentPrim.AttachmentPoint != 0)
3740 return; // Fail silently if attached 4084 return; // Fail silently if attached
@@ -3754,25 +4098,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3754 public LSL_String llGetLinkKey(int linknum) 4098 public LSL_String llGetLinkKey(int linknum)
3755 { 4099 {
3756 m_host.AddScriptLPS(1); 4100 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); 4101 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3777 if (part != null) 4102 if (part != null)
3778 { 4103 {
@@ -3780,6 +4105,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3780 } 4105 }
3781 else 4106 else
3782 { 4107 {
4108 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4109 {
4110 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4111
4112 if (linknum < 0)
4113 return UUID.Zero.ToString();
4114
4115 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4116 if (avatars.Count > linknum)
4117 {
4118 return avatars[linknum].UUID.ToString();
4119 }
4120 }
3783 return UUID.Zero.ToString(); 4121 return UUID.Zero.ToString();
3784 } 4122 }
3785 } 4123 }
@@ -3878,17 +4216,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3878 m_host.AddScriptLPS(1); 4216 m_host.AddScriptLPS(1);
3879 int count = 0; 4217 int count = 0;
3880 4218
3881 lock (m_host.TaskInventory) 4219 m_host.TaskInventory.LockItemsForRead(true);
4220 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3882 { 4221 {
3883 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4222 if (inv.Value.Type == type || type == -1)
3884 { 4223 {
3885 if (inv.Value.Type == type || type == -1) 4224 count = count + 1;
3886 {
3887 count = count + 1;
3888 }
3889 } 4225 }
3890 } 4226 }
3891 4227
4228 m_host.TaskInventory.LockItemsForRead(false);
3892 return count; 4229 return count;
3893 } 4230 }
3894 4231
@@ -3897,16 +4234,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3897 m_host.AddScriptLPS(1); 4234 m_host.AddScriptLPS(1);
3898 ArrayList keys = new ArrayList(); 4235 ArrayList keys = new ArrayList();
3899 4236
3900 lock (m_host.TaskInventory) 4237 m_host.TaskInventory.LockItemsForRead(true);
4238 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3901 { 4239 {
3902 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4240 if (inv.Value.Type == type || type == -1)
3903 { 4241 {
3904 if (inv.Value.Type == type || type == -1) 4242 keys.Add(inv.Value.Name);
3905 {
3906 keys.Add(inv.Value.Name);
3907 }
3908 } 4243 }
3909 } 4244 }
4245 m_host.TaskInventory.LockItemsForRead(false);
3910 4246
3911 if (keys.Count == 0) 4247 if (keys.Count == 0)
3912 { 4248 {
@@ -3943,25 +4279,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3943 } 4279 }
3944 4280
3945 // move the first object found with this inventory name 4281 // move the first object found with this inventory name
3946 lock (m_host.TaskInventory) 4282 m_host.TaskInventory.LockItemsForRead(true);
4283 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3947 { 4284 {
3948 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4285 if (inv.Value.Name == inventory)
3949 { 4286 {
3950 if (inv.Value.Name == inventory) 4287 found = true;
3951 { 4288 objId = inv.Key;
3952 found = true; 4289 assetType = inv.Value.Type;
3953 objId = inv.Key; 4290 objName = inv.Value.Name;
3954 assetType = inv.Value.Type; 4291 break;
3955 objName = inv.Value.Name;
3956 break;
3957 }
3958 } 4292 }
3959 } 4293 }
4294 m_host.TaskInventory.LockItemsForRead(false);
3960 4295
3961 if (!found) 4296 if (!found)
3962 { 4297 {
3963 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4298 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)); 4299 return;
4300// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3965 } 4301 }
3966 4302
3967 // check if destination is an object 4303 // check if destination is an object
@@ -3987,48 +4323,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3987 return; 4323 return;
3988 } 4324 }
3989 } 4325 }
4326
3990 // destination is an avatar 4327 // destination is an avatar
3991 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4328 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3992 4329
3993 if (agentItem == null) 4330 if (agentItem == null)
3994 return; 4331 return;
3995 4332
3996 byte[] bucket = new byte[17]; 4333 byte[] bucket = new byte[1];
3997 bucket[0] = (byte)assetType; 4334 bucket[0] = (byte)assetType;
3998 byte[] objBytes = agentItem.ID.GetBytes(); 4335 //byte[] objBytes = agentItem.ID.GetBytes();
3999 Array.Copy(objBytes, 0, bucket, 1, 16); 4336 //Array.Copy(objBytes, 0, bucket, 1, 16);
4000 4337
4001 GridInstantMessage msg = new GridInstantMessage(World, 4338 GridInstantMessage msg = new GridInstantMessage(World,
4002 m_host.UUID, m_host.Name+", an object owned by "+ 4339 m_host.OwnerID, m_host.Name, destId,
4003 resolveName(m_host.OwnerID)+",", destId,
4004 (byte)InstantMessageDialog.TaskInventoryOffered, 4340 (byte)InstantMessageDialog.TaskInventoryOffered,
4005 false, objName+"\n"+m_host.Name+" is located at "+ 4341 false, objName+". "+m_host.Name+" is located at "+
4006 World.RegionInfo.RegionName+" "+ 4342 World.RegionInfo.RegionName+" "+
4007 m_host.AbsolutePosition.ToString(), 4343 m_host.AbsolutePosition.ToString(),
4008 agentItem.ID, true, m_host.AbsolutePosition, 4344 agentItem.ID, true, m_host.AbsolutePosition,
4009 bucket); 4345 bucket);
4010 if (m_TransferModule != null) 4346
4011 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4347 ScenePresence sp;
4348
4349 if (World.TryGetScenePresence(destId, out sp))
4350 {
4351 sp.ControllingClient.SendInstantMessage(msg);
4352 }
4353 else
4354 {
4355 if (m_TransferModule != null)
4356 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4357 }
4358
4359 //This delay should only occur when giving inventory to avatars.
4012 ScriptSleep(3000); 4360 ScriptSleep(3000);
4013 } 4361 }
4014 } 4362 }
4015 4363
4364 [DebuggerNonUserCode]
4016 public void llRemoveInventory(string name) 4365 public void llRemoveInventory(string name)
4017 { 4366 {
4018 m_host.AddScriptLPS(1); 4367 m_host.AddScriptLPS(1);
4019 4368
4020 lock (m_host.TaskInventory) 4369 List<TaskInventoryItem> inv;
4370 try
4021 { 4371 {
4022 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4372 m_host.TaskInventory.LockItemsForRead(true);
4373 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4374 }
4375 finally
4376 {
4377 m_host.TaskInventory.LockItemsForRead(false);
4378 }
4379 foreach (TaskInventoryItem item in inv)
4380 {
4381 if (item.Name == name)
4023 { 4382 {
4024 if (item.Name == name) 4383 if (item.ItemID == m_itemID)
4025 { 4384 throw new ScriptDeleteException();
4026 if (item.ItemID == m_itemID) 4385 else
4027 throw new ScriptDeleteException(); 4386 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4028 else 4387 return;
4029 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4030 return;
4031 }
4032 } 4388 }
4033 } 4389 }
4034 } 4390 }
@@ -4063,112 +4419,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4063 { 4419 {
4064 m_host.AddScriptLPS(1); 4420 m_host.AddScriptLPS(1);
4065 4421
4066 UUID uuid = (UUID)id; 4422 UUID uuid;
4067 PresenceInfo pinfo = null; 4423 if (UUID.TryParse(id, out uuid))
4068 UserAccount account;
4069
4070 UserInfoCacheEntry ce;
4071 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4072 { 4424 {
4073 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4425 PresenceInfo pinfo = null;
4074 if (account == null) 4426 UserAccount account;
4427
4428 UserInfoCacheEntry ce;
4429 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4075 { 4430 {
4076 m_userInfoCache[uuid] = null; // Cache negative 4431 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4077 return UUID.Zero.ToString(); 4432 if (account == null)
4078 } 4433 {
4434 m_userInfoCache[uuid] = null; // Cache negative
4435 return UUID.Zero.ToString();
4436 }
4079 4437
4080 4438
4081 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4439 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4082 if (pinfos != null && pinfos.Length > 0) 4440 if (pinfos != null && pinfos.Length > 0)
4083 {
4084 foreach (PresenceInfo p in pinfos)
4085 { 4441 {
4086 if (p.RegionID != UUID.Zero) 4442 foreach (PresenceInfo p in pinfos)
4087 { 4443 {
4088 pinfo = p; 4444 if (p.RegionID != UUID.Zero)
4445 {
4446 pinfo = p;
4447 }
4089 } 4448 }
4090 } 4449 }
4091 }
4092 4450
4093 ce = new UserInfoCacheEntry(); 4451 ce = new UserInfoCacheEntry();
4094 ce.time = Util.EnvironmentTickCount(); 4452 ce.time = Util.EnvironmentTickCount();
4095 ce.account = account; 4453 ce.account = account;
4096 ce.pinfo = pinfo; 4454 ce.pinfo = pinfo;
4097 } 4455 m_userInfoCache[uuid] = ce;
4098 else 4456 }
4099 { 4457 else
4100 if (ce == null) 4458 {
4101 return UUID.Zero.ToString(); 4459 if (ce == null)
4460 return UUID.Zero.ToString();
4102 4461
4103 account = ce.account; 4462 account = ce.account;
4104 pinfo = ce.pinfo; 4463 pinfo = ce.pinfo;
4105 } 4464 }
4106 4465
4107 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4466 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 { 4467 {
4112 foreach (PresenceInfo p in pinfos) 4468 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4469 if (pinfos != null && pinfos.Length > 0)
4113 { 4470 {
4114 if (p.RegionID != UUID.Zero) 4471 foreach (PresenceInfo p in pinfos)
4115 { 4472 {
4116 pinfo = p; 4473 if (p.RegionID != UUID.Zero)
4474 {
4475 pinfo = p;
4476 }
4117 } 4477 }
4118 } 4478 }
4119 } 4479 else
4120 else 4480 pinfo = null;
4121 pinfo = null;
4122 4481
4123 ce.time = Util.EnvironmentTickCount(); 4482 ce.time = Util.EnvironmentTickCount();
4124 ce.pinfo = pinfo; 4483 ce.pinfo = pinfo;
4125 } 4484 }
4126 4485
4127 string reply = String.Empty; 4486 string reply = String.Empty;
4128 4487
4129 switch (data) 4488 switch (data)
4130 { 4489 {
4131 case 1: // DATA_ONLINE (0|1) 4490 case 1: // DATA_ONLINE (0|1)
4132 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4491 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4133 reply = "1"; 4492 reply = "1";
4134 else 4493 else
4135 reply = "0"; 4494 reply = "0";
4136 break; 4495 break;
4137 case 2: // DATA_NAME (First Last) 4496 case 2: // DATA_NAME (First Last)
4138 reply = account.FirstName + " " + account.LastName; 4497 reply = account.FirstName + " " + account.LastName;
4139 break; 4498 break;
4140 case 3: // DATA_BORN (YYYY-MM-DD) 4499 case 3: // DATA_BORN (YYYY-MM-DD)
4141 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4500 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4142 born = born.AddSeconds(account.Created); 4501 born = born.AddSeconds(account.Created);
4143 reply = born.ToString("yyyy-MM-dd"); 4502 reply = born.ToString("yyyy-MM-dd");
4144 break; 4503 break;
4145 case 4: // DATA_RATING (0,0,0,0,0,0) 4504 case 4: // DATA_RATING (0,0,0,0,0,0)
4146 reply = "0,0,0,0,0,0"; 4505 reply = "0,0,0,0,0,0";
4147 break; 4506 break;
4148 case 8: // DATA_PAYINFO (0|1|2|3) 4507 case 8: // DATA_PAYINFO (0|1|2|3)
4149 reply = "0"; 4508 reply = "0";
4150 break; 4509 break;
4151 default: 4510 default:
4152 return UUID.Zero.ToString(); // Raise no event 4511 return UUID.Zero.ToString(); // Raise no event
4153 } 4512 }
4154 4513
4155 UUID rq = UUID.Random(); 4514 UUID rq = UUID.Random();
4156 4515
4157 UUID tid = AsyncCommands. 4516 UUID tid = AsyncCommands.
4158 DataserverPlugin.RegisterRequest(m_localID, 4517 DataserverPlugin.RegisterRequest(m_localID,
4159 m_itemID, rq.ToString()); 4518 m_itemID, rq.ToString());
4160 4519
4161 AsyncCommands. 4520 AsyncCommands.
4162 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4521 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4163 4522
4164 ScriptSleep(100); 4523 ScriptSleep(100);
4165 return tid.ToString(); 4524 return tid.ToString();
4525 }
4526 else
4527 {
4528 ShoutError("Invalid UUID passed to llRequestAgentData.");
4529 }
4530 return "";
4166 } 4531 }
4167 4532
4168 public LSL_String llRequestInventoryData(string name) 4533 public LSL_String llRequestInventoryData(string name)
4169 { 4534 {
4170 m_host.AddScriptLPS(1); 4535 m_host.AddScriptLPS(1);
4171 4536
4537 //Clone is thread safe
4172 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4538 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4173 4539
4174 foreach (TaskInventoryItem item in itemDictionary.Values) 4540 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4222,6 +4588,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4222 ScenePresence presence = World.GetScenePresence(agentId); 4588 ScenePresence presence = World.GetScenePresence(agentId);
4223 if (presence != null) 4589 if (presence != null)
4224 { 4590 {
4591 // agent must not be a god
4592 if (presence.UserLevel >= 200) return;
4593
4225 // agent must be over the owners land 4594 // agent must be over the owners land
4226 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4595 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4227 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4596 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
@@ -4244,7 +4613,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4244 UUID av = new UUID(); 4613 UUID av = new UUID();
4245 if (!UUID.TryParse(agent,out av)) 4614 if (!UUID.TryParse(agent,out av))
4246 { 4615 {
4247 LSLError("First parameter to llDialog needs to be a key"); 4616 //LSLError("First parameter to llDialog needs to be a key");
4248 return; 4617 return;
4249 } 4618 }
4250 4619
@@ -4281,17 +4650,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4281 UUID soundId = UUID.Zero; 4650 UUID soundId = UUID.Zero;
4282 if (!UUID.TryParse(impact_sound, out soundId)) 4651 if (!UUID.TryParse(impact_sound, out soundId))
4283 { 4652 {
4284 lock (m_host.TaskInventory) 4653 m_host.TaskInventory.LockItemsForRead(true);
4654 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4285 { 4655 {
4286 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4656 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4287 { 4657 {
4288 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4658 soundId = item.AssetID;
4289 { 4659 break;
4290 soundId = item.AssetID;
4291 break;
4292 }
4293 } 4660 }
4294 } 4661 }
4662 m_host.TaskInventory.LockItemsForRead(false);
4295 } 4663 }
4296 m_host.CollisionSound = soundId; 4664 m_host.CollisionSound = soundId;
4297 m_host.CollisionSoundVolume = (float)impact_volume; 4665 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4331,6 +4699,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4331 UUID partItemID; 4699 UUID partItemID;
4332 foreach (SceneObjectPart part in parts) 4700 foreach (SceneObjectPart part in parts)
4333 { 4701 {
4702 //Clone is thread safe
4334 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4703 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4335 4704
4336 foreach (TaskInventoryItem item in itemsDictionary.Values) 4705 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4545,17 +4914,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4545 4914
4546 m_host.AddScriptLPS(1); 4915 m_host.AddScriptLPS(1);
4547 4916
4548 lock (m_host.TaskInventory) 4917 m_host.TaskInventory.LockItemsForRead(true);
4918 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4549 { 4919 {
4550 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4920 if (item.Type == 10 && item.ItemID == m_itemID)
4551 { 4921 {
4552 if (item.Type == 10 && item.ItemID == m_itemID) 4922 result = item.Name!=null?item.Name:String.Empty;
4553 { 4923 break;
4554 result = item.Name != null ? item.Name : String.Empty;
4555 break;
4556 }
4557 } 4924 }
4558 } 4925 }
4926 m_host.TaskInventory.LockItemsForRead(false);
4559 4927
4560 return result; 4928 return result;
4561 } 4929 }
@@ -4728,23 +5096,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4728 { 5096 {
4729 m_host.AddScriptLPS(1); 5097 m_host.AddScriptLPS(1);
4730 5098
4731 lock (m_host.TaskInventory) 5099 m_host.TaskInventory.LockItemsForRead(true);
5100 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4732 { 5101 {
4733 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5102 if (inv.Value.Name == name)
4734 { 5103 {
4735 if (inv.Value.Name == name) 5104 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4736 { 5105 {
4737 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5106 m_host.TaskInventory.LockItemsForRead(false);
4738 { 5107 return inv.Value.AssetID.ToString();
4739 return inv.Value.AssetID.ToString(); 5108 }
4740 } 5109 else
4741 else 5110 {
4742 { 5111 m_host.TaskInventory.LockItemsForRead(false);
4743 return UUID.Zero.ToString(); 5112 return UUID.Zero.ToString();
4744 }
4745 } 5113 }
4746 } 5114 }
4747 } 5115 }
5116 m_host.TaskInventory.LockItemsForRead(false);
4748 5117
4749 return UUID.Zero.ToString(); 5118 return UUID.Zero.ToString();
4750 } 5119 }
@@ -4897,14 +5266,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4897 { 5266 {
4898 m_host.AddScriptLPS(1); 5267 m_host.AddScriptLPS(1);
4899 5268
4900 if (src == null) 5269 return src.Length;
4901 {
4902 return 0;
4903 }
4904 else
4905 {
4906 return src.Length;
4907 }
4908 } 5270 }
4909 5271
4910 public LSL_Integer llList2Integer(LSL_List src, int index) 5272 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4950,7 +5312,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4950 else if (src.Data[index] is LSL_Float) 5312 else if (src.Data[index] is LSL_Float)
4951 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5313 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4952 else if (src.Data[index] is LSL_String) 5314 else if (src.Data[index] is LSL_String)
4953 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5315 {
5316 string str = ((LSL_String) src.Data[index]).m_string;
5317 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5318 if (m != Match.Empty)
5319 {
5320 str = m.Value;
5321 double d = 0.0;
5322 if (!Double.TryParse(str, out d))
5323 return 0.0;
5324
5325 return d;
5326 }
5327 return 0.0;
5328 }
4954 return Convert.ToDouble(src.Data[index]); 5329 return Convert.ToDouble(src.Data[index]);
4955 } 5330 }
4956 catch (FormatException) 5331 catch (FormatException)
@@ -5223,7 +5598,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5223 } 5598 }
5224 } 5599 }
5225 } 5600 }
5226 else { 5601 else
5602 {
5227 object[] array = new object[src.Length]; 5603 object[] array = new object[src.Length];
5228 Array.Copy(src.Data, 0, array, 0, src.Length); 5604 Array.Copy(src.Data, 0, array, 0, src.Length);
5229 result = new LSL_List(array); 5605 result = new LSL_List(array);
@@ -5672,10 +6048,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5672 m_host.AddScriptLPS(1); 6048 m_host.AddScriptLPS(1);
5673 6049
5674 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6050 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5675 6051 if (parts.Count > 0)
5676 foreach (var part in parts)
5677 { 6052 {
5678 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6053 try
6054 {
6055 parts[0].ParentGroup.areUpdatesSuspended = true;
6056 foreach (var part in parts)
6057 {
6058 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6059 }
6060 }
6061 finally
6062 {
6063 parts[0].ParentGroup.areUpdatesSuspended = false;
6064 }
5679 } 6065 }
5680 } 6066 }
5681 6067
@@ -5729,6 +6115,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5729 ScriptSleep(5000); 6115 ScriptSleep(5000);
5730 } 6116 }
5731 6117
6118 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6119 {
6120 return ParseString2List(str, separators, in_spacers, false);
6121 }
6122
5732 public LSL_Integer llOverMyLand(string id) 6123 public LSL_Integer llOverMyLand(string id)
5733 { 6124 {
5734 m_host.AddScriptLPS(1); 6125 m_host.AddScriptLPS(1);
@@ -5793,8 +6184,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5793 UUID agentId = new UUID(); 6184 UUID agentId = new UUID();
5794 if (!UUID.TryParse(agent, out agentId)) 6185 if (!UUID.TryParse(agent, out agentId))
5795 return new LSL_Integer(0); 6186 return new LSL_Integer(0);
6187 if (agentId == m_host.GroupID)
6188 return new LSL_Integer(1);
5796 ScenePresence presence = World.GetScenePresence(agentId); 6189 ScenePresence presence = World.GetScenePresence(agentId);
5797 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6190 if (presence == null || presence.IsChildAgent) // Return false for child agents
5798 return new LSL_Integer(0); 6191 return new LSL_Integer(0);
5799 IClientAPI client = presence.ControllingClient; 6192 IClientAPI client = presence.ControllingClient;
5800 if (m_host.GroupID == client.ActiveGroupId) 6193 if (m_host.GroupID == client.ActiveGroupId)
@@ -5929,7 +6322,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5929 return m_host.ParentGroup.AttachmentPoint; 6322 return m_host.ParentGroup.AttachmentPoint;
5930 } 6323 }
5931 6324
5932 public LSL_Integer llGetFreeMemory() 6325 public virtual LSL_Integer llGetFreeMemory()
5933 { 6326 {
5934 m_host.AddScriptLPS(1); 6327 m_host.AddScriptLPS(1);
5935 // Make scripts designed for LSO happy 6328 // Make scripts designed for LSO happy
@@ -6046,7 +6439,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6046 SetParticleSystem(m_host, rules); 6439 SetParticleSystem(m_host, rules);
6047 } 6440 }
6048 6441
6049 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6442 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6443 {
6050 6444
6051 6445
6052 if (rules.Length == 0) 6446 if (rules.Length == 0)
@@ -6240,14 +6634,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6240 6634
6241 protected UUID GetTaskInventoryItem(string name) 6635 protected UUID GetTaskInventoryItem(string name)
6242 { 6636 {
6243 lock (m_host.TaskInventory) 6637 m_host.TaskInventory.LockItemsForRead(true);
6638 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6244 { 6639 {
6245 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6640 if (inv.Value.Name == name)
6246 { 6641 {
6247 if (inv.Value.Name == name) 6642 m_host.TaskInventory.LockItemsForRead(false);
6248 return inv.Key; 6643 return inv.Key;
6249 } 6644 }
6250 } 6645 }
6646 m_host.TaskInventory.LockItemsForRead(false);
6251 6647
6252 return UUID.Zero; 6648 return UUID.Zero;
6253 } 6649 }
@@ -6285,16 +6681,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6285 if (folderID == UUID.Zero) 6681 if (folderID == UUID.Zero)
6286 return; 6682 return;
6287 6683
6288 byte[] bucket = new byte[17]; 6684 byte[] bucket = new byte[1];
6289 bucket[0] = (byte)AssetType.Folder; 6685 bucket[0] = (byte)AssetType.Folder;
6290 byte[] objBytes = folderID.GetBytes(); 6686 //byte[] objBytes = folderID.GetBytes();
6291 Array.Copy(objBytes, 0, bucket, 1, 16); 6687 //Array.Copy(objBytes, 0, bucket, 1, 16);
6292 6688
6293 GridInstantMessage msg = new GridInstantMessage(World, 6689 GridInstantMessage msg = new GridInstantMessage(World,
6294 m_host.UUID, m_host.Name+", an object owned by "+ 6690 m_host.OwnerID, m_host.Name, destID,
6295 resolveName(m_host.OwnerID)+",", destID, 6691 (byte)InstantMessageDialog.TaskInventoryOffered,
6296 (byte)InstantMessageDialog.InventoryOffered, 6692 false, category+". "+m_host.Name+" is located at "+
6297 false, category+"\n"+m_host.Name+" is located at "+
6298 World.RegionInfo.RegionName+" "+ 6693 World.RegionInfo.RegionName+" "+
6299 m_host.AbsolutePosition.ToString(), 6694 m_host.AbsolutePosition.ToString(),
6300 folderID, true, m_host.AbsolutePosition, 6695 folderID, true, m_host.AbsolutePosition,
@@ -6497,13 +6892,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6497 UUID av = new UUID(); 6892 UUID av = new UUID();
6498 if (!UUID.TryParse(avatar,out av)) 6893 if (!UUID.TryParse(avatar,out av))
6499 { 6894 {
6500 LSLError("First parameter to llDialog needs to be a key"); 6895 //LSLError("First parameter to llDialog needs to be a key");
6501 return; 6896 return;
6502 } 6897 }
6503 if (buttons.Length < 1) 6898 if (buttons.Length < 1)
6504 { 6899 {
6505 LSLError("No less than 1 button can be shown"); 6900 buttons.Add("OK");
6506 return;
6507 } 6901 }
6508 if (buttons.Length > 12) 6902 if (buttons.Length > 12)
6509 { 6903 {
@@ -6520,7 +6914,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6520 } 6914 }
6521 if (buttons.Data[i].ToString().Length > 24) 6915 if (buttons.Data[i].ToString().Length > 24)
6522 { 6916 {
6523 LSLError("button label cannot be longer than 24 characters"); 6917 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6524 return; 6918 return;
6525 } 6919 }
6526 buts[i] = buttons.Data[i].ToString(); 6920 buts[i] = buttons.Data[i].ToString();
@@ -6579,22 +6973,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6579 } 6973 }
6580 6974
6581 // copy the first script found with this inventory name 6975 // copy the first script found with this inventory name
6582 lock (m_host.TaskInventory) 6976 TaskInventoryItem scriptItem = null;
6977 m_host.TaskInventory.LockItemsForRead(true);
6978 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6583 { 6979 {
6584 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6980 if (inv.Value.Name == name)
6585 { 6981 {
6586 if (inv.Value.Name == name) 6982 // make sure the object is a script
6983 if (10 == inv.Value.Type)
6587 { 6984 {
6588 // make sure the object is a script 6985 found = true;
6589 if (10 == inv.Value.Type) 6986 srcId = inv.Key;
6590 { 6987 scriptItem = inv.Value;
6591 found = true; 6988 break;
6592 srcId = inv.Key;
6593 break;
6594 }
6595 } 6989 }
6596 } 6990 }
6597 } 6991 }
6992 m_host.TaskInventory.LockItemsForRead(false);
6598 6993
6599 if (!found) 6994 if (!found)
6600 { 6995 {
@@ -6602,9 +6997,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6602 return; 6997 return;
6603 } 6998 }
6604 6999
6605 // the rest of the permission checks are done in RezScript, so check the pin there as well 7000 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6606 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7001 if (dest != null)
7002 {
7003 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7004 {
7005 // the rest of the permission checks are done in RezScript, so check the pin there as well
7006 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6607 7007
7008 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7009 m_host.Inventory.RemoveInventoryItem(srcId);
7010 }
7011 }
6608 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7012 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6609 ScriptSleep(3000); 7013 ScriptSleep(3000);
6610 } 7014 }
@@ -6667,19 +7071,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6667 public LSL_String llMD5String(string src, int nonce) 7071 public LSL_String llMD5String(string src, int nonce)
6668 { 7072 {
6669 m_host.AddScriptLPS(1); 7073 m_host.AddScriptLPS(1);
6670 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7074 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6671 } 7075 }
6672 7076
6673 public LSL_String llSHA1String(string src) 7077 public LSL_String llSHA1String(string src)
6674 { 7078 {
6675 m_host.AddScriptLPS(1); 7079 m_host.AddScriptLPS(1);
6676 return Util.SHA1Hash(src).ToLower(); 7080 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6677 } 7081 }
6678 7082
6679 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7083 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6680 { 7084 {
6681 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7085 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6682 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7086 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7087 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7088 return shapeBlock;
6683 7089
6684 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7090 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6685 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7091 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6784,6 +7190,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6784 // Prim type box, cylinder and prism. 7190 // Prim type box, cylinder and prism.
6785 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) 7191 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)
6786 { 7192 {
7193 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7194 return;
7195
6787 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7196 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6788 ObjectShapePacket.ObjectDataBlock shapeBlock; 7197 ObjectShapePacket.ObjectDataBlock shapeBlock;
6789 7198
@@ -6837,6 +7246,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6837 // Prim type sphere. 7246 // Prim type sphere.
6838 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7247 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6839 { 7248 {
7249 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7250 return;
7251
6840 ObjectShapePacket.ObjectDataBlock shapeBlock; 7252 ObjectShapePacket.ObjectDataBlock shapeBlock;
6841 7253
6842 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7254 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6878,6 +7290,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6878 // Prim type torus, tube and ring. 7290 // Prim type torus, tube and ring.
6879 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) 7291 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)
6880 { 7292 {
7293 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7294 return;
7295
6881 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7296 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6882 ObjectShapePacket.ObjectDataBlock shapeBlock; 7297 ObjectShapePacket.ObjectDataBlock shapeBlock;
6883 7298
@@ -7013,6 +7428,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7013 // Prim type sculpt. 7428 // Prim type sculpt.
7014 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7429 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7015 { 7430 {
7431 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7432 return;
7433
7016 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7434 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7017 UUID sculptId; 7435 UUID sculptId;
7018 7436
@@ -7029,13 +7447,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7029 shapeBlock.PathScaleX = 100; 7447 shapeBlock.PathScaleX = 100;
7030 shapeBlock.PathScaleY = 150; 7448 shapeBlock.PathScaleY = 150;
7031 7449
7032 if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER && 7450 if ((type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER) == 0 &&
7033 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE && 7451 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE) == 0 &&
7034 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE && 7452 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE) == 0 &&
7035 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) 7453 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) == 0)
7036 { 7454 {
7037 // default 7455 // default
7038 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7456 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7039 } 7457 }
7040 7458
7041 part.Shape.SetSculptProperties((byte)type, sculptId); 7459 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7051,32 +7469,87 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7051 ScriptSleep(200); 7469 ScriptSleep(200);
7052 } 7470 }
7053 7471
7054 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7472 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7055 { 7473 {
7056 m_host.AddScriptLPS(1); 7474 m_host.AddScriptLPS(1);
7057 7475
7058 setLinkPrimParams(linknumber, rules); 7476 setLinkPrimParams(linknumber, rules);
7059
7060 ScriptSleep(200);
7061 } 7477 }
7062 7478
7063 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7479 private void setLinkPrimParams(int linknumber, LSL_List rules)
7064 { 7480 {
7065 m_host.AddScriptLPS(1); 7481 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7482 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7483 if (parts.Count>0)
7484 {
7485 try
7486 {
7487 parts[0].ParentGroup.areUpdatesSuspended = true;
7488 foreach (SceneObjectPart part in parts)
7489 SetPrimParams(part, rules);
7490 }
7491 finally
7492 {
7493 parts[0].ParentGroup.areUpdatesSuspended = false;
7494 }
7495 }
7496 if (avatars.Count > 0)
7497 {
7498 foreach (ScenePresence avatar in avatars)
7499 SetPrimParams(avatar, rules);
7500 }
7501 }
7066 7502
7067 setLinkPrimParams(linknumber, rules); 7503 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7504 {
7505 llSetLinkPrimitiveParamsFast(linknumber, rules);
7506 ScriptSleep(200);
7068 } 7507 }
7069 7508
7070 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7509 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7071 { 7510 {
7072 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7511 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7512 //We only support PRIM_POSITION and PRIM_ROTATION
7073 7513
7074 foreach (SceneObjectPart part in parts) 7514 int idx = 0;
7075 SetPrimParams(part, rules); 7515
7516 while (idx < rules.Length)
7517 {
7518 int code = rules.GetLSLIntegerItem(idx++);
7519
7520 int remain = rules.Length - idx;
7521
7522
7523
7524 switch (code)
7525 {
7526 case (int)ScriptBaseClass.PRIM_POSITION:
7527 if (remain < 1)
7528 return;
7529 LSL_Vector v;
7530 v = rules.GetVector3Item(idx++);
7531 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7532 av.SendAvatarDataToAllAgents();
7533
7534 break;
7535
7536 case (int)ScriptBaseClass.PRIM_ROTATION:
7537 if (remain < 1)
7538 return;
7539 LSL_Rotation r;
7540 r = rules.GetQuaternionItem(idx++);
7541 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7542 av.SendAvatarDataToAllAgents();
7543 break;
7544 }
7545 }
7076 } 7546 }
7077 7547
7078 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7548 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7079 { 7549 {
7550 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7551 return;
7552
7080 int idx = 0; 7553 int idx = 0;
7081 7554
7082 bool positionChanged = false; 7555 bool positionChanged = false;
@@ -7104,6 +7577,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7104 currentPosition = GetSetPosTarget(part, v, currentPosition); 7577 currentPosition = GetSetPosTarget(part, v, currentPosition);
7105 7578
7106 break; 7579 break;
7580 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
7581 if (remain < 1)
7582 return;
7583
7584 v=rules.GetVector3Item(idx++);
7585 positionChanged = true;
7586 currentPosition = GetSetPosTarget(part, v, currentPosition);
7587
7588 break;
7107 case (int)ScriptBaseClass.PRIM_SIZE: 7589 case (int)ScriptBaseClass.PRIM_SIZE:
7108 if (remain < 1) 7590 if (remain < 1)
7109 return; 7591 return;
@@ -7481,6 +7963,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7481 } 7963 }
7482 } 7964 }
7483 } 7965 }
7966
7967 if (positionChanged)
7968 {
7969 if (part.ParentGroup.RootPart == part)
7970 {
7971 SceneObjectGroup parent = part.ParentGroup;
7972 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
7973 }
7974 else
7975 {
7976 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
7977 SceneObjectGroup parent = part.ParentGroup;
7978 parent.HasGroupChanged = true;
7979 parent.ScheduleGroupForTerseUpdate();
7980 }
7981 }
7484 } 7982 }
7485 7983
7486 public LSL_String llStringToBase64(string str) 7984 public LSL_String llStringToBase64(string str)
@@ -7641,13 +8139,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7641 public LSL_Integer llGetNumberOfPrims() 8139 public LSL_Integer llGetNumberOfPrims()
7642 { 8140 {
7643 m_host.AddScriptLPS(1); 8141 m_host.AddScriptLPS(1);
7644 int avatarCount = 0; 8142 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7645 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8143
7646 {
7647 if (presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID))
7648 avatarCount++;
7649 });
7650
7651 return m_host.ParentGroup.PrimCount + avatarCount; 8144 return m_host.ParentGroup.PrimCount + avatarCount;
7652 } 8145 }
7653 8146
@@ -7663,55 +8156,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7663 m_host.AddScriptLPS(1); 8156 m_host.AddScriptLPS(1);
7664 UUID objID = UUID.Zero; 8157 UUID objID = UUID.Zero;
7665 LSL_List result = new LSL_List(); 8158 LSL_List result = new LSL_List();
8159
8160 // If the ID is not valid, return null result
7666 if (!UUID.TryParse(obj, out objID)) 8161 if (!UUID.TryParse(obj, out objID))
7667 { 8162 {
7668 result.Add(new LSL_Vector()); 8163 result.Add(new LSL_Vector());
7669 result.Add(new LSL_Vector()); 8164 result.Add(new LSL_Vector());
7670 return result; 8165 return result;
7671 } 8166 }
8167
8168 // Check if this is an attached prim. If so, replace
8169 // the UUID with the avatar UUID and report it's bounding box
8170 SceneObjectPart part = World.GetSceneObjectPart(objID);
8171 if (part != null && part.ParentGroup.IsAttachment)
8172 objID = part.ParentGroup.AttachedAvatar;
8173
8174 // Find out if this is an avatar ID. If so, return it's box
7672 ScenePresence presence = World.GetScenePresence(objID); 8175 ScenePresence presence = World.GetScenePresence(objID);
7673 if (presence != null) 8176 if (presence != null)
7674 { 8177 {
7675 if (presence.ParentID == 0) // not sat on an object 8178 // As per LSL Wiki, there is no difference between sitting
8179 // and standing avatar since server 1.36
8180 LSL_Vector lower;
8181 LSL_Vector upper;
8182 if (presence.Animator.Animations.DefaultAnimation.AnimID
8183 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7676 { 8184 {
7677 LSL_Vector lower; 8185 // This is for ground sitting avatars
7678 LSL_Vector upper; 8186 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7679 if (presence.Animator.Animations.DefaultAnimation.AnimID 8187 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7680 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8188 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7681 {
7682 // This is for ground sitting avatars
7683 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7684 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7685 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7686 }
7687 else
7688 {
7689 // This is for standing/flying avatars
7690 float height = presence.Appearance.AvatarHeight / 2.0f;
7691 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7692 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7693 }
7694 result.Add(lower);
7695 result.Add(upper);
7696 return result;
7697 } 8189 }
7698 else 8190 else
7699 { 8191 {
7700 // sitting on an object so we need the bounding box of that 8192 // This is for standing/flying avatars
7701 // which should include the avatar so set the UUID to the 8193 float height = presence.Appearance.AvatarHeight / 2.0f;
7702 // UUID of the object the avatar is sat on and allow it to fall through 8194 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7703 // to processing an object 8195 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7704 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7705 objID = p.UUID;
7706 } 8196 }
8197
8198 // Adjust to the documented error offsets (see LSL Wiki)
8199 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8200 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8201
8202 if (lower.x > upper.x)
8203 lower.x = upper.x;
8204 if (lower.y > upper.y)
8205 lower.y = upper.y;
8206 if (lower.z > upper.z)
8207 lower.z = upper.z;
8208
8209 result.Add(lower);
8210 result.Add(upper);
8211 return result;
7707 } 8212 }
7708 SceneObjectPart part = World.GetSceneObjectPart(objID); 8213
8214 part = World.GetSceneObjectPart(objID);
7709 // Currently only works for single prims without a sitting avatar 8215 // Currently only works for single prims without a sitting avatar
7710 if (part != null) 8216 if (part != null)
7711 { 8217 {
7712 Vector3 halfSize = part.Scale / 2.0f; 8218 float minX;
7713 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8219 float maxX;
7714 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8220 float minY;
8221 float maxY;
8222 float minZ;
8223 float maxZ;
8224
8225 // This BBox is in sim coordinates, with the offset being
8226 // a contained point.
8227 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8228 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8229
8230 minX -= offsets[0].X;
8231 maxX -= offsets[0].X;
8232 minY -= offsets[0].Y;
8233 maxY -= offsets[0].Y;
8234 minZ -= offsets[0].Z;
8235 maxZ -= offsets[0].Z;
8236
8237 LSL_Vector lower;
8238 LSL_Vector upper;
8239
8240 // Adjust to the documented error offsets (see LSL Wiki)
8241 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8242 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8243
8244 if (lower.x > upper.x)
8245 lower.x = upper.x;
8246 if (lower.y > upper.y)
8247 lower.y = upper.y;
8248 if (lower.z > upper.z)
8249 lower.z = upper.z;
8250
7715 result.Add(lower); 8251 result.Add(lower);
7716 result.Add(upper); 8252 result.Add(upper);
7717 return result; 8253 return result;
@@ -7791,13 +8327,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7791 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8327 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7792 part.AbsolutePosition.Y, 8328 part.AbsolutePosition.Y,
7793 part.AbsolutePosition.Z); 8329 part.AbsolutePosition.Z);
7794 // For some reason, the part.AbsolutePosition.* values do not change if the
7795 // linkset is rotated; they always reflect the child prim's world position
7796 // as though the linkset is unrotated. This is incompatible behavior with SL's
7797 // implementation, so will break scripts imported from there (not to mention it
7798 // makes it more difficult to determine a child prim's actual inworld position).
7799 if (part.ParentID != 0)
7800 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7801 res.Add(v); 8330 res.Add(v);
7802 break; 8331 break;
7803 8332
@@ -7968,56 +8497,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7968 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8497 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7969 if (remain < 1) 8498 if (remain < 1)
7970 return res; 8499 return res;
7971 8500 face = (int)rules.GetLSLIntegerItem(idx++);
7972 face=(int)rules.GetLSLIntegerItem(idx++);
7973 8501
7974 tex = part.Shape.Textures; 8502 tex = part.Shape.Textures;
8503 int shiny;
7975 if (face == ScriptBaseClass.ALL_SIDES) 8504 if (face == ScriptBaseClass.ALL_SIDES)
7976 { 8505 {
7977 for (face = 0; face < GetNumberOfSides(part); face++) 8506 for (face = 0; face < GetNumberOfSides(part); face++)
7978 { 8507 {
7979 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8508 Shininess shinyness = tex.GetFace((uint)face).Shiny;
7980 // Convert Shininess to PRIM_SHINY_* 8509 if (shinyness == Shininess.High)
7981 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8510 {
7982 // PRIM_BUMP_* 8511 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7983 res.Add(new LSL_Integer((int)texface.Bump)); 8512 }
8513 else if (shinyness == Shininess.Medium)
8514 {
8515 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8516 }
8517 else if (shinyness == Shininess.Low)
8518 {
8519 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8520 }
8521 else
8522 {
8523 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8524 }
8525 res.Add(new LSL_Integer(shiny));
8526 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7984 } 8527 }
7985 } 8528 }
7986 else 8529 else
7987 { 8530 {
7988 if (face >= 0 && face < GetNumberOfSides(part)) 8531 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8532 if (shinyness == Shininess.High)
7989 { 8533 {
7990 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8534 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7991 // Convert Shininess to PRIM_SHINY_* 8535 }
7992 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8536 else if (shinyness == Shininess.Medium)
7993 // PRIM_BUMP_* 8537 {
7994 res.Add(new LSL_Integer((int)texface.Bump)); 8538 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
7995 } 8539 }
8540 else if (shinyness == Shininess.Low)
8541 {
8542 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8543 }
8544 else
8545 {
8546 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8547 }
8548 res.Add(new LSL_Integer(shiny));
8549 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7996 } 8550 }
7997 break; 8551 break;
7998 8552
7999 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8553 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8000 if (remain < 1) 8554 if (remain < 1)
8001 return res; 8555 return res;
8002 8556 face = (int)rules.GetLSLIntegerItem(idx++);
8003 face=(int)rules.GetLSLIntegerItem(idx++);
8004 8557
8005 tex = part.Shape.Textures; 8558 tex = part.Shape.Textures;
8559 int fullbright;
8006 if (face == ScriptBaseClass.ALL_SIDES) 8560 if (face == ScriptBaseClass.ALL_SIDES)
8007 { 8561 {
8008 for (face = 0; face < GetNumberOfSides(part); face++) 8562 for (face = 0; face < GetNumberOfSides(part); face++)
8009 { 8563 {
8010 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8564 if (tex.GetFace((uint)face).Fullbright == true)
8011 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8565 {
8566 fullbright = ScriptBaseClass.TRUE;
8567 }
8568 else
8569 {
8570 fullbright = ScriptBaseClass.FALSE;
8571 }
8572 res.Add(new LSL_Integer(fullbright));
8012 } 8573 }
8013 } 8574 }
8014 else 8575 else
8015 { 8576 {
8016 if (face >= 0 && face < GetNumberOfSides(part)) 8577 if (tex.GetFace((uint)face).Fullbright == true)
8017 { 8578 {
8018 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8579 fullbright = ScriptBaseClass.TRUE;
8019 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
8020 } 8580 }
8581 else
8582 {
8583 fullbright = ScriptBaseClass.FALSE;
8584 }
8585 res.Add(new LSL_Integer(fullbright));
8021 } 8586 }
8022 break; 8587 break;
8023 8588
@@ -8039,27 +8604,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8039 break; 8604 break;
8040 8605
8041 case (int)ScriptBaseClass.PRIM_TEXGEN: 8606 case (int)ScriptBaseClass.PRIM_TEXGEN:
8607 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8042 if (remain < 1) 8608 if (remain < 1)
8043 return res; 8609 return res;
8044 8610 face = (int)rules.GetLSLIntegerItem(idx++);
8045 face=(int)rules.GetLSLIntegerItem(idx++);
8046 8611
8047 tex = part.Shape.Textures; 8612 tex = part.Shape.Textures;
8048 if (face == ScriptBaseClass.ALL_SIDES) 8613 if (face == ScriptBaseClass.ALL_SIDES)
8049 { 8614 {
8050 for (face = 0; face < GetNumberOfSides(part); face++) 8615 for (face = 0; face < GetNumberOfSides(part); face++)
8051 { 8616 {
8052 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8617 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8053 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8618 {
8054 res.Add(new LSL_Integer((uint)texgen >> 1)); 8619 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8620 }
8621 else
8622 {
8623 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8624 }
8055 } 8625 }
8056 } 8626 }
8057 else 8627 else
8058 { 8628 {
8059 if (face >= 0 && face < GetNumberOfSides(part)) 8629 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8630 {
8631 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8632 }
8633 else
8060 { 8634 {
8061 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8635 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8062 res.Add(new LSL_Integer((uint)texgen >> 1));
8063 } 8636 }
8064 } 8637 }
8065 break; 8638 break;
@@ -8082,28 +8655,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8082 case (int)ScriptBaseClass.PRIM_GLOW: 8655 case (int)ScriptBaseClass.PRIM_GLOW:
8083 if (remain < 1) 8656 if (remain < 1)
8084 return res; 8657 return res;
8085 8658 face = (int)rules.GetLSLIntegerItem(idx++);
8086 face=(int)rules.GetLSLIntegerItem(idx++);
8087 8659
8088 tex = part.Shape.Textures; 8660 tex = part.Shape.Textures;
8661 float primglow;
8089 if (face == ScriptBaseClass.ALL_SIDES) 8662 if (face == ScriptBaseClass.ALL_SIDES)
8090 { 8663 {
8091 for (face = 0; face < GetNumberOfSides(part); face++) 8664 for (face = 0; face < GetNumberOfSides(part); face++)
8092 { 8665 {
8093 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8666 primglow = tex.GetFace((uint)face).Glow;
8094 res.Add(new LSL_Float(texface.Glow)); 8667 res.Add(new LSL_Float(primglow));
8095 } 8668 }
8096 } 8669 }
8097 else 8670 else
8098 { 8671 {
8099 if (face >= 0 && face < GetNumberOfSides(part)) 8672 primglow = tex.GetFace((uint)face).Glow;
8100 { 8673 res.Add(new LSL_Float(primglow));
8101 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8102 res.Add(new LSL_Float(texface.Glow));
8103 }
8104 } 8674 }
8105 break; 8675 break;
8106
8107 case (int)ScriptBaseClass.PRIM_TEXT: 8676 case (int)ScriptBaseClass.PRIM_TEXT:
8108 Color4 textColor = part.GetTextColor(); 8677 Color4 textColor = part.GetTextColor();
8109 res.Add(new LSL_String(part.Text)); 8678 res.Add(new LSL_String(part.Text));
@@ -8655,8 +9224,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8655 // The function returns an ordered list 9224 // The function returns an ordered list
8656 // representing the tokens found in the supplied 9225 // representing the tokens found in the supplied
8657 // sources string. If two successive tokenizers 9226 // sources string. If two successive tokenizers
8658 // are encountered, then a NULL entry is added 9227 // are encountered, then a null-string entry is
8659 // to the list. 9228 // added to the list.
8660 // 9229 //
8661 // It is a precondition that the source and 9230 // It is a precondition that the source and
8662 // toekizer lisst are non-null. If they are null, 9231 // toekizer lisst are non-null. If they are null,
@@ -8664,7 +9233,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8664 // while their lengths are being determined. 9233 // while their lengths are being determined.
8665 // 9234 //
8666 // A small amount of working memoryis required 9235 // A small amount of working memoryis required
8667 // of approximately 8*#tokenizers. 9236 // of approximately 8*#tokenizers + 8*srcstrlen.
8668 // 9237 //
8669 // There are many ways in which this function 9238 // There are many ways in which this function
8670 // can be implemented, this implementation is 9239 // can be implemented, this implementation is
@@ -8680,155 +9249,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8680 // and eliminates redundant tokenizers as soon 9249 // and eliminates redundant tokenizers as soon
8681 // as is possible. 9250 // as is possible.
8682 // 9251 //
8683 // The implementation tries to avoid any copying 9252 // The implementation tries to minimize temporary
8684 // of arrays or other objects. 9253 // garbage generation.
8685 // </remarks> 9254 // </remarks>
8686 9255
8687 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9256 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8688 { 9257 {
8689 int beginning = 0; 9258 return ParseString2List(src, separators, spacers, true);
8690 int srclen = src.Length; 9259 }
8691 int seplen = separators.Length;
8692 object[] separray = separators.Data;
8693 int spclen = spacers.Length;
8694 object[] spcarray = spacers.Data;
8695 int mlen = seplen+spclen;
8696
8697 int[] offset = new int[mlen+1];
8698 bool[] active = new bool[mlen];
8699
8700 int best;
8701 int j;
8702
8703 // Initial capacity reduces resize cost
8704 9260
8705 LSL_List tokens = new LSL_List(); 9261 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9262 {
9263 int srclen = src.Length;
9264 int seplen = separators.Length;
9265 object[] separray = separators.Data;
9266 int spclen = spacers.Length;
9267 object[] spcarray = spacers.Data;
9268 int dellen = 0;
9269 string[] delarray = new string[seplen+spclen];
8706 9270
8707 // All entries are initially valid 9271 int outlen = 0;
9272 string[] outarray = new string[srclen*2+1];
8708 9273
8709 for (int i = 0; i < mlen; i++) 9274 int i, j;
8710 active[i] = true; 9275 string d;
8711 9276
8712 offset[mlen] = srclen; 9277 m_host.AddScriptLPS(1);
8713 9278
8714 while (beginning < srclen) 9279 /*
9280 * Convert separator and spacer lists to C# strings.
9281 * Also filter out null strings so we don't hang.
9282 */
9283 for (i = 0; i < seplen; i ++)
8715 { 9284 {
9285 d = separray[i].ToString();
9286 if (d.Length > 0)
9287 {
9288 delarray[dellen++] = d;
9289 }
9290 }
9291 seplen = dellen;
8716 9292
8717 best = mlen; // as bad as it gets 9293 for (i = 0; i < spclen; i ++)
9294 {
9295 d = spcarray[i].ToString();
9296 if (d.Length > 0)
9297 {
9298 delarray[dellen++] = d;
9299 }
9300 }
8718 9301
8719 // Scan for separators 9302 /*
9303 * Scan through source string from beginning to end.
9304 */
9305 for (i = 0;;)
9306 {
8720 9307
8721 for (j = 0; j < seplen; j++) 9308 /*
9309 * Find earliest delimeter in src starting at i (if any).
9310 */
9311 int earliestDel = -1;
9312 int earliestSrc = srclen;
9313 string earliestStr = null;
9314 for (j = 0; j < dellen; j ++)
8722 { 9315 {
8723 if (separray[j].ToString() == String.Empty) 9316 d = delarray[j];
8724 active[j] = false; 9317 if (d != null)
8725
8726 if (active[j])
8727 { 9318 {
8728 // scan all of the markers 9319 int index = src.IndexOf(d, i);
8729 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9320 if (index < 0)
8730 { 9321 {
8731 // not present at all 9322 delarray[j] = null; // delim nowhere in src, don't check it anymore
8732 active[j] = false;
8733 } 9323 }
8734 else 9324 else if (index < earliestSrc)
8735 { 9325 {
8736 // present and correct 9326 earliestSrc = index; // where delimeter starts in source string
8737 if (offset[j] < offset[best]) 9327 earliestDel = j; // where delimeter is in delarray[]
8738 { 9328 earliestStr = d; // the delimeter string from delarray[]
8739 // closest so far 9329 if (index == i) break; // can't do any better than found at beg of string
8740 best = j;
8741 if (offset[best] == beginning)
8742 break;
8743 }
8744 } 9330 }
8745 } 9331 }
8746 } 9332 }
8747 9333
8748 // Scan for spacers 9334 /*
8749 9335 * Output source string starting at i through start of earliest delimeter.
8750 if (offset[best] != beginning) 9336 */
9337 if (keepNulls || (earliestSrc > i))
8751 { 9338 {
8752 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9339 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8753 {
8754 if (spcarray[j-seplen].ToString() == String.Empty)
8755 active[j] = false;
8756
8757 if (active[j])
8758 {
8759 // scan all of the markers
8760 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8761 {
8762 // not present at all
8763 active[j] = false;
8764 }
8765 else
8766 {
8767 // present and correct
8768 if (offset[j] < offset[best])
8769 {
8770 // closest so far
8771 best = j;
8772 }
8773 }
8774 }
8775 }
8776 } 9340 }
8777 9341
8778 // This is the normal exit from the scanning loop 9342 /*
9343 * If no delimeter found at or after i, we're done scanning.
9344 */
9345 if (earliestDel < 0) break;
8779 9346
8780 if (best == mlen) 9347 /*
9348 * If delimeter was a spacer, output the spacer.
9349 */
9350 if (earliestDel >= seplen)
8781 { 9351 {
8782 // no markers were found on this pass 9352 outarray[outlen++] = earliestStr;
8783 // so we're pretty much done
8784 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8785 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8786 break;
8787 } 9353 }
8788 9354
8789 // Otherwise we just add the newly delimited token 9355 /*
8790 // and recalculate where the search should continue. 9356 * Look at rest of src string following delimeter.
8791 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9357 */
8792 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9358 i = earliestSrc + earliestStr.Length;
8793
8794 if (best < seplen)
8795 {
8796 beginning = offset[best] + (separray[best].ToString()).Length;
8797 }
8798 else
8799 {
8800 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8801 string str = spcarray[best - seplen].ToString();
8802 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8803 tokens.Add(new LSL_String(str));
8804 }
8805 } 9359 }
8806 9360
8807 // This an awkward an not very intuitive boundary case. If the 9361 /*
8808 // last substring is a tokenizer, then there is an implied trailing 9362 * Make up an exact-sized output array suitable for an LSL_List object.
8809 // null list entry. Hopefully the single comparison will not be too 9363 */
8810 // arduous. Alternatively the 'break' could be replced with a return 9364 object[] outlist = new object[outlen];
8811 // but that's shabby programming. 9365 for (i = 0; i < outlen; i ++)
8812
8813 if ((beginning == srclen) && (keepNulls))
8814 { 9366 {
8815 if (srclen != 0) 9367 outlist[i] = new LSL_String(outarray[i]);
8816 tokens.Add(new LSL_String(""));
8817 } 9368 }
8818 9369 return new LSL_List(outlist);
8819 return tokens;
8820 }
8821
8822 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8823 {
8824 m_host.AddScriptLPS(1);
8825 return this.ParseString(src, separators, spacers, false);
8826 }
8827
8828 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8829 {
8830 m_host.AddScriptLPS(1);
8831 return this.ParseString(src, separators, spacers, true);
8832 } 9370 }
8833 9371
8834 public LSL_Integer llGetObjectPermMask(int mask) 9372 public LSL_Integer llGetObjectPermMask(int mask)
@@ -8905,28 +9443,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8905 { 9443 {
8906 m_host.AddScriptLPS(1); 9444 m_host.AddScriptLPS(1);
8907 9445
8908 lock (m_host.TaskInventory) 9446 m_host.TaskInventory.LockItemsForRead(true);
9447 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8909 { 9448 {
8910 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9449 if (inv.Value.Name == item)
8911 { 9450 {
8912 if (inv.Value.Name == item) 9451 m_host.TaskInventory.LockItemsForRead(false);
9452 switch (mask)
8913 { 9453 {
8914 switch (mask) 9454 case 0:
8915 { 9455 return (int)inv.Value.BasePermissions;
8916 case 0: 9456 case 1:
8917 return (int)inv.Value.BasePermissions; 9457 return (int)inv.Value.CurrentPermissions;
8918 case 1: 9458 case 2:
8919 return (int)inv.Value.CurrentPermissions; 9459 return (int)inv.Value.GroupPermissions;
8920 case 2: 9460 case 3:
8921 return (int)inv.Value.GroupPermissions; 9461 return (int)inv.Value.EveryonePermissions;
8922 case 3: 9462 case 4:
8923 return (int)inv.Value.EveryonePermissions; 9463 return (int)inv.Value.NextPermissions;
8924 case 4:
8925 return (int)inv.Value.NextPermissions;
8926 }
8927 } 9464 }
8928 } 9465 }
8929 } 9466 }
9467 m_host.TaskInventory.LockItemsForRead(false);
8930 9468
8931 return -1; 9469 return -1;
8932 } 9470 }
@@ -8973,16 +9511,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8973 { 9511 {
8974 m_host.AddScriptLPS(1); 9512 m_host.AddScriptLPS(1);
8975 9513
8976 lock (m_host.TaskInventory) 9514 m_host.TaskInventory.LockItemsForRead(true);
9515 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8977 { 9516 {
8978 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9517 if (inv.Value.Name == item)
8979 { 9518 {
8980 if (inv.Value.Name == item) 9519 m_host.TaskInventory.LockItemsForRead(false);
8981 { 9520 return inv.Value.CreatorID.ToString();
8982 return inv.Value.CreatorID.ToString();
8983 }
8984 } 9521 }
8985 } 9522 }
9523 m_host.TaskInventory.LockItemsForRead(false);
8986 9524
8987 llSay(0, "No item name '" + item + "'"); 9525 llSay(0, "No item name '" + item + "'");
8988 9526
@@ -9130,7 +9668,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9130 } 9668 }
9131 9669
9132 /// <summary> 9670 /// <summary>
9133 /// illListReplaceList removes the sub-list defined by the inclusive indices 9671 /// llListReplaceList removes the sub-list defined by the inclusive indices
9134 /// start and end and inserts the src list in its place. The inclusive 9672 /// start and end and inserts the src list in its place. The inclusive
9135 /// nature of the indices means that at least one element must be deleted 9673 /// nature of the indices means that at least one element must be deleted
9136 /// if the indices are within the bounds of the existing list. I.e. 2,2 9674 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9187,16 +9725,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9187 // based upon end. Note that if end exceeds the upper 9725 // based upon end. Note that if end exceeds the upper
9188 // bound in this case, the entire destination list 9726 // bound in this case, the entire destination list
9189 // is removed. 9727 // is removed.
9190 else 9728 else if (start == 0)
9191 { 9729 {
9192 if (end + 1 < dest.Length) 9730 if (end + 1 < dest.Length)
9193 {
9194 return src + dest.GetSublist(end + 1, -1); 9731 return src + dest.GetSublist(end + 1, -1);
9195 }
9196 else 9732 else
9197 {
9198 return src; 9733 return src;
9199 } 9734 }
9735 else // Start < 0
9736 {
9737 if (end + 1 < dest.Length)
9738 return dest.GetSublist(end + 1, -1);
9739 else
9740 return new LSL_List();
9200 } 9741 }
9201 } 9742 }
9202 // Finally, if start > end, we strip away a prefix and 9743 // Finally, if start > end, we strip away a prefix and
@@ -9247,17 +9788,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9247 int width = 0; 9788 int width = 0;
9248 int height = 0; 9789 int height = 0;
9249 9790
9250 ParcelMediaCommandEnum? commandToSend = null; 9791 uint commandToSend = 0;
9251 float time = 0.0f; // default is from start 9792 float time = 0.0f; // default is from start
9252 9793
9253 ScenePresence presence = null; 9794 ScenePresence presence = null;
9254 9795
9255 for (int i = 0; i < commandList.Data.Length; i++) 9796 for (int i = 0; i < commandList.Data.Length; i++)
9256 { 9797 {
9257 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 9798 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9258 switch (command) 9799 switch (command)
9259 { 9800 {
9260 case ParcelMediaCommandEnum.Agent: 9801 case (uint)ParcelMediaCommandEnum.Agent:
9261 // we send only to one agent 9802 // we send only to one agent
9262 if ((i + 1) < commandList.Length) 9803 if ((i + 1) < commandList.Length)
9263 { 9804 {
@@ -9274,25 +9815,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9274 } 9815 }
9275 break; 9816 break;
9276 9817
9277 case ParcelMediaCommandEnum.Loop: 9818 case (uint)ParcelMediaCommandEnum.Loop:
9278 loop = 1; 9819 loop = 1;
9279 commandToSend = command; 9820 commandToSend = command;
9280 update = true; //need to send the media update packet to set looping 9821 update = true; //need to send the media update packet to set looping
9281 break; 9822 break;
9282 9823
9283 case ParcelMediaCommandEnum.Play: 9824 case (uint)ParcelMediaCommandEnum.Play:
9284 loop = 0; 9825 loop = 0;
9285 commandToSend = command; 9826 commandToSend = command;
9286 update = true; //need to send the media update packet to make sure it doesn't loop 9827 update = true; //need to send the media update packet to make sure it doesn't loop
9287 break; 9828 break;
9288 9829
9289 case ParcelMediaCommandEnum.Pause: 9830 case (uint)ParcelMediaCommandEnum.Pause:
9290 case ParcelMediaCommandEnum.Stop: 9831 case (uint)ParcelMediaCommandEnum.Stop:
9291 case ParcelMediaCommandEnum.Unload: 9832 case (uint)ParcelMediaCommandEnum.Unload:
9292 commandToSend = command; 9833 commandToSend = command;
9293 break; 9834 break;
9294 9835
9295 case ParcelMediaCommandEnum.Url: 9836 case (uint)ParcelMediaCommandEnum.Url:
9296 if ((i + 1) < commandList.Length) 9837 if ((i + 1) < commandList.Length)
9297 { 9838 {
9298 if (commandList.Data[i + 1] is LSL_String) 9839 if (commandList.Data[i + 1] is LSL_String)
@@ -9305,7 +9846,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9305 } 9846 }
9306 break; 9847 break;
9307 9848
9308 case ParcelMediaCommandEnum.Texture: 9849 case (uint)ParcelMediaCommandEnum.Texture:
9309 if ((i + 1) < commandList.Length) 9850 if ((i + 1) < commandList.Length)
9310 { 9851 {
9311 if (commandList.Data[i + 1] is LSL_String) 9852 if (commandList.Data[i + 1] is LSL_String)
@@ -9318,7 +9859,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9318 } 9859 }
9319 break; 9860 break;
9320 9861
9321 case ParcelMediaCommandEnum.Time: 9862 case (uint)ParcelMediaCommandEnum.Time:
9322 if ((i + 1) < commandList.Length) 9863 if ((i + 1) < commandList.Length)
9323 { 9864 {
9324 if (commandList.Data[i + 1] is LSL_Float) 9865 if (commandList.Data[i + 1] is LSL_Float)
@@ -9330,7 +9871,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9330 } 9871 }
9331 break; 9872 break;
9332 9873
9333 case ParcelMediaCommandEnum.AutoAlign: 9874 case (uint)ParcelMediaCommandEnum.AutoAlign:
9334 if ((i + 1) < commandList.Length) 9875 if ((i + 1) < commandList.Length)
9335 { 9876 {
9336 if (commandList.Data[i + 1] is LSL_Integer) 9877 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9344,7 +9885,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9344 } 9885 }
9345 break; 9886 break;
9346 9887
9347 case ParcelMediaCommandEnum.Type: 9888 case (uint)ParcelMediaCommandEnum.Type:
9348 if ((i + 1) < commandList.Length) 9889 if ((i + 1) < commandList.Length)
9349 { 9890 {
9350 if (commandList.Data[i + 1] is LSL_String) 9891 if (commandList.Data[i + 1] is LSL_String)
@@ -9357,7 +9898,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9357 } 9898 }
9358 break; 9899 break;
9359 9900
9360 case ParcelMediaCommandEnum.Desc: 9901 case (uint)ParcelMediaCommandEnum.Desc:
9361 if ((i + 1) < commandList.Length) 9902 if ((i + 1) < commandList.Length)
9362 { 9903 {
9363 if (commandList.Data[i + 1] is LSL_String) 9904 if (commandList.Data[i + 1] is LSL_String)
@@ -9370,7 +9911,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9370 } 9911 }
9371 break; 9912 break;
9372 9913
9373 case ParcelMediaCommandEnum.Size: 9914 case (uint)ParcelMediaCommandEnum.Size:
9374 if ((i + 2) < commandList.Length) 9915 if ((i + 2) < commandList.Length)
9375 { 9916 {
9376 if (commandList.Data[i + 1] is LSL_Integer) 9917 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9440,7 +9981,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9440 } 9981 }
9441 } 9982 }
9442 9983
9443 if (commandToSend != null) 9984 if (commandToSend != 0)
9444 { 9985 {
9445 // the commandList contained a start/stop/... command, too 9986 // the commandList contained a start/stop/... command, too
9446 if (presence == null) 9987 if (presence == null)
@@ -9477,7 +10018,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9477 10018
9478 if (aList.Data[i] != null) 10019 if (aList.Data[i] != null)
9479 { 10020 {
9480 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10021 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9481 { 10022 {
9482 case ParcelMediaCommandEnum.Url: 10023 case ParcelMediaCommandEnum.Url:
9483 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10024 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9520,16 +10061,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9520 { 10061 {
9521 m_host.AddScriptLPS(1); 10062 m_host.AddScriptLPS(1);
9522 10063
9523 lock (m_host.TaskInventory) 10064 m_host.TaskInventory.LockItemsForRead(true);
10065 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9524 { 10066 {
9525 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10067 if (inv.Value.Name == name)
9526 { 10068 {
9527 if (inv.Value.Name == name) 10069 m_host.TaskInventory.LockItemsForRead(false);
9528 { 10070 return inv.Value.Type;
9529 return inv.Value.Type;
9530 }
9531 } 10071 }
9532 } 10072 }
10073 m_host.TaskInventory.LockItemsForRead(false);
9533 10074
9534 return -1; 10075 return -1;
9535 } 10076 }
@@ -9540,15 +10081,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9540 10081
9541 if (quick_pay_buttons.Data.Length < 4) 10082 if (quick_pay_buttons.Data.Length < 4)
9542 { 10083 {
9543 LSLError("List must have at least 4 elements"); 10084 int x;
9544 return; 10085 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10086 {
10087 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10088 }
9545 } 10089 }
9546 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10090 int[] nPrice = new int[5];
9547 10091 nPrice[0] = price;
9548 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10092 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9549 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10093 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9550 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10094 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9551 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10095 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10096 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9552 m_host.ParentGroup.HasGroupChanged = true; 10097 m_host.ParentGroup.HasGroupChanged = true;
9553 } 10098 }
9554 10099
@@ -9560,17 +10105,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9560 if (invItemID == UUID.Zero) 10105 if (invItemID == UUID.Zero)
9561 return new LSL_Vector(); 10106 return new LSL_Vector();
9562 10107
9563 lock (m_host.TaskInventory) 10108 m_host.TaskInventory.LockItemsForRead(true);
10109 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9564 { 10110 {
9565 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10111 m_host.TaskInventory.LockItemsForRead(false);
9566 return new LSL_Vector(); 10112 return new LSL_Vector();
10113 }
9567 10114
9568 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 10115 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9569 { 10116 {
9570 ShoutError("No permissions to track the camera"); 10117 ShoutError("No permissions to track the camera");
9571 return new LSL_Vector(); 10118 m_host.TaskInventory.LockItemsForRead(false);
9572 } 10119 return new LSL_Vector();
9573 } 10120 }
10121 m_host.TaskInventory.LockItemsForRead(false);
9574 10122
9575 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10123 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9576 if (presence != null) 10124 if (presence != null)
@@ -9588,17 +10136,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9588 if (invItemID == UUID.Zero) 10136 if (invItemID == UUID.Zero)
9589 return new LSL_Rotation(); 10137 return new LSL_Rotation();
9590 10138
9591 lock (m_host.TaskInventory) 10139 m_host.TaskInventory.LockItemsForRead(true);
10140 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9592 { 10141 {
9593 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10142 m_host.TaskInventory.LockItemsForRead(false);
9594 return new LSL_Rotation(); 10143 return new LSL_Rotation();
9595
9596 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9597 {
9598 ShoutError("No permissions to track the camera");
9599 return new LSL_Rotation();
9600 }
9601 } 10144 }
10145 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
10146 {
10147 ShoutError("No permissions to track the camera");
10148 m_host.TaskInventory.LockItemsForRead(false);
10149 return new LSL_Rotation();
10150 }
10151 m_host.TaskInventory.LockItemsForRead(false);
9602 10152
9603 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10153 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9604 if (presence != null) 10154 if (presence != null)
@@ -9660,8 +10210,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9660 { 10210 {
9661 m_host.AddScriptLPS(1); 10211 m_host.AddScriptLPS(1);
9662 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0); 10212 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0);
9663 if (detectedParams == null) return; // only works on the first detected avatar 10213 if (detectedParams == null)
9664 10214 {
10215 if (m_host.ParentGroup.IsAttachment == true)
10216 {
10217 detectedParams = new DetectParams();
10218 detectedParams.Key = m_host.OwnerID;
10219 }
10220 else
10221 {
10222 return;
10223 }
10224 }
10225
9665 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10226 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9666 if (avatar != null) 10227 if (avatar != null)
9667 { 10228 {
@@ -9669,6 +10230,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9669 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10230 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9670 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10231 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9671 } 10232 }
10233
9672 ScriptSleep(1000); 10234 ScriptSleep(1000);
9673 } 10235 }
9674 10236
@@ -9761,14 +10323,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9761 if (objectID == UUID.Zero) return; 10323 if (objectID == UUID.Zero) return;
9762 10324
9763 UUID agentID; 10325 UUID agentID;
9764 lock (m_host.TaskInventory) 10326 m_host.TaskInventory.LockItemsForRead(true);
9765 { 10327 // we need the permission first, to know which avatar we want to set the camera for
9766 // we need the permission first, to know which avatar we want to set the camera for 10328 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9767 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9768 10329
9769 if (agentID == UUID.Zero) return; 10330 if (agentID == UUID.Zero)
9770 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 10331 {
10332 m_host.TaskInventory.LockItemsForRead(false);
10333 return;
10334 }
10335 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10336 {
10337 m_host.TaskInventory.LockItemsForRead(false);
10338 return;
9771 } 10339 }
10340 m_host.TaskInventory.LockItemsForRead(false);
9772 10341
9773 ScenePresence presence = World.GetScenePresence(agentID); 10342 ScenePresence presence = World.GetScenePresence(agentID);
9774 10343
@@ -9777,12 +10346,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9777 10346
9778 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10347 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9779 object[] data = rules.Data; 10348 object[] data = rules.Data;
9780 for (int i = 0; i < data.Length; ++i) { 10349 for (int i = 0; i < data.Length; ++i)
10350 {
9781 int type = Convert.ToInt32(data[i++].ToString()); 10351 int type = Convert.ToInt32(data[i++].ToString());
9782 if (i >= data.Length) break; // odd number of entries => ignore the last 10352 if (i >= data.Length) break; // odd number of entries => ignore the last
9783 10353
9784 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10354 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9785 switch (type) { 10355 switch (type)
10356 {
9786 case ScriptBaseClass.CAMERA_FOCUS: 10357 case ScriptBaseClass.CAMERA_FOCUS:
9787 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10358 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9788 case ScriptBaseClass.CAMERA_POSITION: 10359 case ScriptBaseClass.CAMERA_POSITION:
@@ -9818,12 +10389,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9818 10389
9819 // we need the permission first, to know which avatar we want to clear the camera for 10390 // we need the permission first, to know which avatar we want to clear the camera for
9820 UUID agentID; 10391 UUID agentID;
9821 lock (m_host.TaskInventory) 10392 m_host.TaskInventory.LockItemsForRead(true);
10393 agentID = m_host.TaskInventory[invItemID].PermsGranter;
10394 if (agentID == UUID.Zero)
9822 { 10395 {
9823 agentID = m_host.TaskInventory[invItemID].PermsGranter; 10396 m_host.TaskInventory.LockItemsForRead(false);
9824 if (agentID == UUID.Zero) return; 10397 return;
9825 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
9826 } 10398 }
10399 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10400 {
10401 m_host.TaskInventory.LockItemsForRead(false);
10402 return;
10403 }
10404 m_host.TaskInventory.LockItemsForRead(false);
9827 10405
9828 ScenePresence presence = World.GetScenePresence(agentID); 10406 ScenePresence presence = World.GetScenePresence(agentID);
9829 10407
@@ -9890,19 +10468,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9890 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10468 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
9891 { 10469 {
9892 m_host.AddScriptLPS(1); 10470 m_host.AddScriptLPS(1);
9893 string ret = String.Empty; 10471
9894 string src1 = llBase64ToString(str1); 10472 if (str1 == String.Empty)
9895 string src2 = llBase64ToString(str2); 10473 return String.Empty;
9896 int c = 0; 10474 if (str2 == String.Empty)
9897 for (int i = 0; i < src1.Length; i++) 10475 return str1;
10476
10477 int len = str2.Length;
10478 if ((len % 4) != 0) // LL is EVIL!!!!
10479 {
10480 while (str2.EndsWith("="))
10481 str2 = str2.Substring(0, str2.Length - 1);
10482
10483 len = str2.Length;
10484 int mod = len % 4;
10485
10486 if (mod == 1)
10487 str2 = str2.Substring(0, str2.Length - 1);
10488 else if (mod == 2)
10489 str2 += "==";
10490 else if (mod == 3)
10491 str2 += "=";
10492 }
10493
10494 byte[] data1;
10495 byte[] data2;
10496 try
9898 { 10497 {
9899 ret += (char) (src1[i] ^ src2[c]); 10498 data1 = Convert.FromBase64String(str1);
10499 data2 = Convert.FromBase64String(str2);
10500 }
10501 catch (Exception)
10502 {
10503 return new LSL_String(String.Empty);
10504 }
9900 10505
9901 c++; 10506 byte[] d2 = new Byte[data1.Length];
9902 if (c >= src2.Length) 10507 int pos = 0;
9903 c = 0; 10508
10509 if (data1.Length <= data2.Length)
10510 {
10511 Array.Copy(data2, 0, d2, 0, data1.Length);
9904 } 10512 }
9905 return llStringToBase64(ret); 10513 else
10514 {
10515 while (pos < data1.Length)
10516 {
10517 len = data1.Length - pos;
10518 if (len > data2.Length)
10519 len = data2.Length;
10520
10521 Array.Copy(data2, 0, d2, pos, len);
10522 pos += len;
10523 }
10524 }
10525
10526 for (pos = 0 ; pos < data1.Length ; pos++ )
10527 data1[pos] ^= d2[pos];
10528
10529 return Convert.ToBase64String(data1);
9906 } 10530 }
9907 10531
9908 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10532 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -9959,12 +10583,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9959 Regex r = new Regex(authregex); 10583 Regex r = new Regex(authregex);
9960 int[] gnums = r.GetGroupNumbers(); 10584 int[] gnums = r.GetGroupNumbers();
9961 Match m = r.Match(url); 10585 Match m = r.Match(url);
9962 if (m.Success) { 10586 if (m.Success)
9963 for (int i = 1; i < gnums.Length; i++) { 10587 {
10588 for (int i = 1; i < gnums.Length; i++)
10589 {
9964 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10590 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
9965 //CaptureCollection cc = g.Captures; 10591 //CaptureCollection cc = g.Captures;
9966 } 10592 }
9967 if (m.Groups.Count == 5) { 10593 if (m.Groups.Count == 5)
10594 {
9968 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10595 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
9969 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10596 url = m.Groups[1].ToString() + m.Groups[4].ToString();
9970 } 10597 }
@@ -10250,15 +10877,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10250 10877
10251 internal UUID ScriptByName(string name) 10878 internal UUID ScriptByName(string name)
10252 { 10879 {
10253 lock (m_host.TaskInventory) 10880 m_host.TaskInventory.LockItemsForRead(true);
10881
10882 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10254 { 10883 {
10255 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 10884 if (item.Type == 10 && item.Name == name)
10256 { 10885 {
10257 if (item.Type == 10 && item.Name == name) 10886 m_host.TaskInventory.LockItemsForRead(false);
10258 return item.ItemID; 10887 return item.ItemID;
10259 } 10888 }
10260 } 10889 }
10261 10890
10891 m_host.TaskInventory.LockItemsForRead(false);
10892
10262 return UUID.Zero; 10893 return UUID.Zero;
10263 } 10894 }
10264 10895
@@ -10299,6 +10930,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10299 { 10930 {
10300 m_host.AddScriptLPS(1); 10931 m_host.AddScriptLPS(1);
10301 10932
10933 //Clone is thread safe
10302 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10934 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10303 10935
10304 UUID assetID = UUID.Zero; 10936 UUID assetID = UUID.Zero;
@@ -10361,6 +10993,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10361 { 10993 {
10362 m_host.AddScriptLPS(1); 10994 m_host.AddScriptLPS(1);
10363 10995
10996 //Clone is thread safe
10364 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10997 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10365 10998
10366 UUID assetID = UUID.Zero; 10999 UUID assetID = UUID.Zero;
@@ -10441,15 +11074,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10441 return GetLinkPrimitiveParams(obj, rules); 11074 return GetLinkPrimitiveParams(obj, rules);
10442 } 11075 }
10443 11076
10444 public void print(string str) 11077 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10445 { 11078 {
10446 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11079 List<SceneObjectPart> parts = GetLinkParts(link);
10447 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_itemID, "OSSL"); 11080 if (parts.Count < 1)
10448 if (ossl != null) 11081 return 0;
10449 { 11082
10450 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11083 return GetNumberOfSides(parts[0]);
10451 m_log.Info("LSL print():" + str);
10452 }
10453 } 11084 }
10454 11085
10455 private string Name2Username(string name) 11086 private string Name2Username(string name)
@@ -10495,153 +11126,392 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10495 return rq.ToString(); 11126 return rq.ToString();
10496 } 11127 }
10497 11128
11129 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11130 {
11131 m_SayShoutCount = 0;
11132 }
11133
11134 private struct Tri
11135 {
11136 public Vector3 p1;
11137 public Vector3 p2;
11138 public Vector3 p3;
11139 }
11140
11141 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11142 {
11143 float height = avatar.Appearance.AvatarHeight;
11144 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11145 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11146
11147 if (point.X > b1.X && point.X < b2.X &&
11148 point.Y > b1.Y && point.Y < b2.Y &&
11149 point.Z > b1.Z && point.Z < b2.Z)
11150 return true;
11151 return false;
11152 }
11153
11154 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11155 {
11156 List<ContactResult> contacts = new List<ContactResult>();
11157
11158 Vector3 ab = rayEnd - rayStart;
11159
11160 World.ForEachScenePresence(delegate(ScenePresence sp)
11161 {
11162 Vector3 ac = sp.AbsolutePosition - rayStart;
11163 Vector3 bc = sp.AbsolutePosition - rayEnd;
11164
11165 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11166
11167 if (d > 1.5)
11168 return;
11169
11170 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11171
11172 if (d2 > 0)
11173 return;
11174
11175 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11176 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11177
11178 if (!InBoundingBox(sp, p))
11179 return;
11180
11181 ContactResult result = new ContactResult ();
11182 result.ConsumerID = sp.LocalId;
11183 result.Depth = Vector3.Distance(rayStart, p);
11184 result.Normal = Vector3.Zero;
11185 result.Pos = p;
11186
11187 contacts.Add(result);
11188 });
11189
11190 return contacts.ToArray();
11191 }
11192
11193 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11194 {
11195 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11196 List<ContactResult> contacts = new List<ContactResult>();
11197
11198 Vector3 ab = rayEnd - rayStart;
11199
11200 World.ForEachSOG(delegate(SceneObjectGroup group)
11201 {
11202 if (m_host.ParentGroup == group)
11203 return;
11204
11205 if (group.IsAttachment)
11206 return;
11207
11208 if (group.RootPart.PhysActor == null)
11209 {
11210 if (!includePhantom)
11211 return;
11212 }
11213 else
11214 {
11215 if (group.RootPart.PhysActor.IsPhysical)
11216 {
11217 if (!includePhysical)
11218 return;
11219 }
11220 else
11221 {
11222 if (!includeNonPhysical)
11223 return;
11224 }
11225 }
11226
11227 // Find the radius ouside of which we don't even need to hit test
11228 float minX;
11229 float maxX;
11230 float minY;
11231 float maxY;
11232 float minZ;
11233 float maxZ;
11234
11235 float radius = 0.0f;
11236
11237 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11238
11239 if (Math.Abs(minX) > radius)
11240 radius = Math.Abs(minX);
11241 if (Math.Abs(minY) > radius)
11242 radius = Math.Abs(minY);
11243 if (Math.Abs(minZ) > radius)
11244 radius = Math.Abs(minZ);
11245 if (Math.Abs(maxX) > radius)
11246 radius = Math.Abs(maxX);
11247 if (Math.Abs(maxY) > radius)
11248 radius = Math.Abs(maxY);
11249 if (Math.Abs(maxZ) > radius)
11250 radius = Math.Abs(maxZ);
11251
11252 Vector3 ac = group.AbsolutePosition - rayStart;
11253 Vector3 bc = group.AbsolutePosition - rayEnd;
11254
11255 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11256
11257 // Too far off ray, don't bother
11258 if (d > radius)
11259 return;
11260
11261 // Behind ray, drop
11262 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11263 if (d2 > 0)
11264 return;
11265
11266 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11267 // Miss.
11268 if (!intersection.HitTF)
11269 return;
11270
11271 ContactResult result = new ContactResult ();
11272 result.ConsumerID = group.LocalId;
11273 result.Depth = intersection.distance;
11274 result.Normal = intersection.normal;
11275 result.Pos = intersection.ipoint;
11276
11277 contacts.Add(result);
11278 });
11279
11280 return contacts.ToArray();
11281 }
11282
11283 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11284 {
11285 double[,] heightfield = World.Heightmap.GetDoubles();
11286 List<ContactResult> contacts = new List<ContactResult>();
11287
11288 double min = 2048.0;
11289 double max = 0.0;
11290
11291 // Find the min and max of the heightfield
11292 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11293 {
11294 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11295 {
11296 if (heightfield[x, y] > max)
11297 max = heightfield[x, y];
11298 if (heightfield[x, y] < min)
11299 min = heightfield[x, y];
11300 }
11301 }
11302
11303
11304 // A ray extends past rayEnd, but doesn't go back before
11305 // rayStart. If the start is above the highest point of the ground
11306 // and the ray goes up, we can't hit the ground. Ever.
11307 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11308 return null;
11309
11310 // Same for going down
11311 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11312 return null;
11313
11314 List<Tri> trilist = new List<Tri>();
11315
11316 // Create our triangle list
11317 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11318 {
11319 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11320 {
11321 Tri t1 = new Tri();
11322 Tri t2 = new Tri();
11323
11324 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11325 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11326 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11327 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11328
11329 t1.p1 = p1;
11330 t1.p2 = p2;
11331 t1.p3 = p3;
11332
11333 t2.p1 = p3;
11334 t2.p2 = p4;
11335 t2.p3 = p1;
11336
11337 trilist.Add(t1);
11338 trilist.Add(t2);
11339 }
11340 }
11341
11342 // Ray direction
11343 Vector3 rayDirection = rayEnd - rayStart;
11344
11345 foreach (Tri t in trilist)
11346 {
11347 // Compute triangle plane normal and edges
11348 Vector3 u = t.p2 - t.p1;
11349 Vector3 v = t.p3 - t.p1;
11350 Vector3 n = Vector3.Cross(u, v);
11351
11352 if (n == Vector3.Zero)
11353 continue;
11354
11355 Vector3 w0 = rayStart - t.p1;
11356 double a = -Vector3.Dot(n, w0);
11357 double b = Vector3.Dot(n, rayDirection);
11358
11359 // Not intersecting the plane, or in plane (same thing)
11360 // Ignoring this MAY cause the ground to not be detected
11361 // sometimes
11362 if (Math.Abs(b) < 0.000001)
11363 continue;
11364
11365 double r = a / b;
11366
11367 // ray points away from plane
11368 if (r < 0.0)
11369 continue;
11370
11371 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11372
11373 float uu = Vector3.Dot(u, u);
11374 float uv = Vector3.Dot(u, v);
11375 float vv = Vector3.Dot(v, v);
11376 Vector3 w = ip - t.p1;
11377 float wu = Vector3.Dot(w, u);
11378 float wv = Vector3.Dot(w, v);
11379 float d = uv * uv - uu * vv;
11380
11381 float cs = (uv * wv - vv * wu) / d;
11382 if (cs < 0 || cs > 1.0)
11383 continue;
11384 float ct = (uv * wu - uu * wv) / d;
11385 if (ct < 0 || (cs + ct) > 1.0)
11386 continue;
11387
11388 // Add contact point
11389 ContactResult result = new ContactResult ();
11390 result.ConsumerID = 0;
11391 result.Depth = Vector3.Distance(rayStart, ip);
11392 result.Normal = n;
11393 result.Pos = ip;
11394
11395 contacts.Add(result);
11396 }
11397
11398 if (contacts.Count == 0)
11399 return null;
11400
11401 contacts.Sort(delegate(ContactResult a, ContactResult b)
11402 {
11403 return (int)(a.Depth - b.Depth);
11404 });
11405
11406 return contacts[0];
11407 }
11408
10498 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11409 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10499 { 11410 {
11411 LSL_List list = new LSL_List();
11412
10500 m_host.AddScriptLPS(1); 11413 m_host.AddScriptLPS(1);
10501 11414
10502 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11415 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10503 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11416 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10504 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11417 Vector3 dir = rayEnd - rayStart;
10505 11418
10506 int count = 0; 11419 int count = 1;
10507// int detectPhantom = 0; 11420 bool detectPhantom = false;
10508 int dataFlags = 0; 11421 int dataFlags = 0;
10509 int rejectTypes = 0; 11422 int rejectTypes = 0;
10510 11423
10511 for (int i = 0; i < options.Length; i += 2) 11424 for (int i = 0; i < options.Length; i += 2)
10512 { 11425 {
10513 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11426 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10514 {
10515 count = options.GetLSLIntegerItem(i + 1); 11427 count = options.GetLSLIntegerItem(i + 1);
10516 } 11428 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10517// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11429 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10518// {
10519// detectPhantom = options.GetLSLIntegerItem(i + 1);
10520// }
10521 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11430 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10522 {
10523 dataFlags = options.GetLSLIntegerItem(i + 1); 11431 dataFlags = options.GetLSLIntegerItem(i + 1);
10524 }
10525 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11432 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10526 {
10527 rejectTypes = options.GetLSLIntegerItem(i + 1); 11433 rejectTypes = options.GetLSLIntegerItem(i + 1);
10528 }
10529 } 11434 }
10530 11435
10531 LSL_List list = new LSL_List(); 11436 if (count > 16)
10532 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11437 count = 16;
10533
10534 double distance = Util.GetDistanceTo(startvector, endvector);
10535 11438
10536 if (distance == 0) 11439 List<ContactResult> results = new List<ContactResult>();
10537 distance = 0.001;
10538
10539 Vector3 posToCheck = startvector;
10540 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10541 11440
10542 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11441 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10543 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11442 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10544 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11443 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10545 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11444 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10546 11445
10547 for (float i = 0; i <= distance; i += 0.1f) 11446 if (checkTerrain)
10548 { 11447 {
10549 posToCheck = startvector + (dir * (i / (float)distance)); 11448 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11449 if (groundContact != null)
11450 results.Add((ContactResult)groundContact);
11451 }
10550 11452
10551 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11453 if (checkAgents)
10552 { 11454 {
10553 ContactResult result = new ContactResult(); 11455 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
10554 result.ConsumerID = 0; 11456 foreach (ContactResult r in agentHits)
10555 result.Depth = 0; 11457 results.Add(r);
10556 result.Normal = Vector3.Zero; 11458 }
10557 result.Pos = posToCheck;
10558 results.Add(result);
10559 checkTerrain = false;
10560 }
10561 11459
10562 if (checkAgents) 11460 if (checkPhysical || checkNonPhysical)
10563 { 11461 {
10564 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11462 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
10565 { 11463 foreach (ContactResult r in objectHits)
10566 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X)) 11464 results.Add(r);
10567 {
10568 ContactResult result = new ContactResult ();
10569 result.ConsumerID = sp.LocalId;
10570 result.Depth = 0;
10571 result.Normal = Vector3.Zero;
10572 result.Pos = posToCheck;
10573 results.Add(result);
10574 }
10575 });
10576 }
10577 } 11465 }
10578 11466
10579 int refcount = 0; 11467 results.Sort(delegate(ContactResult a, ContactResult b)
11468 {
11469 return (int)(a.Depth - b.Depth);
11470 });
11471
11472 int values = 0;
10580 foreach (ContactResult result in results) 11473 foreach (ContactResult result in results)
10581 { 11474 {
10582 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) 11475 UUID itemID = UUID.Zero;
10583 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0) 11476 int linkNum = 0;
10584 continue;
10585
10586 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID);
10587 11477
10588 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) 11478 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
10589 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents 11479 // It's a prim!
10590 11480 if (part != null)
10591 if (entity == null)
10592 { 11481 {
10593 list.Add(UUID.Zero); 11482 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10594 11483 itemID = part.ParentGroup.UUID;
10595 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11484 else
10596 list.Add(0); 11485 itemID = part.UUID;
10597
10598 list.Add(result.Pos);
10599
10600 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10601 list.Add(result.Normal);
10602 11486
10603 continue; //Can't find it, so add UUID.Zero 11487 linkNum = part.LinkNum;
10604 } 11488 }
10605 11489 else
10606 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity &&
10607 ((ISceneChildEntity)intersection.obj).PhysActor == null)
10608 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
10609
10610 if (entity is SceneObjectPart)
10611 { 11490 {
10612 if (((SceneObjectPart)entity).PhysActor != null && ((SceneObjectPart)entity).PhysActor.IsPhysical) 11491 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10613 { 11492 /// It it a boy? a girl?
10614 if (!checkPhysical) 11493 if (sp != null)
10615 continue; 11494 itemID = sp.UUID;
10616 }
10617 else
10618 {
10619 if (!checkNonPhysical)
10620 continue;
10621 }
10622 } 11495 }
10623 11496
10624 refcount++; 11497 list.Add(new LSL_String(itemID.ToString()));
10625 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11498 list.Add(new LSL_String(result.Pos.ToString()));
10626 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10627 else
10628 list.Add(entity.UUID);
10629 11499
10630 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11500 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10631 { 11501 list.Add(new LSL_Integer(linkNum));
10632 if (entity is SceneObjectPart)
10633 list.Add(((SceneObjectPart)entity).LinkNum);
10634 else
10635 list.Add(0);
10636 }
10637 11502
10638 list.Add(result.Pos);
10639 11503
10640 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11504 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10641 list.Add(result.Normal); 11505 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11506
11507 values++;
11508 count--;
11509
11510 if (count == 0)
11511 break;
10642 } 11512 }
10643 11513
10644 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11514 list.Add(new LSL_Integer(values));
10645 11515
10646 return list; 11516 return list;
10647 } 11517 }
@@ -10681,7 +11551,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10681 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 11551 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10682 if (!isAccount) return 0; 11552 if (!isAccount) return 0;
10683 if (estate.HasAccess(id)) return 1; 11553 if (estate.HasAccess(id)) return 1;
10684 if (estate.IsBanned(id)) 11554 if (estate.IsBanned(id, World.GetUserFlags(id)))
10685 estate.RemoveBan(id); 11555 estate.RemoveBan(id);
10686 estate.AddEstateUser(id); 11556 estate.AddEstateUser(id);
10687 break; 11557 break;
@@ -10700,14 +11570,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10700 break; 11570 break;
10701 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 11571 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10702 if (!isAccount) return 0; 11572 if (!isAccount) return 0;
10703 if (estate.IsBanned(id)) return 1; 11573 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10704 EstateBan ban = new EstateBan(); 11574 EstateBan ban = new EstateBan();
10705 ban.EstateID = estate.EstateID; 11575 ban.EstateID = estate.EstateID;
10706 ban.BannedUserID = id; 11576 ban.BannedUserID = id;
10707 estate.AddBan(ban); 11577 estate.AddBan(ban);
10708 break; 11578 break;
10709 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 11579 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10710 if (!isAccount || !estate.IsBanned(id)) return 0; 11580 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10711 estate.RemoveBan(id); 11581 estate.RemoveBan(id);
10712 break; 11582 break;
10713 default: return 0; 11583 default: return 0;
@@ -10733,22 +11603,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10733 NotImplemented("llGetSPMaxMemory"); 11603 NotImplemented("llGetSPMaxMemory");
10734 } 11604 }
10735 11605
10736 public void llGetUsedMemory() 11606 public virtual LSL_Integer llGetUsedMemory()
10737 { 11607 {
10738 m_host.AddScriptLPS(1); 11608 m_host.AddScriptLPS(1);
10739 NotImplemented("llGetUsedMemory"); 11609 NotImplemented("llGetUsedMemory");
11610 return 0;
10740 } 11611 }
10741 11612
10742 public void llScriptProfiler(LSL_Integer flags) 11613 public void llScriptProfiler(LSL_Integer flags)
10743 { 11614 {
10744 m_host.AddScriptLPS(1); 11615 m_host.AddScriptLPS(1);
10745 NotImplemented("llScriptProfiler"); 11616 //NotImplemented("llScriptProfiler");
10746 } 11617 }
10747 11618
10748 public void llSetSoundQueueing(int queue) 11619 public void llSetSoundQueueing(int queue)
10749 { 11620 {
10750 m_host.AddScriptLPS(1); 11621 m_host.AddScriptLPS(1);
10751 NotImplemented("llSetSoundQueueing");
10752 } 11622 }
10753 11623
10754 public void llCollisionSprite(string impact_sprite) 11624 public void llCollisionSprite(string impact_sprite)
@@ -10760,7 +11630,133 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10760 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 11630 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10761 { 11631 {
10762 m_host.AddScriptLPS(1); 11632 m_host.AddScriptLPS(1);
10763 NotImplemented("llGodLikeRezObject"); 11633
11634 if (!World.Permissions.IsGod(m_host.OwnerID))
11635 NotImplemented("llGodLikeRezObject");
11636
11637 AssetBase rezAsset = World.AssetService.Get(inventory);
11638 if (rezAsset == null)
11639 {
11640 llSay(0, "Asset not found");
11641 return;
11642 }
11643
11644 SceneObjectGroup group = null;
11645
11646 try
11647 {
11648 string xmlData = Utils.BytesToString(rezAsset.Data);
11649 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
11650 }
11651 catch
11652 {
11653 llSay(0, "Asset not found");
11654 return;
11655 }
11656
11657 if (group == null)
11658 {
11659 llSay(0, "Asset not found");
11660 return;
11661 }
11662
11663 group.RootPart.AttachPoint = group.RootPart.Shape.State;
11664 group.RootPart.AttachOffset = group.AbsolutePosition;
11665
11666 group.ResetIDs();
11667
11668 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
11669 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
11670 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
11671 group.ScheduleGroupForFullUpdate();
11672
11673 // objects rezzed with this method are die_at_edge by default.
11674 group.RootPart.SetDieAtEdge(true);
11675
11676 group.ResumeScripts();
11677
11678 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
11679 "object_rez", new Object[] {
11680 new LSL_String(
11681 group.RootPart.UUID.ToString()) },
11682 new DetectParams[0]));
11683 }
11684
11685 public LSL_String llTransferLindenDollars(string destination, int amount)
11686 {
11687 UUID txn = UUID.Random();
11688
11689 Util.FireAndForget(delegate(object x)
11690 {
11691 int replycode = 0;
11692 string replydata = destination + "," + amount.ToString();
11693
11694 try
11695 {
11696 UUID invItemID=InventorySelf();
11697 if (invItemID == UUID.Zero)
11698 {
11699 replydata = "SERVICE_ERROR";
11700 return;
11701 }
11702
11703 m_host.AddScriptLPS(1);
11704
11705 m_host.TaskInventory.LockItemsForRead(true);
11706 TaskInventoryItem item = m_host.TaskInventory[invItemID];
11707 m_host.TaskInventory.LockItemsForRead(false);
11708
11709 if (item.PermsGranter == UUID.Zero)
11710 {
11711 replydata = "MISSING_PERMISSION_DEBIT";
11712 return;
11713 }
11714
11715 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
11716 {
11717 replydata = "MISSING_PERMISSION_DEBIT";
11718 return;
11719 }
11720
11721 UUID toID = new UUID();
11722
11723 if (!UUID.TryParse(destination, out toID))
11724 {
11725 replydata = "INVALID_AGENT";
11726 return;
11727 }
11728
11729 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
11730
11731 if (money == null)
11732 {
11733 replydata = "TRANSFERS_DISABLED";
11734 return;
11735 }
11736
11737 bool result = money.ObjectGiveMoney(
11738 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
11739
11740 if (result)
11741 {
11742 replycode = 1;
11743 return;
11744 }
11745
11746 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
11747 }
11748 finally
11749 {
11750 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
11751 "transaction_result", new Object[] {
11752 new LSL_String(txn.ToString()),
11753 new LSL_Integer(replycode),
11754 new LSL_String(replydata) },
11755 new DetectParams[0]));
11756 }
11757 });
11758
11759 return txn.ToString();
10764 } 11760 }
10765 11761
10766 #endregion 11762 #endregion
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 7792ab5..4831377 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()
@@ -912,18 +921,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
912 if (target != null) 921 if (target != null)
913 { 922 {
914 UUID animID=UUID.Zero; 923 UUID animID=UUID.Zero;
915 lock (m_host.TaskInventory) 924 m_host.TaskInventory.LockItemsForRead(true);
925 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
916 { 926 {
917 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 927 if (inv.Value.Name == animation)
918 { 928 {
919 if (inv.Value.Name == animation) 929 if (inv.Value.Type == (int)AssetType.Animation)
920 { 930 animID = inv.Value.AssetID;
921 if (inv.Value.Type == (int)AssetType.Animation) 931 continue;
922 animID = inv.Value.AssetID;
923 continue;
924 }
925 } 932 }
926 } 933 }
934 m_host.TaskInventory.LockItemsForRead(false);
927 if (animID == UUID.Zero) 935 if (animID == UUID.Zero)
928 target.Animator.AddAnimation(animation, m_host.UUID); 936 target.Animator.AddAnimation(animation, m_host.UUID);
929 else 937 else
@@ -950,18 +958,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
950 if (target != null) 958 if (target != null)
951 { 959 {
952 UUID animID = UUID.Zero; 960 UUID animID = UUID.Zero;
953 lock (m_host.TaskInventory) 961 m_host.TaskInventory.LockItemsForRead(true);
962 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
954 { 963 {
955 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 964 if (inv.Value.Name == animation)
956 { 965 {
957 if (inv.Value.Name == animation) 966 if (inv.Value.Type == (int)AssetType.Animation)
958 { 967 animID = inv.Value.AssetID;
959 if (inv.Value.Type == (int)AssetType.Animation) 968 continue;
960 animID = inv.Value.AssetID;
961 continue;
962 }
963 } 969 }
964 } 970 }
971 m_host.TaskInventory.LockItemsForRead(false);
965 972
966 if (animID == UUID.Zero) 973 if (animID == UUID.Zero)
967 target.Animator.RemoveAnimation(animation); 974 target.Animator.RemoveAnimation(animation);
@@ -1792,6 +1799,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1792 1799
1793 if (!UUID.TryParse(notecardNameOrUuid, out assetID)) 1800 if (!UUID.TryParse(notecardNameOrUuid, out assetID))
1794 { 1801 {
1802 m_host.TaskInventory.LockItemsForRead(true);
1795 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1803 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1796 { 1804 {
1797 if (item.Type == 7 && item.Name == notecardNameOrUuid) 1805 if (item.Type == 7 && item.Name == notecardNameOrUuid)
@@ -1799,6 +1807,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1799 assetID = item.AssetID; 1807 assetID = item.AssetID;
1800 } 1808 }
1801 } 1809 }
1810 m_host.TaskInventory.LockItemsForRead(false);
1802 } 1811 }
1803 1812
1804 if (assetID == UUID.Zero) 1813 if (assetID == UUID.Zero)
@@ -2216,18 +2225,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2216 2225
2217 private LSL_Key NpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, bool owned) 2226 private LSL_Key NpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, bool owned)
2218 { 2227 {
2228 if (!owned)
2229 OSSLError("Unowned NPCs are unsupported");
2230
2231 string groupTitle = String.Empty;
2232
2233 if (firstname != String.Empty || lastname != String.Empty)
2234 {
2235 if (firstname != "Shown outfit:")
2236 groupTitle = "- NPC -";
2237 }
2238
2219 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2239 INPCModule module = World.RequestModuleInterface<INPCModule>();
2220 if (module != null) 2240 if (module != null)
2221 { 2241 {
2222 AvatarAppearance appearance = null; 2242 AvatarAppearance appearance = null;
2223 2243
2224 UUID id; 2244// UUID id;
2225 if (UUID.TryParse(notecard, out id)) 2245// if (UUID.TryParse(notecard, out id))
2226 { 2246// {
2227 ScenePresence clonePresence = World.GetScenePresence(id); 2247// ScenePresence clonePresence = World.GetScenePresence(id);
2228 if (clonePresence != null) 2248// if (clonePresence != null)
2229 appearance = clonePresence.Appearance; 2249// appearance = clonePresence.Appearance;
2230 } 2250// }
2231 2251
2232 if (appearance == null) 2252 if (appearance == null)
2233 { 2253 {
@@ -2253,6 +2273,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2253 ownerID, 2273 ownerID,
2254 World,appearance); 2274 World,appearance);
2255 2275
2276 ScenePresence sp;
2277 if (World.TryGetScenePresence(x, out sp))
2278 {
2279 sp.Grouptitle = groupTitle;
2280 sp.SendAvatarDataToAllAgents();
2281 }
2256 return new LSL_Key(x.ToString()); 2282 return new LSL_Key(x.ToString());
2257 } 2283 }
2258 2284
@@ -2495,7 +2521,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2495 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2521 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2496 return; 2522 return;
2497 2523
2498 module.DeleteNPC(npcId, World); 2524 Util.FireAndForget(delegate(object x) {
2525 module.DeleteNPC(npcId, World);
2526 });
2499 } 2527 }
2500 } 2528 }
2501 2529
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 8356dce..dddf913 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 }