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.cs3006
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs116
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs32
6 files changed, 2428 insertions, 875 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 993d10f..3cbdde5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -301,6 +301,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
301 return null; 301 return null;
302 } 302 }
303 303
304 public static void StateChange(IScriptEngine engine, uint localID, UUID itemID)
305 {
306 // Remove a specific script
307
308 // Remove dataserver events
309 m_Dataserver[engine].RemoveEvents(localID, itemID);
310
311 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>();
312 if (comms != null)
313 comms.DeleteListener(itemID);
314
315 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>();
316 xmlrpc.DeleteChannels(itemID);
317 xmlrpc.CancelSRDRequests(itemID);
318
319 // Remove Sensors
320 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID);
321
322 }
323
304 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID) 324 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID)
305 { 325 {
306 List<Object> data = new List<Object>(); 326 List<Object> data = new List<Object>();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
new file mode 100644
index 0000000..489c1c6
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
@@ -0,0 +1,118 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using System.Collections;
31using System.Collections.Generic;
32using System.Runtime.Remoting.Lifetime;
33using OpenMetaverse;
34using Nini.Config;
35using OpenSim;
36using OpenSim.Framework;
37using OpenSim.Region.CoreModules.World.LightShare;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Region.ScriptEngine.Shared;
41using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
42using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
43using OpenSim.Region.ScriptEngine.Interfaces;
44using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
45using OpenSim.Services.Interfaces;
46
47using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
48using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
49using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
50using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
51using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
52using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
53using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
54
55namespace OpenSim.Region.ScriptEngine.Shared.Api
56{
57 [Serializable]
58 public class CM_Api : MarshalByRefObject, ICM_Api, IScriptApi
59 {
60 internal IScriptEngine m_ScriptEngine;
61 internal SceneObjectPart m_host;
62 internal uint m_localID;
63 internal UUID m_itemID;
64 internal bool m_CMFunctionsEnabled = false;
65
66 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
67 {
68 m_ScriptEngine = ScriptEngine;
69 m_host = host;
70 m_localID = localID;
71 m_itemID = itemID;
72
73 if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false))
74 m_CMFunctionsEnabled = true;
75 }
76
77 public override Object InitializeLifetimeService()
78 {
79 ILease lease = (ILease)base.InitializeLifetimeService();
80
81 if (lease.CurrentState == LeaseState.Initial)
82 {
83 lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
84 // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
85 // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
86 }
87 return lease;
88 }
89
90 public Scene World
91 {
92 get { return m_ScriptEngine.World; }
93 }
94
95 public string cmDetectedCountry(int number)
96 {
97 m_host.AddScriptLPS(1);
98 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, number);
99 if (detectedParams == null)
100 return String.Empty;
101 return detectedParams.Country;
102 }
103
104 public string cmGetAgentCountry(LSL_Key key)
105 {
106 if (!World.Permissions.IsGod(m_host.OwnerID))
107 return String.Empty;
108
109 UUID uuid;
110
111 if (!UUID.TryParse(key, out uuid))
112 return String.Empty;
113
114 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
115 return account.UserCountry;
116 }
117 }
118}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 704dfc3..9208034 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -28,10 +28,12 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode]
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using System.Text; 33using System.Text;
33using System.Threading; 34using System.Threading;
34using System.Text.RegularExpressions; 35using System.Text.RegularExpressions;
36using System.Timers;
35using Nini.Config; 37using Nini.Config;
36using log4net; 38using log4net;
37using OpenMetaverse; 39using OpenMetaverse;
@@ -44,6 +46,7 @@ using OpenSim.Region.CoreModules.World.Land;
44using OpenSim.Region.CoreModules.World.Terrain; 46using OpenSim.Region.CoreModules.World.Terrain;
45using OpenSim.Region.Framework.Interfaces; 47using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Framework.Scenes.Serialization;
47using OpenSim.Region.Framework.Scenes.Animation; 50using OpenSim.Region.Framework.Scenes.Animation;
48using OpenSim.Region.Physics.Manager; 51using OpenSim.Region.Physics.Manager;
49using OpenSim.Region.ScriptEngine.Shared; 52using OpenSim.Region.ScriptEngine.Shared;
@@ -65,6 +68,7 @@ using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
65using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 68using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
66using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; 69using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
67using System.Reflection; 70using System.Reflection;
71using Timer = System.Timers.Timer;
68 72
69namespace OpenSim.Region.ScriptEngine.Shared.Api 73namespace OpenSim.Region.ScriptEngine.Shared.Api
70{ 74{
@@ -104,16 +108,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
104 protected int m_notecardLineReadCharsMax = 255; 108 protected int m_notecardLineReadCharsMax = 255;
105 protected int m_scriptConsoleChannel = 0; 109 protected int m_scriptConsoleChannel = 0;
106 protected bool m_scriptConsoleChannelEnabled = false; 110 protected bool m_scriptConsoleChannelEnabled = false;
111 protected bool m_debuggerSafe = false;
107 protected IUrlModule m_UrlModule = null; 112 protected IUrlModule m_UrlModule = null;
108 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 113 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
109 new Dictionary<UUID, UserInfoCacheEntry>(); 114 new Dictionary<UUID, UserInfoCacheEntry>();
110 115
116 protected Timer m_ShoutSayTimer;
117 protected int m_SayShoutCount = 0;
118
111 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 119 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
112 { 120 {
121 m_ShoutSayTimer = new Timer(1000);
122 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
123 m_ShoutSayTimer.AutoReset = true;
124 m_ShoutSayTimer.Start();
125
113 m_ScriptEngine = ScriptEngine; 126 m_ScriptEngine = ScriptEngine;
114 m_host = host; 127 m_host = host;
115 m_localID = localID; 128 m_localID = localID;
116 m_itemID = itemID; 129 m_itemID = itemID;
130 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
117 131
118 m_ScriptDelayFactor = 132 m_ScriptDelayFactor =
119 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 133 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
@@ -161,6 +175,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
161 get { return m_ScriptEngine.World; } 175 get { return m_ScriptEngine.World; }
162 } 176 }
163 177
178 [DebuggerNonUserCode]
164 public void state(string newState) 179 public void state(string newState)
165 { 180 {
166 m_ScriptEngine.SetState(m_itemID, newState); 181 m_ScriptEngine.SetState(m_itemID, newState);
@@ -170,6 +185,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
170 /// Reset the named script. The script must be present 185 /// Reset the named script. The script must be present
171 /// in the same prim. 186 /// in the same prim.
172 /// </summary> 187 /// </summary>
188 [DebuggerNonUserCode]
173 public void llResetScript() 189 public void llResetScript()
174 { 190 {
175 m_host.AddScriptLPS(1); 191 m_host.AddScriptLPS(1);
@@ -226,9 +242,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
226 } 242 }
227 } 243 }
228 244
245 public List<ScenePresence> GetLinkAvatars(int linkType)
246 {
247 List<ScenePresence> ret = new List<ScenePresence>();
248 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
249 return ret;
250
251 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
252
253 switch (linkType)
254 {
255 case ScriptBaseClass.LINK_SET:
256 return avs;
257
258 case ScriptBaseClass.LINK_ROOT:
259 return ret;
260
261 case ScriptBaseClass.LINK_ALL_OTHERS:
262 return avs;
263
264 case ScriptBaseClass.LINK_ALL_CHILDREN:
265 return avs;
266
267 case ScriptBaseClass.LINK_THIS:
268 return ret;
269
270 default:
271 if (linkType < 0)
272 return ret;
273
274 int partCount = m_host.ParentGroup.GetPartCount();
275
276 if (linkType <= partCount)
277 {
278 return ret;
279 }
280 else
281 {
282 linkType = linkType - partCount;
283 if (linkType > avs.Count)
284 {
285 return ret;
286 }
287 else
288 {
289 ret.Add(avs[linkType-1]);
290 return ret;
291 }
292 }
293 }
294 }
295
229 public List<SceneObjectPart> GetLinkParts(int linkType) 296 public List<SceneObjectPart> GetLinkParts(int linkType)
230 { 297 {
231 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 298 List<SceneObjectPart> ret = new List<SceneObjectPart>();
299 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
300 return ret;
232 ret.Add(m_host); 301 ret.Add(m_host);
233 302
234 switch (linkType) 303 switch (linkType)
@@ -282,28 +351,46 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
282 /// <returns></returns> 351 /// <returns></returns>
283 protected TaskInventoryItem GetSelfInventoryItem() 352 protected TaskInventoryItem GetSelfInventoryItem()
284 { 353 {
285 lock (m_host.TaskInventory) 354 TaskInventoryItem invItem = null;
286 return m_host.TaskInventory[m_itemID]; 355
356 bool unlock = false;
357 if (!m_host.TaskInventory.IsReadLockedByMe())
358 {
359 m_host.TaskInventory.LockItemsForRead(true);
360 unlock = true;
361 }
362
363 invItem = m_host.TaskInventory[m_itemID];
364
365 if (unlock)
366 {
367 m_host.TaskInventory.LockItemsForRead(false);
368 }
369
370 return invItem;
287 } 371 }
288 372
289 protected UUID InventoryKey(string name, int type) 373 protected UUID InventoryKey(string name, int type)
290 { 374 {
291 m_host.AddScriptLPS(1); 375 m_host.AddScriptLPS(1);
292 376 m_host.TaskInventory.LockItemsForRead(true);
293 lock (m_host.TaskInventory) 377
378 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
294 { 379 {
295 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 380 if (inv.Value.Name == name)
296 { 381 {
297 if (inv.Value.Name == name) 382 m_host.TaskInventory.LockItemsForRead(false);
383
384 if (inv.Value.Type != type)
298 { 385 {
299 if (inv.Value.Type != type) 386 return UUID.Zero;
300 return UUID.Zero;
301
302 return inv.Value.AssetID;
303 } 387 }
388
389 return inv.Value.AssetID;
304 } 390 }
305 } 391 }
306 392
393 m_host.TaskInventory.LockItemsForRead(false);
307 return UUID.Zero; 394 return UUID.Zero;
308 } 395 }
309 396
@@ -311,17 +398,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
311 { 398 {
312 m_host.AddScriptLPS(1); 399 m_host.AddScriptLPS(1);
313 400
314 lock (m_host.TaskInventory) 401
402 m_host.TaskInventory.LockItemsForRead(true);
403
404 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
315 { 405 {
316 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 406 if (inv.Value.Name == name)
317 { 407 {
318 if (inv.Value.Name == name) 408 m_host.TaskInventory.LockItemsForRead(false);
319 { 409 return inv.Value.AssetID;
320 return inv.Value.AssetID;
321 }
322 } 410 }
323 } 411 }
324 412
413 m_host.TaskInventory.LockItemsForRead(false);
414
415
325 return UUID.Zero; 416 return UUID.Zero;
326 } 417 }
327 418
@@ -463,31 +554,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
463 554
464 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 555 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
465 556
466 /// <summary> 557 // Utility function for llRot2Euler
467 /// Convert an LSL rotation to a Euler vector. 558
468 /// </summary> 559 // normalize an angle between -PI and PI (-180 to +180 degrees)
469 /// <remarks> 560 protected double NormalizeAngle(double angle)
470 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
471 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
472 /// </remarks>
473 /// <param name="r"></param>
474 /// <returns></returns>
475 public LSL_Vector llRot2Euler(LSL_Rotation r)
476 { 561 {
477 m_host.AddScriptLPS(1); 562 if (angle > -Math.PI && angle < Math.PI)
563 return angle;
564
565 int numPis = (int)(Math.PI / angle);
566 double remainder = angle - Math.PI * numPis;
567 if (numPis % 2 == 1)
568 return Math.PI - angle;
569 return remainder;
570 }
478 571
479 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 572 public LSL_Vector llRot2Euler(LSL_Rotation q1)
480 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 573 {
481 if (m == 0.0) return new LSL_Vector(); 574 m_host.AddScriptLPS(1);
482 double x = Math.Atan2(-v.y, v.z); 575 LSL_Vector eul = new LSL_Vector();
483 double sin = v.x / m;
484 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities.
485 double y = Math.Asin(sin);
486 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
487 v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0)));
488 double z = Math.Atan2(v.y, v.x);
489 576
490 return new LSL_Vector(x, y, z); 577 double sqw = q1.s*q1.s;
578 double sqx = q1.x*q1.x;
579 double sqy = q1.z*q1.z;
580 double sqz = q1.y*q1.y;
581 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
582 double test = q1.x*q1.z + q1.y*q1.s;
583 if (test > 0.4999*unit) { // singularity at north pole
584 eul.z = 2 * Math.Atan2(q1.x,q1.s);
585 eul.y = Math.PI/2;
586 eul.x = 0;
587 return eul;
588 }
589 if (test < -0.4999*unit) { // singularity at south pole
590 eul.z = -2 * Math.Atan2(q1.x,q1.s);
591 eul.y = -Math.PI/2;
592 eul.x = 0;
593 return eul;
594 }
595 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
596 eul.y = Math.Asin(2*test/unit);
597 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
598 return eul;
491 } 599 }
492 600
493 /* From wiki: 601 /* From wiki:
@@ -689,77 +797,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
689 { 797 {
690 //A and B should both be normalized 798 //A and B should both be normalized
691 m_host.AddScriptLPS(1); 799 m_host.AddScriptLPS(1);
692 LSL_Rotation rotBetween; 800 /* This method is more accurate than the SL one, and thus causes problems
693 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 801 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
694 // continue calculation. 802
695 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 803 double dotProduct = LSL_Vector.Dot(a, b);
804 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
805 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
806 double angle = Math.Acos(dotProduct / magProduct);
807 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
808 double s = Math.Sin(angle / 2);
809
810 double x = axis.x * s;
811 double y = axis.y * s;
812 double z = axis.z * s;
813 double w = Math.Cos(angle / 2);
814
815 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
816 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
817
818 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
819 */
820
821 // This method mimics the 180 errors found in SL
822 // See www.euclideanspace.com... angleBetween
823 LSL_Vector vec_a = a;
824 LSL_Vector vec_b = b;
825
826 // Eliminate zero length
827 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
828 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
829 if (vec_a_mag < 0.00001 ||
830 vec_b_mag < 0.00001)
696 { 831 {
697 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 832 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
698 } 833 }
699 else 834
835 // Normalize
836 vec_a = llVecNorm(vec_a);
837 vec_b = llVecNorm(vec_b);
838
839 // Calculate axis and rotation angle
840 LSL_Vector axis = vec_a % vec_b;
841 LSL_Float cos_theta = vec_a * vec_b;
842
843 // Check if parallel
844 if (cos_theta > 0.99999)
700 { 845 {
701 a = LSL_Vector.Norm(a); 846 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
702 b = LSL_Vector.Norm(b); 847 }
703 double dotProduct = LSL_Vector.Dot(a, b); 848
704 // There are two degenerate cases possible. These are for vectors 180 or 849 // Check if anti-parallel
705 // 0 degrees apart. These have to be detected and handled individually. 850 else if (cos_theta < -0.99999)
706 // 851 {
707 // Check for vectors 180 degrees apart. 852 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
708 // A dot product of -1 would mean the angle between vectors is 180 degrees. 853 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
709 if (dotProduct < -0.9999999f) 854 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
710 { 855 }
711 // First assume X axis is orthogonal to the vectors. 856 else // other rotation
712 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 857 {
713 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 858 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
714 // Check for near zero vector. A very small non-zero number here will create 859 axis = llVecNorm(axis);
715 // a rotation in an undesired direction. 860 double x, y, z, s, t;
716 if (LSL_Vector.Mag(orthoVector) > 0.0001) 861 s = Math.Cos(theta);
717 { 862 t = Math.Sin(theta);
718 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 863 x = axis.x * t;
719 } 864 y = axis.y * t;
720 // If the magnitude of the vector was near zero, then assume the X axis is not 865 z = axis.z * t;
721 // orthogonal and use the Z axis instead. 866 return new LSL_Rotation(x,y,z,s);
722 else
723 {
724 // Set 180 z rotation.
725 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
726 }
727 }
728 // Check for parallel vectors.
729 // A dot product of 1 would mean the angle between vectors is 0 degrees.
730 else if (dotProduct > 0.9999999f)
731 {
732 // Set zero rotation.
733 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
734 }
735 else
736 {
737 // All special checks have been performed so get the axis of rotation.
738 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
739 // Quarternion s value is the length of the unit vector + dot product.
740 double qs = 1.0 + dotProduct;
741 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
742 // Normalize the rotation.
743 double mag = LSL_Rotation.Mag(rotBetween);
744 // We shouldn't have to worry about a divide by zero here. The qs value will be
745 // non-zero because we already know if we're here, then the dotProduct is not -1 so
746 // qs will not be zero. Also, we've already handled the input vectors being zero so the
747 // crossProduct vector should also not be zero.
748 rotBetween.x = rotBetween.x / mag;
749 rotBetween.y = rotBetween.y / mag;
750 rotBetween.z = rotBetween.z / mag;
751 rotBetween.s = rotBetween.s / mag;
752 // Check for undefined values and set zero rotation if any found. This code might not actually be required
753 // any longer since zero vectors are checked for at the top.
754 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
755 {
756 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
757 }
758 }
759 } 867 }
760 return rotBetween;
761 } 868 }
762 869
763 public void llWhisper(int channelID, string text) 870 public void llWhisper(int channelID, string text)
764 { 871 {
765 m_host.AddScriptLPS(1); 872 m_host.AddScriptLPS(1);
@@ -779,6 +886,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
779 { 886 {
780 m_host.AddScriptLPS(1); 887 m_host.AddScriptLPS(1);
781 888
889 if (channelID == 0)
890 m_SayShoutCount++;
891
892 if (m_SayShoutCount >= 11)
893 ScriptSleep(2000);
894
782 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 895 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
783 { 896 {
784 Console.WriteLine(text); 897 Console.WriteLine(text);
@@ -801,6 +914,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
801 { 914 {
802 m_host.AddScriptLPS(1); 915 m_host.AddScriptLPS(1);
803 916
917 if (channelID == 0)
918 m_SayShoutCount++;
919
920 if (m_SayShoutCount >= 11)
921 ScriptSleep(2000);
922
804 if (text.Length > 1023) 923 if (text.Length > 1023)
805 text = text.Substring(0, 1023); 924 text = text.Substring(0, 1023);
806 925
@@ -1103,10 +1222,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1103 return detectedParams.TouchUV; 1222 return detectedParams.TouchUV;
1104 } 1223 }
1105 1224
1225 [DebuggerNonUserCode]
1106 public virtual void llDie() 1226 public virtual void llDie()
1107 { 1227 {
1108 m_host.AddScriptLPS(1); 1228 m_host.AddScriptLPS(1);
1109 throw new SelfDeleteException(); 1229 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1110 } 1230 }
1111 1231
1112 public LSL_Float llGround(LSL_Vector offset) 1232 public LSL_Float llGround(LSL_Vector offset)
@@ -1179,6 +1299,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1179 1299
1180 public void llSetStatus(int status, int value) 1300 public void llSetStatus(int status, int value)
1181 { 1301 {
1302 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1303 return;
1182 m_host.AddScriptLPS(1); 1304 m_host.AddScriptLPS(1);
1183 1305
1184 int statusrotationaxis = 0; 1306 int statusrotationaxis = 0;
@@ -1410,6 +1532,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1410 { 1532 {
1411 m_host.AddScriptLPS(1); 1533 m_host.AddScriptLPS(1);
1412 1534
1535 SetColor(m_host, color, face);
1536 }
1537
1538 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1539 {
1540 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1541 return;
1542
1543 Primitive.TextureEntry tex = part.Shape.Textures;
1544 Color4 texcolor;
1545 if (face >= 0 && face < GetNumberOfSides(part))
1546 {
1547 texcolor = tex.CreateFace((uint)face).RGBA;
1548 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1549 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1550 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1551 tex.FaceTextures[face].RGBA = texcolor;
1552 part.UpdateTextureEntry(tex.GetBytes());
1553 return;
1554 }
1555 else if (face == ScriptBaseClass.ALL_SIDES)
1556 {
1557 for (uint i = 0; i < GetNumberOfSides(part); i++)
1558 {
1559 if (tex.FaceTextures[i] != null)
1560 {
1561 texcolor = tex.FaceTextures[i].RGBA;
1562 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1563 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1564 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1565 tex.FaceTextures[i].RGBA = texcolor;
1566 }
1567 texcolor = tex.DefaultTexture.RGBA;
1568 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1569 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1570 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1571 tex.DefaultTexture.RGBA = texcolor;
1572 }
1573 part.UpdateTextureEntry(tex.GetBytes());
1574 return;
1575 }
1576
1413 if (face == ScriptBaseClass.ALL_SIDES) 1577 if (face == ScriptBaseClass.ALL_SIDES)
1414 face = SceneObjectPart.ALL_SIDES; 1578 face = SceneObjectPart.ALL_SIDES;
1415 1579
@@ -1418,6 +1582,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1418 1582
1419 public void SetTexGen(SceneObjectPart part, int face,int style) 1583 public void SetTexGen(SceneObjectPart part, int face,int style)
1420 { 1584 {
1585 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1586 return;
1587
1421 Primitive.TextureEntry tex = part.Shape.Textures; 1588 Primitive.TextureEntry tex = part.Shape.Textures;
1422 MappingType textype; 1589 MappingType textype;
1423 textype = MappingType.Default; 1590 textype = MappingType.Default;
@@ -1448,6 +1615,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1448 1615
1449 public void SetGlow(SceneObjectPart part, int face, float glow) 1616 public void SetGlow(SceneObjectPart part, int face, float glow)
1450 { 1617 {
1618 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1619 return;
1620
1451 Primitive.TextureEntry tex = part.Shape.Textures; 1621 Primitive.TextureEntry tex = part.Shape.Textures;
1452 if (face >= 0 && face < GetNumberOfSides(part)) 1622 if (face >= 0 && face < GetNumberOfSides(part))
1453 { 1623 {
@@ -1473,6 +1643,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1473 1643
1474 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1644 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1475 { 1645 {
1646 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1647 return;
1476 1648
1477 Shininess sval = new Shininess(); 1649 Shininess sval = new Shininess();
1478 1650
@@ -1523,6 +1695,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1523 1695
1524 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1696 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1525 { 1697 {
1698 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1699 return;
1700
1526 Primitive.TextureEntry tex = part.Shape.Textures; 1701 Primitive.TextureEntry tex = part.Shape.Textures;
1527 if (face >= 0 && face < GetNumberOfSides(part)) 1702 if (face >= 0 && face < GetNumberOfSides(part))
1528 { 1703 {
@@ -1583,13 +1758,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1583 m_host.AddScriptLPS(1); 1758 m_host.AddScriptLPS(1);
1584 1759
1585 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1760 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1586 1761 if (parts.Count > 0)
1587 foreach (SceneObjectPart part in parts) 1762 {
1588 SetAlpha(part, alpha, face); 1763 try
1764 {
1765 parts[0].ParentGroup.areUpdatesSuspended = true;
1766 foreach (SceneObjectPart part in parts)
1767 SetAlpha(part, alpha, face);
1768 }
1769 finally
1770 {
1771 parts[0].ParentGroup.areUpdatesSuspended = false;
1772 }
1773 }
1589 } 1774 }
1590 1775
1591 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1776 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1592 { 1777 {
1778 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1779 return;
1780
1593 Primitive.TextureEntry tex = part.Shape.Textures; 1781 Primitive.TextureEntry tex = part.Shape.Textures;
1594 Color4 texcolor; 1782 Color4 texcolor;
1595 if (face >= 0 && face < GetNumberOfSides(part)) 1783 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1642,7 +1830,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1642 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1830 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1643 float wind, float tension, LSL_Vector Force) 1831 float wind, float tension, LSL_Vector Force)
1644 { 1832 {
1645 if (part == null) 1833 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1646 return; 1834 return;
1647 1835
1648 if (flexi) 1836 if (flexi)
@@ -1676,7 +1864,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1676 /// <param name="falloff"></param> 1864 /// <param name="falloff"></param>
1677 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1865 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1678 { 1866 {
1679 if (part == null) 1867 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1680 return; 1868 return;
1681 1869
1682 if (light) 1870 if (light)
@@ -1754,15 +1942,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1754 m_host.AddScriptLPS(1); 1942 m_host.AddScriptLPS(1);
1755 1943
1756 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1944 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1757 1945 if (parts.Count > 0)
1758 foreach (SceneObjectPart part in parts) 1946 {
1759 SetTexture(part, texture, face); 1947 try
1760 1948 {
1949 parts[0].ParentGroup.areUpdatesSuspended = true;
1950 foreach (SceneObjectPart part in parts)
1951 SetTexture(part, texture, face);
1952 }
1953 finally
1954 {
1955 parts[0].ParentGroup.areUpdatesSuspended = false;
1956 }
1957 }
1761 ScriptSleep(200); 1958 ScriptSleep(200);
1762 } 1959 }
1763 1960
1764 protected void SetTexture(SceneObjectPart part, string texture, int face) 1961 protected void SetTexture(SceneObjectPart part, string texture, int face)
1765 { 1962 {
1963 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1964 return;
1965
1766 UUID textureID = new UUID(); 1966 UUID textureID = new UUID();
1767 1967
1768 textureID = InventoryKey(texture, (int)AssetType.Texture); 1968 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1807,6 +2007,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1807 2007
1808 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 2008 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1809 { 2009 {
2010 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2011 return;
2012
1810 Primitive.TextureEntry tex = part.Shape.Textures; 2013 Primitive.TextureEntry tex = part.Shape.Textures;
1811 if (face >= 0 && face < GetNumberOfSides(part)) 2014 if (face >= 0 && face < GetNumberOfSides(part))
1812 { 2015 {
@@ -1843,6 +2046,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1843 2046
1844 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2047 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1845 { 2048 {
2049 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2050 return;
2051
1846 Primitive.TextureEntry tex = part.Shape.Textures; 2052 Primitive.TextureEntry tex = part.Shape.Textures;
1847 if (face >= 0 && face < GetNumberOfSides(part)) 2053 if (face >= 0 && face < GetNumberOfSides(part))
1848 { 2054 {
@@ -1879,6 +2085,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1879 2085
1880 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2086 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1881 { 2087 {
2088 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2089 return;
2090
1882 Primitive.TextureEntry tex = part.Shape.Textures; 2091 Primitive.TextureEntry tex = part.Shape.Textures;
1883 if (face >= 0 && face < GetNumberOfSides(part)) 2092 if (face >= 0 && face < GetNumberOfSides(part))
1884 { 2093 {
@@ -1983,26 +2192,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1983 return real_vec; 2192 return real_vec;
1984 } 2193 }
1985 2194
2195 public LSL_Integer llSetRegionPos(LSL_Vector pos)
2196 {
2197 return new LSL_Integer(SetRegionPos(m_host, pos));
2198 }
2199
2200 protected int SetRegionPos(SceneObjectPart part, LSL_Vector targetPos)
2201 {
2202 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2203 return 0;
2204
2205 SceneObjectGroup grp = part.ParentGroup;
2206
2207 if (grp.IsAttachment)
2208 return 0;
2209
2210 if (grp.RootPart.PhysActor != null && grp.RootPart.PhysActor.IsPhysical)
2211 return 0;
2212
2213 if (targetPos.x < -10.0f || targetPos.x >= (float)Constants.RegionSize || targetPos.y < -10.0f || targetPos.y >= (float)Constants.RegionSize || targetPos.z < 0 || targetPos.z >= 4096.0f)
2214 return 0;
2215
2216 float constrainedX = (float)targetPos.x;
2217 float constrainedY = (float)targetPos.y;
2218
2219 if (constrainedX < 0.0f)
2220 constrainedX = 0.0f;
2221 if (constrainedY < 0.0f)
2222 constrainedY = 0.0f;
2223 if (constrainedX >= (float)Constants.RegionSize)
2224 constrainedX = (float)Constants.RegionSize - 0.1f;
2225 if (constrainedY >= (float)Constants.RegionSize)
2226 constrainedY = (float)Constants.RegionSize -0.1f;
2227
2228 float ground = World.GetGroundHeight(constrainedX, constrainedY);
2229
2230 if (targetPos.z < ground)
2231 targetPos.z = ground;
2232
2233 Vector3 dest = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z);
2234
2235 if (!World.Permissions.CanObjectEntry(grp.UUID, false, dest))
2236 return 0;
2237
2238 grp.UpdateGroupPosition(dest);
2239
2240 return 1;
2241 }
2242
1986 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2243 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1987 { 2244 {
1988 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2245 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2246 return;
2247
1989 LSL_Vector currentPos = GetPartLocalPos(part); 2248 LSL_Vector currentPos = GetPartLocalPos(part);
2249 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
1990 2250
1991 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
1992 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
1993 2251
1994 if (part.ParentGroup.RootPart == part) 2252 if (part.ParentGroup.RootPart == part)
1995 { 2253 {
1996 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
1997 targetPos.z = ground;
1998 SceneObjectGroup parent = part.ParentGroup; 2254 SceneObjectGroup parent = part.ParentGroup;
1999 LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); 2255 Vector3 dest = 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)); 2256 if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest))
2257 return;
2258 Util.FireAndForget(delegate(object x) {
2259 parent.UpdateGroupPosition(dest);
2260 });
2001 } 2261 }
2002 else 2262 else
2003 { 2263 {
2004 LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); 2264 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; 2265 SceneObjectGroup parent = part.ParentGroup;
2007 parent.HasGroupChanged = true; 2266 parent.HasGroupChanged = true;
2008 parent.ScheduleGroupForTerseUpdate(); 2267 parent.ScheduleGroupForTerseUpdate();
@@ -2035,17 +2294,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2035 else 2294 else
2036 { 2295 {
2037 if (part.ParentGroup.IsAttachment) 2296 if (part.ParentGroup.IsAttachment)
2038 {
2039 pos = part.AttachedPos; 2297 pos = part.AttachedPos;
2040 }
2041 else 2298 else
2042 {
2043 pos = part.AbsolutePosition; 2299 pos = part.AbsolutePosition;
2044 }
2045 } 2300 }
2046 2301
2047// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2048
2049 return new LSL_Vector(pos.X, pos.Y, pos.Z); 2302 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2050 } 2303 }
2051 2304
@@ -2054,9 +2307,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2054 m_host.AddScriptLPS(1); 2307 m_host.AddScriptLPS(1);
2055 2308
2056 // try to let this work as in SL... 2309 // try to let this work as in SL...
2057 if (m_host.ParentID == 0) 2310 if (m_host.LinkNum < 2)
2058 { 2311 {
2059 // special case: If we are root, rotate complete SOG to new rotation 2312 // Special case: If we are root, rotate complete SOG to new
2313 // rotation.
2314 // We are root if the link number is 0 (single prim) or 1
2315 // (root prim). ParentID may be nonzero in attachments and
2316 // using it would cause attachments and HUDs to rotate
2317 // to the wrong positions.
2060 SetRot(m_host, Rot2Quaternion(rot)); 2318 SetRot(m_host, Rot2Quaternion(rot));
2061 } 2319 }
2062 else 2320 else
@@ -2081,6 +2339,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2081 2339
2082 protected void SetRot(SceneObjectPart part, Quaternion rot) 2340 protected void SetRot(SceneObjectPart part, Quaternion rot)
2083 { 2341 {
2342 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2343 return;
2344
2084 part.UpdateRotation(rot); 2345 part.UpdateRotation(rot);
2085 // Update rotation does not move the object in the physics scene if it's a linkset. 2346 // Update rotation does not move the object in the physics scene if it's a linkset.
2086 2347
@@ -2235,13 +2496,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2235 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2496 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2236 { 2497 {
2237 m_host.AddScriptLPS(1); 2498 m_host.AddScriptLPS(1);
2238 m_host.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); 2499 m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
2239 } 2500 }
2240 2501
2241 public void llSetTorque(LSL_Vector torque, int local) 2502 public void llSetTorque(LSL_Vector torque, int local)
2242 { 2503 {
2243 m_host.AddScriptLPS(1); 2504 m_host.AddScriptLPS(1);
2244 m_host.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); 2505 m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0);
2245 } 2506 }
2246 2507
2247 public LSL_Vector llGetTorque() 2508 public LSL_Vector llGetTorque()
@@ -2845,35 +3106,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2845 public void llLookAt(LSL_Vector target, double strength, double damping) 3106 public void llLookAt(LSL_Vector target, double strength, double damping)
2846 { 3107 {
2847 m_host.AddScriptLPS(1); 3108 m_host.AddScriptLPS(1);
2848 // Determine where we are looking from
2849 LSL_Vector from = llGetPos();
2850 3109
2851 // Work out the normalised vector from the source to the target 3110 // Get the normalized vector to the target
2852 LSL_Vector delta = llVecNorm(target - from); 3111 LSL_Vector d1 = llVecNorm(target - llGetPos());
2853 LSL_Vector angle = new LSL_Vector(0,0,0);
2854 3112
2855 // Calculate the yaw 3113 // Get the bearing (yaw)
2856 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3114 LSL_Vector a1 = new LSL_Vector(0,0,0);
2857 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3115 a1.z = llAtan2(d1.y, d1.x);
2858 3116
2859 // Calculate pitch 3117 // Get the elevation (pitch)
2860 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3118 LSL_Vector a2 = new LSL_Vector(0,0,0);
3119 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2861 3120
2862 // we need to convert from a vector describing 3121 LSL_Rotation r1 = llEuler2Rot(a1);
2863 // the angles of rotation in radians into rotation value 3122 LSL_Rotation r2 = llEuler2Rot(a2);
2864 LSL_Rotation rot = llEuler2Rot(angle); 3123 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2865
2866 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2867 // set the rotation of the object, copy that behavior
2868 PhysicsActor pa = m_host.PhysActor;
2869 3124
2870 if (strength == 0 || pa == null || !pa.IsPhysical) 3125 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2871 { 3126 {
2872 llSetRot(rot); 3127 // Do nothing if either value is 0 (this has been checked in SL)
3128 if (strength <= 0.0 || damping <= 0.0)
3129 return;
3130
3131 llSetRot(r3 * r2 * r1);
2873 } 3132 }
2874 else 3133 else
2875 { 3134 {
2876 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3135 if (strength == 0)
3136 {
3137 llSetRot(r3 * r2 * r1);
3138 return;
3139 }
3140
3141 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2877 } 3142 }
2878 } 3143 }
2879 3144
@@ -2918,17 +3183,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2918 } 3183 }
2919 else 3184 else
2920 { 3185 {
2921 if (m_host.IsRoot) 3186 // new SL always returns object mass
2922 { 3187// if (m_host.IsRoot)
3188// {
2923 return m_host.ParentGroup.GetMass(); 3189 return m_host.ParentGroup.GetMass();
2924 } 3190// }
2925 else 3191// else
2926 { 3192// {
2927 return m_host.GetMass(); 3193// return m_host.GetMass();
2928 } 3194// }
2929 } 3195 }
2930 } 3196 }
2931 3197
3198
3199 public LSL_Float llGetMassMKS()
3200 {
3201 return 100f * llGetMass();
3202 }
3203
2932 public void llCollisionFilter(string name, string id, int accept) 3204 public void llCollisionFilter(string name, string id, int accept)
2933 { 3205 {
2934 m_host.AddScriptLPS(1); 3206 m_host.AddScriptLPS(1);
@@ -3039,11 +3311,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3039 { 3311 {
3040 m_host.AddScriptLPS(1); 3312 m_host.AddScriptLPS(1);
3041 3313
3042// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3043// return;
3044
3045 TaskInventoryItem item = GetSelfInventoryItem(); 3314 TaskInventoryItem item = GetSelfInventoryItem();
3046 3315
3316 m_host.TaskInventory.LockItemsForRead(false);
3317
3047 if (item.PermsGranter != m_host.OwnerID) 3318 if (item.PermsGranter != m_host.OwnerID)
3048 return; 3319 return;
3049 3320
@@ -3088,6 +3359,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3088 3359
3089 public void llInstantMessage(string user, string message) 3360 public void llInstantMessage(string user, string message)
3090 { 3361 {
3362 UUID result;
3363 if (!UUID.TryParse(user, out result))
3364 {
3365 ShoutError("An invalid key was passed to llInstantMessage");
3366 ScriptSleep(2000);
3367 return;
3368 }
3369
3370
3091 m_host.AddScriptLPS(1); 3371 m_host.AddScriptLPS(1);
3092 3372
3093 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3373 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3102,14 +3382,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3102 UUID friendTransactionID = UUID.Random(); 3382 UUID friendTransactionID = UUID.Random();
3103 3383
3104 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3384 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3105 3385
3106 GridInstantMessage msg = new GridInstantMessage(); 3386 GridInstantMessage msg = new GridInstantMessage();
3107 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3387 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3108 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3388 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3109 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3389 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3110// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3390// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3111// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3391// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3112 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3392// DateTime dt = DateTime.UtcNow;
3393//
3394// // Ticks from UtcNow, but make it look like local. Evil, huh?
3395// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3396//
3397// try
3398// {
3399// // Convert that to the PST timezone
3400// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3401// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3402// }
3403// catch
3404// {
3405// // No logging here, as it could be VERY spammy
3406// }
3407//
3408// // And make it look local again to fool the unix time util
3409// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3410
3411 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3412
3113 //if (client != null) 3413 //if (client != null)
3114 //{ 3414 //{
3115 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3415 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3123,12 +3423,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3123 msg.message = message.Substring(0, 1024); 3423 msg.message = message.Substring(0, 1024);
3124 else 3424 else
3125 msg.message = message; 3425 msg.message = message;
3126 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3426 msg.dialog = (byte)19; // MessageFromObject
3127 msg.fromGroup = false;// fromGroup; 3427 msg.fromGroup = false;// fromGroup;
3128 msg.offline = (byte)0; //offline; 3428 msg.offline = (byte)0; //offline;
3129 msg.ParentEstateID = 0; //ParentEstateID; 3429 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3130 msg.Position = new Vector3(m_host.AbsolutePosition); 3430 msg.Position = new Vector3(m_host.AbsolutePosition);
3131 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3431 msg.RegionID = World.RegionInfo.RegionID.Guid;
3132 msg.binaryBucket 3432 msg.binaryBucket
3133 = Util.StringToBytes256( 3433 = Util.StringToBytes256(
3134 "{0}/{1}/{2}/{3}", 3434 "{0}/{1}/{2}/{3}",
@@ -3156,7 +3456,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3156 } 3456 }
3157 3457
3158 emailModule.SendEmail(m_host.UUID, address, subject, message); 3458 emailModule.SendEmail(m_host.UUID, address, subject, message);
3159 ScriptSleep(20000); 3459 ScriptSleep(15000);
3160 } 3460 }
3161 3461
3162 public void llGetNextEmail(string address, string subject) 3462 public void llGetNextEmail(string address, string subject)
@@ -3411,15 +3711,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3411 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3711 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3412 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3712 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3413 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3713 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3714 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3414 ScriptBaseClass.PERMISSION_ATTACH; 3715 ScriptBaseClass.PERMISSION_ATTACH;
3415 3716
3416 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3717 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3417 { 3718 {
3418 lock (m_host.TaskInventory) 3719 m_host.TaskInventory.LockItemsForWrite(true);
3419 { 3720 m_host.TaskInventory[m_itemID].PermsGranter = agentID;
3420 m_host.TaskInventory[m_itemID].PermsGranter = agentID; 3721 m_host.TaskInventory[m_itemID].PermsMask = perm;
3421 m_host.TaskInventory[m_itemID].PermsMask = perm; 3722 m_host.TaskInventory.LockItemsForWrite(false);
3422 }
3423 3723
3424 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3724 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3425 "run_time_permissions", new Object[] { 3725 "run_time_permissions", new Object[] {
@@ -3429,28 +3729,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3429 return; 3729 return;
3430 } 3730 }
3431 } 3731 }
3432 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3732 else
3433 { 3733 {
3434 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3734 bool sitting = false;
3435 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3735 if (m_host.SitTargetAvatar == agentID)
3436 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3736 {
3437 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3737 sitting = true;
3438 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3738 }
3739 else
3740 {
3741 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3742 {
3743 if (p.SitTargetAvatar == agentID)
3744 sitting = true;
3745 }
3746 }
3439 3747
3440 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3748 if (sitting)
3441 { 3749 {
3442 lock (m_host.TaskInventory) 3750 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3751 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3752 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3753 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3754 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3755
3756 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3443 { 3757 {
3758 m_host.TaskInventory.LockItemsForWrite(true);
3444 m_host.TaskInventory[m_itemID].PermsGranter = agentID; 3759 m_host.TaskInventory[m_itemID].PermsGranter = agentID;
3445 m_host.TaskInventory[m_itemID].PermsMask = perm; 3760 m_host.TaskInventory[m_itemID].PermsMask = perm;
3446 } 3761 m_host.TaskInventory.LockItemsForWrite(false);
3447 3762
3448 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3763 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3449 "run_time_permissions", new Object[] { 3764 "run_time_permissions", new Object[] {
3450 new LSL_Integer(perm) }, 3765 new LSL_Integer(perm) },
3451 new DetectParams[0])); 3766 new DetectParams[0]));
3452 3767
3453 return; 3768 return;
3769 }
3454 } 3770 }
3455 } 3771 }
3456 3772
@@ -3464,11 +3780,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3464 3780
3465 if (!m_waitingForScriptAnswer) 3781 if (!m_waitingForScriptAnswer)
3466 { 3782 {
3467 lock (m_host.TaskInventory) 3783 m_host.TaskInventory.LockItemsForWrite(true);
3468 { 3784 m_host.TaskInventory[m_itemID].PermsGranter = agentID;
3469 m_host.TaskInventory[m_itemID].PermsGranter = agentID; 3785 m_host.TaskInventory[m_itemID].PermsMask = 0;
3470 m_host.TaskInventory[m_itemID].PermsMask = 0; 3786 m_host.TaskInventory.LockItemsForWrite(false);
3471 }
3472 3787
3473 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3788 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3474 m_waitingForScriptAnswer=true; 3789 m_waitingForScriptAnswer=true;
@@ -3498,11 +3813,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3498 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3813 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3499 llReleaseControls(); 3814 llReleaseControls();
3500 3815
3501 lock (m_host.TaskInventory) 3816 m_host.TaskInventory.LockItemsForWrite(true);
3502 { 3817 m_host.TaskInventory[m_itemID].PermsMask = answer;
3503 m_host.TaskInventory[m_itemID].PermsMask = answer; 3818 m_host.TaskInventory.LockItemsForWrite(false);
3504 } 3819
3505
3506 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( 3820 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
3507 "run_time_permissions", new Object[] { 3821 "run_time_permissions", new Object[] {
3508 new LSL_Integer(answer) }, 3822 new LSL_Integer(answer) },
@@ -3545,14 +3859,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3545 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3859 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3546 { 3860 {
3547 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3861 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3548 3862 if (parts.Count > 0)
3549 foreach (SceneObjectPart part in parts) 3863 {
3550 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3864 try
3865 {
3866 parts[0].ParentGroup.areUpdatesSuspended = true;
3867 foreach (SceneObjectPart part in parts)
3868 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3869 }
3870 finally
3871 {
3872 parts[0].ParentGroup.areUpdatesSuspended = false;
3873 }
3874 }
3551 } 3875 }
3552 3876
3553 public void llCreateLink(string target, int parent) 3877 public void llCreateLink(string target, int parent)
3554 { 3878 {
3555 m_host.AddScriptLPS(1); 3879 m_host.AddScriptLPS(1);
3880
3556 UUID targetID; 3881 UUID targetID;
3557 3882
3558 if (!UUID.TryParse(target, out targetID)) 3883 if (!UUID.TryParse(target, out targetID))
@@ -3660,10 +3985,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3660 // Restructuring Multiple Prims. 3985 // Restructuring Multiple Prims.
3661 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 3986 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3662 parts.Remove(parentPrim.RootPart); 3987 parts.Remove(parentPrim.RootPart);
3663 foreach (SceneObjectPart part in parts) 3988 if (parts.Count > 0)
3664 { 3989 {
3665 parentPrim.DelinkFromGroup(part.LocalId, true); 3990 try
3991 {
3992 parts[0].ParentGroup.areUpdatesSuspended = true;
3993 foreach (SceneObjectPart part in parts)
3994 {
3995 parentPrim.DelinkFromGroup(part.LocalId, true);
3996 }
3997 }
3998 finally
3999 {
4000 parts[0].ParentGroup.areUpdatesSuspended = false;
4001 }
3666 } 4002 }
4003
3667 parentPrim.HasGroupChanged = true; 4004 parentPrim.HasGroupChanged = true;
3668 parentPrim.ScheduleGroupForFullUpdate(); 4005 parentPrim.ScheduleGroupForFullUpdate();
3669 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4006 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3672,12 +4009,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3672 { 4009 {
3673 SceneObjectPart newRoot = parts[0]; 4010 SceneObjectPart newRoot = parts[0];
3674 parts.Remove(newRoot); 4011 parts.Remove(newRoot);
3675 foreach (SceneObjectPart part in parts) 4012
4013 try
3676 { 4014 {
3677 // Required for linking 4015 parts[0].ParentGroup.areUpdatesSuspended = true;
3678 part.ClearUpdateSchedule(); 4016 foreach (SceneObjectPart part in parts)
3679 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4017 {
4018 part.ClearUpdateSchedule();
4019 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4020 }
3680 } 4021 }
4022 finally
4023 {
4024 parts[0].ParentGroup.areUpdatesSuspended = false;
4025 }
4026
4027
3681 newRoot.ParentGroup.HasGroupChanged = true; 4028 newRoot.ParentGroup.HasGroupChanged = true;
3682 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4029 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3683 } 4030 }
@@ -3697,6 +4044,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3697 public void llBreakAllLinks() 4044 public void llBreakAllLinks()
3698 { 4045 {
3699 m_host.AddScriptLPS(1); 4046 m_host.AddScriptLPS(1);
4047
4048 TaskInventoryItem item = GetSelfInventoryItem();
4049
4050 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4051 && !m_automaticLinkPermission)
4052 {
4053 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4054 return;
4055 }
4056
3700 SceneObjectGroup parentPrim = m_host.ParentGroup; 4057 SceneObjectGroup parentPrim = m_host.ParentGroup;
3701 if (parentPrim.AttachmentPoint != 0) 4058 if (parentPrim.AttachmentPoint != 0)
3702 return; // Fail silently if attached 4059 return; // Fail silently if attached
@@ -3716,25 +4073,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3716 public LSL_String llGetLinkKey(int linknum) 4073 public LSL_String llGetLinkKey(int linknum)
3717 { 4074 {
3718 m_host.AddScriptLPS(1); 4075 m_host.AddScriptLPS(1);
3719 List<UUID> keytable = new List<UUID>();
3720 // parse for sitting avatare-uuids
3721 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3722 {
3723 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
3724 keytable.Add(presence.UUID);
3725 });
3726
3727 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3728 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3729 {
3730 return keytable[totalprims - linknum].ToString();
3731 }
3732
3733 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3734 {
3735 return m_host.UUID.ToString();
3736 }
3737
3738 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4076 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3739 if (part != null) 4077 if (part != null)
3740 { 4078 {
@@ -3742,6 +4080,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3742 } 4080 }
3743 else 4081 else
3744 { 4082 {
4083 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4084 {
4085 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4086
4087 if (linknum < 0)
4088 return UUID.Zero.ToString();
4089
4090 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4091 if (avatars.Count > linknum)
4092 {
4093 return avatars[linknum].UUID.ToString();
4094 }
4095 }
3745 return UUID.Zero.ToString(); 4096 return UUID.Zero.ToString();
3746 } 4097 }
3747 } 4098 }
@@ -3841,17 +4192,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3841 m_host.AddScriptLPS(1); 4192 m_host.AddScriptLPS(1);
3842 int count = 0; 4193 int count = 0;
3843 4194
3844 lock (m_host.TaskInventory) 4195 m_host.TaskInventory.LockItemsForRead(true);
4196 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3845 { 4197 {
3846 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4198 if (inv.Value.Type == type || type == -1)
3847 { 4199 {
3848 if (inv.Value.Type == type || type == -1) 4200 count = count + 1;
3849 {
3850 count = count + 1;
3851 }
3852 } 4201 }
3853 } 4202 }
3854 4203
4204 m_host.TaskInventory.LockItemsForRead(false);
3855 return count; 4205 return count;
3856 } 4206 }
3857 4207
@@ -3860,16 +4210,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3860 m_host.AddScriptLPS(1); 4210 m_host.AddScriptLPS(1);
3861 ArrayList keys = new ArrayList(); 4211 ArrayList keys = new ArrayList();
3862 4212
3863 lock (m_host.TaskInventory) 4213 m_host.TaskInventory.LockItemsForRead(true);
4214 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3864 { 4215 {
3865 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4216 if (inv.Value.Type == type || type == -1)
3866 { 4217 {
3867 if (inv.Value.Type == type || type == -1) 4218 keys.Add(inv.Value.Name);
3868 {
3869 keys.Add(inv.Value.Name);
3870 }
3871 } 4219 }
3872 } 4220 }
4221 m_host.TaskInventory.LockItemsForRead(false);
3873 4222
3874 if (keys.Count == 0) 4223 if (keys.Count == 0)
3875 { 4224 {
@@ -3906,25 +4255,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3906 } 4255 }
3907 4256
3908 // move the first object found with this inventory name 4257 // move the first object found with this inventory name
3909 lock (m_host.TaskInventory) 4258 m_host.TaskInventory.LockItemsForRead(true);
4259 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3910 { 4260 {
3911 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4261 if (inv.Value.Name == inventory)
3912 { 4262 {
3913 if (inv.Value.Name == inventory) 4263 found = true;
3914 { 4264 objId = inv.Key;
3915 found = true; 4265 assetType = inv.Value.Type;
3916 objId = inv.Key; 4266 objName = inv.Value.Name;
3917 assetType = inv.Value.Type; 4267 break;
3918 objName = inv.Value.Name;
3919 break;
3920 }
3921 } 4268 }
3922 } 4269 }
4270 m_host.TaskInventory.LockItemsForRead(false);
3923 4271
3924 if (!found) 4272 if (!found)
3925 { 4273 {
3926 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4274 llSay(0, String.Format("Could not find object '{0}'", inventory));
3927 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4275 return;
4276// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3928 } 4277 }
3929 4278
3930 // check if destination is an object 4279 // check if destination is an object
@@ -3950,48 +4299,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3950 return; 4299 return;
3951 } 4300 }
3952 } 4301 }
4302
3953 // destination is an avatar 4303 // destination is an avatar
3954 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4304 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3955 4305
3956 if (agentItem == null) 4306 if (agentItem == null)
3957 return; 4307 return;
3958 4308
3959 byte[] bucket = new byte[17]; 4309 byte[] bucket = new byte[1];
3960 bucket[0] = (byte)assetType; 4310 bucket[0] = (byte)assetType;
3961 byte[] objBytes = agentItem.ID.GetBytes(); 4311 //byte[] objBytes = agentItem.ID.GetBytes();
3962 Array.Copy(objBytes, 0, bucket, 1, 16); 4312 //Array.Copy(objBytes, 0, bucket, 1, 16);
3963 4313
3964 GridInstantMessage msg = new GridInstantMessage(World, 4314 GridInstantMessage msg = new GridInstantMessage(World,
3965 m_host.UUID, m_host.Name+", an object owned by "+ 4315 m_host.OwnerID, m_host.Name, destId,
3966 resolveName(m_host.OwnerID)+",", destId,
3967 (byte)InstantMessageDialog.TaskInventoryOffered, 4316 (byte)InstantMessageDialog.TaskInventoryOffered,
3968 false, objName+"\n"+m_host.Name+" is located at "+ 4317 false, objName+". "+m_host.Name+" is located at "+
3969 World.RegionInfo.RegionName+" "+ 4318 World.RegionInfo.RegionName+" "+
3970 m_host.AbsolutePosition.ToString(), 4319 m_host.AbsolutePosition.ToString(),
3971 agentItem.ID, true, m_host.AbsolutePosition, 4320 agentItem.ID, true, m_host.AbsolutePosition,
3972 bucket); 4321 bucket);
3973 if (m_TransferModule != null) 4322
3974 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4323 ScenePresence sp;
4324
4325 if (World.TryGetScenePresence(destId, out sp))
4326 {
4327 sp.ControllingClient.SendInstantMessage(msg);
4328 }
4329 else
4330 {
4331 if (m_TransferModule != null)
4332 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4333 }
4334
4335 //This delay should only occur when giving inventory to avatars.
3975 ScriptSleep(3000); 4336 ScriptSleep(3000);
3976 } 4337 }
3977 } 4338 }
3978 4339
4340 [DebuggerNonUserCode]
3979 public void llRemoveInventory(string name) 4341 public void llRemoveInventory(string name)
3980 { 4342 {
3981 m_host.AddScriptLPS(1); 4343 m_host.AddScriptLPS(1);
3982 4344
3983 lock (m_host.TaskInventory) 4345 List<TaskInventoryItem> inv;
4346 try
3984 { 4347 {
3985 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4348 m_host.TaskInventory.LockItemsForRead(true);
4349 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4350 }
4351 finally
4352 {
4353 m_host.TaskInventory.LockItemsForRead(false);
4354 }
4355 foreach (TaskInventoryItem item in inv)
4356 {
4357 if (item.Name == name)
3986 { 4358 {
3987 if (item.Name == name) 4359 if (item.ItemID == m_itemID)
3988 { 4360 throw new ScriptDeleteException();
3989 if (item.ItemID == m_itemID) 4361 else
3990 throw new ScriptDeleteException(); 4362 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3991 else 4363 return;
3992 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3993 return;
3994 }
3995 } 4364 }
3996 } 4365 }
3997 } 4366 }
@@ -4026,115 +4395,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4026 { 4395 {
4027 m_host.AddScriptLPS(1); 4396 m_host.AddScriptLPS(1);
4028 4397
4029 UUID uuid = (UUID)id; 4398 UUID uuid;
4030 PresenceInfo pinfo = null; 4399 if (UUID.TryParse(id, out uuid))
4031 UserAccount account;
4032
4033 UserInfoCacheEntry ce;
4034 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4035 { 4400 {
4036 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4401 PresenceInfo pinfo = null;
4037 if (account == null) 4402 UserAccount account;
4403
4404 UserInfoCacheEntry ce;
4405 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4038 { 4406 {
4039 m_userInfoCache[uuid] = null; // Cache negative 4407 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4040 return UUID.Zero.ToString(); 4408 if (account == null)
4041 } 4409 {
4410 m_userInfoCache[uuid] = null; // Cache negative
4411 return UUID.Zero.ToString();
4412 }
4042 4413
4043 4414
4044 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4415 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4045 if (pinfos != null && pinfos.Length > 0) 4416 if (pinfos != null && pinfos.Length > 0)
4046 {
4047 foreach (PresenceInfo p in pinfos)
4048 { 4417 {
4049 if (p.RegionID != UUID.Zero) 4418 foreach (PresenceInfo p in pinfos)
4050 { 4419 {
4051 pinfo = p; 4420 if (p.RegionID != UUID.Zero)
4421 {
4422 pinfo = p;
4423 }
4052 } 4424 }
4053 } 4425 }
4054 }
4055 4426
4056 ce = new UserInfoCacheEntry(); 4427 ce = new UserInfoCacheEntry();
4057 ce.time = Util.EnvironmentTickCount(); 4428 ce.time = Util.EnvironmentTickCount();
4058 ce.account = account; 4429 ce.account = account;
4059 ce.pinfo = pinfo; 4430 ce.pinfo = pinfo;
4060 } 4431 m_userInfoCache[uuid] = ce;
4061 else 4432 }
4062 { 4433 else
4063 if (ce == null) 4434 {
4064 return UUID.Zero.ToString(); 4435 if (ce == null)
4436 return UUID.Zero.ToString();
4065 4437
4066 account = ce.account; 4438 account = ce.account;
4067 pinfo = ce.pinfo; 4439 pinfo = ce.pinfo;
4068 } 4440 }
4069 4441
4070 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4442 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4071 {
4072 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4073 if (pinfos != null && pinfos.Length > 0)
4074 { 4443 {
4075 foreach (PresenceInfo p in pinfos) 4444 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4445 if (pinfos != null && pinfos.Length > 0)
4076 { 4446 {
4077 if (p.RegionID != UUID.Zero) 4447 foreach (PresenceInfo p in pinfos)
4078 { 4448 {
4079 pinfo = p; 4449 if (p.RegionID != UUID.Zero)
4450 {
4451 pinfo = p;
4452 }
4080 } 4453 }
4081 } 4454 }
4082 } 4455 else
4083 else 4456 pinfo = null;
4084 pinfo = null;
4085 4457
4086 ce.time = Util.EnvironmentTickCount(); 4458 ce.time = Util.EnvironmentTickCount();
4087 ce.pinfo = pinfo; 4459 ce.pinfo = pinfo;
4088 } 4460 }
4089 4461
4090 string reply = String.Empty; 4462 string reply = String.Empty;
4091 4463
4092 switch (data) 4464 switch (data)
4093 { 4465 {
4094 case 1: // DATA_ONLINE (0|1) 4466 case 1: // DATA_ONLINE (0|1)
4095 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4467 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4096 reply = "1"; 4468 reply = "1";
4097 else 4469 else
4098 reply = "0"; 4470 reply = "0";
4099 break; 4471 break;
4100 case 2: // DATA_NAME (First Last) 4472 case 2: // DATA_NAME (First Last)
4101 reply = account.FirstName + " " + account.LastName; 4473 reply = account.FirstName + " " + account.LastName;
4102 break; 4474 break;
4103 case 3: // DATA_BORN (YYYY-MM-DD) 4475 case 3: // DATA_BORN (YYYY-MM-DD)
4104 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4476 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4105 born = born.AddSeconds(account.Created); 4477 born = born.AddSeconds(account.Created);
4106 reply = born.ToString("yyyy-MM-dd"); 4478 reply = born.ToString("yyyy-MM-dd");
4107 break; 4479 break;
4108 case 4: // DATA_RATING (0,0,0,0,0,0) 4480 case 4: // DATA_RATING (0,0,0,0,0,0)
4109 reply = "0,0,0,0,0,0"; 4481 reply = "0,0,0,0,0,0";
4110 break; 4482 break;
4111 case 7: // DATA_USERLEVEL (integer) 4483 case 8: // DATA_PAYINFO (0|1|2|3)
4112 reply = account.UserLevel.ToString(); 4484 reply = "0";
4113 break; 4485 break;
4114 case 8: // DATA_PAYINFO (0|1|2|3) 4486 default:
4115 reply = "0"; 4487 return UUID.Zero.ToString(); // Raise no event
4116 break; 4488 }
4117 default:
4118 return UUID.Zero.ToString(); // Raise no event
4119 }
4120 4489
4121 UUID rq = UUID.Random(); 4490 UUID rq = UUID.Random();
4122 4491
4123 UUID tid = AsyncCommands. 4492 UUID tid = AsyncCommands.
4124 DataserverPlugin.RegisterRequest(m_localID, 4493 DataserverPlugin.RegisterRequest(m_localID,
4125 m_itemID, rq.ToString()); 4494 m_itemID, rq.ToString());
4126 4495
4127 AsyncCommands. 4496 AsyncCommands.
4128 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4497 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4129 4498
4130 ScriptSleep(100); 4499 ScriptSleep(100);
4131 return tid.ToString(); 4500 return tid.ToString();
4501 }
4502 else
4503 {
4504 ShoutError("Invalid UUID passed to llRequestAgentData.");
4505 }
4506 return "";
4132 } 4507 }
4133 4508
4134 public LSL_String llRequestInventoryData(string name) 4509 public LSL_String llRequestInventoryData(string name)
4135 { 4510 {
4136 m_host.AddScriptLPS(1); 4511 m_host.AddScriptLPS(1);
4137 4512
4513 //Clone is thread safe
4138 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4514 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4139 4515
4140 foreach (TaskInventoryItem item in itemDictionary.Values) 4516 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4186,19 +4562,64 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4186 if (UUID.TryParse(agent, out agentId)) 4562 if (UUID.TryParse(agent, out agentId))
4187 { 4563 {
4188 ScenePresence presence = World.GetScenePresence(agentId); 4564 ScenePresence presence = World.GetScenePresence(agentId);
4189 if (presence != null) 4565 if (presence != null && presence.PresenceType != PresenceType.Npc)
4190 { 4566 {
4567 // agent must not be a god
4568 if (presence.UserLevel >= 200) return;
4569
4191 // agent must be over the owners land 4570 // agent must be over the owners land
4192 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4571 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4193 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4572 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4194 { 4573 {
4195 World.TeleportClientHome(agentId, presence.ControllingClient); 4574 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4575 {
4576 // They can't be teleported home for some reason
4577 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4578 if (regionInfo != null)
4579 {
4580 World.RequestTeleportLocation(
4581 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4582 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4583 }
4584 }
4196 } 4585 }
4197 } 4586 }
4198 } 4587 }
4199 ScriptSleep(5000); 4588 ScriptSleep(5000);
4200 } 4589 }
4201 4590
4591 public void llTeleportAgent(string agent, string simname, LSL_Vector pos, LSL_Vector lookAt)
4592 {
4593 m_host.AddScriptLPS(1);
4594 UUID agentId = new UUID();
4595 if (UUID.TryParse(agent, out agentId))
4596 {
4597 ScenePresence presence = World.GetScenePresence(agentId);
4598 if (presence != null && presence.PresenceType != PresenceType.Npc)
4599 {
4600 // agent must not be a god
4601 if (presence.GodLevel >= 200) return;
4602
4603 if (simname == String.Empty)
4604 simname = World.RegionInfo.RegionName;
4605
4606 // agent must be over the owners land
4607 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4608 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4609 {
4610 World.RequestTeleportLocation(presence.ControllingClient, simname, new Vector3((float)pos.x, (float)pos.y, (float)pos.z), new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z), (uint)TeleportFlags.ViaLocation);
4611 }
4612 else // or must be wearing the prim
4613 {
4614 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4615 {
4616 World.RequestTeleportLocation(presence.ControllingClient, simname, new Vector3((float)pos.x, (float)pos.y, (float)pos.z), new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z), (uint)TeleportFlags.ViaLocation);
4617 }
4618 }
4619 }
4620 }
4621 }
4622
4202 public void llTextBox(string agent, string message, int chatChannel) 4623 public void llTextBox(string agent, string message, int chatChannel)
4203 { 4624 {
4204 IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); 4625 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
@@ -4210,7 +4631,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4210 UUID av = new UUID(); 4631 UUID av = new UUID();
4211 if (!UUID.TryParse(agent,out av)) 4632 if (!UUID.TryParse(agent,out av))
4212 { 4633 {
4213 LSLError("First parameter to llDialog needs to be a key"); 4634 //LSLError("First parameter to llDialog needs to be a key");
4214 return; 4635 return;
4215 } 4636 }
4216 4637
@@ -4247,17 +4668,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4247 UUID soundId = UUID.Zero; 4668 UUID soundId = UUID.Zero;
4248 if (!UUID.TryParse(impact_sound, out soundId)) 4669 if (!UUID.TryParse(impact_sound, out soundId))
4249 { 4670 {
4250 lock (m_host.TaskInventory) 4671 m_host.TaskInventory.LockItemsForRead(true);
4672 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4251 { 4673 {
4252 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4674 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4253 { 4675 {
4254 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4676 soundId = item.AssetID;
4255 { 4677 break;
4256 soundId = item.AssetID;
4257 break;
4258 }
4259 } 4678 }
4260 } 4679 }
4680 m_host.TaskInventory.LockItemsForRead(false);
4261 } 4681 }
4262 m_host.CollisionSound = soundId; 4682 m_host.CollisionSound = soundId;
4263 m_host.CollisionSoundVolume = (float)impact_volume; 4683 m_host.CollisionSoundVolume = (float)impact_volume;
@@ -4297,6 +4717,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4297 UUID partItemID; 4717 UUID partItemID;
4298 foreach (SceneObjectPart part in parts) 4718 foreach (SceneObjectPart part in parts)
4299 { 4719 {
4720 //Clone is thread safe
4300 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4721 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4301 4722
4302 foreach (TaskInventoryItem item in itemsDictionary.Values) 4723 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4430,7 +4851,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4430 { 4851 {
4431 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4852 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4432 float distance_term = distance * distance * distance; // Script Energy 4853 float distance_term = distance * distance * distance; // Script Energy
4433 float pusher_mass = m_host.GetMass(); 4854 // use total object mass and not part
4855 float pusher_mass = m_host.ParentGroup.GetMass();
4434 4856
4435 float PUSH_ATTENUATION_DISTANCE = 17f; 4857 float PUSH_ATTENUATION_DISTANCE = 17f;
4436 float PUSH_ATTENUATION_SCALE = 5f; 4858 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4671,23 +5093,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4671 { 5093 {
4672 m_host.AddScriptLPS(1); 5094 m_host.AddScriptLPS(1);
4673 5095
4674 lock (m_host.TaskInventory) 5096 m_host.TaskInventory.LockItemsForRead(true);
5097 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4675 { 5098 {
4676 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5099 if (inv.Value.Name == name)
4677 { 5100 {
4678 if (inv.Value.Name == name) 5101 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4679 { 5102 {
4680 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5103 m_host.TaskInventory.LockItemsForRead(false);
4681 { 5104 return inv.Value.AssetID.ToString();
4682 return inv.Value.AssetID.ToString(); 5105 }
4683 } 5106 else
4684 else 5107 {
4685 { 5108 m_host.TaskInventory.LockItemsForRead(false);
4686 return UUID.Zero.ToString(); 5109 return UUID.Zero.ToString();
4687 }
4688 } 5110 }
4689 } 5111 }
4690 } 5112 }
5113 m_host.TaskInventory.LockItemsForRead(false);
4691 5114
4692 return UUID.Zero.ToString(); 5115 return UUID.Zero.ToString();
4693 } 5116 }
@@ -4821,7 +5244,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4821 public LSL_Vector llGetCenterOfMass() 5244 public LSL_Vector llGetCenterOfMass()
4822 { 5245 {
4823 m_host.AddScriptLPS(1); 5246 m_host.AddScriptLPS(1);
4824 Vector3 center = m_host.GetGeometricCenter(); 5247 Vector3 center = m_host.GetCenterOfMass();
4825 return new LSL_Vector(center.X,center.Y,center.Z); 5248 return new LSL_Vector(center.X,center.Y,center.Z);
4826 } 5249 }
4827 5250
@@ -4840,14 +5263,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4840 { 5263 {
4841 m_host.AddScriptLPS(1); 5264 m_host.AddScriptLPS(1);
4842 5265
4843 if (src == null) 5266 return src.Length;
4844 {
4845 return 0;
4846 }
4847 else
4848 {
4849 return src.Length;
4850 }
4851 } 5267 }
4852 5268
4853 public LSL_Integer llList2Integer(LSL_List src, int index) 5269 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4893,7 +5309,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4893 else if (src.Data[index] is LSL_Float) 5309 else if (src.Data[index] is LSL_Float)
4894 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5310 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4895 else if (src.Data[index] is LSL_String) 5311 else if (src.Data[index] is LSL_String)
4896 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5312 {
5313 string str = ((LSL_String) src.Data[index]).m_string;
5314 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5315 if (m != Match.Empty)
5316 {
5317 str = m.Value;
5318 double d = 0.0;
5319 if (!Double.TryParse(str, out d))
5320 return 0.0;
5321
5322 return d;
5323 }
5324 return 0.0;
5325 }
4897 return Convert.ToDouble(src.Data[index]); 5326 return Convert.ToDouble(src.Data[index]);
4898 } 5327 }
4899 catch (FormatException) 5328 catch (FormatException)
@@ -5166,7 +5595,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5166 } 5595 }
5167 } 5596 }
5168 } 5597 }
5169 else { 5598 else
5599 {
5170 object[] array = new object[src.Length]; 5600 object[] array = new object[src.Length];
5171 Array.Copy(src.Data, 0, array, 0, src.Length); 5601 Array.Copy(src.Data, 0, array, 0, src.Length);
5172 result = new LSL_List(array); 5602 result = new LSL_List(array);
@@ -5273,7 +5703,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5273 public LSL_Integer llGetRegionAgentCount() 5703 public LSL_Integer llGetRegionAgentCount()
5274 { 5704 {
5275 m_host.AddScriptLPS(1); 5705 m_host.AddScriptLPS(1);
5276 return new LSL_Integer(World.GetRootAgentCount()); 5706
5707 int count = 0;
5708 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5709 count++;
5710 });
5711
5712 return new LSL_Integer(count);
5277 } 5713 }
5278 5714
5279 public LSL_Vector llGetRegionCorner() 5715 public LSL_Vector llGetRegionCorner()
@@ -5553,6 +5989,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5553 flags |= ScriptBaseClass.AGENT_SITTING; 5989 flags |= ScriptBaseClass.AGENT_SITTING;
5554 } 5990 }
5555 5991
5992 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
5993 {
5994 flags |= ScriptBaseClass.AGENT_MALE;
5995 }
5996
5556 return flags; 5997 return flags;
5557 } 5998 }
5558 5999
@@ -5615,10 +6056,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5615 m_host.AddScriptLPS(1); 6056 m_host.AddScriptLPS(1);
5616 6057
5617 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6058 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5618 6059 if (parts.Count > 0)
5619 foreach (var part in parts)
5620 { 6060 {
5621 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6061 try
6062 {
6063 parts[0].ParentGroup.areUpdatesSuspended = true;
6064 foreach (var part in parts)
6065 {
6066 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6067 }
6068 }
6069 finally
6070 {
6071 parts[0].ParentGroup.areUpdatesSuspended = false;
6072 }
5622 } 6073 }
5623 } 6074 }
5624 6075
@@ -5670,13 +6121,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5670 6121
5671 if (m_host.OwnerID == land.LandData.OwnerID) 6122 if (m_host.OwnerID == land.LandData.OwnerID)
5672 { 6123 {
5673 World.TeleportClientHome(agentID, presence.ControllingClient); 6124 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6125 presence.TeleportWithMomentum(pos, null);
6126 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5674 } 6127 }
5675 } 6128 }
5676 } 6129 }
5677 ScriptSleep(5000); 6130 ScriptSleep(5000);
5678 } 6131 }
5679 6132
6133 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6134 {
6135 return ParseString2List(str, separators, in_spacers, false);
6136 }
6137
5680 public LSL_Integer llOverMyLand(string id) 6138 public LSL_Integer llOverMyLand(string id)
5681 { 6139 {
5682 m_host.AddScriptLPS(1); 6140 m_host.AddScriptLPS(1);
@@ -5741,8 +6199,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5741 UUID agentId = new UUID(); 6199 UUID agentId = new UUID();
5742 if (!UUID.TryParse(agent, out agentId)) 6200 if (!UUID.TryParse(agent, out agentId))
5743 return new LSL_Integer(0); 6201 return new LSL_Integer(0);
6202 if (agentId == m_host.GroupID)
6203 return new LSL_Integer(1);
5744 ScenePresence presence = World.GetScenePresence(agentId); 6204 ScenePresence presence = World.GetScenePresence(agentId);
5745 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6205 if (presence == null || presence.IsChildAgent) // Return false for child agents
5746 return new LSL_Integer(0); 6206 return new LSL_Integer(0);
5747 IClientAPI client = presence.ControllingClient; 6207 IClientAPI client = presence.ControllingClient;
5748 if (m_host.GroupID == client.ActiveGroupId) 6208 if (m_host.GroupID == client.ActiveGroupId)
@@ -5877,7 +6337,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5877 return m_host.ParentGroup.AttachmentPoint; 6337 return m_host.ParentGroup.AttachmentPoint;
5878 } 6338 }
5879 6339
5880 public LSL_Integer llGetFreeMemory() 6340 public virtual LSL_Integer llGetFreeMemory()
5881 { 6341 {
5882 m_host.AddScriptLPS(1); 6342 m_host.AddScriptLPS(1);
5883 // Make scripts designed for LSO happy 6343 // Make scripts designed for LSO happy
@@ -5994,7 +6454,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5994 SetParticleSystem(m_host, rules); 6454 SetParticleSystem(m_host, rules);
5995 } 6455 }
5996 6456
5997 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6457 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6458 {
5998 6459
5999 6460
6000 if (rules.Length == 0) 6461 if (rules.Length == 0)
@@ -6188,14 +6649,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6188 6649
6189 protected UUID GetTaskInventoryItem(string name) 6650 protected UUID GetTaskInventoryItem(string name)
6190 { 6651 {
6191 lock (m_host.TaskInventory) 6652 m_host.TaskInventory.LockItemsForRead(true);
6653 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6192 { 6654 {
6193 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6655 if (inv.Value.Name == name)
6194 { 6656 {
6195 if (inv.Value.Name == name) 6657 m_host.TaskInventory.LockItemsForRead(false);
6196 return inv.Key; 6658 return inv.Key;
6197 } 6659 }
6198 } 6660 }
6661 m_host.TaskInventory.LockItemsForRead(false);
6199 6662
6200 return UUID.Zero; 6663 return UUID.Zero;
6201 } 6664 }
@@ -6233,16 +6696,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6233 if (folderID == UUID.Zero) 6696 if (folderID == UUID.Zero)
6234 return; 6697 return;
6235 6698
6236 byte[] bucket = new byte[17]; 6699 byte[] bucket = new byte[1];
6237 bucket[0] = (byte)AssetType.Folder; 6700 bucket[0] = (byte)AssetType.Folder;
6238 byte[] objBytes = folderID.GetBytes(); 6701 //byte[] objBytes = folderID.GetBytes();
6239 Array.Copy(objBytes, 0, bucket, 1, 16); 6702 //Array.Copy(objBytes, 0, bucket, 1, 16);
6240 6703
6241 GridInstantMessage msg = new GridInstantMessage(World, 6704 GridInstantMessage msg = new GridInstantMessage(World,
6242 m_host.UUID, m_host.Name+", an object owned by "+ 6705 m_host.OwnerID, m_host.Name, destID,
6243 resolveName(m_host.OwnerID)+",", destID, 6706 (byte)InstantMessageDialog.TaskInventoryOffered,
6244 (byte)InstantMessageDialog.InventoryOffered, 6707 false, category+". "+m_host.Name+" is located at "+
6245 false, category+"\n"+m_host.Name+" is located at "+
6246 World.RegionInfo.RegionName+" "+ 6708 World.RegionInfo.RegionName+" "+
6247 m_host.AbsolutePosition.ToString(), 6709 m_host.AbsolutePosition.ToString(),
6248 folderID, true, m_host.AbsolutePosition, 6710 folderID, true, m_host.AbsolutePosition,
@@ -6480,13 +6942,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6480 UUID av = new UUID(); 6942 UUID av = new UUID();
6481 if (!UUID.TryParse(avatar,out av)) 6943 if (!UUID.TryParse(avatar,out av))
6482 { 6944 {
6483 LSLError("First parameter to llDialog needs to be a key"); 6945 //LSLError("First parameter to llDialog needs to be a key");
6484 return; 6946 return;
6485 } 6947 }
6486 if (buttons.Length < 1) 6948 if (buttons.Length < 1)
6487 { 6949 {
6488 LSLError("No less than 1 button can be shown"); 6950 buttons.Add("OK");
6489 return;
6490 } 6951 }
6491 if (buttons.Length > 12) 6952 if (buttons.Length > 12)
6492 { 6953 {
@@ -6503,7 +6964,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6503 } 6964 }
6504 if (buttons.Data[i].ToString().Length > 24) 6965 if (buttons.Data[i].ToString().Length > 24)
6505 { 6966 {
6506 LSLError("button label cannot be longer than 24 characters"); 6967 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6507 return; 6968 return;
6508 } 6969 }
6509 buts[i] = buttons.Data[i].ToString(); 6970 buts[i] = buttons.Data[i].ToString();
@@ -6562,22 +7023,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6562 } 7023 }
6563 7024
6564 // copy the first script found with this inventory name 7025 // copy the first script found with this inventory name
6565 lock (m_host.TaskInventory) 7026 TaskInventoryItem scriptItem = null;
7027 m_host.TaskInventory.LockItemsForRead(true);
7028 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6566 { 7029 {
6567 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 7030 if (inv.Value.Name == name)
6568 { 7031 {
6569 if (inv.Value.Name == name) 7032 // make sure the object is a script
7033 if (10 == inv.Value.Type)
6570 { 7034 {
6571 // make sure the object is a script 7035 found = true;
6572 if (10 == inv.Value.Type) 7036 srcId = inv.Key;
6573 { 7037 scriptItem = inv.Value;
6574 found = true; 7038 break;
6575 srcId = inv.Key;
6576 break;
6577 }
6578 } 7039 }
6579 } 7040 }
6580 } 7041 }
7042 m_host.TaskInventory.LockItemsForRead(false);
6581 7043
6582 if (!found) 7044 if (!found)
6583 { 7045 {
@@ -6585,9 +7047,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6585 return; 7047 return;
6586 } 7048 }
6587 7049
6588 // the rest of the permission checks are done in RezScript, so check the pin there as well 7050 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6589 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7051 if (dest != null)
7052 {
7053 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7054 {
7055 // the rest of the permission checks are done in RezScript, so check the pin there as well
7056 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6590 7057
7058 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7059 m_host.Inventory.RemoveInventoryItem(srcId);
7060 }
7061 }
6591 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7062 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6592 ScriptSleep(3000); 7063 ScriptSleep(3000);
6593 } 7064 }
@@ -6650,19 +7121,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6650 public LSL_String llMD5String(string src, int nonce) 7121 public LSL_String llMD5String(string src, int nonce)
6651 { 7122 {
6652 m_host.AddScriptLPS(1); 7123 m_host.AddScriptLPS(1);
6653 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7124 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6654 } 7125 }
6655 7126
6656 public LSL_String llSHA1String(string src) 7127 public LSL_String llSHA1String(string src)
6657 { 7128 {
6658 m_host.AddScriptLPS(1); 7129 m_host.AddScriptLPS(1);
6659 return Util.SHA1Hash(src).ToLower(); 7130 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6660 } 7131 }
6661 7132
6662 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7133 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6663 { 7134 {
6664 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7135 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6665 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7136 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7137 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7138 return shapeBlock;
6666 7139
6667 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7140 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6668 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7141 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6767,6 +7240,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6767 // Prim type box, cylinder and prism. 7240 // Prim type box, cylinder and prism.
6768 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) 7241 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)
6769 { 7242 {
7243 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7244 return;
7245
6770 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7246 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6771 ObjectShapePacket.ObjectDataBlock shapeBlock; 7247 ObjectShapePacket.ObjectDataBlock shapeBlock;
6772 7248
@@ -6820,6 +7296,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6820 // Prim type sphere. 7296 // Prim type sphere.
6821 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7297 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6822 { 7298 {
7299 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7300 return;
7301
6823 ObjectShapePacket.ObjectDataBlock shapeBlock; 7302 ObjectShapePacket.ObjectDataBlock shapeBlock;
6824 7303
6825 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7304 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6861,6 +7340,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6861 // Prim type torus, tube and ring. 7340 // Prim type torus, tube and ring.
6862 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) 7341 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)
6863 { 7342 {
7343 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7344 return;
7345
6864 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7346 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6865 ObjectShapePacket.ObjectDataBlock shapeBlock; 7347 ObjectShapePacket.ObjectDataBlock shapeBlock;
6866 7348
@@ -6996,6 +7478,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6996 // Prim type sculpt. 7478 // Prim type sculpt.
6997 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7479 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
6998 { 7480 {
7481 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7482 return;
7483
6999 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7484 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7000 UUID sculptId; 7485 UUID sculptId;
7001 7486
@@ -7020,7 +7505,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7020 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7505 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7021 { 7506 {
7022 // default 7507 // default
7023 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7508 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7024 } 7509 }
7025 7510
7026 part.Shape.SetSculptProperties((byte)type, sculptId); 7511 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7036,32 +7521,149 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7036 ScriptSleep(200); 7521 ScriptSleep(200);
7037 } 7522 }
7038 7523
7039 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7524 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7040 { 7525 {
7041 m_host.AddScriptLPS(1); 7526 m_host.AddScriptLPS(1);
7042 7527
7043 setLinkPrimParams(linknumber, rules); 7528 setLinkPrimParams(linknumber, rules);
7529 }
7044 7530
7045 ScriptSleep(200); 7531 private void setLinkPrimParams(int linknumber, LSL_List rules)
7532 {
7533 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7534 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7535 if (parts.Count>0)
7536 {
7537 try
7538 {
7539 parts[0].ParentGroup.areUpdatesSuspended = true;
7540 foreach (SceneObjectPart part in parts)
7541 SetPrimParams(part, rules);
7542 }
7543 finally
7544 {
7545 parts[0].ParentGroup.areUpdatesSuspended = false;
7546 }
7547 }
7548 if (avatars.Count > 0)
7549 {
7550 foreach (ScenePresence avatar in avatars)
7551 SetPrimParams(avatar, rules);
7552 }
7046 } 7553 }
7047 7554
7048 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7555 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7556 float material_density, float material_friction,
7557 float material_restitution, float material_gravity_modifier)
7049 { 7558 {
7050 m_host.AddScriptLPS(1); 7559 ExtraPhysicsData physdata = new ExtraPhysicsData();
7560 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7561 physdata.Density = part.Density;
7562 physdata.Friction = part.Friction;
7563 physdata.Bounce = part.Bounciness;
7564 physdata.GravitationModifier = part.GravityModifier;
7051 7565
7052 setLinkPrimParams(linknumber, rules); 7566 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7567 physdata.Density = material_density;
7568 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7569 physdata.Friction = material_friction;
7570 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7571 physdata.Bounce = material_restitution;
7572 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7573 physdata.GravitationModifier = material_gravity_modifier;
7574
7575 part.UpdateExtraPhysics(physdata);
7053 } 7576 }
7054 7577
7055 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7578 public void llSetPhysicsMaterial(int material_bits,
7579 float material_gravity_modifier, float material_restitution,
7580 float material_friction, float material_density)
7056 { 7581 {
7057 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7582 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7583 }
7058 7584
7059 foreach (SceneObjectPart part in parts) 7585 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7060 SetPrimParams(part, rules); 7586 {
7587 llSetLinkPrimitiveParamsFast(linknumber, rules);
7588 ScriptSleep(200);
7589 }
7590
7591 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7592 {
7593 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7594 //We only support PRIM_POSITION and PRIM_ROTATION
7595
7596 int idx = 0;
7597
7598 while (idx < rules.Length)
7599 {
7600 int code = rules.GetLSLIntegerItem(idx++);
7601
7602 int remain = rules.Length - idx;
7603
7604 switch (code)
7605 {
7606 case (int)ScriptBaseClass.PRIM_POSITION:
7607 {
7608 if (remain < 1)
7609 return;
7610 LSL_Vector v;
7611 v = rules.GetVector3Item(idx++);
7612
7613 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7614 if (part == null)
7615 break;
7616
7617 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7618 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7619 if (llGetLinkNumber() > 1)
7620 {
7621 localRot = llGetLocalRot();
7622 localPos = llGetLocalPos();
7623 }
7624
7625 v -= localPos;
7626 v /= localRot;
7627
7628 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
7629
7630 v = v + 2 * sitOffset;
7631
7632 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7633 av.SendAvatarDataToAllAgents();
7634
7635 }
7636 break;
7637
7638 case (int)ScriptBaseClass.PRIM_ROTATION:
7639 {
7640 if (remain < 1)
7641 return;
7642
7643 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7644 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7645 if (llGetLinkNumber() > 1)
7646 {
7647 localRot = llGetLocalRot();
7648 localPos = llGetLocalPos();
7649 }
7650
7651 LSL_Rotation r;
7652 r = rules.GetQuaternionItem(idx++);
7653 r = r * llGetRootRotation() / localRot;
7654 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7655 av.SendAvatarDataToAllAgents();
7656 }
7657 break;
7658 }
7659 }
7061 } 7660 }
7062 7661
7063 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7662 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7064 { 7663 {
7664 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7665 return;
7666
7065 int idx = 0; 7667 int idx = 0;
7066 7668
7067 bool positionChanged = false; 7669 bool positionChanged = false;
@@ -7383,6 +7985,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7383 part.ScriptSetPhysicsStatus(physics); 7985 part.ScriptSetPhysicsStatus(physics);
7384 break; 7986 break;
7385 7987
7988 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
7989 if (remain < 1)
7990 return;
7991
7992 int shape_type = rules.GetLSLIntegerItem(idx++);
7993
7994 ExtraPhysicsData physdata = new ExtraPhysicsData();
7995 physdata.Density = part.Density;
7996 physdata.Bounce = part.Bounciness;
7997 physdata.GravitationModifier = part.GravityModifier;
7998 physdata.PhysShapeType = (PhysShapeType)shape_type;
7999
8000 part.UpdateExtraPhysics(physdata);
8001
8002 break;
8003
8004 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8005 if (remain < 5)
8006 return;
8007
8008 int material_bits = rules.GetLSLIntegerItem(idx++);
8009 float material_density = (float)rules.GetLSLFloatItem(idx++);
8010 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8011 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8012 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8013
8014 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8015
8016 break;
8017
7386 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8018 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7387 if (remain < 1) 8019 if (remain < 1)
7388 return; 8020 return;
@@ -7456,7 +8088,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7456 if (part.ParentGroup.RootPart == part) 8088 if (part.ParentGroup.RootPart == part)
7457 { 8089 {
7458 SceneObjectGroup parent = part.ParentGroup; 8090 SceneObjectGroup parent = part.ParentGroup;
7459 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8091 Util.FireAndForget(delegate(object x) {
8092 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8093 });
7460 } 8094 }
7461 else 8095 else
7462 { 8096 {
@@ -7467,6 +8101,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7467 } 8101 }
7468 } 8102 }
7469 } 8103 }
8104
8105 if (positionChanged)
8106 {
8107 if (part.ParentGroup.RootPart == part)
8108 {
8109 SceneObjectGroup parent = part.ParentGroup;
8110 Util.FireAndForget(delegate(object x) {
8111 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8112 });
8113 }
8114 else
8115 {
8116 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8117 SceneObjectGroup parent = part.ParentGroup;
8118 parent.HasGroupChanged = true;
8119 parent.ScheduleGroupForTerseUpdate();
8120 }
8121 }
7470 } 8122 }
7471 8123
7472 public LSL_String llStringToBase64(string str) 8124 public LSL_String llStringToBase64(string str)
@@ -7627,13 +8279,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7627 public LSL_Integer llGetNumberOfPrims() 8279 public LSL_Integer llGetNumberOfPrims()
7628 { 8280 {
7629 m_host.AddScriptLPS(1); 8281 m_host.AddScriptLPS(1);
7630 int avatarCount = 0; 8282 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7631 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8283
7632 {
7633 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
7634 avatarCount++;
7635 });
7636
7637 return m_host.ParentGroup.PrimCount + avatarCount; 8284 return m_host.ParentGroup.PrimCount + avatarCount;
7638 } 8285 }
7639 8286
@@ -7649,55 +8296,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7649 m_host.AddScriptLPS(1); 8296 m_host.AddScriptLPS(1);
7650 UUID objID = UUID.Zero; 8297 UUID objID = UUID.Zero;
7651 LSL_List result = new LSL_List(); 8298 LSL_List result = new LSL_List();
8299
8300 // If the ID is not valid, return null result
7652 if (!UUID.TryParse(obj, out objID)) 8301 if (!UUID.TryParse(obj, out objID))
7653 { 8302 {
7654 result.Add(new LSL_Vector()); 8303 result.Add(new LSL_Vector());
7655 result.Add(new LSL_Vector()); 8304 result.Add(new LSL_Vector());
7656 return result; 8305 return result;
7657 } 8306 }
8307
8308 // Check if this is an attached prim. If so, replace
8309 // the UUID with the avatar UUID and report it's bounding box
8310 SceneObjectPart part = World.GetSceneObjectPart(objID);
8311 if (part != null && part.ParentGroup.IsAttachment)
8312 objID = part.ParentGroup.AttachedAvatar;
8313
8314 // Find out if this is an avatar ID. If so, return it's box
7658 ScenePresence presence = World.GetScenePresence(objID); 8315 ScenePresence presence = World.GetScenePresence(objID);
7659 if (presence != null) 8316 if (presence != null)
7660 { 8317 {
7661 if (presence.ParentID == 0) // not sat on an object 8318 // As per LSL Wiki, there is no difference between sitting
8319 // and standing avatar since server 1.36
8320 LSL_Vector lower;
8321 LSL_Vector upper;
8322 if (presence.Animator.Animations.DefaultAnimation.AnimID
8323 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7662 { 8324 {
7663 LSL_Vector lower; 8325 // This is for ground sitting avatars
7664 LSL_Vector upper; 8326 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7665 if (presence.Animator.Animations.DefaultAnimation.AnimID 8327 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7666 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8328 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7667 {
7668 // This is for ground sitting avatars
7669 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7670 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7671 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7672 }
7673 else
7674 {
7675 // This is for standing/flying avatars
7676 float height = presence.Appearance.AvatarHeight / 2.0f;
7677 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7678 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7679 }
7680 result.Add(lower);
7681 result.Add(upper);
7682 return result;
7683 } 8329 }
7684 else 8330 else
7685 { 8331 {
7686 // sitting on an object so we need the bounding box of that 8332 // This is for standing/flying avatars
7687 // which should include the avatar so set the UUID to the 8333 float height = presence.Appearance.AvatarHeight / 2.0f;
7688 // UUID of the object the avatar is sat on and allow it to fall through 8334 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7689 // to processing an object 8335 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7690 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7691 objID = p.UUID;
7692 } 8336 }
8337
8338 // Adjust to the documented error offsets (see LSL Wiki)
8339 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8340 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8341
8342 if (lower.x > upper.x)
8343 lower.x = upper.x;
8344 if (lower.y > upper.y)
8345 lower.y = upper.y;
8346 if (lower.z > upper.z)
8347 lower.z = upper.z;
8348
8349 result.Add(lower);
8350 result.Add(upper);
8351 return result;
7693 } 8352 }
7694 SceneObjectPart part = World.GetSceneObjectPart(objID); 8353
8354 part = World.GetSceneObjectPart(objID);
7695 // Currently only works for single prims without a sitting avatar 8355 // Currently only works for single prims without a sitting avatar
7696 if (part != null) 8356 if (part != null)
7697 { 8357 {
7698 Vector3 halfSize = part.Scale / 2.0f; 8358 float minX;
7699 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8359 float maxX;
7700 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8360 float minY;
8361 float maxY;
8362 float minZ;
8363 float maxZ;
8364
8365 // This BBox is in sim coordinates, with the offset being
8366 // a contained point.
8367 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8368 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8369
8370 minX -= offsets[0].X;
8371 maxX -= offsets[0].X;
8372 minY -= offsets[0].Y;
8373 maxY -= offsets[0].Y;
8374 minZ -= offsets[0].Z;
8375 maxZ -= offsets[0].Z;
8376
8377 LSL_Vector lower;
8378 LSL_Vector upper;
8379
8380 // Adjust to the documented error offsets (see LSL Wiki)
8381 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8382 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8383
8384 if (lower.x > upper.x)
8385 lower.x = upper.x;
8386 if (lower.y > upper.y)
8387 lower.y = upper.y;
8388 if (lower.z > upper.z)
8389 lower.z = upper.z;
8390
7701 result.Add(lower); 8391 result.Add(lower);
7702 result.Add(upper); 8392 result.Add(upper);
7703 return result; 8393 return result;
@@ -7711,7 +8401,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7711 8401
7712 public LSL_Vector llGetGeometricCenter() 8402 public LSL_Vector llGetGeometricCenter()
7713 { 8403 {
7714 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 8404 Vector3 tmp = m_host.GetGeometricCenter();
8405 return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
7715 } 8406 }
7716 8407
7717 public LSL_List llGetPrimitiveParams(LSL_List rules) 8408 public LSL_List llGetPrimitiveParams(LSL_List rules)
@@ -7777,13 +8468,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7777 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8468 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7778 part.AbsolutePosition.Y, 8469 part.AbsolutePosition.Y,
7779 part.AbsolutePosition.Z); 8470 part.AbsolutePosition.Z);
7780 // For some reason, the part.AbsolutePosition.* values do not change if the
7781 // linkset is rotated; they always reflect the child prim's world position
7782 // as though the linkset is unrotated. This is incompatible behavior with SL's
7783 // implementation, so will break scripts imported from there (not to mention it
7784 // makes it more difficult to determine a child prim's actual inworld position).
7785 if (part.ParentID != 0)
7786 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7787 res.Add(v); 8471 res.Add(v);
7788 break; 8472 break;
7789 8473
@@ -7954,56 +8638,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7954 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8638 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7955 if (remain < 1) 8639 if (remain < 1)
7956 return res; 8640 return res;
7957 8641 face = (int)rules.GetLSLIntegerItem(idx++);
7958 face=(int)rules.GetLSLIntegerItem(idx++);
7959 8642
7960 tex = part.Shape.Textures; 8643 tex = part.Shape.Textures;
8644 int shiny;
7961 if (face == ScriptBaseClass.ALL_SIDES) 8645 if (face == ScriptBaseClass.ALL_SIDES)
7962 { 8646 {
7963 for (face = 0; face < GetNumberOfSides(part); face++) 8647 for (face = 0; face < GetNumberOfSides(part); face++)
7964 { 8648 {
7965 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8649 Shininess shinyness = tex.GetFace((uint)face).Shiny;
7966 // Convert Shininess to PRIM_SHINY_* 8650 if (shinyness == Shininess.High)
7967 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8651 {
7968 // PRIM_BUMP_* 8652 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7969 res.Add(new LSL_Integer((int)texface.Bump)); 8653 }
8654 else if (shinyness == Shininess.Medium)
8655 {
8656 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8657 }
8658 else if (shinyness == Shininess.Low)
8659 {
8660 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8661 }
8662 else
8663 {
8664 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8665 }
8666 res.Add(new LSL_Integer(shiny));
8667 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7970 } 8668 }
7971 } 8669 }
7972 else 8670 else
7973 { 8671 {
7974 if (face >= 0 && face < GetNumberOfSides(part)) 8672 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8673 if (shinyness == Shininess.High)
7975 { 8674 {
7976 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8675 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
7977 // Convert Shininess to PRIM_SHINY_* 8676 }
7978 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8677 else if (shinyness == Shininess.Medium)
7979 // PRIM_BUMP_* 8678 {
7980 res.Add(new LSL_Integer((int)texface.Bump)); 8679 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8680 }
8681 else if (shinyness == Shininess.Low)
8682 {
8683 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8684 }
8685 else
8686 {
8687 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
7981 } 8688 }
8689 res.Add(new LSL_Integer(shiny));
8690 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
7982 } 8691 }
7983 break; 8692 break;
7984 8693
7985 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8694 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
7986 if (remain < 1) 8695 if (remain < 1)
7987 return res; 8696 return res;
7988 8697 face = (int)rules.GetLSLIntegerItem(idx++);
7989 face=(int)rules.GetLSLIntegerItem(idx++);
7990 8698
7991 tex = part.Shape.Textures; 8699 tex = part.Shape.Textures;
8700 int fullbright;
7992 if (face == ScriptBaseClass.ALL_SIDES) 8701 if (face == ScriptBaseClass.ALL_SIDES)
7993 { 8702 {
7994 for (face = 0; face < GetNumberOfSides(part); face++) 8703 for (face = 0; face < GetNumberOfSides(part); face++)
7995 { 8704 {
7996 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8705 if (tex.GetFace((uint)face).Fullbright == true)
7997 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8706 {
8707 fullbright = ScriptBaseClass.TRUE;
8708 }
8709 else
8710 {
8711 fullbright = ScriptBaseClass.FALSE;
8712 }
8713 res.Add(new LSL_Integer(fullbright));
7998 } 8714 }
7999 } 8715 }
8000 else 8716 else
8001 { 8717 {
8002 if (face >= 0 && face < GetNumberOfSides(part)) 8718 if (tex.GetFace((uint)face).Fullbright == true)
8003 { 8719 {
8004 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8720 fullbright = ScriptBaseClass.TRUE;
8005 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
8006 } 8721 }
8722 else
8723 {
8724 fullbright = ScriptBaseClass.FALSE;
8725 }
8726 res.Add(new LSL_Integer(fullbright));
8007 } 8727 }
8008 break; 8728 break;
8009 8729
@@ -8025,27 +8745,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8025 break; 8745 break;
8026 8746
8027 case (int)ScriptBaseClass.PRIM_TEXGEN: 8747 case (int)ScriptBaseClass.PRIM_TEXGEN:
8748 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8028 if (remain < 1) 8749 if (remain < 1)
8029 return res; 8750 return res;
8030 8751 face = (int)rules.GetLSLIntegerItem(idx++);
8031 face=(int)rules.GetLSLIntegerItem(idx++);
8032 8752
8033 tex = part.Shape.Textures; 8753 tex = part.Shape.Textures;
8034 if (face == ScriptBaseClass.ALL_SIDES) 8754 if (face == ScriptBaseClass.ALL_SIDES)
8035 { 8755 {
8036 for (face = 0; face < GetNumberOfSides(part); face++) 8756 for (face = 0; face < GetNumberOfSides(part); face++)
8037 { 8757 {
8038 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8758 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8039 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 8759 {
8040 res.Add(new LSL_Integer((uint)texgen >> 1)); 8760 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8761 }
8762 else
8763 {
8764 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8765 }
8041 } 8766 }
8042 } 8767 }
8043 else 8768 else
8044 { 8769 {
8045 if (face >= 0 && face < GetNumberOfSides(part)) 8770 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8046 { 8771 {
8047 MappingType texgen = tex.GetFace((uint)face).TexMapType; 8772 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8048 res.Add(new LSL_Integer((uint)texgen >> 1)); 8773 }
8774 else
8775 {
8776 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8049 } 8777 }
8050 } 8778 }
8051 break; 8779 break;
@@ -8068,28 +8796,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8068 case (int)ScriptBaseClass.PRIM_GLOW: 8796 case (int)ScriptBaseClass.PRIM_GLOW:
8069 if (remain < 1) 8797 if (remain < 1)
8070 return res; 8798 return res;
8071 8799 face = (int)rules.GetLSLIntegerItem(idx++);
8072 face=(int)rules.GetLSLIntegerItem(idx++);
8073 8800
8074 tex = part.Shape.Textures; 8801 tex = part.Shape.Textures;
8802 float primglow;
8075 if (face == ScriptBaseClass.ALL_SIDES) 8803 if (face == ScriptBaseClass.ALL_SIDES)
8076 { 8804 {
8077 for (face = 0; face < GetNumberOfSides(part); face++) 8805 for (face = 0; face < GetNumberOfSides(part); face++)
8078 { 8806 {
8079 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8807 primglow = tex.GetFace((uint)face).Glow;
8080 res.Add(new LSL_Float(texface.Glow)); 8808 res.Add(new LSL_Float(primglow));
8081 } 8809 }
8082 } 8810 }
8083 else 8811 else
8084 { 8812 {
8085 if (face >= 0 && face < GetNumberOfSides(part)) 8813 primglow = tex.GetFace((uint)face).Glow;
8086 { 8814 res.Add(new LSL_Float(primglow));
8087 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8088 res.Add(new LSL_Float(texface.Glow));
8089 }
8090 } 8815 }
8091 break; 8816 break;
8092
8093 case (int)ScriptBaseClass.PRIM_TEXT: 8817 case (int)ScriptBaseClass.PRIM_TEXT:
8094 Color4 textColor = part.GetTextColor(); 8818 Color4 textColor = part.GetTextColor();
8095 res.Add(new LSL_String(part.Text)); 8819 res.Add(new LSL_String(part.Text));
@@ -8701,8 +9425,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8701 // The function returns an ordered list 9425 // The function returns an ordered list
8702 // representing the tokens found in the supplied 9426 // representing the tokens found in the supplied
8703 // sources string. If two successive tokenizers 9427 // sources string. If two successive tokenizers
8704 // are encountered, then a NULL entry is added 9428 // are encountered, then a null-string entry is
8705 // to the list. 9429 // added to the list.
8706 // 9430 //
8707 // It is a precondition that the source and 9431 // It is a precondition that the source and
8708 // toekizer lisst are non-null. If they are null, 9432 // toekizer lisst are non-null. If they are null,
@@ -8710,7 +9434,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8710 // while their lengths are being determined. 9434 // while their lengths are being determined.
8711 // 9435 //
8712 // A small amount of working memoryis required 9436 // A small amount of working memoryis required
8713 // of approximately 8*#tokenizers. 9437 // of approximately 8*#tokenizers + 8*srcstrlen.
8714 // 9438 //
8715 // There are many ways in which this function 9439 // There are many ways in which this function
8716 // can be implemented, this implementation is 9440 // can be implemented, this implementation is
@@ -8726,155 +9450,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8726 // and eliminates redundant tokenizers as soon 9450 // and eliminates redundant tokenizers as soon
8727 // as is possible. 9451 // as is possible.
8728 // 9452 //
8729 // The implementation tries to avoid any copying 9453 // The implementation tries to minimize temporary
8730 // of arrays or other objects. 9454 // garbage generation.
8731 // </remarks> 9455 // </remarks>
8732 9456
8733 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9457 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8734 { 9458 {
8735 int beginning = 0; 9459 return ParseString2List(src, separators, spacers, true);
8736 int srclen = src.Length; 9460 }
8737 int seplen = separators.Length;
8738 object[] separray = separators.Data;
8739 int spclen = spacers.Length;
8740 object[] spcarray = spacers.Data;
8741 int mlen = seplen+spclen;
8742
8743 int[] offset = new int[mlen+1];
8744 bool[] active = new bool[mlen];
8745
8746 int best;
8747 int j;
8748
8749 // Initial capacity reduces resize cost
8750 9461
8751 LSL_List tokens = new LSL_List(); 9462 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9463 {
9464 int srclen = src.Length;
9465 int seplen = separators.Length;
9466 object[] separray = separators.Data;
9467 int spclen = spacers.Length;
9468 object[] spcarray = spacers.Data;
9469 int dellen = 0;
9470 string[] delarray = new string[seplen+spclen];
8752 9471
8753 // All entries are initially valid 9472 int outlen = 0;
9473 string[] outarray = new string[srclen*2+1];
8754 9474
8755 for (int i = 0; i < mlen; i++) 9475 int i, j;
8756 active[i] = true; 9476 string d;
8757 9477
8758 offset[mlen] = srclen; 9478 m_host.AddScriptLPS(1);
8759 9479
8760 while (beginning < srclen) 9480 /*
9481 * Convert separator and spacer lists to C# strings.
9482 * Also filter out null strings so we don't hang.
9483 */
9484 for (i = 0; i < seplen; i ++)
8761 { 9485 {
9486 d = separray[i].ToString();
9487 if (d.Length > 0)
9488 {
9489 delarray[dellen++] = d;
9490 }
9491 }
9492 seplen = dellen;
8762 9493
8763 best = mlen; // as bad as it gets 9494 for (i = 0; i < spclen; i ++)
9495 {
9496 d = spcarray[i].ToString();
9497 if (d.Length > 0)
9498 {
9499 delarray[dellen++] = d;
9500 }
9501 }
8764 9502
8765 // Scan for separators 9503 /*
9504 * Scan through source string from beginning to end.
9505 */
9506 for (i = 0;;)
9507 {
8766 9508
8767 for (j = 0; j < seplen; j++) 9509 /*
9510 * Find earliest delimeter in src starting at i (if any).
9511 */
9512 int earliestDel = -1;
9513 int earliestSrc = srclen;
9514 string earliestStr = null;
9515 for (j = 0; j < dellen; j ++)
8768 { 9516 {
8769 if (separray[j].ToString() == String.Empty) 9517 d = delarray[j];
8770 active[j] = false; 9518 if (d != null)
8771
8772 if (active[j])
8773 { 9519 {
8774 // scan all of the markers 9520 int index = src.IndexOf(d, i);
8775 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9521 if (index < 0)
8776 { 9522 {
8777 // not present at all 9523 delarray[j] = null; // delim nowhere in src, don't check it anymore
8778 active[j] = false;
8779 } 9524 }
8780 else 9525 else if (index < earliestSrc)
8781 { 9526 {
8782 // present and correct 9527 earliestSrc = index; // where delimeter starts in source string
8783 if (offset[j] < offset[best]) 9528 earliestDel = j; // where delimeter is in delarray[]
8784 { 9529 earliestStr = d; // the delimeter string from delarray[]
8785 // closest so far 9530 if (index == i) break; // can't do any better than found at beg of string
8786 best = j;
8787 if (offset[best] == beginning)
8788 break;
8789 }
8790 } 9531 }
8791 } 9532 }
8792 } 9533 }
8793 9534
8794 // Scan for spacers 9535 /*
8795 9536 * Output source string starting at i through start of earliest delimeter.
8796 if (offset[best] != beginning) 9537 */
9538 if (keepNulls || (earliestSrc > i))
8797 { 9539 {
8798 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9540 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8799 {
8800 if (spcarray[j-seplen].ToString() == String.Empty)
8801 active[j] = false;
8802
8803 if (active[j])
8804 {
8805 // scan all of the markers
8806 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8807 {
8808 // not present at all
8809 active[j] = false;
8810 }
8811 else
8812 {
8813 // present and correct
8814 if (offset[j] < offset[best])
8815 {
8816 // closest so far
8817 best = j;
8818 }
8819 }
8820 }
8821 }
8822 } 9541 }
8823 9542
8824 // This is the normal exit from the scanning loop 9543 /*
9544 * If no delimeter found at or after i, we're done scanning.
9545 */
9546 if (earliestDel < 0) break;
8825 9547
8826 if (best == mlen) 9548 /*
9549 * If delimeter was a spacer, output the spacer.
9550 */
9551 if (earliestDel >= seplen)
8827 { 9552 {
8828 // no markers were found on this pass 9553 outarray[outlen++] = earliestStr;
8829 // so we're pretty much done
8830 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8831 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8832 break;
8833 } 9554 }
8834 9555
8835 // Otherwise we just add the newly delimited token 9556 /*
8836 // and recalculate where the search should continue. 9557 * Look at rest of src string following delimeter.
8837 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9558 */
8838 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9559 i = earliestSrc + earliestStr.Length;
8839
8840 if (best < seplen)
8841 {
8842 beginning = offset[best] + (separray[best].ToString()).Length;
8843 }
8844 else
8845 {
8846 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8847 string str = spcarray[best - seplen].ToString();
8848 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8849 tokens.Add(new LSL_String(str));
8850 }
8851 } 9560 }
8852 9561
8853 // This an awkward an not very intuitive boundary case. If the 9562 /*
8854 // last substring is a tokenizer, then there is an implied trailing 9563 * Make up an exact-sized output array suitable for an LSL_List object.
8855 // null list entry. Hopefully the single comparison will not be too 9564 */
8856 // arduous. Alternatively the 'break' could be replced with a return 9565 object[] outlist = new object[outlen];
8857 // but that's shabby programming. 9566 for (i = 0; i < outlen; i ++)
8858
8859 if ((beginning == srclen) && (keepNulls))
8860 { 9567 {
8861 if (srclen != 0) 9568 outlist[i] = new LSL_String(outarray[i]);
8862 tokens.Add(new LSL_String(""));
8863 } 9569 }
8864 9570 return new LSL_List(outlist);
8865 return tokens;
8866 }
8867
8868 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8869 {
8870 m_host.AddScriptLPS(1);
8871 return this.ParseString(src, separators, spacers, false);
8872 }
8873
8874 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8875 {
8876 m_host.AddScriptLPS(1);
8877 return this.ParseString(src, separators, spacers, true);
8878 } 9571 }
8879 9572
8880 public LSL_Integer llGetObjectPermMask(int mask) 9573 public LSL_Integer llGetObjectPermMask(int mask)
@@ -8951,28 +9644,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8951 { 9644 {
8952 m_host.AddScriptLPS(1); 9645 m_host.AddScriptLPS(1);
8953 9646
8954 lock (m_host.TaskInventory) 9647 m_host.TaskInventory.LockItemsForRead(true);
9648 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
8955 { 9649 {
8956 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9650 if (inv.Value.Name == item)
8957 { 9651 {
8958 if (inv.Value.Name == item) 9652 m_host.TaskInventory.LockItemsForRead(false);
9653 switch (mask)
8959 { 9654 {
8960 switch (mask) 9655 case 0:
8961 { 9656 return (int)inv.Value.BasePermissions;
8962 case 0: 9657 case 1:
8963 return (int)inv.Value.BasePermissions; 9658 return (int)inv.Value.CurrentPermissions;
8964 case 1: 9659 case 2:
8965 return (int)inv.Value.CurrentPermissions; 9660 return (int)inv.Value.GroupPermissions;
8966 case 2: 9661 case 3:
8967 return (int)inv.Value.GroupPermissions; 9662 return (int)inv.Value.EveryonePermissions;
8968 case 3: 9663 case 4:
8969 return (int)inv.Value.EveryonePermissions; 9664 return (int)inv.Value.NextPermissions;
8970 case 4:
8971 return (int)inv.Value.NextPermissions;
8972 }
8973 } 9665 }
8974 } 9666 }
8975 } 9667 }
9668 m_host.TaskInventory.LockItemsForRead(false);
8976 9669
8977 return -1; 9670 return -1;
8978 } 9671 }
@@ -9019,16 +9712,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9019 { 9712 {
9020 m_host.AddScriptLPS(1); 9713 m_host.AddScriptLPS(1);
9021 9714
9022 lock (m_host.TaskInventory) 9715 m_host.TaskInventory.LockItemsForRead(true);
9716 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9023 { 9717 {
9024 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 9718 if (inv.Value.Name == item)
9025 { 9719 {
9026 if (inv.Value.Name == item) 9720 m_host.TaskInventory.LockItemsForRead(false);
9027 { 9721 return inv.Value.CreatorID.ToString();
9028 return inv.Value.CreatorID.ToString();
9029 }
9030 } 9722 }
9031 } 9723 }
9724 m_host.TaskInventory.LockItemsForRead(false);
9032 9725
9033 llSay(0, "No item name '" + item + "'"); 9726 llSay(0, "No item name '" + item + "'");
9034 9727
@@ -9154,9 +9847,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9154 { 9847 {
9155 try 9848 try
9156 { 9849 {
9850 /*
9157 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 9851 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
9158 if (obj != null) 9852 if (obj != null)
9159 return (double)obj.GetMass(); 9853 return (double)obj.GetMass();
9854 */
9855 // return total object mass
9856 SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
9857 if (obj != null)
9858 return obj.GetMass();
9859
9160 // the object is null so the key is for an avatar 9860 // the object is null so the key is for an avatar
9161 ScenePresence avatar = World.GetScenePresence(key); 9861 ScenePresence avatar = World.GetScenePresence(key);
9162 if (avatar != null) 9862 if (avatar != null)
@@ -9176,7 +9876,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9176 } 9876 }
9177 9877
9178 /// <summary> 9878 /// <summary>
9179 /// illListReplaceList removes the sub-list defined by the inclusive indices 9879 /// llListReplaceList removes the sub-list defined by the inclusive indices
9180 /// start and end and inserts the src list in its place. The inclusive 9880 /// start and end and inserts the src list in its place. The inclusive
9181 /// nature of the indices means that at least one element must be deleted 9881 /// nature of the indices means that at least one element must be deleted
9182 /// if the indices are within the bounds of the existing list. I.e. 2,2 9882 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9233,16 +9933,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9233 // based upon end. Note that if end exceeds the upper 9933 // based upon end. Note that if end exceeds the upper
9234 // bound in this case, the entire destination list 9934 // bound in this case, the entire destination list
9235 // is removed. 9935 // is removed.
9236 else 9936 else if (start == 0)
9237 { 9937 {
9238 if (end + 1 < dest.Length) 9938 if (end + 1 < dest.Length)
9239 {
9240 return src + dest.GetSublist(end + 1, -1); 9939 return src + dest.GetSublist(end + 1, -1);
9241 }
9242 else 9940 else
9243 {
9244 return src; 9941 return src;
9245 } 9942 }
9943 else // Start < 0
9944 {
9945 if (end + 1 < dest.Length)
9946 return dest.GetSublist(end + 1, -1);
9947 else
9948 return new LSL_List();
9246 } 9949 }
9247 } 9950 }
9248 // Finally, if start > end, we strip away a prefix and 9951 // Finally, if start > end, we strip away a prefix and
@@ -9293,17 +9996,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9293 int width = 0; 9996 int width = 0;
9294 int height = 0; 9997 int height = 0;
9295 9998
9296 ParcelMediaCommandEnum? commandToSend = null; 9999 uint commandToSend = 0;
9297 float time = 0.0f; // default is from start 10000 float time = 0.0f; // default is from start
9298 10001
9299 ScenePresence presence = null; 10002 ScenePresence presence = null;
9300 10003
9301 for (int i = 0; i < commandList.Data.Length; i++) 10004 for (int i = 0; i < commandList.Data.Length; i++)
9302 { 10005 {
9303 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10006 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9304 switch (command) 10007 switch (command)
9305 { 10008 {
9306 case ParcelMediaCommandEnum.Agent: 10009 case (uint)ParcelMediaCommandEnum.Agent:
9307 // we send only to one agent 10010 // we send only to one agent
9308 if ((i + 1) < commandList.Length) 10011 if ((i + 1) < commandList.Length)
9309 { 10012 {
@@ -9320,25 +10023,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9320 } 10023 }
9321 break; 10024 break;
9322 10025
9323 case ParcelMediaCommandEnum.Loop: 10026 case (uint)ParcelMediaCommandEnum.Loop:
9324 loop = 1; 10027 loop = 1;
9325 commandToSend = command; 10028 commandToSend = command;
9326 update = true; //need to send the media update packet to set looping 10029 update = true; //need to send the media update packet to set looping
9327 break; 10030 break;
9328 10031
9329 case ParcelMediaCommandEnum.Play: 10032 case (uint)ParcelMediaCommandEnum.Play:
9330 loop = 0; 10033 loop = 0;
9331 commandToSend = command; 10034 commandToSend = command;
9332 update = true; //need to send the media update packet to make sure it doesn't loop 10035 update = true; //need to send the media update packet to make sure it doesn't loop
9333 break; 10036 break;
9334 10037
9335 case ParcelMediaCommandEnum.Pause: 10038 case (uint)ParcelMediaCommandEnum.Pause:
9336 case ParcelMediaCommandEnum.Stop: 10039 case (uint)ParcelMediaCommandEnum.Stop:
9337 case ParcelMediaCommandEnum.Unload: 10040 case (uint)ParcelMediaCommandEnum.Unload:
9338 commandToSend = command; 10041 commandToSend = command;
9339 break; 10042 break;
9340 10043
9341 case ParcelMediaCommandEnum.Url: 10044 case (uint)ParcelMediaCommandEnum.Url:
9342 if ((i + 1) < commandList.Length) 10045 if ((i + 1) < commandList.Length)
9343 { 10046 {
9344 if (commandList.Data[i + 1] is LSL_String) 10047 if (commandList.Data[i + 1] is LSL_String)
@@ -9351,7 +10054,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9351 } 10054 }
9352 break; 10055 break;
9353 10056
9354 case ParcelMediaCommandEnum.Texture: 10057 case (uint)ParcelMediaCommandEnum.Texture:
9355 if ((i + 1) < commandList.Length) 10058 if ((i + 1) < commandList.Length)
9356 { 10059 {
9357 if (commandList.Data[i + 1] is LSL_String) 10060 if (commandList.Data[i + 1] is LSL_String)
@@ -9364,7 +10067,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9364 } 10067 }
9365 break; 10068 break;
9366 10069
9367 case ParcelMediaCommandEnum.Time: 10070 case (uint)ParcelMediaCommandEnum.Time:
9368 if ((i + 1) < commandList.Length) 10071 if ((i + 1) < commandList.Length)
9369 { 10072 {
9370 if (commandList.Data[i + 1] is LSL_Float) 10073 if (commandList.Data[i + 1] is LSL_Float)
@@ -9376,7 +10079,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9376 } 10079 }
9377 break; 10080 break;
9378 10081
9379 case ParcelMediaCommandEnum.AutoAlign: 10082 case (uint)ParcelMediaCommandEnum.AutoAlign:
9380 if ((i + 1) < commandList.Length) 10083 if ((i + 1) < commandList.Length)
9381 { 10084 {
9382 if (commandList.Data[i + 1] is LSL_Integer) 10085 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9390,7 +10093,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9390 } 10093 }
9391 break; 10094 break;
9392 10095
9393 case ParcelMediaCommandEnum.Type: 10096 case (uint)ParcelMediaCommandEnum.Type:
9394 if ((i + 1) < commandList.Length) 10097 if ((i + 1) < commandList.Length)
9395 { 10098 {
9396 if (commandList.Data[i + 1] is LSL_String) 10099 if (commandList.Data[i + 1] is LSL_String)
@@ -9403,7 +10106,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9403 } 10106 }
9404 break; 10107 break;
9405 10108
9406 case ParcelMediaCommandEnum.Desc: 10109 case (uint)ParcelMediaCommandEnum.Desc:
9407 if ((i + 1) < commandList.Length) 10110 if ((i + 1) < commandList.Length)
9408 { 10111 {
9409 if (commandList.Data[i + 1] is LSL_String) 10112 if (commandList.Data[i + 1] is LSL_String)
@@ -9416,7 +10119,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9416 } 10119 }
9417 break; 10120 break;
9418 10121
9419 case ParcelMediaCommandEnum.Size: 10122 case (uint)ParcelMediaCommandEnum.Size:
9420 if ((i + 2) < commandList.Length) 10123 if ((i + 2) < commandList.Length)
9421 { 10124 {
9422 if (commandList.Data[i + 1] is LSL_Integer) 10125 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9486,7 +10189,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9486 } 10189 }
9487 } 10190 }
9488 10191
9489 if (commandToSend != null) 10192 if (commandToSend != 0)
9490 { 10193 {
9491 // the commandList contained a start/stop/... command, too 10194 // the commandList contained a start/stop/... command, too
9492 if (presence == null) 10195 if (presence == null)
@@ -9523,7 +10226,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9523 10226
9524 if (aList.Data[i] != null) 10227 if (aList.Data[i] != null)
9525 { 10228 {
9526 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10229 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9527 { 10230 {
9528 case ParcelMediaCommandEnum.Url: 10231 case ParcelMediaCommandEnum.Url:
9529 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10232 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9566,16 +10269,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9566 { 10269 {
9567 m_host.AddScriptLPS(1); 10270 m_host.AddScriptLPS(1);
9568 10271
9569 lock (m_host.TaskInventory) 10272 m_host.TaskInventory.LockItemsForRead(true);
10273 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9570 { 10274 {
9571 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10275 if (inv.Value.Name == name)
9572 { 10276 {
9573 if (inv.Value.Name == name) 10277 m_host.TaskInventory.LockItemsForRead(false);
9574 { 10278 return inv.Value.Type;
9575 return inv.Value.Type;
9576 }
9577 } 10279 }
9578 } 10280 }
10281 m_host.TaskInventory.LockItemsForRead(false);
9579 10282
9580 return -1; 10283 return -1;
9581 } 10284 }
@@ -9586,15 +10289,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9586 10289
9587 if (quick_pay_buttons.Data.Length < 4) 10290 if (quick_pay_buttons.Data.Length < 4)
9588 { 10291 {
9589 LSLError("List must have at least 4 elements"); 10292 int x;
9590 return; 10293 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10294 {
10295 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10296 }
9591 } 10297 }
9592 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10298 int[] nPrice = new int[5];
9593 10299 nPrice[0] = price;
9594 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10300 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9595 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10301 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9596 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10302 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9597 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10303 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10304 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9598 m_host.ParentGroup.HasGroupChanged = true; 10305 m_host.ParentGroup.HasGroupChanged = true;
9599 } 10306 }
9600 10307
@@ -9612,6 +10319,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9612 ShoutError("No permissions to track the camera"); 10319 ShoutError("No permissions to track the camera");
9613 return new LSL_Vector(); 10320 return new LSL_Vector();
9614 } 10321 }
10322 m_host.TaskInventory.LockItemsForRead(false);
9615 10323
9616 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10324 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9617 if (presence != null) 10325 if (presence != null)
@@ -9636,6 +10344,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9636 ShoutError("No permissions to track the camera"); 10344 ShoutError("No permissions to track the camera");
9637 return new LSL_Rotation(); 10345 return new LSL_Rotation();
9638 } 10346 }
10347 m_host.TaskInventory.LockItemsForRead(false);
9639 10348
9640 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10349 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9641 if (presence != null) 10350 if (presence != null)
@@ -9697,8 +10406,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9697 { 10406 {
9698 m_host.AddScriptLPS(1); 10407 m_host.AddScriptLPS(1);
9699 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0); 10408 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0);
9700 if (detectedParams == null) return; // only works on the first detected avatar 10409 if (detectedParams == null)
9701 10410 {
10411 if (m_host.ParentGroup.IsAttachment == true)
10412 {
10413 detectedParams = new DetectParams();
10414 detectedParams.Key = m_host.OwnerID;
10415 }
10416 else
10417 {
10418 return;
10419 }
10420 }
10421
9702 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10422 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9703 if (avatar != null) 10423 if (avatar != null)
9704 { 10424 {
@@ -9706,6 +10426,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9706 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10426 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9707 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10427 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9708 } 10428 }
10429
9709 ScriptSleep(1000); 10430 ScriptSleep(1000);
9710 } 10431 }
9711 10432
@@ -9831,12 +10552,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9831 10552
9832 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10553 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9833 object[] data = rules.Data; 10554 object[] data = rules.Data;
9834 for (int i = 0; i < data.Length; ++i) { 10555 for (int i = 0; i < data.Length; ++i)
10556 {
9835 int type = Convert.ToInt32(data[i++].ToString()); 10557 int type = Convert.ToInt32(data[i++].ToString());
9836 if (i >= data.Length) break; // odd number of entries => ignore the last 10558 if (i >= data.Length) break; // odd number of entries => ignore the last
9837 10559
9838 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10560 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9839 switch (type) { 10561 switch (type)
10562 {
9840 case ScriptBaseClass.CAMERA_FOCUS: 10563 case ScriptBaseClass.CAMERA_FOCUS:
9841 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10564 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9842 case ScriptBaseClass.CAMERA_POSITION: 10565 case ScriptBaseClass.CAMERA_POSITION:
@@ -9944,19 +10667,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9944 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10667 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
9945 { 10668 {
9946 m_host.AddScriptLPS(1); 10669 m_host.AddScriptLPS(1);
9947 string ret = String.Empty; 10670
9948 string src1 = llBase64ToString(str1); 10671 if (str1 == String.Empty)
9949 string src2 = llBase64ToString(str2); 10672 return String.Empty;
9950 int c = 0; 10673 if (str2 == String.Empty)
9951 for (int i = 0; i < src1.Length; i++) 10674 return str1;
10675
10676 int len = str2.Length;
10677 if ((len % 4) != 0) // LL is EVIL!!!!
10678 {
10679 while (str2.EndsWith("="))
10680 str2 = str2.Substring(0, str2.Length - 1);
10681
10682 len = str2.Length;
10683 int mod = len % 4;
10684
10685 if (mod == 1)
10686 str2 = str2.Substring(0, str2.Length - 1);
10687 else if (mod == 2)
10688 str2 += "==";
10689 else if (mod == 3)
10690 str2 += "=";
10691 }
10692
10693 byte[] data1;
10694 byte[] data2;
10695 try
10696 {
10697 data1 = Convert.FromBase64String(str1);
10698 data2 = Convert.FromBase64String(str2);
10699 }
10700 catch (Exception)
10701 {
10702 return new LSL_String(String.Empty);
10703 }
10704
10705 byte[] d2 = new Byte[data1.Length];
10706 int pos = 0;
10707
10708 if (data1.Length <= data2.Length)
10709 {
10710 Array.Copy(data2, 0, d2, 0, data1.Length);
10711 }
10712 else
9952 { 10713 {
9953 ret += (char) (src1[i] ^ src2[c]); 10714 while (pos < data1.Length)
10715 {
10716 len = data1.Length - pos;
10717 if (len > data2.Length)
10718 len = data2.Length;
9954 10719
9955 c++; 10720 Array.Copy(data2, 0, d2, pos, len);
9956 if (c >= src2.Length) 10721 pos += len;
9957 c = 0; 10722 }
9958 } 10723 }
9959 return llStringToBase64(ret); 10724
10725 for (pos = 0 ; pos < data1.Length ; pos++ )
10726 data1[pos] ^= d2[pos];
10727
10728 return Convert.ToBase64String(data1);
9960 } 10729 }
9961 10730
9962 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 10731 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10013,12 +10782,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10013 Regex r = new Regex(authregex); 10782 Regex r = new Regex(authregex);
10014 int[] gnums = r.GetGroupNumbers(); 10783 int[] gnums = r.GetGroupNumbers();
10015 Match m = r.Match(url); 10784 Match m = r.Match(url);
10016 if (m.Success) { 10785 if (m.Success)
10017 for (int i = 1; i < gnums.Length; i++) { 10786 {
10787 for (int i = 1; i < gnums.Length; i++)
10788 {
10018 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 10789 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10019 //CaptureCollection cc = g.Captures; 10790 //CaptureCollection cc = g.Captures;
10020 } 10791 }
10021 if (m.Groups.Count == 5) { 10792 if (m.Groups.Count == 5)
10793 {
10022 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 10794 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10023 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 10795 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10024 } 10796 }
@@ -10381,15 +11153,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10381 11153
10382 internal UUID ScriptByName(string name) 11154 internal UUID ScriptByName(string name)
10383 { 11155 {
10384 lock (m_host.TaskInventory) 11156 m_host.TaskInventory.LockItemsForRead(true);
11157
11158 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10385 { 11159 {
10386 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 11160 if (item.Type == 10 && item.Name == name)
10387 { 11161 {
10388 if (item.Type == 10 && item.Name == name) 11162 m_host.TaskInventory.LockItemsForRead(false);
10389 return item.ItemID; 11163 return item.ItemID;
10390 } 11164 }
10391 } 11165 }
10392 11166
11167 m_host.TaskInventory.LockItemsForRead(false);
11168
10393 return UUID.Zero; 11169 return UUID.Zero;
10394 } 11170 }
10395 11171
@@ -10430,6 +11206,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10430 { 11206 {
10431 m_host.AddScriptLPS(1); 11207 m_host.AddScriptLPS(1);
10432 11208
11209 //Clone is thread safe
10433 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11210 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10434 11211
10435 UUID assetID = UUID.Zero; 11212 UUID assetID = UUID.Zero;
@@ -10492,6 +11269,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10492 { 11269 {
10493 m_host.AddScriptLPS(1); 11270 m_host.AddScriptLPS(1);
10494 11271
11272 //Clone is thread safe
10495 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11273 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10496 11274
10497 UUID assetID = UUID.Zero; 11275 UUID assetID = UUID.Zero;
@@ -10572,15 +11350,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10572 return GetLinkPrimitiveParams(obj, rules); 11350 return GetLinkPrimitiveParams(obj, rules);
10573 } 11351 }
10574 11352
10575 public void print(string str) 11353 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10576 { 11354 {
10577 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11355 List<SceneObjectPart> parts = GetLinkParts(link);
10578 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_itemID, "OSSL"); 11356 if (parts.Count < 1)
10579 if (ossl != null) 11357 return 0;
10580 { 11358
10581 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11359 return GetNumberOfSides(parts[0]);
10582 m_log.Info("LSL print():" + str);
10583 }
10584 } 11360 }
10585 11361
10586 private string Name2Username(string name) 11362 private string Name2Username(string name)
@@ -10626,155 +11402,482 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10626 return rq.ToString(); 11402 return rq.ToString();
10627 } 11403 }
10628 11404
11405 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11406 {
11407 m_SayShoutCount = 0;
11408 }
11409
11410 private struct Tri
11411 {
11412 public Vector3 p1;
11413 public Vector3 p2;
11414 public Vector3 p3;
11415 }
11416
11417 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
11418 {
11419 float height = avatar.Appearance.AvatarHeight;
11420 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
11421 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
11422
11423 if (point.X > b1.X && point.X < b2.X &&
11424 point.Y > b1.Y && point.Y < b2.Y &&
11425 point.Z > b1.Z && point.Z < b2.Z)
11426 return true;
11427 return false;
11428 }
11429
11430 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
11431 {
11432 List<ContactResult> contacts = new List<ContactResult>();
11433
11434 Vector3 ab = rayEnd - rayStart;
11435
11436 World.ForEachScenePresence(delegate(ScenePresence sp)
11437 {
11438 Vector3 ac = sp.AbsolutePosition - rayStart;
11439 Vector3 bc = sp.AbsolutePosition - rayEnd;
11440
11441 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11442
11443 if (d > 1.5)
11444 return;
11445
11446 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11447
11448 if (d2 > 0)
11449 return;
11450
11451 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
11452 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
11453
11454 if (!InBoundingBox(sp, p))
11455 return;
11456
11457 ContactResult result = new ContactResult ();
11458 result.ConsumerID = sp.LocalId;
11459 result.Depth = Vector3.Distance(rayStart, p);
11460 result.Normal = Vector3.Zero;
11461 result.Pos = p;
11462
11463 contacts.Add(result);
11464 });
11465
11466 return contacts.ToArray();
11467 }
11468
11469 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
11470 {
11471 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11472 List<ContactResult> contacts = new List<ContactResult>();
11473
11474 Vector3 ab = rayEnd - rayStart;
11475
11476 World.ForEachSOG(delegate(SceneObjectGroup group)
11477 {
11478 if (m_host.ParentGroup == group)
11479 return;
11480
11481 if (group.IsAttachment)
11482 return;
11483
11484 if (group.RootPart.PhysActor == null)
11485 {
11486 if (!includePhantom)
11487 return;
11488 }
11489 else
11490 {
11491 if (group.RootPart.PhysActor.IsPhysical)
11492 {
11493 if (!includePhysical)
11494 return;
11495 }
11496 else
11497 {
11498 if (!includeNonPhysical)
11499 return;
11500 }
11501 }
11502
11503 // Find the radius ouside of which we don't even need to hit test
11504 float minX;
11505 float maxX;
11506 float minY;
11507 float maxY;
11508 float minZ;
11509 float maxZ;
11510
11511 float radius = 0.0f;
11512
11513 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
11514
11515 if (Math.Abs(minX) > radius)
11516 radius = Math.Abs(minX);
11517 if (Math.Abs(minY) > radius)
11518 radius = Math.Abs(minY);
11519 if (Math.Abs(minZ) > radius)
11520 radius = Math.Abs(minZ);
11521 if (Math.Abs(maxX) > radius)
11522 radius = Math.Abs(maxX);
11523 if (Math.Abs(maxY) > radius)
11524 radius = Math.Abs(maxY);
11525 if (Math.Abs(maxZ) > radius)
11526 radius = Math.Abs(maxZ);
11527
11528 Vector3 ac = group.AbsolutePosition - rayStart;
11529 Vector3 bc = group.AbsolutePosition - rayEnd;
11530
11531 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11532
11533 // Too far off ray, don't bother
11534 if (d > radius)
11535 return;
11536
11537 // Behind ray, drop
11538 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
11539 if (d2 > 0)
11540 return;
11541
11542 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11543 // Miss.
11544 if (!intersection.HitTF)
11545 return;
11546
11547 ContactResult result = new ContactResult ();
11548 result.ConsumerID = group.LocalId;
11549 result.Depth = intersection.distance;
11550 result.Normal = intersection.normal;
11551 result.Pos = intersection.ipoint;
11552
11553 contacts.Add(result);
11554 });
11555
11556 return contacts.ToArray();
11557 }
11558
11559 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
11560 {
11561 double[,] heightfield = World.Heightmap.GetDoubles();
11562 List<ContactResult> contacts = new List<ContactResult>();
11563
11564 double min = 2048.0;
11565 double max = 0.0;
11566
11567 // Find the min and max of the heightfield
11568 for (int x = 0 ; x < World.Heightmap.Width ; x++)
11569 {
11570 for (int y = 0 ; y < World.Heightmap.Height ; y++)
11571 {
11572 if (heightfield[x, y] > max)
11573 max = heightfield[x, y];
11574 if (heightfield[x, y] < min)
11575 min = heightfield[x, y];
11576 }
11577 }
11578
11579
11580 // A ray extends past rayEnd, but doesn't go back before
11581 // rayStart. If the start is above the highest point of the ground
11582 // and the ray goes up, we can't hit the ground. Ever.
11583 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
11584 return null;
11585
11586 // Same for going down
11587 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
11588 return null;
11589
11590 List<Tri> trilist = new List<Tri>();
11591
11592 // Create our triangle list
11593 for (int x = 1 ; x < World.Heightmap.Width ; x++)
11594 {
11595 for (int y = 1 ; y < World.Heightmap.Height ; y++)
11596 {
11597 Tri t1 = new Tri();
11598 Tri t2 = new Tri();
11599
11600 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
11601 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
11602 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
11603 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
11604
11605 t1.p1 = p1;
11606 t1.p2 = p2;
11607 t1.p3 = p3;
11608
11609 t2.p1 = p3;
11610 t2.p2 = p4;
11611 t2.p3 = p1;
11612
11613 trilist.Add(t1);
11614 trilist.Add(t2);
11615 }
11616 }
11617
11618 // Ray direction
11619 Vector3 rayDirection = rayEnd - rayStart;
11620
11621 foreach (Tri t in trilist)
11622 {
11623 // Compute triangle plane normal and edges
11624 Vector3 u = t.p2 - t.p1;
11625 Vector3 v = t.p3 - t.p1;
11626 Vector3 n = Vector3.Cross(u, v);
11627
11628 if (n == Vector3.Zero)
11629 continue;
11630
11631 Vector3 w0 = rayStart - t.p1;
11632 double a = -Vector3.Dot(n, w0);
11633 double b = Vector3.Dot(n, rayDirection);
11634
11635 // Not intersecting the plane, or in plane (same thing)
11636 // Ignoring this MAY cause the ground to not be detected
11637 // sometimes
11638 if (Math.Abs(b) < 0.000001)
11639 continue;
11640
11641 double r = a / b;
11642
11643 // ray points away from plane
11644 if (r < 0.0)
11645 continue;
11646
11647 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
11648
11649 float uu = Vector3.Dot(u, u);
11650 float uv = Vector3.Dot(u, v);
11651 float vv = Vector3.Dot(v, v);
11652 Vector3 w = ip - t.p1;
11653 float wu = Vector3.Dot(w, u);
11654 float wv = Vector3.Dot(w, v);
11655 float d = uv * uv - uu * vv;
11656
11657 float cs = (uv * wv - vv * wu) / d;
11658 if (cs < 0 || cs > 1.0)
11659 continue;
11660 float ct = (uv * wu - uu * wv) / d;
11661 if (ct < 0 || (cs + ct) > 1.0)
11662 continue;
11663
11664 // Add contact point
11665 ContactResult result = new ContactResult ();
11666 result.ConsumerID = 0;
11667 result.Depth = Vector3.Distance(rayStart, ip);
11668 result.Normal = n;
11669 result.Pos = ip;
11670
11671 contacts.Add(result);
11672 }
11673
11674 if (contacts.Count == 0)
11675 return null;
11676
11677 contacts.Sort(delegate(ContactResult a, ContactResult b)
11678 {
11679 return (int)(a.Depth - b.Depth);
11680 });
11681
11682 return contacts[0];
11683 }
11684/*
11685 // not done:
11686 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
11687 {
11688 ContactResult[] contacts = null;
11689 World.ForEachSOG(delegate(SceneObjectGroup group)
11690 {
11691 if (m_host.ParentGroup == group)
11692 return;
11693
11694 if (group.IsAttachment)
11695 return;
11696
11697 if(group.RootPart.PhysActor != null)
11698 return;
11699
11700 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
11701 });
11702 return contacts;
11703 }
11704*/
11705
10629 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 11706 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10630 { 11707 {
11708 LSL_List list = new LSL_List();
11709
10631 m_host.AddScriptLPS(1); 11710 m_host.AddScriptLPS(1);
10632 11711
10633 Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); 11712 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
10634 Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); 11713 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
10635 Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); 11714 Vector3 dir = rayEnd - rayStart;
10636 11715
10637 int count = 0; 11716 float dist = Vector3.Mag(dir);
10638// int detectPhantom = 0; 11717
11718 int count = 1;
11719 bool detectPhantom = false;
10639 int dataFlags = 0; 11720 int dataFlags = 0;
10640 int rejectTypes = 0; 11721 int rejectTypes = 0;
10641 11722
10642 for (int i = 0; i < options.Length; i += 2) 11723 for (int i = 0; i < options.Length; i += 2)
10643 { 11724 {
10644 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 11725 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
10645 {
10646 count = options.GetLSLIntegerItem(i + 1); 11726 count = options.GetLSLIntegerItem(i + 1);
10647 } 11727 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
10648// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 11728 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
10649// {
10650// detectPhantom = options.GetLSLIntegerItem(i + 1);
10651// }
10652 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 11729 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
10653 {
10654 dataFlags = options.GetLSLIntegerItem(i + 1); 11730 dataFlags = options.GetLSLIntegerItem(i + 1);
10655 }
10656 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 11731 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
10657 {
10658 rejectTypes = options.GetLSLIntegerItem(i + 1); 11732 rejectTypes = options.GetLSLIntegerItem(i + 1);
10659 }
10660 } 11733 }
10661 11734
10662 LSL_List list = new LSL_List(); 11735 if (count > 16)
10663 List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); 11736 count = 16;
10664
10665 double distance = Util.GetDistanceTo(startvector, endvector);
10666
10667 if (distance == 0)
10668 distance = 0.001;
10669 11737
10670 Vector3 posToCheck = startvector; 11738 List<ContactResult> results = new List<ContactResult>();
10671 ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
10672 11739
10673 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 11740 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
10674 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 11741 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
10675 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 11742 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
10676 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 11743 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10677 11744
10678 for (float i = 0; i <= distance; i += 0.1f) 11745
11746 if (World.SuportsRayCastFiltered())
10679 { 11747 {
10680 posToCheck = startvector + (dir * (i / (float)distance)); 11748 if (dist == 0)
11749 return list;
11750
11751 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
11752 if (checkTerrain)
11753 rayfilter |= RayFilterFlags.land;
11754// if (checkAgents)
11755// rayfilter |= RayFilterFlags.agent;
11756 if (checkPhysical)
11757 rayfilter |= RayFilterFlags.physical;
11758 if (checkNonPhysical)
11759 rayfilter |= RayFilterFlags.nonphysical;
11760 if (detectPhantom)
11761 rayfilter |= RayFilterFlags.LSLPhanton;
10681 11762
10682 if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) 11763 Vector3 direction = dir * ( 1/dist);
11764
11765 if(rayfilter == 0)
10683 { 11766 {
10684 ContactResult result = new ContactResult(); 11767 list.Add(new LSL_Integer(0));
10685 result.ConsumerID = 0; 11768 return list;
10686 result.Depth = 0;
10687 result.Normal = Vector3.Zero;
10688 result.Pos = posToCheck;
10689 results.Add(result);
10690 checkTerrain = false;
10691 } 11769 }
10692 11770
10693 if (checkAgents) 11771 // get some more contacts to sort ???
11772 int physcount = 4 * count;
11773 if (physcount > 20)
11774 physcount = 20;
11775
11776 object physresults;
11777 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
11778
11779 if (physresults == null)
10694 { 11780 {
10695 World.ForEachRootScenePresence(delegate(ScenePresence sp) 11781 list.Add(new LSL_Integer(-3)); // timeout error
10696 { 11782 return list;
10697 if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X))
10698 {
10699 ContactResult result = new ContactResult ();
10700 result.ConsumerID = sp.LocalId;
10701 result.Depth = 0;
10702 result.Normal = Vector3.Zero;
10703 result.Pos = posToCheck;
10704 results.Add(result);
10705 }
10706 });
10707 } 11783 }
10708 }
10709 11784
10710 int refcount = 0; 11785 results = (List<ContactResult>)physresults;
10711 foreach (ContactResult result in results)
10712 {
10713 if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND)
10714 == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0)
10715 continue;
10716 11786
10717 ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID); 11787 // for now physics doesn't detect sitted avatars so do it outside physics
11788 if (checkAgents)
11789 {
11790 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11791 foreach (ContactResult r in agentHits)
11792 results.Add(r);
11793 }
10718 11794
10719 if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) 11795 // bug: will not detect phantom unless they are physical
10720 entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents 11796 // don't use ObjectIntersection because its also bad
11797
11798 }
11799 else
11800 {
11801 if (checkTerrain)
11802 {
11803 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11804 if (groundContact != null)
11805 results.Add((ContactResult)groundContact);
11806 }
10721 11807
10722 if (entity == null) 11808 if (checkAgents)
10723 { 11809 {
10724 list.Add(UUID.Zero); 11810 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
11811 foreach (ContactResult r in agentHits)
11812 results.Add(r);
11813 }
10725 11814
10726 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 11815 if (checkPhysical || checkNonPhysical || detectPhantom)
10727 list.Add(0); 11816 {
11817 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
11818 foreach (ContactResult r in objectHits)
11819 results.Add(r);
11820 }
11821 }
10728 11822
10729 list.Add(result.Pos); 11823 results.Sort(delegate(ContactResult a, ContactResult b)
11824 {
11825 return a.Depth.CompareTo(b.Depth);
11826 });
11827
11828 int values = 0;
11829 SceneObjectGroup thisgrp = m_host.ParentGroup;
10730 11830
10731 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11831 foreach (ContactResult result in results)
10732 list.Add(result.Normal); 11832 {
11833 if (result.Depth > dist)
11834 continue;
10733 11835
10734 continue; //Can't find it, so add UUID.Zero 11836 // physics ray can return colisions with host prim
10735 } 11837 if (m_host.LocalId == result.ConsumerID)
11838 continue;
10736 11839
10737 /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity && 11840 UUID itemID = UUID.Zero;
10738 ((ISceneChildEntity)intersection.obj).PhysActor == null) 11841 int linkNum = 0;
10739 continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
10740 11842
10741 if (entity is SceneObjectPart) 11843 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
11844 // It's a prim!
11845 if (part != null)
10742 { 11846 {
10743 PhysicsActor pa = ((SceneObjectPart)entity).PhysActor; 11847 // dont detect members of same object ???
11848 if (part.ParentGroup == thisgrp)
11849 continue;
10744 11850
10745 if (pa != null && pa.IsPhysical) 11851 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
10746 { 11852 itemID = part.ParentGroup.UUID;
10747 if (!checkPhysical)
10748 continue;
10749 }
10750 else 11853 else
10751 { 11854 itemID = part.UUID;
10752 if (!checkNonPhysical)
10753 continue;
10754 }
10755 }
10756 11855
10757 refcount++; 11856 linkNum = part.LinkNum;
10758 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) 11857 }
10759 list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
10760 else 11858 else
10761 list.Add(entity.UUID);
10762
10763 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
10764 { 11859 {
10765 if (entity is SceneObjectPart) 11860 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
10766 list.Add(((SceneObjectPart)entity).LinkNum); 11861 /// It it a boy? a girl?
10767 else 11862 if (sp != null)
10768 list.Add(0); 11863 itemID = sp.UUID;
10769 } 11864 }
10770 11865
10771 list.Add(result.Pos); 11866 list.Add(new LSL_String(itemID.ToString()));
11867 list.Add(new LSL_String(result.Pos.ToString()));
11868
11869 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
11870 list.Add(new LSL_Integer(linkNum));
10772 11871
10773 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 11872 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
10774 list.Add(result.Normal); 11873 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
11874
11875 values++;
11876 if (values >= count)
11877 break;
10775 } 11878 }
10776 11879
10777 list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED 11880 list.Add(new LSL_Integer(values));
10778 11881
10779 return list; 11882 return list;
10780 } 11883 }
@@ -10814,7 +11917,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10814 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 11917 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
10815 if (!isAccount) return 0; 11918 if (!isAccount) return 0;
10816 if (estate.HasAccess(id)) return 1; 11919 if (estate.HasAccess(id)) return 1;
10817 if (estate.IsBanned(id)) 11920 if (estate.IsBanned(id, World.GetUserFlags(id)))
10818 estate.RemoveBan(id); 11921 estate.RemoveBan(id);
10819 estate.AddEstateUser(id); 11922 estate.AddEstateUser(id);
10820 break; 11923 break;
@@ -10833,14 +11936,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10833 break; 11936 break;
10834 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 11937 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
10835 if (!isAccount) return 0; 11938 if (!isAccount) return 0;
10836 if (estate.IsBanned(id)) return 1; 11939 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
10837 EstateBan ban = new EstateBan(); 11940 EstateBan ban = new EstateBan();
10838 ban.EstateID = estate.EstateID; 11941 ban.EstateID = estate.EstateID;
10839 ban.BannedUserID = id; 11942 ban.BannedUserID = id;
10840 estate.AddBan(ban); 11943 estate.AddBan(ban);
10841 break; 11944 break;
10842 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 11945 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
10843 if (!isAccount || !estate.IsBanned(id)) return 0; 11946 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
10844 estate.RemoveBan(id); 11947 estate.RemoveBan(id);
10845 break; 11948 break;
10846 default: return 0; 11949 default: return 0;
@@ -10869,7 +11972,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10869 return 16384; 11972 return 16384;
10870 } 11973 }
10871 11974
10872 public LSL_Integer llGetUsedMemory() 11975 public virtual LSL_Integer llGetUsedMemory()
10873 { 11976 {
10874 m_host.AddScriptLPS(1); 11977 m_host.AddScriptLPS(1);
10875 // The value returned for LSO scripts in SL 11978 // The value returned for LSO scripts in SL
@@ -10897,7 +12000,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10897 public void llSetSoundQueueing(int queue) 12000 public void llSetSoundQueueing(int queue)
10898 { 12001 {
10899 m_host.AddScriptLPS(1); 12002 m_host.AddScriptLPS(1);
10900 NotImplemented("llSetSoundQueueing");
10901 } 12003 }
10902 12004
10903 public void llCollisionSprite(string impact_sprite) 12005 public void llCollisionSprite(string impact_sprite)
@@ -10909,10 +12011,270 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10909 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12011 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
10910 { 12012 {
10911 m_host.AddScriptLPS(1); 12013 m_host.AddScriptLPS(1);
10912 NotImplemented("llGodLikeRezObject"); 12014
12015 if (!World.Permissions.IsGod(m_host.OwnerID))
12016 NotImplemented("llGodLikeRezObject");
12017
12018 AssetBase rezAsset = World.AssetService.Get(inventory);
12019 if (rezAsset == null)
12020 {
12021 llSay(0, "Asset not found");
12022 return;
12023 }
12024
12025 SceneObjectGroup group = null;
12026
12027 try
12028 {
12029 string xmlData = Utils.BytesToString(rezAsset.Data);
12030 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12031 }
12032 catch
12033 {
12034 llSay(0, "Asset not found");
12035 return;
12036 }
12037
12038 if (group == null)
12039 {
12040 llSay(0, "Asset not found");
12041 return;
12042 }
12043
12044 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12045 group.RootPart.AttachOffset = group.AbsolutePosition;
12046
12047 group.ResetIDs();
12048
12049 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12050 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12051 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12052 group.ScheduleGroupForFullUpdate();
12053
12054 // objects rezzed with this method are die_at_edge by default.
12055 group.RootPart.SetDieAtEdge(true);
12056
12057 group.ResumeScripts();
12058
12059 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12060 "object_rez", new Object[] {
12061 new LSL_String(
12062 group.RootPart.UUID.ToString()) },
12063 new DetectParams[0]));
12064 }
12065
12066 public LSL_String llTransferLindenDollars(string destination, int amount)
12067 {
12068 UUID txn = UUID.Random();
12069
12070 Util.FireAndForget(delegate(object x)
12071 {
12072 int replycode = 0;
12073 string replydata = destination + "," + amount.ToString();
12074
12075 try
12076 {
12077 TaskInventoryItem item = GetSelfInventoryItem();
12078 if (item == null)
12079 {
12080 replydata = "SERVICE_ERROR";
12081 return;
12082 }
12083
12084 m_host.AddScriptLPS(1);
12085
12086 if (item.PermsGranter == UUID.Zero)
12087 {
12088 replydata = "MISSING_PERMISSION_DEBIT";
12089 return;
12090 }
12091
12092 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
12093 {
12094 replydata = "MISSING_PERMISSION_DEBIT";
12095 return;
12096 }
12097
12098 UUID toID = new UUID();
12099
12100 if (!UUID.TryParse(destination, out toID))
12101 {
12102 replydata = "INVALID_AGENT";
12103 return;
12104 }
12105
12106 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
12107
12108 if (money == null)
12109 {
12110 replydata = "TRANSFERS_DISABLED";
12111 return;
12112 }
12113
12114 bool result = money.ObjectGiveMoney(
12115 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
12116
12117 if (result)
12118 {
12119 replycode = 1;
12120 return;
12121 }
12122
12123 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
12124 }
12125 finally
12126 {
12127 m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams(
12128 "transaction_result", new Object[] {
12129 new LSL_String(txn.ToString()),
12130 new LSL_Integer(replycode),
12131 new LSL_String(replydata) },
12132 new DetectParams[0]));
12133 }
12134 });
12135
12136 return txn.ToString();
10913 } 12137 }
10914 12138
10915 #endregion 12139 #endregion
12140
12141 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12142 {
12143 SceneObjectGroup group = m_host.ParentGroup;
12144
12145 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12146 return;
12147 if (group.IsAttachment)
12148 return;
12149
12150 if (frames.Data.Length > 0) // We are getting a new motion
12151 {
12152 if (group.RootPart.KeyframeMotion != null)
12153 group.RootPart.KeyframeMotion.Stop();
12154 group.RootPart.KeyframeMotion = null;
12155
12156 int idx = 0;
12157
12158 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12159 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12160
12161 while (idx < options.Data.Length)
12162 {
12163 int option = (int)options.GetLSLIntegerItem(idx++);
12164 int remain = options.Data.Length - idx;
12165
12166 switch (option)
12167 {
12168 case ScriptBaseClass.KFM_MODE:
12169 if (remain < 1)
12170 break;
12171 int modeval = (int)options.GetLSLIntegerItem(idx++);
12172 switch(modeval)
12173 {
12174 case ScriptBaseClass.KFM_FORWARD:
12175 mode = KeyframeMotion.PlayMode.Forward;
12176 break;
12177 case ScriptBaseClass.KFM_REVERSE:
12178 mode = KeyframeMotion.PlayMode.Reverse;
12179 break;
12180 case ScriptBaseClass.KFM_LOOP:
12181 mode = KeyframeMotion.PlayMode.Loop;
12182 break;
12183 case ScriptBaseClass.KFM_PING_PONG:
12184 mode = KeyframeMotion.PlayMode.PingPong;
12185 break;
12186 }
12187 break;
12188 case ScriptBaseClass.KFM_DATA:
12189 if (remain < 1)
12190 break;
12191 int dataval = (int)options.GetLSLIntegerItem(idx++);
12192 data = (KeyframeMotion.DataFormat)dataval;
12193 break;
12194 }
12195 }
12196
12197 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12198
12199 idx = 0;
12200
12201 int elemLength = 2;
12202 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12203 elemLength = 3;
12204
12205 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12206 while (idx < frames.Data.Length)
12207 {
12208 int remain = frames.Data.Length - idx;
12209
12210 if (remain < elemLength)
12211 break;
12212
12213 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12214 frame.Position = null;
12215 frame.Rotation = null;
12216
12217 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12218 {
12219 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12220 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12221 }
12222 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12223 {
12224 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12225 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12226 }
12227
12228 float tempf = (float)frames.GetLSLFloatItem(idx++);
12229 frame.TimeMS = (int)(tempf * 1000.0f);
12230
12231 keyframes.Add(frame);
12232 }
12233
12234 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12235 group.RootPart.KeyframeMotion.Start();
12236 }
12237 else
12238 {
12239 if (group.RootPart.KeyframeMotion == null)
12240 return;
12241
12242 if (options.Data.Length == 0)
12243 {
12244 group.RootPart.KeyframeMotion.Stop();
12245 return;
12246 }
12247
12248 int code = (int)options.GetLSLIntegerItem(0);
12249
12250 int idx = 0;
12251
12252 while (idx < options.Data.Length)
12253 {
12254 int option = (int)options.GetLSLIntegerItem(idx++);
12255 int remain = options.Data.Length - idx;
12256
12257 switch (option)
12258 {
12259 case ScriptBaseClass.KFM_COMMAND:
12260 int cmd = (int)options.GetLSLIntegerItem(idx++);
12261 switch (cmd)
12262 {
12263 case ScriptBaseClass.KFM_CMD_PLAY:
12264 group.RootPart.KeyframeMotion.Start();
12265 break;
12266 case ScriptBaseClass.KFM_CMD_STOP:
12267 group.RootPart.KeyframeMotion.Stop();
12268 break;
12269 case ScriptBaseClass.KFM_CMD_PAUSE:
12270 group.RootPart.KeyframeMotion.Pause();
12271 break;
12272 }
12273 break;
12274 }
12275 }
12276 }
12277 }
10916 } 12278 }
10917 12279
10918 public class NotecardCache 12280 public class NotecardCache
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 0d4ea19..60568a8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -137,6 +137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
137 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow; 137 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow;
138 internal float m_ScriptDelayFactor = 1.0f; 138 internal float m_ScriptDelayFactor = 1.0f;
139 internal float m_ScriptDistanceFactor = 1.0f; 139 internal float m_ScriptDistanceFactor = 1.0f;
140 internal bool m_debuggerSafe = false;
140 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); 141 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
141 142
142 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) 143 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID)
@@ -145,6 +146,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
145 m_host = host; 146 m_host = host;
146 m_localID = localID; 147 m_localID = localID;
147 m_itemID = itemID; 148 m_itemID = itemID;
149 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
148 150
149 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) 151 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
150 m_OSFunctionsEnabled = true; 152 m_OSFunctionsEnabled = true;
@@ -206,7 +208,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
206 208
207 internal void OSSLError(string msg) 209 internal void OSSLError(string msg)
208 { 210 {
209 throw new Exception("OSSL Runtime Error: " + msg); 211 if (m_debuggerSafe)
212 {
213 OSSLShoutError(msg);
214 }
215 else
216 {
217 throw new Exception("OSSL Runtime Error: " + msg);
218 }
210 } 219 }
211 220
212 /// <summary> 221 /// <summary>
@@ -927,18 +936,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
927 if (target != null) 936 if (target != null)
928 { 937 {
929 UUID animID=UUID.Zero; 938 UUID animID=UUID.Zero;
930 lock (m_host.TaskInventory) 939 m_host.TaskInventory.LockItemsForRead(true);
940 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
931 { 941 {
932 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 942 if (inv.Value.Name == animation)
933 { 943 {
934 if (inv.Value.Name == animation) 944 if (inv.Value.Type == (int)AssetType.Animation)
935 { 945 animID = inv.Value.AssetID;
936 if (inv.Value.Type == (int)AssetType.Animation) 946 continue;
937 animID = inv.Value.AssetID;
938 continue;
939 }
940 } 947 }
941 } 948 }
949 m_host.TaskInventory.LockItemsForRead(false);
942 if (animID == UUID.Zero) 950 if (animID == UUID.Zero)
943 target.Animator.AddAnimation(animation, m_host.UUID); 951 target.Animator.AddAnimation(animation, m_host.UUID);
944 else 952 else
@@ -965,18 +973,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
965 if (target != null) 973 if (target != null)
966 { 974 {
967 UUID animID = UUID.Zero; 975 UUID animID = UUID.Zero;
968 lock (m_host.TaskInventory) 976 m_host.TaskInventory.LockItemsForRead(true);
977 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
969 { 978 {
970 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 979 if (inv.Value.Name == animation)
971 { 980 {
972 if (inv.Value.Name == animation) 981 if (inv.Value.Type == (int)AssetType.Animation)
973 { 982 animID = inv.Value.AssetID;
974 if (inv.Value.Type == (int)AssetType.Animation) 983 continue;
975 animID = inv.Value.AssetID;
976 continue;
977 }
978 } 984 }
979 } 985 }
986 m_host.TaskInventory.LockItemsForRead(false);
980 987
981 if (animID == UUID.Zero) 988 if (animID == UUID.Zero)
982 target.Animator.RemoveAnimation(animation); 989 target.Animator.RemoveAnimation(animation);
@@ -1797,6 +1804,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1797 1804
1798 if (!UUID.TryParse(notecardNameOrUuid, out assetID)) 1805 if (!UUID.TryParse(notecardNameOrUuid, out assetID))
1799 { 1806 {
1807 m_host.TaskInventory.LockItemsForRead(true);
1800 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1808 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1801 { 1809 {
1802 if (item.Type == 7 && item.Name == notecardNameOrUuid) 1810 if (item.Type == 7 && item.Name == notecardNameOrUuid)
@@ -1804,6 +1812,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1804 assetID = item.AssetID; 1812 assetID = item.AssetID;
1805 } 1813 }
1806 } 1814 }
1815 m_host.TaskInventory.LockItemsForRead(false);
1807 } 1816 }
1808 1817
1809 if (assetID == UUID.Zero) 1818 if (assetID == UUID.Zero)
@@ -2271,7 +2280,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2271 CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); 2280 CheckThreatLevel(ThreatLevel.High, "osNpcCreate");
2272 m_host.AddScriptLPS(1); 2281 m_host.AddScriptLPS(1);
2273 2282
2274 return NpcCreate(firstname, lastname, position, notecard, false, false); 2283 return NpcCreate(firstname, lastname, position, notecard, true, false);
2275 } 2284 }
2276 2285
2277 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options) 2286 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options)
@@ -2282,24 +2291,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2282 return NpcCreate( 2291 return NpcCreate(
2283 firstname, lastname, position, notecard, 2292 firstname, lastname, position, notecard,
2284 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0, 2293 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0,
2285 (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) != 0); 2294 false);
2295// (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) != 0);
2286 } 2296 }
2287 2297
2288 private LSL_Key NpcCreate( 2298 private LSL_Key NpcCreate(
2289 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent) 2299 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent)
2290 { 2300 {
2301 if (!owned)
2302 OSSLError("Unowned NPCs are unsupported");
2303
2304 string groupTitle = String.Empty;
2305
2306 if (!World.Permissions.CanRezObject(1, m_host.OwnerID, new Vector3((float)position.x, (float)position.y, (float)position.z)))
2307 return new LSL_Key(UUID.Zero.ToString());
2308
2309 if (firstname != String.Empty || lastname != String.Empty)
2310 {
2311 if (firstname != "Shown outfit:")
2312 groupTitle = "- NPC -";
2313 }
2314
2291 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2315 INPCModule module = World.RequestModuleInterface<INPCModule>();
2292 if (module != null) 2316 if (module != null)
2293 { 2317 {
2294 AvatarAppearance appearance = null; 2318 AvatarAppearance appearance = null;
2295 2319
2296 UUID id; 2320// UUID id;
2297 if (UUID.TryParse(notecard, out id)) 2321// if (UUID.TryParse(notecard, out id))
2298 { 2322// {
2299 ScenePresence clonePresence = World.GetScenePresence(id); 2323// ScenePresence clonePresence = World.GetScenePresence(id);
2300 if (clonePresence != null) 2324// if (clonePresence != null)
2301 appearance = clonePresence.Appearance; 2325// appearance = clonePresence.Appearance;
2302 } 2326// }
2303 2327
2304 if (appearance == null) 2328 if (appearance == null)
2305 { 2329 {
@@ -2327,6 +2351,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2327 World, 2351 World,
2328 appearance); 2352 appearance);
2329 2353
2354 ScenePresence sp;
2355 if (World.TryGetScenePresence(x, out sp))
2356 {
2357 sp.Grouptitle = groupTitle;
2358 sp.SendAvatarDataToAllAgents();
2359 }
2330 return new LSL_Key(x.ToString()); 2360 return new LSL_Key(x.ToString());
2331 } 2361 }
2332 2362
@@ -2617,16 +2647,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2617 CheckThreatLevel(ThreatLevel.High, "osNpcRemove"); 2647 CheckThreatLevel(ThreatLevel.High, "osNpcRemove");
2618 m_host.AddScriptLPS(1); 2648 m_host.AddScriptLPS(1);
2619 2649
2620 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2650 ManualResetEvent ev = new ManualResetEvent(false);
2621 if (module != null)
2622 {
2623 UUID npcId = new UUID(npc.m_string);
2624 2651
2625 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2652 Util.FireAndForget(delegate(object x) {
2626 return; 2653 try
2654 {
2655 INPCModule module = World.RequestModuleInterface<INPCModule>();
2656 if (module != null)
2657 {
2658 UUID npcId = new UUID(npc.m_string);
2627 2659
2628 module.DeleteNPC(npcId, World); 2660 ILandObject l = World.LandChannel.GetLandObject(m_host.GroupPosition.X, m_host.GroupPosition.Y);
2629 } 2661 if (l == null || m_host.OwnerID != l.LandData.OwnerID)
2662 {
2663 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2664 return;
2665 }
2666
2667 module.DeleteNPC(npcId, World);
2668 }
2669 }
2670 finally
2671 {
2672 ev.Set();
2673 }
2674 });
2675 ev.WaitOne();
2630 } 2676 }
2631 2677
2632 public void osNpcPlayAnimation(LSL_Key npc, string animation) 2678 public void osNpcPlayAnimation(LSL_Key npc, string animation)
@@ -3160,4 +3206,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3160 ((LSL_Api)m_LSL_Api).DetachFromAvatar(); 3206 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3161 } 3207 }
3162 } 3208 }
3163} \ No newline at end of file 3209}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 3844753..19f3ce1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -319,7 +319,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
319 float dy; 319 float dy;
320 float dz; 320 float dz;
321 321
322 Quaternion q = SensePoint.GetWorldRotation(); 322// Quaternion q = SensePoint.RotationOffset;
323 Quaternion q = SensePoint.GetWorldRotation(); // non-attached prim Sensor *always* uses World rotation!
323 if (SensePoint.ParentGroup.IsAttachment) 324 if (SensePoint.ParentGroup.IsAttachment)
324 { 325 {
325 // In attachments, rotate the sensor cone with the 326 // In attachments, rotate the sensor cone with the
@@ -333,7 +334,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
333 // Position of a sensor in a child prim attached to an avatar 334 // Position of a sensor in a child prim attached to an avatar
334 // will be still wrong. 335 // will be still wrong.
335 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 336 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
336 q = avatar.Rotation * q; 337 fromRegionPos = avatar.AbsolutePosition;
338 q = avatar.Rotation;
337 } 339 }
338 340
339 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 341 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
@@ -463,7 +465,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
463 // Position of a sensor in a child prim attached to an avatar 465 // Position of a sensor in a child prim attached to an avatar
464 // will be still wrong. 466 // will be still wrong.
465 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 467 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
466 q = avatar.Rotation * q; 468 if (avatar == null)
469 return sensedEntities;
470 fromRegionPos = avatar.AbsolutePosition;
471 q = avatar.Rotation;
467 } 472 }
468 473
469 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 474 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
index bc63030..9ee6946 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
@@ -118,25 +118,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
118 if (Timers.Count == 0) 118 if (Timers.Count == 0)
119 return; 119 return;
120 120
121 Dictionary<string, TimerClass>.ValueCollection tvals;
121 lock (TimerListLock) 122 lock (TimerListLock)
122 { 123 {
123 // Go through all timers 124 // Go through all timers
124 Dictionary<string, TimerClass>.ValueCollection tvals = Timers.Values; 125 tvals = Timers.Values;
125 foreach (TimerClass ts in tvals) 126 }
127
128 foreach (TimerClass ts in tvals)
129 {
130 // Time has passed?
131 if (ts.next < DateTime.Now.Ticks)
126 { 132 {
127 // Time has passed? 133 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next);
128 if (ts.next < DateTime.Now.Ticks) 134 // Add it to queue
129 { 135 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
130 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next); 136 new EventParams("timer", new Object[0],
131 // Add it to queue 137 new DetectParams[0]));
132 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, 138 // set next interval
133 new EventParams("timer", new Object[0], 139
134 new DetectParams[0])); 140 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
135 // set next interval 141 ts.next = DateTime.Now.Ticks + ts.interval;
136
137 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
138 ts.next = DateTime.Now.Ticks + ts.interval;
139 }
140 } 142 }
141 } 143 }
142 } 144 }