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.cs2980
-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, 2516 insertions, 745 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 0a25454..14dd2ad 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);
@@ -2785,16 +3050,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2785 new_group.RootPart.UUID.ToString()) }, 3050 new_group.RootPart.UUID.ToString()) },
2786 new DetectParams[0])); 3051 new DetectParams[0]));
2787 3052
2788 float groupmass = new_group.GetMass(); 3053 // do recoil
3054 SceneObjectGroup hostgrp = m_host.ParentGroup;
3055 if (hostgrp == null)
3056 return;
3057
3058 if (hostgrp.IsAttachment) // don't recoil avatars
3059 return;
2789 3060
2790 PhysicsActor pa = new_group.RootPart.PhysActor; 3061 PhysicsActor pa = new_group.RootPart.PhysActor;
2791 3062
2792 if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) 3063 if (pa != null && pa.IsPhysical && llvel != Vector3.Zero)
2793 { 3064 {
2794 //Recoil. 3065 float groupmass = new_group.GetMass();
2795 llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); 3066 llvel *= -groupmass;
3067 llApplyImpulse(new LSL_Vector(llvel.X, llvel.Y,llvel.Z), 0);
2796 } 3068 }
2797 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3069 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3070 return;
3071
2798 }); 3072 });
2799 3073
2800 //ScriptSleep((int)((groupmass * velmag) / 10)); 3074 //ScriptSleep((int)((groupmass * velmag) / 10));
@@ -2809,35 +3083,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2809 public void llLookAt(LSL_Vector target, double strength, double damping) 3083 public void llLookAt(LSL_Vector target, double strength, double damping)
2810 { 3084 {
2811 m_host.AddScriptLPS(1); 3085 m_host.AddScriptLPS(1);
2812 // Determine where we are looking from
2813 LSL_Vector from = llGetPos();
2814 3086
2815 // Work out the normalised vector from the source to the target 3087 // Get the normalized vector to the target
2816 LSL_Vector delta = llVecNorm(target - from); 3088 LSL_Vector d1 = llVecNorm(target - llGetPos());
2817 LSL_Vector angle = new LSL_Vector(0,0,0);
2818 3089
2819 // Calculate the yaw 3090 // Get the bearing (yaw)
2820 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3091 LSL_Vector a1 = new LSL_Vector(0,0,0);
2821 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3092 a1.z = llAtan2(d1.y, d1.x);
2822 3093
2823 // Calculate pitch 3094 // Get the elevation (pitch)
2824 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3095 LSL_Vector a2 = new LSL_Vector(0,0,0);
3096 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2825 3097
2826 // we need to convert from a vector describing 3098 LSL_Rotation r1 = llEuler2Rot(a1);
2827 // the angles of rotation in radians into rotation value 3099 LSL_Rotation r2 = llEuler2Rot(a2);
2828 LSL_Rotation rot = llEuler2Rot(angle); 3100 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2829
2830 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2831 // set the rotation of the object, copy that behavior
2832 PhysicsActor pa = m_host.PhysActor;
2833 3101
2834 if (strength == 0 || pa == null || !pa.IsPhysical) 3102 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2835 { 3103 {
2836 llSetRot(rot); 3104 // Do nothing if either value is 0 (this has been checked in SL)
3105 if (strength <= 0.0 || damping <= 0.0)
3106 return;
3107
3108 llSetRot(r3 * r2 * r1);
2837 } 3109 }
2838 else 3110 else
2839 { 3111 {
2840 m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); 3112 if (strength == 0)
3113 {
3114 llSetRot(r3 * r2 * r1);
3115 return;
3116 }
3117
3118 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
2841 } 3119 }
2842 } 3120 }
2843 3121
@@ -2883,17 +3161,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2883 } 3161 }
2884 else 3162 else
2885 { 3163 {
2886 if (m_host.IsRoot) 3164 // new SL always returns object mass
2887 { 3165// if (m_host.IsRoot)
3166// {
2888 return m_host.ParentGroup.GetMass(); 3167 return m_host.ParentGroup.GetMass();
2889 } 3168// }
2890 else 3169// else
2891 { 3170// {
2892 return m_host.GetMass(); 3171// return m_host.GetMass();
2893 } 3172// }
2894 } 3173 }
2895 } 3174 }
2896 3175
3176
3177 public LSL_Float llGetMassMKS()
3178 {
3179 return 100f * llGetMass();
3180 }
3181
2897 public void llCollisionFilter(string name, string id, int accept) 3182 public void llCollisionFilter(string name, string id, int accept)
2898 { 3183 {
2899 m_host.AddScriptLPS(1); 3184 m_host.AddScriptLPS(1);
@@ -2968,7 +3253,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2968 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3253 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
2969 3254
2970 if (attachmentsModule != null) 3255 if (attachmentsModule != null)
2971 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false); 3256 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true);
2972 else 3257 else
2973 return false; 3258 return false;
2974 } 3259 }
@@ -2998,9 +3283,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2998 { 3283 {
2999 m_host.AddScriptLPS(1); 3284 m_host.AddScriptLPS(1);
3000 3285
3001// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3002// return;
3003
3004 if (m_item.PermsGranter != m_host.OwnerID) 3286 if (m_item.PermsGranter != m_host.OwnerID)
3005 return; 3287 return;
3006 3288
@@ -3043,6 +3325,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3043 3325
3044 public void llInstantMessage(string user, string message) 3326 public void llInstantMessage(string user, string message)
3045 { 3327 {
3328 UUID result;
3329 if (!UUID.TryParse(user, out result))
3330 {
3331 ShoutError("An invalid key was passed to llInstantMessage");
3332 ScriptSleep(2000);
3333 return;
3334 }
3335
3336
3046 m_host.AddScriptLPS(1); 3337 m_host.AddScriptLPS(1);
3047 3338
3048 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3339 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3057,14 +3348,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3057 UUID friendTransactionID = UUID.Random(); 3348 UUID friendTransactionID = UUID.Random();
3058 3349
3059 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3350 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3060 3351
3061 GridInstantMessage msg = new GridInstantMessage(); 3352 GridInstantMessage msg = new GridInstantMessage();
3062 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3353 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3063 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3354 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3064 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3355 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3065// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3356// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3066// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3357// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3067 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3358// DateTime dt = DateTime.UtcNow;
3359//
3360// // Ticks from UtcNow, but make it look like local. Evil, huh?
3361// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3362//
3363// try
3364// {
3365// // Convert that to the PST timezone
3366// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3367// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3368// }
3369// catch
3370// {
3371// // No logging here, as it could be VERY spammy
3372// }
3373//
3374// // And make it look local again to fool the unix time util
3375// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3376
3377 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3378
3068 //if (client != null) 3379 //if (client != null)
3069 //{ 3380 //{
3070 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3381 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3078,12 +3389,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3078 msg.message = message.Substring(0, 1024); 3389 msg.message = message.Substring(0, 1024);
3079 else 3390 else
3080 msg.message = message; 3391 msg.message = message;
3081 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3392 msg.dialog = (byte)19; // MessageFromObject
3082 msg.fromGroup = false;// fromGroup; 3393 msg.fromGroup = false;// fromGroup;
3083 msg.offline = (byte)0; //offline; 3394 msg.offline = (byte)0; //offline;
3084 msg.ParentEstateID = 0; //ParentEstateID; 3395 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3085 msg.Position = new Vector3(m_host.AbsolutePosition); 3396 msg.Position = new Vector3(m_host.AbsolutePosition);
3086 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3397 msg.RegionID = World.RegionInfo.RegionID.Guid;
3087 msg.binaryBucket 3398 msg.binaryBucket
3088 = Util.StringToBytes256( 3399 = Util.StringToBytes256(
3089 "{0}/{1}/{2}/{3}", 3400 "{0}/{1}/{2}/{3}",
@@ -3111,7 +3422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3111 } 3422 }
3112 3423
3113 emailModule.SendEmail(m_host.UUID, address, subject, message); 3424 emailModule.SendEmail(m_host.UUID, address, subject, message);
3114 llSleep(EMAIL_PAUSE_TIME); 3425 ScriptSleep(EMAIL_PAUSE_TIME * 1000);
3115 } 3426 }
3116 3427
3117 public void llGetNextEmail(string address, string subject) 3428 public void llGetNextEmail(string address, string subject)
@@ -3355,15 +3666,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3355 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3666 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3356 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3667 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3357 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3668 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3669 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3358 ScriptBaseClass.PERMISSION_ATTACH; 3670 ScriptBaseClass.PERMISSION_ATTACH;
3359 3671
3360 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3672 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3361 { 3673 {
3362 lock (m_host.TaskInventory) 3674 m_host.TaskInventory.LockItemsForWrite(true);
3363 { 3675 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3364 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3676 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3365 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3677 m_host.TaskInventory.LockItemsForWrite(false);
3366 }
3367 3678
3368 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3679 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3369 "run_time_permissions", new Object[] { 3680 "run_time_permissions", new Object[] {
@@ -3373,28 +3684,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3373 return; 3684 return;
3374 } 3685 }
3375 } 3686 }
3376 else if (m_host.SitTargetAvatar == agentID) // Sitting avatar 3687 else
3377 { 3688 {
3378 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3689 bool sitting = false;
3379 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3690 if (m_host.SitTargetAvatar == agentID)
3380 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3691 {
3381 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3692 sitting = true;
3382 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3693 }
3694 else
3695 {
3696 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3697 {
3698 if (p.SitTargetAvatar == agentID)
3699 sitting = true;
3700 }
3701 }
3383 3702
3384 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3703 if (sitting)
3385 { 3704 {
3386 lock (m_host.TaskInventory) 3705 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3706 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3707 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3708 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3709 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3710
3711 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3387 { 3712 {
3713 m_host.TaskInventory.LockItemsForWrite(true);
3388 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3714 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3389 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3715 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3390 } 3716 m_host.TaskInventory.LockItemsForWrite(false);
3391 3717
3392 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3718 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3393 "run_time_permissions", new Object[] { 3719 "run_time_permissions", new Object[] {
3394 new LSL_Integer(perm) }, 3720 new LSL_Integer(perm) },
3395 new DetectParams[0])); 3721 new DetectParams[0]));
3396 3722
3397 return; 3723 return;
3724 }
3398 } 3725 }
3399 } 3726 }
3400 3727
@@ -3431,11 +3758,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3431 3758
3432 if (!m_waitingForScriptAnswer) 3759 if (!m_waitingForScriptAnswer)
3433 { 3760 {
3434 lock (m_host.TaskInventory) 3761 m_host.TaskInventory.LockItemsForWrite(true);
3435 { 3762 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3436 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3763 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3437 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 3764 m_host.TaskInventory.LockItemsForWrite(false);
3438 }
3439 3765
3440 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3766 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3441 m_waitingForScriptAnswer=true; 3767 m_waitingForScriptAnswer=true;
@@ -3464,14 +3790,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3464 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3790 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3465 llReleaseControls(); 3791 llReleaseControls();
3466 3792
3467 lock (m_host.TaskInventory) 3793 m_host.TaskInventory.LockItemsForWrite(true);
3468 { 3794 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3469 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 3795 m_host.TaskInventory.LockItemsForWrite(false);
3470 } 3796
3471 3797 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3472 m_ScriptEngine.PostScriptEvent( 3798 "run_time_permissions", new Object[] {
3473 m_item.ItemID, 3799 new LSL_Integer(answer) },
3474 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); 3800 new DetectParams[0]));
3475 } 3801 }
3476 3802
3477 public LSL_String llGetPermissionsKey() 3803 public LSL_String llGetPermissionsKey()
@@ -3510,14 +3836,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3510 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3836 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3511 { 3837 {
3512 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3838 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3513 3839 if (parts.Count > 0)
3514 foreach (SceneObjectPart part in parts) 3840 {
3515 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3841 try
3842 {
3843 parts[0].ParentGroup.areUpdatesSuspended = true;
3844 foreach (SceneObjectPart part in parts)
3845 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3846 }
3847 finally
3848 {
3849 parts[0].ParentGroup.areUpdatesSuspended = false;
3850 }
3851 }
3516 } 3852 }
3517 3853
3518 public void llCreateLink(string target, int parent) 3854 public void llCreateLink(string target, int parent)
3519 { 3855 {
3520 m_host.AddScriptLPS(1); 3856 m_host.AddScriptLPS(1);
3857
3521 UUID targetID; 3858 UUID targetID;
3522 3859
3523 if (!UUID.TryParse(target, out targetID)) 3860 if (!UUID.TryParse(target, out targetID))
@@ -3623,10 +3960,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3623 // Restructuring Multiple Prims. 3960 // Restructuring Multiple Prims.
3624 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 3961 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3625 parts.Remove(parentPrim.RootPart); 3962 parts.Remove(parentPrim.RootPart);
3626 foreach (SceneObjectPart part in parts) 3963 if (parts.Count > 0)
3627 { 3964 {
3628 parentPrim.DelinkFromGroup(part.LocalId, true); 3965 try
3966 {
3967 parts[0].ParentGroup.areUpdatesSuspended = true;
3968 foreach (SceneObjectPart part in parts)
3969 {
3970 parentPrim.DelinkFromGroup(part.LocalId, true);
3971 }
3972 }
3973 finally
3974 {
3975 parts[0].ParentGroup.areUpdatesSuspended = false;
3976 }
3629 } 3977 }
3978
3630 parentPrim.HasGroupChanged = true; 3979 parentPrim.HasGroupChanged = true;
3631 parentPrim.ScheduleGroupForFullUpdate(); 3980 parentPrim.ScheduleGroupForFullUpdate();
3632 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3981 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3635,12 +3984,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3635 { 3984 {
3636 SceneObjectPart newRoot = parts[0]; 3985 SceneObjectPart newRoot = parts[0];
3637 parts.Remove(newRoot); 3986 parts.Remove(newRoot);
3638 foreach (SceneObjectPart part in parts) 3987
3988 try
3639 { 3989 {
3640 // Required for linking 3990 parts[0].ParentGroup.areUpdatesSuspended = true;
3641 part.ClearUpdateSchedule(); 3991 foreach (SceneObjectPart part in parts)
3642 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 3992 {
3993 part.ClearUpdateSchedule();
3994 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3995 }
3643 } 3996 }
3997 finally
3998 {
3999 parts[0].ParentGroup.areUpdatesSuspended = false;
4000 }
4001
4002
3644 newRoot.ParentGroup.HasGroupChanged = true; 4003 newRoot.ParentGroup.HasGroupChanged = true;
3645 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4004 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3646 } 4005 }
@@ -3660,6 +4019,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3660 public void llBreakAllLinks() 4019 public void llBreakAllLinks()
3661 { 4020 {
3662 m_host.AddScriptLPS(1); 4021 m_host.AddScriptLPS(1);
4022
4023 TaskInventoryItem item = m_item;
4024
4025 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4026 && !m_automaticLinkPermission)
4027 {
4028 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4029 return;
4030 }
4031
3663 SceneObjectGroup parentPrim = m_host.ParentGroup; 4032 SceneObjectGroup parentPrim = m_host.ParentGroup;
3664 if (parentPrim.AttachmentPoint != 0) 4033 if (parentPrim.AttachmentPoint != 0)
3665 return; // Fail silently if attached 4034 return; // Fail silently if attached
@@ -3679,25 +4048,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3679 public LSL_String llGetLinkKey(int linknum) 4048 public LSL_String llGetLinkKey(int linknum)
3680 { 4049 {
3681 m_host.AddScriptLPS(1); 4050 m_host.AddScriptLPS(1);
3682 List<UUID> keytable = new List<UUID>();
3683 // parse for sitting avatare-uuids
3684 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3685 {
3686 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
3687 keytable.Add(presence.UUID);
3688 });
3689
3690 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3691 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3692 {
3693 return keytable[totalprims - linknum].ToString();
3694 }
3695
3696 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3697 {
3698 return m_host.UUID.ToString();
3699 }
3700
3701 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4051 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3702 if (part != null) 4052 if (part != null)
3703 { 4053 {
@@ -3705,6 +4055,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3705 } 4055 }
3706 else 4056 else
3707 { 4057 {
4058 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4059 {
4060 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4061
4062 if (linknum < 0)
4063 return UUID.Zero.ToString();
4064
4065 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4066 if (avatars.Count > linknum)
4067 {
4068 return avatars[linknum].UUID.ToString();
4069 }
4070 }
3708 return UUID.Zero.ToString(); 4071 return UUID.Zero.ToString();
3709 } 4072 }
3710 } 4073 }
@@ -3804,17 +4167,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3804 m_host.AddScriptLPS(1); 4167 m_host.AddScriptLPS(1);
3805 int count = 0; 4168 int count = 0;
3806 4169
3807 lock (m_host.TaskInventory) 4170 m_host.TaskInventory.LockItemsForRead(true);
4171 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3808 { 4172 {
3809 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4173 if (inv.Value.Type == type || type == -1)
3810 { 4174 {
3811 if (inv.Value.Type == type || type == -1) 4175 count = count + 1;
3812 {
3813 count = count + 1;
3814 }
3815 } 4176 }
3816 } 4177 }
3817 4178
4179 m_host.TaskInventory.LockItemsForRead(false);
3818 return count; 4180 return count;
3819 } 4181 }
3820 4182
@@ -3823,16 +4185,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3823 m_host.AddScriptLPS(1); 4185 m_host.AddScriptLPS(1);
3824 ArrayList keys = new ArrayList(); 4186 ArrayList keys = new ArrayList();
3825 4187
3826 lock (m_host.TaskInventory) 4188 m_host.TaskInventory.LockItemsForRead(true);
4189 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3827 { 4190 {
3828 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4191 if (inv.Value.Type == type || type == -1)
3829 { 4192 {
3830 if (inv.Value.Type == type || type == -1) 4193 keys.Add(inv.Value.Name);
3831 {
3832 keys.Add(inv.Value.Name);
3833 }
3834 } 4194 }
3835 } 4195 }
4196 m_host.TaskInventory.LockItemsForRead(false);
3836 4197
3837 if (keys.Count == 0) 4198 if (keys.Count == 0)
3838 { 4199 {
@@ -3870,7 +4231,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3870 if (item == null) 4231 if (item == null)
3871 { 4232 {
3872 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4233 llSay(0, String.Format("Could not find object '{0}'", inventory));
3873 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4234 return;
4235// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3874 } 4236 }
3875 4237
3876 UUID objId = item.ItemID; 4238 UUID objId = item.ItemID;
@@ -3898,34 +4260,45 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3898 return; 4260 return;
3899 } 4261 }
3900 } 4262 }
4263
3901 // destination is an avatar 4264 // destination is an avatar
3902 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4265 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3903 4266
3904 if (agentItem == null) 4267 if (agentItem == null)
3905 return; 4268 return;
3906 4269
3907 byte[] bucket = new byte[17]; 4270 byte[] bucket = new byte[1];
3908 bucket[0] = (byte)item.Type; 4271 bucket[0] = (byte)item.Type;
3909 byte[] objBytes = agentItem.ID.GetBytes(); 4272 //byte[] objBytes = agentItem.ID.GetBytes();
3910 Array.Copy(objBytes, 0, bucket, 1, 16); 4273 //Array.Copy(objBytes, 0, bucket, 1, 16);
3911 4274
3912 GridInstantMessage msg = new GridInstantMessage(World, 4275 GridInstantMessage msg = new GridInstantMessage(World,
3913 m_host.UUID, m_host.Name + ", an object owned by " + 4276 m_host.OwnerID, m_host.Name, destId,
3914 resolveName(m_host.OwnerID) + ",", destId,
3915 (byte)InstantMessageDialog.TaskInventoryOffered, 4277 (byte)InstantMessageDialog.TaskInventoryOffered,
3916 false, item.Name + "\n" + m_host.Name + " is located at " + 4278 false, item.Name+". "+m_host.Name+" is located at "+
3917 World.RegionInfo.RegionName+" "+ 4279 World.RegionInfo.RegionName+" "+
3918 m_host.AbsolutePosition.ToString(), 4280 m_host.AbsolutePosition.ToString(),
3919 agentItem.ID, true, m_host.AbsolutePosition, 4281 agentItem.ID, true, m_host.AbsolutePosition,
3920 bucket); 4282 bucket);
3921 4283
3922 if (m_TransferModule != null) 4284 ScenePresence sp;
3923 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
3924 4285
4286 if (World.TryGetScenePresence(destId, out sp))
4287 {
4288 sp.ControllingClient.SendInstantMessage(msg);
4289 }
4290 else
4291 {
4292 if (m_TransferModule != null)
4293 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4294 }
4295
4296 //This delay should only occur when giving inventory to avatars.
3925 ScriptSleep(3000); 4297 ScriptSleep(3000);
3926 } 4298 }
3927 } 4299 }
3928 4300
4301 [DebuggerNonUserCode]
3929 public void llRemoveInventory(string name) 4302 public void llRemoveInventory(string name)
3930 { 4303 {
3931 m_host.AddScriptLPS(1); 4304 m_host.AddScriptLPS(1);
@@ -3971,109 +4344,115 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3971 { 4344 {
3972 m_host.AddScriptLPS(1); 4345 m_host.AddScriptLPS(1);
3973 4346
3974 UUID uuid = (UUID)id; 4347 UUID uuid;
3975 PresenceInfo pinfo = null; 4348 if (UUID.TryParse(id, out uuid))
3976 UserAccount account;
3977
3978 UserInfoCacheEntry ce;
3979 if (!m_userInfoCache.TryGetValue(uuid, out ce))
3980 { 4349 {
3981 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4350 PresenceInfo pinfo = null;
3982 if (account == null) 4351 UserAccount account;
4352
4353 UserInfoCacheEntry ce;
4354 if (!m_userInfoCache.TryGetValue(uuid, out ce))
3983 { 4355 {
3984 m_userInfoCache[uuid] = null; // Cache negative 4356 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
3985 return UUID.Zero.ToString(); 4357 if (account == null)
3986 } 4358 {
4359 m_userInfoCache[uuid] = null; // Cache negative
4360 return UUID.Zero.ToString();
4361 }
3987 4362
3988 4363
3989 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4364 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
3990 if (pinfos != null && pinfos.Length > 0) 4365 if (pinfos != null && pinfos.Length > 0)
3991 {
3992 foreach (PresenceInfo p in pinfos)
3993 { 4366 {
3994 if (p.RegionID != UUID.Zero) 4367 foreach (PresenceInfo p in pinfos)
3995 { 4368 {
3996 pinfo = p; 4369 if (p.RegionID != UUID.Zero)
4370 {
4371 pinfo = p;
4372 }
3997 } 4373 }
3998 } 4374 }
3999 }
4000 4375
4001 ce = new UserInfoCacheEntry(); 4376 ce = new UserInfoCacheEntry();
4002 ce.time = Util.EnvironmentTickCount(); 4377 ce.time = Util.EnvironmentTickCount();
4003 ce.account = account; 4378 ce.account = account;
4004 ce.pinfo = pinfo; 4379 ce.pinfo = pinfo;
4005 } 4380 m_userInfoCache[uuid] = ce;
4006 else 4381 }
4007 { 4382 else
4008 if (ce == null) 4383 {
4009 return UUID.Zero.ToString(); 4384 if (ce == null)
4385 return UUID.Zero.ToString();
4010 4386
4011 account = ce.account; 4387 account = ce.account;
4012 pinfo = ce.pinfo; 4388 pinfo = ce.pinfo;
4013 } 4389 }
4014 4390
4015 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4391 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4016 {
4017 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4018 if (pinfos != null && pinfos.Length > 0)
4019 { 4392 {
4020 foreach (PresenceInfo p in pinfos) 4393 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4394 if (pinfos != null && pinfos.Length > 0)
4021 { 4395 {
4022 if (p.RegionID != UUID.Zero) 4396 foreach (PresenceInfo p in pinfos)
4023 { 4397 {
4024 pinfo = p; 4398 if (p.RegionID != UUID.Zero)
4399 {
4400 pinfo = p;
4401 }
4025 } 4402 }
4026 } 4403 }
4027 } 4404 else
4028 else 4405 pinfo = null;
4029 pinfo = null;
4030 4406
4031 ce.time = Util.EnvironmentTickCount(); 4407 ce.time = Util.EnvironmentTickCount();
4032 ce.pinfo = pinfo; 4408 ce.pinfo = pinfo;
4033 } 4409 }
4034 4410
4035 string reply = String.Empty; 4411 string reply = String.Empty;
4036 4412
4037 switch (data) 4413 switch (data)
4038 { 4414 {
4039 case 1: // DATA_ONLINE (0|1) 4415 case 1: // DATA_ONLINE (0|1)
4040 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4416 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4041 reply = "1"; 4417 reply = "1";
4042 else 4418 else
4043 reply = "0"; 4419 reply = "0";
4044 break; 4420 break;
4045 case 2: // DATA_NAME (First Last) 4421 case 2: // DATA_NAME (First Last)
4046 reply = account.FirstName + " " + account.LastName; 4422 reply = account.FirstName + " " + account.LastName;
4047 break; 4423 break;
4048 case 3: // DATA_BORN (YYYY-MM-DD) 4424 case 3: // DATA_BORN (YYYY-MM-DD)
4049 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4425 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4050 born = born.AddSeconds(account.Created); 4426 born = born.AddSeconds(account.Created);
4051 reply = born.ToString("yyyy-MM-dd"); 4427 reply = born.ToString("yyyy-MM-dd");
4052 break; 4428 break;
4053 case 4: // DATA_RATING (0,0,0,0,0,0) 4429 case 4: // DATA_RATING (0,0,0,0,0,0)
4054 reply = "0,0,0,0,0,0"; 4430 reply = "0,0,0,0,0,0";
4055 break; 4431 break;
4056 case 7: // DATA_USERLEVEL (integer) 4432 case 8: // DATA_PAYINFO (0|1|2|3)
4057 reply = account.UserLevel.ToString(); 4433 reply = "0";
4058 break; 4434 break;
4059 case 8: // DATA_PAYINFO (0|1|2|3) 4435 default:
4060 reply = "0"; 4436 return UUID.Zero.ToString(); // Raise no event
4061 break; 4437 }
4062 default:
4063 return UUID.Zero.ToString(); // Raise no event
4064 }
4065 4438
4066 UUID rq = UUID.Random(); 4439 UUID rq = UUID.Random();
4067 4440
4068 UUID tid = AsyncCommands. 4441 UUID tid = AsyncCommands.
4069 DataserverPlugin.RegisterRequest(m_host.LocalId, 4442 DataserverPlugin.RegisterRequest(m_host.LocalId,
4070 m_item.ItemID, rq.ToString()); 4443 m_item.ItemID, rq.ToString());
4071 4444
4072 AsyncCommands. 4445 AsyncCommands.
4073 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4446 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4074 4447
4075 ScriptSleep(100); 4448 ScriptSleep(100);
4076 return tid.ToString(); 4449 return tid.ToString();
4450 }
4451 else
4452 {
4453 ShoutError("Invalid UUID passed to llRequestAgentData.");
4454 }
4455 return "";
4077 } 4456 }
4078 4457
4079 public LSL_String llRequestInventoryData(string name) 4458 public LSL_String llRequestInventoryData(string name)
@@ -4130,13 +4509,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4130 if (UUID.TryParse(agent, out agentId)) 4509 if (UUID.TryParse(agent, out agentId))
4131 { 4510 {
4132 ScenePresence presence = World.GetScenePresence(agentId); 4511 ScenePresence presence = World.GetScenePresence(agentId);
4133 if (presence != null) 4512 if (presence != null && presence.PresenceType != PresenceType.Npc)
4134 { 4513 {
4514 // agent must not be a god
4515 if (presence.UserLevel >= 200) return;
4516
4135 // agent must be over the owners land 4517 // agent must be over the owners land
4136 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4518 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4137 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4519 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4138 { 4520 {
4139 World.TeleportClientHome(agentId, presence.ControllingClient); 4521 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4522 {
4523 // They can't be teleported home for some reason
4524 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4525 if (regionInfo != null)
4526 {
4527 World.RequestTeleportLocation(
4528 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4529 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4530 }
4531 }
4140 } 4532 }
4141 } 4533 }
4142 } 4534 }
@@ -4248,7 +4640,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4248 UUID av = new UUID(); 4640 UUID av = new UUID();
4249 if (!UUID.TryParse(agent,out av)) 4641 if (!UUID.TryParse(agent,out av))
4250 { 4642 {
4251 LSLError("First parameter to llDialog needs to be a key"); 4643 //LSLError("First parameter to llDialog needs to be a key");
4252 return; 4644 return;
4253 } 4645 }
4254 4646
@@ -4280,7 +4672,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4280 public void llCollisionSound(string impact_sound, double impact_volume) 4672 public void llCollisionSound(string impact_sound, double impact_volume)
4281 { 4673 {
4282 m_host.AddScriptLPS(1); 4674 m_host.AddScriptLPS(1);
4283 4675
4676 if(impact_sound == "")
4677 {
4678 m_host.CollisionSoundVolume = (float)impact_volume;
4679 m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
4680 m_host.CollisionSoundType = 0;
4681 return;
4682 }
4284 // TODO: Parameter check logic required. 4683 // TODO: Parameter check logic required.
4285 UUID soundId = UUID.Zero; 4684 UUID soundId = UUID.Zero;
4286 if (!UUID.TryParse(impact_sound, out soundId)) 4685 if (!UUID.TryParse(impact_sound, out soundId))
@@ -4293,6 +4692,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4293 4692
4294 m_host.CollisionSound = soundId; 4693 m_host.CollisionSound = soundId;
4295 m_host.CollisionSoundVolume = (float)impact_volume; 4694 m_host.CollisionSoundVolume = (float)impact_volume;
4695 m_host.CollisionSoundType = 1;
4296 } 4696 }
4297 4697
4298 public LSL_String llGetAnimation(string id) 4698 public LSL_String llGetAnimation(string id)
@@ -4306,14 +4706,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4306 4706
4307 if (m_host.RegionHandle == presence.RegionHandle) 4707 if (m_host.RegionHandle == presence.RegionHandle)
4308 { 4708 {
4309 Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames;
4310
4311 if (presence != null) 4709 if (presence != null)
4312 { 4710 {
4313 AnimationSet currentAnims = presence.Animator.Animations; 4711 if (presence.SitGround)
4314 string currentAnimationState = String.Empty; 4712 return "Sitting on Ground";
4315 if (animationstateNames.TryGetValue(currentAnims.DefaultAnimation.AnimID, out currentAnimationState)) 4713 if (presence.ParentID != 0 || presence.ParentUUID != UUID.Zero)
4316 return currentAnimationState; 4714 return "Sitting";
4715
4716 string movementAnimation = presence.Animator.CurrentMovementAnimation;
4717 string lslMovementAnimation;
4718
4719 if (MovementAnimationsForLSL.TryGetValue(movementAnimation, out lslMovementAnimation))
4720 return lslMovementAnimation;
4317 } 4721 }
4318 } 4722 }
4319 4723
@@ -4460,7 +4864,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4460 { 4864 {
4461 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4865 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4462 float distance_term = distance * distance * distance; // Script Energy 4866 float distance_term = distance * distance * distance; // Script Energy
4463 float pusher_mass = m_host.GetMass(); 4867 // use total object mass and not part
4868 float pusher_mass = m_host.ParentGroup.GetMass();
4464 4869
4465 float PUSH_ATTENUATION_DISTANCE = 17f; 4870 float PUSH_ATTENUATION_DISTANCE = 17f;
4466 float PUSH_ATTENUATION_SCALE = 5f; 4871 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4710,6 +5115,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4710 { 5115 {
4711 return item.AssetID.ToString(); 5116 return item.AssetID.ToString();
4712 } 5117 }
5118 m_host.TaskInventory.LockItemsForRead(false);
4713 5119
4714 return UUID.Zero.ToString(); 5120 return UUID.Zero.ToString();
4715 } 5121 }
@@ -4843,7 +5249,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4843 public LSL_Vector llGetCenterOfMass() 5249 public LSL_Vector llGetCenterOfMass()
4844 { 5250 {
4845 m_host.AddScriptLPS(1); 5251 m_host.AddScriptLPS(1);
4846 Vector3 center = m_host.GetGeometricCenter(); 5252 Vector3 center = m_host.GetCenterOfMass();
4847 return new LSL_Vector(center.X,center.Y,center.Z); 5253 return new LSL_Vector(center.X,center.Y,center.Z);
4848 } 5254 }
4849 5255
@@ -4862,14 +5268,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4862 { 5268 {
4863 m_host.AddScriptLPS(1); 5269 m_host.AddScriptLPS(1);
4864 5270
4865 if (src == null) 5271 return src.Length;
4866 {
4867 return 0;
4868 }
4869 else
4870 {
4871 return src.Length;
4872 }
4873 } 5272 }
4874 5273
4875 public LSL_Integer llList2Integer(LSL_List src, int index) 5274 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4915,7 +5314,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4915 else if (src.Data[index] is LSL_Float) 5314 else if (src.Data[index] is LSL_Float)
4916 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5315 return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
4917 else if (src.Data[index] is LSL_String) 5316 else if (src.Data[index] is LSL_String)
4918 return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); 5317 {
5318 string str = ((LSL_String) src.Data[index]).m_string;
5319 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5320 if (m != Match.Empty)
5321 {
5322 str = m.Value;
5323 double d = 0.0;
5324 if (!Double.TryParse(str, out d))
5325 return 0.0;
5326
5327 return d;
5328 }
5329 return 0.0;
5330 }
4919 return Convert.ToDouble(src.Data[index]); 5331 return Convert.ToDouble(src.Data[index]);
4920 } 5332 }
4921 catch (FormatException) 5333 catch (FormatException)
@@ -5188,7 +5600,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5188 } 5600 }
5189 } 5601 }
5190 } 5602 }
5191 else { 5603 else
5604 {
5192 object[] array = new object[src.Length]; 5605 object[] array = new object[src.Length];
5193 Array.Copy(src.Data, 0, array, 0, src.Length); 5606 Array.Copy(src.Data, 0, array, 0, src.Length);
5194 result = new LSL_List(array); 5607 result = new LSL_List(array);
@@ -5295,7 +5708,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5295 public LSL_Integer llGetRegionAgentCount() 5708 public LSL_Integer llGetRegionAgentCount()
5296 { 5709 {
5297 m_host.AddScriptLPS(1); 5710 m_host.AddScriptLPS(1);
5298 return new LSL_Integer(World.GetRootAgentCount()); 5711
5712 int count = 0;
5713 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5714 count++;
5715 });
5716
5717 return new LSL_Integer(count);
5299 } 5718 }
5300 5719
5301 public LSL_Vector llGetRegionCorner() 5720 public LSL_Vector llGetRegionCorner()
@@ -5575,6 +5994,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5575 flags |= ScriptBaseClass.AGENT_SITTING; 5994 flags |= ScriptBaseClass.AGENT_SITTING;
5576 } 5995 }
5577 5996
5997 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
5998 {
5999 flags |= ScriptBaseClass.AGENT_MALE;
6000 }
6001
5578 return flags; 6002 return flags;
5579 } 6003 }
5580 6004
@@ -5721,10 +6145,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5721 m_host.AddScriptLPS(1); 6145 m_host.AddScriptLPS(1);
5722 6146
5723 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6147 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5724 6148 if (parts.Count > 0)
5725 foreach (var part in parts)
5726 { 6149 {
5727 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6150 try
6151 {
6152 parts[0].ParentGroup.areUpdatesSuspended = true;
6153 foreach (var part in parts)
6154 {
6155 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6156 }
6157 }
6158 finally
6159 {
6160 parts[0].ParentGroup.areUpdatesSuspended = false;
6161 }
5728 } 6162 }
5729 } 6163 }
5730 6164
@@ -5776,13 +6210,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5776 6210
5777 if (m_host.OwnerID == land.LandData.OwnerID) 6211 if (m_host.OwnerID == land.LandData.OwnerID)
5778 { 6212 {
5779 World.TeleportClientHome(agentID, presence.ControllingClient); 6213 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6214 presence.TeleportWithMomentum(pos, null);
6215 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5780 } 6216 }
5781 } 6217 }
5782 } 6218 }
5783 ScriptSleep(5000); 6219 ScriptSleep(5000);
5784 } 6220 }
5785 6221
6222 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6223 {
6224 return ParseString2List(str, separators, in_spacers, false);
6225 }
6226
5786 public LSL_Integer llOverMyLand(string id) 6227 public LSL_Integer llOverMyLand(string id)
5787 { 6228 {
5788 m_host.AddScriptLPS(1); 6229 m_host.AddScriptLPS(1);
@@ -5847,8 +6288,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5847 UUID agentId = new UUID(); 6288 UUID agentId = new UUID();
5848 if (!UUID.TryParse(agent, out agentId)) 6289 if (!UUID.TryParse(agent, out agentId))
5849 return new LSL_Integer(0); 6290 return new LSL_Integer(0);
6291 if (agentId == m_host.GroupID)
6292 return new LSL_Integer(1);
5850 ScenePresence presence = World.GetScenePresence(agentId); 6293 ScenePresence presence = World.GetScenePresence(agentId);
5851 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6294 if (presence == null || presence.IsChildAgent) // Return false for child agents
5852 return new LSL_Integer(0); 6295 return new LSL_Integer(0);
5853 IClientAPI client = presence.ControllingClient; 6296 IClientAPI client = presence.ControllingClient;
5854 if (m_host.GroupID == client.ActiveGroupId) 6297 if (m_host.GroupID == client.ActiveGroupId)
@@ -5983,7 +6426,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5983 return m_host.ParentGroup.AttachmentPoint; 6426 return m_host.ParentGroup.AttachmentPoint;
5984 } 6427 }
5985 6428
5986 public LSL_Integer llGetFreeMemory() 6429 public virtual LSL_Integer llGetFreeMemory()
5987 { 6430 {
5988 m_host.AddScriptLPS(1); 6431 m_host.AddScriptLPS(1);
5989 // Make scripts designed for LSO happy 6432 // Make scripts designed for LSO happy
@@ -6100,7 +6543,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6100 SetParticleSystem(m_host, rules); 6543 SetParticleSystem(m_host, rules);
6101 } 6544 }
6102 6545
6103 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6546 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6547 {
6104 6548
6105 6549
6106 if (rules.Length == 0) 6550 if (rules.Length == 0)
@@ -6328,17 +6772,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6328 if (folderID == UUID.Zero) 6772 if (folderID == UUID.Zero)
6329 return; 6773 return;
6330 6774
6331 byte[] bucket = new byte[17]; 6775 byte[] bucket = new byte[1];
6332 bucket[0] = (byte)AssetType.Folder; 6776 bucket[0] = (byte)AssetType.Folder;
6333 byte[] objBytes = folderID.GetBytes(); 6777 //byte[] objBytes = folderID.GetBytes();
6334 Array.Copy(objBytes, 0, bucket, 1, 16); 6778 //Array.Copy(objBytes, 0, bucket, 1, 16);
6335 6779
6336 GridInstantMessage msg = new GridInstantMessage(World, 6780 GridInstantMessage msg = new GridInstantMessage(World,
6337 m_host.UUID, m_host.Name + ", an object owned by " + 6781 m_host.OwnerID, m_host.Name, destID,
6338 resolveName(m_host.OwnerID) + ",", destID, 6782 (byte)InstantMessageDialog.TaskInventoryOffered,
6339 (byte)InstantMessageDialog.InventoryOffered, 6783 false, category+". "+m_host.Name+" is located at "+
6340 false, category + "\n" + m_host.Name + " is located at " + 6784 World.RegionInfo.RegionName+" "+
6341 World.RegionInfo.RegionName + " " +
6342 m_host.AbsolutePosition.ToString(), 6785 m_host.AbsolutePosition.ToString(),
6343 folderID, true, m_host.AbsolutePosition, 6786 folderID, true, m_host.AbsolutePosition,
6344 bucket); 6787 bucket);
@@ -6418,7 +6861,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6418 { 6861 {
6419 // LSL quaternions can normalize to 0, normal Quaternions can't. 6862 // LSL quaternions can normalize to 0, normal Quaternions can't.
6420 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) 6863 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
6421 rot.z = 1; // ZERO_ROTATION = 0,0,0,1 6864 rot.s = 1; // ZERO_ROTATION = 0,0,0,1
6422 6865
6423 part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); 6866 part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z);
6424 part.SitTargetOrientation = Rot2Quaternion(rot); 6867 part.SitTargetOrientation = Rot2Quaternion(rot);
@@ -6575,13 +7018,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6575 UUID av = new UUID(); 7018 UUID av = new UUID();
6576 if (!UUID.TryParse(avatar,out av)) 7019 if (!UUID.TryParse(avatar,out av))
6577 { 7020 {
6578 LSLError("First parameter to llDialog needs to be a key"); 7021 //LSLError("First parameter to llDialog needs to be a key");
6579 return; 7022 return;
6580 } 7023 }
6581 if (buttons.Length < 1) 7024 if (buttons.Length < 1)
6582 { 7025 {
6583 LSLError("No less than 1 button can be shown"); 7026 buttons.Add("OK");
6584 return;
6585 } 7027 }
6586 if (buttons.Length > 12) 7028 if (buttons.Length > 12)
6587 { 7029 {
@@ -6598,7 +7040,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6598 } 7040 }
6599 if (buttons.Data[i].ToString().Length > 24) 7041 if (buttons.Data[i].ToString().Length > 24)
6600 { 7042 {
6601 LSLError("button label cannot be longer than 24 characters"); 7043 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6602 return; 7044 return;
6603 } 7045 }
6604 buts[i] = buttons.Data[i].ToString(); 7046 buts[i] = buttons.Data[i].ToString();
@@ -6665,9 +7107,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6665 return; 7107 return;
6666 } 7108 }
6667 7109
6668 // the rest of the permission checks are done in RezScript, so check the pin there as well 7110 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6669 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); 7111 if (dest != null)
7112 {
7113 if ((item.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7114 {
7115 // the rest of the permission checks are done in RezScript, so check the pin there as well
7116 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
6670 7117
7118 if ((item.BasePermissions & (uint)PermissionMask.Copy) == 0)
7119 m_host.Inventory.RemoveInventoryItem(item.ItemID);
7120 }
7121 }
6671 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7122 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6672 ScriptSleep(3000); 7123 ScriptSleep(3000);
6673 } 7124 }
@@ -6730,19 +7181,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6730 public LSL_String llMD5String(string src, int nonce) 7181 public LSL_String llMD5String(string src, int nonce)
6731 { 7182 {
6732 m_host.AddScriptLPS(1); 7183 m_host.AddScriptLPS(1);
6733 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7184 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6734 } 7185 }
6735 7186
6736 public LSL_String llSHA1String(string src) 7187 public LSL_String llSHA1String(string src)
6737 { 7188 {
6738 m_host.AddScriptLPS(1); 7189 m_host.AddScriptLPS(1);
6739 return Util.SHA1Hash(src).ToLower(); 7190 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6740 } 7191 }
6741 7192
6742 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7193 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6743 { 7194 {
6744 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7195 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6745 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7196 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7197 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7198 return shapeBlock;
6746 7199
6747 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7200 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6748 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7201 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6847,6 +7300,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6847 // Prim type box, cylinder and prism. 7300 // Prim type box, cylinder and prism.
6848 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) 7301 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)
6849 { 7302 {
7303 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7304 return;
7305
6850 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7306 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6851 ObjectShapePacket.ObjectDataBlock shapeBlock; 7307 ObjectShapePacket.ObjectDataBlock shapeBlock;
6852 7308
@@ -6900,6 +7356,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6900 // Prim type sphere. 7356 // Prim type sphere.
6901 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7357 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6902 { 7358 {
7359 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7360 return;
7361
6903 ObjectShapePacket.ObjectDataBlock shapeBlock; 7362 ObjectShapePacket.ObjectDataBlock shapeBlock;
6904 7363
6905 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7364 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6941,6 +7400,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6941 // Prim type torus, tube and ring. 7400 // Prim type torus, tube and ring.
6942 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) 7401 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)
6943 { 7402 {
7403 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7404 return;
7405
6944 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7406 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6945 ObjectShapePacket.ObjectDataBlock shapeBlock; 7407 ObjectShapePacket.ObjectDataBlock shapeBlock;
6946 7408
@@ -7076,6 +7538,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7076 // Prim type sculpt. 7538 // Prim type sculpt.
7077 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7539 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7078 { 7540 {
7541 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7542 return;
7543
7079 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7544 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7080 UUID sculptId; 7545 UUID sculptId;
7081 7546
@@ -7100,7 +7565,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7100 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7565 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7101 { 7566 {
7102 // default 7567 // default
7103 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7568 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7104 } 7569 }
7105 7570
7106 part.Shape.SetSculptProperties((byte)type, sculptId); 7571 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7116,34 +7581,311 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7116 ScriptSleep(200); 7581 ScriptSleep(200);
7117 } 7582 }
7118 7583
7119 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7584 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7120 { 7585 {
7121 m_host.AddScriptLPS(1); 7586 m_host.AddScriptLPS(1);
7122 7587
7123 setLinkPrimParams(linknumber, rules); 7588 setLinkPrimParams(linknumber, rules);
7589 }
7590
7591 private void setLinkPrimParams(int linknumber, LSL_List rules)
7592 {
7593 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7594 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7595 if (parts.Count>0)
7596 {
7597 try
7598 {
7599 parts[0].ParentGroup.areUpdatesSuspended = true;
7600 foreach (SceneObjectPart part in parts)
7601 SetPrimParams(part, rules);
7602 }
7603 finally
7604 {
7605 parts[0].ParentGroup.areUpdatesSuspended = false;
7606 }
7607 }
7608 if (avatars.Count > 0)
7609 {
7610 foreach (ScenePresence avatar in avatars)
7611 SetPrimParams(avatar, rules);
7612 }
7613 }
7614
7615 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7616 float material_density, float material_friction,
7617 float material_restitution, float material_gravity_modifier)
7618 {
7619 ExtraPhysicsData physdata = new ExtraPhysicsData();
7620 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7621 physdata.Density = part.Density;
7622 physdata.Friction = part.Friction;
7623 physdata.Bounce = part.Bounciness;
7624 physdata.GravitationModifier = part.GravityModifier;
7124 7625
7626 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7627 physdata.Density = material_density;
7628 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7629 physdata.Friction = material_friction;
7630 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7631 physdata.Bounce = material_restitution;
7632 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7633 physdata.GravitationModifier = material_gravity_modifier;
7634
7635 part.UpdateExtraPhysics(physdata);
7636 }
7637
7638 public void llSetPhysicsMaterial(int material_bits,
7639 float material_gravity_modifier, float material_restitution,
7640 float material_friction, float material_density)
7641 {
7642 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7643 }
7644
7645 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7646 {
7647 llSetLinkPrimitiveParamsFast(linknumber, rules);
7125 ScriptSleep(200); 7648 ScriptSleep(200);
7126 } 7649 }
7127 7650
7128 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7651 // vector up using libomv (c&p from sop )
7652 // vector up rotated by r
7653 private Vector3 Zrot(Quaternion r)
7129 { 7654 {
7130 m_host.AddScriptLPS(1); 7655 double x, y, z, m;
7131 7656
7132 setLinkPrimParams(linknumber, rules); 7657 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
7658 if (Math.Abs(1.0 - m) > 0.000001)
7659 {
7660 m = 1.0 / Math.Sqrt(m);
7661 r.X *= (float)m;
7662 r.Y *= (float)m;
7663 r.Z *= (float)m;
7664 r.W *= (float)m;
7665 }
7666
7667 x = 2 * (r.X * r.Z + r.Y * r.W);
7668 y = 2 * (-r.X * r.W + r.Y * r.Z);
7669 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
7670
7671 return new Vector3((float)x, (float)y, (float)z);
7133 } 7672 }
7134 7673
7135 protected void setLinkPrimParams(int linknumber, LSL_List rules) 7674 protected void SetPrimParams(ScenePresence av, LSL_List rules)
7136 { 7675 {
7137 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7676 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7138 7677
7139 foreach (SceneObjectPart part in parts) 7678 int idx = 0;
7140 SetPrimParams(part, rules); 7679 SceneObjectPart sitpart = World.GetSceneObjectPart(av.ParentID); // betting this will be used
7680
7681 bool positionChanged = false;
7682 Vector3 finalPos = Vector3.Zero;
7683
7684 try
7685 {
7686 while (idx < rules.Length)
7687 {
7688 int code = rules.GetLSLIntegerItem(idx++);
7689
7690 int remain = rules.Length - idx;
7691
7692 switch (code)
7693 {
7694 // a avatar is a child
7695 case (int)ScriptBaseClass.PRIM_POSITION:
7696 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
7697 {
7698 if (remain < 1)
7699 return;
7700 LSL_Vector v;
7701 v = rules.GetVector3Item(idx++);
7702
7703 if (sitpart == null)
7704 break;
7705
7706 Vector3 pos = new Vector3((float)v.x, (float)v.y, (float)v.z); // requested absolute position
7707
7708 if (sitpart != sitpart.ParentGroup.RootPart)
7709 {
7710 pos -= sitpart.OffsetPosition; // remove sit part offset
7711 Quaternion rot = sitpart.RotationOffset;
7712 pos *= Quaternion.Conjugate(rot); // removed sit part rotation
7713 }
7714 Vector3 sitOffset = (Zrot(av.Rotation)) * (av.Appearance.AvatarHeight * 0.02638f * 2.0f);
7715 pos += sitOffset;
7716
7717 finalPos = pos;
7718 positionChanged = true;
7719 }
7720 break;
7721
7722 case (int)ScriptBaseClass.PRIM_ROTATION:
7723 {
7724 if (remain < 1)
7725 return;
7726
7727 if (sitpart == null)
7728 break;
7729
7730 LSL_Rotation r = rules.GetQuaternionItem(idx++);
7731 Quaternion rot = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); // requested world rotation
7732
7733// need to replicate SL bug
7734 SceneObjectGroup sitgrp = sitpart.ParentGroup;
7735 if (sitgrp != null && sitgrp.RootPart != sitpart)
7736 {
7737 rot = sitgrp.RootPart.RotationOffset * rot;
7738 }
7739
7740 Quaternion srot = sitpart.RotationOffset;
7741 rot = Quaternion.Conjugate(srot) * rot; // removed sit part offset rotation
7742 av.Rotation = rot;
7743 av.SendAvatarDataToAllAgents();
7744 }
7745 break;
7746
7747 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
7748 {
7749 if (remain < 1)
7750 return;
7751
7752 if (sitpart == null)
7753 break;
7754
7755 LSL_Rotation r = rules.GetQuaternionItem(idx++);
7756 Quaternion rot = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); // requested offset rotation
7757 if (sitpart != sitpart.ParentGroup.RootPart)
7758 {
7759 Quaternion srot = sitpart.RotationOffset;
7760 rot = Quaternion.Conjugate(srot) * rot; // remove sit part offset rotation
7761 }
7762 av.Rotation = rot;
7763 av.SendAvatarDataToAllAgents();
7764 }
7765 break;
7766
7767 // parse rest doing nothing but number of parameters error check
7768 case (int)ScriptBaseClass.PRIM_SIZE:
7769 case (int)ScriptBaseClass.PRIM_MATERIAL:
7770 case (int)ScriptBaseClass.PRIM_PHANTOM:
7771 case (int)ScriptBaseClass.PRIM_PHYSICS:
7772 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
7773 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7774 case (int)ScriptBaseClass.PRIM_NAME:
7775 case (int)ScriptBaseClass.PRIM_DESC:
7776 if (remain < 1)
7777 return;
7778 idx++;
7779 break;
7780
7781 case (int)ScriptBaseClass.PRIM_GLOW:
7782 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
7783 case (int)ScriptBaseClass.PRIM_TEXGEN:
7784 if (remain < 2)
7785 return;
7786 idx += 2;
7787 break;
7788
7789 case (int)ScriptBaseClass.PRIM_TYPE:
7790 if (remain < 3)
7791 return;
7792 code = (int)rules.GetLSLIntegerItem(idx++);
7793 remain = rules.Length - idx;
7794 switch (code)
7795 {
7796 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
7797 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
7798 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
7799 if (remain < 6)
7800 return;
7801 idx += 6;
7802 break;
7803
7804 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
7805 if (remain < 5)
7806 return;
7807 idx += 5;
7808 break;
7809
7810 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
7811 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
7812 case (int)ScriptBaseClass.PRIM_TYPE_RING:
7813 if (remain < 11)
7814 return;
7815 idx += 11;
7816 break;
7817
7818 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
7819 if (remain < 2)
7820 return;
7821 idx += 2;
7822 break;
7823 }
7824 break;
7825
7826 case (int)ScriptBaseClass.PRIM_COLOR:
7827 case (int)ScriptBaseClass.PRIM_TEXT:
7828 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7829 case (int)ScriptBaseClass.PRIM_OMEGA:
7830 if (remain < 3)
7831 return;
7832 idx += 3;
7833 break;
7834
7835 case (int)ScriptBaseClass.PRIM_TEXTURE:
7836 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
7837 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
7838 if (remain < 5)
7839 return;
7840 idx += 5;
7841 break;
7842
7843 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
7844 if (remain < 7)
7845 return;
7846
7847 idx += 7;
7848 break;
7849
7850 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
7851 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
7852 return;
7853
7854 if (positionChanged)
7855 {
7856 positionChanged = false;
7857 av.OffsetPosition = finalPos;
7858 av.SendAvatarDataToAllAgents();
7859 }
7860
7861 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
7862 LSL_List new_rules = rules.GetSublist(idx, -1);
7863 setLinkPrimParams((int)new_linknumber, new_rules);
7864 return;
7865 }
7866 }
7867 }
7868
7869 finally
7870 {
7871 if (positionChanged)
7872 {
7873 av.OffsetPosition = finalPos;
7874 av.SendAvatarDataToAllAgents();
7875 positionChanged = false;
7876 }
7877 }
7141 } 7878 }
7142 7879
7143 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 7880 protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
7144 { 7881 {
7882 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7883 return;
7884
7145 int idx = 0; 7885 int idx = 0;
7146 7886
7887 SceneObjectGroup parentgrp = part.ParentGroup;
7888
7147 bool positionChanged = false; 7889 bool positionChanged = false;
7148 LSL_Vector currentPosition = GetPartLocalPos(part); 7890 LSL_Vector currentPosition = GetPartLocalPos(part);
7149 7891
@@ -7166,8 +7908,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7166 return; 7908 return;
7167 7909
7168 v=rules.GetVector3Item(idx++); 7910 v=rules.GetVector3Item(idx++);
7169 positionChanged = true;
7170 currentPosition = GetSetPosTarget(part, v, currentPosition); 7911 currentPosition = GetSetPosTarget(part, v, currentPosition);
7912 positionChanged = true;
7171 7913
7172 break; 7914 break;
7173 case (int)ScriptBaseClass.PRIM_SIZE: 7915 case (int)ScriptBaseClass.PRIM_SIZE:
@@ -7183,8 +7925,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7183 return; 7925 return;
7184 7926
7185 LSL_Rotation q = rules.GetQuaternionItem(idx++); 7927 LSL_Rotation q = rules.GetQuaternionItem(idx++);
7928 SceneObjectPart rootPart = parentgrp.RootPart;
7186 // try to let this work as in SL... 7929 // try to let this work as in SL...
7187 if (part.ParentID == 0) 7930 if (rootPart == part)
7188 { 7931 {
7189 // special case: If we are root, rotate complete SOG to new rotation 7932 // special case: If we are root, rotate complete SOG to new rotation
7190 SetRot(part, Rot2Quaternion(q)); 7933 SetRot(part, Rot2Quaternion(q));
@@ -7192,7 +7935,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7192 else 7935 else
7193 { 7936 {
7194 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. 7937 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
7195 SceneObjectPart rootPart = part.ParentGroup.RootPart; 7938 // sounds like sl bug that we need to replicate
7196 SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q)); 7939 SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q));
7197 } 7940 }
7198 7941
@@ -7445,7 +8188,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7445 return; 8188 return;
7446 8189
7447 string ph = rules.Data[idx++].ToString(); 8190 string ph = rules.Data[idx++].ToString();
7448 m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); 8191 parentgrp.ScriptSetPhantomStatus(ph.Equals("1"));
7449 8192
7450 break; 8193 break;
7451 8194
@@ -7463,12 +8206,42 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7463 part.ScriptSetPhysicsStatus(physics); 8206 part.ScriptSetPhysicsStatus(physics);
7464 break; 8207 break;
7465 8208
8209 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
8210 if (remain < 1)
8211 return;
8212
8213 int shape_type = rules.GetLSLIntegerItem(idx++);
8214
8215 ExtraPhysicsData physdata = new ExtraPhysicsData();
8216 physdata.Density = part.Density;
8217 physdata.Bounce = part.Bounciness;
8218 physdata.GravitationModifier = part.GravityModifier;
8219 physdata.PhysShapeType = (PhysShapeType)shape_type;
8220
8221 part.UpdateExtraPhysics(physdata);
8222
8223 break;
8224
8225 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8226 if (remain < 5)
8227 return;
8228
8229 int material_bits = rules.GetLSLIntegerItem(idx++);
8230 float material_density = (float)rules.GetLSLFloatItem(idx++);
8231 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8232 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8233 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8234
8235 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8236
8237 break;
8238
7466 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8239 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7467 if (remain < 1) 8240 if (remain < 1)
7468 return; 8241 return;
7469 string temp = rules.Data[idx++].ToString(); 8242 string temp = rules.Data[idx++].ToString();
7470 8243
7471 m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); 8244 parentgrp.ScriptSetTemporaryStatus(temp.Equals("1"));
7472 8245
7473 break; 8246 break;
7474 8247
@@ -7518,13 +8291,37 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7518 LSL_Float gain = rules.GetLSLFloatItem(idx++); 8291 LSL_Float gain = rules.GetLSLFloatItem(idx++);
7519 TargetOmega(part, axis, (double)spinrate, (double)gain); 8292 TargetOmega(part, axis, (double)spinrate, (double)gain);
7520 break; 8293 break;
8294
7521 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 8295 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
7522 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 8296 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
7523 return; 8297 return;
8298
8299 // do a pending position change before jumping to other part/avatar
8300 if (positionChanged)
8301 {
8302 positionChanged = false;
8303 if (parentgrp == null)
8304 return;
8305
8306 if (parentgrp.RootPart == part)
8307 {
8308
8309 Util.FireAndForget(delegate(object x)
8310 {
8311 parentgrp.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8312 });
8313 }
8314 else
8315 {
8316 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8317 parentgrp.HasGroupChanged = true;
8318 parentgrp.ScheduleGroupForTerseUpdate();
8319 }
8320 }
8321
7524 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); 8322 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
7525 LSL_List new_rules = rules.GetSublist(idx, -1); 8323 LSL_List new_rules = rules.GetSublist(idx, -1);
7526 setLinkPrimParams((int)new_linknumber, new_rules); 8324 setLinkPrimParams((int)new_linknumber, new_rules);
7527
7528 return; 8325 return;
7529 } 8326 }
7530 } 8327 }
@@ -7536,7 +8333,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7536 if (part.ParentGroup.RootPart == part) 8333 if (part.ParentGroup.RootPart == part)
7537 { 8334 {
7538 SceneObjectGroup parent = part.ParentGroup; 8335 SceneObjectGroup parent = part.ParentGroup;
7539 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8336 Util.FireAndForget(delegate(object x) {
8337 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8338 });
7540 } 8339 }
7541 else 8340 else
7542 { 8341 {
@@ -7707,13 +8506,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7707 public LSL_Integer llGetNumberOfPrims() 8506 public LSL_Integer llGetNumberOfPrims()
7708 { 8507 {
7709 m_host.AddScriptLPS(1); 8508 m_host.AddScriptLPS(1);
7710 int avatarCount = 0; 8509 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7711 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8510
7712 {
7713 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
7714 avatarCount++;
7715 });
7716
7717 return m_host.ParentGroup.PrimCount + avatarCount; 8511 return m_host.ParentGroup.PrimCount + avatarCount;
7718 } 8512 }
7719 8513
@@ -7729,55 +8523,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7729 m_host.AddScriptLPS(1); 8523 m_host.AddScriptLPS(1);
7730 UUID objID = UUID.Zero; 8524 UUID objID = UUID.Zero;
7731 LSL_List result = new LSL_List(); 8525 LSL_List result = new LSL_List();
8526
8527 // If the ID is not valid, return null result
7732 if (!UUID.TryParse(obj, out objID)) 8528 if (!UUID.TryParse(obj, out objID))
7733 { 8529 {
7734 result.Add(new LSL_Vector()); 8530 result.Add(new LSL_Vector());
7735 result.Add(new LSL_Vector()); 8531 result.Add(new LSL_Vector());
7736 return result; 8532 return result;
7737 } 8533 }
8534
8535 // Check if this is an attached prim. If so, replace
8536 // the UUID with the avatar UUID and report it's bounding box
8537 SceneObjectPart part = World.GetSceneObjectPart(objID);
8538 if (part != null && part.ParentGroup.IsAttachment)
8539 objID = part.ParentGroup.AttachedAvatar;
8540
8541 // Find out if this is an avatar ID. If so, return it's box
7738 ScenePresence presence = World.GetScenePresence(objID); 8542 ScenePresence presence = World.GetScenePresence(objID);
7739 if (presence != null) 8543 if (presence != null)
7740 { 8544 {
7741 if (presence.ParentID == 0) // not sat on an object 8545 // As per LSL Wiki, there is no difference between sitting
8546 // and standing avatar since server 1.36
8547 LSL_Vector lower;
8548 LSL_Vector upper;
8549 if (presence.Animator.Animations.DefaultAnimation.AnimID
8550 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7742 { 8551 {
7743 LSL_Vector lower; 8552 // This is for ground sitting avatars
7744 LSL_Vector upper; 8553 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7745 if (presence.Animator.Animations.DefaultAnimation.AnimID 8554 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7746 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8555 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7747 {
7748 // This is for ground sitting avatars
7749 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7750 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7751 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7752 }
7753 else
7754 {
7755 // This is for standing/flying avatars
7756 float height = presence.Appearance.AvatarHeight / 2.0f;
7757 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7758 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7759 }
7760 result.Add(lower);
7761 result.Add(upper);
7762 return result;
7763 } 8556 }
7764 else 8557 else
7765 { 8558 {
7766 // sitting on an object so we need the bounding box of that 8559 // This is for standing/flying avatars
7767 // which should include the avatar so set the UUID to the 8560 float height = presence.Appearance.AvatarHeight / 2.0f;
7768 // UUID of the object the avatar is sat on and allow it to fall through 8561 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7769 // to processing an object 8562 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7770 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7771 objID = p.UUID;
7772 } 8563 }
8564
8565 // Adjust to the documented error offsets (see LSL Wiki)
8566 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8567 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8568
8569 if (lower.x > upper.x)
8570 lower.x = upper.x;
8571 if (lower.y > upper.y)
8572 lower.y = upper.y;
8573 if (lower.z > upper.z)
8574 lower.z = upper.z;
8575
8576 result.Add(lower);
8577 result.Add(upper);
8578 return result;
7773 } 8579 }
7774 SceneObjectPart part = World.GetSceneObjectPart(objID); 8580
8581 part = World.GetSceneObjectPart(objID);
7775 // Currently only works for single prims without a sitting avatar 8582 // Currently only works for single prims without a sitting avatar
7776 if (part != null) 8583 if (part != null)
7777 { 8584 {
7778 Vector3 halfSize = part.Scale / 2.0f; 8585 float minX;
7779 LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); 8586 float maxX;
7780 LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); 8587 float minY;
8588 float maxY;
8589 float minZ;
8590 float maxZ;
8591
8592 // This BBox is in sim coordinates, with the offset being
8593 // a contained point.
8594 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8595 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8596
8597 minX -= offsets[0].X;
8598 maxX -= offsets[0].X;
8599 minY -= offsets[0].Y;
8600 maxY -= offsets[0].Y;
8601 minZ -= offsets[0].Z;
8602 maxZ -= offsets[0].Z;
8603
8604 LSL_Vector lower;
8605 LSL_Vector upper;
8606
8607 // Adjust to the documented error offsets (see LSL Wiki)
8608 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8609 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8610
8611 if (lower.x > upper.x)
8612 lower.x = upper.x;
8613 if (lower.y > upper.y)
8614 lower.y = upper.y;
8615 if (lower.z > upper.z)
8616 lower.z = upper.z;
8617
7781 result.Add(lower); 8618 result.Add(lower);
7782 result.Add(upper); 8619 result.Add(upper);
7783 return result; 8620 return result;
@@ -7791,7 +8628,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7791 8628
7792 public LSL_Vector llGetGeometricCenter() 8629 public LSL_Vector llGetGeometricCenter()
7793 { 8630 {
7794 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 8631 Vector3 tmp = m_host.GetGeometricCenter();
8632 return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
7795 } 8633 }
7796 8634
7797 public LSL_List llGetPrimitiveParams(LSL_List rules) 8635 public LSL_List llGetPrimitiveParams(LSL_List rules)
@@ -7804,16 +8642,291 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7804 { 8642 {
7805 m_host.AddScriptLPS(1); 8643 m_host.AddScriptLPS(1);
7806 8644
8645 // acording to SL wiki this must indicate a single link number or link_root or link_this.
8646 // keep other options as before
8647
7807 List<SceneObjectPart> parts = GetLinkParts(linknumber); 8648 List<SceneObjectPart> parts = GetLinkParts(linknumber);
8649 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7808 8650
7809 LSL_List res = new LSL_List(); 8651 LSL_List res = new LSL_List();
7810 8652
7811 foreach (var part in parts) 8653 if (parts.Count > 0)
7812 { 8654 {
7813 LSL_List partRes = GetLinkPrimitiveParams(part, rules); 8655 foreach (var part in parts)
7814 res += partRes; 8656 {
8657 LSL_List partRes = GetLinkPrimitiveParams(part, rules);
8658 res += partRes;
8659 }
8660 }
8661 if (avatars.Count > 0)
8662 {
8663 foreach (ScenePresence avatar in avatars)
8664 {
8665 LSL_List avaRes = GetLinkPrimitiveParams(avatar, rules);
8666 res += avaRes;
8667 }
7815 } 8668 }
8669 return res;
8670 }
8671
8672 public LSL_List GetLinkPrimitiveParams(ScenePresence avatar, LSL_List rules)
8673 {
8674 // avatars case
8675 // replies as SL wiki
8676
8677 LSL_List res = new LSL_List();
8678// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
8679 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
8680
8681 int idx = 0;
8682 while (idx < rules.Length)
8683 {
8684 int code = (int)rules.GetLSLIntegerItem(idx++);
8685 int remain = rules.Length - idx;
8686
8687 switch (code)
8688 {
8689 case (int)ScriptBaseClass.PRIM_MATERIAL:
8690 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
8691 break;
8692
8693 case (int)ScriptBaseClass.PRIM_PHYSICS:
8694 res.Add(new LSL_Integer(0));
8695 break;
8696
8697 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
8698 res.Add(new LSL_Integer(0));
8699 break;
8700
8701 case (int)ScriptBaseClass.PRIM_PHANTOM:
8702 res.Add(new LSL_Integer(0));
8703 break;
8704
8705 case (int)ScriptBaseClass.PRIM_POSITION:
8706
8707 Vector3 pos = avatar.OffsetPosition;
8708
8709 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
8710 pos -= sitOffset;
8711
8712 if( sitPart != null)
8713 pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation();
8714
8715 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
8716 break;
8717
8718 case (int)ScriptBaseClass.PRIM_SIZE:
8719 // as in llGetAgentSize above
8720 res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight));
8721 break;
8722
8723 case (int)ScriptBaseClass.PRIM_ROTATION:
8724 Quaternion rot = avatar.Rotation;
8725 if (sitPart != null)
8726 {
8727 rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation
8728 }
8729
8730 res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W));
8731 break;
8732
8733 case (int)ScriptBaseClass.PRIM_TYPE:
8734 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
8735 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
8736 res.Add(new LSL_Vector(0f,1.0f,0f));
8737 res.Add(new LSL_Float(0.0f));
8738 res.Add(new LSL_Vector(0, 0, 0));
8739 res.Add(new LSL_Vector(1.0f,1.0f,0f));
8740 res.Add(new LSL_Vector(0, 0, 0));
8741 break;
8742
8743 case (int)ScriptBaseClass.PRIM_TEXTURE:
8744 if (remain < 1)
8745 return res;
8746
8747 int face = (int)rules.GetLSLIntegerItem(idx++);
8748 if (face == ScriptBaseClass.ALL_SIDES)
8749 {
8750 for (face = 0; face < 21; face++)
8751 {
8752 res.Add(new LSL_String(""));
8753 res.Add(new LSL_Vector(0,0,0));
8754 res.Add(new LSL_Vector(0,0,0));
8755 res.Add(new LSL_Float(0.0));
8756 }
8757 }
8758 else
8759 {
8760 if (face >= 0 && face < 21)
8761 {
8762 res.Add(new LSL_String(""));
8763 res.Add(new LSL_Vector(0,0,0));
8764 res.Add(new LSL_Vector(0,0,0));
8765 res.Add(new LSL_Float(0.0));
8766 }
8767 }
8768 break;
8769
8770 case (int)ScriptBaseClass.PRIM_COLOR:
8771 if (remain < 1)
8772 return res;
8773
8774 face = (int)rules.GetLSLIntegerItem(idx++);
8775
8776 if (face == ScriptBaseClass.ALL_SIDES)
8777 {
8778 for (face = 0; face < 21; face++)
8779 {
8780 res.Add(new LSL_Vector(0,0,0));
8781 res.Add(new LSL_Float(0));
8782 }
8783 }
8784 else
8785 {
8786 res.Add(new LSL_Vector(0,0,0));
8787 res.Add(new LSL_Float(0));
8788 }
8789 break;
8790
8791 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8792 if (remain < 1)
8793 return res;
8794 face = (int)rules.GetLSLIntegerItem(idx++);
7816 8795
8796 if (face == ScriptBaseClass.ALL_SIDES)
8797 {
8798 for (face = 0; face < 21; face++)
8799 {
8800 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
8801 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
8802 }
8803 }
8804 else
8805 {
8806 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
8807 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
8808 }
8809 break;
8810
8811 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8812 if (remain < 1)
8813 return res;
8814 face = (int)rules.GetLSLIntegerItem(idx++);
8815
8816 if (face == ScriptBaseClass.ALL_SIDES)
8817 {
8818 for (face = 0; face < 21; face++)
8819 {
8820 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
8821 }
8822 }
8823 else
8824 {
8825 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
8826 }
8827 break;
8828
8829 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
8830 res.Add(new LSL_Integer(0));
8831 res.Add(new LSL_Integer(0));// softness
8832 res.Add(new LSL_Float(0.0f)); // gravity
8833 res.Add(new LSL_Float(0.0f)); // friction
8834 res.Add(new LSL_Float(0.0f)); // wind
8835 res.Add(new LSL_Float(0.0f)); // tension
8836 res.Add(new LSL_Vector(0f,0f,0f));
8837 break;
8838
8839 case (int)ScriptBaseClass.PRIM_TEXGEN:
8840 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8841 if (remain < 1)
8842 return res;
8843 face = (int)rules.GetLSLIntegerItem(idx++);
8844
8845 if (face == ScriptBaseClass.ALL_SIDES)
8846 {
8847 for (face = 0; face < 21; face++)
8848 {
8849 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8850 }
8851 }
8852 else
8853 {
8854 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8855 }
8856 break;
8857
8858 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
8859 res.Add(new LSL_Integer(0));
8860 res.Add(new LSL_Vector(0f,0f,0f));
8861 res.Add(new LSL_Float(0f)); // intensity
8862 res.Add(new LSL_Float(0f)); // radius
8863 res.Add(new LSL_Float(0f)); // falloff
8864 break;
8865
8866 case (int)ScriptBaseClass.PRIM_GLOW:
8867 if (remain < 1)
8868 return res;
8869 face = (int)rules.GetLSLIntegerItem(idx++);
8870
8871 if (face == ScriptBaseClass.ALL_SIDES)
8872 {
8873 for (face = 0; face < 21; face++)
8874 {
8875 res.Add(new LSL_Float(0f));
8876 }
8877 }
8878 else
8879 {
8880 res.Add(new LSL_Float(0f));
8881 }
8882 break;
8883
8884 case (int)ScriptBaseClass.PRIM_TEXT:
8885 res.Add(new LSL_String(""));
8886 res.Add(new LSL_Vector(0f,0f,0f));
8887 res.Add(new LSL_Float(1.0f));
8888 break;
8889
8890 case (int)ScriptBaseClass.PRIM_NAME:
8891 res.Add(new LSL_String(avatar.Name));
8892 break;
8893
8894 case (int)ScriptBaseClass.PRIM_DESC:
8895 res.Add(new LSL_String(""));
8896 break;
8897
8898 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8899 Quaternion lrot = avatar.Rotation;
8900
8901 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
8902 {
8903 lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset
8904 }
8905 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
8906 break;
8907
8908 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
8909 Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part
8910 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
8911 lpos -= lsitOffset;
8912
8913 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
8914 {
8915 lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim
8916 }
8917 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
8918 break;
8919
8920 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
8921 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
8922 return res;
8923 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
8924 LSL_List new_rules = rules.GetSublist(idx, -1);
8925
8926 res += llGetLinkPrimitiveParams((int)new_linknumber, new_rules);
8927 return res;
8928 }
8929 }
7817 return res; 8930 return res;
7818 } 8931 }
7819 8932
@@ -7857,13 +8970,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7857 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8970 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
7858 part.AbsolutePosition.Y, 8971 part.AbsolutePosition.Y,
7859 part.AbsolutePosition.Z); 8972 part.AbsolutePosition.Z);
7860 // For some reason, the part.AbsolutePosition.* values do not change if the
7861 // linkset is rotated; they always reflect the child prim's world position
7862 // as though the linkset is unrotated. This is incompatible behavior with SL's
7863 // implementation, so will break scripts imported from there (not to mention it
7864 // makes it more difficult to determine a child prim's actual inworld position).
7865 if (part.ParentID != 0)
7866 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
7867 res.Add(v); 8973 res.Add(v);
7868 break; 8974 break;
7869 8975
@@ -8034,56 +9140,92 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8034 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 9140 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8035 if (remain < 1) 9141 if (remain < 1)
8036 return res; 9142 return res;
8037 9143 face = (int)rules.GetLSLIntegerItem(idx++);
8038 face=(int)rules.GetLSLIntegerItem(idx++);
8039 9144
8040 tex = part.Shape.Textures; 9145 tex = part.Shape.Textures;
9146 int shiny;
8041 if (face == ScriptBaseClass.ALL_SIDES) 9147 if (face == ScriptBaseClass.ALL_SIDES)
8042 { 9148 {
8043 for (face = 0; face < GetNumberOfSides(part); face++) 9149 for (face = 0; face < GetNumberOfSides(part); face++)
8044 { 9150 {
8045 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9151 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8046 // Convert Shininess to PRIM_SHINY_* 9152 if (shinyness == Shininess.High)
8047 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 9153 {
8048 // PRIM_BUMP_* 9154 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8049 res.Add(new LSL_Integer((int)texface.Bump)); 9155 }
9156 else if (shinyness == Shininess.Medium)
9157 {
9158 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
9159 }
9160 else if (shinyness == Shininess.Low)
9161 {
9162 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
9163 }
9164 else
9165 {
9166 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
9167 }
9168 res.Add(new LSL_Integer(shiny));
9169 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8050 } 9170 }
8051 } 9171 }
8052 else 9172 else
8053 { 9173 {
8054 if (face >= 0 && face < GetNumberOfSides(part)) 9174 Shininess shinyness = tex.GetFace((uint)face).Shiny;
9175 if (shinyness == Shininess.High)
8055 { 9176 {
8056 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9177 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8057 // Convert Shininess to PRIM_SHINY_* 9178 }
8058 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 9179 else if (shinyness == Shininess.Medium)
8059 // PRIM_BUMP_* 9180 {
8060 res.Add(new LSL_Integer((int)texface.Bump)); 9181 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
9182 }
9183 else if (shinyness == Shininess.Low)
9184 {
9185 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
9186 }
9187 else
9188 {
9189 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8061 } 9190 }
9191 res.Add(new LSL_Integer(shiny));
9192 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8062 } 9193 }
8063 break; 9194 break;
8064 9195
8065 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 9196 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8066 if (remain < 1) 9197 if (remain < 1)
8067 return res; 9198 return res;
8068 9199 face = (int)rules.GetLSLIntegerItem(idx++);
8069 face=(int)rules.GetLSLIntegerItem(idx++);
8070 9200
8071 tex = part.Shape.Textures; 9201 tex = part.Shape.Textures;
9202 int fullbright;
8072 if (face == ScriptBaseClass.ALL_SIDES) 9203 if (face == ScriptBaseClass.ALL_SIDES)
8073 { 9204 {
8074 for (face = 0; face < GetNumberOfSides(part); face++) 9205 for (face = 0; face < GetNumberOfSides(part); face++)
8075 { 9206 {
8076 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9207 if (tex.GetFace((uint)face).Fullbright == true)
8077 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 9208 {
9209 fullbright = ScriptBaseClass.TRUE;
9210 }
9211 else
9212 {
9213 fullbright = ScriptBaseClass.FALSE;
9214 }
9215 res.Add(new LSL_Integer(fullbright));
8078 } 9216 }
8079 } 9217 }
8080 else 9218 else
8081 { 9219 {
8082 if (face >= 0 && face < GetNumberOfSides(part)) 9220 if (tex.GetFace((uint)face).Fullbright == true)
8083 { 9221 {
8084 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9222 fullbright = ScriptBaseClass.TRUE;
8085 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
8086 } 9223 }
9224 else
9225 {
9226 fullbright = ScriptBaseClass.FALSE;
9227 }
9228 res.Add(new LSL_Integer(fullbright));
8087 } 9229 }
8088 break; 9230 break;
8089 9231
@@ -8105,27 +9247,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8105 break; 9247 break;
8106 9248
8107 case (int)ScriptBaseClass.PRIM_TEXGEN: 9249 case (int)ScriptBaseClass.PRIM_TEXGEN:
9250 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8108 if (remain < 1) 9251 if (remain < 1)
8109 return res; 9252 return res;
8110 9253 face = (int)rules.GetLSLIntegerItem(idx++);
8111 face=(int)rules.GetLSLIntegerItem(idx++);
8112 9254
8113 tex = part.Shape.Textures; 9255 tex = part.Shape.Textures;
8114 if (face == ScriptBaseClass.ALL_SIDES) 9256 if (face == ScriptBaseClass.ALL_SIDES)
8115 { 9257 {
8116 for (face = 0; face < GetNumberOfSides(part); face++) 9258 for (face = 0; face < GetNumberOfSides(part); face++)
8117 { 9259 {
8118 MappingType texgen = tex.GetFace((uint)face).TexMapType; 9260 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8119 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 9261 {
8120 res.Add(new LSL_Integer((uint)texgen >> 1)); 9262 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
9263 }
9264 else
9265 {
9266 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
9267 }
8121 } 9268 }
8122 } 9269 }
8123 else 9270 else
8124 { 9271 {
8125 if (face >= 0 && face < GetNumberOfSides(part)) 9272 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8126 { 9273 {
8127 MappingType texgen = tex.GetFace((uint)face).TexMapType; 9274 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8128 res.Add(new LSL_Integer((uint)texgen >> 1)); 9275 }
9276 else
9277 {
9278 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8129 } 9279 }
8130 } 9280 }
8131 break; 9281 break;
@@ -8148,25 +9298,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8148 case (int)ScriptBaseClass.PRIM_GLOW: 9298 case (int)ScriptBaseClass.PRIM_GLOW:
8149 if (remain < 1) 9299 if (remain < 1)
8150 return res; 9300 return res;
8151 9301 face = (int)rules.GetLSLIntegerItem(idx++);
8152 face=(int)rules.GetLSLIntegerItem(idx++);
8153 9302
8154 tex = part.Shape.Textures; 9303 tex = part.Shape.Textures;
9304 float primglow;
8155 if (face == ScriptBaseClass.ALL_SIDES) 9305 if (face == ScriptBaseClass.ALL_SIDES)
8156 { 9306 {
8157 for (face = 0; face < GetNumberOfSides(part); face++) 9307 for (face = 0; face < GetNumberOfSides(part); face++)
8158 { 9308 {
8159 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9309 primglow = tex.GetFace((uint)face).Glow;
8160 res.Add(new LSL_Float(texface.Glow)); 9310 res.Add(new LSL_Float(primglow));
8161 } 9311 }
8162 } 9312 }
8163 else 9313 else
8164 { 9314 {
8165 if (face >= 0 && face < GetNumberOfSides(part)) 9315 primglow = tex.GetFace((uint)face).Glow;
8166 { 9316 res.Add(new LSL_Float(primglow));
8167 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8168 res.Add(new LSL_Float(texface.Glow));
8169 }
8170 } 9317 }
8171 break; 9318 break;
8172 9319
@@ -8178,18 +9325,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8178 textColor.B)); 9325 textColor.B));
8179 res.Add(new LSL_Float(textColor.A)); 9326 res.Add(new LSL_Float(textColor.A));
8180 break; 9327 break;
9328
8181 case (int)ScriptBaseClass.PRIM_NAME: 9329 case (int)ScriptBaseClass.PRIM_NAME:
8182 res.Add(new LSL_String(part.Name)); 9330 res.Add(new LSL_String(part.Name));
8183 break; 9331 break;
9332
8184 case (int)ScriptBaseClass.PRIM_DESC: 9333 case (int)ScriptBaseClass.PRIM_DESC:
8185 res.Add(new LSL_String(part.Description)); 9334 res.Add(new LSL_String(part.Description));
8186 break; 9335 break;
9336
8187 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 9337 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8188 res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); 9338 res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W));
8189 break; 9339 break;
9340
8190 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 9341 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
8191 res.Add(new LSL_Vector(GetPartLocalPos(part))); 9342 res.Add(new LSL_Vector(GetPartLocalPos(part)));
8192 break; 9343 break;
9344
9345 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
9346 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
9347 return res;
9348 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
9349 LSL_List new_rules = rules.GetSublist(idx, -1);
9350 LSL_List tres = llGetLinkPrimitiveParams((int)new_linknumber, new_rules);
9351 res += tres;
9352 return res;
8193 } 9353 }
8194 } 9354 }
8195 return res; 9355 return res;
@@ -8782,8 +9942,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8782 // The function returns an ordered list 9942 // The function returns an ordered list
8783 // representing the tokens found in the supplied 9943 // representing the tokens found in the supplied
8784 // sources string. If two successive tokenizers 9944 // sources string. If two successive tokenizers
8785 // are encountered, then a NULL entry is added 9945 // are encountered, then a null-string entry is
8786 // to the list. 9946 // added to the list.
8787 // 9947 //
8788 // It is a precondition that the source and 9948 // It is a precondition that the source and
8789 // toekizer lisst are non-null. If they are null, 9949 // toekizer lisst are non-null. If they are null,
@@ -8791,7 +9951,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8791 // while their lengths are being determined. 9951 // while their lengths are being determined.
8792 // 9952 //
8793 // A small amount of working memoryis required 9953 // A small amount of working memoryis required
8794 // of approximately 8*#tokenizers. 9954 // of approximately 8*#tokenizers + 8*srcstrlen.
8795 // 9955 //
8796 // There are many ways in which this function 9956 // There are many ways in which this function
8797 // can be implemented, this implementation is 9957 // can be implemented, this implementation is
@@ -8807,155 +9967,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8807 // and eliminates redundant tokenizers as soon 9967 // and eliminates redundant tokenizers as soon
8808 // as is possible. 9968 // as is possible.
8809 // 9969 //
8810 // The implementation tries to avoid any copying 9970 // The implementation tries to minimize temporary
8811 // of arrays or other objects. 9971 // garbage generation.
8812 // </remarks> 9972 // </remarks>
8813 9973
8814 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9974 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8815 { 9975 {
8816 int beginning = 0; 9976 return ParseString2List(src, separators, spacers, true);
8817 int srclen = src.Length; 9977 }
8818 int seplen = separators.Length;
8819 object[] separray = separators.Data;
8820 int spclen = spacers.Length;
8821 object[] spcarray = spacers.Data;
8822 int mlen = seplen+spclen;
8823
8824 int[] offset = new int[mlen+1];
8825 bool[] active = new bool[mlen];
8826
8827 int best;
8828 int j;
8829
8830 // Initial capacity reduces resize cost
8831 9978
8832 LSL_List tokens = new LSL_List(); 9979 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9980 {
9981 int srclen = src.Length;
9982 int seplen = separators.Length;
9983 object[] separray = separators.Data;
9984 int spclen = spacers.Length;
9985 object[] spcarray = spacers.Data;
9986 int dellen = 0;
9987 string[] delarray = new string[seplen+spclen];
8833 9988
8834 // All entries are initially valid 9989 int outlen = 0;
9990 string[] outarray = new string[srclen*2+1];
8835 9991
8836 for (int i = 0; i < mlen; i++) 9992 int i, j;
8837 active[i] = true; 9993 string d;
8838 9994
8839 offset[mlen] = srclen; 9995 m_host.AddScriptLPS(1);
8840 9996
8841 while (beginning < srclen) 9997 /*
9998 * Convert separator and spacer lists to C# strings.
9999 * Also filter out null strings so we don't hang.
10000 */
10001 for (i = 0; i < seplen; i ++)
8842 { 10002 {
10003 d = separray[i].ToString();
10004 if (d.Length > 0)
10005 {
10006 delarray[dellen++] = d;
10007 }
10008 }
10009 seplen = dellen;
8843 10010
8844 best = mlen; // as bad as it gets 10011 for (i = 0; i < spclen; i ++)
10012 {
10013 d = spcarray[i].ToString();
10014 if (d.Length > 0)
10015 {
10016 delarray[dellen++] = d;
10017 }
10018 }
8845 10019
8846 // Scan for separators 10020 /*
10021 * Scan through source string from beginning to end.
10022 */
10023 for (i = 0;;)
10024 {
8847 10025
8848 for (j = 0; j < seplen; j++) 10026 /*
10027 * Find earliest delimeter in src starting at i (if any).
10028 */
10029 int earliestDel = -1;
10030 int earliestSrc = srclen;
10031 string earliestStr = null;
10032 for (j = 0; j < dellen; j ++)
8849 { 10033 {
8850 if (separray[j].ToString() == String.Empty) 10034 d = delarray[j];
8851 active[j] = false; 10035 if (d != null)
8852
8853 if (active[j])
8854 { 10036 {
8855 // scan all of the markers 10037 int index = src.IndexOf(d, i);
8856 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 10038 if (index < 0)
8857 { 10039 {
8858 // not present at all 10040 delarray[j] = null; // delim nowhere in src, don't check it anymore
8859 active[j] = false;
8860 } 10041 }
8861 else 10042 else if (index < earliestSrc)
8862 { 10043 {
8863 // present and correct 10044 earliestSrc = index; // where delimeter starts in source string
8864 if (offset[j] < offset[best]) 10045 earliestDel = j; // where delimeter is in delarray[]
8865 { 10046 earliestStr = d; // the delimeter string from delarray[]
8866 // closest so far 10047 if (index == i) break; // can't do any better than found at beg of string
8867 best = j;
8868 if (offset[best] == beginning)
8869 break;
8870 }
8871 } 10048 }
8872 } 10049 }
8873 } 10050 }
8874 10051
8875 // Scan for spacers 10052 /*
8876 10053 * Output source string starting at i through start of earliest delimeter.
8877 if (offset[best] != beginning) 10054 */
10055 if (keepNulls || (earliestSrc > i))
8878 { 10056 {
8879 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 10057 outarray[outlen++] = src.Substring(i, earliestSrc - i);
8880 {
8881 if (spcarray[j-seplen].ToString() == String.Empty)
8882 active[j] = false;
8883
8884 if (active[j])
8885 {
8886 // scan all of the markers
8887 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
8888 {
8889 // not present at all
8890 active[j] = false;
8891 }
8892 else
8893 {
8894 // present and correct
8895 if (offset[j] < offset[best])
8896 {
8897 // closest so far
8898 best = j;
8899 }
8900 }
8901 }
8902 }
8903 } 10058 }
8904 10059
8905 // This is the normal exit from the scanning loop 10060 /*
10061 * If no delimeter found at or after i, we're done scanning.
10062 */
10063 if (earliestDel < 0) break;
8906 10064
8907 if (best == mlen) 10065 /*
10066 * If delimeter was a spacer, output the spacer.
10067 */
10068 if (earliestDel >= seplen)
8908 { 10069 {
8909 // no markers were found on this pass 10070 outarray[outlen++] = earliestStr;
8910 // so we're pretty much done
8911 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
8912 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
8913 break;
8914 } 10071 }
8915 10072
8916 // Otherwise we just add the newly delimited token 10073 /*
8917 // and recalculate where the search should continue. 10074 * Look at rest of src string following delimeter.
8918 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 10075 */
8919 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 10076 i = earliestSrc + earliestStr.Length;
8920
8921 if (best < seplen)
8922 {
8923 beginning = offset[best] + (separray[best].ToString()).Length;
8924 }
8925 else
8926 {
8927 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
8928 string str = spcarray[best - seplen].ToString();
8929 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
8930 tokens.Add(new LSL_String(str));
8931 }
8932 } 10077 }
8933 10078
8934 // This an awkward an not very intuitive boundary case. If the 10079 /*
8935 // last substring is a tokenizer, then there is an implied trailing 10080 * Make up an exact-sized output array suitable for an LSL_List object.
8936 // null list entry. Hopefully the single comparison will not be too 10081 */
8937 // arduous. Alternatively the 'break' could be replced with a return 10082 object[] outlist = new object[outlen];
8938 // but that's shabby programming. 10083 for (i = 0; i < outlen; i ++)
8939
8940 if ((beginning == srclen) && (keepNulls))
8941 { 10084 {
8942 if (srclen != 0) 10085 outlist[i] = new LSL_String(outarray[i]);
8943 tokens.Add(new LSL_String(""));
8944 } 10086 }
8945 10087 return new LSL_List(outlist);
8946 return tokens;
8947 }
8948
8949 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
8950 {
8951 m_host.AddScriptLPS(1);
8952 return this.ParseString(src, separators, spacers, false);
8953 }
8954
8955 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8956 {
8957 m_host.AddScriptLPS(1);
8958 return this.ParseString(src, separators, spacers, true);
8959 } 10088 }
8960 10089
8961 public LSL_Integer llGetObjectPermMask(int mask) 10090 public LSL_Integer llGetObjectPermMask(int mask)
@@ -9050,6 +10179,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9050 case 4: 10179 case 4:
9051 return (int)item.NextPermissions; 10180 return (int)item.NextPermissions;
9052 } 10181 }
10182 m_host.TaskInventory.LockItemsForRead(false);
9053 10183
9054 return -1; 10184 return -1;
9055 } 10185 }
@@ -9240,9 +10370,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9240 { 10370 {
9241 try 10371 try
9242 { 10372 {
10373 /*
9243 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 10374 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
9244 if (obj != null) 10375 if (obj != null)
9245 return (double)obj.GetMass(); 10376 return (double)obj.GetMass();
10377 */
10378 // return total object mass
10379 SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
10380 if (obj != null)
10381 return obj.GetMass();
10382
9246 // the object is null so the key is for an avatar 10383 // the object is null so the key is for an avatar
9247 ScenePresence avatar = World.GetScenePresence(key); 10384 ScenePresence avatar = World.GetScenePresence(key);
9248 if (avatar != null) 10385 if (avatar != null)
@@ -9262,7 +10399,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9262 } 10399 }
9263 10400
9264 /// <summary> 10401 /// <summary>
9265 /// illListReplaceList removes the sub-list defined by the inclusive indices 10402 /// llListReplaceList removes the sub-list defined by the inclusive indices
9266 /// start and end and inserts the src list in its place. The inclusive 10403 /// start and end and inserts the src list in its place. The inclusive
9267 /// nature of the indices means that at least one element must be deleted 10404 /// nature of the indices means that at least one element must be deleted
9268 /// if the indices are within the bounds of the existing list. I.e. 2,2 10405 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9319,16 +10456,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9319 // based upon end. Note that if end exceeds the upper 10456 // based upon end. Note that if end exceeds the upper
9320 // bound in this case, the entire destination list 10457 // bound in this case, the entire destination list
9321 // is removed. 10458 // is removed.
9322 else 10459 else if (start == 0)
9323 { 10460 {
9324 if (end + 1 < dest.Length) 10461 if (end + 1 < dest.Length)
9325 {
9326 return src + dest.GetSublist(end + 1, -1); 10462 return src + dest.GetSublist(end + 1, -1);
9327 }
9328 else 10463 else
9329 {
9330 return src; 10464 return src;
9331 } 10465 }
10466 else // Start < 0
10467 {
10468 if (end + 1 < dest.Length)
10469 return dest.GetSublist(end + 1, -1);
10470 else
10471 return new LSL_List();
9332 } 10472 }
9333 } 10473 }
9334 // Finally, if start > end, we strip away a prefix and 10474 // Finally, if start > end, we strip away a prefix and
@@ -9379,17 +10519,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9379 int width = 0; 10519 int width = 0;
9380 int height = 0; 10520 int height = 0;
9381 10521
9382 ParcelMediaCommandEnum? commandToSend = null; 10522 uint commandToSend = 0;
9383 float time = 0.0f; // default is from start 10523 float time = 0.0f; // default is from start
9384 10524
9385 ScenePresence presence = null; 10525 ScenePresence presence = null;
9386 10526
9387 for (int i = 0; i < commandList.Data.Length; i++) 10527 for (int i = 0; i < commandList.Data.Length; i++)
9388 { 10528 {
9389 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10529 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9390 switch (command) 10530 switch (command)
9391 { 10531 {
9392 case ParcelMediaCommandEnum.Agent: 10532 case (uint)ParcelMediaCommandEnum.Agent:
9393 // we send only to one agent 10533 // we send only to one agent
9394 if ((i + 1) < commandList.Length) 10534 if ((i + 1) < commandList.Length)
9395 { 10535 {
@@ -9406,25 +10546,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9406 } 10546 }
9407 break; 10547 break;
9408 10548
9409 case ParcelMediaCommandEnum.Loop: 10549 case (uint)ParcelMediaCommandEnum.Loop:
9410 loop = 1; 10550 loop = 1;
9411 commandToSend = command; 10551 commandToSend = command;
9412 update = true; //need to send the media update packet to set looping 10552 update = true; //need to send the media update packet to set looping
9413 break; 10553 break;
9414 10554
9415 case ParcelMediaCommandEnum.Play: 10555 case (uint)ParcelMediaCommandEnum.Play:
9416 loop = 0; 10556 loop = 0;
9417 commandToSend = command; 10557 commandToSend = command;
9418 update = true; //need to send the media update packet to make sure it doesn't loop 10558 update = true; //need to send the media update packet to make sure it doesn't loop
9419 break; 10559 break;
9420 10560
9421 case ParcelMediaCommandEnum.Pause: 10561 case (uint)ParcelMediaCommandEnum.Pause:
9422 case ParcelMediaCommandEnum.Stop: 10562 case (uint)ParcelMediaCommandEnum.Stop:
9423 case ParcelMediaCommandEnum.Unload: 10563 case (uint)ParcelMediaCommandEnum.Unload:
9424 commandToSend = command; 10564 commandToSend = command;
9425 break; 10565 break;
9426 10566
9427 case ParcelMediaCommandEnum.Url: 10567 case (uint)ParcelMediaCommandEnum.Url:
9428 if ((i + 1) < commandList.Length) 10568 if ((i + 1) < commandList.Length)
9429 { 10569 {
9430 if (commandList.Data[i + 1] is LSL_String) 10570 if (commandList.Data[i + 1] is LSL_String)
@@ -9437,7 +10577,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9437 } 10577 }
9438 break; 10578 break;
9439 10579
9440 case ParcelMediaCommandEnum.Texture: 10580 case (uint)ParcelMediaCommandEnum.Texture:
9441 if ((i + 1) < commandList.Length) 10581 if ((i + 1) < commandList.Length)
9442 { 10582 {
9443 if (commandList.Data[i + 1] is LSL_String) 10583 if (commandList.Data[i + 1] is LSL_String)
@@ -9450,7 +10590,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9450 } 10590 }
9451 break; 10591 break;
9452 10592
9453 case ParcelMediaCommandEnum.Time: 10593 case (uint)ParcelMediaCommandEnum.Time:
9454 if ((i + 1) < commandList.Length) 10594 if ((i + 1) < commandList.Length)
9455 { 10595 {
9456 if (commandList.Data[i + 1] is LSL_Float) 10596 if (commandList.Data[i + 1] is LSL_Float)
@@ -9462,7 +10602,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9462 } 10602 }
9463 break; 10603 break;
9464 10604
9465 case ParcelMediaCommandEnum.AutoAlign: 10605 case (uint)ParcelMediaCommandEnum.AutoAlign:
9466 if ((i + 1) < commandList.Length) 10606 if ((i + 1) < commandList.Length)
9467 { 10607 {
9468 if (commandList.Data[i + 1] is LSL_Integer) 10608 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9476,7 +10616,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9476 } 10616 }
9477 break; 10617 break;
9478 10618
9479 case ParcelMediaCommandEnum.Type: 10619 case (uint)ParcelMediaCommandEnum.Type:
9480 if ((i + 1) < commandList.Length) 10620 if ((i + 1) < commandList.Length)
9481 { 10621 {
9482 if (commandList.Data[i + 1] is LSL_String) 10622 if (commandList.Data[i + 1] is LSL_String)
@@ -9489,7 +10629,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9489 } 10629 }
9490 break; 10630 break;
9491 10631
9492 case ParcelMediaCommandEnum.Desc: 10632 case (uint)ParcelMediaCommandEnum.Desc:
9493 if ((i + 1) < commandList.Length) 10633 if ((i + 1) < commandList.Length)
9494 { 10634 {
9495 if (commandList.Data[i + 1] is LSL_String) 10635 if (commandList.Data[i + 1] is LSL_String)
@@ -9502,7 +10642,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9502 } 10642 }
9503 break; 10643 break;
9504 10644
9505 case ParcelMediaCommandEnum.Size: 10645 case (uint)ParcelMediaCommandEnum.Size:
9506 if ((i + 2) < commandList.Length) 10646 if ((i + 2) < commandList.Length)
9507 { 10647 {
9508 if (commandList.Data[i + 1] is LSL_Integer) 10648 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9572,7 +10712,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9572 } 10712 }
9573 } 10713 }
9574 10714
9575 if (commandToSend != null) 10715 if (commandToSend != 0)
9576 { 10716 {
9577 // the commandList contained a start/stop/... command, too 10717 // the commandList contained a start/stop/... command, too
9578 if (presence == null) 10718 if (presence == null)
@@ -9609,7 +10749,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9609 10749
9610 if (aList.Data[i] != null) 10750 if (aList.Data[i] != null)
9611 { 10751 {
9612 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10752 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9613 { 10753 {
9614 case ParcelMediaCommandEnum.Url: 10754 case ParcelMediaCommandEnum.Url:
9615 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10755 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9666,15 +10806,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9666 10806
9667 if (quick_pay_buttons.Data.Length < 4) 10807 if (quick_pay_buttons.Data.Length < 4)
9668 { 10808 {
9669 LSLError("List must have at least 4 elements"); 10809 int x;
9670 return; 10810 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10811 {
10812 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10813 }
9671 } 10814 }
9672 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10815 int[] nPrice = new int[5];
9673 10816 nPrice[0] = price;
9674 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10817 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9675 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10818 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9676 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10819 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9677 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10820 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10821 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9678 m_host.ParentGroup.HasGroupChanged = true; 10822 m_host.ParentGroup.HasGroupChanged = true;
9679 } 10823 }
9680 10824
@@ -9691,7 +10835,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9691 return new LSL_Vector(); 10835 return new LSL_Vector();
9692 } 10836 }
9693 10837
9694 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10838// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10839 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9695 if (presence != null) 10840 if (presence != null)
9696 { 10841 {
9697 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); 10842 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
@@ -9713,7 +10858,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9713 return new LSL_Rotation(); 10858 return new LSL_Rotation();
9714 } 10859 }
9715 10860
9716 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10861// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10862 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9717 if (presence != null) 10863 if (presence != null)
9718 { 10864 {
9719 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); 10865 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W);
@@ -9773,8 +10919,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9773 { 10919 {
9774 m_host.AddScriptLPS(1); 10920 m_host.AddScriptLPS(1);
9775 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 10921 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
9776 if (detectedParams == null) return; // only works on the first detected avatar 10922 if (detectedParams == null)
9777 10923 {
10924 if (m_host.ParentGroup.IsAttachment == true)
10925 {
10926 detectedParams = new DetectParams();
10927 detectedParams.Key = m_host.OwnerID;
10928 }
10929 else
10930 {
10931 return;
10932 }
10933 }
10934
9778 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10935 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9779 if (avatar != null) 10936 if (avatar != null)
9780 { 10937 {
@@ -9782,6 +10939,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9782 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10939 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
9783 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); 10940 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
9784 } 10941 }
10942
9785 ScriptSleep(1000); 10943 ScriptSleep(1000);
9786 } 10944 }
9787 10945
@@ -9905,12 +11063,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9905 11063
9906 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 11064 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
9907 object[] data = rules.Data; 11065 object[] data = rules.Data;
9908 for (int i = 0; i < data.Length; ++i) { 11066 for (int i = 0; i < data.Length; ++i)
11067 {
9909 int type = Convert.ToInt32(data[i++].ToString()); 11068 int type = Convert.ToInt32(data[i++].ToString());
9910 if (i >= data.Length) break; // odd number of entries => ignore the last 11069 if (i >= data.Length) break; // odd number of entries => ignore the last
9911 11070
9912 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 11071 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
9913 switch (type) { 11072 switch (type)
11073 {
9914 case ScriptBaseClass.CAMERA_FOCUS: 11074 case ScriptBaseClass.CAMERA_FOCUS:
9915 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 11075 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
9916 case ScriptBaseClass.CAMERA_POSITION: 11076 case ScriptBaseClass.CAMERA_POSITION:
@@ -10016,19 +11176,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10016 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 11176 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
10017 { 11177 {
10018 m_host.AddScriptLPS(1); 11178 m_host.AddScriptLPS(1);
10019 string ret = String.Empty; 11179
10020 string src1 = llBase64ToString(str1); 11180 if (str1 == String.Empty)
10021 string src2 = llBase64ToString(str2); 11181 return String.Empty;
10022 int c = 0; 11182 if (str2 == String.Empty)
10023 for (int i = 0; i < src1.Length; i++) 11183 return str1;
11184
11185 int len = str2.Length;
11186 if ((len % 4) != 0) // LL is EVIL!!!!
11187 {
11188 while (str2.EndsWith("="))
11189 str2 = str2.Substring(0, str2.Length - 1);
11190
11191 len = str2.Length;
11192 int mod = len % 4;
11193
11194 if (mod == 1)
11195 str2 = str2.Substring(0, str2.Length - 1);
11196 else if (mod == 2)
11197 str2 += "==";
11198 else if (mod == 3)
11199 str2 += "=";
11200 }
11201
11202 byte[] data1;
11203 byte[] data2;
11204 try
10024 { 11205 {
10025 ret += (char) (src1[i] ^ src2[c]); 11206 data1 = Convert.FromBase64String(str1);
11207 data2 = Convert.FromBase64String(str2);
11208 }
11209 catch (Exception)
11210 {
11211 return new LSL_String(String.Empty);
11212 }
10026 11213
10027 c++; 11214 byte[] d2 = new Byte[data1.Length];
10028 if (c >= src2.Length) 11215 int pos = 0;
10029 c = 0; 11216
11217 if (data1.Length <= data2.Length)
11218 {
11219 Array.Copy(data2, 0, d2, 0, data1.Length);
10030 } 11220 }
10031 return llStringToBase64(ret); 11221 else
11222 {
11223 while (pos < data1.Length)
11224 {
11225 len = data1.Length - pos;
11226 if (len > data2.Length)
11227 len = data2.Length;
11228
11229 Array.Copy(data2, 0, d2, pos, len);
11230 pos += len;
11231 }
11232 }
11233
11234 for (pos = 0 ; pos < data1.Length ; pos++ )
11235 data1[pos] ^= d2[pos];
11236
11237 return Convert.ToBase64String(data1);
10032 } 11238 }
10033 11239
10034 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 11240 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10085,12 +11291,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10085 Regex r = new Regex(authregex); 11291 Regex r = new Regex(authregex);
10086 int[] gnums = r.GetGroupNumbers(); 11292 int[] gnums = r.GetGroupNumbers();
10087 Match m = r.Match(url); 11293 Match m = r.Match(url);
10088 if (m.Success) { 11294 if (m.Success)
10089 for (int i = 1; i < gnums.Length; i++) { 11295 {
11296 for (int i = 1; i < gnums.Length; i++)
11297 {
10090 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 11298 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10091 //CaptureCollection cc = g.Captures; 11299 //CaptureCollection cc = g.Captures;
10092 } 11300 }
10093 if (m.Groups.Count == 5) { 11301 if (m.Groups.Count == 5)
11302 {
10094 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 11303 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10095 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 11304 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10096 } 11305 }
@@ -10293,6 +11502,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10293 11502
10294 LSL_List ret = new LSL_List(); 11503 LSL_List ret = new LSL_List();
10295 UUID key = new UUID(); 11504 UUID key = new UUID();
11505
11506
10296 if (UUID.TryParse(id, out key)) 11507 if (UUID.TryParse(id, out key))
10297 { 11508 {
10298 ScenePresence av = World.GetScenePresence(key); 11509 ScenePresence av = World.GetScenePresence(key);
@@ -10310,13 +11521,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10310 ret.Add(new LSL_String("")); 11521 ret.Add(new LSL_String(""));
10311 break; 11522 break;
10312 case ScriptBaseClass.OBJECT_POS: 11523 case ScriptBaseClass.OBJECT_POS:
10313 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); 11524 Vector3 avpos;
11525
11526 if (av.ParentID != 0 && av.ParentPart != null)
11527 {
11528 avpos = av.OffsetPosition;
11529
11530 Vector3 sitOffset = (Zrot(av.Rotation)) * (av.Appearance.AvatarHeight * 0.02638f *2.0f);
11531 avpos -= sitOffset;
11532
11533 avpos = av.ParentPart.GetWorldPosition() + avpos * av.ParentPart.GetWorldRotation();
11534 }
11535 else
11536 avpos = av.AbsolutePosition;
11537
11538 ret.Add(new LSL_Vector((double)avpos.X, (double)avpos.Y, (double)avpos.Z));
10314 break; 11539 break;
10315 case ScriptBaseClass.OBJECT_ROT: 11540 case ScriptBaseClass.OBJECT_ROT:
10316 ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W)); 11541 Quaternion avrot = av.Rotation;
11542 if (av.ParentID != 0 && av.ParentPart != null)
11543 {
11544 avrot = av.ParentPart.GetWorldRotation() * avrot;
11545 }
11546 ret.Add(new LSL_Rotation((double)avrot.X, (double)avrot.Y, (double)avrot.Z, (double)avrot.W));
10317 break; 11547 break;
10318 case ScriptBaseClass.OBJECT_VELOCITY: 11548 case ScriptBaseClass.OBJECT_VELOCITY:
10319 ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); 11549 Vector3 avvel = av.Velocity;
11550 ret.Add(new LSL_Vector((double)avvel.X, (double)avvel.Y, (double)avvel.Z));
10320 break; 11551 break;
10321 case ScriptBaseClass.OBJECT_OWNER: 11552 case ScriptBaseClass.OBJECT_OWNER:
10322 ret.Add(new LSL_String(id)); 11553 ret.Add(new LSL_String(id));
@@ -10372,17 +11603,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10372 case ScriptBaseClass.OBJECT_NAME: 11603 case ScriptBaseClass.OBJECT_NAME:
10373 ret.Add(new LSL_String(obj.Name)); 11604 ret.Add(new LSL_String(obj.Name));
10374 break; 11605 break;
10375 case ScriptBaseClass.OBJECT_DESC: 11606 case ScriptBaseClass.OBJECT_DESC:
10376 ret.Add(new LSL_String(obj.Description)); 11607 ret.Add(new LSL_String(obj.Description));
10377 break; 11608 break;
10378 case ScriptBaseClass.OBJECT_POS: 11609 case ScriptBaseClass.OBJECT_POS:
10379 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); 11610 Vector3 opos = obj.AbsolutePosition;
11611 ret.Add(new LSL_Vector(opos.X, opos.Y, opos.Z));
10380 break; 11612 break;
10381 case ScriptBaseClass.OBJECT_ROT: 11613 case ScriptBaseClass.OBJECT_ROT:
10382 ret.Add(new LSL_Rotation(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W)); 11614// Quaternion orot = obj.RotationOffset;
11615// ret.Add(new LSL_Rotation(orot.X, orot.Y, orot.Z, orot.W));
11616
11617 LSL_Rotation objrot = GetPartRot(obj);
11618 ret.Add(objrot);
10383 break; 11619 break;
10384 case ScriptBaseClass.OBJECT_VELOCITY: 11620 case ScriptBaseClass.OBJECT_VELOCITY:
10385 ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z)); 11621 Vector3 ovel = obj.Velocity;
11622 ret.Add(new LSL_Vector(ovel.X, ovel.Y, ovel.Z));
10386 break; 11623 break;
10387 case ScriptBaseClass.OBJECT_OWNER: 11624 case ScriptBaseClass.OBJECT_OWNER:
10388 ret.Add(new LSL_String(obj.OwnerID.ToString())); 11625 ret.Add(new LSL_String(obj.OwnerID.ToString()));
@@ -10416,9 +11653,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10416 // The value returned in SL for normal prims is prim count 11653 // The value returned in SL for normal prims is prim count
10417 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount)); 11654 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
10418 break; 11655 break;
10419 // The following 3 costs I have intentionaly coded to return zero. They are part of 11656
10420 // "Land Impact" calculations. These calculations are probably not applicable 11657 // costs below may need to be diferent for root parts, need to check
10421 // to OpenSim and are not yet complete in SL
10422 case ScriptBaseClass.OBJECT_SERVER_COST: 11658 case ScriptBaseClass.OBJECT_SERVER_COST:
10423 // The linden calculation is here 11659 // The linden calculation is here
10424 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight 11660 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
@@ -10426,16 +11662,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10426 ret.Add(new LSL_Float(0)); 11662 ret.Add(new LSL_Float(0));
10427 break; 11663 break;
10428 case ScriptBaseClass.OBJECT_STREAMING_COST: 11664 case ScriptBaseClass.OBJECT_STREAMING_COST:
10429 // The linden calculation is here 11665 // The value returned in SL for normal prims is prim count * 0.06
10430 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost 11666 ret.Add(new LSL_Float(obj.StreamingCost));
10431 // The value returned in SL for normal prims looks like the prim count * 0.06
10432 ret.Add(new LSL_Float(0));
10433 break; 11667 break;
10434 case ScriptBaseClass.OBJECT_PHYSICS_COST: 11668 case ScriptBaseClass.OBJECT_PHYSICS_COST:
10435 // The linden calculation is here 11669 // The value returned in SL for normal prims is prim count
10436 // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics 11670 ret.Add(new LSL_Float(obj.PhysicsCost));
10437 // The value returned in SL for normal prims looks like the prim count
10438 ret.Add(new LSL_Float(0));
10439 break; 11671 break;
10440 default: 11672 default:
10441 // Invalid or unhandled constant. 11673 // Invalid or unhandled constant.
@@ -10628,15 +11860,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10628 return GetLinkPrimitiveParams(obj, rules); 11860 return GetLinkPrimitiveParams(obj, rules);
10629 } 11861 }
10630 11862
10631 public void print(string str) 11863 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10632 { 11864 {
10633 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11865 List<SceneObjectPart> parts = GetLinkParts(link);
10634 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11866 if (parts.Count < 1)
10635 if (ossl != null) 11867 return 0;
10636 { 11868
10637 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11869 return GetNumberOfSides(parts[0]);
10638 m_log.Info("LSL print():" + str);
10639 }
10640 } 11870 }
10641 11871
10642 private string Name2Username(string name) 11872 private string Name2Username(string name)
@@ -10682,6 +11912,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10682 return rq.ToString(); 11912 return rq.ToString();
10683 } 11913 }
10684 11914
11915 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11916 {
11917 m_SayShoutCount = 0;
11918 }
11919
10685 private struct Tri 11920 private struct Tri
10686 { 11921 {
10687 public Vector3 p1; 11922 public Vector3 p1;
@@ -10821,9 +12056,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10821 12056
10822 ContactResult result = new ContactResult (); 12057 ContactResult result = new ContactResult ();
10823 result.ConsumerID = group.LocalId; 12058 result.ConsumerID = group.LocalId;
10824 result.Depth = intersection.distance; 12059// result.Depth = intersection.distance;
10825 result.Normal = intersection.normal; 12060 result.Normal = intersection.normal;
10826 result.Pos = intersection.ipoint; 12061 result.Pos = intersection.ipoint;
12062 result.Depth = Vector3.Mag(rayStart - result.Pos);
10827 12063
10828 contacts.Add(result); 12064 contacts.Add(result);
10829 }); 12065 });
@@ -10956,6 +12192,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10956 12192
10957 return contacts[0]; 12193 return contacts[0];
10958 } 12194 }
12195/*
12196 // not done:
12197 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
12198 {
12199 ContactResult[] contacts = null;
12200 World.ForEachSOG(delegate(SceneObjectGroup group)
12201 {
12202 if (m_host.ParentGroup == group)
12203 return;
12204
12205 if (group.IsAttachment)
12206 return;
12207
12208 if(group.RootPart.PhysActor != null)
12209 return;
12210
12211 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
12212 });
12213 return contacts;
12214 }
12215*/
10959 12216
10960 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 12217 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
10961 { 12218 {
@@ -10997,32 +12254,96 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10997 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 12254 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
10998 12255
10999 12256
11000 if (checkTerrain) 12257 if (false)// World.SuportsRayCastFiltered())
11001 { 12258 {
11002 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); 12259 if (dist == 0)
11003 if (groundContact != null) 12260 return list;
11004 results.Add((ContactResult)groundContact);
11005 }
11006 12261
11007 if (checkAgents) 12262 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
11008 { 12263 if (checkTerrain)
11009 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); 12264 rayfilter |= RayFilterFlags.land;
11010 foreach (ContactResult r in agentHits) 12265// if (checkAgents)
11011 results.Add(r); 12266// rayfilter |= RayFilterFlags.agent;
11012 } 12267 if (checkPhysical)
12268 rayfilter |= RayFilterFlags.physical;
12269 if (checkNonPhysical)
12270 rayfilter |= RayFilterFlags.nonphysical;
12271 if (detectPhantom)
12272 rayfilter |= RayFilterFlags.LSLPhanton;
12273
12274 Vector3 direction = dir * ( 1/dist);
12275
12276 if(rayfilter == 0)
12277 {
12278 list.Add(new LSL_Integer(0));
12279 return list;
12280 }
11013 12281
11014 if (checkPhysical || checkNonPhysical || detectPhantom) 12282 // get some more contacts to sort ???
12283 int physcount = 4 * count;
12284 if (physcount > 20)
12285 physcount = 20;
12286
12287 object physresults;
12288 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
12289
12290 if (physresults == null)
12291 {
12292 list.Add(new LSL_Integer(-3)); // timeout error
12293 return list;
12294 }
12295
12296 results = (List<ContactResult>)physresults;
12297
12298 // for now physics doesn't detect sitted avatars so do it outside physics
12299 if (checkAgents)
12300 {
12301 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
12302 foreach (ContactResult r in agentHits)
12303 results.Add(r);
12304 }
12305
12306 // TODO: Replace this with a better solution. ObjectIntersection can only
12307 // detect nonphysical phantoms. They are detected by virtue of being
12308 // nonphysical (e.g. no PhysActor) so will not conflict with detecting
12309 // physicsl phantoms as done by the physics scene
12310 // We don't want anything else but phantoms here.
12311 if (detectPhantom)
12312 {
12313 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, false, false, true);
12314 foreach (ContactResult r in objectHits)
12315 results.Add(r);
12316 }
12317 }
12318 else
11015 { 12319 {
11016 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); 12320 if (checkTerrain)
11017 foreach (ContactResult r in objectHits) 12321 {
11018 results.Add(r); 12322 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
12323 if (groundContact != null)
12324 results.Add((ContactResult)groundContact);
12325 }
12326
12327 if (checkAgents)
12328 {
12329 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
12330 foreach (ContactResult r in agentHits)
12331 results.Add(r);
12332 }
12333
12334 if (checkPhysical || checkNonPhysical || detectPhantom)
12335 {
12336 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
12337 foreach (ContactResult r in objectHits)
12338 results.Add(r);
12339 }
11019 } 12340 }
11020 12341
11021 results.Sort(delegate(ContactResult a, ContactResult b) 12342 results.Sort(delegate(ContactResult a, ContactResult b)
11022 { 12343 {
11023 return a.Depth.CompareTo(b.Depth); 12344 return a.Depth.CompareTo(b.Depth);
11024 }); 12345 });
11025 12346
11026 int values = 0; 12347 int values = 0;
11027 SceneObjectGroup thisgrp = m_host.ParentGroup; 12348 SceneObjectGroup thisgrp = m_host.ParentGroup;
11028 12349
@@ -11115,7 +12436,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11115 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 12436 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
11116 if (!isAccount) return 0; 12437 if (!isAccount) return 0;
11117 if (estate.HasAccess(id)) return 1; 12438 if (estate.HasAccess(id)) return 1;
11118 if (estate.IsBanned(id)) 12439 if (estate.IsBanned(id, World.GetUserFlags(id)))
11119 estate.RemoveBan(id); 12440 estate.RemoveBan(id);
11120 estate.AddEstateUser(id); 12441 estate.AddEstateUser(id);
11121 break; 12442 break;
@@ -11134,14 +12455,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11134 break; 12455 break;
11135 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 12456 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
11136 if (!isAccount) return 0; 12457 if (!isAccount) return 0;
11137 if (estate.IsBanned(id)) return 1; 12458 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
11138 EstateBan ban = new EstateBan(); 12459 EstateBan ban = new EstateBan();
11139 ban.EstateID = estate.EstateID; 12460 ban.EstateID = estate.EstateID;
11140 ban.BannedUserID = id; 12461 ban.BannedUserID = id;
11141 estate.AddBan(ban); 12462 estate.AddBan(ban);
11142 break; 12463 break;
11143 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 12464 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
11144 if (!isAccount || !estate.IsBanned(id)) return 0; 12465 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
11145 estate.RemoveBan(id); 12466 estate.RemoveBan(id);
11146 break; 12467 break;
11147 default: return 0; 12468 default: return 0;
@@ -11170,7 +12491,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11170 return 16384; 12491 return 16384;
11171 } 12492 }
11172 12493
11173 public LSL_Integer llGetUsedMemory() 12494 public virtual LSL_Integer llGetUsedMemory()
11174 { 12495 {
11175 m_host.AddScriptLPS(1); 12496 m_host.AddScriptLPS(1);
11176 // The value returned for LSO scripts in SL 12497 // The value returned for LSO scripts in SL
@@ -11198,7 +12519,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11198 public void llSetSoundQueueing(int queue) 12519 public void llSetSoundQueueing(int queue)
11199 { 12520 {
11200 m_host.AddScriptLPS(1); 12521 m_host.AddScriptLPS(1);
11201 NotImplemented("llSetSoundQueueing");
11202 } 12522 }
11203 12523
11204 public void llCollisionSprite(string impact_sprite) 12524 public void llCollisionSprite(string impact_sprite)
@@ -11210,10 +12530,270 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11210 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12530 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
11211 { 12531 {
11212 m_host.AddScriptLPS(1); 12532 m_host.AddScriptLPS(1);
11213 NotImplemented("llGodLikeRezObject"); 12533
12534 if (!World.Permissions.IsGod(m_host.OwnerID))
12535 NotImplemented("llGodLikeRezObject");
12536
12537 AssetBase rezAsset = World.AssetService.Get(inventory);
12538 if (rezAsset == null)
12539 {
12540 llSay(0, "Asset not found");
12541 return;
12542 }
12543
12544 SceneObjectGroup group = null;
12545
12546 try
12547 {
12548 string xmlData = Utils.BytesToString(rezAsset.Data);
12549 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12550 }
12551 catch
12552 {
12553 llSay(0, "Asset not found");
12554 return;
12555 }
12556
12557 if (group == null)
12558 {
12559 llSay(0, "Asset not found");
12560 return;
12561 }
12562
12563 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12564 group.RootPart.AttachOffset = group.AbsolutePosition;
12565
12566 group.ResetIDs();
12567
12568 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12569 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12570 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12571 group.ScheduleGroupForFullUpdate();
12572
12573 // objects rezzed with this method are die_at_edge by default.
12574 group.RootPart.SetDieAtEdge(true);
12575
12576 group.ResumeScripts();
12577
12578 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12579 "object_rez", new Object[] {
12580 new LSL_String(
12581 group.RootPart.UUID.ToString()) },
12582 new DetectParams[0]));
12583 }
12584
12585 public LSL_String llTransferLindenDollars(string destination, int amount)
12586 {
12587 UUID txn = UUID.Random();
12588
12589 Util.FireAndForget(delegate(object x)
12590 {
12591 int replycode = 0;
12592 string replydata = destination + "," + amount.ToString();
12593
12594 try
12595 {
12596 TaskInventoryItem item = m_item;
12597 if (item == null)
12598 {
12599 replydata = "SERVICE_ERROR";
12600 return;
12601 }
12602
12603 m_host.AddScriptLPS(1);
12604
12605 if (item.PermsGranter == UUID.Zero)
12606 {
12607 replydata = "MISSING_PERMISSION_DEBIT";
12608 return;
12609 }
12610
12611 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
12612 {
12613 replydata = "MISSING_PERMISSION_DEBIT";
12614 return;
12615 }
12616
12617 UUID toID = new UUID();
12618
12619 if (!UUID.TryParse(destination, out toID))
12620 {
12621 replydata = "INVALID_AGENT";
12622 return;
12623 }
12624
12625 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
12626
12627 if (money == null)
12628 {
12629 replydata = "TRANSFERS_DISABLED";
12630 return;
12631 }
12632
12633 bool result = money.ObjectGiveMoney(
12634 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
12635
12636 if (result)
12637 {
12638 replycode = 1;
12639 return;
12640 }
12641
12642 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
12643 }
12644 finally
12645 {
12646 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
12647 "transaction_result", new Object[] {
12648 new LSL_String(txn.ToString()),
12649 new LSL_Integer(replycode),
12650 new LSL_String(replydata) },
12651 new DetectParams[0]));
12652 }
12653 });
12654
12655 return txn.ToString();
11214 } 12656 }
11215 12657
11216 #endregion 12658 #endregion
12659
12660 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12661 {
12662 SceneObjectGroup group = m_host.ParentGroup;
12663
12664 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12665 return;
12666 if (group.IsAttachment)
12667 return;
12668
12669 if (frames.Data.Length > 0) // We are getting a new motion
12670 {
12671 if (group.RootPart.KeyframeMotion != null)
12672 group.RootPart.KeyframeMotion.Stop();
12673 group.RootPart.KeyframeMotion = null;
12674
12675 int idx = 0;
12676
12677 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12678 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12679
12680 while (idx < options.Data.Length)
12681 {
12682 int option = (int)options.GetLSLIntegerItem(idx++);
12683 int remain = options.Data.Length - idx;
12684
12685 switch (option)
12686 {
12687 case ScriptBaseClass.KFM_MODE:
12688 if (remain < 1)
12689 break;
12690 int modeval = (int)options.GetLSLIntegerItem(idx++);
12691 switch(modeval)
12692 {
12693 case ScriptBaseClass.KFM_FORWARD:
12694 mode = KeyframeMotion.PlayMode.Forward;
12695 break;
12696 case ScriptBaseClass.KFM_REVERSE:
12697 mode = KeyframeMotion.PlayMode.Reverse;
12698 break;
12699 case ScriptBaseClass.KFM_LOOP:
12700 mode = KeyframeMotion.PlayMode.Loop;
12701 break;
12702 case ScriptBaseClass.KFM_PING_PONG:
12703 mode = KeyframeMotion.PlayMode.PingPong;
12704 break;
12705 }
12706 break;
12707 case ScriptBaseClass.KFM_DATA:
12708 if (remain < 1)
12709 break;
12710 int dataval = (int)options.GetLSLIntegerItem(idx++);
12711 data = (KeyframeMotion.DataFormat)dataval;
12712 break;
12713 }
12714 }
12715
12716 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12717
12718 idx = 0;
12719
12720 int elemLength = 2;
12721 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12722 elemLength = 3;
12723
12724 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12725 while (idx < frames.Data.Length)
12726 {
12727 int remain = frames.Data.Length - idx;
12728
12729 if (remain < elemLength)
12730 break;
12731
12732 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12733 frame.Position = null;
12734 frame.Rotation = null;
12735
12736 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12737 {
12738 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12739 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12740 }
12741 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12742 {
12743 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12744 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12745 }
12746
12747 float tempf = (float)frames.GetLSLFloatItem(idx++);
12748 frame.TimeMS = (int)(tempf * 1000.0f);
12749
12750 keyframes.Add(frame);
12751 }
12752
12753 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12754 group.RootPart.KeyframeMotion.Start();
12755 }
12756 else
12757 {
12758 if (group.RootPart.KeyframeMotion == null)
12759 return;
12760
12761 if (options.Data.Length == 0)
12762 {
12763 group.RootPart.KeyframeMotion.Stop();
12764 return;
12765 }
12766
12767 int code = (int)options.GetLSLIntegerItem(0);
12768
12769 int idx = 0;
12770
12771 while (idx < options.Data.Length)
12772 {
12773 int option = (int)options.GetLSLIntegerItem(idx++);
12774 int remain = options.Data.Length - idx;
12775
12776 switch (option)
12777 {
12778 case ScriptBaseClass.KFM_COMMAND:
12779 int cmd = (int)options.GetLSLIntegerItem(idx++);
12780 switch (cmd)
12781 {
12782 case ScriptBaseClass.KFM_CMD_PLAY:
12783 group.RootPart.KeyframeMotion.Start();
12784 break;
12785 case ScriptBaseClass.KFM_CMD_STOP:
12786 group.RootPart.KeyframeMotion.Stop();
12787 break;
12788 case ScriptBaseClass.KFM_CMD_PAUSE:
12789 group.RootPart.KeyframeMotion.Pause();
12790 break;
12791 }
12792 break;
12793 }
12794 }
12795 }
12796 }
11217 } 12797 }
11218 12798
11219 public class NotecardCache 12799 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 7385dd9..77b659b 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)
@@ -3213,4 +3261,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3213 ((LSL_Api)m_LSL_Api).DetachFromAvatar(); 3261 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3214 } 3262 }
3215 } 3263 }
3216} \ No newline at end of file 3264}
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 }