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.cs2815
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs60
-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, 2126 insertions, 928 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 d6de39f..466e540 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);
@@ -161,6 +175,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
161 get { return m_ScriptEngine.World; } 175 get { return m_ScriptEngine.World; }
162 } 176 }
163 177
178 [DebuggerNonUserCode]
164 public void state(string newState) 179 public void state(string newState)
165 { 180 {
166 m_ScriptEngine.SetState(m_itemID, newState); 181 m_ScriptEngine.SetState(m_itemID, newState);
@@ -170,6 +185,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
170 /// Reset the named script. The script must be present 185 /// Reset the named script. The script must be present
171 /// in the same prim. 186 /// in the same prim.
172 /// </summary> 187 /// </summary>
188 [DebuggerNonUserCode]
173 public void llResetScript() 189 public void llResetScript()
174 { 190 {
175 m_host.AddScriptLPS(1); 191 m_host.AddScriptLPS(1);
@@ -226,9 +242,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
226 } 242 }
227 } 243 }
228 244
245 public List<ScenePresence> GetLinkAvatars(int linkType)
246 {
247 List<ScenePresence> ret = new List<ScenePresence>();
248 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
249 return ret;
250
251 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
252
253 switch (linkType)
254 {
255 case ScriptBaseClass.LINK_SET:
256 return avs;
257
258 case ScriptBaseClass.LINK_ROOT:
259 return ret;
260
261 case ScriptBaseClass.LINK_ALL_OTHERS:
262 return avs;
263
264 case ScriptBaseClass.LINK_ALL_CHILDREN:
265 return avs;
266
267 case ScriptBaseClass.LINK_THIS:
268 return ret;
269
270 default:
271 if (linkType < 0)
272 return ret;
273
274 int partCount = m_host.ParentGroup.GetPartCount();
275
276 if (linkType <= partCount)
277 {
278 return ret;
279 }
280 else
281 {
282 linkType = linkType - partCount;
283 if (linkType > avs.Count)
284 {
285 return ret;
286 }
287 else
288 {
289 ret.Add(avs[linkType-1]);
290 return ret;
291 }
292 }
293 }
294 }
295
229 public List<SceneObjectPart> GetLinkParts(int linkType) 296 public List<SceneObjectPart> GetLinkParts(int linkType)
230 { 297 {
231 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 298 List<SceneObjectPart> ret = new List<SceneObjectPart>();
299 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
300 return ret;
232 ret.Add(m_host); 301 ret.Add(m_host);
233 302
234 switch (linkType) 303 switch (linkType)
@@ -275,40 +344,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
275 protected UUID InventorySelf() 344 protected UUID InventorySelf()
276 { 345 {
277 UUID invItemID = new UUID(); 346 UUID invItemID = new UUID();
278 347 bool unlock = false;
279 lock (m_host.TaskInventory) 348 if (!m_host.TaskInventory.IsReadLockedByMe())
280 { 349 {
281 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 350 m_host.TaskInventory.LockItemsForRead(true);
351 unlock = true;
352 }
353 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
354 {
355 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
282 { 356 {
283 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) 357 invItemID = inv.Key;
284 { 358 break;
285 invItemID = inv.Key;
286 break;
287 }
288 } 359 }
289 } 360 }
290 361 if (unlock)
362 {
363 m_host.TaskInventory.LockItemsForRead(false);
364 }
291 return invItemID; 365 return invItemID;
292 } 366 }
293 367
294 protected UUID InventoryKey(string name, int type) 368 protected UUID InventoryKey(string name, int type)
295 { 369 {
296 m_host.AddScriptLPS(1); 370 m_host.AddScriptLPS(1);
297 371 m_host.TaskInventory.LockItemsForRead(true);
298 lock (m_host.TaskInventory) 372
373 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
299 { 374 {
300 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 375 if (inv.Value.Name == name)
301 { 376 {
302 if (inv.Value.Name == name) 377 m_host.TaskInventory.LockItemsForRead(false);
378
379 if (inv.Value.Type != type)
303 { 380 {
304 if (inv.Value.Type != type) 381 return UUID.Zero;
305 return UUID.Zero;
306
307 return inv.Value.AssetID;
308 } 382 }
383
384 return inv.Value.AssetID;
309 } 385 }
310 } 386 }
311 387
388 m_host.TaskInventory.LockItemsForRead(false);
312 return UUID.Zero; 389 return UUID.Zero;
313 } 390 }
314 391
@@ -316,17 +393,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
316 { 393 {
317 m_host.AddScriptLPS(1); 394 m_host.AddScriptLPS(1);
318 395
319 lock (m_host.TaskInventory) 396
397 m_host.TaskInventory.LockItemsForRead(true);
398
399 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
320 { 400 {
321 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 401 if (inv.Value.Name == name)
322 { 402 {
323 if (inv.Value.Name == name) 403 m_host.TaskInventory.LockItemsForRead(false);
324 { 404 return inv.Value.AssetID;
325 return inv.Value.AssetID;
326 }
327 } 405 }
328 } 406 }
329 407
408 m_host.TaskInventory.LockItemsForRead(false);
409
410
330 return UUID.Zero; 411 return UUID.Zero;
331 } 412 }
332 413
@@ -468,31 +549,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
468 549
469 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 550 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
470 551
471 /// <summary> 552 // Utility function for llRot2Euler
472 /// Convert an LSL rotation to a Euler vector. 553
473 /// </summary> 554 // normalize an angle between -PI and PI (-180 to +180 degrees)
474 /// <remarks> 555 protected double NormalizeAngle(double angle)
475 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
476 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
477 /// </remarks>
478 /// <param name="r"></param>
479 /// <returns></returns>
480 public LSL_Vector llRot2Euler(LSL_Rotation r)
481 { 556 {
482 m_host.AddScriptLPS(1); 557 if (angle > -Math.PI && angle < Math.PI)
558 return angle;
483 559
484 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 560 int numPis = (int)(Math.PI / angle);
485 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 561 double remainder = angle - Math.PI * numPis;
486 if (m == 0.0) return new LSL_Vector(); 562 if (numPis % 2 == 1)
487 double x = Math.Atan2(-v.y, v.z); 563 return Math.PI - angle;
488 double sin = v.x / m; 564 return remainder;
489 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. 565 }
490 double y = Math.Asin(sin); 566
491 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation 567 public LSL_Vector llRot2Euler(LSL_Rotation q1)
492 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))); 568 {
493 double z = Math.Atan2(v.y, v.x); 569 m_host.AddScriptLPS(1);
570 LSL_Vector eul = new LSL_Vector();
494 571
495 return new LSL_Vector(x, y, z); 572 double sqw = q1.s*q1.s;
573 double sqx = q1.x*q1.x;
574 double sqy = q1.z*q1.z;
575 double sqz = q1.y*q1.y;
576 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
577 double test = q1.x*q1.z + q1.y*q1.s;
578 if (test > 0.4999*unit) { // singularity at north pole
579 eul.z = 2 * Math.Atan2(q1.x,q1.s);
580 eul.y = Math.PI/2;
581 eul.x = 0;
582 return eul;
583 }
584 if (test < -0.4999*unit) { // singularity at south pole
585 eul.z = -2 * Math.Atan2(q1.x,q1.s);
586 eul.y = -Math.PI/2;
587 eul.x = 0;
588 return eul;
589 }
590 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
591 eul.y = Math.Asin(2*test/unit);
592 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
593 return eul;
496 } 594 }
497 595
498 /* From wiki: 596 /* From wiki:
@@ -694,77 +792,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
694 { 792 {
695 //A and B should both be normalized 793 //A and B should both be normalized
696 m_host.AddScriptLPS(1); 794 m_host.AddScriptLPS(1);
697 LSL_Rotation rotBetween; 795 /* This method is more accurate than the SL one, and thus causes problems
698 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 796 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
699 // continue calculation. 797
700 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 798 double dotProduct = LSL_Vector.Dot(a, b);
799 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
800 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
801 double angle = Math.Acos(dotProduct / magProduct);
802 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
803 double s = Math.Sin(angle / 2);
804
805 double x = axis.x * s;
806 double y = axis.y * s;
807 double z = axis.z * s;
808 double w = Math.Cos(angle / 2);
809
810 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
811 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
812
813 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
814 */
815
816 // This method mimics the 180 errors found in SL
817 // See www.euclideanspace.com... angleBetween
818 LSL_Vector vec_a = a;
819 LSL_Vector vec_b = b;
820
821 // Eliminate zero length
822 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
823 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
824 if (vec_a_mag < 0.00001 ||
825 vec_b_mag < 0.00001)
701 { 826 {
702 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 827 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
703 } 828 }
704 else 829
830 // Normalize
831 vec_a = llVecNorm(vec_a);
832 vec_b = llVecNorm(vec_b);
833
834 // Calculate axis and rotation angle
835 LSL_Vector axis = vec_a % vec_b;
836 LSL_Float cos_theta = vec_a * vec_b;
837
838 // Check if parallel
839 if (cos_theta > 0.99999)
705 { 840 {
706 a = LSL_Vector.Norm(a); 841 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
707 b = LSL_Vector.Norm(b); 842 }
708 double dotProduct = LSL_Vector.Dot(a, b); 843
709 // There are two degenerate cases possible. These are for vectors 180 or 844 // Check if anti-parallel
710 // 0 degrees apart. These have to be detected and handled individually. 845 else if (cos_theta < -0.99999)
711 // 846 {
712 // Check for vectors 180 degrees apart. 847 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
713 // A dot product of -1 would mean the angle between vectors is 180 degrees. 848 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
714 if (dotProduct < -0.9999999f) 849 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
715 { 850 }
716 // First assume X axis is orthogonal to the vectors. 851 else // other rotation
717 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 852 {
718 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 853 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
719 // Check for near zero vector. A very small non-zero number here will create 854 axis = llVecNorm(axis);
720 // a rotation in an undesired direction. 855 double x, y, z, s, t;
721 if (LSL_Vector.Mag(orthoVector) > 0.0001) 856 s = Math.Cos(theta);
722 { 857 t = Math.Sin(theta);
723 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 858 x = axis.x * t;
724 } 859 y = axis.y * t;
725 // If the magnitude of the vector was near zero, then assume the X axis is not 860 z = axis.z * t;
726 // orthogonal and use the Z axis instead. 861 return new LSL_Rotation(x,y,z,s);
727 else
728 {
729 // Set 180 z rotation.
730 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
731 }
732 }
733 // Check for parallel vectors.
734 // A dot product of 1 would mean the angle between vectors is 0 degrees.
735 else if (dotProduct > 0.9999999f)
736 {
737 // Set zero rotation.
738 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
739 }
740 else
741 {
742 // All special checks have been performed so get the axis of rotation.
743 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
744 // Quarternion s value is the length of the unit vector + dot product.
745 double qs = 1.0 + dotProduct;
746 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
747 // Normalize the rotation.
748 double mag = LSL_Rotation.Mag(rotBetween);
749 // We shouldn't have to worry about a divide by zero here. The qs value will be
750 // non-zero because we already know if we're here, then the dotProduct is not -1 so
751 // qs will not be zero. Also, we've already handled the input vectors being zero so the
752 // crossProduct vector should also not be zero.
753 rotBetween.x = rotBetween.x / mag;
754 rotBetween.y = rotBetween.y / mag;
755 rotBetween.z = rotBetween.z / mag;
756 rotBetween.s = rotBetween.s / mag;
757 // Check for undefined values and set zero rotation if any found. This code might not actually be required
758 // any longer since zero vectors are checked for at the top.
759 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
760 {
761 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
762 }
763 }
764 } 862 }
765 return rotBetween;
766 } 863 }
767 864
768 public void llWhisper(int channelID, string text) 865 public void llWhisper(int channelID, string text)
769 { 866 {
770 m_host.AddScriptLPS(1); 867 m_host.AddScriptLPS(1);
@@ -784,6 +881,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
784 { 881 {
785 m_host.AddScriptLPS(1); 882 m_host.AddScriptLPS(1);
786 883
884 if (channelID == 0)
885 m_SayShoutCount++;
886
887 if (m_SayShoutCount >= 11)
888 ScriptSleep(2000);
889
787 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 890 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
788 { 891 {
789 Console.WriteLine(text); 892 Console.WriteLine(text);
@@ -806,6 +909,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
806 { 909 {
807 m_host.AddScriptLPS(1); 910 m_host.AddScriptLPS(1);
808 911
912 if (channelID == 0)
913 m_SayShoutCount++;
914
915 if (m_SayShoutCount >= 11)
916 ScriptSleep(2000);
917
809 if (text.Length > 1023) 918 if (text.Length > 1023)
810 text = text.Substring(0, 1023); 919 text = text.Substring(0, 1023);
811 920
@@ -1106,10 +1215,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1106 return detectedParams.TouchUV; 1215 return detectedParams.TouchUV;
1107 } 1216 }
1108 1217
1218 [DebuggerNonUserCode]
1109 public virtual void llDie() 1219 public virtual void llDie()
1110 { 1220 {
1111 m_host.AddScriptLPS(1); 1221 m_host.AddScriptLPS(1);
1112 throw new SelfDeleteException(); 1222 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1113 } 1223 }
1114 1224
1115 public LSL_Float llGround(LSL_Vector offset) 1225 public LSL_Float llGround(LSL_Vector offset)
@@ -1182,6 +1292,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1182 1292
1183 public void llSetStatus(int status, int value) 1293 public void llSetStatus(int status, int value)
1184 { 1294 {
1295 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1296 return;
1185 m_host.AddScriptLPS(1); 1297 m_host.AddScriptLPS(1);
1186 1298
1187 int statusrotationaxis = 0; 1299 int statusrotationaxis = 0;
@@ -1411,6 +1523,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1411 { 1523 {
1412 m_host.AddScriptLPS(1); 1524 m_host.AddScriptLPS(1);
1413 1525
1526 SetColor(m_host, color, face);
1527 }
1528
1529 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1530 {
1531 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1532 return;
1533
1534 Primitive.TextureEntry tex = part.Shape.Textures;
1535 Color4 texcolor;
1536 if (face >= 0 && face < GetNumberOfSides(part))
1537 {
1538 texcolor = tex.CreateFace((uint)face).RGBA;
1539 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1540 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1541 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1542 tex.FaceTextures[face].RGBA = texcolor;
1543 part.UpdateTextureEntry(tex.GetBytes());
1544 return;
1545 }
1546 else if (face == ScriptBaseClass.ALL_SIDES)
1547 {
1548 for (uint i = 0; i < GetNumberOfSides(part); i++)
1549 {
1550 if (tex.FaceTextures[i] != null)
1551 {
1552 texcolor = tex.FaceTextures[i].RGBA;
1553 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1554 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1555 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1556 tex.FaceTextures[i].RGBA = texcolor;
1557 }
1558 texcolor = tex.DefaultTexture.RGBA;
1559 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1560 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1561 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1562 tex.DefaultTexture.RGBA = texcolor;
1563 }
1564 part.UpdateTextureEntry(tex.GetBytes());
1565 return;
1566 }
1567
1414 if (face == ScriptBaseClass.ALL_SIDES) 1568 if (face == ScriptBaseClass.ALL_SIDES)
1415 face = SceneObjectPart.ALL_SIDES; 1569 face = SceneObjectPart.ALL_SIDES;
1416 1570
@@ -1419,6 +1573,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1419 1573
1420 public void SetTexGen(SceneObjectPart part, int face,int style) 1574 public void SetTexGen(SceneObjectPart part, int face,int style)
1421 { 1575 {
1576 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1577 return;
1578
1422 Primitive.TextureEntry tex = part.Shape.Textures; 1579 Primitive.TextureEntry tex = part.Shape.Textures;
1423 MappingType textype; 1580 MappingType textype;
1424 textype = MappingType.Default; 1581 textype = MappingType.Default;
@@ -1449,6 +1606,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1449 1606
1450 public void SetGlow(SceneObjectPart part, int face, float glow) 1607 public void SetGlow(SceneObjectPart part, int face, float glow)
1451 { 1608 {
1609 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1610 return;
1611
1452 Primitive.TextureEntry tex = part.Shape.Textures; 1612 Primitive.TextureEntry tex = part.Shape.Textures;
1453 if (face >= 0 && face < GetNumberOfSides(part)) 1613 if (face >= 0 && face < GetNumberOfSides(part))
1454 { 1614 {
@@ -1474,6 +1634,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1474 1634
1475 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1635 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1476 { 1636 {
1637 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1638 return;
1477 1639
1478 Shininess sval = new Shininess(); 1640 Shininess sval = new Shininess();
1479 1641
@@ -1524,6 +1686,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1524 1686
1525 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1687 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1526 { 1688 {
1689 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1690 return;
1691
1527 Primitive.TextureEntry tex = part.Shape.Textures; 1692 Primitive.TextureEntry tex = part.Shape.Textures;
1528 if (face >= 0 && face < GetNumberOfSides(part)) 1693 if (face >= 0 && face < GetNumberOfSides(part))
1529 { 1694 {
@@ -1584,13 +1749,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1584 m_host.AddScriptLPS(1); 1749 m_host.AddScriptLPS(1);
1585 1750
1586 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1751 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1587 1752 if (parts.Count > 0)
1588 foreach (SceneObjectPart part in parts) 1753 {
1589 SetAlpha(part, alpha, face); 1754 try
1755 {
1756 parts[0].ParentGroup.areUpdatesSuspended = true;
1757 foreach (SceneObjectPart part in parts)
1758 SetAlpha(part, alpha, face);
1759 }
1760 finally
1761 {
1762 parts[0].ParentGroup.areUpdatesSuspended = false;
1763 }
1764 }
1590 } 1765 }
1591 1766
1592 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1767 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1593 { 1768 {
1769 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1770 return;
1771
1594 Primitive.TextureEntry tex = part.Shape.Textures; 1772 Primitive.TextureEntry tex = part.Shape.Textures;
1595 Color4 texcolor; 1773 Color4 texcolor;
1596 if (face >= 0 && face < GetNumberOfSides(part)) 1774 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1643,7 +1821,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1643 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1821 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1644 float wind, float tension, LSL_Vector Force) 1822 float wind, float tension, LSL_Vector Force)
1645 { 1823 {
1646 if (part == null) 1824 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1647 return; 1825 return;
1648 1826
1649 if (flexi) 1827 if (flexi)
@@ -1677,7 +1855,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1677 /// <param name="falloff"></param> 1855 /// <param name="falloff"></param>
1678 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1856 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1679 { 1857 {
1680 if (part == null) 1858 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1681 return; 1859 return;
1682 1860
1683 if (light) 1861 if (light)
@@ -1754,15 +1932,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1754 m_host.AddScriptLPS(1); 1932 m_host.AddScriptLPS(1);
1755 1933
1756 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1934 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1757 1935 if (parts.Count > 0)
1758 foreach (SceneObjectPart part in parts) 1936 {
1759 SetTexture(part, texture, face); 1937 try
1760 1938 {
1939 parts[0].ParentGroup.areUpdatesSuspended = true;
1940 foreach (SceneObjectPart part in parts)
1941 SetTexture(part, texture, face);
1942 }
1943 finally
1944 {
1945 parts[0].ParentGroup.areUpdatesSuspended = false;
1946 }
1947 }
1761 ScriptSleep(200); 1948 ScriptSleep(200);
1762 } 1949 }
1763 1950
1764 protected void SetTexture(SceneObjectPart part, string texture, int face) 1951 protected void SetTexture(SceneObjectPart part, string texture, int face)
1765 { 1952 {
1953 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1954 return;
1955
1766 UUID textureID = new UUID(); 1956 UUID textureID = new UUID();
1767 1957
1768 textureID = InventoryKey(texture, (int)AssetType.Texture); 1958 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1807,6 +1997,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1807 1997
1808 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 1998 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1809 { 1999 {
2000 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2001 return;
2002
1810 Primitive.TextureEntry tex = part.Shape.Textures; 2003 Primitive.TextureEntry tex = part.Shape.Textures;
1811 if (face >= 0 && face < GetNumberOfSides(part)) 2004 if (face >= 0 && face < GetNumberOfSides(part))
1812 { 2005 {
@@ -1843,6 +2036,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1843 2036
1844 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2037 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1845 { 2038 {
2039 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2040 return;
2041
1846 Primitive.TextureEntry tex = part.Shape.Textures; 2042 Primitive.TextureEntry tex = part.Shape.Textures;
1847 if (face >= 0 && face < GetNumberOfSides(part)) 2043 if (face >= 0 && face < GetNumberOfSides(part))
1848 { 2044 {
@@ -1879,6 +2075,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1879 2075
1880 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2076 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1881 { 2077 {
2078 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2079 return;
2080
1882 Primitive.TextureEntry tex = part.Shape.Textures; 2081 Primitive.TextureEntry tex = part.Shape.Textures;
1883 if (face >= 0 && face < GetNumberOfSides(part)) 2082 if (face >= 0 && face < GetNumberOfSides(part))
1884 { 2083 {
@@ -1985,24 +2184,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1985 2184
1986 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2185 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1987 { 2186 {
1988 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2187 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1989 LSL_Vector currentPos = GetPartLocalPos(part); 2188 return;
1990 2189
1991 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); 2190 LSL_Vector currentPos = GetPartLocalPos(part);
1992 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); 2191 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
1993 2192
1994 if (part.ParentGroup.RootPart == part) 2193 if (part.ParentGroup.RootPart == part)
1995 { 2194 {
1996 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
1997 targetPos.z = ground;
1998 SceneObjectGroup parent = part.ParentGroup; 2195 SceneObjectGroup parent = part.ParentGroup;
1999 LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); 2196 parent.UpdateGroupPosition(new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z));
2000 parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z));
2001 } 2197 }
2002 else 2198 else
2003 { 2199 {
2004 LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); 2200 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
2005 part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z);
2006 SceneObjectGroup parent = part.ParentGroup; 2201 SceneObjectGroup parent = part.ParentGroup;
2007 parent.HasGroupChanged = true; 2202 parent.HasGroupChanged = true;
2008 parent.ScheduleGroupForTerseUpdate(); 2203 parent.ScheduleGroupForTerseUpdate();
@@ -2053,9 +2248,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2053 m_host.AddScriptLPS(1); 2248 m_host.AddScriptLPS(1);
2054 2249
2055 // try to let this work as in SL... 2250 // try to let this work as in SL...
2056 if (m_host.ParentID == 0) 2251 if (m_host.LinkNum < 2)
2057 { 2252 {
2058 // special case: If we are root, rotate complete SOG to new rotation 2253 // Special case: If we are root, rotate complete SOG to new
2254 // rotation.
2255 // We are root if the link number is 0 (single prim) or 1
2256 // (root prim). ParentID may be nonzero in attachments and
2257 // using it would cause attachments and HUDs to rotate
2258 // to the wrong positions.
2059 SetRot(m_host, Rot2Quaternion(rot)); 2259 SetRot(m_host, Rot2Quaternion(rot));
2060 } 2260 }
2061 else 2261 else
@@ -2080,6 +2280,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2080 2280
2081 protected void SetRot(SceneObjectPart part, Quaternion rot) 2281 protected void SetRot(SceneObjectPart part, Quaternion rot)
2082 { 2282 {
2283 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2284 return;
2285
2083 part.UpdateRotation(rot); 2286 part.UpdateRotation(rot);
2084 // Update rotation does not move the object in the physics scene if it's a linkset. 2287 // Update rotation does not move the object in the physics scene if it's a linkset.
2085 2288
@@ -2703,12 +2906,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2703 2906
2704 m_host.AddScriptLPS(1); 2907 m_host.AddScriptLPS(1);
2705 2908
2909 m_host.TaskInventory.LockItemsForRead(true);
2706 TaskInventoryItem item = m_host.TaskInventory[invItemID]; 2910 TaskInventoryItem item = m_host.TaskInventory[invItemID];
2707 2911 m_host.TaskInventory.LockItemsForRead(false);
2708 lock (m_host.TaskInventory)
2709 {
2710 item = m_host.TaskInventory[invItemID];
2711 }
2712 2912
2713 if (item.PermsGranter == UUID.Zero) 2913 if (item.PermsGranter == UUID.Zero)
2714 return 0; 2914 return 0;
@@ -2783,6 +2983,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2783 if (dist > m_ScriptDistanceFactor * 10.0f) 2983 if (dist > m_ScriptDistanceFactor * 10.0f)
2784 return; 2984 return;
2785 2985
2986 //Clone is thread-safe
2786 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 2987 TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
2787 2988
2788 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory) 2989 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
@@ -2843,6 +3044,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2843 3044
2844 public void llLookAt(LSL_Vector target, double strength, double damping) 3045 public void llLookAt(LSL_Vector target, double strength, double damping)
2845 { 3046 {
3047 /*
2846 m_host.AddScriptLPS(1); 3048 m_host.AddScriptLPS(1);
2847 // Determine where we are looking from 3049 // Determine where we are looking from
2848 LSL_Vector from = llGetPos(); 3050 LSL_Vector from = llGetPos();
@@ -2862,10 +3064,54 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2862 // the angles of rotation in radians into rotation value 3064 // the angles of rotation in radians into rotation value
2863 3065
2864 LSL_Types.Quaternion rot = llEuler2Rot(angle); 3066 LSL_Types.Quaternion rot = llEuler2Rot(angle);
2865 Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); 3067
2866 m_host.startLookAt(rotation, (float)damping, (float)strength); 3068 // This would only work if your physics system contains an APID controller:
3069 // Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
3070 // m_host.startLookAt(rotation, (float)damping, (float)strength);
3071
2867 // Orient the object to the angle calculated 3072 // Orient the object to the angle calculated
2868 //llSetRot(rot); 3073 llSetRot(rot);
3074 */
3075
3076 //The above code, while nice, doesn't replicate the behaviour of SL and tends to "roll" the object.
3077 //There's probably a smarter way of doing this, my rotation math-fu is weak.
3078 // http://bugs.meta7.com/view.php?id=28
3079 // - Tom
3080
3081 /* And the following does not do the job either. It has to be performed inside the ODE glue-code. -.- .._.
3082 LSL_Rotation newrot = llGetRot() * llRotBetween(new LSL_Vector(1.0d, 0.0d, 0.0d) * llGetRot(), new LSL_Vector(0.0d, 0.0d, -1.0d));
3083 llSetRot(newrot * llRotBetween(new LSL_Vector(0.0d,0.0d,1.0d) * newrot, target - llGetPos()));
3084 */
3085 if (m_host.PhysActor != null && !m_host.PhysActor.IsPhysical)
3086 {
3087 // Part is non-phys, convert this to a llSetRot()
3088 Vector3 tgt = new Vector3((float)target.x, (float)target.y, (float)target.z);
3089 Vector3 dir = tgt - m_host.GroupPosition;
3090 dir.Normalize();
3091 float tzrot = (float)Math.Atan2(dir.Y, dir.X);
3092 float txy = (float)Math.Sqrt((dir.X * dir.X) + (dir.Y * dir.Y));
3093 float terot = (float)Math.Atan2(-dir.Z, txy);
3094 LSL_Vector az = new LSL_Vector(0.0f, 0.0f, tzrot);
3095 LSL_Vector ae = new LSL_Vector(0.0f, terot, 0.0f);
3096 LSL_Types.Quaternion spin = llEuler2Rot(az);
3097 LSL_Types.Quaternion rot = llEuler2Rot(ae) * spin;
3098 llSetRot(rot);
3099 }
3100 else
3101 {
3102 // Physical, send the target vector to RotLookAt method inside a 'rotation', the .w -99.9 value indicates it is really a LookAt.
3103 Quaternion q = new Quaternion((float)target.x, (float)target.y, (float)target.z, -99.9f);
3104 m_host.RotLookAt(q, (float)strength, (float)damping);
3105 }
3106
3107 }
3108
3109 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
3110 {
3111 m_host.AddScriptLPS(1);
3112// NotImplemented("llRotLookAt");
3113 m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping);
3114
2869 } 3115 }
2870 3116
2871 public void llStopLookAt() 3117 public void llStopLookAt()
@@ -2914,13 +3160,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2914 { 3160 {
2915 TaskInventoryItem item; 3161 TaskInventoryItem item;
2916 3162
2917 lock (m_host.TaskInventory) 3163 m_host.TaskInventory.LockItemsForRead(true);
3164 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2918 { 3165 {
2919 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3166 m_host.TaskInventory.LockItemsForRead(false);
2920 return; 3167 return;
2921 else 3168 }
2922 item = m_host.TaskInventory[InventorySelf()]; 3169 else
3170 {
3171 item = m_host.TaskInventory[InventorySelf()];
2923 } 3172 }
3173 m_host.TaskInventory.LockItemsForRead(false);
2924 3174
2925 if (item.PermsGranter != UUID.Zero) 3175 if (item.PermsGranter != UUID.Zero)
2926 { 3176 {
@@ -2942,13 +3192,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2942 { 3192 {
2943 TaskInventoryItem item; 3193 TaskInventoryItem item;
2944 3194
3195 m_host.TaskInventory.LockItemsForRead(true);
2945 lock (m_host.TaskInventory) 3196 lock (m_host.TaskInventory)
2946 { 3197 {
3198
2947 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3199 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3200 {
3201 m_host.TaskInventory.LockItemsForRead(false);
2948 return; 3202 return;
3203 }
2949 else 3204 else
3205 {
2950 item = m_host.TaskInventory[InventorySelf()]; 3206 item = m_host.TaskInventory[InventorySelf()];
3207 }
2951 } 3208 }
3209 m_host.TaskInventory.LockItemsForRead(false);
2952 3210
2953 m_host.AddScriptLPS(1); 3211 m_host.AddScriptLPS(1);
2954 3212
@@ -2980,19 +3238,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2980 { 3238 {
2981 m_host.AddScriptLPS(1); 3239 m_host.AddScriptLPS(1);
2982 3240
2983// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
2984// return;
2985
2986 TaskInventoryItem item; 3241 TaskInventoryItem item;
2987 3242
2988 lock (m_host.TaskInventory) 3243 m_host.TaskInventory.LockItemsForRead(true);
3244
3245 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
2989 { 3246 {
2990 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3247 m_host.TaskInventory.LockItemsForRead(false);
2991 return; 3248 return;
2992 else 3249 }
2993 item = m_host.TaskInventory[InventorySelf()]; 3250 else
3251 {
3252 item = m_host.TaskInventory[InventorySelf()];
2994 } 3253 }
2995 3254
3255 m_host.TaskInventory.LockItemsForRead(false);
3256
2996 if (item.PermsGranter != m_host.OwnerID) 3257 if (item.PermsGranter != m_host.OwnerID)
2997 return; 3258 return;
2998 3259
@@ -3017,13 +3278,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3017 3278
3018 TaskInventoryItem item; 3279 TaskInventoryItem item;
3019 3280
3020 lock (m_host.TaskInventory) 3281 m_host.TaskInventory.LockItemsForRead(true);
3282
3283 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3021 { 3284 {
3022 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3285 m_host.TaskInventory.LockItemsForRead(false);
3023 return; 3286 return;
3024 else
3025 item = m_host.TaskInventory[InventorySelf()];
3026 } 3287 }
3288 else
3289 {
3290 item = m_host.TaskInventory[InventorySelf()];
3291 }
3292 m_host.TaskInventory.LockItemsForRead(false);
3293
3027 3294
3028 if (item.PermsGranter != m_host.OwnerID) 3295 if (item.PermsGranter != m_host.OwnerID)
3029 return; 3296 return;
@@ -3070,6 +3337,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3070 3337
3071 public void llInstantMessage(string user, string message) 3338 public void llInstantMessage(string user, string message)
3072 { 3339 {
3340 UUID result;
3341 if (!UUID.TryParse(user, out result))
3342 {
3343 ShoutError("An invalid key was passed to llInstantMessage");
3344 ScriptSleep(2000);
3345 return;
3346 }
3347
3348
3073 m_host.AddScriptLPS(1); 3349 m_host.AddScriptLPS(1);
3074 3350
3075 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3351 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3084,14 +3360,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3084 UUID friendTransactionID = UUID.Random(); 3360 UUID friendTransactionID = UUID.Random();
3085 3361
3086 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3362 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3087 3363
3088 GridInstantMessage msg = new GridInstantMessage(); 3364 GridInstantMessage msg = new GridInstantMessage();
3089 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3365 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3090 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3366 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3091 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3367 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3092// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3368// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3093// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3369// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3094 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3370// DateTime dt = DateTime.UtcNow;
3371//
3372// // Ticks from UtcNow, but make it look like local. Evil, huh?
3373// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3374//
3375// try
3376// {
3377// // Convert that to the PST timezone
3378// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3379// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3380// }
3381// catch
3382// {
3383// // No logging here, as it could be VERY spammy
3384// }
3385//
3386// // And make it look local again to fool the unix time util
3387// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3388
3389 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3390
3095 //if (client != null) 3391 //if (client != null)
3096 //{ 3392 //{
3097 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3393 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3105,12 +3401,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3105 msg.message = message.Substring(0, 1024); 3401 msg.message = message.Substring(0, 1024);
3106 else 3402 else
3107 msg.message = message; 3403 msg.message = message;
3108 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3404 msg.dialog = (byte)19; // MessageFromObject
3109 msg.fromGroup = false;// fromGroup; 3405 msg.fromGroup = false;// fromGroup;
3110 msg.offline = (byte)0; //offline; 3406 msg.offline = (byte)0; //offline;
3111 msg.ParentEstateID = 0; //ParentEstateID; 3407 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3112 msg.Position = new Vector3(m_host.AbsolutePosition); 3408 msg.Position = new Vector3(m_host.AbsolutePosition);
3113 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3409 msg.RegionID = World.RegionInfo.RegionID.Guid;
3114 msg.binaryBucket 3410 msg.binaryBucket
3115 = Util.StringToBytes256( 3411 = Util.StringToBytes256(
3116 "{0}/{1}/{2}/{3}", 3412 "{0}/{1}/{2}/{3}",
@@ -3138,7 +3434,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3138 } 3434 }
3139 3435
3140 emailModule.SendEmail(m_host.UUID, address, subject, message); 3436 emailModule.SendEmail(m_host.UUID, address, subject, message);
3141 ScriptSleep(20000); 3437 ScriptSleep(15000);
3142 } 3438 }
3143 3439
3144 public void llGetNextEmail(string address, string subject) 3440 public void llGetNextEmail(string address, string subject)
@@ -3238,13 +3534,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3238 m_host.AddScriptLPS(1); 3534 m_host.AddScriptLPS(1);
3239 } 3535 }
3240 3536
3241 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
3242 {
3243 m_host.AddScriptLPS(1);
3244 Quaternion rot = new Quaternion((float)target.x, (float)target.y, (float)target.z, (float)target.s);
3245 m_host.RotLookAt(rot, (float)strength, (float)damping);
3246 }
3247
3248 public LSL_Integer llStringLength(string str) 3537 public LSL_Integer llStringLength(string str)
3249 { 3538 {
3250 m_host.AddScriptLPS(1); 3539 m_host.AddScriptLPS(1);
@@ -3268,14 +3557,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3268 3557
3269 TaskInventoryItem item; 3558 TaskInventoryItem item;
3270 3559
3271 lock (m_host.TaskInventory) 3560 m_host.TaskInventory.LockItemsForRead(true);
3561 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3272 { 3562 {
3273 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3563 m_host.TaskInventory.LockItemsForRead(false);
3274 return; 3564 return;
3275 else
3276 item = m_host.TaskInventory[InventorySelf()];
3277 } 3565 }
3278 3566 else
3567 {
3568 item = m_host.TaskInventory[InventorySelf()];
3569 }
3570 m_host.TaskInventory.LockItemsForRead(false);
3279 if (item.PermsGranter == UUID.Zero) 3571 if (item.PermsGranter == UUID.Zero)
3280 return; 3572 return;
3281 3573
@@ -3305,13 +3597,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3305 3597
3306 TaskInventoryItem item; 3598 TaskInventoryItem item;
3307 3599
3308 lock (m_host.TaskInventory) 3600 m_host.TaskInventory.LockItemsForRead(true);
3601 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
3309 { 3602 {
3310 if (!m_host.TaskInventory.ContainsKey(InventorySelf())) 3603 m_host.TaskInventory.LockItemsForRead(false);
3311 return; 3604 return;
3312 else 3605 }
3313 item = m_host.TaskInventory[InventorySelf()]; 3606 else
3607 {
3608 item = m_host.TaskInventory[InventorySelf()];
3314 } 3609 }
3610 m_host.TaskInventory.LockItemsForRead(false);
3611
3315 3612
3316 if (item.PermsGranter == UUID.Zero) 3613 if (item.PermsGranter == UUID.Zero)
3317 return; 3614 return;
@@ -3378,10 +3675,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3378 3675
3379 TaskInventoryItem item; 3676 TaskInventoryItem item;
3380 3677
3381 lock (m_host.TaskInventory) 3678
3679 m_host.TaskInventory.LockItemsForRead(true);
3680 if (!m_host.TaskInventory.ContainsKey(invItemID))
3681 {
3682 m_host.TaskInventory.LockItemsForRead(false);
3683 return;
3684 }
3685 else
3382 { 3686 {
3383 item = m_host.TaskInventory[invItemID]; 3687 item = m_host.TaskInventory[invItemID];
3384 } 3688 }
3689 m_host.TaskInventory.LockItemsForRead(false);
3385 3690
3386 if (agentID == UUID.Zero || perm == 0) // Releasing permissions 3691 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
3387 { 3692 {
@@ -3409,15 +3714,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3409 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3714 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3410 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3715 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3411 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3716 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3717 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3412 ScriptBaseClass.PERMISSION_ATTACH; 3718 ScriptBaseClass.PERMISSION_ATTACH;
3413 3719
3414 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3720 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3415 { 3721 {
3416 lock (m_host.TaskInventory) 3722 m_host.TaskInventory.LockItemsForWrite(true);
3417 { 3723 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3418 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3724 m_host.TaskInventory[invItemID].PermsMask = perm;
3419 m_host.TaskInventory[invItemID].PermsMask = perm; 3725 m_host.TaskInventory.LockItemsForWrite(false);
3420 }
3421 3726
3422 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3727 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3423 "run_time_permissions", new Object[] { 3728 "run_time_permissions", new Object[] {
@@ -3427,28 +3732,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3427 return; 3732 return;
3428 } 3733 }
3429 } 3734 }
3430 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3735 else
3431 { 3736 {
3432 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3737 bool sitting = false;
3433 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3738 if (m_host.SitTargetAvatar == agentID)
3434 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3739 {
3435 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3740 sitting = true;
3436 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3741 }
3742 else
3743 {
3744 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3745 {
3746 if (p.SitTargetAvatar == agentID)
3747 sitting = true;
3748 }
3749 }
3437 3750
3438 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3751 if (sitting)
3439 { 3752 {
3440 lock (m_host.TaskInventory) 3753 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3754 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3755 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3756 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3757 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3758
3759 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3441 { 3760 {
3761 m_host.TaskInventory.LockItemsForWrite(true);
3442 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3762 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3443 m_host.TaskInventory[invItemID].PermsMask = perm; 3763 m_host.TaskInventory[invItemID].PermsMask = perm;
3444 } 3764 m_host.TaskInventory.LockItemsForWrite(false);
3445 3765
3446 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3766 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3447 "run_time_permissions", new Object[] { 3767 "run_time_permissions", new Object[] {
3448 new LSL_Integer(perm) }, 3768 new LSL_Integer(perm) },
3449 new DetectParams[0])); 3769 new DetectParams[0]));
3450 3770
3451 return; 3771 return;
3772 }
3452 } 3773 }
3453 } 3774 }
3454 3775
@@ -3462,11 +3783,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3462 3783
3463 if (!m_waitingForScriptAnswer) 3784 if (!m_waitingForScriptAnswer)
3464 { 3785 {
3465 lock (m_host.TaskInventory) 3786 m_host.TaskInventory.LockItemsForWrite(true);
3466 { 3787 m_host.TaskInventory[invItemID].PermsGranter = agentID;
3467 m_host.TaskInventory[invItemID].PermsGranter = agentID; 3788 m_host.TaskInventory[invItemID].PermsMask = 0;
3468 m_host.TaskInventory[invItemID].PermsMask = 0; 3789 m_host.TaskInventory.LockItemsForWrite(false);
3469 }
3470 3790
3471 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3791 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3472 m_waitingForScriptAnswer=true; 3792 m_waitingForScriptAnswer=true;
@@ -3501,10 +3821,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3501 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3821 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3502 llReleaseControls(); 3822 llReleaseControls();
3503 3823
3504 lock (m_host.TaskInventory) 3824
3505 { 3825 m_host.TaskInventory.LockItemsForWrite(true);
3506 m_host.TaskInventory[invItemID].PermsMask = answer; 3826 m_host.TaskInventory[invItemID].PermsMask = answer;
3507 } 3827 m_host.TaskInventory.LockItemsForWrite(false);
3828
3508 3829
3509 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3830 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3510 "run_time_permissions", new Object[] { 3831 "run_time_permissions", new Object[] {
@@ -3516,16 +3837,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3516 { 3837 {
3517 m_host.AddScriptLPS(1); 3838 m_host.AddScriptLPS(1);
3518 3839
3519 lock (m_host.TaskInventory) 3840 m_host.TaskInventory.LockItemsForRead(true);
3841
3842 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3520 { 3843 {
3521 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3844 if (item.Type == 10 && item.ItemID == m_itemID)
3522 { 3845 {
3523 if (item.Type == 10 && item.ItemID == m_itemID) 3846 m_host.TaskInventory.LockItemsForRead(false);
3524 { 3847 return item.PermsGranter.ToString();
3525 return item.PermsGranter.ToString();
3526 }
3527 } 3848 }
3528 } 3849 }
3850 m_host.TaskInventory.LockItemsForRead(false);
3529 3851
3530 return UUID.Zero.ToString(); 3852 return UUID.Zero.ToString();
3531 } 3853 }
@@ -3534,19 +3856,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3534 { 3856 {
3535 m_host.AddScriptLPS(1); 3857 m_host.AddScriptLPS(1);
3536 3858
3537 lock (m_host.TaskInventory) 3859 m_host.TaskInventory.LockItemsForRead(true);
3860
3861 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
3538 { 3862 {
3539 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 3863 if (item.Type == 10 && item.ItemID == m_itemID)
3540 { 3864 {
3541 if (item.Type == 10 && item.ItemID == m_itemID) 3865 int perms = item.PermsMask;
3542 { 3866 if (m_automaticLinkPermission)
3543 int perms = item.PermsMask; 3867 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
3544 if (m_automaticLinkPermission) 3868 m_host.TaskInventory.LockItemsForRead(false);
3545 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 3869 return perms;
3546 return perms;
3547 }
3548 } 3870 }
3549 } 3871 }
3872 m_host.TaskInventory.LockItemsForRead(false);
3550 3873
3551 return 0; 3874 return 0;
3552 } 3875 }
@@ -3568,9 +3891,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3568 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3891 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3569 { 3892 {
3570 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3893 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3571 3894 if (parts.Count > 0)
3572 foreach (SceneObjectPart part in parts) 3895 {
3573 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3896 try
3897 {
3898 parts[0].ParentGroup.areUpdatesSuspended = true;
3899 foreach (SceneObjectPart part in parts)
3900 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3901 }
3902 finally
3903 {
3904 parts[0].ParentGroup.areUpdatesSuspended = false;
3905 }
3906 }
3574 } 3907 }
3575 3908
3576 public void llCreateLink(string target, int parent) 3909 public void llCreateLink(string target, int parent)
@@ -3583,11 +3916,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3583 return; 3916 return;
3584 3917
3585 TaskInventoryItem item; 3918 TaskInventoryItem item;
3586 lock (m_host.TaskInventory) 3919 m_host.TaskInventory.LockItemsForRead(true);
3587 { 3920 item = m_host.TaskInventory[invItemID];
3588 item = m_host.TaskInventory[invItemID]; 3921 m_host.TaskInventory.LockItemsForRead(false);
3589 } 3922
3590
3591 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3923 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3592 && !m_automaticLinkPermission) 3924 && !m_automaticLinkPermission)
3593 { 3925 {
@@ -3604,11 +3936,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3604 3936
3605 if (targetPart.ParentGroup.AttachmentPoint != 0) 3937 if (targetPart.ParentGroup.AttachmentPoint != 0)
3606 return; // Fail silently if attached 3938 return; // Fail silently if attached
3939
3940 if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID)
3941 return;
3942
3607 SceneObjectGroup parentPrim = null, childPrim = null; 3943 SceneObjectGroup parentPrim = null, childPrim = null;
3608 3944
3609 if (targetPart != null) 3945 if (targetPart != null)
3610 { 3946 {
3611 if (parent != 0) { 3947 if (parent != 0)
3948 {
3612 parentPrim = m_host.ParentGroup; 3949 parentPrim = m_host.ParentGroup;
3613 childPrim = targetPart.ParentGroup; 3950 childPrim = targetPart.ParentGroup;
3614 } 3951 }
@@ -3639,16 +3976,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3639 m_host.AddScriptLPS(1); 3976 m_host.AddScriptLPS(1);
3640 UUID invItemID = InventorySelf(); 3977 UUID invItemID = InventorySelf();
3641 3978
3642 lock (m_host.TaskInventory) 3979 m_host.TaskInventory.LockItemsForRead(true);
3643 {
3644 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3980 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3645 && !m_automaticLinkPermission) 3981 && !m_automaticLinkPermission)
3646 { 3982 {
3647 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 3983 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
3984 m_host.TaskInventory.LockItemsForRead(false);
3648 return; 3985 return;
3649 } 3986 }
3650 } 3987 m_host.TaskInventory.LockItemsForRead(false);
3651 3988
3652 if (linknum < ScriptBaseClass.LINK_THIS) 3989 if (linknum < ScriptBaseClass.LINK_THIS)
3653 return; 3990 return;
3654 3991
@@ -3687,10 +4024,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3687 // Restructuring Multiple Prims. 4024 // Restructuring Multiple Prims.
3688 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4025 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3689 parts.Remove(parentPrim.RootPart); 4026 parts.Remove(parentPrim.RootPart);
3690 foreach (SceneObjectPart part in parts) 4027 if (parts.Count > 0)
3691 { 4028 {
3692 parentPrim.DelinkFromGroup(part.LocalId, true); 4029 try
4030 {
4031 parts[0].ParentGroup.areUpdatesSuspended = true;
4032 foreach (SceneObjectPart part in parts)
4033 {
4034 parentPrim.DelinkFromGroup(part.LocalId, true);
4035 }
4036 }
4037 finally
4038 {
4039 parts[0].ParentGroup.areUpdatesSuspended = false;
4040 }
3693 } 4041 }
4042
3694 parentPrim.HasGroupChanged = true; 4043 parentPrim.HasGroupChanged = true;
3695 parentPrim.ScheduleGroupForFullUpdate(); 4044 parentPrim.ScheduleGroupForFullUpdate();
3696 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4045 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3699,12 +4048,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3699 { 4048 {
3700 SceneObjectPart newRoot = parts[0]; 4049 SceneObjectPart newRoot = parts[0];
3701 parts.Remove(newRoot); 4050 parts.Remove(newRoot);
3702 foreach (SceneObjectPart part in parts) 4051
4052 try
3703 { 4053 {
3704 // Required for linking 4054 parts[0].ParentGroup.areUpdatesSuspended = true;
3705 part.ClearUpdateSchedule(); 4055 foreach (SceneObjectPart part in parts)
3706 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4056 {
4057 part.ClearUpdateSchedule();
4058 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4059 }
3707 } 4060 }
4061 finally
4062 {
4063 parts[0].ParentGroup.areUpdatesSuspended = false;
4064 }
4065
4066
3708 newRoot.ParentGroup.HasGroupChanged = true; 4067 newRoot.ParentGroup.HasGroupChanged = true;
3709 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4068 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3710 } 4069 }
@@ -3724,6 +4083,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3724 public void llBreakAllLinks() 4083 public void llBreakAllLinks()
3725 { 4084 {
3726 m_host.AddScriptLPS(1); 4085 m_host.AddScriptLPS(1);
4086
4087 UUID invItemID = InventorySelf();
4088
4089 TaskInventoryItem item;
4090 m_host.TaskInventory.LockItemsForRead(true);
4091 item = m_host.TaskInventory[invItemID];
4092 m_host.TaskInventory.LockItemsForRead(false);
4093
4094 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4095 && !m_automaticLinkPermission)
4096 {
4097 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4098 return;
4099 }
4100
3727 SceneObjectGroup parentPrim = m_host.ParentGroup; 4101 SceneObjectGroup parentPrim = m_host.ParentGroup;
3728 if (parentPrim.AttachmentPoint != 0) 4102 if (parentPrim.AttachmentPoint != 0)
3729 return; // Fail silently if attached 4103 return; // Fail silently if attached
@@ -3743,25 +4117,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3743 public LSL_String llGetLinkKey(int linknum) 4117 public LSL_String llGetLinkKey(int linknum)
3744 { 4118 {
3745 m_host.AddScriptLPS(1); 4119 m_host.AddScriptLPS(1);
3746 List<UUID> keytable = new List<UUID>();
3747 // parse for sitting avatare-uuids
3748 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3749 {
3750 if (presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID))
3751 keytable.Add(presence.UUID);
3752 });
3753
3754 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3755 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3756 {
3757 return keytable[totalprims - linknum].ToString();
3758 }
3759
3760 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3761 {
3762 return m_host.UUID.ToString();
3763 }
3764
3765 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4120 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3766 if (part != null) 4121 if (part != null)
3767 { 4122 {
@@ -3769,6 +4124,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3769 } 4124 }
3770 else 4125 else
3771 { 4126 {
4127 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4128 {
4129 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4130
4131 if (linknum < 0)
4132 return UUID.Zero.ToString();
4133
4134 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4135 if (avatars.Count > linknum)
4136 {
4137 return avatars[linknum].UUID.ToString();
4138 }
4139 }
3772 return UUID.Zero.ToString(); 4140 return UUID.Zero.ToString();
3773 } 4141 }
3774 } 4142 }
@@ -3867,17 +4235,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3867 m_host.AddScriptLPS(1); 4235 m_host.AddScriptLPS(1);
3868 int count = 0; 4236 int count = 0;
3869 4237
3870 lock (m_host.TaskInventory) 4238 m_host.TaskInventory.LockItemsForRead(true);
4239 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3871 { 4240 {
3872 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4241 if (inv.Value.Type == type || type == -1)
3873 { 4242 {
3874 if (inv.Value.Type == type || type == -1) 4243 count = count + 1;
3875 {
3876 count = count + 1;
3877 }
3878 } 4244 }
3879 } 4245 }
3880 4246
4247 m_host.TaskInventory.LockItemsForRead(false);
3881 return count; 4248 return count;
3882 } 4249 }
3883 4250
@@ -3886,16 +4253,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3886 m_host.AddScriptLPS(1); 4253 m_host.AddScriptLPS(1);
3887 ArrayList keys = new ArrayList(); 4254 ArrayList keys = new ArrayList();
3888 4255
3889 lock (m_host.TaskInventory) 4256 m_host.TaskInventory.LockItemsForRead(true);
4257 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3890 { 4258 {
3891 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4259 if (inv.Value.Type == type || type == -1)
3892 { 4260 {
3893 if (inv.Value.Type == type || type == -1) 4261 keys.Add(inv.Value.Name);
3894 {
3895 keys.Add(inv.Value.Name);
3896 }
3897 } 4262 }
3898 } 4263 }
4264 m_host.TaskInventory.LockItemsForRead(false);
3899 4265
3900 if (keys.Count == 0) 4266 if (keys.Count == 0)
3901 { 4267 {
@@ -3932,25 +4298,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3932 } 4298 }
3933 4299
3934 // move the first object found with this inventory name 4300 // move the first object found with this inventory name
3935 lock (m_host.TaskInventory) 4301 m_host.TaskInventory.LockItemsForRead(true);
4302 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3936 { 4303 {
3937 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4304 if (inv.Value.Name == inventory)
3938 { 4305 {
3939 if (inv.Value.Name == inventory) 4306 found = true;
3940 { 4307 objId = inv.Key;
3941 found = true; 4308 assetType = inv.Value.Type;
3942 objId = inv.Key; 4309 objName = inv.Value.Name;
3943 assetType = inv.Value.Type; 4310 break;
3944 objName = inv.Value.Name;
3945 break;
3946 }
3947 } 4311 }
3948 } 4312 }
4313 m_host.TaskInventory.LockItemsForRead(false);
3949 4314
3950 if (!found) 4315 if (!found)
3951 { 4316 {
3952 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4317 llSay(0, String.Format("Could not find object '{0}'", inventory));
3953 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4318 return;
4319// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3954 } 4320 }
3955 4321
3956 // check if destination is an object 4322 // check if destination is an object
@@ -3976,48 +4342,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3976 return; 4342 return;
3977 } 4343 }
3978 } 4344 }
4345
3979 // destination is an avatar 4346 // destination is an avatar
3980 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4347 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3981 4348
3982 if (agentItem == null) 4349 if (agentItem == null)
3983 return; 4350 return;
3984 4351
3985 byte[] bucket = new byte[17]; 4352 byte[] bucket = new byte[1];
3986 bucket[0] = (byte)assetType; 4353 bucket[0] = (byte)assetType;
3987 byte[] objBytes = agentItem.ID.GetBytes(); 4354 //byte[] objBytes = agentItem.ID.GetBytes();
3988 Array.Copy(objBytes, 0, bucket, 1, 16); 4355 //Array.Copy(objBytes, 0, bucket, 1, 16);
3989 4356
3990 GridInstantMessage msg = new GridInstantMessage(World, 4357 GridInstantMessage msg = new GridInstantMessage(World,
3991 m_host.UUID, m_host.Name+", an object owned by "+ 4358 m_host.OwnerID, m_host.Name, destId,
3992 resolveName(m_host.OwnerID)+",", destId,
3993 (byte)InstantMessageDialog.TaskInventoryOffered, 4359 (byte)InstantMessageDialog.TaskInventoryOffered,
3994 false, objName+"\n"+m_host.Name+" is located at "+ 4360 false, objName+". "+m_host.Name+" is located at "+
3995 World.RegionInfo.RegionName+" "+ 4361 World.RegionInfo.RegionName+" "+
3996 m_host.AbsolutePosition.ToString(), 4362 m_host.AbsolutePosition.ToString(),
3997 agentItem.ID, true, m_host.AbsolutePosition, 4363 agentItem.ID, true, m_host.AbsolutePosition,
3998 bucket); 4364 bucket);
3999 if (m_TransferModule != null) 4365
4000 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4366 ScenePresence sp;
4367
4368 if (World.TryGetScenePresence(destId, out sp))
4369 {
4370 sp.ControllingClient.SendInstantMessage(msg);
4371 }
4372 else
4373 {
4374 if (m_TransferModule != null)
4375 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4376 }
4377
4378 //This delay should only occur when giving inventory to avatars.
4001 ScriptSleep(3000); 4379 ScriptSleep(3000);
4002 } 4380 }
4003 } 4381 }
4004 4382
4383 [DebuggerNonUserCode]
4005 public void llRemoveInventory(string name) 4384 public void llRemoveInventory(string name)
4006 { 4385 {
4007 m_host.AddScriptLPS(1); 4386 m_host.AddScriptLPS(1);
4008 4387
4009 lock (m_host.TaskInventory) 4388 List<TaskInventoryItem> inv;
4389 try
4010 { 4390 {
4011 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4391 m_host.TaskInventory.LockItemsForRead(true);
4392 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4393 }
4394 finally
4395 {
4396 m_host.TaskInventory.LockItemsForRead(false);
4397 }
4398 foreach (TaskInventoryItem item in inv)
4399 {
4400 if (item.Name == name)
4012 { 4401 {
4013 if (item.Name == name) 4402 if (item.ItemID == m_itemID)
4014 { 4403 throw new ScriptDeleteException();
4015 if (item.ItemID == m_itemID) 4404 else
4016 throw new ScriptDeleteException(); 4405 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4017 else 4406 return;
4018 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4019 return;
4020 }
4021 } 4407 }
4022 } 4408 }
4023 } 4409 }
@@ -4052,112 +4438,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4052 { 4438 {
4053 m_host.AddScriptLPS(1); 4439 m_host.AddScriptLPS(1);
4054 4440
4055 UUID uuid = (UUID)id; 4441 UUID uuid;
4056 PresenceInfo pinfo = null; 4442 if (UUID.TryParse(id, out uuid))
4057 UserAccount account;
4058
4059 UserInfoCacheEntry ce;
4060 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4061 { 4443 {
4062 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4444 PresenceInfo pinfo = null;
4063 if (account == null) 4445 UserAccount account;
4446
4447 UserInfoCacheEntry ce;
4448 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4064 { 4449 {
4065 m_userInfoCache[uuid] = null; // Cache negative 4450 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4066 return UUID.Zero.ToString(); 4451 if (account == null)
4067 } 4452 {
4453 m_userInfoCache[uuid] = null; // Cache negative
4454 return UUID.Zero.ToString();
4455 }
4068 4456
4069 4457
4070 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4458 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4071 if (pinfos != null && pinfos.Length > 0) 4459 if (pinfos != null && pinfos.Length > 0)
4072 {
4073 foreach (PresenceInfo p in pinfos)
4074 { 4460 {
4075 if (p.RegionID != UUID.Zero) 4461 foreach (PresenceInfo p in pinfos)
4076 { 4462 {
4077 pinfo = p; 4463 if (p.RegionID != UUID.Zero)
4464 {
4465 pinfo = p;
4466 }
4078 } 4467 }
4079 } 4468 }
4080 }
4081 4469
4082 ce = new UserInfoCacheEntry(); 4470 ce = new UserInfoCacheEntry();
4083 ce.time = Util.EnvironmentTickCount(); 4471 ce.time = Util.EnvironmentTickCount();
4084 ce.account = account; 4472 ce.account = account;
4085 ce.pinfo = pinfo; 4473 ce.pinfo = pinfo;
4086 } 4474 m_userInfoCache[uuid] = ce;
4087 else 4475 }
4088 { 4476 else
4089 if (ce == null) 4477 {
4090 return UUID.Zero.ToString(); 4478 if (ce == null)
4479 return UUID.Zero.ToString();
4091 4480
4092 account = ce.account; 4481 account = ce.account;
4093 pinfo = ce.pinfo; 4482 pinfo = ce.pinfo;
4094 } 4483 }
4095 4484
4096 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4485 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4097 {
4098 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4099 if (pinfos != null && pinfos.Length > 0)
4100 { 4486 {
4101 foreach (PresenceInfo p in pinfos) 4487 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4488 if (pinfos != null && pinfos.Length > 0)
4102 { 4489 {
4103 if (p.RegionID != UUID.Zero) 4490 foreach (PresenceInfo p in pinfos)
4104 { 4491 {
4105 pinfo = p; 4492 if (p.RegionID != UUID.Zero)
4493 {
4494 pinfo = p;
4495 }
4106 } 4496 }
4107 } 4497 }
4108 } 4498 else
4109 else 4499 pinfo = null;
4110 pinfo = null;
4111 4500
4112 ce.time = Util.EnvironmentTickCount(); 4501 ce.time = Util.EnvironmentTickCount();
4113 ce.pinfo = pinfo; 4502 ce.pinfo = pinfo;
4114 } 4503 }
4115 4504
4116 string reply = String.Empty; 4505 string reply = String.Empty;
4117 4506
4118 switch (data) 4507 switch (data)
4119 { 4508 {
4120 case 1: // DATA_ONLINE (0|1) 4509 case 1: // DATA_ONLINE (0|1)
4121 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4510 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4122 reply = "1"; 4511 reply = "1";
4123 else 4512 else
4124 reply = "0"; 4513 reply = "0";
4125 break; 4514 break;
4126 case 2: // DATA_NAME (First Last) 4515 case 2: // DATA_NAME (First Last)
4127 reply = account.FirstName + " " + account.LastName; 4516 reply = account.FirstName + " " + account.LastName;
4128 break; 4517 break;
4129 case 3: // DATA_BORN (YYYY-MM-DD) 4518 case 3: // DATA_BORN (YYYY-MM-DD)
4130 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4519 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4131 born = born.AddSeconds(account.Created); 4520 born = born.AddSeconds(account.Created);
4132 reply = born.ToString("yyyy-MM-dd"); 4521 reply = born.ToString("yyyy-MM-dd");
4133 break; 4522 break;
4134 case 4: // DATA_RATING (0,0,0,0,0,0) 4523 case 4: // DATA_RATING (0,0,0,0,0,0)
4135 reply = "0,0,0,0,0,0"; 4524 reply = "0,0,0,0,0,0";
4136 break; 4525 break;
4137 case 8: // DATA_PAYINFO (0|1|2|3) 4526 case 8: // DATA_PAYINFO (0|1|2|3)
4138 reply = "0"; 4527 reply = "0";
4139 break; 4528 break;
4140 default: 4529 default:
4141 return UUID.Zero.ToString(); // Raise no event 4530 return UUID.Zero.ToString(); // Raise no event
4142 } 4531 }
4143 4532
4144 UUID rq = UUID.Random(); 4533 UUID rq = UUID.Random();
4145 4534
4146 UUID tid = AsyncCommands. 4535 UUID tid = AsyncCommands.
4147 DataserverPlugin.RegisterRequest(m_localID, 4536 DataserverPlugin.RegisterRequest(m_localID,
4148 m_itemID, rq.ToString()); 4537 m_itemID, rq.ToString());
4149 4538
4150 AsyncCommands. 4539 AsyncCommands.
4151 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4540 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4152 4541
4153 ScriptSleep(100); 4542 ScriptSleep(100);
4154 return tid.ToString(); 4543 return tid.ToString();
4544 }
4545 else
4546 {
4547 ShoutError("Invalid UUID passed to llRequestAgentData.");
4548 }
4549 return "";
4155 } 4550 }
4156 4551
4157 public LSL_String llRequestInventoryData(string name) 4552 public LSL_String llRequestInventoryData(string name)
4158 { 4553 {
4159 m_host.AddScriptLPS(1); 4554 m_host.AddScriptLPS(1);
4160 4555
4556 //Clone is thread safe
4161 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4557 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4162 4558
4163 foreach (TaskInventoryItem item in itemDictionary.Values) 4559 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4211,6 +4607,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4211 ScenePresence presence = World.GetScenePresence(agentId); 4607 ScenePresence presence = World.GetScenePresence(agentId);
4212 if (presence != null) 4608 if (presence != null)
4213 { 4609 {
4610 // agent must not be a god
4611 if (presence.UserLevel >= 200) return;
4612
4214 // agent must be over the owners land 4613 // agent must be over the owners land
4215 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4614 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4216 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4615 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
@@ -4233,7 +4632,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4233 UUID av = new UUID(); 4632 UUID av = new UUID();
4234 if (!UUID.TryParse(agent,out av)) 4633 if (!UUID.TryParse(agent,out av))
4235 { 4634 {
4236 LSLError("First parameter to llDialog needs to be a key"); 4635 //LSLError("First parameter to llDialog needs to be a key");
4237 return; 4636 return;
4238 } 4637 }
4239 4638
@@ -4270,17 +4669,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4270 UUID soundId = UUID.Zero; 4669 UUID soundId = UUID.Zero;
4271 if (!UUID.TryParse(impact_sound, out soundId)) 4670 if (!UUID.TryParse(impact_sound, out soundId))
4272 { 4671 {
4273 lock (m_host.TaskInventory) 4672 m_host.TaskInventory.LockItemsForRead(true);
4673 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4274 { 4674 {
4275 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4675 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4276 { 4676 {
4277 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4677 soundId = item.AssetID;
4278 { 4678 break;
4279 soundId = item.AssetID;
4280 break;
4281 }
4282 } 4679 }
4283 } 4680 }
4681 m_host.TaskInventory.LockItemsForRead(false);
4284 } 4682 }
4285 m_host.CollisionSound = soundId; 4683 m_host.CollisionSound = soundId;
4286 m_host.CollisionSoundVolume = (float)impact_volume; 4684 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4320,6 +4718,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4320 UUID partItemID; 4718 UUID partItemID;
4321 foreach (SceneObjectPart part in parts) 4719 foreach (SceneObjectPart part in parts)
4322 { 4720 {
4721 //Clone is thread safe
4323 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4722 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4324 4723
4325 foreach (TaskInventoryItem item in itemsDictionary.Values) 4724 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4534,17 +4933,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4534 4933
4535 m_host.AddScriptLPS(1); 4934 m_host.AddScriptLPS(1);
4536 4935
4537 lock (m_host.TaskInventory) 4936 m_host.TaskInventory.LockItemsForRead(true);
4937 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4538 { 4938 {
4539 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4939 if (item.Type == 10 && item.ItemID == m_itemID)
4540 { 4940 {
4541 if (item.Type == 10 && item.ItemID == m_itemID) 4941 result = item.Name!=null?item.Name:String.Empty;
4542 { 4942 break;
4543 result = item.Name != null ? item.Name : String.Empty;
4544 break;
4545 }
4546 } 4943 }
4547 } 4944 }
4945 m_host.TaskInventory.LockItemsForRead(false);
4548 4946
4549 return result; 4947 return result;
4550 } 4948 }
@@ -4717,23 +5115,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4717 { 5115 {
4718 m_host.AddScriptLPS(1); 5116 m_host.AddScriptLPS(1);
4719 5117
4720 lock (m_host.TaskInventory) 5118 m_host.TaskInventory.LockItemsForRead(true);
5119 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4721 { 5120 {
4722 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5121 if (inv.Value.Name == name)
4723 { 5122 {
4724 if (inv.Value.Name == name) 5123 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4725 { 5124 {
4726 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5125 m_host.TaskInventory.LockItemsForRead(false);
4727 { 5126 return inv.Value.AssetID.ToString();
4728 return inv.Value.AssetID.ToString(); 5127 }
4729 } 5128 else
4730 else 5129 {
4731 { 5130 m_host.TaskInventory.LockItemsForRead(false);
4732 return UUID.Zero.ToString(); 5131 return UUID.Zero.ToString();
4733 }
4734 } 5132 }
4735 } 5133 }
4736 } 5134 }
5135 m_host.TaskInventory.LockItemsForRead(false);
4737 5136
4738 return UUID.Zero.ToString(); 5137 return UUID.Zero.ToString();
4739 } 5138 }
@@ -4886,14 +5285,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4886 { 5285 {
4887 m_host.AddScriptLPS(1); 5286 m_host.AddScriptLPS(1);
4888 5287
4889 if (src == null) 5288 return src.Length;
4890 {
4891 return 0;
4892 }
4893 else
4894 {
4895 return src.Length;
4896 }
4897 } 5289 }
4898 5290
4899 public LSL_Integer llList2Integer(LSL_List src, int index) 5291 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4939,7 +5331,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4939 else if (src.Data[index] is LSL_Float) 5331 else if (src.Data[index] is LSL_Float)
4940 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5332 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4941 else if (src.Data[index] is LSL_String) 5333 else if (src.Data[index] is LSL_String)
4942 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5334 {
5335 string str = ((LSL_String) src.Data[index]).m_string;
5336 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5337 if (m != Match.Empty)
5338 {
5339 str = m.Value;
5340 double d = 0.0;
5341 if (!Double.TryParse(str, out d))
5342 return 0.0;
5343
5344 return d;
5345 }
5346 return 0.0;
5347 }
4943 return Convert.ToDouble(src.Data[index]); 5348 return Convert.ToDouble(src.Data[index]);
4944 } 5349 }
4945 catch (FormatException) 5350 catch (FormatException)
@@ -5212,7 +5617,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5212 } 5617 }
5213 } 5618 }
5214 } 5619 }
5215 else { 5620 else
5621 {
5216 object[] array = new object[src.Length]; 5622 object[] array = new object[src.Length];
5217 Array.Copy(src.Data, 0, array, 0, src.Length); 5623 Array.Copy(src.Data, 0, array, 0, src.Length);
5218 result = new LSL_List(array); 5624 result = new LSL_List(array);
@@ -5661,10 +6067,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5661 m_host.AddScriptLPS(1); 6067 m_host.AddScriptLPS(1);
5662 6068
5663 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6069 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5664 6070 if (parts.Count > 0)
5665 foreach (var part in parts)
5666 { 6071 {
5667 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6072 try
6073 {
6074 parts[0].ParentGroup.areUpdatesSuspended = true;
6075 foreach (var part in parts)
6076 {
6077 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6078 }
6079 }
6080 finally
6081 {
6082 parts[0].ParentGroup.areUpdatesSuspended = false;
6083 }
5668 } 6084 }
5669 } 6085 }
5670 6086
@@ -5718,6 +6134,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5718 ScriptSleep(5000); 6134 ScriptSleep(5000);
5719 } 6135 }
5720 6136
6137 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6138 {
6139 return ParseString2List(str, separators, in_spacers, false);
6140 }
6141
5721 public LSL_Integer llOverMyLand(string id) 6142 public LSL_Integer llOverMyLand(string id)
5722 { 6143 {
5723 m_host.AddScriptLPS(1); 6144 m_host.AddScriptLPS(1);
@@ -5782,8 +6203,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5782 UUID agentId = new UUID(); 6203 UUID agentId = new UUID();
5783 if (!UUID.TryParse(agent, out agentId)) 6204 if (!UUID.TryParse(agent, out agentId))
5784 return new LSL_Integer(0); 6205 return new LSL_Integer(0);
6206 if (agentId == m_host.GroupID)
6207 return new LSL_Integer(1);
5785 ScenePresence presence = World.GetScenePresence(agentId); 6208 ScenePresence presence = World.GetScenePresence(agentId);
5786 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6209 if (presence == null || presence.IsChildAgent) // Return false for child agents
5787 return new LSL_Integer(0); 6210 return new LSL_Integer(0);
5788 IClientAPI client = presence.ControllingClient; 6211 IClientAPI client = presence.ControllingClient;
5789 if (m_host.GroupID == client.ActiveGroupId) 6212 if (m_host.GroupID == client.ActiveGroupId)
@@ -5918,7 +6341,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5918 return m_host.ParentGroup.AttachmentPoint; 6341 return m_host.ParentGroup.AttachmentPoint;
5919 } 6342 }
5920 6343
5921 public LSL_Integer llGetFreeMemory() 6344 public virtual LSL_Integer llGetFreeMemory()
5922 { 6345 {
5923 m_host.AddScriptLPS(1); 6346 m_host.AddScriptLPS(1);
5924 // Make scripts designed for LSO happy 6347 // Make scripts designed for LSO happy
@@ -6035,7 +6458,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6035 SetParticleSystem(m_host, rules); 6458 SetParticleSystem(m_host, rules);
6036 } 6459 }
6037 6460
6038 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6461 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6462 {
6039 6463
6040 6464
6041 if (rules.Length == 0) 6465 if (rules.Length == 0)
@@ -6229,14 +6653,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6229 6653
6230 protected UUID GetTaskInventoryItem(string name) 6654 protected UUID GetTaskInventoryItem(string name)
6231 { 6655 {
6232 lock (m_host.TaskInventory) 6656 m_host.TaskInventory.LockItemsForRead(true);
6657 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6233 { 6658 {
6234 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6659 if (inv.Value.Name == name)
6235 { 6660 {
6236 if (inv.Value.Name == name) 6661 m_host.TaskInventory.LockItemsForRead(false);
6237 return inv.Key; 6662 return inv.Key;
6238 } 6663 }
6239 } 6664 }
6665 m_host.TaskInventory.LockItemsForRead(false);
6240 6666
6241 return UUID.Zero; 6667 return UUID.Zero;
6242 } 6668 }
@@ -6274,16 +6700,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6274 if (folderID == UUID.Zero) 6700 if (folderID == UUID.Zero)
6275 return; 6701 return;
6276 6702
6277 byte[] bucket = new byte[17]; 6703 byte[] bucket = new byte[1];
6278 bucket[0] = (byte)AssetType.Folder; 6704 bucket[0] = (byte)AssetType.Folder;
6279 byte[] objBytes = folderID.GetBytes(); 6705 //byte[] objBytes = folderID.GetBytes();
6280 Array.Copy(objBytes, 0, bucket, 1, 16); 6706 //Array.Copy(objBytes, 0, bucket, 1, 16);
6281 6707
6282 GridInstantMessage msg = new GridInstantMessage(World, 6708 GridInstantMessage msg = new GridInstantMessage(World,
6283 m_host.UUID, m_host.Name+", an object owned by "+ 6709 m_host.OwnerID, m_host.Name, destID,
6284 resolveName(m_host.OwnerID)+",", destID, 6710 (byte)InstantMessageDialog.TaskInventoryOffered,
6285 (byte)InstantMessageDialog.InventoryOffered, 6711 false, category+". "+m_host.Name+" is located at "+
6286 false, category+"\n"+m_host.Name+" is located at "+
6287 World.RegionInfo.RegionName+" "+ 6712 World.RegionInfo.RegionName+" "+
6288 m_host.AbsolutePosition.ToString(), 6713 m_host.AbsolutePosition.ToString(),
6289 folderID, true, m_host.AbsolutePosition, 6714 folderID, true, m_host.AbsolutePosition,
@@ -6486,13 +6911,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6486 UUID av = new UUID(); 6911 UUID av = new UUID();
6487 if (!UUID.TryParse(avatar,out av)) 6912 if (!UUID.TryParse(avatar,out av))
6488 { 6913 {
6489 LSLError("First parameter to llDialog needs to be a key"); 6914 //LSLError("First parameter to llDialog needs to be a key");
6490 return; 6915 return;
6491 } 6916 }
6492 if (buttons.Length < 1) 6917 if (buttons.Length < 1)
6493 { 6918 {
6494 LSLError("No less than 1 button can be shown"); 6919 buttons.Add("OK");
6495 return;
6496 } 6920 }
6497 if (buttons.Length > 12) 6921 if (buttons.Length > 12)
6498 { 6922 {
@@ -6509,7 +6933,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6509 } 6933 }
6510 if (buttons.Data[i].ToString().Length > 24) 6934 if (buttons.Data[i].ToString().Length > 24)
6511 { 6935 {
6512 LSLError("button label cannot be longer than 24 characters"); 6936 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6513 return; 6937 return;
6514 } 6938 }
6515 buts[i] = buttons.Data[i].ToString(); 6939 buts[i] = buttons.Data[i].ToString();
@@ -6568,22 +6992,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6568 } 6992 }
6569 6993
6570 // copy the first script found with this inventory name 6994 // copy the first script found with this inventory name
6571 lock (m_host.TaskInventory) 6995 TaskInventoryItem scriptItem = null;
6996 m_host.TaskInventory.LockItemsForRead(true);
6997 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6572 { 6998 {
6573 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6999 if (inv.Value.Name == name)
6574 { 7000 {
6575 if (inv.Value.Name == name) 7001 // make sure the object is a script
7002 if (10 == inv.Value.Type)
6576 { 7003 {
6577 // make sure the object is a script 7004 found = true;
6578 if (10 == inv.Value.Type) 7005 srcId = inv.Key;
6579 { 7006 scriptItem = inv.Value;
6580 found = true; 7007 break;
6581 srcId = inv.Key;
6582 break;
6583 }
6584 } 7008 }
6585 } 7009 }
6586 } 7010 }
7011 m_host.TaskInventory.LockItemsForRead(false);
6587 7012
6588 if (!found) 7013 if (!found)
6589 { 7014 {
@@ -6591,8 +7016,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6591 return; 7016 return;
6592 } 7017 }
6593 7018
6594 // the rest of the permission checks are done in RezScript, so check the pin there as well 7019 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6595 World.RezScript(srcId, m_host, destId, pin, running, start_param); 7020 if (dest != null)
7021 {
7022 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7023 {
7024 // the rest of the permission checks are done in RezScript, so check the pin there as well
7025 World.RezScript(srcId, m_host, destId, pin, running, start_param);
7026
7027 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7028 m_host.Inventory.RemoveInventoryItem(srcId);
7029 }
7030 }
6596 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7031 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6597 ScriptSleep(3000); 7032 ScriptSleep(3000);
6598 } 7033 }
@@ -6655,19 +7090,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6655 public LSL_String llMD5String(string src, int nonce) 7090 public LSL_String llMD5String(string src, int nonce)
6656 { 7091 {
6657 m_host.AddScriptLPS(1); 7092 m_host.AddScriptLPS(1);
6658 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7093 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6659 } 7094 }
6660 7095
6661 public LSL_String llSHA1String(string src) 7096 public LSL_String llSHA1String(string src)
6662 { 7097 {
6663 m_host.AddScriptLPS(1); 7098 m_host.AddScriptLPS(1);
6664 return Util.SHA1Hash(src).ToLower(); 7099 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6665 } 7100 }
6666 7101
6667 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7102 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6668 { 7103 {
6669 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7104 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6670 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7105 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7106 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7107 return shapeBlock;
6671 7108
6672 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7109 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6673 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7110 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6772,6 +7209,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6772 // Prim type box, cylinder and prism. 7209 // Prim type box, cylinder and prism.
6773 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) 7210 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)
6774 { 7211 {
7212 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7213 return;
7214
6775 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7215 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6776 ObjectShapePacket.ObjectDataBlock shapeBlock; 7216 ObjectShapePacket.ObjectDataBlock shapeBlock;
6777 7217
@@ -6825,6 +7265,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6825 // Prim type sphere. 7265 // Prim type sphere.
6826 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7266 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6827 { 7267 {
7268 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7269 return;
7270
6828 ObjectShapePacket.ObjectDataBlock shapeBlock; 7271 ObjectShapePacket.ObjectDataBlock shapeBlock;
6829 7272
6830 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7273 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6866,6 +7309,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6866 // Prim type torus, tube and ring. 7309 // Prim type torus, tube and ring.
6867 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) 7310 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)
6868 { 7311 {
7312 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7313 return;
7314
6869 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7315 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6870 ObjectShapePacket.ObjectDataBlock shapeBlock; 7316 ObjectShapePacket.ObjectDataBlock shapeBlock;
6871 7317
@@ -7001,6 +7447,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7001 // Prim type sculpt. 7447 // Prim type sculpt.
7002 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7448 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7003 { 7449 {
7450 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7451 return;
7452
7004 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7453 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7005 UUID sculptId; 7454 UUID sculptId;
7006 7455
@@ -7017,13 +7466,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7017 shapeBlock.PathScaleX = 100; 7466 shapeBlock.PathScaleX = 100;
7018 shapeBlock.PathScaleY = 150; 7467 shapeBlock.PathScaleY = 150;
7019 7468
7020 if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER && 7469 if ((type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER) == 0 &&
7021 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE && 7470 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE) == 0 &&
7022 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE && 7471 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE) == 0 &&
7023 type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) 7472 (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) == 0)
7024 { 7473 {
7025 // default 7474 // default
7026 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7475 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7027 } 7476 }
7028 7477
7029 part.Shape.SetSculptProperties((byte)type, sculptId); 7478 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7039,32 +7488,87 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7039 ScriptSleep(200); 7488 ScriptSleep(200);
7040 } 7489 }
7041 7490
7042 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7491 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7043 { 7492 {
7044 m_host.AddScriptLPS(1); 7493 m_host.AddScriptLPS(1);
7045 7494
7046 setLinkPrimParams(linknumber, rules); 7495 setLinkPrimParams(linknumber, rules);
7047
7048 ScriptSleep(200);
7049 } 7496 }
7050 7497
7051 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7498 private void setLinkPrimParams(int linknumber, LSL_List rules)
7052 { 7499 {
7053 m_host.AddScriptLPS(1); 7500 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7501 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7502 if (parts.Count>0)
7503 {
7504 try
7505 {
7506 parts[0].ParentGroup.areUpdatesSuspended = true;
7507 foreach (SceneObjectPart part in parts)
7508 SetPrimParams(part, rules);
7509 }
7510 finally
7511 {
7512 parts[0].ParentGroup.areUpdatesSuspended = false;
7513 }
7514 }
7515 if (avatars.Count > 0)
7516 {
7517 foreach (ScenePresence avatar in avatars)
7518 SetPrimParams(avatar, rules);
7519 }
7520 }
7054 7521
7055 setLinkPrimParams(linknumber, rules); 7522 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7523 {
7524 llSetLinkPrimitiveParamsFast(linknumber, rules);
7525 ScriptSleep(200);
7056 } 7526 }
7057 7527
7058 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7528 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7059 { 7529 {
7060 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7530 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7531 //We only support PRIM_POSITION and PRIM_ROTATION
7061 7532
7062 foreach (SceneObjectPart part in parts) 7533 int idx = 0;
7063 SetPrimParams(part, rules); 7534
7535 while (idx < rules.Length)
7536 {
7537 int code = rules.GetLSLIntegerItem(idx++);
7538
7539 int remain = rules.Length - idx;
7540
7541
7542
7543 switch (code)
7544 {
7545 case (int)ScriptBaseClass.PRIM_POSITION:
7546 if (remain < 1)
7547 return;
7548 LSL_Vector v;
7549 v = rules.GetVector3Item(idx++);
7550 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7551 av.SendAvatarDataToAllAgents();
7552
7553 break;
7554
7555 case (int)ScriptBaseClass.PRIM_ROTATION:
7556 if (remain < 1)
7557 return;
7558 LSL_Rotation r;
7559 r = rules.GetQuaternionItem(idx++);
7560 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7561 av.SendAvatarDataToAllAgents();
7562 break;
7563 }
7564 }
7064 } 7565 }
7065 7566
7066 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7567 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7067 { 7568 {
7569 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7570 return;
7571
7068 int idx = 0; 7572 int idx = 0;
7069 7573
7070 bool positionChanged = false; 7574 bool positionChanged = false;
@@ -7092,6 +7596,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7092 currentPosition = GetSetPosTarget(part, v, currentPosition); 7596 currentPosition = GetSetPosTarget(part, v, currentPosition);
7093 7597
7094 break; 7598 break;
7599 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
7600 if (remain < 1)
7601 return;
7602
7603 v=rules.GetVector3Item(idx++);
7604 positionChanged = true;
7605 currentPosition = GetSetPosTarget(part, v, currentPosition);
7606
7607 break;
7095 case (int)ScriptBaseClass.PRIM_SIZE: 7608 case (int)ScriptBaseClass.PRIM_SIZE:
7096 if (remain < 1) 7609 if (remain < 1)
7097 return; 7610 return;
@@ -7469,6 +7982,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7469 } 7982 }
7470 } 7983 }
7471 } 7984 }
7985
7986 if (positionChanged)
7987 {
7988 if (part.ParentGroup.RootPart == part)
7989 {
7990 SceneObjectGroup parent = part.ParentGroup;
7991 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
7992 }
7993 else
7994 {
7995 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
7996 SceneObjectGroup parent = part.ParentGroup;
7997 parent.HasGroupChanged = true;
7998 parent.ScheduleGroupForTerseUpdate();
7999 }
8000 }
7472 } 8001 }
7473 8002
7474 public LSL_String llStringToBase64(string str) 8003 public LSL_String llStringToBase64(string str)
@@ -7617,13 +8146,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7617 public LSL_Integer llGetNumberOfPrims() 8146 public LSL_Integer llGetNumberOfPrims()
7618 { 8147 {
7619 m_host.AddScriptLPS(1); 8148 m_host.AddScriptLPS(1);
7620 int avatarCount = 0; 8149 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7621 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8150
7622 {
7623 if (presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID))
7624 avatarCount++;
7625 });
7626
7627 return m_host.ParentGroup.PrimCount + avatarCount; 8151 return m_host.ParentGroup.PrimCount + avatarCount;
7628 } 8152 }
7629 8153
@@ -7639,55 +8163,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7639 m_host.AddScriptLPS(1); 8163 m_host.AddScriptLPS(1);
7640 UUID objID = UUID.Zero; 8164 UUID objID = UUID.Zero;
7641 LSL_List result = new LSL_List(); 8165 LSL_List result = new LSL_List();
8166
8167 // If the ID is not valid, return null result
7642 if (!UUID.TryParse(obj, out objID)) 8168 if (!UUID.TryParse(obj, out objID))
7643 { 8169 {
7644 result.Add(new LSL_Vector()); 8170 result.Add(new LSL_Vector());
7645 result.Add(new LSL_Vector()); 8171 result.Add(new LSL_Vector());
7646 return result; 8172 return result;
7647 } 8173 }
8174
8175 // Check if this is an attached prim. If so, replace
8176 // the UUID with the avatar UUID and report it's bounding box
8177 SceneObjectPart part = World.GetSceneObjectPart(objID);
8178 if (part != null && part.ParentGroup.IsAttachment)
8179 objID = part.ParentGroup.AttachedAvatar;
8180
8181 // Find out if this is an avatar ID. If so, return it's box
7648 ScenePresence presence = World.GetScenePresence(objID); 8182 ScenePresence presence = World.GetScenePresence(objID);
7649 if (presence != null) 8183 if (presence != null)
7650 { 8184 {
7651 if (presence.ParentID == 0) // not sat on an object 8185 // As per LSL Wiki, there is no difference between sitting
8186 // and standing avatar since server 1.36
8187 LSL_Vector lower;
8188 LSL_Vector upper;
8189 if (presence.Animator.Animations.DefaultAnimation.AnimID
8190 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7652 { 8191 {
7653 LSL_Vector lower; 8192 // This is for ground sitting avatars
7654 LSL_Vector upper; 8193 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7655 if (presence.Animator.Animations.DefaultAnimation.AnimID 8194 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7656 == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8195 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7657 {
7658 // This is for ground sitting avatars
7659 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7660 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7661 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7662 }
7663 else
7664 {
7665 // This is for standing/flying avatars
7666 float height = presence.Appearance.AvatarHeight / 2.0f;
7667 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7668 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7669 }
7670 result.Add(lower);
7671 result.Add(upper);
7672 return result;
7673 } 8196 }
7674 else 8197 else
7675 { 8198 {
7676 // sitting on an object so we need the bounding box of that 8199 // This is for standing/flying avatars
7677 // which should include the avatar so set the UUID to the 8200 float height = presence.Appearance.AvatarHeight / 2.0f;
7678 // UUID of the object the avatar is sat on and allow it to fall through 8201 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7679 // to processing an object 8202 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7680 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7681 objID = p.UUID;
7682 } 8203 }
8204
8205 // Adjust to the documented error offsets (see LSL Wiki)
8206 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8207 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8208
8209 if (lower.x > upper.x)
8210 lower.x = upper.x;
8211 if (lower.y > upper.y)
8212 lower.y = upper.y;
8213 if (lower.z > upper.z)
8214 lower.z = upper.z;
8215
8216 result.Add(lower);
8217 result.Add(upper);
8218 return result;
7683 } 8219 }
7684 SceneObjectPart part = World.GetSceneObjectPart(objID); 8220
8221 part = World.GetSceneObjectPart(objID);
7685 // Currently only works for single prims without a sitting avatar 8222 // Currently only works for single prims without a sitting avatar
7686 if (part != null) 8223 if (part != null)
7687 { 8224 {
7688 Vector3 halfSize = part.Scale / 2.0f; 8225 float minX;
7689 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8226 float maxX;
7690 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8227 float minY;
8228 float maxY;
8229 float minZ;
8230 float maxZ;
8231
8232 // This BBox is in sim coordinates, with the offset being
8233 // a contained point.
8234 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8235 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8236
8237 minX -= offsets[0].X;
8238 maxX -= offsets[0].X;
8239 minY -= offsets[0].Y;
8240 maxY -= offsets[0].Y;
8241 minZ -= offsets[0].Z;
8242 maxZ -= offsets[0].Z;
8243
8244 LSL_Vector lower;
8245 LSL_Vector upper;
8246
8247 // Adjust to the documented error offsets (see LSL Wiki)
8248 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8249 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8250
8251 if (lower.x > upper.x)
8252 lower.x = upper.x;
8253 if (lower.y > upper.y)
8254 lower.y = upper.y;
8255 if (lower.z > upper.z)
8256 lower.z = upper.z;
8257
7691 result.Add(lower); 8258 result.Add(lower);
7692 result.Add(upper); 8259 result.Add(upper);
7693 return result; 8260 return result;
@@ -7767,13 +8334,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7767 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8334 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7768 part.AbsolutePosition.Y, 8335 part.AbsolutePosition.Y,
7769 part.AbsolutePosition.Z); 8336 part.AbsolutePosition.Z);
7770 // For some reason, the part.AbsolutePosition.* values do not change if the
7771 // linkset is rotated; they always reflect the child prim's world position
7772 // as though the linkset is unrotated. This is incompatible behavior with SL's
7773 // implementation, so will break scripts imported from there (not to mention it
7774 // makes it more difficult to determine a child prim's actual inworld position).
7775 if (part.ParentID != 0)
7776 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7777 res.Add(v); 8337 res.Add(v);
7778 break; 8338 break;
7779 8339
@@ -7944,56 +8504,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7944 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8504 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7945 if (remain < 1) 8505 if (remain < 1)
7946 return res; 8506 return res;
7947 8507 face = (int)rules.GetLSLIntegerItem(idx++);
7948 face=(int)rules.GetLSLIntegerItem(idx++);
7949 8508
7950 tex = part.Shape.Textures; 8509 tex = part.Shape.Textures;
8510 int shiny;
7951 if (face == ScriptBaseClass.ALL_SIDES) 8511 if (face == ScriptBaseClass.ALL_SIDES)
7952 { 8512 {
7953 for (face = 0; face < GetNumberOfSides(part); face++) 8513 for (face = 0; face < GetNumberOfSides(part); face++)
7954 { 8514 {
7955 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8515 Shininess shinyness = tex.GetFace((uint)face).Shiny;
7956 // Convert Shininess to PRIM_SHINY_* 8516 if (shinyness == Shininess.High)
7957 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8517 {
7958 // PRIM_BUMP_* 8518 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7959 res.Add(new LSL_Integer((int)texface.Bump)); 8519 }
8520 else if (shinyness == Shininess.Medium)
8521 {
8522 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8523 }
8524 else if (shinyness == Shininess.Low)
8525 {
8526 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8527 }
8528 else
8529 {
8530 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8531 }
8532 res.Add(new LSL_Integer(shiny));
8533 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7960 } 8534 }
7961 } 8535 }
7962 else 8536 else
7963 { 8537 {
7964 if (face >= 0 && face < GetNumberOfSides(part)) 8538 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8539 if (shinyness == Shininess.High)
7965 { 8540 {
7966 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8541 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7967 // Convert Shininess to PRIM_SHINY_*
7968 res.Add(new LSL_Integer((uint)texface.Shiny >> 6));
7969 // PRIM_BUMP_*
7970 res.Add(new LSL_Integer((int)texface.Bump));
7971 } 8542 }
8543 else if (shinyness == Shininess.Medium)
8544 {
8545 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8546 }
8547 else if (shinyness == Shininess.Low)
8548 {
8549 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8550 }
8551 else
8552 {
8553 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8554 }
8555 res.Add(new LSL_Integer(shiny));
8556 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7972 } 8557 }
7973 break; 8558 break;
7974 8559
7975 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8560 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
7976 if (remain < 1) 8561 if (remain < 1)
7977 return res; 8562 return res;
7978 8563 face = (int)rules.GetLSLIntegerItem(idx++);
7979 face=(int)rules.GetLSLIntegerItem(idx++);
7980 8564
7981 tex = part.Shape.Textures; 8565 tex = part.Shape.Textures;
8566 int fullbright;
7982 if (face == ScriptBaseClass.ALL_SIDES) 8567 if (face == ScriptBaseClass.ALL_SIDES)
7983 { 8568 {
7984 for (face = 0; face < GetNumberOfSides(part); face++) 8569 for (face = 0; face < GetNumberOfSides(part); face++)
7985 { 8570 {
7986 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8571 if (tex.GetFace((uint)face).Fullbright == true)
7987 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8572 {
8573 fullbright = ScriptBaseClass.TRUE;
8574 }
8575 else
8576 {
8577 fullbright = ScriptBaseClass.FALSE;
8578 }
8579 res.Add(new LSL_Integer(fullbright));
7988 } 8580 }
7989 } 8581 }
7990 else 8582 else
7991 { 8583 {
7992 if (face >= 0 && face < GetNumberOfSides(part)) 8584 if (tex.GetFace((uint)face).Fullbright == true)
7993 { 8585 {
7994 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8586 fullbright = ScriptBaseClass.TRUE;
7995 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8587 }
8588 else
8589 {
8590 fullbright = ScriptBaseClass.FALSE;
7996 } 8591 }
8592 res.Add(new LSL_Integer(fullbright));
7997 } 8593 }
7998 break; 8594 break;
7999 8595
@@ -8015,27 +8611,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8015 break; 8611 break;
8016 8612
8017 case (int)ScriptBaseClass.PRIM_TEXGEN: 8613 case (int)ScriptBaseClass.PRIM_TEXGEN:
8614 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8018 if (remain < 1) 8615 if (remain < 1)
8019 return res; 8616 return res;
8020 8617 face = (int)rules.GetLSLIntegerItem(idx++);
8021 face=(int)rules.GetLSLIntegerItem(idx++);
8022 8618
8023 tex = part.Shape.Textures; 8619 tex = part.Shape.Textures;
8024 if (face == ScriptBaseClass.ALL_SIDES) 8620 if (face == ScriptBaseClass.ALL_SIDES)
8025 { 8621 {
8026 for (face = 0; face < GetNumberOfSides(part); face++) 8622 for (face = 0; face < GetNumberOfSides(part); face++)
8027 { 8623 {
8028 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8624 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8029 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8625 {
8030 res.Add(new LSL_Integer((uint)texgen >> 1)); 8626 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8627 }
8628 else
8629 {
8630 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8631 }
8031 } 8632 }
8032 } 8633 }
8033 else 8634 else
8034 { 8635 {
8035 if (face >= 0 && face < GetNumberOfSides(part)) 8636 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8036 { 8637 {
8037 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8638 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8038 res.Add(new LSL_Integer((uint)texgen >> 1)); 8639 }
8640 else
8641 {
8642 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8039 } 8643 }
8040 } 8644 }
8041 break; 8645 break;
@@ -8058,28 +8662,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8058 case (int)ScriptBaseClass.PRIM_GLOW: 8662 case (int)ScriptBaseClass.PRIM_GLOW:
8059 if (remain < 1) 8663 if (remain < 1)
8060 return res; 8664 return res;
8061 8665 face = (int)rules.GetLSLIntegerItem(idx++);
8062 face=(int)rules.GetLSLIntegerItem(idx++);
8063 8666
8064 tex = part.Shape.Textures; 8667 tex = part.Shape.Textures;
8668 float primglow;
8065 if (face == ScriptBaseClass.ALL_SIDES) 8669 if (face == ScriptBaseClass.ALL_SIDES)
8066 { 8670 {
8067 for (face = 0; face < GetNumberOfSides(part); face++) 8671 for (face = 0; face < GetNumberOfSides(part); face++)
8068 { 8672 {
8069 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8673 primglow = tex.GetFace((uint)face).Glow;
8070 res.Add(new LSL_Float(texface.Glow)); 8674 res.Add(new LSL_Float(primglow));
8071 } 8675 }
8072 } 8676 }
8073 else 8677 else
8074 { 8678 {
8075 if (face >= 0 && face < GetNumberOfSides(part)) 8679 primglow = tex.GetFace((uint)face).Glow;
8076 { 8680 res.Add(new LSL_Float(primglow));
8077 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8078 res.Add(new LSL_Float(texface.Glow));
8079 }
8080 } 8681 }
8081 break; 8682 break;
8082
8083 case (int)ScriptBaseClass.PRIM_TEXT: 8683 case (int)ScriptBaseClass.PRIM_TEXT:
8084 Color4 textColor = part.GetTextColor(); 8684 Color4 textColor = part.GetTextColor();
8085 res.Add(new LSL_String(part.Text)); 8685 res.Add(new LSL_String(part.Text));
@@ -8631,8 +9231,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8631 // The function returns an ordered list 9231 // The function returns an ordered list
8632 // representing the tokens found in the supplied 9232 // representing the tokens found in the supplied
8633 // sources string. If two successive tokenizers 9233 // sources string. If two successive tokenizers
8634 // are encountered, then a NULL entry is added 9234 // are encountered, then a null-string entry is
8635 // to the list. 9235 // added to the list.
8636 // 9236 //
8637 // It is a precondition that the source and 9237 // It is a precondition that the source and
8638 // toekizer lisst are non-null. If they are null, 9238 // toekizer lisst are non-null. If they are null,
@@ -8640,7 +9240,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8640 // while their lengths are being determined. 9240 // while their lengths are being determined.
8641 // 9241 //
8642 // A small amount of working memoryis required 9242 // A small amount of working memoryis required
8643 // of approximately 8*#tokenizers. 9243 // of approximately 8*#tokenizers + 8*srcstrlen.
8644 // 9244 //
8645 // There are many ways in which this function 9245 // There are many ways in which this function
8646 // can be implemented, this implementation is 9246 // can be implemented, this implementation is
@@ -8656,155 +9256,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8656 // and eliminates redundant tokenizers as soon 9256 // and eliminates redundant tokenizers as soon
8657 // as is possible. 9257 // as is possible.
8658 // 9258 //
8659 // The implementation tries to avoid any copying 9259 // The implementation tries to minimize temporary
8660 // of arrays or other objects. 9260 // garbage generation.
8661 // </remarks> 9261 // </remarks>
8662 9262
8663 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9263 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8664 { 9264 {
8665 int beginning = 0; 9265 return ParseString2List(src, separators, spacers, true);
8666 int srclen = src.Length; 9266 }
8667 int seplen = separators.Length;
8668 object[] separray = separators.Data;
8669 int spclen = spacers.Length;
8670 object[] spcarray = spacers.Data;
8671 int mlen = seplen+spclen;
8672
8673 int[] offset = new int[mlen+1];
8674 bool[] active = new bool[mlen];
8675
8676 int best;
8677 int j;
8678
8679 // Initial capacity reduces resize cost
8680 9267
8681 LSL_List tokens = new LSL_List(); 9268 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9269 {
9270 int srclen = src.Length;
9271 int seplen = separators.Length;
9272 object[] separray = separators.Data;
9273 int spclen = spacers.Length;
9274 object[] spcarray = spacers.Data;
9275 int dellen = 0;
9276 string[] delarray = new string[seplen+spclen];
8682 9277
8683 // All entries are initially valid 9278 int outlen = 0;
9279 string[] outarray = new string[srclen*2+1];
8684 9280
8685 for (int i = 0; i < mlen; i++) 9281 int i, j;
8686 active[i] = true; 9282 string d;
8687 9283
8688 offset[mlen] = srclen; 9284 m_host.AddScriptLPS(1);
8689 9285
8690 while (beginning < srclen) 9286 /*
9287 * Convert separator and spacer lists to C# strings.
9288 * Also filter out null strings so we don't hang.
9289 */
9290 for (i = 0; i < seplen; i ++)
8691 { 9291 {
9292 d = separray[i].ToString();
9293 if (d.Length > 0)
9294 {
9295 delarray[dellen++] = d;
9296 }
9297 }
9298 seplen = dellen;
8692 9299
8693 best = mlen; // as bad as it gets 9300 for (i = 0; i < spclen; i ++)
9301 {
9302 d = spcarray[i].ToString();
9303 if (d.Length > 0)
9304 {
9305 delarray[dellen++] = d;
9306 }
9307 }
8694 9308
8695 // Scan for separators 9309 /*
9310 * Scan through source string from beginning to end.
9311 */
9312 for (i = 0;;)
9313 {
8696 9314
8697 for (j = 0; j < seplen; j++) 9315 /*
9316 * Find earliest delimeter in src starting at i (if any).
9317 */
9318 int earliestDel = -1;
9319 int earliestSrc = srclen;
9320 string earliestStr = null;
9321 for (j = 0; j < dellen; j ++)
8698 { 9322 {
8699 if (separray[j].ToString() == String.Empty) 9323 d = delarray[j];
8700 active[j] = false; 9324 if (d != null)
8701
8702 if (active[j])
8703 { 9325 {
8704 // scan all of the markers 9326 int index = src.IndexOf(d, i);
8705 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9327 if (index < 0)
8706 { 9328 {
8707 // not present at all 9329 delarray[j] = null; // delim nowhere in src, don't check it anymore
8708 active[j] = false;
8709 } 9330 }
8710 else 9331 else if (index < earliestSrc)
8711 { 9332 {
8712 // present and correct 9333 earliestSrc = index; // where delimeter starts in source string
8713 if (offset[j] < offset[best]) 9334 earliestDel = j; // where delimeter is in delarray[]
8714 { 9335 earliestStr = d; // the delimeter string from delarray[]
8715 // closest so far 9336 if (index == i) break; // can't do any better than found at beg of string
8716 best = j;
8717 if (offset[best] == beginning)
8718 break;
8719 }
8720 } 9337 }
8721 } 9338 }
8722 } 9339 }
8723 9340
8724 // Scan for spacers 9341 /*
8725 9342 * Output source string starting at i through start of earliest delimeter.
8726 if (offset[best] != beginning) 9343 */
9344 if (keepNulls || (earliestSrc > i))
8727 { 9345 {
8728 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9346 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8729 {
8730 if (spcarray[j-seplen].ToString() == String.Empty)
8731 active[j] = false;
8732
8733 if (active[j])
8734 {
8735 // scan all of the markers
8736 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8737 {
8738 // not present at all
8739 active[j] = false;
8740 }
8741 else
8742 {
8743 // present and correct
8744 if (offset[j] < offset[best])
8745 {
8746 // closest so far
8747 best = j;
8748 }
8749 }
8750 }
8751 }
8752 } 9347 }
8753 9348
8754 // This is the normal exit from the scanning loop 9349 /*
9350 * If no delimeter found at or after i, we're done scanning.
9351 */
9352 if (earliestDel < 0) break;
8755 9353
8756 if (best == mlen) 9354 /*
9355 * If delimeter was a spacer, output the spacer.
9356 */
9357 if (earliestDel >= seplen)
8757 { 9358 {
8758 // no markers were found on this pass 9359 outarray[outlen++] = earliestStr;
8759 // so we're pretty much done
8760 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8761 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8762 break;
8763 } 9360 }
8764 9361
8765 // Otherwise we just add the newly delimited token 9362 /*
8766 // and recalculate where the search should continue. 9363 * Look at rest of src string following delimeter.
8767 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9364 */
8768 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9365 i = earliestSrc + earliestStr.Length;
8769
8770 if (best < seplen)
8771 {
8772 beginning = offset[best] + (separray[best].ToString()).Length;
8773 }
8774 else
8775 {
8776 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8777 string str = spcarray[best - seplen].ToString();
8778 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8779 tokens.Add(new LSL_String(str));
8780 }
8781 } 9366 }
8782 9367
8783 // This an awkward an not very intuitive boundary case. If the 9368 /*
8784 // last substring is a tokenizer, then there is an implied trailing 9369 * Make up an exact-sized output array suitable for an LSL_List object.
8785 // null list entry. Hopefully the single comparison will not be too 9370 */
8786 // arduous. Alternatively the 'break' could be replced with a return 9371 object[] outlist = new object[outlen];
8787 // but that's shabby programming. 9372 for (i = 0; i < outlen; i ++)
8788
8789 if ((beginning == srclen) && (keepNulls))
8790 { 9373 {
8791 if (srclen != 0) 9374 outlist[i] = new LSL_String(outarray[i]);
8792 tokens.Add(new LSL_String(""));
8793 } 9375 }
8794 9376 return new LSL_List(outlist);
8795 return tokens;
8796 }
8797
8798 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8799 {
8800 m_host.AddScriptLPS(1);
8801 return this.ParseString(src, separators, spacers, false);
8802 }
8803
8804 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8805 {
8806 m_host.AddScriptLPS(1);
8807 return this.ParseString(src, separators, spacers, true);
8808 } 9377 }
8809 9378
8810 public LSL_Integer llGetObjectPermMask(int mask) 9379 public LSL_Integer llGetObjectPermMask(int mask)
@@ -8881,28 +9450,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8881 { 9450 {
8882 m_host.AddScriptLPS(1); 9451 m_host.AddScriptLPS(1);
8883 9452
8884 lock (m_host.TaskInventory) 9453 m_host.TaskInventory.LockItemsForRead(true);
9454 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8885 { 9455 {
8886 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9456 if (inv.Value.Name == item)
8887 { 9457 {
8888 if (inv.Value.Name == item) 9458 m_host.TaskInventory.LockItemsForRead(false);
9459 switch (mask)
8889 { 9460 {
8890 switch (mask) 9461 case 0:
8891 { 9462 return (int)inv.Value.BasePermissions;
8892 case 0: 9463 case 1:
8893 return (int)inv.Value.BasePermissions; 9464 return (int)inv.Value.CurrentPermissions;
8894 case 1: 9465 case 2:
8895 return (int)inv.Value.CurrentPermissions; 9466 return (int)inv.Value.GroupPermissions;
8896 case 2: 9467 case 3:
8897 return (int)inv.Value.GroupPermissions; 9468 return (int)inv.Value.EveryonePermissions;
8898 case 3: 9469 case 4:
8899 return (int)inv.Value.EveryonePermissions; 9470 return (int)inv.Value.NextPermissions;
8900 case 4:
8901 return (int)inv.Value.NextPermissions;
8902 }
8903 } 9471 }
8904 } 9472 }
8905 } 9473 }
9474 m_host.TaskInventory.LockItemsForRead(false);
8906 9475
8907 return -1; 9476 return -1;
8908 } 9477 }
@@ -8949,16 +9518,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8949 { 9518 {
8950 m_host.AddScriptLPS(1); 9519 m_host.AddScriptLPS(1);
8951 9520
8952 lock (m_host.TaskInventory) 9521 m_host.TaskInventory.LockItemsForRead(true);
9522 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8953 { 9523 {
8954 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9524 if (inv.Value.Name == item)
8955 { 9525 {
8956 if (inv.Value.Name == item) 9526 m_host.TaskInventory.LockItemsForRead(false);
8957 { 9527 return inv.Value.CreatorID.ToString();
8958 return inv.Value.CreatorID.ToString();
8959 }
8960 } 9528 }
8961 } 9529 }
9530 m_host.TaskInventory.LockItemsForRead(false);
8962 9531
8963 llSay(0, "No item name '" + item + "'"); 9532 llSay(0, "No item name '" + item + "'");
8964 9533
@@ -9106,7 +9675,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9106 } 9675 }
9107 9676
9108 /// <summary> 9677 /// <summary>
9109 /// illListReplaceList removes the sub-list defined by the inclusive indices 9678 /// llListReplaceList removes the sub-list defined by the inclusive indices
9110 /// start and end and inserts the src list in its place. The inclusive 9679 /// start and end and inserts the src list in its place. The inclusive
9111 /// nature of the indices means that at least one element must be deleted 9680 /// nature of the indices means that at least one element must be deleted
9112 /// if the indices are within the bounds of the existing list. I.e. 2,2 9681 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9163,16 +9732,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9163 // based upon end. Note that if end exceeds the upper 9732 // based upon end. Note that if end exceeds the upper
9164 // bound in this case, the entire destination list 9733 // bound in this case, the entire destination list
9165 // is removed. 9734 // is removed.
9166 else 9735 else if (start == 0)
9167 { 9736 {
9168 if (end + 1 < dest.Length) 9737 if (end + 1 < dest.Length)
9169 {
9170 return src + dest.GetSublist(end + 1, -1); 9738 return src + dest.GetSublist(end + 1, -1);
9171 }
9172 else 9739 else
9173 {
9174 return src; 9740 return src;
9175 } 9741 }
9742 else // Start < 0
9743 {
9744 if (end + 1 < dest.Length)
9745 return dest.GetSublist(end + 1, -1);
9746 else
9747 return new LSL_List();
9176 } 9748 }
9177 } 9749 }
9178 // Finally, if start > end, we strip away a prefix and 9750 // Finally, if start > end, we strip away a prefix and
@@ -9223,17 +9795,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9223 int width = 0; 9795 int width = 0;
9224 int height = 0; 9796 int height = 0;
9225 9797
9226 ParcelMediaCommandEnum? commandToSend = null; 9798 uint commandToSend = 0;
9227 float time = 0.0f; // default is from start 9799 float time = 0.0f; // default is from start
9228 9800
9229 ScenePresence presence = null; 9801 ScenePresence presence = null;
9230 9802
9231 for (int i = 0; i < commandList.Data.Length; i++) 9803 for (int i = 0; i < commandList.Data.Length; i++)
9232 { 9804 {
9233 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 9805 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9234 switch (command) 9806 switch (command)
9235 { 9807 {
9236 case ParcelMediaCommandEnum.Agent: 9808 case (uint)ParcelMediaCommandEnum.Agent:
9237 // we send only to one agent 9809 // we send only to one agent
9238 if ((i + 1) < commandList.Length) 9810 if ((i + 1) < commandList.Length)
9239 { 9811 {
@@ -9250,25 +9822,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9250 } 9822 }
9251 break; 9823 break;
9252 9824
9253 case ParcelMediaCommandEnum.Loop: 9825 case (uint)ParcelMediaCommandEnum.Loop:
9254 loop = 1; 9826 loop = 1;
9255 commandToSend = command; 9827 commandToSend = command;
9256 update = true; //need to send the media update packet to set looping 9828 update = true; //need to send the media update packet to set looping
9257 break; 9829 break;
9258 9830
9259 case ParcelMediaCommandEnum.Play: 9831 case (uint)ParcelMediaCommandEnum.Play:
9260 loop = 0; 9832 loop = 0;
9261 commandToSend = command; 9833 commandToSend = command;
9262 update = true; //need to send the media update packet to make sure it doesn't loop 9834 update = true; //need to send the media update packet to make sure it doesn't loop
9263 break; 9835 break;
9264 9836
9265 case ParcelMediaCommandEnum.Pause: 9837 case (uint)ParcelMediaCommandEnum.Pause:
9266 case ParcelMediaCommandEnum.Stop: 9838 case (uint)ParcelMediaCommandEnum.Stop:
9267 case ParcelMediaCommandEnum.Unload: 9839 case (uint)ParcelMediaCommandEnum.Unload:
9268 commandToSend = command; 9840 commandToSend = command;
9269 break; 9841 break;
9270 9842
9271 case ParcelMediaCommandEnum.Url: 9843 case (uint)ParcelMediaCommandEnum.Url:
9272 if ((i + 1) < commandList.Length) 9844 if ((i + 1) < commandList.Length)
9273 { 9845 {
9274 if (commandList.Data[i + 1] is LSL_String) 9846 if (commandList.Data[i + 1] is LSL_String)
@@ -9281,7 +9853,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9281 } 9853 }
9282 break; 9854 break;
9283 9855
9284 case ParcelMediaCommandEnum.Texture: 9856 case (uint)ParcelMediaCommandEnum.Texture:
9285 if ((i + 1) < commandList.Length) 9857 if ((i + 1) < commandList.Length)
9286 { 9858 {
9287 if (commandList.Data[i + 1] is LSL_String) 9859 if (commandList.Data[i + 1] is LSL_String)
@@ -9294,7 +9866,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9294 } 9866 }
9295 break; 9867 break;
9296 9868
9297 case ParcelMediaCommandEnum.Time: 9869 case (uint)ParcelMediaCommandEnum.Time:
9298 if ((i + 1) < commandList.Length) 9870 if ((i + 1) < commandList.Length)
9299 { 9871 {
9300 if (commandList.Data[i + 1] is LSL_Float) 9872 if (commandList.Data[i + 1] is LSL_Float)
@@ -9306,7 +9878,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9306 } 9878 }
9307 break; 9879 break;
9308 9880
9309 case ParcelMediaCommandEnum.AutoAlign: 9881 case (uint)ParcelMediaCommandEnum.AutoAlign:
9310 if ((i + 1) < commandList.Length) 9882 if ((i + 1) < commandList.Length)
9311 { 9883 {
9312 if (commandList.Data[i + 1] is LSL_Integer) 9884 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9320,7 +9892,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9320 } 9892 }
9321 break; 9893 break;
9322 9894
9323 case ParcelMediaCommandEnum.Type: 9895 case (uint)ParcelMediaCommandEnum.Type:
9324 if ((i + 1) < commandList.Length) 9896 if ((i + 1) < commandList.Length)
9325 { 9897 {
9326 if (commandList.Data[i + 1] is LSL_String) 9898 if (commandList.Data[i + 1] is LSL_String)
@@ -9333,7 +9905,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9333 } 9905 }
9334 break; 9906 break;
9335 9907
9336 case ParcelMediaCommandEnum.Desc: 9908 case (uint)ParcelMediaCommandEnum.Desc:
9337 if ((i + 1) < commandList.Length) 9909 if ((i + 1) < commandList.Length)
9338 { 9910 {
9339 if (commandList.Data[i + 1] is LSL_String) 9911 if (commandList.Data[i + 1] is LSL_String)
@@ -9346,7 +9918,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9346 } 9918 }
9347 break; 9919 break;
9348 9920
9349 case ParcelMediaCommandEnum.Size: 9921 case (uint)ParcelMediaCommandEnum.Size:
9350 if ((i + 2) < commandList.Length) 9922 if ((i + 2) < commandList.Length)
9351 { 9923 {
9352 if (commandList.Data[i + 1] is LSL_Integer) 9924 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9416,7 +9988,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9416 } 9988 }
9417 } 9989 }
9418 9990
9419 if (commandToSend != null) 9991 if (commandToSend != 0)
9420 { 9992 {
9421 // the commandList contained a start/stop/... command, too 9993 // the commandList contained a start/stop/... command, too
9422 if (presence == null) 9994 if (presence == null)
@@ -9453,7 +10025,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9453 10025
9454 if (aList.Data[i] != null) 10026 if (aList.Data[i] != null)
9455 { 10027 {
9456 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10028 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9457 { 10029 {
9458 case ParcelMediaCommandEnum.Url: 10030 case ParcelMediaCommandEnum.Url:
9459 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10031 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9496,16 +10068,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9496 { 10068 {
9497 m_host.AddScriptLPS(1); 10069 m_host.AddScriptLPS(1);
9498 10070
9499 lock (m_host.TaskInventory) 10071 m_host.TaskInventory.LockItemsForRead(true);
10072 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9500 { 10073 {
9501 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10074 if (inv.Value.Name == name)
9502 { 10075 {
9503 if (inv.Value.Name == name) 10076 m_host.TaskInventory.LockItemsForRead(false);
9504 { 10077 return inv.Value.Type;
9505 return inv.Value.Type;
9506 }
9507 } 10078 }
9508 } 10079 }
10080 m_host.TaskInventory.LockItemsForRead(false);
9509 10081
9510 return -1; 10082 return -1;
9511 } 10083 }
@@ -9516,15 +10088,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9516 10088
9517 if (quick_pay_buttons.Data.Length < 4) 10089 if (quick_pay_buttons.Data.Length < 4)
9518 { 10090 {
9519 LSLError("List must have at least 4 elements"); 10091 int x;
9520 return; 10092 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10093 {
10094 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10095 }
9521 } 10096 }
9522 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10097 int[] nPrice = new int[5];
9523 10098 nPrice[0] = price;
9524 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10099 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9525 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10100 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9526 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10101 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9527 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10102 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10103 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9528 m_host.ParentGroup.HasGroupChanged = true; 10104 m_host.ParentGroup.HasGroupChanged = true;
9529 } 10105 }
9530 10106
@@ -9536,17 +10112,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9536 if (invItemID == UUID.Zero) 10112 if (invItemID == UUID.Zero)
9537 return new LSL_Vector(); 10113 return new LSL_Vector();
9538 10114
9539 lock (m_host.TaskInventory) 10115 m_host.TaskInventory.LockItemsForRead(true);
10116 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9540 { 10117 {
9541 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10118 m_host.TaskInventory.LockItemsForRead(false);
9542 return new LSL_Vector(); 10119 return new LSL_Vector();
10120 }
9543 10121
9544 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 10122 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9545 { 10123 {
9546 ShoutError("No permissions to track the camera"); 10124 ShoutError("No permissions to track the camera");
9547 return new LSL_Vector(); 10125 m_host.TaskInventory.LockItemsForRead(false);
9548 } 10126 return new LSL_Vector();
9549 } 10127 }
10128 m_host.TaskInventory.LockItemsForRead(false);
9550 10129
9551 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10130 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9552 if (presence != null) 10131 if (presence != null)
@@ -9564,17 +10143,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9564 if (invItemID == UUID.Zero) 10143 if (invItemID == UUID.Zero)
9565 return new LSL_Rotation(); 10144 return new LSL_Rotation();
9566 10145
9567 lock (m_host.TaskInventory) 10146 m_host.TaskInventory.LockItemsForRead(true);
10147 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
9568 { 10148 {
9569 if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) 10149 m_host.TaskInventory.LockItemsForRead(false);
9570 return new LSL_Rotation(); 10150 return new LSL_Rotation();
9571 10151 }
9572 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 10152 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9573 { 10153 {
9574 ShoutError("No permissions to track the camera"); 10154 ShoutError("No permissions to track the camera");
9575 return new LSL_Rotation(); 10155 m_host.TaskInventory.LockItemsForRead(false);
9576 } 10156 return new LSL_Rotation();
9577 } 10157 }
10158 m_host.TaskInventory.LockItemsForRead(false);
9578 10159
9579 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10160 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9580 if (presence != null) 10161 if (presence != null)
@@ -9636,8 +10217,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9636 { 10217 {
9637 m_host.AddScriptLPS(1); 10218 m_host.AddScriptLPS(1);
9638 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0); 10219 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0);
9639 if (detectedParams == null) return; // only works on the first detected avatar 10220 if (detectedParams == null)
9640 10221 {
10222 if (m_host.ParentGroup.IsAttachment == true)
10223 {
10224 detectedParams = new DetectParams();
10225 detectedParams.Key = m_host.OwnerID;
10226 }
10227 else
10228 {
10229 return;
10230 }
10231 }
10232
9641 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10233 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9642 if (avatar != null) 10234 if (avatar != null)
9643 { 10235 {
@@ -9645,6 +10237,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9645 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10237 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9646 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10238 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9647 } 10239 }
10240
9648 ScriptSleep(1000); 10241 ScriptSleep(1000);
9649 } 10242 }
9650 10243
@@ -9737,14 +10330,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9737 if (objectID == UUID.Zero) return; 10330 if (objectID == UUID.Zero) return;
9738 10331
9739 UUID agentID; 10332 UUID agentID;
9740 lock (m_host.TaskInventory) 10333 m_host.TaskInventory.LockItemsForRead(true);
9741 { 10334 // we need the permission first, to know which avatar we want to set the camera for
9742 // we need the permission first, to know which avatar we want to set the camera for 10335 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9743 agentID = m_host.TaskInventory[invItemID].PermsGranter;
9744 10336
9745 if (agentID == UUID.Zero) return; 10337 if (agentID == UUID.Zero)
9746 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 10338 {
10339 m_host.TaskInventory.LockItemsForRead(false);
10340 return;
10341 }
10342 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10343 {
10344 m_host.TaskInventory.LockItemsForRead(false);
10345 return;
9747 } 10346 }
10347 m_host.TaskInventory.LockItemsForRead(false);
9748 10348
9749 ScenePresence presence = World.GetScenePresence(agentID); 10349 ScenePresence presence = World.GetScenePresence(agentID);
9750 10350
@@ -9753,12 +10353,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9753 10353
9754 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10354 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9755 object[] data = rules.Data; 10355 object[] data = rules.Data;
9756 for (int i = 0; i < data.Length; ++i) { 10356 for (int i = 0; i < data.Length; ++i)
10357 {
9757 int type = Convert.ToInt32(data[i++].ToString()); 10358 int type = Convert.ToInt32(data[i++].ToString());
9758 if (i >= data.Length) break; // odd number of entries => ignore the last 10359 if (i >= data.Length) break; // odd number of entries => ignore the last
9759 10360
9760 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10361 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9761 switch (type) { 10362 switch (type)
10363 {
9762 case ScriptBaseClass.CAMERA_FOCUS: 10364 case ScriptBaseClass.CAMERA_FOCUS:
9763 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10365 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9764 case ScriptBaseClass.CAMERA_POSITION: 10366 case ScriptBaseClass.CAMERA_POSITION:
@@ -9794,12 +10396,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9794 10396
9795 // we need the permission first, to know which avatar we want to clear the camera for 10397 // we need the permission first, to know which avatar we want to clear the camera for
9796 UUID agentID; 10398 UUID agentID;
9797 lock (m_host.TaskInventory) 10399 m_host.TaskInventory.LockItemsForRead(true);
10400 agentID = m_host.TaskInventory[invItemID].PermsGranter;
10401 if (agentID == UUID.Zero)
9798 { 10402 {
9799 agentID = m_host.TaskInventory[invItemID].PermsGranter; 10403 m_host.TaskInventory.LockItemsForRead(false);
9800 if (agentID == UUID.Zero) return; 10404 return;
9801 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; 10405 }
10406 if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
10407 {
10408 m_host.TaskInventory.LockItemsForRead(false);
10409 return;
9802 } 10410 }
10411 m_host.TaskInventory.LockItemsForRead(false);
9803 10412
9804 ScenePresence presence = World.GetScenePresence(agentID); 10413 ScenePresence presence = World.GetScenePresence(agentID);
9805 10414
@@ -9866,19 +10475,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9866 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10475 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
9867 { 10476 {
9868 m_host.AddScriptLPS(1); 10477 m_host.AddScriptLPS(1);
9869 string ret = String.Empty; 10478
9870 string src1 = llBase64ToString(str1); 10479 if (str1 == String.Empty)
9871 string src2 = llBase64ToString(str2); 10480 return String.Empty;
9872 int c = 0; 10481 if (str2 == String.Empty)
9873 for (int i = 0; i < src1.Length; i++) 10482 return str1;
10483
10484 int len = str2.Length;
10485 if ((len % 4) != 0) // LL is EVIL!!!!
9874 { 10486 {
9875 ret += (char) (src1[i] ^ src2[c]); 10487 while (str2.EndsWith("="))
10488 str2 = str2.Substring(0, str2.Length - 1);
9876 10489
9877 c++; 10490 len = str2.Length;
9878 if (c >= src2.Length) 10491 int mod = len % 4;
9879 c = 0; 10492
10493 if (mod == 1)
10494 str2 = str2.Substring(0, str2.Length - 1);
10495 else if (mod == 2)
10496 str2 += "==";
10497 else if (mod == 3)
10498 str2 += "=";
10499 }
10500
10501 byte[] data1;
10502 byte[] data2;
10503 try
10504 {
10505 data1 = Convert.FromBase64String(str1);
10506 data2 = Convert.FromBase64String(str2);
9880 } 10507 }
9881 return llStringToBase64(ret); 10508 catch (Exception)
10509 {
10510 return new LSL_String(String.Empty);
10511 }
10512
10513 byte[] d2 = new Byte[data1.Length];
10514 int pos = 0;
10515
10516 if (data1.Length <= data2.Length)
10517 {
10518 Array.Copy(data2, 0, d2, 0, data1.Length);
10519 }
10520 else
10521 {
10522 while (pos < data1.Length)
10523 {
10524 len = data1.Length - pos;
10525 if (len > data2.Length)
10526 len = data2.Length;
10527
10528 Array.Copy(data2, 0, d2, pos, len);
10529 pos += len;
10530 }
10531 }
10532
10533 for (pos = 0 ; pos < data1.Length ; pos++ )
10534 data1[pos] ^= d2[pos];
10535
10536 return Convert.ToBase64String(data1);
9882 } 10537 }
9883 10538
9884 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10539 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -9935,12 +10590,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9935 Regex r = new Regex(authregex); 10590 Regex r = new Regex(authregex);
9936 int[] gnums = r.GetGroupNumbers(); 10591 int[] gnums = r.GetGroupNumbers();
9937 Match m = r.Match(url); 10592 Match m = r.Match(url);
9938 if (m.Success) { 10593 if (m.Success)
9939 for (int i = 1; i < gnums.Length; i++) { 10594 {
10595 for (int i = 1; i < gnums.Length; i++)
10596 {
9940 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10597 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
9941 //CaptureCollection cc = g.Captures; 10598 //CaptureCollection cc = g.Captures;
9942 } 10599 }
9943 if (m.Groups.Count == 5) { 10600 if (m.Groups.Count == 5)
10601 {
9944 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10602 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
9945 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10603 url = m.Groups[1].ToString() + m.Groups[4].ToString();
9946 } 10604 }
@@ -10226,15 +10884,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10226 10884
10227 internal UUID ScriptByName(string name) 10885 internal UUID ScriptByName(string name)
10228 { 10886 {
10229 lock (m_host.TaskInventory) 10887 m_host.TaskInventory.LockItemsForRead(true);
10888
10889 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10230 { 10890 {
10231 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 10891 if (item.Type == 10 && item.Name == name)
10232 { 10892 {
10233 if (item.Type == 10 && item.Name == name) 10893 m_host.TaskInventory.LockItemsForRead(false);
10234 return item.ItemID; 10894 return item.ItemID;
10235 } 10895 }
10236 } 10896 }
10237 10897
10898 m_host.TaskInventory.LockItemsForRead(false);
10899
10238 return UUID.Zero; 10900 return UUID.Zero;
10239 } 10901 }
10240 10902
@@ -10275,6 +10937,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10275 { 10937 {
10276 m_host.AddScriptLPS(1); 10938 m_host.AddScriptLPS(1);
10277 10939
10940 //Clone is thread safe
10278 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 10941 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10279 10942
10280 UUID assetID = UUID.Zero; 10943 UUID assetID = UUID.Zero;
@@ -10337,6 +11000,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10337 { 11000 {
10338 m_host.AddScriptLPS(1); 11001 m_host.AddScriptLPS(1);
10339 11002
11003 //Clone is thread safe
10340 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11004 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10341 11005
10342 UUID assetID = UUID.Zero; 11006 UUID assetID = UUID.Zero;
@@ -10417,15 +11081,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10417 return GetLinkPrimitiveParams(obj, rules); 11081 return GetLinkPrimitiveParams(obj, rules);
10418 } 11082 }
10419 11083
10420 public void print(string str) 11084 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10421 { 11085 {
10422 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11086 List<SceneObjectPart> parts = GetLinkParts(link);
10423 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_itemID, "OSSL"); 11087 if (parts.Count < 1)
10424 if (ossl != null) 11088 return 0;
10425 { 11089
10426 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11090 return GetNumberOfSides(parts[0]);
10427 m_log.Info("LSL print():" + str);
10428 }
10429 } 11091 }
10430 11092
10431 private string Name2Username(string name) 11093 private string Name2Username(string name)
@@ -10471,153 +11133,392 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10471 return rq.ToString(); 11133 return rq.ToString();
10472 } 11134 }
10473 11135
11136 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11137 {
11138 m_SayShoutCount = 0;
11139 }
11140
11141 private struct Tri
11142 {
11143 public Vector3 p1;
11144 public Vector3 p2;
11145 public Vector3 p3;
11146 }
11147
11148 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11149 {
11150 float height = avatar.Appearance.AvatarHeight;
11151 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11152 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11153
11154 if (point.X > b1.X && point.X < b2.X &&
11155 point.Y > b1.Y && point.Y < b2.Y &&
11156 point.Z > b1.Z && point.Z < b2.Z)
11157 return true;
11158 return false;
11159 }
11160
11161 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11162 {
11163 List<ContactResult> contacts = new List<ContactResult>();
11164
11165 Vector3 ab = rayEnd - rayStart;
11166
11167 World.ForEachScenePresence(delegate(ScenePresence sp)
11168 {
11169 Vector3 ac = sp.AbsolutePosition - rayStart;
11170 Vector3 bc = sp.AbsolutePosition - rayEnd;
11171
11172 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11173
11174 if (d > 1.5)
11175 return;
11176
11177 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11178
11179 if (d2 > 0)
11180 return;
11181
11182 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11183 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11184
11185 if (!InBoundingBox(sp, p))
11186 return;
11187
11188 ContactResult result = new ContactResult ();
11189 result.ConsumerID = sp.LocalId;
11190 result.Depth = Vector3.Distance(rayStart, p);
11191 result.Normal = Vector3.Zero;
11192 result.Pos = p;
11193
11194 contacts.Add(result);
11195 });
11196
11197 return contacts.ToArray();
11198 }
11199
11200 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11201 {
11202 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11203 List<ContactResult> contacts = new List<ContactResult>();
11204
11205 Vector3 ab = rayEnd - rayStart;
11206
11207 World.ForEachSOG(delegate(SceneObjectGroup group)
11208 {
11209 if (m_host.ParentGroup == group)
11210 return;
11211
11212 if (group.IsAttachment)
11213 return;
11214
11215 if (group.RootPart.PhysActor == null)
11216 {
11217 if (!includePhantom)
11218 return;
11219 }
11220 else
11221 {
11222 if (group.RootPart.PhysActor.IsPhysical)
11223 {
11224 if (!includePhysical)
11225 return;
11226 }
11227 else
11228 {
11229 if (!includeNonPhysical)
11230 return;
11231 }
11232 }
11233
11234 // Find the radius ouside of which we don't even need to hit test
11235 float minX;
11236 float maxX;
11237 float minY;
11238 float maxY;
11239 float minZ;
11240 float maxZ;
11241
11242 float radius = 0.0f;
11243
11244 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11245
11246 if (Math.Abs(minX) > radius)
11247 radius = Math.Abs(minX);
11248 if (Math.Abs(minY) > radius)
11249 radius = Math.Abs(minY);
11250 if (Math.Abs(minZ) > radius)
11251 radius = Math.Abs(minZ);
11252 if (Math.Abs(maxX) > radius)
11253 radius = Math.Abs(maxX);
11254 if (Math.Abs(maxY) > radius)
11255 radius = Math.Abs(maxY);
11256 if (Math.Abs(maxZ) > radius)
11257 radius = Math.Abs(maxZ);
11258
11259 Vector3 ac = group.AbsolutePosition - rayStart;
11260 Vector3 bc = group.AbsolutePosition - rayEnd;
11261
11262 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11263
11264 // Too far off ray, don't bother
11265 if (d > radius)
11266 return;
11267
11268 // Behind ray, drop
11269 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11270 if (d2 > 0)
11271 return;
11272
11273 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11274 // Miss.
11275 if (!intersection.HitTF)
11276 return;
11277
11278 ContactResult result = new ContactResult ();
11279 result.ConsumerID = group.LocalId;
11280 result.Depth = intersection.distance;
11281 result.Normal = intersection.normal;
11282 result.Pos = intersection.ipoint;
11283
11284 contacts.Add(result);
11285 });
11286
11287 return contacts.ToArray();
11288 }
11289
11290 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11291 {
11292 double[,] heightfield = World.Heightmap.GetDoubles();
11293 List<ContactResult> contacts = new List<ContactResult>();
11294
11295 double min = 2048.0;
11296 double max = 0.0;
11297
11298 // Find the min and max of the heightfield
11299 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11300 {
11301 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11302 {
11303 if (heightfield[x, y] > max)
11304 max = heightfield[x, y];
11305 if (heightfield[x, y] < min)
11306 min = heightfield[x, y];
11307 }
11308 }
11309
11310
11311 // A ray extends past rayEnd, but doesn't go back before
11312 // rayStart. If the start is above the highest point of the ground
11313 // and the ray goes up, we can't hit the ground. Ever.
11314 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11315 return null;
11316
11317 // Same for going down
11318 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11319 return null;
11320
11321 List<Tri> trilist = new List<Tri>();
11322
11323 // Create our triangle list
11324 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11325 {
11326 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11327 {
11328 Tri t1 = new Tri();
11329 Tri t2 = new Tri();
11330
11331 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11332 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11333 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11334 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11335
11336 t1.p1 = p1;
11337 t1.p2 = p2;
11338 t1.p3 = p3;
11339
11340 t2.p1 = p3;
11341 t2.p2 = p4;
11342 t2.p3 = p1;
11343
11344 trilist.Add(t1);
11345 trilist.Add(t2);
11346 }
11347 }
11348
11349 // Ray direction
11350 Vector3 rayDirection = rayEnd - rayStart;
11351
11352 foreach (Tri t in trilist)
11353 {
11354 // Compute triangle plane normal and edges
11355 Vector3 u = t.p2 - t.p1;
11356 Vector3 v = t.p3 - t.p1;
11357 Vector3 n = Vector3.Cross(u, v);
11358
11359 if (n == Vector3.Zero)
11360 continue;
11361
11362 Vector3 w0 = rayStart - t.p1;
11363 double a = -Vector3.Dot(n, w0);
11364 double b = Vector3.Dot(n, rayDirection);
11365
11366 // Not intersecting the plane, or in plane (same thing)
11367 // Ignoring this MAY cause the ground to not be detected
11368 // sometimes
11369 if (Math.Abs(b) < 0.000001)
11370 continue;
11371
11372 double r = a / b;
11373
11374 // ray points away from plane
11375 if (r < 0.0)
11376 continue;
11377
11378 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11379
11380 float uu = Vector3.Dot(u, u);
11381 float uv = Vector3.Dot(u, v);
11382 float vv = Vector3.Dot(v, v);
11383 Vector3 w = ip - t.p1;
11384 float wu = Vector3.Dot(w, u);
11385 float wv = Vector3.Dot(w, v);
11386 float d = uv * uv - uu * vv;
11387
11388 float cs = (uv * wv - vv * wu) / d;
11389 if (cs < 0 || cs > 1.0)
11390 continue;
11391 float ct = (uv * wu - uu * wv) / d;
11392 if (ct < 0 || (cs + ct) > 1.0)
11393 continue;
11394
11395 // Add contact point
11396 ContactResult result = new ContactResult ();
11397 result.ConsumerID = 0;
11398 result.Depth = Vector3.Distance(rayStart, ip);
11399 result.Normal = n;
11400 result.Pos = ip;
11401
11402 contacts.Add(result);
11403 }
11404
11405 if (contacts.Count == 0)
11406 return null;
11407
11408 contacts.Sort(delegate(ContactResult a, ContactResult b)
11409 {
11410 return (int)(a.Depth - b.Depth);
11411 });
11412
11413 return contacts[0];
11414 }
11415
10474 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11416 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10475 { 11417 {
11418 LSL_List list = new LSL_List();
11419
10476 m_host.AddScriptLPS(1); 11420 m_host.AddScriptLPS(1);
10477 11421
10478 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11422 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10479 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11423 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10480 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11424 Vector3 dir = rayEnd - rayStart;
10481 11425
10482 int count = 0; 11426 int count = 1;
10483// int detectPhantom = 0; 11427 bool detectPhantom = false;
10484 int dataFlags = 0; 11428 int dataFlags = 0;
10485 int rejectTypes = 0; 11429 int rejectTypes = 0;
10486 11430
10487 for (int i = 0; i < options.Length; i += 2) 11431 for (int i = 0; i < options.Length; i += 2)
10488 { 11432 {
10489 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11433 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10490 {
10491 count = options.GetLSLIntegerItem(i + 1); 11434 count = options.GetLSLIntegerItem(i + 1);
10492 } 11435 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10493// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11436 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10494// {
10495// detectPhantom = options.GetLSLIntegerItem(i + 1);
10496// }
10497 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11437 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10498 {
10499 dataFlags = options.GetLSLIntegerItem(i + 1); 11438 dataFlags = options.GetLSLIntegerItem(i + 1);
10500 }
10501 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11439 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10502 {
10503 rejectTypes = options.GetLSLIntegerItem(i + 1); 11440 rejectTypes = options.GetLSLIntegerItem(i + 1);
10504 }
10505 } 11441 }
10506 11442
10507 LSL_List list = new LSL_List(); 11443 if (count > 16)
10508 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11444 count = 16;
10509
10510 double distance = Util.GetDistanceTo(startvector, endvector);
10511 11445
10512 if (distance == 0) 11446 List<ContactResult> results = new List<ContactResult>();
10513 distance = 0.001;
10514
10515 Vector3 posToCheck = startvector;
10516 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10517 11447
10518 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11448 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10519 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11449 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10520 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11450 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10521 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11451 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10522 11452
10523 for (float i = 0; i <= distance; i += 0.1f) 11453 if (checkTerrain)
10524 { 11454 {
10525 posToCheck = startvector + (dir * (i / (float)distance)); 11455 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11456 if (groundContact != null)
11457 results.Add((ContactResult)groundContact);
11458 }
10526 11459
10527 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11460 if (checkAgents)
10528 { 11461 {
10529 ContactResult result = new ContactResult(); 11462 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
10530 result.ConsumerID = 0; 11463 foreach (ContactResult r in agentHits)
10531 result.Depth = 0; 11464 results.Add(r);
10532 result.Normal = Vector3.Zero; 11465 }
10533 result.Pos = posToCheck;
10534 results.Add(result);
10535 checkTerrain = false;
10536 }
10537 11466
10538 if (checkAgents) 11467 if (checkPhysical || checkNonPhysical)
10539 { 11468 {
10540 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11469 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
10541 { 11470 foreach (ContactResult r in objectHits)
10542 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X)) 11471 results.Add(r);
10543 {
10544 ContactResult result = new ContactResult ();
10545 result.ConsumerID = sp.LocalId;
10546 result.Depth = 0;
10547 result.Normal = Vector3.Zero;
10548 result.Pos = posToCheck;
10549 results.Add(result);
10550 }
10551 });
10552 }
10553 } 11472 }
10554 11473
10555 int refcount = 0; 11474 results.Sort(delegate(ContactResult a, ContactResult b)
11475 {
11476 return (int)(a.Depth - b.Depth);
11477 });
11478
11479 int values = 0;
10556 foreach (ContactResult result in results) 11480 foreach (ContactResult result in results)
10557 { 11481 {
10558 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) 11482 UUID itemID = UUID.Zero;
10559 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0) 11483 int linkNum = 0;
10560 continue;
10561
10562 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID);
10563 11484
10564 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) 11485 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
10565 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents 11486 // It's a prim!
10566 11487 if (part != null)
10567 if (entity == null)
10568 { 11488 {
10569 list.Add(UUID.Zero); 11489 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10570 11490 itemID = part.ParentGroup.UUID;
10571 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11491 else
10572 list.Add(0); 11492 itemID = part.UUID;
10573
10574 list.Add(result.Pos);
10575
10576 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10577 list.Add(result.Normal);
10578 11493
10579 continue; //Can't find it, so add UUID.Zero 11494 linkNum = part.LinkNum;
10580 } 11495 }
10581 11496 else
10582 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity &&
10583 ((ISceneChildEntity)intersection.obj).PhysActor == null)
10584 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
10585
10586 if (entity is SceneObjectPart)
10587 { 11497 {
10588 if (((SceneObjectPart)entity).PhysActor != null && ((SceneObjectPart)entity).PhysActor.IsPhysical) 11498 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10589 { 11499 /// It it a boy? a girl?
10590 if (!checkPhysical) 11500 if (sp != null)
10591 continue; 11501 itemID = sp.UUID;
10592 }
10593 else
10594 {
10595 if (!checkNonPhysical)
10596 continue;
10597 }
10598 } 11502 }
10599 11503
10600 refcount++; 11504 list.Add(new LSL_String(itemID.ToString()));
10601 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11505 list.Add(new LSL_String(result.Pos.ToString()));
10602 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10603 else
10604 list.Add(entity.UUID);
10605 11506
10606 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11507 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10607 { 11508 list.Add(new LSL_Integer(linkNum));
10608 if (entity is SceneObjectPart)
10609 list.Add(((SceneObjectPart)entity).LinkNum);
10610 else
10611 list.Add(0);
10612 }
10613 11509
10614 list.Add(result.Pos);
10615 11510
10616 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11511 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10617 list.Add(result.Normal); 11512 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11513
11514 values++;
11515 count--;
11516
11517 if (count == 0)
11518 break;
10618 } 11519 }
10619 11520
10620 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11521 list.Add(new LSL_Integer(values));
10621 11522
10622 return list; 11523 return list;
10623 } 11524 }
@@ -10640,22 +11541,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10640 NotImplemented("llGetSPMaxMemory"); 11541 NotImplemented("llGetSPMaxMemory");
10641 } 11542 }
10642 11543
10643 public void llGetUsedMemory() 11544 public virtual LSL_Integer llGetUsedMemory()
10644 { 11545 {
10645 m_host.AddScriptLPS(1); 11546 m_host.AddScriptLPS(1);
10646 NotImplemented("llGetUsedMemory"); 11547 NotImplemented("llGetUsedMemory");
11548 return 0;
10647 } 11549 }
10648 11550
10649 public void llScriptProfiler(LSL_Integer flags) 11551 public void llScriptProfiler(LSL_Integer flags)
10650 { 11552 {
10651 m_host.AddScriptLPS(1); 11553 m_host.AddScriptLPS(1);
10652 NotImplemented("llScriptProfiler"); 11554 //NotImplemented("llScriptProfiler");
10653 } 11555 }
10654 11556
10655 public void llSetSoundQueueing(int queue) 11557 public void llSetSoundQueueing(int queue)
10656 { 11558 {
10657 m_host.AddScriptLPS(1); 11559 m_host.AddScriptLPS(1);
10658 NotImplemented("llSetSoundQueueing");
10659 } 11560 }
10660 11561
10661 public void llCollisionSprite(string impact_sprite) 11562 public void llCollisionSprite(string impact_sprite)
@@ -10667,7 +11568,133 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10667 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 11568 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10668 { 11569 {
10669 m_host.AddScriptLPS(1); 11570 m_host.AddScriptLPS(1);
10670 NotImplemented("llGodLikeRezObject"); 11571
11572 if (!World.Permissions.IsGod(m_host.OwnerID))
11573 NotImplemented("llGodLikeRezObject");
11574
11575 AssetBase rezAsset = World.AssetService.Get(inventory);
11576 if (rezAsset == null)
11577 {
11578 llSay(0, "Asset not found");
11579 return;
11580 }
11581
11582 SceneObjectGroup group = null;
11583
11584 try
11585 {
11586 string xmlData = Utils.BytesToString(rezAsset.Data);
11587 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
11588 }
11589 catch
11590 {
11591 llSay(0, "Asset not found");
11592 return;
11593 }
11594
11595 if (group == null)
11596 {
11597 llSay(0, "Asset not found");
11598 return;
11599 }
11600
11601 group.RootPart.AttachPoint = group.RootPart.Shape.State;
11602 group.RootPart.AttachOffset = group.AbsolutePosition;
11603
11604 group.ResetIDs();
11605
11606 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
11607 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
11608 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
11609 group.ScheduleGroupForFullUpdate();
11610
11611 // objects rezzed with this method are die_at_edge by default.
11612 group.RootPart.SetDieAtEdge(true);
11613
11614 group.ResumeScripts();
11615
11616 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
11617 "object_rez", new Object[] {
11618 new LSL_String(
11619 group.RootPart.UUID.ToString()) },
11620 new DetectParams[0]));
11621 }
11622
11623 public LSL_String llTransferLindenDollars(string destination, int amount)
11624 {
11625 UUID txn = UUID.Random();
11626
11627 Util.FireAndForget(delegate(object x)
11628 {
11629 int replycode = 0;
11630 string replydata = destination + "," + amount.ToString();
11631
11632 try
11633 {
11634 UUID invItemID=InventorySelf();
11635 if (invItemID == UUID.Zero)
11636 {
11637 replydata = "SERVICE_ERROR";
11638 return;
11639 }
11640
11641 m_host.AddScriptLPS(1);
11642
11643 m_host.TaskInventory.LockItemsForRead(true);
11644 TaskInventoryItem item = m_host.TaskInventory[invItemID];
11645 m_host.TaskInventory.LockItemsForRead(false);
11646
11647 if (item.PermsGranter == UUID.Zero)
11648 {
11649 replydata = "MISSING_PERMISSION_DEBIT";
11650 return;
11651 }
11652
11653 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
11654 {
11655 replydata = "MISSING_PERMISSION_DEBIT";
11656 return;
11657 }
11658
11659 UUID toID = new UUID();
11660
11661 if (!UUID.TryParse(destination, out toID))
11662 {
11663 replydata = "INVALID_AGENT";
11664 return;
11665 }
11666
11667 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
11668
11669 if (money == null)
11670 {
11671 replydata = "TRANSFERS_DISABLED";
11672 return;
11673 }
11674
11675 bool result = money.ObjectGiveMoney(
11676 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
11677
11678 if (result)
11679 {
11680 replycode = 1;
11681 return;
11682 }
11683
11684 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
11685 }
11686 finally
11687 {
11688 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
11689 "transaction_result", new Object[] {
11690 new LSL_String(txn.ToString()),
11691 new LSL_Integer(replycode),
11692 new LSL_String(replydata) },
11693 new DetectParams[0]));
11694 }
11695 });
11696
11697 return txn.ToString();
10671 } 11698 }
10672 11699
10673 #endregion 11700 #endregion
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 40d9d6f..78c3fa0 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()
@@ -902,18 +911,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
902 if (target != null) 911 if (target != null)
903 { 912 {
904 UUID animID=UUID.Zero; 913 UUID animID=UUID.Zero;
905 lock (m_host.TaskInventory) 914 m_host.TaskInventory.LockItemsForRead(true);
915 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
906 { 916 {
907 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 917 if (inv.Value.Name == animation)
908 { 918 {
909 if (inv.Value.Name == animation) 919 if (inv.Value.Type == (int)AssetType.Animation)
910 { 920 animID = inv.Value.AssetID;
911 if (inv.Value.Type == (int)AssetType.Animation) 921 continue;
912 animID = inv.Value.AssetID;
913 continue;
914 }
915 } 922 }
916 } 923 }
924 m_host.TaskInventory.LockItemsForRead(false);
917 if (animID == UUID.Zero) 925 if (animID == UUID.Zero)
918 target.Animator.AddAnimation(animation, m_host.UUID); 926 target.Animator.AddAnimation(animation, m_host.UUID);
919 else 927 else
@@ -940,18 +948,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
940 if (target != null) 948 if (target != null)
941 { 949 {
942 UUID animID = UUID.Zero; 950 UUID animID = UUID.Zero;
943 lock (m_host.TaskInventory) 951 m_host.TaskInventory.LockItemsForRead(true);
952 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
944 { 953 {
945 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 954 if (inv.Value.Name == animation)
946 { 955 {
947 if (inv.Value.Name == animation) 956 if (inv.Value.Type == (int)AssetType.Animation)
948 { 957 animID = inv.Value.AssetID;
949 if (inv.Value.Type == (int)AssetType.Animation) 958 continue;
950 animID = inv.Value.AssetID;
951 continue;
952 }
953 } 959 }
954 } 960 }
961 m_host.TaskInventory.LockItemsForRead(false);
955 962
956 if (animID == UUID.Zero) 963 if (animID == UUID.Zero)
957 target.Animator.RemoveAnimation(animation); 964 target.Animator.RemoveAnimation(animation);
@@ -1782,6 +1789,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1782 1789
1783 if (!UUID.TryParse(notecardNameOrUuid, out assetID)) 1790 if (!UUID.TryParse(notecardNameOrUuid, out assetID))
1784 { 1791 {
1792 m_host.TaskInventory.LockItemsForRead(true);
1785 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1793 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1786 { 1794 {
1787 if (item.Type == 7 && item.Name == notecardNameOrUuid) 1795 if (item.Type == 7 && item.Name == notecardNameOrUuid)
@@ -1789,6 +1797,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1789 assetID = item.AssetID; 1797 assetID = item.AssetID;
1790 } 1798 }
1791 } 1799 }
1800 m_host.TaskInventory.LockItemsForRead(false);
1792 } 1801 }
1793 1802
1794 if (assetID == UUID.Zero) 1803 if (assetID == UUID.Zero)
@@ -2091,6 +2100,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2091 2100
2092 private LSL_Key NpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, bool owned) 2101 private LSL_Key NpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, bool owned)
2093 { 2102 {
2103 if (!owned)
2104 OSSLError("Unowned NPCs are unsupported");
2105
2106 string groupTitle = String.Empty;
2107
2108 if (firstname != String.Empty || lastname != String.Empty)
2109 {
2110 if (firstname != "Shown outfit:")
2111 groupTitle = "- NPC -";
2112 }
2113
2094 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2114 INPCModule module = World.RequestModuleInterface<INPCModule>();
2095 if (module != null) 2115 if (module != null)
2096 { 2116 {
@@ -2128,6 +2148,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2128 ownerID, 2148 ownerID,
2129 World,appearance); 2149 World,appearance);
2130 2150
2151 ScenePresence sp;
2152 if (World.TryGetScenePresence(x, out sp))
2153 {
2154 sp.Grouptitle = groupTitle;
2155 sp.SendAvatarDataToAllAgents();
2156 }
2131 return new LSL_Key(x.ToString()); 2157 return new LSL_Key(x.ToString());
2132 } 2158 }
2133 2159
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 }