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.cs116
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs3155
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs102
-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, 2608 insertions, 828 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..b5fa6de
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
@@ -0,0 +1,116 @@
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 TaskInventoryItem m_item;
63 internal bool m_CMFunctionsEnabled = false;
64
65 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
66 {
67 m_ScriptEngine = ScriptEngine;
68 m_host = host;
69 m_item = item;
70
71 if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false))
72 m_CMFunctionsEnabled = true;
73 }
74
75 public override Object InitializeLifetimeService()
76 {
77 ILease lease = (ILease)base.InitializeLifetimeService();
78
79 if (lease.CurrentState == LeaseState.Initial)
80 {
81 lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
82 // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
83 // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
84 }
85 return lease;
86 }
87
88 public Scene World
89 {
90 get { return m_ScriptEngine.World; }
91 }
92
93 public string cmDetectedCountry(int number)
94 {
95 m_host.AddScriptLPS(1);
96 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
97 if (detectedParams == null)
98 return String.Empty;
99 return detectedParams.Country;
100 }
101
102 public string cmGetAgentCountry(LSL_Key key)
103 {
104 if (!World.Permissions.IsGod(m_host.OwnerID))
105 return String.Empty;
106
107 UUID uuid;
108
109 if (!UUID.TryParse(key, out uuid))
110 return String.Empty;
111
112 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
113 return account.UserCountry;
114 }
115 }
116}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 12eb098..04c4c00 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{
@@ -103,15 +107,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
103 protected int m_notecardLineReadCharsMax = 255; 107 protected int m_notecardLineReadCharsMax = 255;
104 protected int m_scriptConsoleChannel = 0; 108 protected int m_scriptConsoleChannel = 0;
105 protected bool m_scriptConsoleChannelEnabled = false; 109 protected bool m_scriptConsoleChannelEnabled = false;
110 protected bool m_debuggerSafe = false;
106 protected IUrlModule m_UrlModule = null; 111 protected IUrlModule m_UrlModule = null;
107 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); 112 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
108 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 113 new Dictionary<UUID, UserInfoCacheEntry>();
114 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
115
116 protected Timer m_ShoutSayTimer;
117 protected int m_SayShoutCount = 0;
118
119 private Dictionary<string, string> MovementAnimationsForLSL =
120 new Dictionary<string, string> {
121 {"FLY", "Flying"},
122 {"FLYSLOW", "FlyingSlow"},
123 {"HOVER_UP", "Hovering Up"},
124 {"HOVER_DOWN", "Hovering Down"},
125 {"HOVER", "Hovering"},
126 {"LAND", "Landing"},
127 {"FALLDOWN", "Falling Down"},
128 {"PREJUMP", "PreJumping"},
129 {"JUMP", "Jumping"},
130 {"STANDUP", "Standing Up"},
131 {"SOFT_LAND", "Soft Landing"},
132 {"STAND", "Standing"},
133 {"CROUCHWALK", "CrouchWalking"},
134 {"RUN", "Running"},
135 {"WALK", "Walking"},
136 {"CROUCH", "Crouching"},
137 {"TURNLEFT", "Turning Left"},
138 {"TURNRIGHT", "Turning Right"}
139 };
109 140
110 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 141 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
111 { 142 {
143 m_ShoutSayTimer = new Timer(1000);
144 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
145 m_ShoutSayTimer.AutoReset = true;
146 m_ShoutSayTimer.Start();
147
112 m_ScriptEngine = ScriptEngine; 148 m_ScriptEngine = ScriptEngine;
113 m_host = host; 149 m_host = host;
114 m_item = item; 150 m_item = item;
151 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
115 152
116 LoadLimits(); // read script limits from config. 153 LoadLimits(); // read script limits from config.
117 154
@@ -171,6 +208,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
171 get { return m_ScriptEngine.World; } 208 get { return m_ScriptEngine.World; }
172 } 209 }
173 210
211 [DebuggerNonUserCode]
174 public void state(string newState) 212 public void state(string newState)
175 { 213 {
176 m_ScriptEngine.SetState(m_item.ItemID, newState); 214 m_ScriptEngine.SetState(m_item.ItemID, newState);
@@ -180,6 +218,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
180 /// Reset the named script. The script must be present 218 /// Reset the named script. The script must be present
181 /// in the same prim. 219 /// in the same prim.
182 /// </summary> 220 /// </summary>
221 [DebuggerNonUserCode]
183 public void llResetScript() 222 public void llResetScript()
184 { 223 {
185 m_host.AddScriptLPS(1); 224 m_host.AddScriptLPS(1);
@@ -236,9 +275,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
236 } 275 }
237 } 276 }
238 277
278 public List<ScenePresence> GetLinkAvatars(int linkType)
279 {
280 List<ScenePresence> ret = new List<ScenePresence>();
281 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
282 return ret;
283
284 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
285
286 switch (linkType)
287 {
288 case ScriptBaseClass.LINK_SET:
289 return avs;
290
291 case ScriptBaseClass.LINK_ROOT:
292 return ret;
293
294 case ScriptBaseClass.LINK_ALL_OTHERS:
295 return avs;
296
297 case ScriptBaseClass.LINK_ALL_CHILDREN:
298 return avs;
299
300 case ScriptBaseClass.LINK_THIS:
301 return ret;
302
303 default:
304 if (linkType < 0)
305 return ret;
306
307 int partCount = m_host.ParentGroup.GetPartCount();
308
309 if (linkType <= partCount)
310 {
311 return ret;
312 }
313 else
314 {
315 linkType = linkType - partCount;
316 if (linkType > avs.Count)
317 {
318 return ret;
319 }
320 else
321 {
322 ret.Add(avs[linkType-1]);
323 return ret;
324 }
325 }
326 }
327 }
328
239 public List<SceneObjectPart> GetLinkParts(int linkType) 329 public List<SceneObjectPart> GetLinkParts(int linkType)
240 { 330 {
241 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 331 List<SceneObjectPart> ret = new List<SceneObjectPart>();
332 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
333 return ret;
242 ret.Add(m_host); 334 ret.Add(m_host);
243 335
244 switch (linkType) 336 switch (linkType)
@@ -432,31 +524,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
432 524
433 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 525 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
434 526
435 /// <summary> 527 // Utility function for llRot2Euler
436 /// Convert an LSL rotation to a Euler vector. 528
437 /// </summary> 529 // normalize an angle between -PI and PI (-180 to +180 degrees)
438 /// <remarks> 530 protected double NormalizeAngle(double angle)
439 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
440 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
441 /// </remarks>
442 /// <param name="r"></param>
443 /// <returns></returns>
444 public LSL_Vector llRot2Euler(LSL_Rotation r)
445 { 531 {
446 m_host.AddScriptLPS(1); 532 if (angle > -Math.PI && angle < Math.PI)
533 return angle;
534
535 int numPis = (int)(Math.PI / angle);
536 double remainder = angle - Math.PI * numPis;
537 if (numPis % 2 == 1)
538 return Math.PI - angle;
539 return remainder;
540 }
447 541
448 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 542 public LSL_Vector llRot2Euler(LSL_Rotation q1)
449 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 543 {
450 if (m == 0.0) return new LSL_Vector(); 544 m_host.AddScriptLPS(1);
451 double x = Math.Atan2(-v.y, v.z); 545 LSL_Vector eul = new LSL_Vector();
452 double sin = v.x / m;
453 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities.
454 double y = Math.Asin(sin);
455 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
456 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)));
457 double z = Math.Atan2(v.y, v.x);
458 546
459 return new LSL_Vector(x, y, z); 547 double sqw = q1.s*q1.s;
548 double sqx = q1.x*q1.x;
549 double sqy = q1.z*q1.z;
550 double sqz = q1.y*q1.y;
551 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
552 double test = q1.x*q1.z + q1.y*q1.s;
553 if (test > 0.4999*unit) { // singularity at north pole
554 eul.z = 2 * Math.Atan2(q1.x,q1.s);
555 eul.y = Math.PI/2;
556 eul.x = 0;
557 return eul;
558 }
559 if (test < -0.4999*unit) { // singularity at south pole
560 eul.z = -2 * Math.Atan2(q1.x,q1.s);
561 eul.y = -Math.PI/2;
562 eul.x = 0;
563 return eul;
564 }
565 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
566 eul.y = Math.Asin(2*test/unit);
567 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
568 return eul;
460 } 569 }
461 570
462 /* From wiki: 571 /* From wiki:
@@ -658,77 +767,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
658 { 767 {
659 //A and B should both be normalized 768 //A and B should both be normalized
660 m_host.AddScriptLPS(1); 769 m_host.AddScriptLPS(1);
661 LSL_Rotation rotBetween; 770 /* This method is more accurate than the SL one, and thus causes problems
662 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 771 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
663 // continue calculation. 772
664 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 773 double dotProduct = LSL_Vector.Dot(a, b);
774 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
775 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
776 double angle = Math.Acos(dotProduct / magProduct);
777 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
778 double s = Math.Sin(angle / 2);
779
780 double x = axis.x * s;
781 double y = axis.y * s;
782 double z = axis.z * s;
783 double w = Math.Cos(angle / 2);
784
785 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
786 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
787
788 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
789 */
790
791 // This method mimics the 180 errors found in SL
792 // See www.euclideanspace.com... angleBetween
793 LSL_Vector vec_a = a;
794 LSL_Vector vec_b = b;
795
796 // Eliminate zero length
797 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
798 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
799 if (vec_a_mag < 0.00001 ||
800 vec_b_mag < 0.00001)
665 { 801 {
666 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 802 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
667 } 803 }
668 else 804
805 // Normalize
806 vec_a = llVecNorm(vec_a);
807 vec_b = llVecNorm(vec_b);
808
809 // Calculate axis and rotation angle
810 LSL_Vector axis = vec_a % vec_b;
811 LSL_Float cos_theta = vec_a * vec_b;
812
813 // Check if parallel
814 if (cos_theta > 0.99999)
669 { 815 {
670 a = LSL_Vector.Norm(a); 816 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
671 b = LSL_Vector.Norm(b); 817 }
672 double dotProduct = LSL_Vector.Dot(a, b); 818
673 // There are two degenerate cases possible. These are for vectors 180 or 819 // Check if anti-parallel
674 // 0 degrees apart. These have to be detected and handled individually. 820 else if (cos_theta < -0.99999)
675 // 821 {
676 // Check for vectors 180 degrees apart. 822 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
677 // A dot product of -1 would mean the angle between vectors is 180 degrees. 823 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
678 if (dotProduct < -0.9999999f) 824 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
679 { 825 }
680 // First assume X axis is orthogonal to the vectors. 826 else // other rotation
681 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 827 {
682 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 828 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
683 // Check for near zero vector. A very small non-zero number here will create 829 axis = llVecNorm(axis);
684 // a rotation in an undesired direction. 830 double x, y, z, s, t;
685 if (LSL_Vector.Mag(orthoVector) > 0.0001) 831 s = Math.Cos(theta);
686 { 832 t = Math.Sin(theta);
687 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 833 x = axis.x * t;
688 } 834 y = axis.y * t;
689 // If the magnitude of the vector was near zero, then assume the X axis is not 835 z = axis.z * t;
690 // orthogonal and use the Z axis instead. 836 return new LSL_Rotation(x,y,z,s);
691 else
692 {
693 // Set 180 z rotation.
694 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
695 }
696 }
697 // Check for parallel vectors.
698 // A dot product of 1 would mean the angle between vectors is 0 degrees.
699 else if (dotProduct > 0.9999999f)
700 {
701 // Set zero rotation.
702 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
703 }
704 else
705 {
706 // All special checks have been performed so get the axis of rotation.
707 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
708 // Quarternion s value is the length of the unit vector + dot product.
709 double qs = 1.0 + dotProduct;
710 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
711 // Normalize the rotation.
712 double mag = LSL_Rotation.Mag(rotBetween);
713 // We shouldn't have to worry about a divide by zero here. The qs value will be
714 // non-zero because we already know if we're here, then the dotProduct is not -1 so
715 // qs will not be zero. Also, we've already handled the input vectors being zero so the
716 // crossProduct vector should also not be zero.
717 rotBetween.x = rotBetween.x / mag;
718 rotBetween.y = rotBetween.y / mag;
719 rotBetween.z = rotBetween.z / mag;
720 rotBetween.s = rotBetween.s / mag;
721 // Check for undefined values and set zero rotation if any found. This code might not actually be required
722 // any longer since zero vectors are checked for at the top.
723 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
724 {
725 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
726 }
727 }
728 } 837 }
729 return rotBetween;
730 } 838 }
731 839
732 public void llWhisper(int channelID, string text) 840 public void llWhisper(int channelID, string text)
733 { 841 {
734 m_host.AddScriptLPS(1); 842 m_host.AddScriptLPS(1);
@@ -748,6 +856,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
748 { 856 {
749 m_host.AddScriptLPS(1); 857 m_host.AddScriptLPS(1);
750 858
859 if (channelID == 0)
860 m_SayShoutCount++;
861
862 if (m_SayShoutCount >= 11)
863 ScriptSleep(2000);
864
751 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 865 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
752 { 866 {
753 Console.WriteLine(text); 867 Console.WriteLine(text);
@@ -770,6 +884,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
770 { 884 {
771 m_host.AddScriptLPS(1); 885 m_host.AddScriptLPS(1);
772 886
887 if (channelID == 0)
888 m_SayShoutCount++;
889
890 if (m_SayShoutCount >= 11)
891 ScriptSleep(2000);
892
773 if (text.Length > 1023) 893 if (text.Length > 1023)
774 text = text.Substring(0, 1023); 894 text = text.Substring(0, 1023);
775 895
@@ -801,22 +921,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
801 921
802 public void llRegionSayTo(string target, int channel, string msg) 922 public void llRegionSayTo(string target, int channel, string msg)
803 { 923 {
924 string error = String.Empty;
925
804 if (msg.Length > 1023) 926 if (msg.Length > 1023)
805 msg = msg.Substring(0, 1023); 927 msg = msg.Substring(0, 1023);
806 928
807 m_host.AddScriptLPS(1); 929 m_host.AddScriptLPS(1);
808 930
809 if (channel == ScriptBaseClass.DEBUG_CHANNEL)
810 {
811 return;
812 }
813
814 UUID TargetID; 931 UUID TargetID;
815 UUID.TryParse(target, out TargetID); 932 UUID.TryParse(target, out TargetID);
816 933
817 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 934 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
818 if (wComm != null) 935 if (wComm != null)
819 wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg); 936 if (!wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg, out error))
937 LSLError(error);
820 } 938 }
821 939
822 public LSL_Integer llListen(int channelID, string name, string ID, string msg) 940 public LSL_Integer llListen(int channelID, string name, string ID, string msg)
@@ -1072,10 +1190,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1072 return detectedParams.TouchUV; 1190 return detectedParams.TouchUV;
1073 } 1191 }
1074 1192
1193 [DebuggerNonUserCode]
1075 public virtual void llDie() 1194 public virtual void llDie()
1076 { 1195 {
1077 m_host.AddScriptLPS(1); 1196 m_host.AddScriptLPS(1);
1078 throw new SelfDeleteException(); 1197 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1079 } 1198 }
1080 1199
1081 public LSL_Float llGround(LSL_Vector offset) 1200 public LSL_Float llGround(LSL_Vector offset)
@@ -1148,6 +1267,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1148 1267
1149 public void llSetStatus(int status, int value) 1268 public void llSetStatus(int status, int value)
1150 { 1269 {
1270 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1271 return;
1151 m_host.AddScriptLPS(1); 1272 m_host.AddScriptLPS(1);
1152 1273
1153 int statusrotationaxis = 0; 1274 int statusrotationaxis = 0;
@@ -1171,6 +1292,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1171 if (!allow) 1292 if (!allow)
1172 return; 1293 return;
1173 1294
1295 if (m_host.ParentGroup.RootPart.PhysActor != null &&
1296 m_host.ParentGroup.RootPart.PhysActor.IsPhysical)
1297 return;
1298
1174 m_host.ScriptSetPhysicsStatus(true); 1299 m_host.ScriptSetPhysicsStatus(true);
1175 } 1300 }
1176 else 1301 else
@@ -1379,6 +1504,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1379 { 1504 {
1380 m_host.AddScriptLPS(1); 1505 m_host.AddScriptLPS(1);
1381 1506
1507 SetColor(m_host, color, face);
1508 }
1509
1510 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1511 {
1512 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1513 return;
1514
1515 Primitive.TextureEntry tex = part.Shape.Textures;
1516 Color4 texcolor;
1517 if (face >= 0 && face < GetNumberOfSides(part))
1518 {
1519 texcolor = tex.CreateFace((uint)face).RGBA;
1520 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1521 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1522 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1523 tex.FaceTextures[face].RGBA = texcolor;
1524 part.UpdateTextureEntry(tex.GetBytes());
1525 return;
1526 }
1527 else if (face == ScriptBaseClass.ALL_SIDES)
1528 {
1529 for (uint i = 0; i < GetNumberOfSides(part); i++)
1530 {
1531 if (tex.FaceTextures[i] != null)
1532 {
1533 texcolor = tex.FaceTextures[i].RGBA;
1534 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1535 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1536 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1537 tex.FaceTextures[i].RGBA = texcolor;
1538 }
1539 texcolor = tex.DefaultTexture.RGBA;
1540 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1541 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1542 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1543 tex.DefaultTexture.RGBA = texcolor;
1544 }
1545 part.UpdateTextureEntry(tex.GetBytes());
1546 return;
1547 }
1548
1382 if (face == ScriptBaseClass.ALL_SIDES) 1549 if (face == ScriptBaseClass.ALL_SIDES)
1383 face = SceneObjectPart.ALL_SIDES; 1550 face = SceneObjectPart.ALL_SIDES;
1384 1551
@@ -1387,6 +1554,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1387 1554
1388 public void SetTexGen(SceneObjectPart part, int face,int style) 1555 public void SetTexGen(SceneObjectPart part, int face,int style)
1389 { 1556 {
1557 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1558 return;
1559
1390 Primitive.TextureEntry tex = part.Shape.Textures; 1560 Primitive.TextureEntry tex = part.Shape.Textures;
1391 MappingType textype; 1561 MappingType textype;
1392 textype = MappingType.Default; 1562 textype = MappingType.Default;
@@ -1417,6 +1587,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1417 1587
1418 public void SetGlow(SceneObjectPart part, int face, float glow) 1588 public void SetGlow(SceneObjectPart part, int face, float glow)
1419 { 1589 {
1590 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1591 return;
1592
1420 Primitive.TextureEntry tex = part.Shape.Textures; 1593 Primitive.TextureEntry tex = part.Shape.Textures;
1421 if (face >= 0 && face < GetNumberOfSides(part)) 1594 if (face >= 0 && face < GetNumberOfSides(part))
1422 { 1595 {
@@ -1442,6 +1615,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1442 1615
1443 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1616 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1444 { 1617 {
1618 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1619 return;
1445 1620
1446 Shininess sval = new Shininess(); 1621 Shininess sval = new Shininess();
1447 1622
@@ -1492,6 +1667,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1492 1667
1493 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1668 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1494 { 1669 {
1670 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1671 return;
1672
1495 Primitive.TextureEntry tex = part.Shape.Textures; 1673 Primitive.TextureEntry tex = part.Shape.Textures;
1496 if (face >= 0 && face < GetNumberOfSides(part)) 1674 if (face >= 0 && face < GetNumberOfSides(part))
1497 { 1675 {
@@ -1552,13 +1730,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1552 m_host.AddScriptLPS(1); 1730 m_host.AddScriptLPS(1);
1553 1731
1554 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1732 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1555 1733 if (parts.Count > 0)
1556 foreach (SceneObjectPart part in parts) 1734 {
1557 SetAlpha(part, alpha, face); 1735 try
1736 {
1737 parts[0].ParentGroup.areUpdatesSuspended = true;
1738 foreach (SceneObjectPart part in parts)
1739 SetAlpha(part, alpha, face);
1740 }
1741 finally
1742 {
1743 parts[0].ParentGroup.areUpdatesSuspended = false;
1744 }
1745 }
1558 } 1746 }
1559 1747
1560 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1748 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1561 { 1749 {
1750 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1751 return;
1752
1562 Primitive.TextureEntry tex = part.Shape.Textures; 1753 Primitive.TextureEntry tex = part.Shape.Textures;
1563 Color4 texcolor; 1754 Color4 texcolor;
1564 if (face >= 0 && face < GetNumberOfSides(part)) 1755 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1611,7 +1802,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1611 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1802 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1612 float wind, float tension, LSL_Vector Force) 1803 float wind, float tension, LSL_Vector Force)
1613 { 1804 {
1614 if (part == null) 1805 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1615 return; 1806 return;
1616 1807
1617 if (flexi) 1808 if (flexi)
@@ -1645,7 +1836,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1645 /// <param name="falloff"></param> 1836 /// <param name="falloff"></param>
1646 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1837 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1647 { 1838 {
1648 if (part == null) 1839 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1649 return; 1840 return;
1650 1841
1651 if (light) 1842 if (light)
@@ -1724,15 +1915,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1724 m_host.AddScriptLPS(1); 1915 m_host.AddScriptLPS(1);
1725 1916
1726 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1917 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1727 1918 if (parts.Count > 0)
1728 foreach (SceneObjectPart part in parts) 1919 {
1729 SetTexture(part, texture, face); 1920 try
1730 1921 {
1922 parts[0].ParentGroup.areUpdatesSuspended = true;
1923 foreach (SceneObjectPart part in parts)
1924 SetTexture(part, texture, face);
1925 }
1926 finally
1927 {
1928 parts[0].ParentGroup.areUpdatesSuspended = false;
1929 }
1930 }
1731 ScriptSleep(200); 1931 ScriptSleep(200);
1732 } 1932 }
1733 1933
1734 protected void SetTexture(SceneObjectPart part, string texture, int face) 1934 protected void SetTexture(SceneObjectPart part, string texture, int face)
1735 { 1935 {
1936 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1937 return;
1938
1736 UUID textureID = new UUID(); 1939 UUID textureID = new UUID();
1737 1940
1738 textureID = InventoryKey(texture, (int)AssetType.Texture); 1941 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1777,6 +1980,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1777 1980
1778 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 1981 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1779 { 1982 {
1983 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1984 return;
1985
1780 Primitive.TextureEntry tex = part.Shape.Textures; 1986 Primitive.TextureEntry tex = part.Shape.Textures;
1781 if (face >= 0 && face < GetNumberOfSides(part)) 1987 if (face >= 0 && face < GetNumberOfSides(part))
1782 { 1988 {
@@ -1813,6 +2019,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1813 2019
1814 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2020 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1815 { 2021 {
2022 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2023 return;
2024
1816 Primitive.TextureEntry tex = part.Shape.Textures; 2025 Primitive.TextureEntry tex = part.Shape.Textures;
1817 if (face >= 0 && face < GetNumberOfSides(part)) 2026 if (face >= 0 && face < GetNumberOfSides(part))
1818 { 2027 {
@@ -1849,6 +2058,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1849 2058
1850 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2059 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1851 { 2060 {
2061 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2062 return;
2063
1852 Primitive.TextureEntry tex = part.Shape.Textures; 2064 Primitive.TextureEntry tex = part.Shape.Textures;
1853 if (face >= 0 && face < GetNumberOfSides(part)) 2065 if (face >= 0 && face < GetNumberOfSides(part))
1854 { 2066 {
@@ -1953,26 +2165,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1953 return real_vec; 2165 return real_vec;
1954 } 2166 }
1955 2167
2168 public LSL_Integer llSetRegionPos(LSL_Vector pos)
2169 {
2170 return new LSL_Integer(SetRegionPos(m_host, pos));
2171 }
2172
2173 protected int SetRegionPos(SceneObjectPart part, LSL_Vector targetPos)
2174 {
2175 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2176 return 0;
2177
2178 SceneObjectGroup grp = part.ParentGroup;
2179
2180 if (grp.IsAttachment)
2181 return 0;
2182
2183 if (grp.RootPart.PhysActor != null && grp.RootPart.PhysActor.IsPhysical)
2184 return 0;
2185
2186 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)
2187 return 0;
2188
2189 float constrainedX = (float)targetPos.x;
2190 float constrainedY = (float)targetPos.y;
2191
2192 if (constrainedX < 0.0f)
2193 constrainedX = 0.0f;
2194 if (constrainedY < 0.0f)
2195 constrainedY = 0.0f;
2196 if (constrainedX >= (float)Constants.RegionSize)
2197 constrainedX = (float)Constants.RegionSize - 0.1f;
2198 if (constrainedY >= (float)Constants.RegionSize)
2199 constrainedY = (float)Constants.RegionSize -0.1f;
2200
2201 float ground = World.GetGroundHeight(constrainedX, constrainedY);
2202
2203 if (targetPos.z < ground)
2204 targetPos.z = ground;
2205
2206 Vector3 dest = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z);
2207
2208 if (!World.Permissions.CanObjectEntry(grp.UUID, false, dest))
2209 return 0;
2210
2211 grp.UpdateGroupPosition(dest);
2212
2213 return 1;
2214 }
2215
1956 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) 2216 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
1957 { 2217 {
1958 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2218 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2219 return;
2220
1959 LSL_Vector currentPos = GetPartLocalPos(part); 2221 LSL_Vector currentPos = GetPartLocalPos(part);
2222 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
1960 2223
1961 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
1962 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
1963 2224
1964 if (part.ParentGroup.RootPart == part) 2225 if (part.ParentGroup.RootPart == part)
1965 { 2226 {
1966 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
1967 targetPos.z = ground;
1968 SceneObjectGroup parent = part.ParentGroup; 2227 SceneObjectGroup parent = part.ParentGroup;
1969 LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); 2228 Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
1970 parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z)); 2229 if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest))
2230 return;
2231 Util.FireAndForget(delegate(object x) {
2232 parent.UpdateGroupPosition(dest);
2233 });
1971 } 2234 }
1972 else 2235 else
1973 { 2236 {
1974 LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); 2237 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
1975 part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z);
1976 SceneObjectGroup parent = part.ParentGroup; 2238 SceneObjectGroup parent = part.ParentGroup;
1977 parent.HasGroupChanged = true; 2239 parent.HasGroupChanged = true;
1978 parent.ScheduleGroupForTerseUpdate(); 2240 parent.ScheduleGroupForTerseUpdate();
@@ -2005,17 +2267,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2005 else 2267 else
2006 { 2268 {
2007 if (part.ParentGroup.IsAttachment) 2269 if (part.ParentGroup.IsAttachment)
2008 {
2009 pos = part.AttachedPos; 2270 pos = part.AttachedPos;
2010 }
2011 else 2271 else
2012 {
2013 pos = part.AbsolutePosition; 2272 pos = part.AbsolutePosition;
2014 }
2015 } 2273 }
2016 2274
2017// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2018
2019 return new LSL_Vector(pos.X, pos.Y, pos.Z); 2275 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2020 } 2276 }
2021 2277
@@ -2024,9 +2280,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2024 m_host.AddScriptLPS(1); 2280 m_host.AddScriptLPS(1);
2025 2281
2026 // try to let this work as in SL... 2282 // try to let this work as in SL...
2027 if (m_host.ParentID == 0) 2283 if (m_host.LinkNum < 2)
2028 { 2284 {
2029 // special case: If we are root, rotate complete SOG to new rotation 2285 // Special case: If we are root, rotate complete SOG to new
2286 // rotation.
2287 // We are root if the link number is 0 (single prim) or 1
2288 // (root prim). ParentID may be nonzero in attachments and
2289 // using it would cause attachments and HUDs to rotate
2290 // to the wrong positions.
2030 SetRot(m_host, Rot2Quaternion(rot)); 2291 SetRot(m_host, Rot2Quaternion(rot));
2031 } 2292 }
2032 else 2293 else
@@ -2051,6 +2312,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2051 2312
2052 protected void SetRot(SceneObjectPart part, Quaternion rot) 2313 protected void SetRot(SceneObjectPart part, Quaternion rot)
2053 { 2314 {
2315 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2316 return;
2317
2054 part.UpdateRotation(rot); 2318 part.UpdateRotation(rot);
2055 // Update rotation does not move the object in the physics scene if it's a linkset. 2319 // Update rotation does not move the object in the physics scene if it's a linkset.
2056 2320
@@ -2066,7 +2330,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2066 // scene 2330 // scene
2067 PhysicsActor pa = part.PhysActor; 2331 PhysicsActor pa = part.PhysActor;
2068 2332
2069 if (pa != null && !pa.IsPhysical) 2333 if (pa != null && !pa.IsPhysical && part == part.ParentGroup.RootPart)
2070 { 2334 {
2071 part.ParentGroup.ResetChildPrimPhysicsPositions(); 2335 part.ParentGroup.ResetChildPrimPhysicsPositions();
2072 } 2336 }
@@ -2205,13 +2469,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2205 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2469 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2206 { 2470 {
2207 m_host.AddScriptLPS(1); 2471 m_host.AddScriptLPS(1);
2208 m_host.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); 2472 m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
2209 } 2473 }
2210 2474
2211 public void llSetTorque(LSL_Vector torque, int local) 2475 public void llSetTorque(LSL_Vector torque, int local)
2212 { 2476 {
2213 m_host.AddScriptLPS(1); 2477 m_host.AddScriptLPS(1);
2214 m_host.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); 2478 m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0);
2215 } 2479 }
2216 2480
2217 public LSL_Vector llGetTorque() 2481 public LSL_Vector llGetTorque()
@@ -2232,16 +2496,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2232 { 2496 {
2233 m_host.AddScriptLPS(1); 2497 m_host.AddScriptLPS(1);
2234 2498
2235 Vector3 vel; 2499 Vector3 vel = Vector3.Zero;
2236 2500
2237 if (m_host.ParentGroup.IsAttachment) 2501 if (m_host.ParentGroup.IsAttachment)
2238 { 2502 {
2239 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); 2503 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2240 vel = avatar.Velocity; 2504 if (avatar != null)
2505 vel = avatar.Velocity;
2241 } 2506 }
2242 else 2507 else
2243 { 2508 {
2244 vel = m_host.Velocity; 2509 vel = m_host.ParentGroup.RootPart.Velocity;
2245 } 2510 }
2246 2511
2247 return new LSL_Vector(vel.X, vel.Y, vel.Z); 2512 return new LSL_Vector(vel.X, vel.Y, vel.Z);
@@ -2790,8 +3055,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2790 3055
2791 if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) 3056 if (pa != null && pa.IsPhysical && llvel != Vector3.Zero)
2792 { 3057 {
2793 //Recoil. 3058 // recoil
2794 llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); 3059 llvel *= -groupmass;
3060 llApplyImpulse(new LSL_Vector(llvel.X, llvel.Y,llvel.Z), 0);
2795 } 3061 }
2796 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3062 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
2797 return; 3063 return;
@@ -2813,35 +3079,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2813 public void llLookAt(LSL_Vector target, double strength, double damping) 3079 public void llLookAt(LSL_Vector target, double strength, double damping)
2814 { 3080 {
2815 m_host.AddScriptLPS(1); 3081 m_host.AddScriptLPS(1);
2816 // Determine where we are looking from
2817 LSL_Vector from = llGetPos();
2818 3082
2819 // Work out the normalised vector from the source to the target 3083 // Get the normalized vector to the target
2820 LSL_Vector delta = llVecNorm(target - from); 3084 LSL_Vector d1 = llVecNorm(target - llGetPos());
2821 LSL_Vector angle = new LSL_Vector(0,0,0);
2822 3085
2823 // Calculate the yaw 3086 // Get the bearing (yaw)
2824 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3087 LSL_Vector a1 = new LSL_Vector(0,0,0);
2825 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3088 a1.z = llAtan2(d1.y, d1.x);
2826 3089
2827 // Calculate pitch 3090 // Get the elevation (pitch)
2828 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3091 LSL_Vector a2 = new LSL_Vector(0,0,0);
3092 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2829 3093
2830 // we need to convert from a vector describing 3094 LSL_Rotation r1 = llEuler2Rot(a1);
2831 // the angles of rotation in radians into rotation value 3095 LSL_Rotation r2 = llEuler2Rot(a2);
2832 LSL_Rotation rot = llEuler2Rot(angle); 3096 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2833
2834 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2835 // set the rotation of the object, copy that behavior
2836 PhysicsActor pa = m_host.PhysActor;
2837 3097
2838 if (strength == 0 || pa == null || !pa.IsPhysical) 3098 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2839 { 3099 {
2840 llSetRot(rot); 3100 // Do nothing if either value is 0 (this has been checked in SL)
3101 if (strength <= 0.0 || damping <= 0.0)
3102 return;
3103
3104 llSetRot(r3 * r2 * r1);
2841 } 3105 }
2842 else 3106 else
2843 { 3107 {
2844 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3108 if (strength == 0)
3109 {
3110 llSetRot(r3 * r2 * r1);
3111 return;
3112 }
3113
3114 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2845 } 3115 }
2846 } 3116 }
2847 3117
@@ -2887,17 +3157,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2887 } 3157 }
2888 else 3158 else
2889 { 3159 {
2890 if (m_host.IsRoot) 3160 // new SL always returns object mass
2891 { 3161// if (m_host.IsRoot)
3162// {
2892 return m_host.ParentGroup.GetMass(); 3163 return m_host.ParentGroup.GetMass();
2893 } 3164// }
2894 else 3165// else
2895 { 3166// {
2896 return m_host.GetMass(); 3167// return m_host.GetMass();
2897 } 3168// }
2898 } 3169 }
2899 } 3170 }
2900 3171
3172
3173 public LSL_Float llGetMassMKS()
3174 {
3175 return 100f * llGetMass();
3176 }
3177
2901 public void llCollisionFilter(string name, string id, int accept) 3178 public void llCollisionFilter(string name, string id, int accept)
2902 { 3179 {
2903 m_host.AddScriptLPS(1); 3180 m_host.AddScriptLPS(1);
@@ -2972,7 +3249,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2972 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3249 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
2973 3250
2974 if (attachmentsModule != null) 3251 if (attachmentsModule != null)
2975 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false); 3252 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true);
2976 else 3253 else
2977 return false; 3254 return false;
2978 } 3255 }
@@ -3002,9 +3279,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3002 { 3279 {
3003 m_host.AddScriptLPS(1); 3280 m_host.AddScriptLPS(1);
3004 3281
3005// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3006// return;
3007
3008 if (m_item.PermsGranter != m_host.OwnerID) 3282 if (m_item.PermsGranter != m_host.OwnerID)
3009 return; 3283 return;
3010 3284
@@ -3047,6 +3321,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3047 3321
3048 public void llInstantMessage(string user, string message) 3322 public void llInstantMessage(string user, string message)
3049 { 3323 {
3324 UUID result;
3325 if (!UUID.TryParse(user, out result))
3326 {
3327 ShoutError("An invalid key was passed to llInstantMessage");
3328 ScriptSleep(2000);
3329 return;
3330 }
3331
3332
3050 m_host.AddScriptLPS(1); 3333 m_host.AddScriptLPS(1);
3051 3334
3052 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3335 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3061,14 +3344,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3061 UUID friendTransactionID = UUID.Random(); 3344 UUID friendTransactionID = UUID.Random();
3062 3345
3063 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3346 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3064 3347
3065 GridInstantMessage msg = new GridInstantMessage(); 3348 GridInstantMessage msg = new GridInstantMessage();
3066 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3349 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3067 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3350 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3068 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3351 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3069// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3352// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3070// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3353// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3071 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3354// DateTime dt = DateTime.UtcNow;
3355//
3356// // Ticks from UtcNow, but make it look like local. Evil, huh?
3357// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3358//
3359// try
3360// {
3361// // Convert that to the PST timezone
3362// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3363// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3364// }
3365// catch
3366// {
3367// // No logging here, as it could be VERY spammy
3368// }
3369//
3370// // And make it look local again to fool the unix time util
3371// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3372
3373 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3374
3072 //if (client != null) 3375 //if (client != null)
3073 //{ 3376 //{
3074 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3377 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3082,12 +3385,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3082 msg.message = message.Substring(0, 1024); 3385 msg.message = message.Substring(0, 1024);
3083 else 3386 else
3084 msg.message = message; 3387 msg.message = message;
3085 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3388 msg.dialog = (byte)19; // MessageFromObject
3086 msg.fromGroup = false;// fromGroup; 3389 msg.fromGroup = false;// fromGroup;
3087 msg.offline = (byte)0; //offline; 3390 msg.offline = (byte)0; //offline;
3088 msg.ParentEstateID = 0; //ParentEstateID; 3391 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3089 msg.Position = new Vector3(m_host.AbsolutePosition); 3392 msg.Position = new Vector3(m_host.AbsolutePosition);
3090 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3393 msg.RegionID = World.RegionInfo.RegionID.Guid;
3091 msg.binaryBucket 3394 msg.binaryBucket
3092 = Util.StringToBytes256( 3395 = Util.StringToBytes256(
3093 "{0}/{1}/{2}/{3}", 3396 "{0}/{1}/{2}/{3}",
@@ -3115,7 +3418,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3115 } 3418 }
3116 3419
3117 emailModule.SendEmail(m_host.UUID, address, subject, message); 3420 emailModule.SendEmail(m_host.UUID, address, subject, message);
3118 llSleep(EMAIL_PAUSE_TIME); 3421 ScriptSleep(EMAIL_PAUSE_TIME * 1000);
3119 } 3422 }
3120 3423
3121 public void llGetNextEmail(string address, string subject) 3424 public void llGetNextEmail(string address, string subject)
@@ -3359,15 +3662,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3359 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3662 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3360 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3663 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3361 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3664 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3665 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3362 ScriptBaseClass.PERMISSION_ATTACH; 3666 ScriptBaseClass.PERMISSION_ATTACH;
3363 3667
3364 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3668 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3365 { 3669 {
3366 lock (m_host.TaskInventory) 3670 m_host.TaskInventory.LockItemsForWrite(true);
3367 { 3671 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3368 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3672 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3369 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3673 m_host.TaskInventory.LockItemsForWrite(false);
3370 }
3371 3674
3372 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3675 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3373 "run_time_permissions", new Object[] { 3676 "run_time_permissions", new Object[] {
@@ -3377,28 +3680,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3377 return; 3680 return;
3378 } 3681 }
3379 } 3682 }
3380 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3683 else
3381 { 3684 {
3382 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3685 bool sitting = false;
3383 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3686 if (m_host.SitTargetAvatar == agentID)
3384 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3687 {
3385 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3688 sitting = true;
3386 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3689 }
3690 else
3691 {
3692 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3693 {
3694 if (p.SitTargetAvatar == agentID)
3695 sitting = true;
3696 }
3697 }
3387 3698
3388 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3699 if (sitting)
3389 { 3700 {
3390 lock (m_host.TaskInventory) 3701 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3702 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3703 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3704 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3705 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3706
3707 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3391 { 3708 {
3709 m_host.TaskInventory.LockItemsForWrite(true);
3392 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3710 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3393 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3711 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3394 } 3712 m_host.TaskInventory.LockItemsForWrite(false);
3395 3713
3396 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3714 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3397 "run_time_permissions", new Object[] { 3715 "run_time_permissions", new Object[] {
3398 new LSL_Integer(perm) }, 3716 new LSL_Integer(perm) },
3399 new DetectParams[0])); 3717 new DetectParams[0]));
3400 3718
3401 return; 3719 return;
3720 }
3402 } 3721 }
3403 } 3722 }
3404 3723
@@ -3435,11 +3754,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3435 3754
3436 if (!m_waitingForScriptAnswer) 3755 if (!m_waitingForScriptAnswer)
3437 { 3756 {
3438 lock (m_host.TaskInventory) 3757 m_host.TaskInventory.LockItemsForWrite(true);
3439 { 3758 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3440 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3759 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3441 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 3760 m_host.TaskInventory.LockItemsForWrite(false);
3442 }
3443 3761
3444 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3762 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3445 m_waitingForScriptAnswer=true; 3763 m_waitingForScriptAnswer=true;
@@ -3468,14 +3786,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3468 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3786 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3469 llReleaseControls(); 3787 llReleaseControls();
3470 3788
3471 lock (m_host.TaskInventory) 3789 m_host.TaskInventory.LockItemsForWrite(true);
3472 { 3790 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3473 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 3791 m_host.TaskInventory.LockItemsForWrite(false);
3474 } 3792
3475 3793 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3476 m_ScriptEngine.PostScriptEvent( 3794 "run_time_permissions", new Object[] {
3477 m_item.ItemID, 3795 new LSL_Integer(answer) },
3478 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); 3796 new DetectParams[0]));
3479 } 3797 }
3480 3798
3481 public LSL_String llGetPermissionsKey() 3799 public LSL_String llGetPermissionsKey()
@@ -3514,14 +3832,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3514 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3832 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3515 { 3833 {
3516 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3834 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3517 3835 if (parts.Count > 0)
3518 foreach (SceneObjectPart part in parts) 3836 {
3519 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3837 try
3838 {
3839 parts[0].ParentGroup.areUpdatesSuspended = true;
3840 foreach (SceneObjectPart part in parts)
3841 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3842 }
3843 finally
3844 {
3845 parts[0].ParentGroup.areUpdatesSuspended = false;
3846 }
3847 }
3520 } 3848 }
3521 3849
3522 public void llCreateLink(string target, int parent) 3850 public void llCreateLink(string target, int parent)
3523 { 3851 {
3524 m_host.AddScriptLPS(1); 3852 m_host.AddScriptLPS(1);
3853
3525 UUID targetID; 3854 UUID targetID;
3526 3855
3527 if (!UUID.TryParse(target, out targetID)) 3856 if (!UUID.TryParse(target, out targetID))
@@ -3627,10 +3956,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3627 // Restructuring Multiple Prims. 3956 // Restructuring Multiple Prims.
3628 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 3957 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3629 parts.Remove(parentPrim.RootPart); 3958 parts.Remove(parentPrim.RootPart);
3630 foreach (SceneObjectPart part in parts) 3959 if (parts.Count > 0)
3631 { 3960 {
3632 parentPrim.DelinkFromGroup(part.LocalId, true); 3961 try
3962 {
3963 parts[0].ParentGroup.areUpdatesSuspended = true;
3964 foreach (SceneObjectPart part in parts)
3965 {
3966 parentPrim.DelinkFromGroup(part.LocalId, true);
3967 }
3968 }
3969 finally
3970 {
3971 parts[0].ParentGroup.areUpdatesSuspended = false;
3972 }
3633 } 3973 }
3974
3634 parentPrim.HasGroupChanged = true; 3975 parentPrim.HasGroupChanged = true;
3635 parentPrim.ScheduleGroupForFullUpdate(); 3976 parentPrim.ScheduleGroupForFullUpdate();
3636 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3977 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3639,12 +3980,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3639 { 3980 {
3640 SceneObjectPart newRoot = parts[0]; 3981 SceneObjectPart newRoot = parts[0];
3641 parts.Remove(newRoot); 3982 parts.Remove(newRoot);
3642 foreach (SceneObjectPart part in parts) 3983
3984 try
3643 { 3985 {
3644 // Required for linking 3986 parts[0].ParentGroup.areUpdatesSuspended = true;
3645 part.ClearUpdateSchedule(); 3987 foreach (SceneObjectPart part in parts)
3646 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 3988 {
3989 part.ClearUpdateSchedule();
3990 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3991 }
3647 } 3992 }
3993 finally
3994 {
3995 parts[0].ParentGroup.areUpdatesSuspended = false;
3996 }
3997
3998
3648 newRoot.ParentGroup.HasGroupChanged = true; 3999 newRoot.ParentGroup.HasGroupChanged = true;
3649 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4000 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3650 } 4001 }
@@ -3664,6 +4015,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3664 public void llBreakAllLinks() 4015 public void llBreakAllLinks()
3665 { 4016 {
3666 m_host.AddScriptLPS(1); 4017 m_host.AddScriptLPS(1);
4018
4019 TaskInventoryItem item = m_item;
4020
4021 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4022 && !m_automaticLinkPermission)
4023 {
4024 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4025 return;
4026 }
4027
3667 SceneObjectGroup parentPrim = m_host.ParentGroup; 4028 SceneObjectGroup parentPrim = m_host.ParentGroup;
3668 if (parentPrim.AttachmentPoint != 0) 4029 if (parentPrim.AttachmentPoint != 0)
3669 return; // Fail silently if attached 4030 return; // Fail silently if attached
@@ -3683,25 +4044,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3683 public LSL_String llGetLinkKey(int linknum) 4044 public LSL_String llGetLinkKey(int linknum)
3684 { 4045 {
3685 m_host.AddScriptLPS(1); 4046 m_host.AddScriptLPS(1);
3686 List<UUID> keytable = new List<UUID>();
3687 // parse for sitting avatare-uuids
3688 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3689 {
3690 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
3691 keytable.Add(presence.UUID);
3692 });
3693
3694 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3695 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3696 {
3697 return keytable[totalprims - linknum].ToString();
3698 }
3699
3700 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3701 {
3702 return m_host.UUID.ToString();
3703 }
3704
3705 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4047 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3706 if (part != null) 4048 if (part != null)
3707 { 4049 {
@@ -3709,6 +4051,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3709 } 4051 }
3710 else 4052 else
3711 { 4053 {
4054 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4055 {
4056 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4057
4058 if (linknum < 0)
4059 return UUID.Zero.ToString();
4060
4061 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4062 if (avatars.Count > linknum)
4063 {
4064 return avatars[linknum].UUID.ToString();
4065 }
4066 }
3712 return UUID.Zero.ToString(); 4067 return UUID.Zero.ToString();
3713 } 4068 }
3714 } 4069 }
@@ -3808,17 +4163,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3808 m_host.AddScriptLPS(1); 4163 m_host.AddScriptLPS(1);
3809 int count = 0; 4164 int count = 0;
3810 4165
3811 lock (m_host.TaskInventory) 4166 m_host.TaskInventory.LockItemsForRead(true);
4167 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3812 { 4168 {
3813 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4169 if (inv.Value.Type == type || type == -1)
3814 { 4170 {
3815 if (inv.Value.Type == type || type == -1) 4171 count = count + 1;
3816 {
3817 count = count + 1;
3818 }
3819 } 4172 }
3820 } 4173 }
3821 4174
4175 m_host.TaskInventory.LockItemsForRead(false);
3822 return count; 4176 return count;
3823 } 4177 }
3824 4178
@@ -3827,16 +4181,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3827 m_host.AddScriptLPS(1); 4181 m_host.AddScriptLPS(1);
3828 ArrayList keys = new ArrayList(); 4182 ArrayList keys = new ArrayList();
3829 4183
3830 lock (m_host.TaskInventory) 4184 m_host.TaskInventory.LockItemsForRead(true);
4185 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3831 { 4186 {
3832 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4187 if (inv.Value.Type == type || type == -1)
3833 { 4188 {
3834 if (inv.Value.Type == type || type == -1) 4189 keys.Add(inv.Value.Name);
3835 {
3836 keys.Add(inv.Value.Name);
3837 }
3838 } 4190 }
3839 } 4191 }
4192 m_host.TaskInventory.LockItemsForRead(false);
3840 4193
3841 if (keys.Count == 0) 4194 if (keys.Count == 0)
3842 { 4195 {
@@ -3873,25 +4226,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3873 } 4226 }
3874 4227
3875 // move the first object found with this inventory name 4228 // move the first object found with this inventory name
3876 lock (m_host.TaskInventory) 4229 m_host.TaskInventory.LockItemsForRead(true);
4230 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3877 { 4231 {
3878 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4232 if (inv.Value.Name == inventory)
3879 { 4233 {
3880 if (inv.Value.Name == inventory) 4234 found = true;
3881 { 4235 objId = inv.Key;
3882 found = true; 4236 assetType = inv.Value.Type;
3883 objId = inv.Key; 4237 objName = inv.Value.Name;
3884 assetType = inv.Value.Type; 4238 break;
3885 objName = inv.Value.Name;
3886 break;
3887 }
3888 } 4239 }
3889 } 4240 }
4241 m_host.TaskInventory.LockItemsForRead(false);
3890 4242
3891 if (!found) 4243 if (!found)
3892 { 4244 {
3893 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4245 llSay(0, String.Format("Could not find object '{0}'", inventory));
3894 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4246 return;
4247// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3895 } 4248 }
3896 4249
3897 // check if destination is an object 4250 // check if destination is an object
@@ -3917,48 +4270,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3917 return; 4270 return;
3918 } 4271 }
3919 } 4272 }
4273
3920 // destination is an avatar 4274 // destination is an avatar
3921 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4275 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3922 4276
3923 if (agentItem == null) 4277 if (agentItem == null)
3924 return; 4278 return;
3925 4279
3926 byte[] bucket = new byte[17]; 4280 byte[] bucket = new byte[1];
3927 bucket[0] = (byte)assetType; 4281 bucket[0] = (byte)assetType;
3928 byte[] objBytes = agentItem.ID.GetBytes(); 4282 //byte[] objBytes = agentItem.ID.GetBytes();
3929 Array.Copy(objBytes, 0, bucket, 1, 16); 4283 //Array.Copy(objBytes, 0, bucket, 1, 16);
3930 4284
3931 GridInstantMessage msg = new GridInstantMessage(World, 4285 GridInstantMessage msg = new GridInstantMessage(World,
3932 m_host.UUID, m_host.Name+", an object owned by "+ 4286 m_host.OwnerID, m_host.Name, destId,
3933 resolveName(m_host.OwnerID)+",", destId,
3934 (byte)InstantMessageDialog.TaskInventoryOffered, 4287 (byte)InstantMessageDialog.TaskInventoryOffered,
3935 false, objName+"\n"+m_host.Name+" is located at "+ 4288 false, objName+". "+m_host.Name+" is located at "+
3936 World.RegionInfo.RegionName+" "+ 4289 World.RegionInfo.RegionName+" "+
3937 m_host.AbsolutePosition.ToString(), 4290 m_host.AbsolutePosition.ToString(),
3938 agentItem.ID, true, m_host.AbsolutePosition, 4291 agentItem.ID, true, m_host.AbsolutePosition,
3939 bucket); 4292 bucket);
3940 if (m_TransferModule != null) 4293
3941 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4294 ScenePresence sp;
4295
4296 if (World.TryGetScenePresence(destId, out sp))
4297 {
4298 sp.ControllingClient.SendInstantMessage(msg);
4299 }
4300 else
4301 {
4302 if (m_TransferModule != null)
4303 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4304 }
4305
4306 //This delay should only occur when giving inventory to avatars.
3942 ScriptSleep(3000); 4307 ScriptSleep(3000);
3943 } 4308 }
3944 } 4309 }
3945 4310
4311 [DebuggerNonUserCode]
3946 public void llRemoveInventory(string name) 4312 public void llRemoveInventory(string name)
3947 { 4313 {
3948 m_host.AddScriptLPS(1); 4314 m_host.AddScriptLPS(1);
3949 4315
3950 lock (m_host.TaskInventory) 4316 List<TaskInventoryItem> inv;
4317 try
3951 { 4318 {
3952 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4319 m_host.TaskInventory.LockItemsForRead(true);
4320 inv = new List<TaskInventoryItem>(m_host.TaskInventory.Values);
4321 }
4322 finally
4323 {
4324 m_host.TaskInventory.LockItemsForRead(false);
4325 }
4326 foreach (TaskInventoryItem item in inv)
4327 {
4328 if (item.Name == name)
3953 { 4329 {
3954 if (item.Name == name) 4330 if (item.ItemID == m_item.ItemID)
3955 { 4331 throw new ScriptDeleteException();
3956 if (item.ItemID == m_item.ItemID) 4332 else
3957 throw new ScriptDeleteException(); 4333 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3958 else 4334 return;
3959 m_host.Inventory.RemoveInventoryItem(item.ItemID);
3960 return;
3961 }
3962 } 4335 }
3963 } 4336 }
3964 } 4337 }
@@ -3993,115 +4366,122 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3993 { 4366 {
3994 m_host.AddScriptLPS(1); 4367 m_host.AddScriptLPS(1);
3995 4368
3996 UUID uuid = (UUID)id; 4369 UUID uuid;
3997 PresenceInfo pinfo = null; 4370 if (UUID.TryParse(id, out uuid))
3998 UserAccount account;
3999
4000 UserInfoCacheEntry ce;
4001 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4002 { 4371 {
4003 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4372 PresenceInfo pinfo = null;
4004 if (account == null) 4373 UserAccount account;
4374
4375 UserInfoCacheEntry ce;
4376 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4005 { 4377 {
4006 m_userInfoCache[uuid] = null; // Cache negative 4378 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4007 return UUID.Zero.ToString(); 4379 if (account == null)
4008 } 4380 {
4381 m_userInfoCache[uuid] = null; // Cache negative
4382 return UUID.Zero.ToString();
4383 }
4009 4384
4010 4385
4011 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4386 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4012 if (pinfos != null && pinfos.Length > 0) 4387 if (pinfos != null && pinfos.Length > 0)
4013 {
4014 foreach (PresenceInfo p in pinfos)
4015 { 4388 {
4016 if (p.RegionID != UUID.Zero) 4389 foreach (PresenceInfo p in pinfos)
4017 { 4390 {
4018 pinfo = p; 4391 if (p.RegionID != UUID.Zero)
4392 {
4393 pinfo = p;
4394 }
4019 } 4395 }
4020 } 4396 }
4021 }
4022 4397
4023 ce = new UserInfoCacheEntry(); 4398 ce = new UserInfoCacheEntry();
4024 ce.time = Util.EnvironmentTickCount(); 4399 ce.time = Util.EnvironmentTickCount();
4025 ce.account = account; 4400 ce.account = account;
4026 ce.pinfo = pinfo; 4401 ce.pinfo = pinfo;
4027 } 4402 m_userInfoCache[uuid] = ce;
4028 else 4403 }
4029 { 4404 else
4030 if (ce == null) 4405 {
4031 return UUID.Zero.ToString(); 4406 if (ce == null)
4407 return UUID.Zero.ToString();
4032 4408
4033 account = ce.account; 4409 account = ce.account;
4034 pinfo = ce.pinfo; 4410 pinfo = ce.pinfo;
4035 } 4411 }
4036 4412
4037 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4413 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4038 {
4039 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4040 if (pinfos != null && pinfos.Length > 0)
4041 { 4414 {
4042 foreach (PresenceInfo p in pinfos) 4415 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4416 if (pinfos != null && pinfos.Length > 0)
4043 { 4417 {
4044 if (p.RegionID != UUID.Zero) 4418 foreach (PresenceInfo p in pinfos)
4045 { 4419 {
4046 pinfo = p; 4420 if (p.RegionID != UUID.Zero)
4421 {
4422 pinfo = p;
4423 }
4047 } 4424 }
4048 } 4425 }
4049 } 4426 else
4050 else 4427 pinfo = null;
4051 pinfo = null;
4052 4428
4053 ce.time = Util.EnvironmentTickCount(); 4429 ce.time = Util.EnvironmentTickCount();
4054 ce.pinfo = pinfo; 4430 ce.pinfo = pinfo;
4055 } 4431 }
4056 4432
4057 string reply = String.Empty; 4433 string reply = String.Empty;
4058 4434
4059 switch (data) 4435 switch (data)
4060 { 4436 {
4061 case 1: // DATA_ONLINE (0|1) 4437 case 1: // DATA_ONLINE (0|1)
4062 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4438 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4063 reply = "1"; 4439 reply = "1";
4064 else 4440 else
4065 reply = "0"; 4441 reply = "0";
4066 break; 4442 break;
4067 case 2: // DATA_NAME (First Last) 4443 case 2: // DATA_NAME (First Last)
4068 reply = account.FirstName + " " + account.LastName; 4444 reply = account.FirstName + " " + account.LastName;
4069 break; 4445 break;
4070 case 3: // DATA_BORN (YYYY-MM-DD) 4446 case 3: // DATA_BORN (YYYY-MM-DD)
4071 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4447 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4072 born = born.AddSeconds(account.Created); 4448 born = born.AddSeconds(account.Created);
4073 reply = born.ToString("yyyy-MM-dd"); 4449 reply = born.ToString("yyyy-MM-dd");
4074 break; 4450 break;
4075 case 4: // DATA_RATING (0,0,0,0,0,0) 4451 case 4: // DATA_RATING (0,0,0,0,0,0)
4076 reply = "0,0,0,0,0,0"; 4452 reply = "0,0,0,0,0,0";
4077 break; 4453 break;
4078 case 7: // DATA_USERLEVEL (integer) 4454 case 8: // DATA_PAYINFO (0|1|2|3)
4079 reply = account.UserLevel.ToString(); 4455 reply = "0";
4080 break; 4456 break;
4081 case 8: // DATA_PAYINFO (0|1|2|3) 4457 default:
4082 reply = "0"; 4458 return UUID.Zero.ToString(); // Raise no event
4083 break; 4459 }
4084 default:
4085 return UUID.Zero.ToString(); // Raise no event
4086 }
4087 4460
4088 UUID rq = UUID.Random(); 4461 UUID rq = UUID.Random();
4089 4462
4090 UUID tid = AsyncCommands. 4463 UUID tid = AsyncCommands.
4091 DataserverPlugin.RegisterRequest(m_host.LocalId, 4464 DataserverPlugin.RegisterRequest(m_host.LocalId,
4092 m_item.ItemID, rq.ToString()); 4465 m_item.ItemID, rq.ToString());
4093 4466
4094 AsyncCommands. 4467 AsyncCommands.
4095 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4468 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4096 4469
4097 ScriptSleep(100); 4470 ScriptSleep(100);
4098 return tid.ToString(); 4471 return tid.ToString();
4472 }
4473 else
4474 {
4475 ShoutError("Invalid UUID passed to llRequestAgentData.");
4476 }
4477 return "";
4099 } 4478 }
4100 4479
4101 public LSL_String llRequestInventoryData(string name) 4480 public LSL_String llRequestInventoryData(string name)
4102 { 4481 {
4103 m_host.AddScriptLPS(1); 4482 m_host.AddScriptLPS(1);
4104 4483
4484 //Clone is thread safe
4105 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 4485 TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
4106 4486
4107 foreach (TaskInventoryItem item in itemDictionary.Values) 4487 foreach (TaskInventoryItem item in itemDictionary.Values)
@@ -4153,13 +4533,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4153 if (UUID.TryParse(agent, out agentId)) 4533 if (UUID.TryParse(agent, out agentId))
4154 { 4534 {
4155 ScenePresence presence = World.GetScenePresence(agentId); 4535 ScenePresence presence = World.GetScenePresence(agentId);
4156 if (presence != null) 4536 if (presence != null && presence.PresenceType != PresenceType.Npc)
4157 { 4537 {
4538 // agent must not be a god
4539 if (presence.UserLevel >= 200) return;
4540
4158 // agent must be over the owners land 4541 // agent must be over the owners land
4159 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4542 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4160 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4543 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4161 { 4544 {
4162 World.TeleportClientHome(agentId, presence.ControllingClient); 4545 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4546 {
4547 // They can't be teleported home for some reason
4548 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4549 if (regionInfo != null)
4550 {
4551 World.RequestTeleportLocation(
4552 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4553 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4554 }
4555 }
4163 } 4556 }
4164 } 4557 }
4165 } 4558 }
@@ -4271,7 +4664,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4271 UUID av = new UUID(); 4664 UUID av = new UUID();
4272 if (!UUID.TryParse(agent,out av)) 4665 if (!UUID.TryParse(agent,out av))
4273 { 4666 {
4274 LSLError("First parameter to llDialog needs to be a key"); 4667 //LSLError("First parameter to llDialog needs to be a key");
4275 return; 4668 return;
4276 } 4669 }
4277 4670
@@ -4303,25 +4696,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4303 public void llCollisionSound(string impact_sound, double impact_volume) 4696 public void llCollisionSound(string impact_sound, double impact_volume)
4304 { 4697 {
4305 m_host.AddScriptLPS(1); 4698 m_host.AddScriptLPS(1);
4306 4699
4700 if(impact_sound == "")
4701 {
4702 m_host.CollisionSoundVolume = (float)impact_volume;
4703 m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
4704 m_host.CollisionSoundType = 0;
4705 return;
4706 }
4307 // TODO: Parameter check logic required. 4707 // TODO: Parameter check logic required.
4308 UUID soundId = UUID.Zero; 4708 UUID soundId = UUID.Zero;
4309 if (!UUID.TryParse(impact_sound, out soundId)) 4709 if (!UUID.TryParse(impact_sound, out soundId))
4310 { 4710 {
4311 lock (m_host.TaskInventory) 4711 m_host.TaskInventory.LockItemsForRead(true);
4712 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
4312 { 4713 {
4313 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 4714 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
4314 { 4715 {
4315 if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) 4716 soundId = item.AssetID;
4316 { 4717 break;
4317 soundId = item.AssetID;
4318 break;
4319 }
4320 } 4718 }
4321 } 4719 }
4720 m_host.TaskInventory.LockItemsForRead(false);
4322 } 4721 }
4323 m_host.CollisionSound = soundId;
4324 m_host.CollisionSoundVolume = (float)impact_volume; 4722 m_host.CollisionSoundVolume = (float)impact_volume;
4723 m_host.CollisionSound = soundId;
4724 m_host.CollisionSoundType = 1;
4325 } 4725 }
4326 4726
4327 public LSL_String llGetAnimation(string id) 4727 public LSL_String llGetAnimation(string id)
@@ -4335,14 +4735,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4335 4735
4336 if (m_host.RegionHandle == presence.RegionHandle) 4736 if (m_host.RegionHandle == presence.RegionHandle)
4337 { 4737 {
4338 Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames;
4339
4340 if (presence != null) 4738 if (presence != null)
4341 { 4739 {
4342 AnimationSet currentAnims = presence.Animator.Animations; 4740 if (presence.SitGround)
4343 string currentAnimationState = String.Empty; 4741 return "Sitting on Ground";
4344 if (animationstateNames.TryGetValue(currentAnims.DefaultAnimation.AnimID, out currentAnimationState)) 4742 if (presence.ParentID != 0 || presence.ParentUUID != UUID.Zero)
4345 return currentAnimationState; 4743 return "Sitting";
4744
4745 string movementAnimation = presence.Animator.CurrentMovementAnimation;
4746 string lslMovementAnimation;
4747
4748 if (MovementAnimationsForLSL.TryGetValue(movementAnimation, out lslMovementAnimation))
4749 return lslMovementAnimation;
4346 } 4750 }
4347 } 4751 }
4348 4752
@@ -4358,6 +4762,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4358 UUID partItemID; 4762 UUID partItemID;
4359 foreach (SceneObjectPart part in parts) 4763 foreach (SceneObjectPart part in parts)
4360 { 4764 {
4765 //Clone is thread safe
4361 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 4766 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
4362 4767
4363 foreach (TaskInventoryItem item in itemsDictionary.Values) 4768 foreach (TaskInventoryItem item in itemsDictionary.Values)
@@ -4491,7 +4896,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4491 { 4896 {
4492 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4897 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4493 float distance_term = distance * distance * distance; // Script Energy 4898 float distance_term = distance * distance * distance; // Script Energy
4494 float pusher_mass = m_host.GetMass(); 4899 // use total object mass and not part
4900 float pusher_mass = m_host.ParentGroup.GetMass();
4495 4901
4496 float PUSH_ATTENUATION_DISTANCE = 17f; 4902 float PUSH_ATTENUATION_DISTANCE = 17f;
4497 float PUSH_ATTENUATION_SCALE = 5f; 4903 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4730,23 +5136,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4730 { 5136 {
4731 m_host.AddScriptLPS(1); 5137 m_host.AddScriptLPS(1);
4732 5138
4733 lock (m_host.TaskInventory) 5139 m_host.TaskInventory.LockItemsForRead(true);
5140 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4734 { 5141 {
4735 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 5142 if (inv.Value.Name == name)
4736 { 5143 {
4737 if (inv.Value.Name == name) 5144 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
4738 { 5145 {
4739 if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5146 m_host.TaskInventory.LockItemsForRead(false);
4740 { 5147 return inv.Value.AssetID.ToString();
4741 return inv.Value.AssetID.ToString(); 5148 }
4742 } 5149 else
4743 else 5150 {
4744 { 5151 m_host.TaskInventory.LockItemsForRead(false);
4745 return UUID.Zero.ToString(); 5152 return UUID.Zero.ToString();
4746 }
4747 } 5153 }
4748 } 5154 }
4749 } 5155 }
5156 m_host.TaskInventory.LockItemsForRead(false);
4750 5157
4751 return UUID.Zero.ToString(); 5158 return UUID.Zero.ToString();
4752 } 5159 }
@@ -4880,7 +5287,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4880 public LSL_Vector llGetCenterOfMass() 5287 public LSL_Vector llGetCenterOfMass()
4881 { 5288 {
4882 m_host.AddScriptLPS(1); 5289 m_host.AddScriptLPS(1);
4883 Vector3 center = m_host.GetGeometricCenter(); 5290 Vector3 center = m_host.GetCenterOfMass();
4884 return new LSL_Vector(center.X,center.Y,center.Z); 5291 return new LSL_Vector(center.X,center.Y,center.Z);
4885 } 5292 }
4886 5293
@@ -4899,14 +5306,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4899 { 5306 {
4900 m_host.AddScriptLPS(1); 5307 m_host.AddScriptLPS(1);
4901 5308
4902 if (src == null) 5309 return src.Length;
4903 {
4904 return 0;
4905 }
4906 else
4907 {
4908 return src.Length;
4909 }
4910 } 5310 }
4911 5311
4912 public LSL_Integer llList2Integer(LSL_List src, int index) 5312 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4952,7 +5352,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4952 else if (src.Data[index] is LSL_Float) 5352 else if (src.Data[index] is LSL_Float)
4953 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5353 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4954 else if (src.Data[index] is LSL_String) 5354 else if (src.Data[index] is LSL_String)
4955 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5355 {
5356 string str = ((LSL_String) src.Data[index]).m_string;
5357 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5358 if (m != Match.Empty)
5359 {
5360 str = m.Value;
5361 double d = 0.0;
5362 if (!Double.TryParse(str, out d))
5363 return 0.0;
5364
5365 return d;
5366 }
5367 return 0.0;
5368 }
4956 return Convert.ToDouble(src.Data[index]); 5369 return Convert.ToDouble(src.Data[index]);
4957 } 5370 }
4958 catch (FormatException) 5371 catch (FormatException)
@@ -5225,7 +5638,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5225 } 5638 }
5226 } 5639 }
5227 } 5640 }
5228 else { 5641 else
5642 {
5229 object[] array = new object[src.Length]; 5643 object[] array = new object[src.Length];
5230 Array.Copy(src.Data, 0, array, 0, src.Length); 5644 Array.Copy(src.Data, 0, array, 0, src.Length);
5231 result = new LSL_List(array); 5645 result = new LSL_List(array);
@@ -5332,7 +5746,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5332 public LSL_Integer llGetRegionAgentCount() 5746 public LSL_Integer llGetRegionAgentCount()
5333 { 5747 {
5334 m_host.AddScriptLPS(1); 5748 m_host.AddScriptLPS(1);
5335 return new LSL_Integer(World.GetRootAgentCount()); 5749
5750 int count = 0;
5751 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5752 count++;
5753 });
5754
5755 return new LSL_Integer(count);
5336 } 5756 }
5337 5757
5338 public LSL_Vector llGetRegionCorner() 5758 public LSL_Vector llGetRegionCorner()
@@ -5612,6 +6032,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5612 flags |= ScriptBaseClass.AGENT_SITTING; 6032 flags |= ScriptBaseClass.AGENT_SITTING;
5613 } 6033 }
5614 6034
6035 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
6036 {
6037 flags |= ScriptBaseClass.AGENT_MALE;
6038 }
6039
5615 return flags; 6040 return flags;
5616 } 6041 }
5617 6042
@@ -5758,10 +6183,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5758 m_host.AddScriptLPS(1); 6183 m_host.AddScriptLPS(1);
5759 6184
5760 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6185 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5761 6186 if (parts.Count > 0)
5762 foreach (var part in parts)
5763 { 6187 {
5764 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6188 try
6189 {
6190 parts[0].ParentGroup.areUpdatesSuspended = true;
6191 foreach (var part in parts)
6192 {
6193 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6194 }
6195 }
6196 finally
6197 {
6198 parts[0].ParentGroup.areUpdatesSuspended = false;
6199 }
5765 } 6200 }
5766 } 6201 }
5767 6202
@@ -5813,13 +6248,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5813 6248
5814 if (m_host.OwnerID == land.LandData.OwnerID) 6249 if (m_host.OwnerID == land.LandData.OwnerID)
5815 { 6250 {
5816 World.TeleportClientHome(agentID, presence.ControllingClient); 6251 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6252 presence.TeleportWithMomentum(pos, null);
6253 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5817 } 6254 }
5818 } 6255 }
5819 } 6256 }
5820 ScriptSleep(5000); 6257 ScriptSleep(5000);
5821 } 6258 }
5822 6259
6260 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6261 {
6262 return ParseString2List(str, separators, in_spacers, false);
6263 }
6264
5823 public LSL_Integer llOverMyLand(string id) 6265 public LSL_Integer llOverMyLand(string id)
5824 { 6266 {
5825 m_host.AddScriptLPS(1); 6267 m_host.AddScriptLPS(1);
@@ -5884,8 +6326,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5884 UUID agentId = new UUID(); 6326 UUID agentId = new UUID();
5885 if (!UUID.TryParse(agent, out agentId)) 6327 if (!UUID.TryParse(agent, out agentId))
5886 return new LSL_Integer(0); 6328 return new LSL_Integer(0);
6329 if (agentId == m_host.GroupID)
6330 return new LSL_Integer(1);
5887 ScenePresence presence = World.GetScenePresence(agentId); 6331 ScenePresence presence = World.GetScenePresence(agentId);
5888 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6332 if (presence == null || presence.IsChildAgent) // Return false for child agents
5889 return new LSL_Integer(0); 6333 return new LSL_Integer(0);
5890 IClientAPI client = presence.ControllingClient; 6334 IClientAPI client = presence.ControllingClient;
5891 if (m_host.GroupID == client.ActiveGroupId) 6335 if (m_host.GroupID == client.ActiveGroupId)
@@ -6020,7 +6464,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6020 return m_host.ParentGroup.AttachmentPoint; 6464 return m_host.ParentGroup.AttachmentPoint;
6021 } 6465 }
6022 6466
6023 public LSL_Integer llGetFreeMemory() 6467 public virtual LSL_Integer llGetFreeMemory()
6024 { 6468 {
6025 m_host.AddScriptLPS(1); 6469 m_host.AddScriptLPS(1);
6026 // Make scripts designed for LSO happy 6470 // Make scripts designed for LSO happy
@@ -6137,7 +6581,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6137 SetParticleSystem(m_host, rules); 6581 SetParticleSystem(m_host, rules);
6138 } 6582 }
6139 6583
6140 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6584 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6585 {
6141 6586
6142 6587
6143 if (rules.Length == 0) 6588 if (rules.Length == 0)
@@ -6331,14 +6776,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6331 6776
6332 protected UUID GetTaskInventoryItem(string name) 6777 protected UUID GetTaskInventoryItem(string name)
6333 { 6778 {
6334 lock (m_host.TaskInventory) 6779 m_host.TaskInventory.LockItemsForRead(true);
6780 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6335 { 6781 {
6336 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 6782 if (inv.Value.Name == name)
6337 { 6783 {
6338 if (inv.Value.Name == name) 6784 m_host.TaskInventory.LockItemsForRead(false);
6339 return inv.Key; 6785 return inv.Key;
6340 } 6786 }
6341 } 6787 }
6788 m_host.TaskInventory.LockItemsForRead(false);
6342 6789
6343 return UUID.Zero; 6790 return UUID.Zero;
6344 } 6791 }
@@ -6376,16 +6823,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6376 if (folderID == UUID.Zero) 6823 if (folderID == UUID.Zero)
6377 return; 6824 return;
6378 6825
6379 byte[] bucket = new byte[17]; 6826 byte[] bucket = new byte[1];
6380 bucket[0] = (byte)AssetType.Folder; 6827 bucket[0] = (byte)AssetType.Folder;
6381 byte[] objBytes = folderID.GetBytes(); 6828 //byte[] objBytes = folderID.GetBytes();
6382 Array.Copy(objBytes, 0, bucket, 1, 16); 6829 //Array.Copy(objBytes, 0, bucket, 1, 16);
6383 6830
6384 GridInstantMessage msg = new GridInstantMessage(World, 6831 GridInstantMessage msg = new GridInstantMessage(World,
6385 m_host.UUID, m_host.Name+", an object owned by "+ 6832 m_host.OwnerID, m_host.Name, destID,
6386 resolveName(m_host.OwnerID)+",", destID, 6833 (byte)InstantMessageDialog.TaskInventoryOffered,
6387 (byte)InstantMessageDialog.InventoryOffered, 6834 false, category+". "+m_host.Name+" is located at "+
6388 false, category+"\n"+m_host.Name+" is located at "+
6389 World.RegionInfo.RegionName+" "+ 6835 World.RegionInfo.RegionName+" "+
6390 m_host.AbsolutePosition.ToString(), 6836 m_host.AbsolutePosition.ToString(),
6391 folderID, true, m_host.AbsolutePosition, 6837 folderID, true, m_host.AbsolutePosition,
@@ -6466,7 +6912,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6466 { 6912 {
6467 // LSL quaternions can normalize to 0, normal Quaternions can't. 6913 // LSL quaternions can normalize to 0, normal Quaternions can't.
6468 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) 6914 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
6469 rot.z = 1; // ZERO_ROTATION = 0,0,0,1 6915 rot.s = 1; // ZERO_ROTATION = 0,0,0,1
6470 6916
6471 part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); 6917 part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z);
6472 part.SitTargetOrientation = Rot2Quaternion(rot); 6918 part.SitTargetOrientation = Rot2Quaternion(rot);
@@ -6623,13 +7069,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6623 UUID av = new UUID(); 7069 UUID av = new UUID();
6624 if (!UUID.TryParse(avatar,out av)) 7070 if (!UUID.TryParse(avatar,out av))
6625 { 7071 {
6626 LSLError("First parameter to llDialog needs to be a key"); 7072 //LSLError("First parameter to llDialog needs to be a key");
6627 return; 7073 return;
6628 } 7074 }
6629 if (buttons.Length < 1) 7075 if (buttons.Length < 1)
6630 { 7076 {
6631 LSLError("No less than 1 button can be shown"); 7077 buttons.Add("OK");
6632 return;
6633 } 7078 }
6634 if (buttons.Length > 12) 7079 if (buttons.Length > 12)
6635 { 7080 {
@@ -6646,7 +7091,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6646 } 7091 }
6647 if (buttons.Data[i].ToString().Length > 24) 7092 if (buttons.Data[i].ToString().Length > 24)
6648 { 7093 {
6649 LSLError("button label cannot be longer than 24 characters"); 7094 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6650 return; 7095 return;
6651 } 7096 }
6652 buts[i] = buttons.Data[i].ToString(); 7097 buts[i] = buttons.Data[i].ToString();
@@ -6705,22 +7150,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6705 } 7150 }
6706 7151
6707 // copy the first script found with this inventory name 7152 // copy the first script found with this inventory name
6708 lock (m_host.TaskInventory) 7153 TaskInventoryItem scriptItem = null;
7154 m_host.TaskInventory.LockItemsForRead(true);
7155 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
6709 { 7156 {
6710 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 7157 if (inv.Value.Name == name)
6711 { 7158 {
6712 if (inv.Value.Name == name) 7159 // make sure the object is a script
7160 if (10 == inv.Value.Type)
6713 { 7161 {
6714 // make sure the object is a script 7162 found = true;
6715 if (10 == inv.Value.Type) 7163 srcId = inv.Key;
6716 { 7164 scriptItem = inv.Value;
6717 found = true; 7165 break;
6718 srcId = inv.Key;
6719 break;
6720 }
6721 } 7166 }
6722 } 7167 }
6723 } 7168 }
7169 m_host.TaskInventory.LockItemsForRead(false);
6724 7170
6725 if (!found) 7171 if (!found)
6726 { 7172 {
@@ -6728,9 +7174,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6728 return; 7174 return;
6729 } 7175 }
6730 7176
6731 // the rest of the permission checks are done in RezScript, so check the pin there as well 7177 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6732 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); 7178 if (dest != null)
7179 {
7180 if ((scriptItem.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7181 {
7182 // the rest of the permission checks are done in RezScript, so check the pin there as well
7183 World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param);
6733 7184
7185 if ((scriptItem.BasePermissions & (uint)PermissionMask.Copy) == 0)
7186 m_host.Inventory.RemoveInventoryItem(srcId);
7187 }
7188 }
6734 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7189 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6735 ScriptSleep(3000); 7190 ScriptSleep(3000);
6736 } 7191 }
@@ -6793,19 +7248,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6793 public LSL_String llMD5String(string src, int nonce) 7248 public LSL_String llMD5String(string src, int nonce)
6794 { 7249 {
6795 m_host.AddScriptLPS(1); 7250 m_host.AddScriptLPS(1);
6796 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7251 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6797 } 7252 }
6798 7253
6799 public LSL_String llSHA1String(string src) 7254 public LSL_String llSHA1String(string src)
6800 { 7255 {
6801 m_host.AddScriptLPS(1); 7256 m_host.AddScriptLPS(1);
6802 return Util.SHA1Hash(src).ToLower(); 7257 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6803 } 7258 }
6804 7259
6805 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7260 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6806 { 7261 {
6807 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7262 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6808 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7263 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7264 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7265 return shapeBlock;
6809 7266
6810 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7267 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6811 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7268 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6910,6 +7367,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6910 // Prim type box, cylinder and prism. 7367 // Prim type box, cylinder and prism.
6911 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) 7368 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)
6912 { 7369 {
7370 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7371 return;
7372
6913 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7373 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6914 ObjectShapePacket.ObjectDataBlock shapeBlock; 7374 ObjectShapePacket.ObjectDataBlock shapeBlock;
6915 7375
@@ -6963,6 +7423,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6963 // Prim type sphere. 7423 // Prim type sphere.
6964 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7424 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6965 { 7425 {
7426 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7427 return;
7428
6966 ObjectShapePacket.ObjectDataBlock shapeBlock; 7429 ObjectShapePacket.ObjectDataBlock shapeBlock;
6967 7430
6968 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7431 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -7004,6 +7467,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7004 // Prim type torus, tube and ring. 7467 // Prim type torus, tube and ring.
7005 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) 7468 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)
7006 { 7469 {
7470 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7471 return;
7472
7007 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7473 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7008 ObjectShapePacket.ObjectDataBlock shapeBlock; 7474 ObjectShapePacket.ObjectDataBlock shapeBlock;
7009 7475
@@ -7139,6 +7605,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7139 // Prim type sculpt. 7605 // Prim type sculpt.
7140 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7606 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7141 { 7607 {
7608 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7609 return;
7610
7142 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7611 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7143 UUID sculptId; 7612 UUID sculptId;
7144 7613
@@ -7163,7 +7632,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7163 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7632 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7164 { 7633 {
7165 // default 7634 // default
7166 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7635 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7167 } 7636 }
7168 7637
7169 part.Shape.SetSculptProperties((byte)type, sculptId); 7638 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7179,34 +7648,311 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7179 ScriptSleep(200); 7648 ScriptSleep(200);
7180 } 7649 }
7181 7650
7182 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7651 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7183 { 7652 {
7184 m_host.AddScriptLPS(1); 7653 m_host.AddScriptLPS(1);
7185 7654
7186 setLinkPrimParams(linknumber, rules); 7655 setLinkPrimParams(linknumber, rules);
7656 }
7657
7658 private void setLinkPrimParams(int linknumber, LSL_List rules)
7659 {
7660 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7661 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7662 if (parts.Count>0)
7663 {
7664 try
7665 {
7666 parts[0].ParentGroup.areUpdatesSuspended = true;
7667 foreach (SceneObjectPart part in parts)
7668 SetPrimParams(part, rules);
7669 }
7670 finally
7671 {
7672 parts[0].ParentGroup.areUpdatesSuspended = false;
7673 }
7674 }
7675 if (avatars.Count > 0)
7676 {
7677 foreach (ScenePresence avatar in avatars)
7678 SetPrimParams(avatar, rules);
7679 }
7680 }
7681
7682 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7683 float material_density, float material_friction,
7684 float material_restitution, float material_gravity_modifier)
7685 {
7686 ExtraPhysicsData physdata = new ExtraPhysicsData();
7687 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7688 physdata.Density = part.Density;
7689 physdata.Friction = part.Friction;
7690 physdata.Bounce = part.Bounciness;
7691 physdata.GravitationModifier = part.GravityModifier;
7692
7693 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7694 physdata.Density = material_density;
7695 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7696 physdata.Friction = material_friction;
7697 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7698 physdata.Bounce = material_restitution;
7699 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7700 physdata.GravitationModifier = material_gravity_modifier;
7701
7702 part.UpdateExtraPhysics(physdata);
7703 }
7187 7704
7705 public void llSetPhysicsMaterial(int material_bits,
7706 float material_gravity_modifier, float material_restitution,
7707 float material_friction, float material_density)
7708 {
7709 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7710 }
7711
7712 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7713 {
7714 llSetLinkPrimitiveParamsFast(linknumber, rules);
7188 ScriptSleep(200); 7715 ScriptSleep(200);
7189 } 7716 }
7190 7717
7191 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7718 // vector up using libomv (c&p from sop )
7719 // vector up rotated by r
7720 private Vector3 Zrot(Quaternion r)
7192 { 7721 {
7193 m_host.AddScriptLPS(1); 7722 double x, y, z, m;
7194 7723
7195 setLinkPrimParams(linknumber, rules); 7724 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
7725 if (Math.Abs(1.0 - m) > 0.000001)
7726 {
7727 m = 1.0 / Math.Sqrt(m);
7728 r.X *= (float)m;
7729 r.Y *= (float)m;
7730 r.Z *= (float)m;
7731 r.W *= (float)m;
7732 }
7733
7734 x = 2 * (r.X * r.Z + r.Y * r.W);
7735 y = 2 * (-r.X * r.W + r.Y * r.Z);
7736 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
7737
7738 return new Vector3((float)x, (float)y, (float)z);
7196 } 7739 }
7197 7740
7198 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7741 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7199 { 7742 {
7200 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7743 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7201 7744
7202 foreach (SceneObjectPart part in parts) 7745 int idx = 0;
7203 SetPrimParams(part, rules); 7746 SceneObjectPart sitpart = World.GetSceneObjectPart(av.ParentID); // betting this will be used
7747
7748 bool positionChanged = false;
7749 Vector3 finalPos = Vector3.Zero;
7750
7751 try
7752 {
7753 while (idx < rules.Length)
7754 {
7755 int code = rules.GetLSLIntegerItem(idx++);
7756
7757 int remain = rules.Length - idx;
7758
7759 switch (code)
7760 {
7761 // a avatar is a child
7762 case (int)ScriptBaseClass.PRIM_POSITION:
7763 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
7764 {
7765 if (remain < 1)
7766 return;
7767 LSL_Vector v;
7768 v = rules.GetVector3Item(idx++);
7769
7770 if (sitpart == null)
7771 break;
7772
7773 Vector3 pos = new Vector3((float)v.x, (float)v.y, (float)v.z); // requested absolute position
7774
7775 if (sitpart != sitpart.ParentGroup.RootPart)
7776 {
7777 pos -= sitpart.OffsetPosition; // remove sit part offset
7778 Quaternion rot = sitpart.RotationOffset;
7779 pos *= Quaternion.Conjugate(rot); // removed sit part rotation
7780 }
7781 Vector3 sitOffset = (Zrot(av.Rotation)) * (av.Appearance.AvatarHeight * 0.02638f * 2.0f);
7782 pos += sitOffset;
7783
7784 finalPos = pos;
7785 positionChanged = true;
7786 }
7787 break;
7788
7789 case (int)ScriptBaseClass.PRIM_ROTATION:
7790 {
7791 if (remain < 1)
7792 return;
7793
7794 if (sitpart == null)
7795 break;
7796
7797 LSL_Rotation r = rules.GetQuaternionItem(idx++);
7798 Quaternion rot = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); // requested world rotation
7799
7800// need to replicate SL bug
7801 SceneObjectGroup sitgrp = sitpart.ParentGroup;
7802 if (sitgrp != null && sitgrp.RootPart != sitpart)
7803 {
7804 rot = sitgrp.RootPart.RotationOffset * rot;
7805 }
7806
7807 Quaternion srot = sitpart.RotationOffset;
7808 rot = Quaternion.Conjugate(srot) * rot; // removed sit part offset rotation
7809 av.Rotation = rot;
7810 av.SendAvatarDataToAllAgents();
7811 }
7812 break;
7813
7814 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
7815 {
7816 if (remain < 1)
7817 return;
7818
7819 if (sitpart == null)
7820 break;
7821
7822 LSL_Rotation r = rules.GetQuaternionItem(idx++);
7823 Quaternion rot = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); // requested offset rotation
7824 if (sitpart != sitpart.ParentGroup.RootPart)
7825 {
7826 Quaternion srot = sitpart.RotationOffset;
7827 rot = Quaternion.Conjugate(srot) * rot; // remove sit part offset rotation
7828 }
7829 av.Rotation = rot;
7830 av.SendAvatarDataToAllAgents();
7831 }
7832 break;
7833
7834 // parse rest doing nothing but number of parameters error check
7835 case (int)ScriptBaseClass.PRIM_SIZE:
7836 case (int)ScriptBaseClass.PRIM_MATERIAL:
7837 case (int)ScriptBaseClass.PRIM_PHANTOM:
7838 case (int)ScriptBaseClass.PRIM_PHYSICS:
7839 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
7840 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7841 case (int)ScriptBaseClass.PRIM_NAME:
7842 case (int)ScriptBaseClass.PRIM_DESC:
7843 if (remain < 1)
7844 return;
7845 idx++;
7846 break;
7847
7848 case (int)ScriptBaseClass.PRIM_GLOW:
7849 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
7850 case (int)ScriptBaseClass.PRIM_TEXGEN:
7851 if (remain < 2)
7852 return;
7853 idx += 2;
7854 break;
7855
7856 case (int)ScriptBaseClass.PRIM_TYPE:
7857 if (remain < 3)
7858 return;
7859 code = (int)rules.GetLSLIntegerItem(idx++);
7860 remain = rules.Length - idx;
7861 switch (code)
7862 {
7863 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
7864 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
7865 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
7866 if (remain < 6)
7867 return;
7868 idx += 6;
7869 break;
7870
7871 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
7872 if (remain < 5)
7873 return;
7874 idx += 5;
7875 break;
7876
7877 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
7878 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
7879 case (int)ScriptBaseClass.PRIM_TYPE_RING:
7880 if (remain < 11)
7881 return;
7882 idx += 11;
7883 break;
7884
7885 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
7886 if (remain < 2)
7887 return;
7888 idx += 2;
7889 break;
7890 }
7891 break;
7892
7893 case (int)ScriptBaseClass.PRIM_COLOR:
7894 case (int)ScriptBaseClass.PRIM_TEXT:
7895 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7896 case (int)ScriptBaseClass.PRIM_OMEGA:
7897 if (remain < 3)
7898 return;
7899 idx += 3;
7900 break;
7901
7902 case (int)ScriptBaseClass.PRIM_TEXTURE:
7903 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
7904 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
7905 if (remain < 5)
7906 return;
7907 idx += 5;
7908 break;
7909
7910 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
7911 if (remain < 7)
7912 return;
7913
7914 idx += 7;
7915 break;
7916
7917 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
7918 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
7919 return;
7920
7921 if (positionChanged)
7922 {
7923 positionChanged = false;
7924 av.OffsetPosition = finalPos;
7925 av.SendAvatarDataToAllAgents();
7926 }
7927
7928 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
7929 LSL_List new_rules = rules.GetSublist(idx, -1);
7930 setLinkPrimParams((int)new_linknumber, new_rules);
7931 return;
7932 }
7933 }
7934 }
7935
7936 finally
7937 {
7938 if (positionChanged)
7939 {
7940 av.OffsetPosition = finalPos;
7941 av.SendAvatarDataToAllAgents();
7942 positionChanged = false;
7943 }
7944 }
7204 } 7945 }
7205 7946
7206 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7947 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7207 { 7948 {
7949 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7950 return;
7951
7208 int idx = 0; 7952 int idx = 0;
7209 7953
7954 SceneObjectGroup parentgrp = part.ParentGroup;
7955
7210 bool positionChanged = false; 7956 bool positionChanged = false;
7211 LSL_Vector currentPosition = GetPartLocalPos(part); 7957 LSL_Vector currentPosition = GetPartLocalPos(part);
7212 7958
@@ -7229,8 +7975,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7229 return; 7975 return;
7230 7976
7231 v=rules.GetVector3Item(idx++); 7977 v=rules.GetVector3Item(idx++);
7232 positionChanged = true;
7233 currentPosition = GetSetPosTarget(part, v, currentPosition); 7978 currentPosition = GetSetPosTarget(part, v, currentPosition);
7979 positionChanged = true;
7234 7980
7235 break; 7981 break;
7236 case (int)ScriptBaseClass.PRIM_SIZE: 7982 case (int)ScriptBaseClass.PRIM_SIZE:
@@ -7246,8 +7992,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7246 return; 7992 return;
7247 7993
7248 LSL_Rotation q = rules.GetQuaternionItem(idx++); 7994 LSL_Rotation q = rules.GetQuaternionItem(idx++);
7995 SceneObjectPart rootPart = parentgrp.RootPart;
7249 // try to let this work as in SL... 7996 // try to let this work as in SL...
7250 if (part.ParentID == 0) 7997 if (rootPart == part)
7251 { 7998 {
7252 // special case: If we are root, rotate complete SOG to new rotation 7999 // special case: If we are root, rotate complete SOG to new rotation
7253 SetRot(part, Rot2Quaternion(q)); 8000 SetRot(part, Rot2Quaternion(q));
@@ -7255,7 +8002,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7255 else 8002 else
7256 { 8003 {
7257 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. 8004 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
7258 SceneObjectPart rootPart = part.ParentGroup.RootPart; 8005 // sounds like sl bug that we need to replicate
7259 SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q)); 8006 SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q));
7260 } 8007 }
7261 8008
@@ -7508,7 +8255,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7508 return; 8255 return;
7509 8256
7510 string ph = rules.Data[idx++].ToString(); 8257 string ph = rules.Data[idx++].ToString();
7511 m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); 8258 parentgrp.ScriptSetPhantomStatus(ph.Equals("1"));
7512 8259
7513 break; 8260 break;
7514 8261
@@ -7526,12 +8273,42 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7526 part.ScriptSetPhysicsStatus(physics); 8273 part.ScriptSetPhysicsStatus(physics);
7527 break; 8274 break;
7528 8275
8276 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
8277 if (remain < 1)
8278 return;
8279
8280 int shape_type = rules.GetLSLIntegerItem(idx++);
8281
8282 ExtraPhysicsData physdata = new ExtraPhysicsData();
8283 physdata.Density = part.Density;
8284 physdata.Bounce = part.Bounciness;
8285 physdata.GravitationModifier = part.GravityModifier;
8286 physdata.PhysShapeType = (PhysShapeType)shape_type;
8287
8288 part.UpdateExtraPhysics(physdata);
8289
8290 break;
8291
8292 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8293 if (remain < 5)
8294 return;
8295
8296 int material_bits = rules.GetLSLIntegerItem(idx++);
8297 float material_density = (float)rules.GetLSLFloatItem(idx++);
8298 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8299 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8300 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8301
8302 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8303
8304 break;
8305
7529 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8306 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7530 if (remain < 1) 8307 if (remain < 1)
7531 return; 8308 return;
7532 string temp = rules.Data[idx++].ToString(); 8309 string temp = rules.Data[idx++].ToString();
7533 8310
7534 m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); 8311 parentgrp.ScriptSetTemporaryStatus(temp.Equals("1"));
7535 8312
7536 break; 8313 break;
7537 8314
@@ -7581,13 +8358,37 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7581 LSL_Float gain = rules.GetLSLFloatItem(idx++); 8358 LSL_Float gain = rules.GetLSLFloatItem(idx++);
7582 TargetOmega(part, axis, (double)spinrate, (double)gain); 8359 TargetOmega(part, axis, (double)spinrate, (double)gain);
7583 break; 8360 break;
8361
7584 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 8362 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
7585 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 8363 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
7586 return; 8364 return;
8365
8366 // do a pending position change before jumping to other part/avatar
8367 if (positionChanged)
8368 {
8369 positionChanged = false;
8370 if (parentgrp == null)
8371 return;
8372
8373 if (parentgrp.RootPart == part)
8374 {
8375
8376 Util.FireAndForget(delegate(object x)
8377 {
8378 parentgrp.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8379 });
8380 }
8381 else
8382 {
8383 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8384 parentgrp.HasGroupChanged = true;
8385 parentgrp.ScheduleGroupForTerseUpdate();
8386 }
8387 }
8388
7587 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); 8389 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
7588 LSL_List new_rules = rules.GetSublist(idx, -1); 8390 LSL_List new_rules = rules.GetSublist(idx, -1);
7589 setLinkPrimParams((int)new_linknumber, new_rules); 8391 setLinkPrimParams((int)new_linknumber, new_rules);
7590
7591 return; 8392 return;
7592 } 8393 }
7593 } 8394 }
@@ -7599,7 +8400,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7599 if (part.ParentGroup.RootPart == part) 8400 if (part.ParentGroup.RootPart == part)
7600 { 8401 {
7601 SceneObjectGroup parent = part.ParentGroup; 8402 SceneObjectGroup parent = part.ParentGroup;
7602 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8403 Util.FireAndForget(delegate(object x) {
8404 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8405 });
7603 } 8406 }
7604 else 8407 else
7605 { 8408 {
@@ -7770,13 +8573,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7770 public LSL_Integer llGetNumberOfPrims() 8573 public LSL_Integer llGetNumberOfPrims()
7771 { 8574 {
7772 m_host.AddScriptLPS(1); 8575 m_host.AddScriptLPS(1);
7773 int avatarCount = 0; 8576 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7774 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8577
7775 {
7776 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
7777 avatarCount++;
7778 });
7779
7780 return m_host.ParentGroup.PrimCount + avatarCount; 8578 return m_host.ParentGroup.PrimCount + avatarCount;
7781 } 8579 }
7782 8580
@@ -7792,55 +8590,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7792 m_host.AddScriptLPS(1); 8590 m_host.AddScriptLPS(1);
7793 UUID objID = UUID.Zero; 8591 UUID objID = UUID.Zero;
7794 LSL_List result = new LSL_List(); 8592 LSL_List result = new LSL_List();
8593
8594 // If the ID is not valid, return null result
7795 if (!UUID.TryParse(obj, out objID)) 8595 if (!UUID.TryParse(obj, out objID))
7796 { 8596 {
7797 result.Add(new LSL_Vector()); 8597 result.Add(new LSL_Vector());
7798 result.Add(new LSL_Vector()); 8598 result.Add(new LSL_Vector());
7799 return result; 8599 return result;
7800 } 8600 }
8601
8602 // Check if this is an attached prim. If so, replace
8603 // the UUID with the avatar UUID and report it's bounding box
8604 SceneObjectPart part = World.GetSceneObjectPart(objID);
8605 if (part != null && part.ParentGroup.IsAttachment)
8606 objID = part.ParentGroup.AttachedAvatar;
8607
8608 // Find out if this is an avatar ID. If so, return it's box
7801 ScenePresence presence = World.GetScenePresence(objID); 8609 ScenePresence presence = World.GetScenePresence(objID);
7802 if (presence != null) 8610 if (presence != null)
7803 { 8611 {
7804 if (presence.ParentID == 0) // not sat on an object 8612 // As per LSL Wiki, there is no difference between sitting
8613 // and standing avatar since server 1.36
8614 LSL_Vector lower;
8615 LSL_Vector upper;
8616 if (presence.Animator.Animations.DefaultAnimation.AnimID
8617 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7805 { 8618 {
7806 LSL_Vector lower; 8619 // This is for ground sitting avatars
7807 LSL_Vector upper; 8620 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7808 if (presence.Animator.Animations.DefaultAnimation.AnimID 8621 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7809 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8622 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7810 {
7811 // This is for ground sitting avatars
7812 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7813 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7814 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7815 }
7816 else
7817 {
7818 // This is for standing/flying avatars
7819 float height = presence.Appearance.AvatarHeight / 2.0f;
7820 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7821 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7822 }
7823 result.Add(lower);
7824 result.Add(upper);
7825 return result;
7826 } 8623 }
7827 else 8624 else
7828 { 8625 {
7829 // sitting on an object so we need the bounding box of that 8626 // This is for standing/flying avatars
7830 // which should include the avatar so set the UUID to the 8627 float height = presence.Appearance.AvatarHeight / 2.0f;
7831 // UUID of the object the avatar is sat on and allow it to fall through 8628 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7832 // to processing an object 8629 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7833 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7834 objID = p.UUID;
7835 } 8630 }
8631
8632 // Adjust to the documented error offsets (see LSL Wiki)
8633 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8634 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8635
8636 if (lower.x > upper.x)
8637 lower.x = upper.x;
8638 if (lower.y > upper.y)
8639 lower.y = upper.y;
8640 if (lower.z > upper.z)
8641 lower.z = upper.z;
8642
8643 result.Add(lower);
8644 result.Add(upper);
8645 return result;
7836 } 8646 }
7837 SceneObjectPart part = World.GetSceneObjectPart(objID); 8647
8648 part = World.GetSceneObjectPart(objID);
7838 // Currently only works for single prims without a sitting avatar 8649 // Currently only works for single prims without a sitting avatar
7839 if (part != null) 8650 if (part != null)
7840 { 8651 {
7841 Vector3 halfSize = part.Scale / 2.0f; 8652 float minX;
7842 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8653 float maxX;
7843 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8654 float minY;
8655 float maxY;
8656 float minZ;
8657 float maxZ;
8658
8659 // This BBox is in sim coordinates, with the offset being
8660 // a contained point.
8661 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8662 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8663
8664 minX -= offsets[0].X;
8665 maxX -= offsets[0].X;
8666 minY -= offsets[0].Y;
8667 maxY -= offsets[0].Y;
8668 minZ -= offsets[0].Z;
8669 maxZ -= offsets[0].Z;
8670
8671 LSL_Vector lower;
8672 LSL_Vector upper;
8673
8674 // Adjust to the documented error offsets (see LSL Wiki)
8675 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8676 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8677
8678 if (lower.x > upper.x)
8679 lower.x = upper.x;
8680 if (lower.y > upper.y)
8681 lower.y = upper.y;
8682 if (lower.z > upper.z)
8683 lower.z = upper.z;
8684
7844 result.Add(lower); 8685 result.Add(lower);
7845 result.Add(upper); 8686 result.Add(upper);
7846 return result; 8687 return result;
@@ -7854,7 +8695,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7854 8695
7855 public LSL_Vector llGetGeometricCenter() 8696 public LSL_Vector llGetGeometricCenter()
7856 { 8697 {
7857 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 8698 Vector3 tmp = m_host.GetGeometricCenter();
8699 return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
7858 } 8700 }
7859 8701
7860 public LSL_List llGetPrimitiveParams(LSL_List rules) 8702 public LSL_List llGetPrimitiveParams(LSL_List rules)
@@ -7867,16 +8709,291 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7867 { 8709 {
7868 m_host.AddScriptLPS(1); 8710 m_host.AddScriptLPS(1);
7869 8711
8712 // acording to SL wiki this must indicate a single link number or link_root or link_this.
8713 // keep other options as before
8714
7870 List<SceneObjectPart> parts = GetLinkParts(linknumber); 8715 List<SceneObjectPart> parts = GetLinkParts(linknumber);
8716 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7871 8717
7872 LSL_List res = new LSL_List(); 8718 LSL_List res = new LSL_List();
7873 8719
7874 foreach (var part in parts) 8720 if (parts.Count > 0)
8721 {
8722 foreach (var part in parts)
8723 {
8724 LSL_List partRes = GetLinkPrimitiveParams(part, rules);
8725 res += partRes;
8726 }
8727 }
8728 if (avatars.Count > 0)
7875 { 8729 {
7876 LSL_List partRes = GetLinkPrimitiveParams(part, rules); 8730 foreach (ScenePresence avatar in avatars)
7877 res += partRes; 8731 {
8732 LSL_List avaRes = GetLinkPrimitiveParams(avatar, rules);
8733 res += avaRes;
8734 }
7878 } 8735 }
8736 return res;
8737 }
8738
8739 public LSL_List GetLinkPrimitiveParams(ScenePresence avatar, LSL_List rules)
8740 {
8741 // avatars case
8742 // replies as SL wiki
8743
8744 LSL_List res = new LSL_List();
8745// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
8746 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
8747
8748 int idx = 0;
8749 while (idx < rules.Length)
8750 {
8751 int code = (int)rules.GetLSLIntegerItem(idx++);
8752 int remain = rules.Length - idx;
8753
8754 switch (code)
8755 {
8756 case (int)ScriptBaseClass.PRIM_MATERIAL:
8757 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
8758 break;
8759
8760 case (int)ScriptBaseClass.PRIM_PHYSICS:
8761 res.Add(new LSL_Integer(0));
8762 break;
8763
8764 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
8765 res.Add(new LSL_Integer(0));
8766 break;
7879 8767
8768 case (int)ScriptBaseClass.PRIM_PHANTOM:
8769 res.Add(new LSL_Integer(0));
8770 break;
8771
8772 case (int)ScriptBaseClass.PRIM_POSITION:
8773
8774 Vector3 pos = avatar.OffsetPosition;
8775
8776 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
8777 pos -= sitOffset;
8778
8779 if( sitPart != null)
8780 pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation();
8781
8782 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
8783 break;
8784
8785 case (int)ScriptBaseClass.PRIM_SIZE:
8786 // as in llGetAgentSize above
8787 res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight));
8788 break;
8789
8790 case (int)ScriptBaseClass.PRIM_ROTATION:
8791 Quaternion rot = avatar.Rotation;
8792 if (sitPart != null)
8793 {
8794 rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation
8795 }
8796
8797 res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W));
8798 break;
8799
8800 case (int)ScriptBaseClass.PRIM_TYPE:
8801 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
8802 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
8803 res.Add(new LSL_Vector(0f,1.0f,0f));
8804 res.Add(new LSL_Float(0.0f));
8805 res.Add(new LSL_Vector(0, 0, 0));
8806 res.Add(new LSL_Vector(1.0f,1.0f,0f));
8807 res.Add(new LSL_Vector(0, 0, 0));
8808 break;
8809
8810 case (int)ScriptBaseClass.PRIM_TEXTURE:
8811 if (remain < 1)
8812 return res;
8813
8814 int face = (int)rules.GetLSLIntegerItem(idx++);
8815 if (face == ScriptBaseClass.ALL_SIDES)
8816 {
8817 for (face = 0; face < 21; face++)
8818 {
8819 res.Add(new LSL_String(""));
8820 res.Add(new LSL_Vector(0,0,0));
8821 res.Add(new LSL_Vector(0,0,0));
8822 res.Add(new LSL_Float(0.0));
8823 }
8824 }
8825 else
8826 {
8827 if (face >= 0 && face < 21)
8828 {
8829 res.Add(new LSL_String(""));
8830 res.Add(new LSL_Vector(0,0,0));
8831 res.Add(new LSL_Vector(0,0,0));
8832 res.Add(new LSL_Float(0.0));
8833 }
8834 }
8835 break;
8836
8837 case (int)ScriptBaseClass.PRIM_COLOR:
8838 if (remain < 1)
8839 return res;
8840
8841 face = (int)rules.GetLSLIntegerItem(idx++);
8842
8843 if (face == ScriptBaseClass.ALL_SIDES)
8844 {
8845 for (face = 0; face < 21; face++)
8846 {
8847 res.Add(new LSL_Vector(0,0,0));
8848 res.Add(new LSL_Float(0));
8849 }
8850 }
8851 else
8852 {
8853 res.Add(new LSL_Vector(0,0,0));
8854 res.Add(new LSL_Float(0));
8855 }
8856 break;
8857
8858 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8859 if (remain < 1)
8860 return res;
8861 face = (int)rules.GetLSLIntegerItem(idx++);
8862
8863 if (face == ScriptBaseClass.ALL_SIDES)
8864 {
8865 for (face = 0; face < 21; face++)
8866 {
8867 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
8868 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
8869 }
8870 }
8871 else
8872 {
8873 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
8874 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
8875 }
8876 break;
8877
8878 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8879 if (remain < 1)
8880 return res;
8881 face = (int)rules.GetLSLIntegerItem(idx++);
8882
8883 if (face == ScriptBaseClass.ALL_SIDES)
8884 {
8885 for (face = 0; face < 21; face++)
8886 {
8887 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
8888 }
8889 }
8890 else
8891 {
8892 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
8893 }
8894 break;
8895
8896 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
8897 res.Add(new LSL_Integer(0));
8898 res.Add(new LSL_Integer(0));// softness
8899 res.Add(new LSL_Float(0.0f)); // gravity
8900 res.Add(new LSL_Float(0.0f)); // friction
8901 res.Add(new LSL_Float(0.0f)); // wind
8902 res.Add(new LSL_Float(0.0f)); // tension
8903 res.Add(new LSL_Vector(0f,0f,0f));
8904 break;
8905
8906 case (int)ScriptBaseClass.PRIM_TEXGEN:
8907 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8908 if (remain < 1)
8909 return res;
8910 face = (int)rules.GetLSLIntegerItem(idx++);
8911
8912 if (face == ScriptBaseClass.ALL_SIDES)
8913 {
8914 for (face = 0; face < 21; face++)
8915 {
8916 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8917 }
8918 }
8919 else
8920 {
8921 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8922 }
8923 break;
8924
8925 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
8926 res.Add(new LSL_Integer(0));
8927 res.Add(new LSL_Vector(0f,0f,0f));
8928 res.Add(new LSL_Float(0f)); // intensity
8929 res.Add(new LSL_Float(0f)); // radius
8930 res.Add(new LSL_Float(0f)); // falloff
8931 break;
8932
8933 case (int)ScriptBaseClass.PRIM_GLOW:
8934 if (remain < 1)
8935 return res;
8936 face = (int)rules.GetLSLIntegerItem(idx++);
8937
8938 if (face == ScriptBaseClass.ALL_SIDES)
8939 {
8940 for (face = 0; face < 21; face++)
8941 {
8942 res.Add(new LSL_Float(0f));
8943 }
8944 }
8945 else
8946 {
8947 res.Add(new LSL_Float(0f));
8948 }
8949 break;
8950
8951 case (int)ScriptBaseClass.PRIM_TEXT:
8952 res.Add(new LSL_String(""));
8953 res.Add(new LSL_Vector(0f,0f,0f));
8954 res.Add(new LSL_Float(1.0f));
8955 break;
8956
8957 case (int)ScriptBaseClass.PRIM_NAME:
8958 res.Add(new LSL_String(avatar.Name));
8959 break;
8960
8961 case (int)ScriptBaseClass.PRIM_DESC:
8962 res.Add(new LSL_String(""));
8963 break;
8964
8965 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8966 Quaternion lrot = avatar.Rotation;
8967
8968 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
8969 {
8970 lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset
8971 }
8972 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
8973 break;
8974
8975 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
8976 Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part
8977 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
8978 lpos -= lsitOffset;
8979
8980 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
8981 {
8982 lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim
8983 }
8984 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
8985 break;
8986
8987 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
8988 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
8989 return res;
8990 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
8991 LSL_List new_rules = rules.GetSublist(idx, -1);
8992
8993 res += llGetLinkPrimitiveParams((int)new_linknumber, new_rules);
8994 return res;
8995 }
8996 }
7880 return res; 8997 return res;
7881 } 8998 }
7882 8999
@@ -7920,13 +9037,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7920 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 9037 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7921 part.AbsolutePosition.Y, 9038 part.AbsolutePosition.Y,
7922 part.AbsolutePosition.Z); 9039 part.AbsolutePosition.Z);
7923 // For some reason, the part.AbsolutePosition.* values do not change if the
7924 // linkset is rotated; they always reflect the child prim's world position
7925 // as though the linkset is unrotated. This is incompatible behavior with SL's
7926 // implementation, so will break scripts imported from there (not to mention it
7927 // makes it more difficult to determine a child prim's actual inworld position).
7928 if (part.ParentID != 0)
7929 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7930 res.Add(v); 9040 res.Add(v);
7931 break; 9041 break;
7932 9042
@@ -8097,56 +9207,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8097 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 9207 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8098 if (remain < 1) 9208 if (remain < 1)
8099 return res; 9209 return res;
8100 9210 face = (int)rules.GetLSLIntegerItem(idx++);
8101 face=(int)rules.GetLSLIntegerItem(idx++);
8102 9211
8103 tex = part.Shape.Textures; 9212 tex = part.Shape.Textures;
9213 int shiny;
8104 if (face == ScriptBaseClass.ALL_SIDES) 9214 if (face == ScriptBaseClass.ALL_SIDES)
8105 { 9215 {
8106 for (face = 0; face < GetNumberOfSides(part); face++) 9216 for (face = 0; face < GetNumberOfSides(part); face++)
8107 { 9217 {
8108 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9218 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8109 // Convert Shininess to PRIM_SHINY_* 9219 if (shinyness == Shininess.High)
8110 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 9220 {
8111 // PRIM_BUMP_* 9221 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8112 res.Add(new LSL_Integer((int)texface.Bump)); 9222 }
9223 else if (shinyness == Shininess.Medium)
9224 {
9225 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
9226 }
9227 else if (shinyness == Shininess.Low)
9228 {
9229 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
9230 }
9231 else
9232 {
9233 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
9234 }
9235 res.Add(new LSL_Integer(shiny));
9236 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8113 } 9237 }
8114 } 9238 }
8115 else 9239 else
8116 { 9240 {
8117 if (face >= 0 && face < GetNumberOfSides(part)) 9241 Shininess shinyness = tex.GetFace((uint)face).Shiny;
9242 if (shinyness == Shininess.High)
8118 { 9243 {
8119 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9244 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8120 // Convert Shininess to PRIM_SHINY_* 9245 }
8121 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 9246 else if (shinyness == Shininess.Medium)
8122 // PRIM_BUMP_* 9247 {
8123 res.Add(new LSL_Integer((int)texface.Bump)); 9248 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
9249 }
9250 else if (shinyness == Shininess.Low)
9251 {
9252 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
9253 }
9254 else
9255 {
9256 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8124 } 9257 }
9258 res.Add(new LSL_Integer(shiny));
9259 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8125 } 9260 }
8126 break; 9261 break;
8127 9262
8128 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 9263 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8129 if (remain < 1) 9264 if (remain < 1)
8130 return res; 9265 return res;
8131 9266 face = (int)rules.GetLSLIntegerItem(idx++);
8132 face=(int)rules.GetLSLIntegerItem(idx++);
8133 9267
8134 tex = part.Shape.Textures; 9268 tex = part.Shape.Textures;
9269 int fullbright;
8135 if (face == ScriptBaseClass.ALL_SIDES) 9270 if (face == ScriptBaseClass.ALL_SIDES)
8136 { 9271 {
8137 for (face = 0; face < GetNumberOfSides(part); face++) 9272 for (face = 0; face < GetNumberOfSides(part); face++)
8138 { 9273 {
8139 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9274 if (tex.GetFace((uint)face).Fullbright == true)
8140 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 9275 {
9276 fullbright = ScriptBaseClass.TRUE;
9277 }
9278 else
9279 {
9280 fullbright = ScriptBaseClass.FALSE;
9281 }
9282 res.Add(new LSL_Integer(fullbright));
8141 } 9283 }
8142 } 9284 }
8143 else 9285 else
8144 { 9286 {
8145 if (face >= 0 && face < GetNumberOfSides(part)) 9287 if (tex.GetFace((uint)face).Fullbright == true)
8146 { 9288 {
8147 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9289 fullbright = ScriptBaseClass.TRUE;
8148 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 9290 }
9291 else
9292 {
9293 fullbright = ScriptBaseClass.FALSE;
8149 } 9294 }
9295 res.Add(new LSL_Integer(fullbright));
8150 } 9296 }
8151 break; 9297 break;
8152 9298
@@ -8168,27 +9314,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8168 break; 9314 break;
8169 9315
8170 case (int)ScriptBaseClass.PRIM_TEXGEN: 9316 case (int)ScriptBaseClass.PRIM_TEXGEN:
9317 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8171 if (remain < 1) 9318 if (remain < 1)
8172 return res; 9319 return res;
8173 9320 face = (int)rules.GetLSLIntegerItem(idx++);
8174 face=(int)rules.GetLSLIntegerItem(idx++);
8175 9321
8176 tex = part.Shape.Textures; 9322 tex = part.Shape.Textures;
8177 if (face == ScriptBaseClass.ALL_SIDES) 9323 if (face == ScriptBaseClass.ALL_SIDES)
8178 { 9324 {
8179 for (face = 0; face < GetNumberOfSides(part); face++) 9325 for (face = 0; face < GetNumberOfSides(part); face++)
8180 { 9326 {
8181 MappingType texgen = tex.GetFace((uint)face).TexMapType; 9327 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8182 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 9328 {
8183 res.Add(new LSL_Integer((uint)texgen >> 1)); 9329 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
9330 }
9331 else
9332 {
9333 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
9334 }
8184 } 9335 }
8185 } 9336 }
8186 else 9337 else
8187 { 9338 {
8188 if (face >= 0 && face < GetNumberOfSides(part)) 9339 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
9340 {
9341 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
9342 }
9343 else
8189 { 9344 {
8190 MappingType texgen = tex.GetFace((uint)face).TexMapType; 9345 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8191 res.Add(new LSL_Integer((uint)texgen >> 1));
8192 } 9346 }
8193 } 9347 }
8194 break; 9348 break;
@@ -8211,25 +9365,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8211 case (int)ScriptBaseClass.PRIM_GLOW: 9365 case (int)ScriptBaseClass.PRIM_GLOW:
8212 if (remain < 1) 9366 if (remain < 1)
8213 return res; 9367 return res;
8214 9368 face = (int)rules.GetLSLIntegerItem(idx++);
8215 face=(int)rules.GetLSLIntegerItem(idx++);
8216 9369
8217 tex = part.Shape.Textures; 9370 tex = part.Shape.Textures;
9371 float primglow;
8218 if (face == ScriptBaseClass.ALL_SIDES) 9372 if (face == ScriptBaseClass.ALL_SIDES)
8219 { 9373 {
8220 for (face = 0; face < GetNumberOfSides(part); face++) 9374 for (face = 0; face < GetNumberOfSides(part); face++)
8221 { 9375 {
8222 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9376 primglow = tex.GetFace((uint)face).Glow;
8223 res.Add(new LSL_Float(texface.Glow)); 9377 res.Add(new LSL_Float(primglow));
8224 } 9378 }
8225 } 9379 }
8226 else 9380 else
8227 { 9381 {
8228 if (face >= 0 && face < GetNumberOfSides(part)) 9382 primglow = tex.GetFace((uint)face).Glow;
8229 { 9383 res.Add(new LSL_Float(primglow));
8230 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8231 res.Add(new LSL_Float(texface.Glow));
8232 }
8233 } 9384 }
8234 break; 9385 break;
8235 9386
@@ -8241,18 +9392,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8241 textColor.B)); 9392 textColor.B));
8242 res.Add(new LSL_Float(textColor.A)); 9393 res.Add(new LSL_Float(textColor.A));
8243 break; 9394 break;
9395
8244 case (int)ScriptBaseClass.PRIM_NAME: 9396 case (int)ScriptBaseClass.PRIM_NAME:
8245 res.Add(new LSL_String(part.Name)); 9397 res.Add(new LSL_String(part.Name));
8246 break; 9398 break;
9399
8247 case (int)ScriptBaseClass.PRIM_DESC: 9400 case (int)ScriptBaseClass.PRIM_DESC:
8248 res.Add(new LSL_String(part.Description)); 9401 res.Add(new LSL_String(part.Description));
8249 break; 9402 break;
9403
8250 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 9404 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8251 res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); 9405 res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W));
8252 break; 9406 break;
9407
8253 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 9408 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
8254 res.Add(new LSL_Vector(GetPartLocalPos(part))); 9409 res.Add(new LSL_Vector(GetPartLocalPos(part)));
8255 break; 9410 break;
9411
9412 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
9413 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
9414 return res;
9415 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
9416 LSL_List new_rules = rules.GetSublist(idx, -1);
9417 LSL_List tres = llGetLinkPrimitiveParams((int)new_linknumber, new_rules);
9418 res += tres;
9419 return res;
8256 } 9420 }
8257 } 9421 }
8258 return res; 9422 return res;
@@ -8845,8 +10009,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8845 // The function returns an ordered list 10009 // The function returns an ordered list
8846 // representing the tokens found in the supplied 10010 // representing the tokens found in the supplied
8847 // sources string. If two successive tokenizers 10011 // sources string. If two successive tokenizers
8848 // are encountered, then a NULL entry is added 10012 // are encountered, then a null-string entry is
8849 // to the list. 10013 // added to the list.
8850 // 10014 //
8851 // It is a precondition that the source and 10015 // It is a precondition that the source and
8852 // toekizer lisst are non-null. If they are null, 10016 // toekizer lisst are non-null. If they are null,
@@ -8854,7 +10018,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8854 // while their lengths are being determined. 10018 // while their lengths are being determined.
8855 // 10019 //
8856 // A small amount of working memoryis required 10020 // A small amount of working memoryis required
8857 // of approximately 8*#tokenizers. 10021 // of approximately 8*#tokenizers + 8*srcstrlen.
8858 // 10022 //
8859 // There are many ways in which this function 10023 // There are many ways in which this function
8860 // can be implemented, this implementation is 10024 // can be implemented, this implementation is
@@ -8870,155 +10034,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8870 // and eliminates redundant tokenizers as soon 10034 // and eliminates redundant tokenizers as soon
8871 // as is possible. 10035 // as is possible.
8872 // 10036 //
8873 // The implementation tries to avoid any copying 10037 // The implementation tries to minimize temporary
8874 // of arrays or other objects. 10038 // garbage generation.
8875 // </remarks> 10039 // </remarks>
8876 10040
8877 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 10041 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8878 { 10042 {
8879 int beginning = 0; 10043 return ParseString2List(src, separators, spacers, true);
8880 int srclen = src.Length; 10044 }
8881 int seplen = separators.Length;
8882 object[] separray = separators.Data;
8883 int spclen = spacers.Length;
8884 object[] spcarray = spacers.Data;
8885 int mlen = seplen+spclen;
8886
8887 int[] offset = new int[mlen+1];
8888 bool[] active = new bool[mlen];
8889
8890 int best;
8891 int j;
8892
8893 // Initial capacity reduces resize cost
8894 10045
8895 LSL_List tokens = new LSL_List(); 10046 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
10047 {
10048 int srclen = src.Length;
10049 int seplen = separators.Length;
10050 object[] separray = separators.Data;
10051 int spclen = spacers.Length;
10052 object[] spcarray = spacers.Data;
10053 int dellen = 0;
10054 string[] delarray = new string[seplen+spclen];
8896 10055
8897 // All entries are initially valid 10056 int outlen = 0;
10057 string[] outarray = new string[srclen*2+1];
8898 10058
8899 for (int i = 0; i < mlen; i++) 10059 int i, j;
8900 active[i] = true; 10060 string d;
8901 10061
8902 offset[mlen] = srclen; 10062 m_host.AddScriptLPS(1);
8903 10063
8904 while (beginning < srclen) 10064 /*
10065 * Convert separator and spacer lists to C# strings.
10066 * Also filter out null strings so we don't hang.
10067 */
10068 for (i = 0; i < seplen; i ++)
8905 { 10069 {
10070 d = separray[i].ToString();
10071 if (d.Length > 0)
10072 {
10073 delarray[dellen++] = d;
10074 }
10075 }
10076 seplen = dellen;
8906 10077
8907 best = mlen; // as bad as it gets 10078 for (i = 0; i < spclen; i ++)
10079 {
10080 d = spcarray[i].ToString();
10081 if (d.Length > 0)
10082 {
10083 delarray[dellen++] = d;
10084 }
10085 }
8908 10086
8909 // Scan for separators 10087 /*
10088 * Scan through source string from beginning to end.
10089 */
10090 for (i = 0;;)
10091 {
8910 10092
8911 for (j = 0; j < seplen; j++) 10093 /*
10094 * Find earliest delimeter in src starting at i (if any).
10095 */
10096 int earliestDel = -1;
10097 int earliestSrc = srclen;
10098 string earliestStr = null;
10099 for (j = 0; j < dellen; j ++)
8912 { 10100 {
8913 if (separray[j].ToString() == String.Empty) 10101 d = delarray[j];
8914 active[j] = false; 10102 if (d != null)
8915
8916 if (active[j])
8917 { 10103 {
8918 // scan all of the markers 10104 int index = src.IndexOf(d, i);
8919 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 10105 if (index < 0)
8920 { 10106 {
8921 // not present at all 10107 delarray[j] = null; // delim nowhere in src, don't check it anymore
8922 active[j] = false;
8923 } 10108 }
8924 else 10109 else if (index < earliestSrc)
8925 { 10110 {
8926 // present and correct 10111 earliestSrc = index; // where delimeter starts in source string
8927 if (offset[j] < offset[best]) 10112 earliestDel = j; // where delimeter is in delarray[]
8928 { 10113 earliestStr = d; // the delimeter string from delarray[]
8929 // closest so far 10114 if (index == i) break; // can't do any better than found at beg of string
8930 best = j;
8931 if (offset[best] == beginning)
8932 break;
8933 }
8934 } 10115 }
8935 } 10116 }
8936 } 10117 }
8937 10118
8938 // Scan for spacers 10119 /*
8939 10120 * Output source string starting at i through start of earliest delimeter.
8940 if (offset[best] != beginning) 10121 */
10122 if (keepNulls || (earliestSrc > i))
8941 { 10123 {
8942 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 10124 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8943 {
8944 if (spcarray[j-seplen].ToString() == String.Empty)
8945 active[j] = false;
8946
8947 if (active[j])
8948 {
8949 // scan all of the markers
8950 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8951 {
8952 // not present at all
8953 active[j] = false;
8954 }
8955 else
8956 {
8957 // present and correct
8958 if (offset[j] < offset[best])
8959 {
8960 // closest so far
8961 best = j;
8962 }
8963 }
8964 }
8965 }
8966 } 10125 }
8967 10126
8968 // This is the normal exit from the scanning loop 10127 /*
10128 * If no delimeter found at or after i, we're done scanning.
10129 */
10130 if (earliestDel < 0) break;
8969 10131
8970 if (best == mlen) 10132 /*
10133 * If delimeter was a spacer, output the spacer.
10134 */
10135 if (earliestDel >= seplen)
8971 { 10136 {
8972 // no markers were found on this pass 10137 outarray[outlen++] = earliestStr;
8973 // so we're pretty much done
8974 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8975 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8976 break;
8977 } 10138 }
8978 10139
8979 // Otherwise we just add the newly delimited token 10140 /*
8980 // and recalculate where the search should continue. 10141 * Look at rest of src string following delimeter.
8981 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 10142 */
8982 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 10143 i = earliestSrc + earliestStr.Length;
8983
8984 if (best < seplen)
8985 {
8986 beginning = offset[best] + (separray[best].ToString()).Length;
8987 }
8988 else
8989 {
8990 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8991 string str = spcarray[best - seplen].ToString();
8992 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8993 tokens.Add(new LSL_String(str));
8994 }
8995 } 10144 }
8996 10145
8997 // This an awkward an not very intuitive boundary case. If the 10146 /*
8998 // last substring is a tokenizer, then there is an implied trailing 10147 * Make up an exact-sized output array suitable for an LSL_List object.
8999 // null list entry. Hopefully the single comparison will not be too 10148 */
9000 // arduous. Alternatively the 'break' could be replced with a return 10149 object[] outlist = new object[outlen];
9001 // but that's shabby programming. 10150 for (i = 0; i < outlen; i ++)
9002
9003 if ((beginning == srclen) && (keepNulls))
9004 { 10151 {
9005 if (srclen != 0) 10152 outlist[i] = new LSL_String(outarray[i]);
9006 tokens.Add(new LSL_String(""));
9007 } 10153 }
9008 10154 return new LSL_List(outlist);
9009 return tokens;
9010 }
9011
9012 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
9013 {
9014 m_host.AddScriptLPS(1);
9015 return this.ParseString(src, separators, spacers, false);
9016 }
9017
9018 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
9019 {
9020 m_host.AddScriptLPS(1);
9021 return this.ParseString(src, separators, spacers, true);
9022 } 10155 }
9023 10156
9024 public LSL_Integer llGetObjectPermMask(int mask) 10157 public LSL_Integer llGetObjectPermMask(int mask)
@@ -9095,28 +10228,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9095 { 10228 {
9096 m_host.AddScriptLPS(1); 10229 m_host.AddScriptLPS(1);
9097 10230
9098 lock (m_host.TaskInventory) 10231 m_host.TaskInventory.LockItemsForRead(true);
10232 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9099 { 10233 {
9100 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10234 if (inv.Value.Name == item)
9101 { 10235 {
9102 if (inv.Value.Name == item) 10236 m_host.TaskInventory.LockItemsForRead(false);
10237 switch (mask)
9103 { 10238 {
9104 switch (mask) 10239 case 0:
9105 { 10240 return (int)inv.Value.BasePermissions;
9106 case 0: 10241 case 1:
9107 return (int)inv.Value.BasePermissions; 10242 return (int)inv.Value.CurrentPermissions;
9108 case 1: 10243 case 2:
9109 return (int)inv.Value.CurrentPermissions; 10244 return (int)inv.Value.GroupPermissions;
9110 case 2: 10245 case 3:
9111 return (int)inv.Value.GroupPermissions; 10246 return (int)inv.Value.EveryonePermissions;
9112 case 3: 10247 case 4:
9113 return (int)inv.Value.EveryonePermissions; 10248 return (int)inv.Value.NextPermissions;
9114 case 4:
9115 return (int)inv.Value.NextPermissions;
9116 }
9117 } 10249 }
9118 } 10250 }
9119 } 10251 }
10252 m_host.TaskInventory.LockItemsForRead(false);
9120 10253
9121 return -1; 10254 return -1;
9122 } 10255 }
@@ -9163,16 +10296,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9163 { 10296 {
9164 m_host.AddScriptLPS(1); 10297 m_host.AddScriptLPS(1);
9165 10298
9166 lock (m_host.TaskInventory) 10299 m_host.TaskInventory.LockItemsForRead(true);
10300 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9167 { 10301 {
9168 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10302 if (inv.Value.Name == item)
9169 { 10303 {
9170 if (inv.Value.Name == item) 10304 m_host.TaskInventory.LockItemsForRead(false);
9171 { 10305 return inv.Value.CreatorID.ToString();
9172 return inv.Value.CreatorID.ToString();
9173 }
9174 } 10306 }
9175 } 10307 }
10308 m_host.TaskInventory.LockItemsForRead(false);
9176 10309
9177 llSay(0, "No item name '" + item + "'"); 10310 llSay(0, "No item name '" + item + "'");
9178 10311
@@ -9314,9 +10447,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9314 { 10447 {
9315 try 10448 try
9316 { 10449 {
10450 /*
9317 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 10451 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
9318 if (obj != null) 10452 if (obj != null)
9319 return (double)obj.GetMass(); 10453 return (double)obj.GetMass();
10454 */
10455 // return total object mass
10456 SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
10457 if (obj != null)
10458 return obj.GetMass();
10459
9320 // the object is null so the key is for an avatar 10460 // the object is null so the key is for an avatar
9321 ScenePresence avatar = World.GetScenePresence(key); 10461 ScenePresence avatar = World.GetScenePresence(key);
9322 if (avatar != null) 10462 if (avatar != null)
@@ -9336,7 +10476,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9336 } 10476 }
9337 10477
9338 /// <summary> 10478 /// <summary>
9339 /// illListReplaceList removes the sub-list defined by the inclusive indices 10479 /// llListReplaceList removes the sub-list defined by the inclusive indices
9340 /// start and end and inserts the src list in its place. The inclusive 10480 /// start and end and inserts the src list in its place. The inclusive
9341 /// nature of the indices means that at least one element must be deleted 10481 /// nature of the indices means that at least one element must be deleted
9342 /// if the indices are within the bounds of the existing list. I.e. 2,2 10482 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9393,16 +10533,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9393 // based upon end. Note that if end exceeds the upper 10533 // based upon end. Note that if end exceeds the upper
9394 // bound in this case, the entire destination list 10534 // bound in this case, the entire destination list
9395 // is removed. 10535 // is removed.
9396 else 10536 else if (start == 0)
9397 { 10537 {
9398 if (end + 1 < dest.Length) 10538 if (end + 1 < dest.Length)
9399 {
9400 return src + dest.GetSublist(end + 1, -1); 10539 return src + dest.GetSublist(end + 1, -1);
9401 }
9402 else 10540 else
9403 {
9404 return src; 10541 return src;
9405 } 10542 }
10543 else // Start < 0
10544 {
10545 if (end + 1 < dest.Length)
10546 return dest.GetSublist(end + 1, -1);
10547 else
10548 return new LSL_List();
9406 } 10549 }
9407 } 10550 }
9408 // Finally, if start > end, we strip away a prefix and 10551 // Finally, if start > end, we strip away a prefix and
@@ -9453,17 +10596,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9453 int width = 0; 10596 int width = 0;
9454 int height = 0; 10597 int height = 0;
9455 10598
9456 ParcelMediaCommandEnum? commandToSend = null; 10599 uint commandToSend = 0;
9457 float time = 0.0f; // default is from start 10600 float time = 0.0f; // default is from start
9458 10601
9459 ScenePresence presence = null; 10602 ScenePresence presence = null;
9460 10603
9461 for (int i = 0; i < commandList.Data.Length; i++) 10604 for (int i = 0; i < commandList.Data.Length; i++)
9462 { 10605 {
9463 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10606 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9464 switch (command) 10607 switch (command)
9465 { 10608 {
9466 case ParcelMediaCommandEnum.Agent: 10609 case (uint)ParcelMediaCommandEnum.Agent:
9467 // we send only to one agent 10610 // we send only to one agent
9468 if ((i + 1) < commandList.Length) 10611 if ((i + 1) < commandList.Length)
9469 { 10612 {
@@ -9480,25 +10623,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9480 } 10623 }
9481 break; 10624 break;
9482 10625
9483 case ParcelMediaCommandEnum.Loop: 10626 case (uint)ParcelMediaCommandEnum.Loop:
9484 loop = 1; 10627 loop = 1;
9485 commandToSend = command; 10628 commandToSend = command;
9486 update = true; //need to send the media update packet to set looping 10629 update = true; //need to send the media update packet to set looping
9487 break; 10630 break;
9488 10631
9489 case ParcelMediaCommandEnum.Play: 10632 case (uint)ParcelMediaCommandEnum.Play:
9490 loop = 0; 10633 loop = 0;
9491 commandToSend = command; 10634 commandToSend = command;
9492 update = true; //need to send the media update packet to make sure it doesn't loop 10635 update = true; //need to send the media update packet to make sure it doesn't loop
9493 break; 10636 break;
9494 10637
9495 case ParcelMediaCommandEnum.Pause: 10638 case (uint)ParcelMediaCommandEnum.Pause:
9496 case ParcelMediaCommandEnum.Stop: 10639 case (uint)ParcelMediaCommandEnum.Stop:
9497 case ParcelMediaCommandEnum.Unload: 10640 case (uint)ParcelMediaCommandEnum.Unload:
9498 commandToSend = command; 10641 commandToSend = command;
9499 break; 10642 break;
9500 10643
9501 case ParcelMediaCommandEnum.Url: 10644 case (uint)ParcelMediaCommandEnum.Url:
9502 if ((i + 1) < commandList.Length) 10645 if ((i + 1) < commandList.Length)
9503 { 10646 {
9504 if (commandList.Data[i + 1] is LSL_String) 10647 if (commandList.Data[i + 1] is LSL_String)
@@ -9511,7 +10654,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9511 } 10654 }
9512 break; 10655 break;
9513 10656
9514 case ParcelMediaCommandEnum.Texture: 10657 case (uint)ParcelMediaCommandEnum.Texture:
9515 if ((i + 1) < commandList.Length) 10658 if ((i + 1) < commandList.Length)
9516 { 10659 {
9517 if (commandList.Data[i + 1] is LSL_String) 10660 if (commandList.Data[i + 1] is LSL_String)
@@ -9524,7 +10667,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9524 } 10667 }
9525 break; 10668 break;
9526 10669
9527 case ParcelMediaCommandEnum.Time: 10670 case (uint)ParcelMediaCommandEnum.Time:
9528 if ((i + 1) < commandList.Length) 10671 if ((i + 1) < commandList.Length)
9529 { 10672 {
9530 if (commandList.Data[i + 1] is LSL_Float) 10673 if (commandList.Data[i + 1] is LSL_Float)
@@ -9536,7 +10679,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9536 } 10679 }
9537 break; 10680 break;
9538 10681
9539 case ParcelMediaCommandEnum.AutoAlign: 10682 case (uint)ParcelMediaCommandEnum.AutoAlign:
9540 if ((i + 1) < commandList.Length) 10683 if ((i + 1) < commandList.Length)
9541 { 10684 {
9542 if (commandList.Data[i + 1] is LSL_Integer) 10685 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9550,7 +10693,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9550 } 10693 }
9551 break; 10694 break;
9552 10695
9553 case ParcelMediaCommandEnum.Type: 10696 case (uint)ParcelMediaCommandEnum.Type:
9554 if ((i + 1) < commandList.Length) 10697 if ((i + 1) < commandList.Length)
9555 { 10698 {
9556 if (commandList.Data[i + 1] is LSL_String) 10699 if (commandList.Data[i + 1] is LSL_String)
@@ -9563,7 +10706,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9563 } 10706 }
9564 break; 10707 break;
9565 10708
9566 case ParcelMediaCommandEnum.Desc: 10709 case (uint)ParcelMediaCommandEnum.Desc:
9567 if ((i + 1) < commandList.Length) 10710 if ((i + 1) < commandList.Length)
9568 { 10711 {
9569 if (commandList.Data[i + 1] is LSL_String) 10712 if (commandList.Data[i + 1] is LSL_String)
@@ -9576,7 +10719,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9576 } 10719 }
9577 break; 10720 break;
9578 10721
9579 case ParcelMediaCommandEnum.Size: 10722 case (uint)ParcelMediaCommandEnum.Size:
9580 if ((i + 2) < commandList.Length) 10723 if ((i + 2) < commandList.Length)
9581 { 10724 {
9582 if (commandList.Data[i + 1] is LSL_Integer) 10725 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9646,7 +10789,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9646 } 10789 }
9647 } 10790 }
9648 10791
9649 if (commandToSend != null) 10792 if (commandToSend != 0)
9650 { 10793 {
9651 // the commandList contained a start/stop/... command, too 10794 // the commandList contained a start/stop/... command, too
9652 if (presence == null) 10795 if (presence == null)
@@ -9683,7 +10826,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9683 10826
9684 if (aList.Data[i] != null) 10827 if (aList.Data[i] != null)
9685 { 10828 {
9686 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10829 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9687 { 10830 {
9688 case ParcelMediaCommandEnum.Url: 10831 case ParcelMediaCommandEnum.Url:
9689 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10832 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9726,16 +10869,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9726 { 10869 {
9727 m_host.AddScriptLPS(1); 10870 m_host.AddScriptLPS(1);
9728 10871
9729 lock (m_host.TaskInventory) 10872 m_host.TaskInventory.LockItemsForRead(true);
10873 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
9730 { 10874 {
9731 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 10875 if (inv.Value.Name == name)
9732 { 10876 {
9733 if (inv.Value.Name == name) 10877 m_host.TaskInventory.LockItemsForRead(false);
9734 { 10878 return inv.Value.Type;
9735 return inv.Value.Type;
9736 }
9737 } 10879 }
9738 } 10880 }
10881 m_host.TaskInventory.LockItemsForRead(false);
9739 10882
9740 return -1; 10883 return -1;
9741 } 10884 }
@@ -9746,15 +10889,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9746 10889
9747 if (quick_pay_buttons.Data.Length < 4) 10890 if (quick_pay_buttons.Data.Length < 4)
9748 { 10891 {
9749 LSLError("List must have at least 4 elements"); 10892 int x;
9750 return; 10893 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10894 {
10895 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10896 }
9751 } 10897 }
9752 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10898 int[] nPrice = new int[5];
9753 10899 nPrice[0] = price;
9754 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10900 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9755 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10901 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9756 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10902 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9757 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10903 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10904 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9758 m_host.ParentGroup.HasGroupChanged = true; 10905 m_host.ParentGroup.HasGroupChanged = true;
9759 } 10906 }
9760 10907
@@ -9771,7 +10918,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9771 return new LSL_Vector(); 10918 return new LSL_Vector();
9772 } 10919 }
9773 10920
9774 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10921// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10922 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9775 if (presence != null) 10923 if (presence != null)
9776 { 10924 {
9777 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); 10925 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
@@ -9793,7 +10941,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9793 return new LSL_Rotation(); 10941 return new LSL_Rotation();
9794 } 10942 }
9795 10943
9796 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10944// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10945 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9797 if (presence != null) 10946 if (presence != null)
9798 { 10947 {
9799 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); 10948 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W);
@@ -9853,8 +11002,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9853 { 11002 {
9854 m_host.AddScriptLPS(1); 11003 m_host.AddScriptLPS(1);
9855 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 11004 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
9856 if (detectedParams == null) return; // only works on the first detected avatar 11005 if (detectedParams == null)
9857 11006 {
11007 if (m_host.ParentGroup.IsAttachment == true)
11008 {
11009 detectedParams = new DetectParams();
11010 detectedParams.Key = m_host.OwnerID;
11011 }
11012 else
11013 {
11014 return;
11015 }
11016 }
11017
9858 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 11018 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9859 if (avatar != null) 11019 if (avatar != null)
9860 { 11020 {
@@ -9862,6 +11022,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9862 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 11022 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9863 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 11023 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9864 } 11024 }
11025
9865 ScriptSleep(1000); 11026 ScriptSleep(1000);
9866 } 11027 }
9867 11028
@@ -9985,12 +11146,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9985 11146
9986 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 11147 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9987 object[] data = rules.Data; 11148 object[] data = rules.Data;
9988 for (int i = 0; i < data.Length; ++i) { 11149 for (int i = 0; i < data.Length; ++i)
11150 {
9989 int type = Convert.ToInt32(data[i++].ToString()); 11151 int type = Convert.ToInt32(data[i++].ToString());
9990 if (i >= data.Length) break; // odd number of entries => ignore the last 11152 if (i >= data.Length) break; // odd number of entries => ignore the last
9991 11153
9992 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 11154 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9993 switch (type) { 11155 switch (type)
11156 {
9994 case ScriptBaseClass.CAMERA_FOCUS: 11157 case ScriptBaseClass.CAMERA_FOCUS:
9995 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 11158 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9996 case ScriptBaseClass.CAMERA_POSITION: 11159 case ScriptBaseClass.CAMERA_POSITION:
@@ -10096,19 +11259,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10096 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 11259 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
10097 { 11260 {
10098 m_host.AddScriptLPS(1); 11261 m_host.AddScriptLPS(1);
10099 string ret = String.Empty; 11262
10100 string src1 = llBase64ToString(str1); 11263 if (str1 == String.Empty)
10101 string src2 = llBase64ToString(str2); 11264 return String.Empty;
10102 int c = 0; 11265 if (str2 == String.Empty)
10103 for (int i = 0; i < src1.Length; i++) 11266 return str1;
11267
11268 int len = str2.Length;
11269 if ((len % 4) != 0) // LL is EVIL!!!!
10104 { 11270 {
10105 ret += (char) (src1[i] ^ src2[c]); 11271 while (str2.EndsWith("="))
11272 str2 = str2.Substring(0, str2.Length - 1);
11273
11274 len = str2.Length;
11275 int mod = len % 4;
10106 11276
10107 c++; 11277 if (mod == 1)
10108 if (c >= src2.Length) 11278 str2 = str2.Substring(0, str2.Length - 1);
10109 c = 0; 11279 else if (mod == 2)
11280 str2 += "==";
11281 else if (mod == 3)
11282 str2 += "=";
10110 } 11283 }
10111 return llStringToBase64(ret); 11284
11285 byte[] data1;
11286 byte[] data2;
11287 try
11288 {
11289 data1 = Convert.FromBase64String(str1);
11290 data2 = Convert.FromBase64String(str2);
11291 }
11292 catch (Exception)
11293 {
11294 return new LSL_String(String.Empty);
11295 }
11296
11297 byte[] d2 = new Byte[data1.Length];
11298 int pos = 0;
11299
11300 if (data1.Length <= data2.Length)
11301 {
11302 Array.Copy(data2, 0, d2, 0, data1.Length);
11303 }
11304 else
11305 {
11306 while (pos < data1.Length)
11307 {
11308 len = data1.Length - pos;
11309 if (len > data2.Length)
11310 len = data2.Length;
11311
11312 Array.Copy(data2, 0, d2, pos, len);
11313 pos += len;
11314 }
11315 }
11316
11317 for (pos = 0 ; pos < data1.Length ; pos++ )
11318 data1[pos] ^= d2[pos];
11319
11320 return Convert.ToBase64String(data1);
10112 } 11321 }
10113 11322
10114 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 11323 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10165,12 +11374,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10165 Regex r = new Regex(authregex); 11374 Regex r = new Regex(authregex);
10166 int[] gnums = r.GetGroupNumbers(); 11375 int[] gnums = r.GetGroupNumbers();
10167 Match m = r.Match(url); 11376 Match m = r.Match(url);
10168 if (m.Success) { 11377 if (m.Success)
10169 for (int i = 1; i < gnums.Length; i++) { 11378 {
11379 for (int i = 1; i < gnums.Length; i++)
11380 {
10170 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 11381 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10171 //CaptureCollection cc = g.Captures; 11382 //CaptureCollection cc = g.Captures;
10172 } 11383 }
10173 if (m.Groups.Count == 5) { 11384 if (m.Groups.Count == 5)
11385 {
10174 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 11386 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10175 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 11387 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10176 } 11388 }
@@ -10373,6 +11585,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10373 11585
10374 LSL_List ret = new LSL_List(); 11586 LSL_List ret = new LSL_List();
10375 UUID key = new UUID(); 11587 UUID key = new UUID();
11588
11589
10376 if (UUID.TryParse(id, out key)) 11590 if (UUID.TryParse(id, out key))
10377 { 11591 {
10378 ScenePresence av = World.GetScenePresence(key); 11592 ScenePresence av = World.GetScenePresence(key);
@@ -10390,13 +11604,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10390 ret.Add(new LSL_String("")); 11604 ret.Add(new LSL_String(""));
10391 break; 11605 break;
10392 case ScriptBaseClass.OBJECT_POS: 11606 case ScriptBaseClass.OBJECT_POS:
10393 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); 11607 Vector3 avpos;
11608
11609 if (av.ParentID != 0 && av.ParentPart != null)
11610 {
11611 avpos = av.OffsetPosition;
11612
11613 Vector3 sitOffset = (Zrot(av.Rotation)) * (av.Appearance.AvatarHeight * 0.02638f *2.0f);
11614 avpos -= sitOffset;
11615
11616 avpos = av.ParentPart.GetWorldPosition() + avpos * av.ParentPart.GetWorldRotation();
11617 }
11618 else
11619 avpos = av.AbsolutePosition;
11620
11621 ret.Add(new LSL_Vector((double)avpos.X, (double)avpos.Y, (double)avpos.Z));
10394 break; 11622 break;
10395 case ScriptBaseClass.OBJECT_ROT: 11623 case ScriptBaseClass.OBJECT_ROT:
10396 ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W)); 11624 Quaternion avrot = av.Rotation;
11625 if (av.ParentID != 0 && av.ParentPart != null)
11626 {
11627 avrot = av.ParentPart.GetWorldRotation() * avrot;
11628 }
11629 ret.Add(new LSL_Rotation((double)avrot.X, (double)avrot.Y, (double)avrot.Z, (double)avrot.W));
10397 break; 11630 break;
10398 case ScriptBaseClass.OBJECT_VELOCITY: 11631 case ScriptBaseClass.OBJECT_VELOCITY:
10399 ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); 11632 Vector3 avvel = av.Velocity;
11633 ret.Add(new LSL_Vector((double)avvel.X, (double)avvel.Y, (double)avvel.Z));
10400 break; 11634 break;
10401 case ScriptBaseClass.OBJECT_OWNER: 11635 case ScriptBaseClass.OBJECT_OWNER:
10402 ret.Add(new LSL_String(id)); 11636 ret.Add(new LSL_String(id));
@@ -10452,17 +11686,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10452 case ScriptBaseClass.OBJECT_NAME: 11686 case ScriptBaseClass.OBJECT_NAME:
10453 ret.Add(new LSL_String(obj.Name)); 11687 ret.Add(new LSL_String(obj.Name));
10454 break; 11688 break;
10455 case ScriptBaseClass.OBJECT_DESC: 11689 case ScriptBaseClass.OBJECT_DESC:
10456 ret.Add(new LSL_String(obj.Description)); 11690 ret.Add(new LSL_String(obj.Description));
10457 break; 11691 break;
10458 case ScriptBaseClass.OBJECT_POS: 11692 case ScriptBaseClass.OBJECT_POS:
10459 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); 11693 Vector3 opos = obj.AbsolutePosition;
11694 ret.Add(new LSL_Vector(opos.X, opos.Y, opos.Z));
10460 break; 11695 break;
10461 case ScriptBaseClass.OBJECT_ROT: 11696 case ScriptBaseClass.OBJECT_ROT:
10462 ret.Add(new LSL_Rotation(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W)); 11697// Quaternion orot = obj.RotationOffset;
11698// ret.Add(new LSL_Rotation(orot.X, orot.Y, orot.Z, orot.W));
11699
11700 LSL_Rotation objrot = GetPartRot(obj);
11701 ret.Add(objrot);
10463 break; 11702 break;
10464 case ScriptBaseClass.OBJECT_VELOCITY: 11703 case ScriptBaseClass.OBJECT_VELOCITY:
10465 ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z)); 11704 Vector3 ovel = obj.Velocity;
11705 ret.Add(new LSL_Vector(ovel.X, ovel.Y, ovel.Z));
10466 break; 11706 break;
10467 case ScriptBaseClass.OBJECT_OWNER: 11707 case ScriptBaseClass.OBJECT_OWNER:
10468 ret.Add(new LSL_String(obj.OwnerID.ToString())); 11708 ret.Add(new LSL_String(obj.OwnerID.ToString()));
@@ -10496,9 +11736,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10496 // The value returned in SL for normal prims is prim count 11736 // The value returned in SL for normal prims is prim count
10497 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount)); 11737 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
10498 break; 11738 break;
10499 // The following 3 costs I have intentionaly coded to return zero. They are part of 11739
10500 // "Land Impact" calculations. These calculations are probably not applicable 11740 // costs below may need to be diferent for root parts, need to check
10501 // to OpenSim and are not yet complete in SL
10502 case ScriptBaseClass.OBJECT_SERVER_COST: 11741 case ScriptBaseClass.OBJECT_SERVER_COST:
10503 // The linden calculation is here 11742 // The linden calculation is here
10504 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight 11743 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
@@ -10506,16 +11745,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10506 ret.Add(new LSL_Float(0)); 11745 ret.Add(new LSL_Float(0));
10507 break; 11746 break;
10508 case ScriptBaseClass.OBJECT_STREAMING_COST: 11747 case ScriptBaseClass.OBJECT_STREAMING_COST:
10509 // The linden calculation is here 11748 // The value returned in SL for normal prims is prim count * 0.06
10510 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost 11749 ret.Add(new LSL_Float(obj.StreamingCost));
10511 // The value returned in SL for normal prims looks like the prim count * 0.06
10512 ret.Add(new LSL_Float(0));
10513 break; 11750 break;
10514 case ScriptBaseClass.OBJECT_PHYSICS_COST: 11751 case ScriptBaseClass.OBJECT_PHYSICS_COST:
10515 // The linden calculation is here 11752 // The value returned in SL for normal prims is prim count
10516 // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics 11753 ret.Add(new LSL_Float(obj.PhysicsCost));
10517 // The value returned in SL for normal prims looks like the prim count
10518 ret.Add(new LSL_Float(0));
10519 break; 11754 break;
10520 default: 11755 default:
10521 // Invalid or unhandled constant. 11756 // Invalid or unhandled constant.
@@ -10533,15 +11768,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10533 11768
10534 internal UUID ScriptByName(string name) 11769 internal UUID ScriptByName(string name)
10535 { 11770 {
10536 lock (m_host.TaskInventory) 11771 m_host.TaskInventory.LockItemsForRead(true);
11772
11773 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
10537 { 11774 {
10538 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 11775 if (item.Type == 10 && item.Name == name)
10539 { 11776 {
10540 if (item.Type == 10 && item.Name == name) 11777 m_host.TaskInventory.LockItemsForRead(false);
10541 return item.ItemID; 11778 return item.ItemID;
10542 } 11779 }
10543 } 11780 }
10544 11781
11782 m_host.TaskInventory.LockItemsForRead(false);
11783
10545 return UUID.Zero; 11784 return UUID.Zero;
10546 } 11785 }
10547 11786
@@ -10582,6 +11821,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10582 { 11821 {
10583 m_host.AddScriptLPS(1); 11822 m_host.AddScriptLPS(1);
10584 11823
11824 //Clone is thread safe
10585 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11825 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10586 11826
10587 UUID assetID = UUID.Zero; 11827 UUID assetID = UUID.Zero;
@@ -10644,6 +11884,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10644 { 11884 {
10645 m_host.AddScriptLPS(1); 11885 m_host.AddScriptLPS(1);
10646 11886
11887 //Clone is thread safe
10647 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); 11888 TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
10648 11889
10649 UUID assetID = UUID.Zero; 11890 UUID assetID = UUID.Zero;
@@ -10724,15 +11965,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10724 return GetLinkPrimitiveParams(obj, rules); 11965 return GetLinkPrimitiveParams(obj, rules);
10725 } 11966 }
10726 11967
10727 public void print(string str) 11968 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10728 { 11969 {
10729 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11970 List<SceneObjectPart> parts = GetLinkParts(link);
10730 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11971 if (parts.Count < 1)
10731 if (ossl != null) 11972 return 0;
10732 { 11973
10733 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11974 return GetNumberOfSides(parts[0]);
10734 m_log.Info("LSL print():" + str);
10735 }
10736 } 11975 }
10737 11976
10738 private string Name2Username(string name) 11977 private string Name2Username(string name)
@@ -10778,6 +12017,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10778 return rq.ToString(); 12017 return rq.ToString();
10779 } 12018 }
10780 12019
12020 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
12021 {
12022 m_SayShoutCount = 0;
12023 }
12024
10781 private struct Tri 12025 private struct Tri
10782 { 12026 {
10783 public Vector3 p1; 12027 public Vector3 p1;
@@ -10917,9 +12161,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10917 12161
10918 ContactResult result = new ContactResult (); 12162 ContactResult result = new ContactResult ();
10919 result.ConsumerID = group.LocalId; 12163 result.ConsumerID = group.LocalId;
10920 result.Depth = intersection.distance; 12164// result.Depth = intersection.distance;
10921 result.Normal = intersection.normal; 12165 result.Normal = intersection.normal;
10922 result.Pos = intersection.ipoint; 12166 result.Pos = intersection.ipoint;
12167 result.Depth = Vector3.Mag(rayStart - result.Pos);
10923 12168
10924 contacts.Add(result); 12169 contacts.Add(result);
10925 }); 12170 });
@@ -11052,6 +12297,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11052 12297
11053 return contacts[0]; 12298 return contacts[0];
11054 } 12299 }
12300/*
12301 // not done:
12302 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
12303 {
12304 ContactResult[] contacts = null;
12305 World.ForEachSOG(delegate(SceneObjectGroup group)
12306 {
12307 if (m_host.ParentGroup == group)
12308 return;
12309
12310 if (group.IsAttachment)
12311 return;
12312
12313 if(group.RootPart.PhysActor != null)
12314 return;
12315
12316 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
12317 });
12318 return contacts;
12319 }
12320*/
11055 12321
11056 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 12322 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
11057 { 12323 {
@@ -11093,32 +12359,96 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11093 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 12359 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
11094 12360
11095 12361
11096 if (checkTerrain) 12362 if (false)// World.SuportsRayCastFiltered())
11097 { 12363 {
11098 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); 12364 if (dist == 0)
11099 if (groundContact != null) 12365 return list;
11100 results.Add((ContactResult)groundContact);
11101 }
11102 12366
11103 if (checkAgents) 12367 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
11104 { 12368 if (checkTerrain)
11105 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); 12369 rayfilter |= RayFilterFlags.land;
11106 foreach (ContactResult r in agentHits) 12370// if (checkAgents)
11107 results.Add(r); 12371// rayfilter |= RayFilterFlags.agent;
11108 } 12372 if (checkPhysical)
12373 rayfilter |= RayFilterFlags.physical;
12374 if (checkNonPhysical)
12375 rayfilter |= RayFilterFlags.nonphysical;
12376 if (detectPhantom)
12377 rayfilter |= RayFilterFlags.LSLPhanton;
12378
12379 Vector3 direction = dir * ( 1/dist);
12380
12381 if(rayfilter == 0)
12382 {
12383 list.Add(new LSL_Integer(0));
12384 return list;
12385 }
12386
12387 // get some more contacts to sort ???
12388 int physcount = 4 * count;
12389 if (physcount > 20)
12390 physcount = 20;
12391
12392 object physresults;
12393 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
12394
12395 if (physresults == null)
12396 {
12397 list.Add(new LSL_Integer(-3)); // timeout error
12398 return list;
12399 }
11109 12400
11110 if (checkPhysical || checkNonPhysical || detectPhantom) 12401 results = (List<ContactResult>)physresults;
12402
12403 // for now physics doesn't detect sitted avatars so do it outside physics
12404 if (checkAgents)
12405 {
12406 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
12407 foreach (ContactResult r in agentHits)
12408 results.Add(r);
12409 }
12410
12411 // TODO: Replace this with a better solution. ObjectIntersection can only
12412 // detect nonphysical phantoms. They are detected by virtue of being
12413 // nonphysical (e.g. no PhysActor) so will not conflict with detecting
12414 // physicsl phantoms as done by the physics scene
12415 // We don't want anything else but phantoms here.
12416 if (detectPhantom)
12417 {
12418 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, false, false, true);
12419 foreach (ContactResult r in objectHits)
12420 results.Add(r);
12421 }
12422 }
12423 else
11111 { 12424 {
11112 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); 12425 if (checkTerrain)
11113 foreach (ContactResult r in objectHits) 12426 {
11114 results.Add(r); 12427 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
12428 if (groundContact != null)
12429 results.Add((ContactResult)groundContact);
12430 }
12431
12432 if (checkAgents)
12433 {
12434 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
12435 foreach (ContactResult r in agentHits)
12436 results.Add(r);
12437 }
12438
12439 if (checkPhysical || checkNonPhysical || detectPhantom)
12440 {
12441 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
12442 foreach (ContactResult r in objectHits)
12443 results.Add(r);
12444 }
11115 } 12445 }
11116 12446
11117 results.Sort(delegate(ContactResult a, ContactResult b) 12447 results.Sort(delegate(ContactResult a, ContactResult b)
11118 { 12448 {
11119 return a.Depth.CompareTo(b.Depth); 12449 return a.Depth.CompareTo(b.Depth);
11120 }); 12450 });
11121 12451
11122 int values = 0; 12452 int values = 0;
11123 SceneObjectGroup thisgrp = m_host.ParentGroup; 12453 SceneObjectGroup thisgrp = m_host.ParentGroup;
11124 12454
@@ -11211,7 +12541,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11211 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 12541 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
11212 if (!isAccount) return 0; 12542 if (!isAccount) return 0;
11213 if (estate.HasAccess(id)) return 1; 12543 if (estate.HasAccess(id)) return 1;
11214 if (estate.IsBanned(id)) 12544 if (estate.IsBanned(id, World.GetUserFlags(id)))
11215 estate.RemoveBan(id); 12545 estate.RemoveBan(id);
11216 estate.AddEstateUser(id); 12546 estate.AddEstateUser(id);
11217 break; 12547 break;
@@ -11230,14 +12560,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11230 break; 12560 break;
11231 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 12561 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
11232 if (!isAccount) return 0; 12562 if (!isAccount) return 0;
11233 if (estate.IsBanned(id)) return 1; 12563 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
11234 EstateBan ban = new EstateBan(); 12564 EstateBan ban = new EstateBan();
11235 ban.EstateID = estate.EstateID; 12565 ban.EstateID = estate.EstateID;
11236 ban.BannedUserID = id; 12566 ban.BannedUserID = id;
11237 estate.AddBan(ban); 12567 estate.AddBan(ban);
11238 break; 12568 break;
11239 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 12569 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
11240 if (!isAccount || !estate.IsBanned(id)) return 0; 12570 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
11241 estate.RemoveBan(id); 12571 estate.RemoveBan(id);
11242 break; 12572 break;
11243 default: return 0; 12573 default: return 0;
@@ -11266,7 +12596,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11266 return 16384; 12596 return 16384;
11267 } 12597 }
11268 12598
11269 public LSL_Integer llGetUsedMemory() 12599 public virtual LSL_Integer llGetUsedMemory()
11270 { 12600 {
11271 m_host.AddScriptLPS(1); 12601 m_host.AddScriptLPS(1);
11272 // The value returned for LSO scripts in SL 12602 // The value returned for LSO scripts in SL
@@ -11294,7 +12624,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11294 public void llSetSoundQueueing(int queue) 12624 public void llSetSoundQueueing(int queue)
11295 { 12625 {
11296 m_host.AddScriptLPS(1); 12626 m_host.AddScriptLPS(1);
11297 NotImplemented("llSetSoundQueueing");
11298 } 12627 }
11299 12628
11300 public void llCollisionSprite(string impact_sprite) 12629 public void llCollisionSprite(string impact_sprite)
@@ -11306,10 +12635,270 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11306 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12635 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
11307 { 12636 {
11308 m_host.AddScriptLPS(1); 12637 m_host.AddScriptLPS(1);
11309 NotImplemented("llGodLikeRezObject"); 12638
12639 if (!World.Permissions.IsGod(m_host.OwnerID))
12640 NotImplemented("llGodLikeRezObject");
12641
12642 AssetBase rezAsset = World.AssetService.Get(inventory);
12643 if (rezAsset == null)
12644 {
12645 llSay(0, "Asset not found");
12646 return;
12647 }
12648
12649 SceneObjectGroup group = null;
12650
12651 try
12652 {
12653 string xmlData = Utils.BytesToString(rezAsset.Data);
12654 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12655 }
12656 catch
12657 {
12658 llSay(0, "Asset not found");
12659 return;
12660 }
12661
12662 if (group == null)
12663 {
12664 llSay(0, "Asset not found");
12665 return;
12666 }
12667
12668 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12669 group.RootPart.AttachOffset = group.AbsolutePosition;
12670
12671 group.ResetIDs();
12672
12673 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12674 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12675 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12676 group.ScheduleGroupForFullUpdate();
12677
12678 // objects rezzed with this method are die_at_edge by default.
12679 group.RootPart.SetDieAtEdge(true);
12680
12681 group.ResumeScripts();
12682
12683 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12684 "object_rez", new Object[] {
12685 new LSL_String(
12686 group.RootPart.UUID.ToString()) },
12687 new DetectParams[0]));
12688 }
12689
12690 public LSL_String llTransferLindenDollars(string destination, int amount)
12691 {
12692 UUID txn = UUID.Random();
12693
12694 Util.FireAndForget(delegate(object x)
12695 {
12696 int replycode = 0;
12697 string replydata = destination + "," + amount.ToString();
12698
12699 try
12700 {
12701 TaskInventoryItem item = m_item;
12702 if (item == null)
12703 {
12704 replydata = "SERVICE_ERROR";
12705 return;
12706 }
12707
12708 m_host.AddScriptLPS(1);
12709
12710 if (item.PermsGranter == UUID.Zero)
12711 {
12712 replydata = "MISSING_PERMISSION_DEBIT";
12713 return;
12714 }
12715
12716 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
12717 {
12718 replydata = "MISSING_PERMISSION_DEBIT";
12719 return;
12720 }
12721
12722 UUID toID = new UUID();
12723
12724 if (!UUID.TryParse(destination, out toID))
12725 {
12726 replydata = "INVALID_AGENT";
12727 return;
12728 }
12729
12730 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
12731
12732 if (money == null)
12733 {
12734 replydata = "TRANSFERS_DISABLED";
12735 return;
12736 }
12737
12738 bool result = money.ObjectGiveMoney(
12739 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
12740
12741 if (result)
12742 {
12743 replycode = 1;
12744 return;
12745 }
12746
12747 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
12748 }
12749 finally
12750 {
12751 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
12752 "transaction_result", new Object[] {
12753 new LSL_String(txn.ToString()),
12754 new LSL_Integer(replycode),
12755 new LSL_String(replydata) },
12756 new DetectParams[0]));
12757 }
12758 });
12759
12760 return txn.ToString();
11310 } 12761 }
11311 12762
11312 #endregion 12763 #endregion
12764
12765 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12766 {
12767 SceneObjectGroup group = m_host.ParentGroup;
12768
12769 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12770 return;
12771 if (group.IsAttachment)
12772 return;
12773
12774 if (frames.Data.Length > 0) // We are getting a new motion
12775 {
12776 if (group.RootPart.KeyframeMotion != null)
12777 group.RootPart.KeyframeMotion.Stop();
12778 group.RootPart.KeyframeMotion = null;
12779
12780 int idx = 0;
12781
12782 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12783 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12784
12785 while (idx < options.Data.Length)
12786 {
12787 int option = (int)options.GetLSLIntegerItem(idx++);
12788 int remain = options.Data.Length - idx;
12789
12790 switch (option)
12791 {
12792 case ScriptBaseClass.KFM_MODE:
12793 if (remain < 1)
12794 break;
12795 int modeval = (int)options.GetLSLIntegerItem(idx++);
12796 switch(modeval)
12797 {
12798 case ScriptBaseClass.KFM_FORWARD:
12799 mode = KeyframeMotion.PlayMode.Forward;
12800 break;
12801 case ScriptBaseClass.KFM_REVERSE:
12802 mode = KeyframeMotion.PlayMode.Reverse;
12803 break;
12804 case ScriptBaseClass.KFM_LOOP:
12805 mode = KeyframeMotion.PlayMode.Loop;
12806 break;
12807 case ScriptBaseClass.KFM_PING_PONG:
12808 mode = KeyframeMotion.PlayMode.PingPong;
12809 break;
12810 }
12811 break;
12812 case ScriptBaseClass.KFM_DATA:
12813 if (remain < 1)
12814 break;
12815 int dataval = (int)options.GetLSLIntegerItem(idx++);
12816 data = (KeyframeMotion.DataFormat)dataval;
12817 break;
12818 }
12819 }
12820
12821 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12822
12823 idx = 0;
12824
12825 int elemLength = 2;
12826 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12827 elemLength = 3;
12828
12829 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12830 while (idx < frames.Data.Length)
12831 {
12832 int remain = frames.Data.Length - idx;
12833
12834 if (remain < elemLength)
12835 break;
12836
12837 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12838 frame.Position = null;
12839 frame.Rotation = null;
12840
12841 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12842 {
12843 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12844 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12845 }
12846 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12847 {
12848 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12849 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12850 }
12851
12852 float tempf = (float)frames.GetLSLFloatItem(idx++);
12853 frame.TimeMS = (int)(tempf * 1000.0f);
12854
12855 keyframes.Add(frame);
12856 }
12857
12858 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12859 group.RootPart.KeyframeMotion.Start();
12860 }
12861 else
12862 {
12863 if (group.RootPart.KeyframeMotion == null)
12864 return;
12865
12866 if (options.Data.Length == 0)
12867 {
12868 group.RootPart.KeyframeMotion.Stop();
12869 return;
12870 }
12871
12872 int code = (int)options.GetLSLIntegerItem(0);
12873
12874 int idx = 0;
12875
12876 while (idx < options.Data.Length)
12877 {
12878 int option = (int)options.GetLSLIntegerItem(idx++);
12879 int remain = options.Data.Length - idx;
12880
12881 switch (option)
12882 {
12883 case ScriptBaseClass.KFM_COMMAND:
12884 int cmd = (int)options.GetLSLIntegerItem(idx++);
12885 switch (cmd)
12886 {
12887 case ScriptBaseClass.KFM_CMD_PLAY:
12888 group.RootPart.KeyframeMotion.Start();
12889 break;
12890 case ScriptBaseClass.KFM_CMD_STOP:
12891 group.RootPart.KeyframeMotion.Stop();
12892 break;
12893 case ScriptBaseClass.KFM_CMD_PAUSE:
12894 group.RootPart.KeyframeMotion.Pause();
12895 break;
12896 }
12897 break;
12898 }
12899 }
12900 }
12901 }
11313 } 12902 }
11314 12903
11315 public class NotecardCache 12904 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 7fa25f5..795376b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -138,6 +138,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
138 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow; 138 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow;
139 internal float m_ScriptDelayFactor = 1.0f; 139 internal float m_ScriptDelayFactor = 1.0f;
140 internal float m_ScriptDistanceFactor = 1.0f; 140 internal float m_ScriptDistanceFactor = 1.0f;
141 internal bool m_debuggerSafe = false;
141 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); 142 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
142 143
143 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 144 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
@@ -145,6 +146,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
145 m_ScriptEngine = ScriptEngine; 146 m_ScriptEngine = ScriptEngine;
146 m_host = host; 147 m_host = host;
147 m_item = item; 148 m_item = item;
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>
@@ -920,18 +929,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
920 if (target != null) 929 if (target != null)
921 { 930 {
922 UUID animID=UUID.Zero; 931 UUID animID=UUID.Zero;
923 lock (m_host.TaskInventory) 932 m_host.TaskInventory.LockItemsForRead(true);
933 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
924 { 934 {
925 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 935 if (inv.Value.Name == animation)
926 { 936 {
927 if (inv.Value.Name == animation) 937 if (inv.Value.Type == (int)AssetType.Animation)
928 { 938 animID = inv.Value.AssetID;
929 if (inv.Value.Type == (int)AssetType.Animation) 939 continue;
930 animID = inv.Value.AssetID;
931 continue;
932 }
933 } 940 }
934 } 941 }
942 m_host.TaskInventory.LockItemsForRead(false);
935 if (animID == UUID.Zero) 943 if (animID == UUID.Zero)
936 target.Animator.AddAnimation(animation, m_host.UUID); 944 target.Animator.AddAnimation(animation, m_host.UUID);
937 else 945 else
@@ -972,6 +980,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
972 else 980 else
973 animID = UUID.Zero; 981 animID = UUID.Zero;
974 } 982 }
983 m_host.TaskInventory.LockItemsForRead(false);
975 984
976 if (animID == UUID.Zero) 985 if (animID == UUID.Zero)
977 target.Animator.RemoveAnimation(animation); 986 target.Animator.RemoveAnimation(animation);
@@ -1792,6 +1801,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1792 1801
1793 if (!UUID.TryParse(notecardNameOrUuid, out assetID)) 1802 if (!UUID.TryParse(notecardNameOrUuid, out assetID))
1794 { 1803 {
1804 m_host.TaskInventory.LockItemsForRead(true);
1795 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1805 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1796 { 1806 {
1797 if (item.Type == 7 && item.Name == notecardNameOrUuid) 1807 if (item.Type == 7 && item.Name == notecardNameOrUuid)
@@ -1799,6 +1809,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1799 assetID = item.AssetID; 1809 assetID = item.AssetID;
1800 } 1810 }
1801 } 1811 }
1812 m_host.TaskInventory.LockItemsForRead(false);
1802 } 1813 }
1803 1814
1804 if (assetID == UUID.Zero) 1815 if (assetID == UUID.Zero)
@@ -2271,7 +2282,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2271 CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); 2282 CheckThreatLevel(ThreatLevel.High, "osNpcCreate");
2272 m_host.AddScriptLPS(1); 2283 m_host.AddScriptLPS(1);
2273 2284
2274 return NpcCreate(firstname, lastname, position, notecard, false, false); 2285 return NpcCreate(firstname, lastname, position, notecard, true, false);
2275 } 2286 }
2276 2287
2277 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options) 2288 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options)
@@ -2282,24 +2293,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2282 return NpcCreate( 2293 return NpcCreate(
2283 firstname, lastname, position, notecard, 2294 firstname, lastname, position, notecard,
2284 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0, 2295 (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0,
2285 (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) != 0); 2296 false);
2297// (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) != 0);
2286 } 2298 }
2287 2299
2288 private LSL_Key NpcCreate( 2300 private LSL_Key NpcCreate(
2289 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent) 2301 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent)
2290 { 2302 {
2303 if (!owned)
2304 OSSLError("Unowned NPCs are unsupported");
2305
2306 string groupTitle = String.Empty;
2307
2308 if (!World.Permissions.CanRezObject(1, m_host.OwnerID, new Vector3((float)position.x, (float)position.y, (float)position.z)))
2309 return new LSL_Key(UUID.Zero.ToString());
2310
2311 if (firstname != String.Empty || lastname != String.Empty)
2312 {
2313 if (firstname != "Shown outfit:")
2314 groupTitle = "- NPC -";
2315 }
2316
2291 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2317 INPCModule module = World.RequestModuleInterface<INPCModule>();
2292 if (module != null) 2318 if (module != null)
2293 { 2319 {
2294 AvatarAppearance appearance = null; 2320 AvatarAppearance appearance = null;
2295 2321
2296 UUID id; 2322// UUID id;
2297 if (UUID.TryParse(notecard, out id)) 2323// if (UUID.TryParse(notecard, out id))
2298 { 2324// {
2299 ScenePresence clonePresence = World.GetScenePresence(id); 2325// ScenePresence clonePresence = World.GetScenePresence(id);
2300 if (clonePresence != null) 2326// if (clonePresence != null)
2301 appearance = clonePresence.Appearance; 2327// appearance = clonePresence.Appearance;
2302 } 2328// }
2303 2329
2304 if (appearance == null) 2330 if (appearance == null)
2305 { 2331 {
@@ -2327,6 +2353,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2327 World, 2353 World,
2328 appearance); 2354 appearance);
2329 2355
2356 ScenePresence sp;
2357 if (World.TryGetScenePresence(x, out sp))
2358 {
2359 sp.Grouptitle = groupTitle;
2360 sp.SendAvatarDataToAllAgents();
2361 }
2330 return new LSL_Key(x.ToString()); 2362 return new LSL_Key(x.ToString());
2331 } 2363 }
2332 2364
@@ -2618,16 +2650,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2618 CheckThreatLevel(ThreatLevel.High, "osNpcRemove"); 2650 CheckThreatLevel(ThreatLevel.High, "osNpcRemove");
2619 m_host.AddScriptLPS(1); 2651 m_host.AddScriptLPS(1);
2620 2652
2621 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2653 ManualResetEvent ev = new ManualResetEvent(false);
2622 if (module != null)
2623 {
2624 UUID npcId = new UUID(npc.m_string);
2625 2654
2626 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2655 Util.FireAndForget(delegate(object x) {
2627 return; 2656 try
2657 {
2658 INPCModule module = World.RequestModuleInterface<INPCModule>();
2659 if (module != null)
2660 {
2661 UUID npcId = new UUID(npc.m_string);
2628 2662
2629 module.DeleteNPC(npcId, World); 2663 ILandObject l = World.LandChannel.GetLandObject(m_host.GroupPosition.X, m_host.GroupPosition.Y);
2630 } 2664 if (l == null || m_host.OwnerID != l.LandData.OwnerID)
2665 {
2666 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2667 return;
2668 }
2669
2670 module.DeleteNPC(npcId, World);
2671 }
2672 }
2673 finally
2674 {
2675 ev.Set();
2676 }
2677 });
2678 ev.WaitOne();
2631 } 2679 }
2632 2680
2633 public void osNpcPlayAnimation(LSL_Key npc, string animation) 2681 public void osNpcPlayAnimation(LSL_Key npc, string animation)
@@ -3161,4 +3209,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3161 ((LSL_Api)m_LSL_Api).DetachFromAvatar(); 3209 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3162 } 3210 }
3163 } 3211 }
3164} \ No newline at end of file 3212}
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 }