aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs3181
1 files changed, 2440 insertions, 741 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index ae92716..61e8a28 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -24,14 +24,16 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
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,52 @@ 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 DateTime m_lastSayShoutCheck;
119
120 private Dictionary<string, string> MovementAnimationsForLSL =
121 new Dictionary<string, string> {
122 {"FLY", "Flying"},
123 {"FLYSLOW", "FlyingSlow"},
124 {"HOVER_UP", "Hovering Up"},
125 {"HOVER_DOWN", "Hovering Down"},
126 {"HOVER", "Hovering"},
127 {"LAND", "Landing"},
128 {"FALLDOWN", "Falling Down"},
129 {"PREJUMP", "PreJumping"},
130 {"JUMP", "Jumping"},
131 {"STANDUP", "Standing Up"},
132 {"SOFT_LAND", "Soft Landing"},
133 {"STAND", "Standing"},
134 {"CROUCHWALK", "CrouchWalking"},
135 {"RUN", "Running"},
136 {"WALK", "Walking"},
137 {"CROUCH", "Crouching"},
138 {"TURNLEFT", "Turning Left"},
139 {"TURNRIGHT", "Turning Right"}
140 };
109 141
110 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 142 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
111 { 143 {
144/*
145 m_ShoutSayTimer = new Timer(1000);
146 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
147 m_ShoutSayTimer.AutoReset = true;
148 m_ShoutSayTimer.Start();
149*/
150 m_lastSayShoutCheck = DateTime.UtcNow;
151
112 m_ScriptEngine = ScriptEngine; 152 m_ScriptEngine = ScriptEngine;
113 m_host = host; 153 m_host = host;
114 m_item = item; 154 m_item = item;
155 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
115 156
116 LoadLimits(); // read script limits from config. 157 LoadLimits(); // read script limits from config.
117 158
@@ -171,6 +212,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
171 get { return m_ScriptEngine.World; } 212 get { return m_ScriptEngine.World; }
172 } 213 }
173 214
215 [DebuggerNonUserCode]
174 public void state(string newState) 216 public void state(string newState)
175 { 217 {
176 m_ScriptEngine.SetState(m_item.ItemID, newState); 218 m_ScriptEngine.SetState(m_item.ItemID, newState);
@@ -180,6 +222,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
180 /// Reset the named script. The script must be present 222 /// Reset the named script. The script must be present
181 /// in the same prim. 223 /// in the same prim.
182 /// </summary> 224 /// </summary>
225 [DebuggerNonUserCode]
183 public void llResetScript() 226 public void llResetScript()
184 { 227 {
185 m_host.AddScriptLPS(1); 228 m_host.AddScriptLPS(1);
@@ -242,6 +285,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
242 } 285 }
243 } 286 }
244 287
288 public List<ScenePresence> GetLinkAvatars(int linkType)
289 {
290 List<ScenePresence> ret = new List<ScenePresence>();
291 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
292 return ret;
293
294 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
295
296 switch (linkType)
297 {
298 case ScriptBaseClass.LINK_SET:
299 return avs;
300
301 case ScriptBaseClass.LINK_ROOT:
302 return ret;
303
304 case ScriptBaseClass.LINK_ALL_OTHERS:
305 return avs;
306
307 case ScriptBaseClass.LINK_ALL_CHILDREN:
308 return avs;
309
310 case ScriptBaseClass.LINK_THIS:
311 return ret;
312
313 default:
314 if (linkType < 0)
315 return ret;
316
317 int partCount = m_host.ParentGroup.GetPartCount();
318
319 if (linkType <= partCount)
320 {
321 return ret;
322 }
323 else
324 {
325 linkType = linkType - partCount;
326 if (linkType > avs.Count)
327 {
328 return ret;
329 }
330 else
331 {
332 ret.Add(avs[linkType-1]);
333 return ret;
334 }
335 }
336 }
337 }
338
245 public List<SceneObjectPart> GetLinkParts(int linkType) 339 public List<SceneObjectPart> GetLinkParts(int linkType)
246 { 340 {
247 return GetLinkParts(m_host, linkType); 341 return GetLinkParts(m_host, linkType);
@@ -250,6 +344,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
250 private List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) 344 private List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
251 { 345 {
252 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 346 List<SceneObjectPart> ret = new List<SceneObjectPart>();
347 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
348 return ret;
253 ret.Add(part); 349 ret.Add(part);
254 350
255 switch (linkType) 351 switch (linkType)
@@ -440,31 +536,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
440 536
441 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 537 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
442 538
443 /// <summary> 539 // Utility function for llRot2Euler
444 /// Convert an LSL rotation to a Euler vector. 540
445 /// </summary> 541 // normalize an angle between -PI and PI (-180 to +180 degrees)
446 /// <remarks> 542 protected double NormalizeAngle(double angle)
447 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
448 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
449 /// </remarks>
450 /// <param name="r"></param>
451 /// <returns></returns>
452 public LSL_Vector llRot2Euler(LSL_Rotation r)
453 { 543 {
454 m_host.AddScriptLPS(1); 544 if (angle > -Math.PI && angle < Math.PI)
545 return angle;
455 546
456 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 547 int numPis = (int)(Math.PI / angle);
457 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 548 double remainder = angle - Math.PI * numPis;
458 if (m == 0.0) return new LSL_Vector(); 549 if (numPis % 2 == 1)
459 double x = Math.Atan2(-v.y, v.z); 550 return Math.PI - angle;
460 double sin = v.x / m; 551 return remainder;
461 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. 552 }
462 double y = Math.Asin(sin);
463 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
464 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)));
465 double z = Math.Atan2(v.y, v.x);
466 553
467 return new LSL_Vector(x, y, z); 554 public LSL_Vector llRot2Euler(LSL_Rotation q1)
555 {
556 m_host.AddScriptLPS(1);
557 LSL_Vector eul = new LSL_Vector();
558
559 double sqw = q1.s*q1.s;
560 double sqx = q1.x*q1.x;
561 double sqy = q1.z*q1.z;
562 double sqz = q1.y*q1.y;
563 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
564 double test = q1.x*q1.z + q1.y*q1.s;
565 if (test > 0.4999*unit) { // singularity at north pole
566 eul.z = 2 * Math.Atan2(q1.x,q1.s);
567 eul.y = Math.PI/2;
568 eul.x = 0;
569 return eul;
570 }
571 if (test < -0.4999*unit) { // singularity at south pole
572 eul.z = -2 * Math.Atan2(q1.x,q1.s);
573 eul.y = -Math.PI/2;
574 eul.x = 0;
575 return eul;
576 }
577 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
578 eul.y = Math.Asin(2*test/unit);
579 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
580 return eul;
468 } 581 }
469 582
470 /* From wiki: 583 /* From wiki:
@@ -517,18 +630,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
517 m_host.AddScriptLPS(1); 630 m_host.AddScriptLPS(1);
518 631
519 double x,y,z,s; 632 double x,y,z,s;
520 633 v.x *= 0.5;
521 double c1 = Math.Cos(v.x * 0.5); 634 v.y *= 0.5;
522 double c2 = Math.Cos(v.y * 0.5); 635 v.z *= 0.5;
523 double c3 = Math.Cos(v.z * 0.5); 636 double c1 = Math.Cos(v.x);
524 double s1 = Math.Sin(v.x * 0.5); 637 double c2 = Math.Cos(v.y);
525 double s2 = Math.Sin(v.y * 0.5); 638 double c1c2 = c1 * c2;
526 double s3 = Math.Sin(v.z * 0.5); 639 double s1 = Math.Sin(v.x);
527 640 double s2 = Math.Sin(v.y);
528 x = s1 * c2 * c3 + c1 * s2 * s3; 641 double s1s2 = s1 * s2;
529 y = c1 * s2 * c3 - s1 * c2 * s3; 642 double c1s2 = c1 * s2;
530 z = s1 * s2 * c3 + c1 * c2 * s3; 643 double s1c2 = s1 * c2;
531 s = c1 * c2 * c3 - s1 * s2 * s3; 644 double c3 = Math.Cos(v.z);
645 double s3 = Math.Sin(v.z);
646
647 x = s1c2 * c3 + c1s2 * s3;
648 y = c1s2 * c3 - s1c2 * s3;
649 z = s1s2 * c3 + c1c2 * s3;
650 s = c1c2 * c3 - s1s2 * s3;
532 651
533 return new LSL_Rotation(x, y, z, s); 652 return new LSL_Rotation(x, y, z, s);
534 } 653 }
@@ -666,77 +785,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
666 { 785 {
667 //A and B should both be normalized 786 //A and B should both be normalized
668 m_host.AddScriptLPS(1); 787 m_host.AddScriptLPS(1);
669 LSL_Rotation rotBetween; 788 /* This method is more accurate than the SL one, and thus causes problems
670 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 789 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
671 // continue calculation. 790
672 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 791 double dotProduct = LSL_Vector.Dot(a, b);
792 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
793 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
794 double angle = Math.Acos(dotProduct / magProduct);
795 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
796 double s = Math.Sin(angle / 2);
797
798 double x = axis.x * s;
799 double y = axis.y * s;
800 double z = axis.z * s;
801 double w = Math.Cos(angle / 2);
802
803 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
804 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
805
806 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
807 */
808
809 // This method mimics the 180 errors found in SL
810 // See www.euclideanspace.com... angleBetween
811 LSL_Vector vec_a = a;
812 LSL_Vector vec_b = b;
813
814 // Eliminate zero length
815 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
816 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
817 if (vec_a_mag < 0.00001 ||
818 vec_b_mag < 0.00001)
673 { 819 {
674 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 820 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
675 } 821 }
676 else 822
823 // Normalize
824 vec_a = llVecNorm(vec_a);
825 vec_b = llVecNorm(vec_b);
826
827 // Calculate axis and rotation angle
828 LSL_Vector axis = vec_a % vec_b;
829 LSL_Float cos_theta = vec_a * vec_b;
830
831 // Check if parallel
832 if (cos_theta > 0.99999)
677 { 833 {
678 a = LSL_Vector.Norm(a); 834 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
679 b = LSL_Vector.Norm(b); 835 }
680 double dotProduct = LSL_Vector.Dot(a, b); 836
681 // There are two degenerate cases possible. These are for vectors 180 or 837 // Check if anti-parallel
682 // 0 degrees apart. These have to be detected and handled individually. 838 else if (cos_theta < -0.99999)
683 // 839 {
684 // Check for vectors 180 degrees apart. 840 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
685 // A dot product of -1 would mean the angle between vectors is 180 degrees. 841 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
686 if (dotProduct < -0.9999999f) 842 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
687 { 843 }
688 // First assume X axis is orthogonal to the vectors. 844 else // other rotation
689 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 845 {
690 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 846 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
691 // Check for near zero vector. A very small non-zero number here will create 847 axis = llVecNorm(axis);
692 // a rotation in an undesired direction. 848 double x, y, z, s, t;
693 if (LSL_Vector.Mag(orthoVector) > 0.0001) 849 s = Math.Cos(theta);
694 { 850 t = Math.Sin(theta);
695 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 851 x = axis.x * t;
696 } 852 y = axis.y * t;
697 // If the magnitude of the vector was near zero, then assume the X axis is not 853 z = axis.z * t;
698 // orthogonal and use the Z axis instead. 854 return new LSL_Rotation(x,y,z,s);
699 else
700 {
701 // Set 180 z rotation.
702 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
703 }
704 }
705 // Check for parallel vectors.
706 // A dot product of 1 would mean the angle between vectors is 0 degrees.
707 else if (dotProduct > 0.9999999f)
708 {
709 // Set zero rotation.
710 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
711 }
712 else
713 {
714 // All special checks have been performed so get the axis of rotation.
715 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
716 // Quarternion s value is the length of the unit vector + dot product.
717 double qs = 1.0 + dotProduct;
718 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
719 // Normalize the rotation.
720 double mag = LSL_Rotation.Mag(rotBetween);
721 // We shouldn't have to worry about a divide by zero here. The qs value will be
722 // non-zero because we already know if we're here, then the dotProduct is not -1 so
723 // qs will not be zero. Also, we've already handled the input vectors being zero so the
724 // crossProduct vector should also not be zero.
725 rotBetween.x = rotBetween.x / mag;
726 rotBetween.y = rotBetween.y / mag;
727 rotBetween.z = rotBetween.z / mag;
728 rotBetween.s = rotBetween.s / mag;
729 // Check for undefined values and set zero rotation if any found. This code might not actually be required
730 // any longer since zero vectors are checked for at the top.
731 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
732 {
733 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
734 }
735 }
736 } 855 }
737 return rotBetween;
738 } 856 }
739 857
740 public void llWhisper(int channelID, string text) 858 public void llWhisper(int channelID, string text)
741 { 859 {
742 m_host.AddScriptLPS(1); 860 m_host.AddScriptLPS(1);
@@ -752,10 +870,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
752 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text); 870 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
753 } 871 }
754 872
873 private void CheckSayShoutTime()
874 {
875 DateTime now = DateTime.UtcNow;
876 if ((now - m_lastSayShoutCheck).Ticks > 10000000) // 1sec
877 {
878 m_lastSayShoutCheck = now;
879 m_SayShoutCount = 0;
880 }
881 else
882 m_SayShoutCount++;
883 }
884
755 public void llSay(int channelID, string text) 885 public void llSay(int channelID, string text)
756 { 886 {
757 m_host.AddScriptLPS(1); 887 m_host.AddScriptLPS(1);
758 888
889 if (channelID == 0)
890// m_SayShoutCount++;
891 CheckSayShoutTime();
892
893 if (m_SayShoutCount >= 11)
894 ScriptSleep(2000);
895
759 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 896 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
760 { 897 {
761 Console.WriteLine(text); 898 Console.WriteLine(text);
@@ -778,6 +915,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
778 { 915 {
779 m_host.AddScriptLPS(1); 916 m_host.AddScriptLPS(1);
780 917
918 if (channelID == 0)
919// m_SayShoutCount++;
920 CheckSayShoutTime();
921
922 if (m_SayShoutCount >= 11)
923 ScriptSleep(2000);
924
781 if (text.Length > 1023) 925 if (text.Length > 1023)
782 text = text.Substring(0, 1023); 926 text = text.Substring(0, 1023);
783 927
@@ -809,22 +953,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
809 953
810 public void llRegionSayTo(string target, int channel, string msg) 954 public void llRegionSayTo(string target, int channel, string msg)
811 { 955 {
956 string error = String.Empty;
957
812 if (msg.Length > 1023) 958 if (msg.Length > 1023)
813 msg = msg.Substring(0, 1023); 959 msg = msg.Substring(0, 1023);
814 960
815 m_host.AddScriptLPS(1); 961 m_host.AddScriptLPS(1);
816 962
817 if (channel == ScriptBaseClass.DEBUG_CHANNEL)
818 {
819 return;
820 }
821
822 UUID TargetID; 963 UUID TargetID;
823 UUID.TryParse(target, out TargetID); 964 UUID.TryParse(target, out TargetID);
824 965
825 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 966 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
826 if (wComm != null) 967 if (wComm != null)
827 wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg); 968 if (!wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg, out error))
969 LSLError(error);
828 } 970 }
829 971
830 public LSL_Integer llListen(int channelID, string name, string ID, string msg) 972 public LSL_Integer llListen(int channelID, string name, string ID, string msg)
@@ -1080,10 +1222,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1080 return detectedParams.TouchUV; 1222 return detectedParams.TouchUV;
1081 } 1223 }
1082 1224
1225 [DebuggerNonUserCode]
1083 public virtual void llDie() 1226 public virtual void llDie()
1084 { 1227 {
1085 m_host.AddScriptLPS(1); 1228 m_host.AddScriptLPS(1);
1086 throw new SelfDeleteException(); 1229 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1087 } 1230 }
1088 1231
1089 public LSL_Float llGround(LSL_Vector offset) 1232 public LSL_Float llGround(LSL_Vector offset)
@@ -1154,6 +1297,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1154 1297
1155 public void llSetStatus(int status, int value) 1298 public void llSetStatus(int status, int value)
1156 { 1299 {
1300 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1301 return;
1157 m_host.AddScriptLPS(1); 1302 m_host.AddScriptLPS(1);
1158 1303
1159 int statusrotationaxis = 0; 1304 int statusrotationaxis = 0;
@@ -1177,6 +1322,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1177 if (!allow) 1322 if (!allow)
1178 return; 1323 return;
1179 1324
1325 if (m_host.ParentGroup.RootPart.PhysActor != null &&
1326 m_host.ParentGroup.RootPart.PhysActor.IsPhysical)
1327 return;
1328
1180 m_host.ScriptSetPhysicsStatus(true); 1329 m_host.ScriptSetPhysicsStatus(true);
1181 } 1330 }
1182 else 1331 else
@@ -1376,6 +1525,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1376 { 1525 {
1377 m_host.AddScriptLPS(1); 1526 m_host.AddScriptLPS(1);
1378 1527
1528 SetColor(m_host, color, face);
1529 }
1530
1531 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1532 {
1533 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1534 return;
1535
1536 Primitive.TextureEntry tex = part.Shape.Textures;
1537 Color4 texcolor;
1538 if (face >= 0 && face < GetNumberOfSides(part))
1539 {
1540 texcolor = tex.CreateFace((uint)face).RGBA;
1541 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1542 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1543 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1544 tex.FaceTextures[face].RGBA = texcolor;
1545 part.UpdateTextureEntry(tex.GetBytes());
1546 return;
1547 }
1548 else if (face == ScriptBaseClass.ALL_SIDES)
1549 {
1550 for (uint i = 0; i < GetNumberOfSides(part); i++)
1551 {
1552 if (tex.FaceTextures[i] != null)
1553 {
1554 texcolor = tex.FaceTextures[i].RGBA;
1555 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1556 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1557 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1558 tex.FaceTextures[i].RGBA = texcolor;
1559 }
1560 texcolor = tex.DefaultTexture.RGBA;
1561 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1562 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1563 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1564 tex.DefaultTexture.RGBA = texcolor;
1565 }
1566 part.UpdateTextureEntry(tex.GetBytes());
1567 return;
1568 }
1569
1379 if (face == ScriptBaseClass.ALL_SIDES) 1570 if (face == ScriptBaseClass.ALL_SIDES)
1380 face = SceneObjectPart.ALL_SIDES; 1571 face = SceneObjectPart.ALL_SIDES;
1381 1572
@@ -1384,6 +1575,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1384 1575
1385 public void SetTexGen(SceneObjectPart part, int face,int style) 1576 public void SetTexGen(SceneObjectPart part, int face,int style)
1386 { 1577 {
1578 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1579 return;
1580
1387 Primitive.TextureEntry tex = part.Shape.Textures; 1581 Primitive.TextureEntry tex = part.Shape.Textures;
1388 MappingType textype; 1582 MappingType textype;
1389 textype = MappingType.Default; 1583 textype = MappingType.Default;
@@ -1414,6 +1608,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1414 1608
1415 public void SetGlow(SceneObjectPart part, int face, float glow) 1609 public void SetGlow(SceneObjectPart part, int face, float glow)
1416 { 1610 {
1611 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1612 return;
1613
1417 Primitive.TextureEntry tex = part.Shape.Textures; 1614 Primitive.TextureEntry tex = part.Shape.Textures;
1418 if (face >= 0 && face < GetNumberOfSides(part)) 1615 if (face >= 0 && face < GetNumberOfSides(part))
1419 { 1616 {
@@ -1439,6 +1636,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1439 1636
1440 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1637 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1441 { 1638 {
1639 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1640 return;
1442 1641
1443 Shininess sval = new Shininess(); 1642 Shininess sval = new Shininess();
1444 1643
@@ -1489,6 +1688,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1489 1688
1490 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1689 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1491 { 1690 {
1691 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1692 return;
1693
1492 Primitive.TextureEntry tex = part.Shape.Textures; 1694 Primitive.TextureEntry tex = part.Shape.Textures;
1493 if (face >= 0 && face < GetNumberOfSides(part)) 1695 if (face >= 0 && face < GetNumberOfSides(part))
1494 { 1696 {
@@ -1549,13 +1751,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1549 m_host.AddScriptLPS(1); 1751 m_host.AddScriptLPS(1);
1550 1752
1551 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1753 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1552 1754 if (parts.Count > 0)
1553 foreach (SceneObjectPart part in parts) 1755 {
1554 SetAlpha(part, alpha, face); 1756 try
1757 {
1758 foreach (SceneObjectPart part in parts)
1759 SetAlpha(part, alpha, face);
1760 }
1761 finally
1762 {
1763 }
1764 }
1555 } 1765 }
1556 1766
1557 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1767 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1558 { 1768 {
1769 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1770 return;
1771
1559 Primitive.TextureEntry tex = part.Shape.Textures; 1772 Primitive.TextureEntry tex = part.Shape.Textures;
1560 Color4 texcolor; 1773 Color4 texcolor;
1561 if (face >= 0 && face < GetNumberOfSides(part)) 1774 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1608,7 +1821,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1608 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1821 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1609 float wind, float tension, LSL_Vector Force) 1822 float wind, float tension, LSL_Vector Force)
1610 { 1823 {
1611 if (part == null) 1824 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1612 return; 1825 return;
1613 1826
1614 if (flexi) 1827 if (flexi)
@@ -1642,7 +1855,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1642 /// <param name="falloff"></param> 1855 /// <param name="falloff"></param>
1643 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1856 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1644 { 1857 {
1645 if (part == null) 1858 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1646 return; 1859 return;
1647 1860
1648 if (light) 1861 if (light)
@@ -1675,11 +1888,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1675 Primitive.TextureEntry tex = part.Shape.Textures; 1888 Primitive.TextureEntry tex = part.Shape.Textures;
1676 Color4 texcolor; 1889 Color4 texcolor;
1677 LSL_Vector rgb = new LSL_Vector(); 1890 LSL_Vector rgb = new LSL_Vector();
1891 int nsides = GetNumberOfSides(part);
1892
1678 if (face == ScriptBaseClass.ALL_SIDES) 1893 if (face == ScriptBaseClass.ALL_SIDES)
1679 { 1894 {
1680 int i; 1895 int i;
1681 1896 for (i = 0; i < nsides; i++)
1682 for (i = 0 ; i < GetNumberOfSides(part); i++)
1683 { 1897 {
1684 texcolor = tex.GetFace((uint)i).RGBA; 1898 texcolor = tex.GetFace((uint)i).RGBA;
1685 rgb.x += texcolor.R; 1899 rgb.x += texcolor.R;
@@ -1687,14 +1901,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1687 rgb.z += texcolor.B; 1901 rgb.z += texcolor.B;
1688 } 1902 }
1689 1903
1690 rgb.x /= (float)GetNumberOfSides(part); 1904 float invnsides = 1.0f / (float)nsides;
1691 rgb.y /= (float)GetNumberOfSides(part); 1905
1692 rgb.z /= (float)GetNumberOfSides(part); 1906 rgb.x *= invnsides;
1907 rgb.y *= invnsides;
1908 rgb.z *= invnsides;
1693 1909
1694 return rgb; 1910 return rgb;
1695 } 1911 }
1696 1912 if (face >= 0 && face < nsides)
1697 if (face >= 0 && face < GetNumberOfSides(part))
1698 { 1913 {
1699 texcolor = tex.GetFace((uint)face).RGBA; 1914 texcolor = tex.GetFace((uint)face).RGBA;
1700 rgb.x = texcolor.R; 1915 rgb.x = texcolor.R;
@@ -1721,15 +1936,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1721 m_host.AddScriptLPS(1); 1936 m_host.AddScriptLPS(1);
1722 1937
1723 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1938 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1724 1939 if (parts.Count > 0)
1725 foreach (SceneObjectPart part in parts) 1940 {
1726 SetTexture(part, texture, face); 1941 try
1727 1942 {
1943 foreach (SceneObjectPart part in parts)
1944 SetTexture(part, texture, face);
1945 }
1946 finally
1947 {
1948 }
1949 }
1728 ScriptSleep(200); 1950 ScriptSleep(200);
1729 } 1951 }
1730 1952
1731 protected void SetTexture(SceneObjectPart part, string texture, int face) 1953 protected void SetTexture(SceneObjectPart part, string texture, int face)
1732 { 1954 {
1955 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1956 return;
1957
1733 UUID textureID = new UUID(); 1958 UUID textureID = new UUID();
1734 1959
1735 textureID = InventoryKey(texture, (int)AssetType.Texture); 1960 textureID = InventoryKey(texture, (int)AssetType.Texture);
@@ -1774,6 +1999,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1774 1999
1775 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 2000 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1776 { 2001 {
2002 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2003 return;
2004
1777 Primitive.TextureEntry tex = part.Shape.Textures; 2005 Primitive.TextureEntry tex = part.Shape.Textures;
1778 if (face >= 0 && face < GetNumberOfSides(part)) 2006 if (face >= 0 && face < GetNumberOfSides(part))
1779 { 2007 {
@@ -1810,6 +2038,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1810 2038
1811 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2039 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1812 { 2040 {
2041 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2042 return;
2043
1813 Primitive.TextureEntry tex = part.Shape.Textures; 2044 Primitive.TextureEntry tex = part.Shape.Textures;
1814 if (face >= 0 && face < GetNumberOfSides(part)) 2045 if (face >= 0 && face < GetNumberOfSides(part))
1815 { 2046 {
@@ -1846,6 +2077,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1846 2077
1847 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2078 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1848 { 2079 {
2080 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2081 return;
2082
1849 Primitive.TextureEntry tex = part.Shape.Textures; 2083 Primitive.TextureEntry tex = part.Shape.Textures;
1850 if (face >= 0 && face < GetNumberOfSides(part)) 2084 if (face >= 0 && face < GetNumberOfSides(part))
1851 { 2085 {
@@ -2016,24 +2250,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2016 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param> 2250 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param>
2017 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust) 2251 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
2018 { 2252 {
2019 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2253 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2254 return;
2255
2020 LSL_Vector currentPos = GetPartLocalPos(part); 2256 LSL_Vector currentPos = GetPartLocalPos(part);
2257 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos);
2021 2258
2022 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
2023 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
2024 2259
2025 if (part.ParentGroup.RootPart == part) 2260 if (part.ParentGroup.RootPart == part)
2026 { 2261 {
2027 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
2028 targetPos.z = ground;
2029 SceneObjectGroup parent = part.ParentGroup; 2262 SceneObjectGroup parent = part.ParentGroup;
2030 parent.UpdateGroupPosition(!adjust ? targetPos : 2263 if (!World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos))
2031 SetPosAdjust(currentPos, targetPos)); 2264 return;
2265 Util.FireAndForget(delegate(object x) {
2266 parent.UpdateGroupPosition((Vector3)toPos);
2267 });
2032 } 2268 }
2033 else 2269 else
2034 { 2270 {
2035 part.OffsetPosition = !adjust ? targetPos : 2271 part.OffsetPosition = (Vector3)toPos;
2036 SetPosAdjust(currentPos, targetPos);
2037 SceneObjectGroup parent = part.ParentGroup; 2272 SceneObjectGroup parent = part.ParentGroup;
2038 parent.HasGroupChanged = true; 2273 parent.HasGroupChanged = true;
2039 parent.ScheduleGroupForTerseUpdate(); 2274 parent.ScheduleGroupForTerseUpdate();
@@ -2066,13 +2301,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2066 else 2301 else
2067 { 2302 {
2068 if (part.ParentGroup.IsAttachment) 2303 if (part.ParentGroup.IsAttachment)
2069 {
2070 pos = part.AttachedPos; 2304 pos = part.AttachedPos;
2071 }
2072 else 2305 else
2073 {
2074 pos = part.AbsolutePosition; 2306 pos = part.AbsolutePosition;
2075 }
2076 } 2307 }
2077 2308
2078// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); 2309// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
@@ -2085,18 +2316,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2085 m_host.AddScriptLPS(1); 2316 m_host.AddScriptLPS(1);
2086 2317
2087 // try to let this work as in SL... 2318 // try to let this work as in SL...
2088 if (m_host.ParentID == 0) 2319 if (m_host.LinkNum < 2)
2089 { 2320 {
2090 // special case: If we are root, rotate complete SOG to new rotation 2321 // Special case: If we are root, rotate complete SOG to new
2322 // rotation.
2323 // We are root if the link number is 0 (single prim) or 1
2324 // (root prim). ParentID may be nonzero in attachments and
2325 // using it would cause attachments and HUDs to rotate
2326 // to the wrong positions.
2327
2091 SetRot(m_host, rot); 2328 SetRot(m_host, rot);
2092 } 2329 }
2093 else 2330 else
2094 { 2331 {
2095 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. 2332 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
2096 SceneObjectPart rootPart = m_host.ParentGroup.RootPart; 2333 SceneObjectPart rootPart;
2097 if (rootPart != null) // better safe than sorry 2334 if (m_host.ParentGroup != null) // better safe than sorry
2098 { 2335 {
2099 SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); 2336 rootPart = m_host.ParentGroup.RootPart;
2337 if (rootPart != null)
2338 SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot);
2100 } 2339 }
2101 } 2340 }
2102 2341
@@ -2112,25 +2351,46 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2112 2351
2113 protected void SetRot(SceneObjectPart part, Quaternion rot) 2352 protected void SetRot(SceneObjectPart part, Quaternion rot)
2114 { 2353 {
2115 part.UpdateRotation(rot); 2354 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2116 // Update rotation does not move the object in the physics scene if it's a linkset. 2355 return;
2117 2356
2118//KF: Do NOT use this next line if using ODE physics engine. This need a switch based on .ini Phys Engine type 2357 bool isroot = (part == part.ParentGroup.RootPart);
2119// part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition; 2358 bool isphys;
2120 2359
2121 // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line
2122 // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt
2123 // It's perfectly okay when the object is not an active physical body though.
2124 // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against
2125 // but only if the object is not physial and active. This is important for rotating doors.
2126 // without the absoluteposition = absoluteposition happening, the doors do not move in the physics
2127 // scene
2128 PhysicsActor pa = part.PhysActor; 2360 PhysicsActor pa = part.PhysActor;
2129 2361
2130 if (pa != null && !pa.IsPhysical) 2362 // keep using physactor ideia of isphysical
2363 // it should be SOP ideia of that
2364 // not much of a issue with ubitODE
2365 if (pa != null && pa.IsPhysical)
2366 isphys = true;
2367 else
2368 isphys = false;
2369
2370 // SL doesn't let scripts rotate root of physical linksets
2371 if (isroot && isphys)
2372 return;
2373
2374 part.UpdateRotation(rot);
2375
2376 // Update rotation does not move the object in the physics engine if it's a non physical linkset
2377 // so do a nasty update of parts positions if is a root part rotation
2378 if (isroot && pa != null) // with if above implies non physical root part
2131 { 2379 {
2132 part.ParentGroup.ResetChildPrimPhysicsPositions(); 2380 part.ParentGroup.ResetChildPrimPhysicsPositions();
2133 } 2381 }
2382 else // fix sitting avatars. This is only needed bc of how we link avas to child parts, not root part
2383 {
2384 List<ScenePresence> sittingavas = part.ParentGroup.GetLinkedAvatars();
2385 if (sittingavas.Count > 0)
2386 {
2387 foreach (ScenePresence av in sittingavas)
2388 {
2389 if (isroot || part.LocalId == av.ParentID)
2390 av.SendTerseUpdateToAllClients();
2391 }
2392 }
2393 }
2134 } 2394 }
2135 2395
2136 /// <summary> 2396 /// <summary>
@@ -2178,8 +2438,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2178 2438
2179 public LSL_Rotation llGetLocalRot() 2439 public LSL_Rotation llGetLocalRot()
2180 { 2440 {
2441 return GetPartLocalRot(m_host);
2442 }
2443
2444 private LSL_Rotation GetPartLocalRot(SceneObjectPart part)
2445 {
2181 m_host.AddScriptLPS(1); 2446 m_host.AddScriptLPS(1);
2182 return new LSL_Rotation(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W); 2447 Quaternion rot = part.RotationOffset;
2448 return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
2183 } 2449 }
2184 2450
2185 public void llSetForce(LSL_Vector force, int local) 2451 public void llSetForce(LSL_Vector force, int local)
@@ -2259,16 +2525,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2259 m_host.ApplyImpulse(v, local != 0); 2525 m_host.ApplyImpulse(v, local != 0);
2260 } 2526 }
2261 2527
2528
2262 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2529 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2263 { 2530 {
2264 m_host.AddScriptLPS(1); 2531 m_host.AddScriptLPS(1);
2265 m_host.ApplyAngularImpulse(force, local != 0); 2532 m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0);
2266 } 2533 }
2267 2534
2268 public void llSetTorque(LSL_Vector torque, int local) 2535 public void llSetTorque(LSL_Vector torque, int local)
2269 { 2536 {
2270 m_host.AddScriptLPS(1); 2537 m_host.AddScriptLPS(1);
2271 m_host.SetAngularImpulse(torque, local != 0); 2538 m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0);
2272 } 2539 }
2273 2540
2274 public LSL_Vector llGetTorque() 2541 public LSL_Vector llGetTorque()
@@ -2285,20 +2552,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2285 llSetTorque(torque, local); 2552 llSetTorque(torque, local);
2286 } 2553 }
2287 2554
2555 public void llSetVelocity(LSL_Vector vel, int local)
2556 {
2557 m_host.AddScriptLPS(1);
2558 m_host.SetVelocity(new Vector3((float)vel.x, (float)vel.y, (float)vel.z), local != 0);
2559 }
2560
2288 public LSL_Vector llGetVel() 2561 public LSL_Vector llGetVel()
2289 { 2562 {
2290 m_host.AddScriptLPS(1); 2563 m_host.AddScriptLPS(1);
2291 2564
2292 Vector3 vel; 2565 Vector3 vel = Vector3.Zero;
2293 2566
2294 if (m_host.ParentGroup.IsAttachment) 2567 if (m_host.ParentGroup.IsAttachment)
2295 { 2568 {
2296 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); 2569 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2297 vel = avatar.Velocity; 2570 if (avatar != null)
2571 vel = avatar.Velocity;
2298 } 2572 }
2299 else 2573 else
2300 { 2574 {
2301 vel = m_host.Velocity; 2575 vel = m_host.ParentGroup.RootPart.Velocity;
2302 } 2576 }
2303 2577
2304 return new LSL_Vector(vel.X, vel.Y, vel.Z); 2578 return new LSL_Vector(vel.X, vel.Y, vel.Z);
@@ -2310,10 +2584,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2310 return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z); 2584 return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z);
2311 } 2585 }
2312 2586
2587 public void llSetAngularVelocity(LSL_Vector avel, int local)
2588 {
2589 m_host.AddScriptLPS(1);
2590 m_host.SetAngularVelocity(new Vector3((float)avel.x, (float)avel.y, (float)avel.z), local != 0);
2591 }
2592
2313 public LSL_Vector llGetOmega() 2593 public LSL_Vector llGetOmega()
2314 { 2594 {
2315 m_host.AddScriptLPS(1); 2595 m_host.AddScriptLPS(1);
2316 return new LSL_Vector(m_host.AngularVelocity.X, m_host.AngularVelocity.Y, m_host.AngularVelocity.Z); 2596 Vector3 avel = m_host.AngularVelocity;
2597 return new LSL_Vector(avel.X, avel.Y, avel.Z);
2317 } 2598 }
2318 2599
2319 public LSL_Float llGetTimeOfDay() 2600 public LSL_Float llGetTimeOfDay()
@@ -2839,16 +3120,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2839 new_group.RootPart.UUID.ToString()) }, 3120 new_group.RootPart.UUID.ToString()) },
2840 new DetectParams[0])); 3121 new DetectParams[0]));
2841 3122
2842 float groupmass = new_group.GetMass(); 3123 // do recoil
3124 SceneObjectGroup hostgrp = m_host.ParentGroup;
3125 if (hostgrp == null)
3126 return;
3127
3128 if (hostgrp.IsAttachment) // don't recoil avatars
3129 return;
2843 3130
2844 PhysicsActor pa = new_group.RootPart.PhysActor; 3131 PhysicsActor pa = new_group.RootPart.PhysActor;
2845 3132
2846 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3133 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
2847 { 3134 {
2848 //Recoil. 3135 float groupmass = new_group.GetMass();
2849 llApplyImpulse(vel * groupmass, 0); 3136 vel *= -groupmass;
3137 llApplyImpulse(vel, 0);
2850 } 3138 }
2851 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3139 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3140 return;
3141
2852 }); 3142 });
2853 3143
2854 //ScriptSleep((int)((groupmass * velmag) / 10)); 3144 //ScriptSleep((int)((groupmass * velmag) / 10));
@@ -2863,35 +3153,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2863 public void llLookAt(LSL_Vector target, double strength, double damping) 3153 public void llLookAt(LSL_Vector target, double strength, double damping)
2864 { 3154 {
2865 m_host.AddScriptLPS(1); 3155 m_host.AddScriptLPS(1);
2866 // Determine where we are looking from
2867 LSL_Vector from = llGetPos();
2868 3156
2869 // Work out the normalised vector from the source to the target 3157 // Get the normalized vector to the target
2870 LSL_Vector delta = llVecNorm(target - from); 3158 LSL_Vector d1 = llVecNorm(target - llGetPos());
2871 LSL_Vector angle = new LSL_Vector(0,0,0);
2872 3159
2873 // Calculate the yaw 3160 // Get the bearing (yaw)
2874 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3161 LSL_Vector a1 = new LSL_Vector(0,0,0);
2875 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3162 a1.z = llAtan2(d1.y, d1.x);
2876 3163
2877 // Calculate pitch 3164 // Get the elevation (pitch)
2878 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3165 LSL_Vector a2 = new LSL_Vector(0,0,0);
3166 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2879 3167
2880 // we need to convert from a vector describing 3168 LSL_Rotation r1 = llEuler2Rot(a1);
2881 // the angles of rotation in radians into rotation value 3169 LSL_Rotation r2 = llEuler2Rot(a2);
2882 LSL_Rotation rot = llEuler2Rot(angle); 3170 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2883
2884 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2885 // set the rotation of the object, copy that behavior
2886 PhysicsActor pa = m_host.PhysActor;
2887 3171
2888 if (strength == 0 || pa == null || !pa.IsPhysical) 3172 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2889 { 3173 {
2890 llSetRot(rot); 3174 // Do nothing if either value is 0 (this has been checked in SL)
3175 if (strength <= 0.0 || damping <= 0.0)
3176 return;
3177
3178 llSetRot(r3 * r2 * r1);
2891 } 3179 }
2892 else 3180 else
2893 { 3181 {
2894 m_host.StartLookAt(rot, (float)strength, (float)damping); 3182 if (strength == 0)
3183 {
3184 llSetRot(r3 * r2 * r1);
3185 return;
3186 }
3187
3188 m_host.StartLookAt((Quaternion)(r3 * r2 * r1), (float)strength, (float)damping);
2895 } 3189 }
2896 } 3190 }
2897 3191
@@ -2937,17 +3231,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2937 } 3231 }
2938 else 3232 else
2939 { 3233 {
2940 if (m_host.IsRoot) 3234 // new SL always returns object mass
2941 { 3235// if (m_host.IsRoot)
3236// {
2942 return m_host.ParentGroup.GetMass(); 3237 return m_host.ParentGroup.GetMass();
2943 } 3238// }
2944 else 3239// else
2945 { 3240// {
2946 return m_host.GetMass(); 3241// return m_host.GetMass();
2947 } 3242// }
2948 } 3243 }
2949 } 3244 }
2950 3245
3246
3247 public LSL_Float llGetMassMKS()
3248 {
3249 return 100f * llGetMass();
3250 }
3251
2951 public void llCollisionFilter(string name, string id, int accept) 3252 public void llCollisionFilter(string name, string id, int accept)
2952 { 3253 {
2953 m_host.AddScriptLPS(1); 3254 m_host.AddScriptLPS(1);
@@ -2995,8 +3296,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2995 { 3296 {
2996 // Unregister controls from Presence 3297 // Unregister controls from Presence
2997 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID); 3298 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID);
2998 // Remove Take Control permission.
2999 m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3000 } 3299 }
3001 } 3300 }
3002 } 3301 }
@@ -3022,7 +3321,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3022 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3321 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3023 3322
3024 if (attachmentsModule != null) 3323 if (attachmentsModule != null)
3025 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, false); 3324 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, false);
3026 else 3325 else
3027 return false; 3326 return false;
3028 } 3327 }
@@ -3052,9 +3351,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3052 { 3351 {
3053 m_host.AddScriptLPS(1); 3352 m_host.AddScriptLPS(1);
3054 3353
3055// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3056// return;
3057
3058 if (m_item.PermsGranter != m_host.OwnerID) 3354 if (m_item.PermsGranter != m_host.OwnerID)
3059 return; 3355 return;
3060 3356
@@ -3097,6 +3393,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3097 3393
3098 public void llInstantMessage(string user, string message) 3394 public void llInstantMessage(string user, string message)
3099 { 3395 {
3396 UUID result;
3397 if (!UUID.TryParse(user, out result))
3398 {
3399 ShoutError("An invalid key was passed to llInstantMessage");
3400 ScriptSleep(2000);
3401 return;
3402 }
3403
3404
3100 m_host.AddScriptLPS(1); 3405 m_host.AddScriptLPS(1);
3101 3406
3102 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3407 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3111,14 +3416,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3111 UUID friendTransactionID = UUID.Random(); 3416 UUID friendTransactionID = UUID.Random();
3112 3417
3113 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3418 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3114 3419
3115 GridInstantMessage msg = new GridInstantMessage(); 3420 GridInstantMessage msg = new GridInstantMessage();
3116 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3421 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3117 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3422 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3118 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3423 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3119// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3424// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3120// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3425// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3121 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3426// DateTime dt = DateTime.UtcNow;
3427//
3428// // Ticks from UtcNow, but make it look like local. Evil, huh?
3429// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3430//
3431// try
3432// {
3433// // Convert that to the PST timezone
3434// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3435// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3436// }
3437// catch
3438// {
3439// // No logging here, as it could be VERY spammy
3440// }
3441//
3442// // And make it look local again to fool the unix time util
3443// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3444
3445 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3446
3122 //if (client != null) 3447 //if (client != null)
3123 //{ 3448 //{
3124 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3449 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3132,12 +3457,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3132 msg.message = message.Substring(0, 1024); 3457 msg.message = message.Substring(0, 1024);
3133 else 3458 else
3134 msg.message = message; 3459 msg.message = message;
3135 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3460 msg.dialog = (byte)19; // MessageFromObject
3136 msg.fromGroup = false;// fromGroup; 3461 msg.fromGroup = false;// fromGroup;
3137 msg.offline = (byte)0; //offline; 3462 msg.offline = (byte)0; //offline;
3138 msg.ParentEstateID = 0; //ParentEstateID; 3463 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3139 msg.Position = new Vector3(m_host.AbsolutePosition); 3464 msg.Position = new Vector3(m_host.AbsolutePosition);
3140 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3465 msg.RegionID = World.RegionInfo.RegionID.Guid;
3141 msg.binaryBucket 3466 msg.binaryBucket
3142 = Util.StringToBytes256( 3467 = Util.StringToBytes256(
3143 "{0}/{1}/{2}/{3}", 3468 "{0}/{1}/{2}/{3}",
@@ -3165,7 +3490,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3165 } 3490 }
3166 3491
3167 emailModule.SendEmail(m_host.UUID, address, subject, message); 3492 emailModule.SendEmail(m_host.UUID, address, subject, message);
3168 llSleep(EMAIL_PAUSE_TIME); 3493 ScriptSleep(EMAIL_PAUSE_TIME * 1000);
3169 } 3494 }
3170 3495
3171 public void llGetNextEmail(string address, string subject) 3496 public void llGetNextEmail(string address, string subject)
@@ -3411,7 +3736,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3411 implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3736 implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3412 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3737 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3413 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3738 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3739 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3414 ScriptBaseClass.PERMISSION_ATTACH; 3740 ScriptBaseClass.PERMISSION_ATTACH;
3741
3415 } 3742 }
3416 else 3743 else
3417 { 3744 {
@@ -3446,11 +3773,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3446 3773
3447 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3774 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3448 { 3775 {
3449 lock (m_host.TaskInventory) 3776 m_host.TaskInventory.LockItemsForWrite(true);
3450 { 3777 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3451 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3778 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3452 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3779 m_host.TaskInventory.LockItemsForWrite(false);
3453 }
3454 3780
3455 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3781 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3456 "run_time_permissions", new Object[] { 3782 "run_time_permissions", new Object[] {
@@ -3493,11 +3819,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3493 3819
3494 if (!m_waitingForScriptAnswer) 3820 if (!m_waitingForScriptAnswer)
3495 { 3821 {
3496 lock (m_host.TaskInventory) 3822 m_host.TaskInventory.LockItemsForWrite(true);
3497 { 3823 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3498 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3824 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3499 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 3825 m_host.TaskInventory.LockItemsForWrite(false);
3500 }
3501 3826
3502 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3827 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3503 m_waitingForScriptAnswer=true; 3828 m_waitingForScriptAnswer=true;
@@ -3526,14 +3851,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3526 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3851 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3527 llReleaseControls(); 3852 llReleaseControls();
3528 3853
3529 lock (m_host.TaskInventory) 3854 m_host.TaskInventory.LockItemsForWrite(true);
3530 { 3855 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3531 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 3856 m_host.TaskInventory.LockItemsForWrite(false);
3532 } 3857
3533 3858 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3534 m_ScriptEngine.PostScriptEvent( 3859 "run_time_permissions", new Object[] {
3535 m_item.ItemID, 3860 new LSL_Integer(answer) },
3536 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); 3861 new DetectParams[0]));
3537 } 3862 }
3538 3863
3539 public LSL_String llGetPermissionsKey() 3864 public LSL_String llGetPermissionsKey()
@@ -3572,14 +3897,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3572 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3897 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3573 { 3898 {
3574 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3899 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3575 3900 if (parts.Count > 0)
3576 foreach (SceneObjectPart part in parts) 3901 {
3577 part.SetFaceColorAlpha(face, color, null); 3902 try
3903 {
3904 foreach (SceneObjectPart part in parts)
3905 part.SetFaceColorAlpha(face, color, null);
3906 }
3907 finally
3908 {
3909 }
3910 }
3578 } 3911 }
3579 3912
3580 public void llCreateLink(string target, int parent) 3913 public void llCreateLink(string target, int parent)
3581 { 3914 {
3582 m_host.AddScriptLPS(1); 3915 m_host.AddScriptLPS(1);
3916
3583 UUID targetID; 3917 UUID targetID;
3584 3918
3585 if (!UUID.TryParse(target, out targetID)) 3919 if (!UUID.TryParse(target, out targetID))
@@ -3685,10 +4019,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3685 // Restructuring Multiple Prims. 4019 // Restructuring Multiple Prims.
3686 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4020 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3687 parts.Remove(parentPrim.RootPart); 4021 parts.Remove(parentPrim.RootPart);
3688 foreach (SceneObjectPart part in parts) 4022 if (parts.Count > 0)
3689 { 4023 {
3690 parentPrim.DelinkFromGroup(part.LocalId, true); 4024 try
4025 {
4026 foreach (SceneObjectPart part in parts)
4027 {
4028 parentPrim.DelinkFromGroup(part.LocalId, true);
4029 }
4030 }
4031 finally
4032 {
4033 }
3691 } 4034 }
4035
3692 parentPrim.HasGroupChanged = true; 4036 parentPrim.HasGroupChanged = true;
3693 parentPrim.ScheduleGroupForFullUpdate(); 4037 parentPrim.ScheduleGroupForFullUpdate();
3694 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4038 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3697,12 +4041,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3697 { 4041 {
3698 SceneObjectPart newRoot = parts[0]; 4042 SceneObjectPart newRoot = parts[0];
3699 parts.Remove(newRoot); 4043 parts.Remove(newRoot);
3700 foreach (SceneObjectPart part in parts) 4044
4045 try
3701 { 4046 {
3702 // Required for linking 4047 foreach (SceneObjectPart part in parts)
3703 part.ClearUpdateSchedule(); 4048 {
3704 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4049 part.ClearUpdateSchedule();
4050 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4051 }
3705 } 4052 }
4053 finally
4054 {
4055 }
4056
4057
3706 newRoot.ParentGroup.HasGroupChanged = true; 4058 newRoot.ParentGroup.HasGroupChanged = true;
3707 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4059 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3708 } 4060 }
@@ -3722,6 +4074,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3722 public void llBreakAllLinks() 4074 public void llBreakAllLinks()
3723 { 4075 {
3724 m_host.AddScriptLPS(1); 4076 m_host.AddScriptLPS(1);
4077
4078 TaskInventoryItem item = m_item;
4079
4080 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4081 && !m_automaticLinkPermission)
4082 {
4083 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4084 return;
4085 }
4086
3725 SceneObjectGroup parentPrim = m_host.ParentGroup; 4087 SceneObjectGroup parentPrim = m_host.ParentGroup;
3726 if (parentPrim.AttachmentPoint != 0) 4088 if (parentPrim.AttachmentPoint != 0)
3727 return; // Fail silently if attached 4089 return; // Fail silently if attached
@@ -3741,25 +4103,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3741 public LSL_String llGetLinkKey(int linknum) 4103 public LSL_String llGetLinkKey(int linknum)
3742 { 4104 {
3743 m_host.AddScriptLPS(1); 4105 m_host.AddScriptLPS(1);
3744 List<UUID> keytable = new List<UUID>();
3745 // parse for sitting avatare-uuids
3746 World.ForEachRootScenePresence(delegate(ScenePresence presence)
3747 {
3748 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
3749 keytable.Add(presence.UUID);
3750 });
3751
3752 int totalprims = m_host.ParentGroup.PrimCount + keytable.Count;
3753 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims)
3754 {
3755 return keytable[totalprims - linknum].ToString();
3756 }
3757
3758 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1)
3759 {
3760 return m_host.UUID.ToString();
3761 }
3762
3763 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); 4106 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3764 if (part != null) 4107 if (part != null)
3765 { 4108 {
@@ -3767,6 +4110,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3767 } 4110 }
3768 else 4111 else
3769 { 4112 {
4113 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4114 {
4115 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4116
4117 if (linknum < 0)
4118 return UUID.Zero.ToString();
4119
4120 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4121 if (avatars.Count > linknum)
4122 {
4123 return avatars[linknum].UUID.ToString();
4124 }
4125 }
3770 return UUID.Zero.ToString(); 4126 return UUID.Zero.ToString();
3771 } 4127 }
3772 } 4128 }
@@ -3866,17 +4222,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3866 m_host.AddScriptLPS(1); 4222 m_host.AddScriptLPS(1);
3867 int count = 0; 4223 int count = 0;
3868 4224
3869 lock (m_host.TaskInventory) 4225 m_host.TaskInventory.LockItemsForRead(true);
4226 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3870 { 4227 {
3871 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4228 if (inv.Value.Type == type || type == -1)
3872 { 4229 {
3873 if (inv.Value.Type == type || type == -1) 4230 count = count + 1;
3874 {
3875 count = count + 1;
3876 }
3877 } 4231 }
3878 } 4232 }
3879 4233
4234 m_host.TaskInventory.LockItemsForRead(false);
3880 return count; 4235 return count;
3881 } 4236 }
3882 4237
@@ -3885,16 +4240,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3885 m_host.AddScriptLPS(1); 4240 m_host.AddScriptLPS(1);
3886 ArrayList keys = new ArrayList(); 4241 ArrayList keys = new ArrayList();
3887 4242
3888 lock (m_host.TaskInventory) 4243 m_host.TaskInventory.LockItemsForRead(true);
4244 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3889 { 4245 {
3890 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4246 if (inv.Value.Type == type || type == -1)
3891 { 4247 {
3892 if (inv.Value.Type == type || type == -1) 4248 keys.Add(inv.Value.Name);
3893 {
3894 keys.Add(inv.Value.Name);
3895 }
3896 } 4249 }
3897 } 4250 }
4251 m_host.TaskInventory.LockItemsForRead(false);
3898 4252
3899 if (keys.Count == 0) 4253 if (keys.Count == 0)
3900 { 4254 {
@@ -3932,7 +4286,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3932 if (item == null) 4286 if (item == null)
3933 { 4287 {
3934 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4288 llSay(0, String.Format("Could not find object '{0}'", inventory));
3935 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4289 return;
4290// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3936 } 4291 }
3937 4292
3938 UUID objId = item.ItemID; 4293 UUID objId = item.ItemID;
@@ -3960,33 +4315,45 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3960 return; 4315 return;
3961 } 4316 }
3962 } 4317 }
4318
3963 // destination is an avatar 4319 // destination is an avatar
3964 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4320 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3965 4321
3966 if (agentItem == null) 4322 if (agentItem == null)
3967 return; 4323 return;
3968 4324
3969 if (m_TransferModule != null) 4325 byte[] bucket = new byte[1];
3970 { 4326 bucket[0] = (byte)item.Type;
3971 byte[] bucket = new byte[] { (byte)item.Type }; 4327 //byte[] objBytes = agentItem.ID.GetBytes();
4328 //Array.Copy(objBytes, 0, bucket, 1, 16);
3972 4329
3973 GridInstantMessage msg = new GridInstantMessage(World, 4330 GridInstantMessage msg = new GridInstantMessage(World,
3974 m_host.UUID, m_host.Name + ", an object owned by " + 4331 m_host.OwnerID, m_host.Name, destId,
3975 resolveName(m_host.OwnerID) + ",", destId, 4332 (byte)InstantMessageDialog.TaskInventoryOffered,
3976 (byte)InstantMessageDialog.TaskInventoryOffered, 4333 false, item.Name+". "+m_host.Name+" is located at "+
3977 false, item.Name + "\n" + m_host.Name + " is located at " + 4334 World.RegionInfo.RegionName+" "+
3978 World.RegionInfo.RegionName+" "+ 4335 m_host.AbsolutePosition.ToString(),
3979 m_host.AbsolutePosition.ToString(), 4336 agentItem.ID, true, m_host.AbsolutePosition,
3980 agentItem.ID, true, m_host.AbsolutePosition, 4337 bucket);
3981 bucket);
3982 4338
3983 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4339 ScenePresence sp;
3984 }
3985 4340
4341 if (World.TryGetScenePresence(destId, out sp))
4342 {
4343 sp.ControllingClient.SendInstantMessage(msg);
4344 }
4345 else
4346 {
4347 if (m_TransferModule != null)
4348 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4349 }
4350
4351 //This delay should only occur when giving inventory to avatars.
3986 ScriptSleep(3000); 4352 ScriptSleep(3000);
3987 } 4353 }
3988 } 4354 }
3989 4355
4356 [DebuggerNonUserCode]
3990 public void llRemoveInventory(string name) 4357 public void llRemoveInventory(string name)
3991 { 4358 {
3992 m_host.AddScriptLPS(1); 4359 m_host.AddScriptLPS(1);
@@ -4030,109 +4397,115 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4030 { 4397 {
4031 m_host.AddScriptLPS(1); 4398 m_host.AddScriptLPS(1);
4032 4399
4033 UUID uuid = (UUID)id; 4400 UUID uuid;
4034 PresenceInfo pinfo = null; 4401 if (UUID.TryParse(id, out uuid))
4035 UserAccount account;
4036
4037 UserInfoCacheEntry ce;
4038 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4039 { 4402 {
4040 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4403 PresenceInfo pinfo = null;
4041 if (account == null) 4404 UserAccount account;
4405
4406 UserInfoCacheEntry ce;
4407 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4042 { 4408 {
4043 m_userInfoCache[uuid] = null; // Cache negative 4409 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4044 return UUID.Zero.ToString(); 4410 if (account == null)
4045 } 4411 {
4412 m_userInfoCache[uuid] = null; // Cache negative
4413 return UUID.Zero.ToString();
4414 }
4046 4415
4047 4416
4048 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4417 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4049 if (pinfos != null && pinfos.Length > 0) 4418 if (pinfos != null && pinfos.Length > 0)
4050 {
4051 foreach (PresenceInfo p in pinfos)
4052 { 4419 {
4053 if (p.RegionID != UUID.Zero) 4420 foreach (PresenceInfo p in pinfos)
4054 { 4421 {
4055 pinfo = p; 4422 if (p.RegionID != UUID.Zero)
4423 {
4424 pinfo = p;
4425 }
4056 } 4426 }
4057 } 4427 }
4058 }
4059 4428
4060 ce = new UserInfoCacheEntry(); 4429 ce = new UserInfoCacheEntry();
4061 ce.time = Util.EnvironmentTickCount(); 4430 ce.time = Util.EnvironmentTickCount();
4062 ce.account = account; 4431 ce.account = account;
4063 ce.pinfo = pinfo; 4432 ce.pinfo = pinfo;
4064 } 4433 m_userInfoCache[uuid] = ce;
4065 else 4434 }
4066 { 4435 else
4067 if (ce == null) 4436 {
4068 return UUID.Zero.ToString(); 4437 if (ce == null)
4438 return UUID.Zero.ToString();
4069 4439
4070 account = ce.account; 4440 account = ce.account;
4071 pinfo = ce.pinfo; 4441 pinfo = ce.pinfo;
4072 } 4442 }
4073 4443
4074 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4444 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4075 {
4076 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4077 if (pinfos != null && pinfos.Length > 0)
4078 { 4445 {
4079 foreach (PresenceInfo p in pinfos) 4446 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4447 if (pinfos != null && pinfos.Length > 0)
4080 { 4448 {
4081 if (p.RegionID != UUID.Zero) 4449 foreach (PresenceInfo p in pinfos)
4082 { 4450 {
4083 pinfo = p; 4451 if (p.RegionID != UUID.Zero)
4452 {
4453 pinfo = p;
4454 }
4084 } 4455 }
4085 } 4456 }
4086 } 4457 else
4087 else 4458 pinfo = null;
4088 pinfo = null;
4089 4459
4090 ce.time = Util.EnvironmentTickCount(); 4460 ce.time = Util.EnvironmentTickCount();
4091 ce.pinfo = pinfo; 4461 ce.pinfo = pinfo;
4092 } 4462 }
4093 4463
4094 string reply = String.Empty; 4464 string reply = String.Empty;
4095 4465
4096 switch (data) 4466 switch (data)
4097 { 4467 {
4098 case 1: // DATA_ONLINE (0|1) 4468 case 1: // DATA_ONLINE (0|1)
4099 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4469 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4100 reply = "1"; 4470 reply = "1";
4101 else 4471 else
4102 reply = "0"; 4472 reply = "0";
4103 break; 4473 break;
4104 case 2: // DATA_NAME (First Last) 4474 case 2: // DATA_NAME (First Last)
4105 reply = account.FirstName + " " + account.LastName; 4475 reply = account.FirstName + " " + account.LastName;
4106 break; 4476 break;
4107 case 3: // DATA_BORN (YYYY-MM-DD) 4477 case 3: // DATA_BORN (YYYY-MM-DD)
4108 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4478 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4109 born = born.AddSeconds(account.Created); 4479 born = born.AddSeconds(account.Created);
4110 reply = born.ToString("yyyy-MM-dd"); 4480 reply = born.ToString("yyyy-MM-dd");
4111 break; 4481 break;
4112 case 4: // DATA_RATING (0,0,0,0,0,0) 4482 case 4: // DATA_RATING (0,0,0,0,0,0)
4113 reply = "0,0,0,0,0,0"; 4483 reply = "0,0,0,0,0,0";
4114 break; 4484 break;
4115 case 7: // DATA_USERLEVEL (integer) 4485 case 8: // DATA_PAYINFO (0|1|2|3)
4116 reply = account.UserLevel.ToString(); 4486 reply = "0";
4117 break; 4487 break;
4118 case 8: // DATA_PAYINFO (0|1|2|3) 4488 default:
4119 reply = "0"; 4489 return UUID.Zero.ToString(); // Raise no event
4120 break; 4490 }
4121 default:
4122 return UUID.Zero.ToString(); // Raise no event
4123 }
4124 4491
4125 UUID rq = UUID.Random(); 4492 UUID rq = UUID.Random();
4126 4493
4127 UUID tid = AsyncCommands. 4494 UUID tid = AsyncCommands.
4128 DataserverPlugin.RegisterRequest(m_host.LocalId, 4495 DataserverPlugin.RegisterRequest(m_host.LocalId,
4129 m_item.ItemID, rq.ToString()); 4496 m_item.ItemID, rq.ToString());
4130 4497
4131 AsyncCommands. 4498 AsyncCommands.
4132 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4499 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4133 4500
4134 ScriptSleep(100); 4501 ScriptSleep(100);
4135 return tid.ToString(); 4502 return tid.ToString();
4503 }
4504 else
4505 {
4506 ShoutError("Invalid UUID passed to llRequestAgentData.");
4507 }
4508 return "";
4136 } 4509 }
4137 4510
4138 public LSL_String llRequestInventoryData(string name) 4511 public LSL_String llRequestInventoryData(string name)
@@ -4189,13 +4562,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4189 if (UUID.TryParse(agent, out agentId)) 4562 if (UUID.TryParse(agent, out agentId))
4190 { 4563 {
4191 ScenePresence presence = World.GetScenePresence(agentId); 4564 ScenePresence presence = World.GetScenePresence(agentId);
4192 if (presence != null) 4565 if (presence != null && presence.PresenceType != PresenceType.Npc)
4193 { 4566 {
4567 // agent must not be a god
4568 if (presence.UserLevel >= 200) return;
4569
4194 // agent must be over the owners land 4570 // agent must be over the owners land
4195 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4571 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4196 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4572 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4197 { 4573 {
4198 World.TeleportClientHome(agentId, presence.ControllingClient); 4574 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4575 {
4576 // They can't be teleported home for some reason
4577 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4578 if (regionInfo != null)
4579 {
4580 World.RequestTeleportLocation(
4581 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4582 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4583 }
4584 }
4199 } 4585 }
4200 } 4586 }
4201 } 4587 }
@@ -4302,7 +4688,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4302 UUID av = new UUID(); 4688 UUID av = new UUID();
4303 if (!UUID.TryParse(agent,out av)) 4689 if (!UUID.TryParse(agent,out av))
4304 { 4690 {
4305 LSLError("First parameter to llDialog needs to be a key"); 4691 //LSLError("First parameter to llDialog needs to be a key");
4306 return; 4692 return;
4307 } 4693 }
4308 4694
@@ -4334,7 +4720,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4334 public void llCollisionSound(string impact_sound, double impact_volume) 4720 public void llCollisionSound(string impact_sound, double impact_volume)
4335 { 4721 {
4336 m_host.AddScriptLPS(1); 4722 m_host.AddScriptLPS(1);
4337 4723
4724 if(impact_sound == "")
4725 {
4726 m_host.CollisionSoundVolume = (float)impact_volume;
4727 m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
4728 m_host.CollisionSoundType = 0;
4729 return;
4730 }
4338 // TODO: Parameter check logic required. 4731 // TODO: Parameter check logic required.
4339 UUID soundId = UUID.Zero; 4732 UUID soundId = UUID.Zero;
4340 if (!UUID.TryParse(impact_sound, out soundId)) 4733 if (!UUID.TryParse(impact_sound, out soundId))
@@ -4347,6 +4740,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4347 4740
4348 m_host.CollisionSound = soundId; 4741 m_host.CollisionSound = soundId;
4349 m_host.CollisionSoundVolume = (float)impact_volume; 4742 m_host.CollisionSoundVolume = (float)impact_volume;
4743 m_host.CollisionSoundType = 1;
4350 } 4744 }
4351 4745
4352 public LSL_String llGetAnimation(string id) 4746 public LSL_String llGetAnimation(string id)
@@ -4360,14 +4754,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4360 4754
4361 if (m_host.RegionHandle == presence.RegionHandle) 4755 if (m_host.RegionHandle == presence.RegionHandle)
4362 { 4756 {
4363 Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames;
4364
4365 if (presence != null) 4757 if (presence != null)
4366 { 4758 {
4367 AnimationSet currentAnims = presence.Animator.Animations; 4759 if (presence.SitGround)
4368 string currentAnimationState = String.Empty; 4760 return "Sitting on Ground";
4369 if (animationstateNames.TryGetValue(currentAnims.DefaultAnimation.AnimID, out currentAnimationState)) 4761 if (presence.ParentID != 0 || presence.ParentUUID != UUID.Zero)
4370 return currentAnimationState; 4762 return "Sitting";
4763
4764 string movementAnimation = presence.Animator.CurrentMovementAnimation;
4765 string lslMovementAnimation;
4766
4767 if (MovementAnimationsForLSL.TryGetValue(movementAnimation, out lslMovementAnimation))
4768 return lslMovementAnimation;
4371 } 4769 }
4372 } 4770 }
4373 4771
@@ -4514,7 +4912,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4514 { 4912 {
4515 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4913 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4516 float distance_term = distance * distance * distance; // Script Energy 4914 float distance_term = distance * distance * distance; // Script Energy
4517 float pusher_mass = m_host.GetMass(); 4915 // use total object mass and not part
4916 float pusher_mass = m_host.ParentGroup.GetMass();
4518 4917
4519 float PUSH_ATTENUATION_DISTANCE = 17f; 4918 float PUSH_ATTENUATION_DISTANCE = 17f;
4520 float PUSH_ATTENUATION_SCALE = 5f; 4919 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4764,6 +5163,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4764 { 5163 {
4765 return item.AssetID.ToString(); 5164 return item.AssetID.ToString();
4766 } 5165 }
5166 m_host.TaskInventory.LockItemsForRead(false);
4767 5167
4768 return UUID.Zero.ToString(); 5168 return UUID.Zero.ToString();
4769 } 5169 }
@@ -4897,7 +5297,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4897 public LSL_Vector llGetCenterOfMass() 5297 public LSL_Vector llGetCenterOfMass()
4898 { 5298 {
4899 m_host.AddScriptLPS(1); 5299 m_host.AddScriptLPS(1);
4900 Vector3 center = m_host.GetGeometricCenter(); 5300 Vector3 center = m_host.GetCenterOfMass();
4901 return new LSL_Vector(center.X,center.Y,center.Z); 5301 return new LSL_Vector(center.X,center.Y,center.Z);
4902 } 5302 }
4903 5303
@@ -4916,14 +5316,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4916 { 5316 {
4917 m_host.AddScriptLPS(1); 5317 m_host.AddScriptLPS(1);
4918 5318
4919 if (src == null) 5319 return src.Length;
4920 {
4921 return 0;
4922 }
4923 else
4924 {
4925 return src.Length;
4926 }
4927 } 5320 }
4928 5321
4929 public LSL_Integer llList2Integer(LSL_List src, int index) 5322 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4994,7 +5387,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4994 else if (src.Data[index] is LSL_Float) 5387 else if (src.Data[index] is LSL_Float)
4995 return Convert.ToDouble(((LSL_Float)src.Data[index]).value); 5388 return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
4996 else if (src.Data[index] is LSL_String) 5389 else if (src.Data[index] is LSL_String)
4997 return Convert.ToDouble(((LSL_String)src.Data[index]).m_string); 5390 {
5391 string str = ((LSL_String) src.Data[index]).m_string;
5392 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5393 if (m != Match.Empty)
5394 {
5395 str = m.Value;
5396 double d = 0.0;
5397 if (!Double.TryParse(str, out d))
5398 return 0.0;
5399
5400 return d;
5401 }
5402 return 0.0;
5403 }
4998 return Convert.ToDouble(src.Data[index]); 5404 return Convert.ToDouble(src.Data[index]);
4999 } 5405 }
5000 catch (FormatException) 5406 catch (FormatException)
@@ -5294,7 +5700,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5294 } 5700 }
5295 } 5701 }
5296 } 5702 }
5297 else { 5703 else
5704 {
5298 object[] array = new object[src.Length]; 5705 object[] array = new object[src.Length];
5299 Array.Copy(src.Data, 0, array, 0, src.Length); 5706 Array.Copy(src.Data, 0, array, 0, src.Length);
5300 result = new LSL_List(array); 5707 result = new LSL_List(array);
@@ -5401,7 +5808,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5401 public LSL_Integer llGetRegionAgentCount() 5808 public LSL_Integer llGetRegionAgentCount()
5402 { 5809 {
5403 m_host.AddScriptLPS(1); 5810 m_host.AddScriptLPS(1);
5404 return new LSL_Integer(World.GetRootAgentCount()); 5811
5812 int count = 0;
5813 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5814 count++;
5815 });
5816
5817 return new LSL_Integer(count);
5405 } 5818 }
5406 5819
5407 public LSL_Vector llGetRegionCorner() 5820 public LSL_Vector llGetRegionCorner()
@@ -5634,6 +6047,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5634 flags |= ScriptBaseClass.AGENT_AWAY; 6047 flags |= ScriptBaseClass.AGENT_AWAY;
5635 } 6048 }
5636 6049
6050 UUID busy = new UUID("efcf670c-2d18-8128-973a-034ebc806b67");
6051 UUID[] anims = agent.Animator.GetAnimationArray();
6052 if (Array.Exists<UUID>(anims, a => { return a == busy; }))
6053 {
6054 flags |= ScriptBaseClass.AGENT_BUSY;
6055 }
6056
5637 // seems to get unset, even if in mouselook, when avatar is sitting on a prim??? 6057 // seems to get unset, even if in mouselook, when avatar is sitting on a prim???
5638 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) 6058 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
5639 { 6059 {
@@ -5681,6 +6101,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5681 flags |= ScriptBaseClass.AGENT_SITTING; 6101 flags |= ScriptBaseClass.AGENT_SITTING;
5682 } 6102 }
5683 6103
6104 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
6105 {
6106 flags |= ScriptBaseClass.AGENT_MALE;
6107 }
6108
5684 return flags; 6109 return flags;
5685 } 6110 }
5686 6111
@@ -5828,9 +6253,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5828 6253
5829 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6254 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5830 6255
5831 foreach (SceneObjectPart part in parts) 6256 try
6257 {
6258 foreach (SceneObjectPart part in parts)
6259 {
6260 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6261 }
6262 }
6263 finally
5832 { 6264 {
5833 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
5834 } 6265 }
5835 } 6266 }
5836 6267
@@ -5882,13 +6313,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5882 6313
5883 if (m_host.OwnerID == land.LandData.OwnerID) 6314 if (m_host.OwnerID == land.LandData.OwnerID)
5884 { 6315 {
5885 World.TeleportClientHome(agentID, presence.ControllingClient); 6316 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6317 presence.TeleportWithMomentum(pos, null);
6318 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5886 } 6319 }
5887 } 6320 }
5888 } 6321 }
5889 ScriptSleep(5000); 6322 ScriptSleep(5000);
5890 } 6323 }
5891 6324
6325 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6326 {
6327 return ParseString2List(str, separators, in_spacers, false);
6328 }
6329
5892 public LSL_Integer llOverMyLand(string id) 6330 public LSL_Integer llOverMyLand(string id)
5893 { 6331 {
5894 m_host.AddScriptLPS(1); 6332 m_host.AddScriptLPS(1);
@@ -5947,20 +6385,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5947 return agentSize; 6385 return agentSize;
5948 } 6386 }
5949 6387
5950 public LSL_Integer llSameGroup(string agent) 6388 public LSL_Integer llSameGroup(string id)
5951 { 6389 {
5952 m_host.AddScriptLPS(1); 6390 m_host.AddScriptLPS(1);
5953 UUID agentId = new UUID(); 6391 UUID uuid = new UUID();
5954 if (!UUID.TryParse(agent, out agentId)) 6392 if (!UUID.TryParse(id, out uuid))
5955 return new LSL_Integer(0);
5956 ScenePresence presence = World.GetScenePresence(agentId);
5957 if (presence == null || presence.IsChildAgent) // Return flase for child agents
5958 return new LSL_Integer(0); 6393 return new LSL_Integer(0);
5959 IClientAPI client = presence.ControllingClient; 6394
5960 if (m_host.GroupID == client.ActiveGroupId) 6395 // Check if it's a group key
6396 if (uuid == m_host.ParentGroup.RootPart.GroupID)
5961 return new LSL_Integer(1); 6397 return new LSL_Integer(1);
5962 else 6398
6399 // We got passed a UUID.Zero
6400 if (uuid == UUID.Zero)
6401 return new LSL_Integer(0);
6402
6403 // Handle the case where id names an avatar
6404 ScenePresence presence = World.GetScenePresence(uuid);
6405 if (presence != null)
6406 {
6407 if (presence.IsChildAgent)
6408 return new LSL_Integer(0);
6409
6410 IClientAPI client = presence.ControllingClient;
6411 if (m_host.ParentGroup.RootPart.GroupID == client.ActiveGroupId)
6412 return new LSL_Integer(1);
6413
6414 return new LSL_Integer(0);
6415 }
6416
6417 // Handle object case
6418 SceneObjectPart part = World.GetSceneObjectPart(uuid);
6419 if (part != null)
6420 {
6421 // This will handle both deed and non-deed and also the no
6422 // group case
6423 if (part.ParentGroup.RootPart.GroupID == m_host.ParentGroup.RootPart.GroupID)
6424 return new LSL_Integer(1);
6425
5963 return new LSL_Integer(0); 6426 return new LSL_Integer(0);
6427 }
6428
6429 return new LSL_Integer(0);
5964 } 6430 }
5965 6431
5966 public void llUnSit(string id) 6432 public void llUnSit(string id)
@@ -6085,7 +6551,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6085 return m_host.ParentGroup.AttachmentPoint; 6551 return m_host.ParentGroup.AttachmentPoint;
6086 } 6552 }
6087 6553
6088 public LSL_Integer llGetFreeMemory() 6554 public virtual LSL_Integer llGetFreeMemory()
6089 { 6555 {
6090 m_host.AddScriptLPS(1); 6556 m_host.AddScriptLPS(1);
6091 // Make scripts designed for LSO happy 6557 // Make scripts designed for LSO happy
@@ -6202,7 +6668,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6202 SetParticleSystem(m_host, rules); 6668 SetParticleSystem(m_host, rules);
6203 } 6669 }
6204 6670
6205 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { 6671 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6672 {
6206 6673
6207 6674
6208 if (rules.Length == 0) 6675 if (rules.Length == 0)
@@ -6516,6 +6983,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6516 6983
6517 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot) 6984 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot)
6518 { 6985 {
6986 // LSL quaternions can normalize to 0, normal Quaternions can't.
6987 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
6988 rot.s = 1; // ZERO_ROTATION = 0,0,0,1
6989
6519 part.SitTargetPosition = offset; 6990 part.SitTargetPosition = offset;
6520 part.SitTargetOrientation = rot; 6991 part.SitTargetOrientation = rot;
6521 part.ParentGroup.HasGroupChanged = true; 6992 part.ParentGroup.HasGroupChanged = true;
@@ -6671,13 +7142,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6671 UUID av = new UUID(); 7142 UUID av = new UUID();
6672 if (!UUID.TryParse(avatar,out av)) 7143 if (!UUID.TryParse(avatar,out av))
6673 { 7144 {
6674 LSLError("First parameter to llDialog needs to be a key"); 7145 //LSLError("First parameter to llDialog needs to be a key");
6675 return; 7146 return;
6676 } 7147 }
6677 if (buttons.Length < 1) 7148 if (buttons.Length < 1)
6678 { 7149 {
6679 LSLError("No less than 1 button can be shown"); 7150 buttons.Add("OK");
6680 return;
6681 } 7151 }
6682 if (buttons.Length > 12) 7152 if (buttons.Length > 12)
6683 { 7153 {
@@ -6694,7 +7164,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6694 } 7164 }
6695 if (buttons.Data[i].ToString().Length > 24) 7165 if (buttons.Data[i].ToString().Length > 24)
6696 { 7166 {
6697 LSLError("button label cannot be longer than 24 characters"); 7167 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6698 return; 7168 return;
6699 } 7169 }
6700 buts[i] = buttons.Data[i].ToString(); 7170 buts[i] = buttons.Data[i].ToString();
@@ -6761,9 +7231,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6761 return; 7231 return;
6762 } 7232 }
6763 7233
6764 // the rest of the permission checks are done in RezScript, so check the pin there as well 7234 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6765 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); 7235 if (dest != null)
7236 {
7237 if ((item.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7238 {
7239 // the rest of the permission checks are done in RezScript, so check the pin there as well
7240 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
6766 7241
7242 if ((item.BasePermissions & (uint)PermissionMask.Copy) == 0)
7243 m_host.Inventory.RemoveInventoryItem(item.ItemID);
7244 }
7245 }
6767 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7246 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6768 ScriptSleep(3000); 7247 ScriptSleep(3000);
6769 } 7248 }
@@ -6826,19 +7305,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6826 public LSL_String llMD5String(string src, int nonce) 7305 public LSL_String llMD5String(string src, int nonce)
6827 { 7306 {
6828 m_host.AddScriptLPS(1); 7307 m_host.AddScriptLPS(1);
6829 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7308 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6830 } 7309 }
6831 7310
6832 public LSL_String llSHA1String(string src) 7311 public LSL_String llSHA1String(string src)
6833 { 7312 {
6834 m_host.AddScriptLPS(1); 7313 m_host.AddScriptLPS(1);
6835 return Util.SHA1Hash(src).ToLower(); 7314 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6836 } 7315 }
6837 7316
6838 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7317 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6839 { 7318 {
6840 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7319 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6841 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7320 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7321 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7322 return shapeBlock;
6842 7323
6843 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7324 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6844 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7325 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6943,6 +7424,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6943 // Prim type box, cylinder and prism. 7424 // Prim type box, cylinder and prism.
6944 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) 7425 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)
6945 { 7426 {
7427 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7428 return;
7429
6946 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7430 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6947 ObjectShapePacket.ObjectDataBlock shapeBlock; 7431 ObjectShapePacket.ObjectDataBlock shapeBlock;
6948 7432
@@ -6996,6 +7480,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6996 // Prim type sphere. 7480 // Prim type sphere.
6997 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7481 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
6998 { 7482 {
7483 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7484 return;
7485
6999 ObjectShapePacket.ObjectDataBlock shapeBlock; 7486 ObjectShapePacket.ObjectDataBlock shapeBlock;
7000 7487
7001 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7488 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -7037,6 +7524,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7037 // Prim type torus, tube and ring. 7524 // Prim type torus, tube and ring.
7038 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) 7525 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)
7039 { 7526 {
7527 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7528 return;
7529
7040 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7530 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7041 ObjectShapePacket.ObjectDataBlock shapeBlock; 7531 ObjectShapePacket.ObjectDataBlock shapeBlock;
7042 7532
@@ -7172,6 +7662,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7172 // Prim type sculpt. 7662 // Prim type sculpt.
7173 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7663 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7174 { 7664 {
7665 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7666 return;
7667
7175 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7668 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7176 UUID sculptId; 7669 UUID sculptId;
7177 7670
@@ -7196,7 +7689,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7196 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7689 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7197 { 7690 {
7198 // default 7691 // default
7199 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7692 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7200 } 7693 }
7201 7694
7202 part.Shape.SetSculptProperties((byte)type, sculptId); 7695 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7213,48 +7706,131 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7213 ScriptSleep(200); 7706 ScriptSleep(200);
7214 } 7707 }
7215 7708
7216 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7709 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7217 { 7710 {
7218 m_host.AddScriptLPS(1); 7711 m_host.AddScriptLPS(1);
7219 7712
7220 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); 7713 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
7221 7714
7222 ScriptSleep(200); 7715 ScriptSleep(200);
7223 } 7716 }
7224 7717
7225 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7718 private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
7226 { 7719 {
7227 m_host.AddScriptLPS(1); 7720 List<object> parts = new List<object>();
7721 List<SceneObjectPart> prims = GetLinkParts(linknumber);
7722 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7723 foreach (SceneObjectPart p in prims)
7724 parts.Add(p);
7725 foreach (ScenePresence p in avatars)
7726 parts.Add(p);
7228 7727
7229 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); 7728 LSL_List remaining = null;
7729 uint rulesParsed = 0;
7730
7731 if (parts.Count > 0)
7732 {
7733 foreach (object part in parts)
7734 {
7735 if (part is SceneObjectPart)
7736 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7737 else
7738 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7739 }
7740
7741 while ((object)remaining != null && remaining.Length > 2)
7742 {
7743 linknumber = remaining.GetLSLIntegerItem(0);
7744 rules = remaining.GetSublist(1, -1);
7745 parts.Clear();
7746 prims = GetLinkParts(linknumber);
7747 avatars = GetLinkAvatars(linknumber);
7748 foreach (SceneObjectPart p in prims)
7749 parts.Add(p);
7750 foreach (ScenePresence p in avatars)
7751 parts.Add(p);
7752
7753 foreach (object part in parts)
7754 {
7755 if (part is SceneObjectPart)
7756 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7757 else
7758 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7759 }
7760 }
7761 }
7230 } 7762 }
7231 7763
7232 protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) 7764 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7765 float material_density, float material_friction,
7766 float material_restitution, float material_gravity_modifier)
7233 { 7767 {
7234 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7768 ExtraPhysicsData physdata = new ExtraPhysicsData();
7769 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7770 physdata.Density = part.Density;
7771 physdata.Friction = part.Friction;
7772 physdata.Bounce = part.Bounciness;
7773 physdata.GravitationModifier = part.GravityModifier;
7235 7774
7236 LSL_List remaining = null; 7775 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7237 uint rulesParsed = 0; 7776 physdata.Density = material_density;
7777 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7778 physdata.Friction = material_friction;
7779 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7780 physdata.Bounce = material_restitution;
7781 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7782 physdata.GravitationModifier = material_gravity_modifier;
7238 7783
7239 foreach (SceneObjectPart part in parts) 7784 part.UpdateExtraPhysics(physdata);
7240 remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); 7785 }
7241 7786
7242 while (remaining != null && remaining.Length > 2) 7787 public void llSetPhysicsMaterial(int material_bits,
7243 { 7788 float material_gravity_modifier, float material_restitution,
7244 linknumber = remaining.GetLSLIntegerItem(0); 7789 float material_friction, float material_density)
7245 rules = remaining.GetSublist(1, -1); 7790 {
7246 parts = GetLinkParts(linknumber); 7791 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7792 }
7247 7793
7248 foreach (SceneObjectPart part in parts) 7794 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7249 remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); 7795 {
7796 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
7797 llSetLinkPrimitiveParamsFast(linknumber, rules);
7798 ScriptSleep(200);
7799 }
7800
7801 // vector up using libomv (c&p from sop )
7802 // vector up rotated by r
7803 private Vector3 Zrot(Quaternion r)
7804 {
7805 double x, y, z, m;
7806
7807 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
7808 if (Math.Abs(1.0 - m) > 0.000001)
7809 {
7810 m = 1.0 / Math.Sqrt(m);
7811 r.X *= (float)m;
7812 r.Y *= (float)m;
7813 r.Z *= (float)m;
7814 r.W *= (float)m;
7250 } 7815 }
7816
7817 x = 2 * (r.X * r.Z + r.Y * r.W);
7818 y = 2 * (-r.X * r.W + r.Y * r.Z);
7819 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
7820
7821 return new Vector3((float)x, (float)y, (float)z);
7251 } 7822 }
7252 7823
7253 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) 7824 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
7254 { 7825 {
7826 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7827 return null;
7828
7255 int idx = 0; 7829 int idx = 0;
7256 int idxStart = 0; 7830 int idxStart = 0;
7257 7831
7832 SceneObjectGroup parentgrp = part.ParentGroup;
7833
7258 bool positionChanged = false; 7834 bool positionChanged = false;
7259 LSL_Vector currentPosition = GetPartLocalPos(part); 7835 LSL_Vector currentPosition = GetPartLocalPos(part);
7260 7836
@@ -7279,8 +7855,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7279 return null; 7855 return null;
7280 7856
7281 v=rules.GetVector3Item(idx++); 7857 v=rules.GetVector3Item(idx++);
7282 positionChanged = true;
7283 currentPosition = GetSetPosTarget(part, v, currentPosition); 7858 currentPosition = GetSetPosTarget(part, v, currentPosition);
7859 positionChanged = true;
7284 7860
7285 break; 7861 break;
7286 case (int)ScriptBaseClass.PRIM_SIZE: 7862 case (int)ScriptBaseClass.PRIM_SIZE:
@@ -7296,8 +7872,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7296 return null; 7872 return null;
7297 7873
7298 LSL_Rotation q = rules.GetQuaternionItem(idx++); 7874 LSL_Rotation q = rules.GetQuaternionItem(idx++);
7875 SceneObjectPart rootPart = parentgrp.RootPart;
7299 // try to let this work as in SL... 7876 // try to let this work as in SL...
7300 if (part.ParentID == 0) 7877 if (rootPart == part)
7301 { 7878 {
7302 // special case: If we are root, rotate complete SOG to new rotation 7879 // special case: If we are root, rotate complete SOG to new rotation
7303 SetRot(part, q); 7880 SetRot(part, q);
@@ -7305,7 +7882,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7305 else 7882 else
7306 { 7883 {
7307 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. 7884 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
7308 SceneObjectPart rootPart = part.ParentGroup.RootPart; 7885 // sounds like sl bug that we need to replicate
7309 SetRot(part, rootPart.RotationOffset * (Quaternion)q); 7886 SetRot(part, rootPart.RotationOffset * (Quaternion)q);
7310 } 7887 }
7311 7888
@@ -7557,7 +8134,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7557 return null; 8134 return null;
7558 8135
7559 string ph = rules.Data[idx++].ToString(); 8136 string ph = rules.Data[idx++].ToString();
7560 m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); 8137 parentgrp.ScriptSetPhantomStatus(ph.Equals("1"));
7561 8138
7562 break; 8139 break;
7563 8140
@@ -7575,12 +8152,42 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7575 part.ScriptSetPhysicsStatus(physics); 8152 part.ScriptSetPhysicsStatus(physics);
7576 break; 8153 break;
7577 8154
8155 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
8156 if (remain < 1)
8157 return null;
8158
8159 int shape_type = rules.GetLSLIntegerItem(idx++);
8160
8161 ExtraPhysicsData physdata = new ExtraPhysicsData();
8162 physdata.Density = part.Density;
8163 physdata.Bounce = part.Bounciness;
8164 physdata.GravitationModifier = part.GravityModifier;
8165 physdata.PhysShapeType = (PhysShapeType)shape_type;
8166
8167 part.UpdateExtraPhysics(physdata);
8168
8169 break;
8170
8171 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8172 if (remain < 5)
8173 return null;
8174
8175 int material_bits = rules.GetLSLIntegerItem(idx++);
8176 float material_density = (float)rules.GetLSLFloatItem(idx++);
8177 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8178 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8179 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8180
8181 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8182
8183 break;
8184
7578 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8185 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7579 if (remain < 1) 8186 if (remain < 1)
7580 return null; 8187 return null;
7581 string temp = rules.Data[idx++].ToString(); 8188 string temp = rules.Data[idx++].ToString();
7582 8189
7583 m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); 8190 parentgrp.ScriptSetTemporaryStatus(temp.Equals("1"));
7584 8191
7585 break; 8192 break;
7586 8193
@@ -7654,7 +8261,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7654 if (part.ParentGroup.RootPart == part) 8261 if (part.ParentGroup.RootPart == part)
7655 { 8262 {
7656 SceneObjectGroup parent = part.ParentGroup; 8263 SceneObjectGroup parent = part.ParentGroup;
7657 parent.UpdateGroupPosition(currentPosition); 8264 Util.FireAndForget(delegate(object x) {
8265 parent.UpdateGroupPosition(currentPosition);
8266 });
7658 } 8267 }
7659 else 8268 else
7660 { 8269 {
@@ -7699,10 +8308,91 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7699 8308
7700 public LSL_String llXorBase64Strings(string str1, string str2) 8309 public LSL_String llXorBase64Strings(string str1, string str2)
7701 { 8310 {
7702 m_host.AddScriptLPS(1); 8311 string b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7703 Deprecated("llXorBase64Strings"); 8312
7704 ScriptSleep(300); 8313 ScriptSleep(300);
7705 return String.Empty; 8314 m_host.AddScriptLPS(1);
8315
8316 if (str1 == String.Empty)
8317 return String.Empty;
8318 if (str2 == String.Empty)
8319 return str1;
8320
8321 int len = str2.Length;
8322 if ((len % 4) != 0) // LL is EVIL!!!!
8323 {
8324 while (str2.EndsWith("="))
8325 str2 = str2.Substring(0, str2.Length - 1);
8326
8327 len = str2.Length;
8328 int mod = len % 4;
8329
8330 if (mod == 1)
8331 str2 = str2.Substring(0, str2.Length - 1);
8332 else if (mod == 2)
8333 str2 += "==";
8334 else if (mod == 3)
8335 str2 += "=";
8336 }
8337
8338 byte[] data1;
8339 byte[] data2;
8340 try
8341 {
8342 data1 = Convert.FromBase64String(str1);
8343 data2 = Convert.FromBase64String(str2);
8344 }
8345 catch (Exception)
8346 {
8347 return new LSL_String(String.Empty);
8348 }
8349
8350 // For cases where the decoded length of s2 is greater
8351 // than the decoded length of s1, simply perform a normal
8352 // decode and XOR
8353 //
8354 if (data2.Length >= data1.Length)
8355 {
8356 for (int pos = 0 ; pos < data1.Length ; pos++ )
8357 data1[pos] ^= data2[pos];
8358
8359 return Convert.ToBase64String(data1);
8360 }
8361
8362 // Remove padding
8363 while (str1.EndsWith("="))
8364 str1 = str1.Substring(0, str1.Length - 1);
8365 while (str2.EndsWith("="))
8366 str2 = str2.Substring(0, str2.Length - 1);
8367
8368 byte[] d1 = new byte[str1.Length];
8369 byte[] d2 = new byte[str2.Length];
8370
8371 for (int i = 0 ; i < str1.Length ; i++)
8372 {
8373 int idx = b64.IndexOf(str1.Substring(i, 1));
8374 if (idx == -1)
8375 idx = 0;
8376 d1[i] = (byte)idx;
8377 }
8378
8379 for (int i = 0 ; i < str2.Length ; i++)
8380 {
8381 int idx = b64.IndexOf(str2.Substring(i, 1));
8382 if (idx == -1)
8383 idx = 0;
8384 d2[i] = (byte)idx;
8385 }
8386
8387 string output = String.Empty;
8388
8389 for (int pos = 0 ; pos < d1.Length ; pos++)
8390 output += b64[d1[pos] ^ d2[pos % d2.Length]];
8391
8392 while (output.Length % 3 > 0)
8393 output += "=";
8394
8395 return output;
7706 } 8396 }
7707 8397
7708 public void llRemoteDataSetRegion() 8398 public void llRemoteDataSetRegion()
@@ -7826,13 +8516,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7826 public LSL_Integer llGetNumberOfPrims() 8516 public LSL_Integer llGetNumberOfPrims()
7827 { 8517 {
7828 m_host.AddScriptLPS(1); 8518 m_host.AddScriptLPS(1);
7829 int avatarCount = 0; 8519 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7830 World.ForEachRootScenePresence(delegate(ScenePresence presence) 8520
7831 {
7832 if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID))
7833 avatarCount++;
7834 });
7835
7836 return m_host.ParentGroup.PrimCount + avatarCount; 8521 return m_host.ParentGroup.PrimCount + avatarCount;
7837 } 8522 }
7838 8523
@@ -7848,55 +8533,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7848 m_host.AddScriptLPS(1); 8533 m_host.AddScriptLPS(1);
7849 UUID objID = UUID.Zero; 8534 UUID objID = UUID.Zero;
7850 LSL_List result = new LSL_List(); 8535 LSL_List result = new LSL_List();
8536
8537 // If the ID is not valid, return null result
7851 if (!UUID.TryParse(obj, out objID)) 8538 if (!UUID.TryParse(obj, out objID))
7852 { 8539 {
7853 result.Add(new LSL_Vector()); 8540 result.Add(new LSL_Vector());
7854 result.Add(new LSL_Vector()); 8541 result.Add(new LSL_Vector());
7855 return result; 8542 return result;
7856 } 8543 }
8544
8545 // Check if this is an attached prim. If so, replace
8546 // the UUID with the avatar UUID and report it's bounding box
8547 SceneObjectPart part = World.GetSceneObjectPart(objID);
8548 if (part != null && part.ParentGroup.IsAttachment)
8549 objID = part.ParentGroup.AttachedAvatar;
8550
8551 // Find out if this is an avatar ID. If so, return it's box
7857 ScenePresence presence = World.GetScenePresence(objID); 8552 ScenePresence presence = World.GetScenePresence(objID);
7858 if (presence != null) 8553 if (presence != null)
7859 { 8554 {
7860 if (presence.ParentID == 0) // not sat on an object 8555 // As per LSL Wiki, there is no difference between sitting
8556 // and standing avatar since server 1.36
8557 LSL_Vector lower;
8558 LSL_Vector upper;
8559 if (presence.Animator.Animations.DefaultAnimation.AnimID
8560 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7861 { 8561 {
7862 LSL_Vector lower; 8562 // This is for ground sitting avatars
7863 LSL_Vector upper; 8563 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7864 if (presence.Animator.Animations.DefaultAnimation.AnimID 8564 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7865 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8565 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7866 {
7867 // This is for ground sitting avatars
7868 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7869 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7870 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7871 }
7872 else
7873 {
7874 // This is for standing/flying avatars
7875 float height = presence.Appearance.AvatarHeight / 2.0f;
7876 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7877 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7878 }
7879 result.Add(lower);
7880 result.Add(upper);
7881 return result;
7882 } 8566 }
7883 else 8567 else
7884 { 8568 {
7885 // sitting on an object so we need the bounding box of that 8569 // This is for standing/flying avatars
7886 // which should include the avatar so set the UUID to the 8570 float height = presence.Appearance.AvatarHeight / 2.0f;
7887 // UUID of the object the avatar is sat on and allow it to fall through 8571 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7888 // to processing an object 8572 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7889 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7890 objID = p.UUID;
7891 } 8573 }
8574
8575 // Adjust to the documented error offsets (see LSL Wiki)
8576 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8577 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8578
8579 if (lower.x > upper.x)
8580 lower.x = upper.x;
8581 if (lower.y > upper.y)
8582 lower.y = upper.y;
8583 if (lower.z > upper.z)
8584 lower.z = upper.z;
8585
8586 result.Add(lower);
8587 result.Add(upper);
8588 return result;
7892 } 8589 }
7893 SceneObjectPart part = World.GetSceneObjectPart(objID); 8590
8591 part = World.GetSceneObjectPart(objID);
7894 // Currently only works for single prims without a sitting avatar 8592 // Currently only works for single prims without a sitting avatar
7895 if (part != null) 8593 if (part != null)
7896 { 8594 {
7897 Vector3 halfSize = part.Scale / 2.0f; 8595 float minX;
7898 LSL_Vector lower = (new LSL_Vector(halfSize)) * -1.0f; 8596 float maxX;
7899 LSL_Vector upper = new LSL_Vector(halfSize); 8597 float minY;
8598 float maxY;
8599 float minZ;
8600 float maxZ;
8601
8602 // This BBox is in sim coordinates, with the offset being
8603 // a contained point.
8604 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8605 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8606
8607 minX -= offsets[0].X;
8608 maxX -= offsets[0].X;
8609 minY -= offsets[0].Y;
8610 maxY -= offsets[0].Y;
8611 minZ -= offsets[0].Z;
8612 maxZ -= offsets[0].Z;
8613
8614 LSL_Vector lower;
8615 LSL_Vector upper;
8616
8617 // Adjust to the documented error offsets (see LSL Wiki)
8618 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8619 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8620
8621 if (lower.x > upper.x)
8622 lower.x = upper.x;
8623 if (lower.y > upper.y)
8624 lower.y = upper.y;
8625 if (lower.z > upper.z)
8626 lower.z = upper.z;
8627
7900 result.Add(lower); 8628 result.Add(lower);
7901 result.Add(upper); 8629 result.Add(upper);
7902 return result; 8630 return result;
@@ -7910,7 +8638,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7910 8638
7911 public LSL_Vector llGetGeometricCenter() 8639 public LSL_Vector llGetGeometricCenter()
7912 { 8640 {
7913 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 8641 Vector3 tmp = m_host.GetGeometricCenter();
8642 return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
7914 } 8643 }
7915 8644
7916 public LSL_List llGetPrimitiveParams(LSL_List rules) 8645 public LSL_List llGetPrimitiveParams(LSL_List rules)
@@ -7938,24 +8667,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7938 { 8667 {
7939 m_host.AddScriptLPS(1); 8668 m_host.AddScriptLPS(1);
7940 8669
7941 List<SceneObjectPart> parts = GetLinkParts(linknumber); 8670 // acording to SL wiki this must indicate a single link number or link_root or link_this.
8671 // keep other options as before
7942 8672
8673 List<SceneObjectPart> parts;
8674 List<ScenePresence> avatars;
8675
7943 LSL_List res = new LSL_List(); 8676 LSL_List res = new LSL_List();
7944 LSL_List remaining = null; 8677 LSL_List remaining = null;
7945 8678
7946 foreach (SceneObjectPart part in parts) 8679 while (rules.Length > 0)
7947 {
7948 remaining = GetPrimParams(part, rules, ref res);
7949 }
7950
7951 while (remaining != null && remaining.Length > 2)
7952 { 8680 {
7953 linknumber = remaining.GetLSLIntegerItem(0);
7954 rules = remaining.GetSublist(1, -1);
7955 parts = GetLinkParts(linknumber); 8681 parts = GetLinkParts(linknumber);
8682 avatars = GetLinkAvatars(linknumber);
7956 8683
8684 remaining = null;
7957 foreach (SceneObjectPart part in parts) 8685 foreach (SceneObjectPart part in parts)
8686 {
7958 remaining = GetPrimParams(part, rules, ref res); 8687 remaining = GetPrimParams(part, rules, ref res);
8688 }
8689 foreach (ScenePresence avatar in avatars)
8690 {
8691 remaining = GetPrimParams(avatar, rules, ref res);
8692 }
8693
8694 if (remaining != null && remaining.Length > 0)
8695 {
8696 linknumber = remaining.GetLSLIntegerItem(0);
8697 rules = remaining.GetSublist(1, -1);
8698 }
7959 } 8699 }
7960 8700
7961 return res; 8701 return res;
@@ -8000,13 +8740,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8000 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8740 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
8001 part.AbsolutePosition.Y, 8741 part.AbsolutePosition.Y,
8002 part.AbsolutePosition.Z); 8742 part.AbsolutePosition.Z);
8003 // For some reason, the part.AbsolutePosition.* values do not change if the
8004 // linkset is rotated; they always reflect the child prim's world position
8005 // as though the linkset is unrotated. This is incompatible behavior with SL's
8006 // implementation, so will break scripts imported from there (not to mention it
8007 // makes it more difficult to determine a child prim's actual inworld position).
8008 if (part.ParentID != 0)
8009 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
8010 res.Add(v); 8743 res.Add(v);
8011 break; 8744 break;
8012 8745
@@ -8178,30 +8911,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8178 if (remain < 1) 8911 if (remain < 1)
8179 return null; 8912 return null;
8180 8913
8181 face=(int)rules.GetLSLIntegerItem(idx++); 8914 face = (int)rules.GetLSLIntegerItem(idx++);
8182 8915
8183 tex = part.Shape.Textures; 8916 tex = part.Shape.Textures;
8917 int shiny;
8184 if (face == ScriptBaseClass.ALL_SIDES) 8918 if (face == ScriptBaseClass.ALL_SIDES)
8185 { 8919 {
8186 for (face = 0; face < GetNumberOfSides(part); face++) 8920 for (face = 0; face < GetNumberOfSides(part); face++)
8187 { 8921 {
8188 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8922 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8189 // Convert Shininess to PRIM_SHINY_* 8923 if (shinyness == Shininess.High)
8190 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8924 {
8191 // PRIM_BUMP_* 8925 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8192 res.Add(new LSL_Integer((int)texface.Bump)); 8926 }
8927 else if (shinyness == Shininess.Medium)
8928 {
8929 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8930 }
8931 else if (shinyness == Shininess.Low)
8932 {
8933 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8934 }
8935 else
8936 {
8937 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8938 }
8939 res.Add(new LSL_Integer(shiny));
8940 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8193 } 8941 }
8194 } 8942 }
8195 else 8943 else
8196 { 8944 {
8197 if (face >= 0 && face < GetNumberOfSides(part)) 8945 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8946 if (shinyness == Shininess.High)
8198 { 8947 {
8199 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8948 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8200 // Convert Shininess to PRIM_SHINY_* 8949 }
8201 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8950 else if (shinyness == Shininess.Medium)
8202 // PRIM_BUMP_* 8951 {
8203 res.Add(new LSL_Integer((int)texface.Bump)); 8952 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8204 } 8953 }
8954 else if (shinyness == Shininess.Low)
8955 {
8956 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8957 }
8958 else
8959 {
8960 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8961 }
8962 res.Add(new LSL_Integer(shiny));
8963 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8205 } 8964 }
8206 break; 8965 break;
8207 8966
@@ -8209,24 +8968,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8209 if (remain < 1) 8968 if (remain < 1)
8210 return null; 8969 return null;
8211 8970
8212 face=(int)rules.GetLSLIntegerItem(idx++); 8971 face = (int)rules.GetLSLIntegerItem(idx++);
8213 8972
8214 tex = part.Shape.Textures; 8973 tex = part.Shape.Textures;
8974 int fullbright;
8215 if (face == ScriptBaseClass.ALL_SIDES) 8975 if (face == ScriptBaseClass.ALL_SIDES)
8216 { 8976 {
8217 for (face = 0; face < GetNumberOfSides(part); face++) 8977 for (face = 0; face < GetNumberOfSides(part); face++)
8218 { 8978 {
8219 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8979 if (tex.GetFace((uint)face).Fullbright == true)
8220 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 8980 {
8981 fullbright = ScriptBaseClass.TRUE;
8982 }
8983 else
8984 {
8985 fullbright = ScriptBaseClass.FALSE;
8986 }
8987 res.Add(new LSL_Integer(fullbright));
8221 } 8988 }
8222 } 8989 }
8223 else 8990 else
8224 { 8991 {
8225 if (face >= 0 && face < GetNumberOfSides(part)) 8992 if (tex.GetFace((uint)face).Fullbright == true)
8226 { 8993 {
8227 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8994 fullbright = ScriptBaseClass.TRUE;
8228 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
8229 } 8995 }
8996 else
8997 {
8998 fullbright = ScriptBaseClass.FALSE;
8999 }
9000 res.Add(new LSL_Integer(fullbright));
8230 } 9001 }
8231 break; 9002 break;
8232 9003
@@ -8248,27 +9019,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8248 break; 9019 break;
8249 9020
8250 case (int)ScriptBaseClass.PRIM_TEXGEN: 9021 case (int)ScriptBaseClass.PRIM_TEXGEN:
9022 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8251 if (remain < 1) 9023 if (remain < 1)
8252 return null; 9024 return null;
8253 9025
8254 face=(int)rules.GetLSLIntegerItem(idx++); 9026 face = (int)rules.GetLSLIntegerItem(idx++);
8255 9027
8256 tex = part.Shape.Textures; 9028 tex = part.Shape.Textures;
8257 if (face == ScriptBaseClass.ALL_SIDES) 9029 if (face == ScriptBaseClass.ALL_SIDES)
8258 { 9030 {
8259 for (face = 0; face < GetNumberOfSides(part); face++) 9031 for (face = 0; face < GetNumberOfSides(part); face++)
8260 { 9032 {
8261 MappingType texgen = tex.GetFace((uint)face).TexMapType; 9033 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8262 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 9034 {
8263 res.Add(new LSL_Integer((uint)texgen >> 1)); 9035 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
9036 }
9037 else
9038 {
9039 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
9040 }
8264 } 9041 }
8265 } 9042 }
8266 else 9043 else
8267 { 9044 {
8268 if (face >= 0 && face < GetNumberOfSides(part)) 9045 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8269 { 9046 {
8270 MappingType texgen = tex.GetFace((uint)face).TexMapType; 9047 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8271 res.Add(new LSL_Integer((uint)texgen >> 1)); 9048 }
9049 else
9050 {
9051 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8272 } 9052 }
8273 } 9053 }
8274 break; 9054 break;
@@ -8292,24 +9072,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8292 if (remain < 1) 9072 if (remain < 1)
8293 return null; 9073 return null;
8294 9074
8295 face=(int)rules.GetLSLIntegerItem(idx++); 9075 face = (int)rules.GetLSLIntegerItem(idx++);
8296 9076
8297 tex = part.Shape.Textures; 9077 tex = part.Shape.Textures;
9078 float primglow;
8298 if (face == ScriptBaseClass.ALL_SIDES) 9079 if (face == ScriptBaseClass.ALL_SIDES)
8299 { 9080 {
8300 for (face = 0; face < GetNumberOfSides(part); face++) 9081 for (face = 0; face < GetNumberOfSides(part); face++)
8301 { 9082 {
8302 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9083 primglow = tex.GetFace((uint)face).Glow;
8303 res.Add(new LSL_Float(texface.Glow)); 9084 res.Add(new LSL_Float(primglow));
8304 } 9085 }
8305 } 9086 }
8306 else 9087 else
8307 { 9088 {
8308 if (face >= 0 && face < GetNumberOfSides(part)) 9089 primglow = tex.GetFace((uint)face).Glow;
8309 { 9090 res.Add(new LSL_Float(primglow));
8310 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8311 res.Add(new LSL_Float(texface.Glow));
8312 }
8313 } 9091 }
8314 break; 9092 break;
8315 9093
@@ -8321,15 +9099,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8321 textColor.B)); 9099 textColor.B));
8322 res.Add(new LSL_Float(textColor.A)); 9100 res.Add(new LSL_Float(textColor.A));
8323 break; 9101 break;
9102
8324 case (int)ScriptBaseClass.PRIM_NAME: 9103 case (int)ScriptBaseClass.PRIM_NAME:
8325 res.Add(new LSL_String(part.Name)); 9104 res.Add(new LSL_String(part.Name));
8326 break; 9105 break;
9106
8327 case (int)ScriptBaseClass.PRIM_DESC: 9107 case (int)ScriptBaseClass.PRIM_DESC:
8328 res.Add(new LSL_String(part.Description)); 9108 res.Add(new LSL_String(part.Description));
8329 break; 9109 break;
9110
8330 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 9111 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8331 res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); 9112 res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W));
8332 break; 9113 break;
9114
8333 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 9115 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
8334 res.Add(new LSL_Vector(GetPartLocalPos(part))); 9116 res.Add(new LSL_Vector(GetPartLocalPos(part)));
8335 break; 9117 break;
@@ -8940,8 +9722,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8940 // The function returns an ordered list 9722 // The function returns an ordered list
8941 // representing the tokens found in the supplied 9723 // representing the tokens found in the supplied
8942 // sources string. If two successive tokenizers 9724 // sources string. If two successive tokenizers
8943 // are encountered, then a NULL entry is added 9725 // are encountered, then a null-string entry is
8944 // to the list. 9726 // added to the list.
8945 // 9727 //
8946 // It is a precondition that the source and 9728 // It is a precondition that the source and
8947 // toekizer lisst are non-null. If they are null, 9729 // toekizer lisst are non-null. If they are null,
@@ -8949,7 +9731,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8949 // while their lengths are being determined. 9731 // while their lengths are being determined.
8950 // 9732 //
8951 // A small amount of working memoryis required 9733 // A small amount of working memoryis required
8952 // of approximately 8*#tokenizers. 9734 // of approximately 8*#tokenizers + 8*srcstrlen.
8953 // 9735 //
8954 // There are many ways in which this function 9736 // There are many ways in which this function
8955 // can be implemented, this implementation is 9737 // can be implemented, this implementation is
@@ -8965,155 +9747,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8965 // and eliminates redundant tokenizers as soon 9747 // and eliminates redundant tokenizers as soon
8966 // as is possible. 9748 // as is possible.
8967 // 9749 //
8968 // The implementation tries to avoid any copying 9750 // The implementation tries to minimize temporary
8969 // of arrays or other objects. 9751 // garbage generation.
8970 // </remarks> 9752 // </remarks>
8971 9753
8972 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9754 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8973 { 9755 {
8974 int beginning = 0; 9756 return ParseString2List(src, separators, spacers, true);
8975 int srclen = src.Length; 9757 }
8976 int seplen = separators.Length;
8977 object[] separray = separators.Data;
8978 int spclen = spacers.Length;
8979 object[] spcarray = spacers.Data;
8980 int mlen = seplen+spclen;
8981
8982 int[] offset = new int[mlen+1];
8983 bool[] active = new bool[mlen];
8984
8985 int best;
8986 int j;
8987
8988 // Initial capacity reduces resize cost
8989 9758
8990 LSL_List tokens = new LSL_List(); 9759 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9760 {
9761 int srclen = src.Length;
9762 int seplen = separators.Length;
9763 object[] separray = separators.Data;
9764 int spclen = spacers.Length;
9765 object[] spcarray = spacers.Data;
9766 int dellen = 0;
9767 string[] delarray = new string[seplen+spclen];
8991 9768
8992 // All entries are initially valid 9769 int outlen = 0;
9770 string[] outarray = new string[srclen*2+1];
8993 9771
8994 for (int i = 0; i < mlen; i++) 9772 int i, j;
8995 active[i] = true; 9773 string d;
8996 9774
8997 offset[mlen] = srclen; 9775 m_host.AddScriptLPS(1);
8998 9776
8999 while (beginning < srclen) 9777 /*
9778 * Convert separator and spacer lists to C# strings.
9779 * Also filter out null strings so we don't hang.
9780 */
9781 for (i = 0; i < seplen; i ++)
9000 { 9782 {
9783 d = separray[i].ToString();
9784 if (d.Length > 0)
9785 {
9786 delarray[dellen++] = d;
9787 }
9788 }
9789 seplen = dellen;
9001 9790
9002 best = mlen; // as bad as it gets 9791 for (i = 0; i < spclen; i ++)
9792 {
9793 d = spcarray[i].ToString();
9794 if (d.Length > 0)
9795 {
9796 delarray[dellen++] = d;
9797 }
9798 }
9003 9799
9004 // Scan for separators 9800 /*
9801 * Scan through source string from beginning to end.
9802 */
9803 for (i = 0;;)
9804 {
9005 9805
9006 for (j = 0; j < seplen; j++) 9806 /*
9807 * Find earliest delimeter in src starting at i (if any).
9808 */
9809 int earliestDel = -1;
9810 int earliestSrc = srclen;
9811 string earliestStr = null;
9812 for (j = 0; j < dellen; j ++)
9007 { 9813 {
9008 if (separray[j].ToString() == String.Empty) 9814 d = delarray[j];
9009 active[j] = false; 9815 if (d != null)
9010
9011 if (active[j])
9012 { 9816 {
9013 // scan all of the markers 9817 int index = src.IndexOf(d, i);
9014 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9818 if (index < 0)
9015 { 9819 {
9016 // not present at all 9820 delarray[j] = null; // delim nowhere in src, don't check it anymore
9017 active[j] = false;
9018 } 9821 }
9019 else 9822 else if (index < earliestSrc)
9020 { 9823 {
9021 // present and correct 9824 earliestSrc = index; // where delimeter starts in source string
9022 if (offset[j] < offset[best]) 9825 earliestDel = j; // where delimeter is in delarray[]
9023 { 9826 earliestStr = d; // the delimeter string from delarray[]
9024 // closest so far 9827 if (index == i) break; // can't do any better than found at beg of string
9025 best = j;
9026 if (offset[best] == beginning)
9027 break;
9028 }
9029 } 9828 }
9030 } 9829 }
9031 } 9830 }
9032 9831
9033 // Scan for spacers 9832 /*
9034 9833 * Output source string starting at i through start of earliest delimeter.
9035 if (offset[best] != beginning) 9834 */
9835 if (keepNulls || (earliestSrc > i))
9036 { 9836 {
9037 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9837 outarray[outlen++] = src.Substring(i, earliestSrc - i);
9038 {
9039 if (spcarray[j-seplen].ToString() == String.Empty)
9040 active[j] = false;
9041
9042 if (active[j])
9043 {
9044 // scan all of the markers
9045 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
9046 {
9047 // not present at all
9048 active[j] = false;
9049 }
9050 else
9051 {
9052 // present and correct
9053 if (offset[j] < offset[best])
9054 {
9055 // closest so far
9056 best = j;
9057 }
9058 }
9059 }
9060 }
9061 } 9838 }
9062 9839
9063 // This is the normal exit from the scanning loop 9840 /*
9841 * If no delimeter found at or after i, we're done scanning.
9842 */
9843 if (earliestDel < 0) break;
9064 9844
9065 if (best == mlen) 9845 /*
9846 * If delimeter was a spacer, output the spacer.
9847 */
9848 if (earliestDel >= seplen)
9066 { 9849 {
9067 // no markers were found on this pass 9850 outarray[outlen++] = earliestStr;
9068 // so we're pretty much done
9069 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
9070 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
9071 break;
9072 } 9851 }
9073 9852
9074 // Otherwise we just add the newly delimited token 9853 /*
9075 // and recalculate where the search should continue. 9854 * Look at rest of src string following delimeter.
9076 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9855 */
9077 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9856 i = earliestSrc + earliestStr.Length;
9078
9079 if (best < seplen)
9080 {
9081 beginning = offset[best] + (separray[best].ToString()).Length;
9082 }
9083 else
9084 {
9085 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
9086 string str = spcarray[best - seplen].ToString();
9087 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
9088 tokens.Add(new LSL_String(str));
9089 }
9090 } 9857 }
9091 9858
9092 // This an awkward an not very intuitive boundary case. If the 9859 /*
9093 // last substring is a tokenizer, then there is an implied trailing 9860 * Make up an exact-sized output array suitable for an LSL_List object.
9094 // null list entry. Hopefully the single comparison will not be too 9861 */
9095 // arduous. Alternatively the 'break' could be replced with a return 9862 object[] outlist = new object[outlen];
9096 // but that's shabby programming. 9863 for (i = 0; i < outlen; i ++)
9097
9098 if ((beginning == srclen) && (keepNulls))
9099 { 9864 {
9100 if (srclen != 0) 9865 outlist[i] = new LSL_String(outarray[i]);
9101 tokens.Add(new LSL_String(""));
9102 } 9866 }
9103 9867 return new LSL_List(outlist);
9104 return tokens;
9105 }
9106
9107 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
9108 {
9109 m_host.AddScriptLPS(1);
9110 return this.ParseString(src, separators, spacers, false);
9111 }
9112
9113 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
9114 {
9115 m_host.AddScriptLPS(1);
9116 return this.ParseString(src, separators, spacers, true);
9117 } 9868 }
9118 9869
9119 public LSL_Integer llGetObjectPermMask(int mask) 9870 public LSL_Integer llGetObjectPermMask(int mask)
@@ -9208,6 +9959,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9208 case 4: 9959 case 4:
9209 return (int)item.NextPermissions; 9960 return (int)item.NextPermissions;
9210 } 9961 }
9962 m_host.TaskInventory.LockItemsForRead(false);
9211 9963
9212 return -1; 9964 return -1;
9213 } 9965 }
@@ -9398,9 +10150,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9398 { 10150 {
9399 try 10151 try
9400 { 10152 {
10153 /*
9401 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 10154 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
9402 if (obj != null) 10155 if (obj != null)
9403 return (double)obj.GetMass(); 10156 return (double)obj.GetMass();
10157 */
10158 // return total object mass
10159 SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
10160 if (obj != null)
10161 return obj.GetMass();
10162
9404 // the object is null so the key is for an avatar 10163 // the object is null so the key is for an avatar
9405 ScenePresence avatar = World.GetScenePresence(key); 10164 ScenePresence avatar = World.GetScenePresence(key);
9406 if (avatar != null) 10165 if (avatar != null)
@@ -9420,7 +10179,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9420 } 10179 }
9421 10180
9422 /// <summary> 10181 /// <summary>
9423 /// illListReplaceList removes the sub-list defined by the inclusive indices 10182 /// llListReplaceList removes the sub-list defined by the inclusive indices
9424 /// start and end and inserts the src list in its place. The inclusive 10183 /// start and end and inserts the src list in its place. The inclusive
9425 /// nature of the indices means that at least one element must be deleted 10184 /// nature of the indices means that at least one element must be deleted
9426 /// if the indices are within the bounds of the existing list. I.e. 2,2 10185 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9477,16 +10236,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9477 // based upon end. Note that if end exceeds the upper 10236 // based upon end. Note that if end exceeds the upper
9478 // bound in this case, the entire destination list 10237 // bound in this case, the entire destination list
9479 // is removed. 10238 // is removed.
9480 else 10239 else if (start == 0)
9481 { 10240 {
9482 if (end + 1 < dest.Length) 10241 if (end + 1 < dest.Length)
9483 {
9484 return src + dest.GetSublist(end + 1, -1); 10242 return src + dest.GetSublist(end + 1, -1);
9485 }
9486 else 10243 else
9487 {
9488 return src; 10244 return src;
9489 } 10245 }
10246 else // Start < 0
10247 {
10248 if (end + 1 < dest.Length)
10249 return dest.GetSublist(end + 1, -1);
10250 else
10251 return new LSL_List();
9490 } 10252 }
9491 } 10253 }
9492 // Finally, if start > end, we strip away a prefix and 10254 // Finally, if start > end, we strip away a prefix and
@@ -9537,17 +10299,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9537 int width = 0; 10299 int width = 0;
9538 int height = 0; 10300 int height = 0;
9539 10301
9540 ParcelMediaCommandEnum? commandToSend = null; 10302 uint commandToSend = 0;
9541 float time = 0.0f; // default is from start 10303 float time = 0.0f; // default is from start
9542 10304
9543 ScenePresence presence = null; 10305 ScenePresence presence = null;
9544 10306
9545 for (int i = 0; i < commandList.Data.Length; i++) 10307 for (int i = 0; i < commandList.Data.Length; i++)
9546 { 10308 {
9547 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10309 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9548 switch (command) 10310 switch (command)
9549 { 10311 {
9550 case ParcelMediaCommandEnum.Agent: 10312 case (uint)ParcelMediaCommandEnum.Agent:
9551 // we send only to one agent 10313 // we send only to one agent
9552 if ((i + 1) < commandList.Length) 10314 if ((i + 1) < commandList.Length)
9553 { 10315 {
@@ -9564,25 +10326,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9564 } 10326 }
9565 break; 10327 break;
9566 10328
9567 case ParcelMediaCommandEnum.Loop: 10329 case (uint)ParcelMediaCommandEnum.Loop:
9568 loop = 1; 10330 loop = 1;
9569 commandToSend = command; 10331 commandToSend = command;
9570 update = true; //need to send the media update packet to set looping 10332 update = true; //need to send the media update packet to set looping
9571 break; 10333 break;
9572 10334
9573 case ParcelMediaCommandEnum.Play: 10335 case (uint)ParcelMediaCommandEnum.Play:
9574 loop = 0; 10336 loop = 0;
9575 commandToSend = command; 10337 commandToSend = command;
9576 update = true; //need to send the media update packet to make sure it doesn't loop 10338 update = true; //need to send the media update packet to make sure it doesn't loop
9577 break; 10339 break;
9578 10340
9579 case ParcelMediaCommandEnum.Pause: 10341 case (uint)ParcelMediaCommandEnum.Pause:
9580 case ParcelMediaCommandEnum.Stop: 10342 case (uint)ParcelMediaCommandEnum.Stop:
9581 case ParcelMediaCommandEnum.Unload: 10343 case (uint)ParcelMediaCommandEnum.Unload:
9582 commandToSend = command; 10344 commandToSend = command;
9583 break; 10345 break;
9584 10346
9585 case ParcelMediaCommandEnum.Url: 10347 case (uint)ParcelMediaCommandEnum.Url:
9586 if ((i + 1) < commandList.Length) 10348 if ((i + 1) < commandList.Length)
9587 { 10349 {
9588 if (commandList.Data[i + 1] is LSL_String) 10350 if (commandList.Data[i + 1] is LSL_String)
@@ -9595,7 +10357,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9595 } 10357 }
9596 break; 10358 break;
9597 10359
9598 case ParcelMediaCommandEnum.Texture: 10360 case (uint)ParcelMediaCommandEnum.Texture:
9599 if ((i + 1) < commandList.Length) 10361 if ((i + 1) < commandList.Length)
9600 { 10362 {
9601 if (commandList.Data[i + 1] is LSL_String) 10363 if (commandList.Data[i + 1] is LSL_String)
@@ -9608,7 +10370,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9608 } 10370 }
9609 break; 10371 break;
9610 10372
9611 case ParcelMediaCommandEnum.Time: 10373 case (uint)ParcelMediaCommandEnum.Time:
9612 if ((i + 1) < commandList.Length) 10374 if ((i + 1) < commandList.Length)
9613 { 10375 {
9614 if (commandList.Data[i + 1] is LSL_Float) 10376 if (commandList.Data[i + 1] is LSL_Float)
@@ -9620,7 +10382,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9620 } 10382 }
9621 break; 10383 break;
9622 10384
9623 case ParcelMediaCommandEnum.AutoAlign: 10385 case (uint)ParcelMediaCommandEnum.AutoAlign:
9624 if ((i + 1) < commandList.Length) 10386 if ((i + 1) < commandList.Length)
9625 { 10387 {
9626 if (commandList.Data[i + 1] is LSL_Integer) 10388 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9634,7 +10396,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9634 } 10396 }
9635 break; 10397 break;
9636 10398
9637 case ParcelMediaCommandEnum.Type: 10399 case (uint)ParcelMediaCommandEnum.Type:
9638 if ((i + 1) < commandList.Length) 10400 if ((i + 1) < commandList.Length)
9639 { 10401 {
9640 if (commandList.Data[i + 1] is LSL_String) 10402 if (commandList.Data[i + 1] is LSL_String)
@@ -9647,7 +10409,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9647 } 10409 }
9648 break; 10410 break;
9649 10411
9650 case ParcelMediaCommandEnum.Desc: 10412 case (uint)ParcelMediaCommandEnum.Desc:
9651 if ((i + 1) < commandList.Length) 10413 if ((i + 1) < commandList.Length)
9652 { 10414 {
9653 if (commandList.Data[i + 1] is LSL_String) 10415 if (commandList.Data[i + 1] is LSL_String)
@@ -9660,7 +10422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9660 } 10422 }
9661 break; 10423 break;
9662 10424
9663 case ParcelMediaCommandEnum.Size: 10425 case (uint)ParcelMediaCommandEnum.Size:
9664 if ((i + 2) < commandList.Length) 10426 if ((i + 2) < commandList.Length)
9665 { 10427 {
9666 if (commandList.Data[i + 1] is LSL_Integer) 10428 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9730,7 +10492,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9730 } 10492 }
9731 } 10493 }
9732 10494
9733 if (commandToSend != null) 10495 if (commandToSend != 0)
9734 { 10496 {
9735 // the commandList contained a start/stop/... command, too 10497 // the commandList contained a start/stop/... command, too
9736 if (presence == null) 10498 if (presence == null)
@@ -9767,7 +10529,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9767 10529
9768 if (aList.Data[i] != null) 10530 if (aList.Data[i] != null)
9769 { 10531 {
9770 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10532 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9771 { 10533 {
9772 case ParcelMediaCommandEnum.Url: 10534 case ParcelMediaCommandEnum.Url:
9773 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10535 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
@@ -9824,15 +10586,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9824 10586
9825 if (quick_pay_buttons.Data.Length < 4) 10587 if (quick_pay_buttons.Data.Length < 4)
9826 { 10588 {
9827 LSLError("List must have at least 4 elements"); 10589 int x;
9828 return; 10590 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10591 {
10592 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10593 }
9829 } 10594 }
9830 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10595 int[] nPrice = new int[5];
9831 10596 nPrice[0] = price;
9832 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10597 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9833 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10598 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9834 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10599 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9835 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10600 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10601 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9836 m_host.ParentGroup.HasGroupChanged = true; 10602 m_host.ParentGroup.HasGroupChanged = true;
9837 } 10603 }
9838 10604
@@ -9849,7 +10615,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9849 return new LSL_Vector(); 10615 return new LSL_Vector();
9850 } 10616 }
9851 10617
9852 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10618// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10619 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9853 if (presence != null) 10620 if (presence != null)
9854 { 10621 {
9855 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); 10622 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
@@ -9871,7 +10638,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9871 return new LSL_Rotation(); 10638 return new LSL_Rotation();
9872 } 10639 }
9873 10640
9874 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10641// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10642 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9875 if (presence != null) 10643 if (presence != null)
9876 { 10644 {
9877 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); 10645 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W);
@@ -9931,14 +10699,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9931 { 10699 {
9932 m_host.AddScriptLPS(1); 10700 m_host.AddScriptLPS(1);
9933 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 10701 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
9934 if (detectedParams == null) return; // only works on the first detected avatar 10702 if (detectedParams == null)
9935 10703 {
10704 if (m_host.ParentGroup.IsAttachment == true)
10705 {
10706 detectedParams = new DetectParams();
10707 detectedParams.Key = m_host.OwnerID;
10708 }
10709 else
10710 {
10711 return;
10712 }
10713 }
10714
9936 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10715 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9937 if (avatar != null) 10716 if (avatar != null)
9938 { 10717 {
9939 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, 10718 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name,
9940 simname, pos, lookAt); 10719 simname, pos, lookAt);
9941 } 10720 }
10721
9942 ScriptSleep(1000); 10722 ScriptSleep(1000);
9943 } 10723 }
9944 10724
@@ -10062,12 +10842,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10062 10842
10063 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10843 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
10064 object[] data = rules.Data; 10844 object[] data = rules.Data;
10065 for (int i = 0; i < data.Length; ++i) { 10845 for (int i = 0; i < data.Length; ++i)
10846 {
10066 int type = Convert.ToInt32(data[i++].ToString()); 10847 int type = Convert.ToInt32(data[i++].ToString());
10067 if (i >= data.Length) break; // odd number of entries => ignore the last 10848 if (i >= data.Length) break; // odd number of entries => ignore the last
10068 10849
10069 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10850 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
10070 switch (type) { 10851 switch (type)
10852 {
10071 case ScriptBaseClass.CAMERA_FOCUS: 10853 case ScriptBaseClass.CAMERA_FOCUS:
10072 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10854 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
10073 case ScriptBaseClass.CAMERA_POSITION: 10855 case ScriptBaseClass.CAMERA_POSITION:
@@ -10173,19 +10955,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10173 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 10955 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
10174 { 10956 {
10175 m_host.AddScriptLPS(1); 10957 m_host.AddScriptLPS(1);
10176 string ret = String.Empty; 10958
10177 string src1 = llBase64ToString(str1); 10959 if (str1 == String.Empty)
10178 string src2 = llBase64ToString(str2); 10960 return String.Empty;
10179 int c = 0; 10961 if (str2 == String.Empty)
10180 for (int i = 0; i < src1.Length; i++) 10962 return str1;
10963
10964 int len = str2.Length;
10965 if ((len % 4) != 0) // LL is EVIL!!!!
10181 { 10966 {
10182 ret += (char) (src1[i] ^ src2[c]); 10967 while (str2.EndsWith("="))
10968 str2 = str2.Substring(0, str2.Length - 1);
10183 10969
10184 c++; 10970 len = str2.Length;
10185 if (c >= src2.Length) 10971 int mod = len % 4;
10186 c = 0; 10972
10973 if (mod == 1)
10974 str2 = str2.Substring(0, str2.Length - 1);
10975 else if (mod == 2)
10976 str2 += "==";
10977 else if (mod == 3)
10978 str2 += "=";
10187 } 10979 }
10188 return llStringToBase64(ret); 10980
10981 byte[] data1;
10982 byte[] data2;
10983 try
10984 {
10985 data1 = Convert.FromBase64String(str1);
10986 data2 = Convert.FromBase64String(str2);
10987 }
10988 catch (Exception)
10989 {
10990 return new LSL_String(String.Empty);
10991 }
10992
10993 byte[] d2 = new Byte[data1.Length];
10994 int pos = 0;
10995
10996 if (data1.Length <= data2.Length)
10997 {
10998 Array.Copy(data2, 0, d2, 0, data1.Length);
10999 }
11000 else
11001 {
11002 while (pos < data1.Length)
11003 {
11004 len = data1.Length - pos;
11005 if (len > data2.Length)
11006 len = data2.Length;
11007
11008 Array.Copy(data2, 0, d2, pos, len);
11009 pos += len;
11010 }
11011 }
11012
11013 for (pos = 0 ; pos < data1.Length ; pos++ )
11014 data1[pos] ^= d2[pos];
11015
11016 return Convert.ToBase64String(data1);
10189 } 11017 }
10190 11018
10191 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 11019 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10238,16 +11066,72 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10238 if (userAgent != null) 11066 if (userAgent != null)
10239 httpHeaders["User-Agent"] = userAgent; 11067 httpHeaders["User-Agent"] = userAgent;
10240 11068
11069 // See if the URL contains any header hacks
11070 string[] urlParts = url.Split(new char[] {'\n'});
11071 if (urlParts.Length > 1)
11072 {
11073 // Iterate the passed headers and parse them
11074 for (int i = 1 ; i < urlParts.Length ; i++ )
11075 {
11076 // The rest of those would be added to the body in SL.
11077 // Let's not do that.
11078 if (urlParts[i] == String.Empty)
11079 break;
11080
11081 // See if this could be a valid header
11082 string[] headerParts = urlParts[i].Split(new char[] {':'}, 2);
11083 if (headerParts.Length != 2)
11084 continue;
11085
11086 string headerName = headerParts[0].Trim();
11087 string headerValue = headerParts[1].Trim();
11088
11089 // Filter out headers that could be used to abuse
11090 // another system or cloak the request
11091 if (headerName.ToLower() == "x-secondlife-shard" ||
11092 headerName.ToLower() == "x-secondlife-object-name" ||
11093 headerName.ToLower() == "x-secondlife-object-key" ||
11094 headerName.ToLower() == "x-secondlife-region" ||
11095 headerName.ToLower() == "x-secondlife-local-position" ||
11096 headerName.ToLower() == "x-secondlife-local-velocity" ||
11097 headerName.ToLower() == "x-secondlife-local-rotation" ||
11098 headerName.ToLower() == "x-secondlife-owner-name" ||
11099 headerName.ToLower() == "x-secondlife-owner-key" ||
11100 headerName.ToLower() == "connection" ||
11101 headerName.ToLower() == "content-length" ||
11102 headerName.ToLower() == "from" ||
11103 headerName.ToLower() == "host" ||
11104 headerName.ToLower() == "proxy-authorization" ||
11105 headerName.ToLower() == "referer" ||
11106 headerName.ToLower() == "trailer" ||
11107 headerName.ToLower() == "transfer-encoding" ||
11108 headerName.ToLower() == "via" ||
11109 headerName.ToLower() == "authorization")
11110 continue;
11111
11112 httpHeaders[headerName] = headerValue;
11113 }
11114
11115 // Finally, strip any protocol specifier from the URL
11116 url = urlParts[0].Trim();
11117 int idx = url.IndexOf(" HTTP/");
11118 if (idx != -1)
11119 url = url.Substring(0, idx);
11120 }
11121
10241 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$"; 11122 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$";
10242 Regex r = new Regex(authregex); 11123 Regex r = new Regex(authregex);
10243 int[] gnums = r.GetGroupNumbers(); 11124 int[] gnums = r.GetGroupNumbers();
10244 Match m = r.Match(url); 11125 Match m = r.Match(url);
10245 if (m.Success) { 11126 if (m.Success)
10246 for (int i = 1; i < gnums.Length; i++) { 11127 {
11128 for (int i = 1; i < gnums.Length; i++)
11129 {
10247 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 11130 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10248 //CaptureCollection cc = g.Captures; 11131 //CaptureCollection cc = g.Captures;
10249 } 11132 }
10250 if (m.Groups.Count == 5) { 11133 if (m.Groups.Count == 5)
11134 {
10251 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 11135 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10252 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 11136 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10253 } 11137 }
@@ -10450,6 +11334,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10450 11334
10451 LSL_List ret = new LSL_List(); 11335 LSL_List ret = new LSL_List();
10452 UUID key = new UUID(); 11336 UUID key = new UUID();
11337
11338
10453 if (UUID.TryParse(id, out key)) 11339 if (UUID.TryParse(id, out key))
10454 { 11340 {
10455 ScenePresence av = World.GetScenePresence(key); 11341 ScenePresence av = World.GetScenePresence(key);
@@ -10467,13 +11353,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10467 ret.Add(new LSL_String("")); 11353 ret.Add(new LSL_String(""));
10468 break; 11354 break;
10469 case ScriptBaseClass.OBJECT_POS: 11355 case ScriptBaseClass.OBJECT_POS:
10470 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); 11356 Vector3 avpos;
11357
11358 if (av.ParentID != 0 && av.ParentPart != null)
11359 {
11360 avpos = av.OffsetPosition;
11361
11362 Vector3 sitOffset = (Zrot(av.Rotation)) * (av.Appearance.AvatarHeight * 0.02638f *2.0f);
11363 avpos -= sitOffset;
11364
11365 avpos = av.ParentPart.GetWorldPosition() + avpos * av.ParentPart.GetWorldRotation();
11366 }
11367 else
11368 avpos = av.AbsolutePosition;
11369
11370 ret.Add(new LSL_Vector((double)avpos.X, (double)avpos.Y, (double)avpos.Z));
10471 break; 11371 break;
10472 case ScriptBaseClass.OBJECT_ROT: 11372 case ScriptBaseClass.OBJECT_ROT:
10473 ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W)); 11373 Quaternion avrot = av.Rotation;
11374 if (av.ParentID != 0 && av.ParentPart != null)
11375 {
11376 avrot = av.ParentPart.GetWorldRotation() * avrot;
11377 }
11378 ret.Add(new LSL_Rotation((double)avrot.X, (double)avrot.Y, (double)avrot.Z, (double)avrot.W));
10474 break; 11379 break;
10475 case ScriptBaseClass.OBJECT_VELOCITY: 11380 case ScriptBaseClass.OBJECT_VELOCITY:
10476 ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); 11381 Vector3 avvel = av.Velocity;
11382 ret.Add(new LSL_Vector((double)avvel.X, (double)avvel.Y, (double)avvel.Z));
10477 break; 11383 break;
10478 case ScriptBaseClass.OBJECT_OWNER: 11384 case ScriptBaseClass.OBJECT_OWNER:
10479 ret.Add(new LSL_String(id)); 11385 ret.Add(new LSL_String(id));
@@ -10529,11 +11435,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10529 case ScriptBaseClass.OBJECT_NAME: 11435 case ScriptBaseClass.OBJECT_NAME:
10530 ret.Add(new LSL_String(obj.Name)); 11436 ret.Add(new LSL_String(obj.Name));
10531 break; 11437 break;
10532 case ScriptBaseClass.OBJECT_DESC: 11438 case ScriptBaseClass.OBJECT_DESC:
10533 ret.Add(new LSL_String(obj.Description)); 11439 ret.Add(new LSL_String(obj.Description));
10534 break; 11440 break;
10535 case ScriptBaseClass.OBJECT_POS: 11441 case ScriptBaseClass.OBJECT_POS:
10536 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); 11442 Vector3 opos = obj.AbsolutePosition;
11443 ret.Add(new LSL_Vector(opos.X, opos.Y, opos.Z));
10537 break; 11444 break;
10538 case ScriptBaseClass.OBJECT_ROT: 11445 case ScriptBaseClass.OBJECT_ROT:
10539 { 11446 {
@@ -10583,9 +11490,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10583 // The value returned in SL for normal prims is prim count 11490 // The value returned in SL for normal prims is prim count
10584 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount)); 11491 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
10585 break; 11492 break;
10586 // The following 3 costs I have intentionaly coded to return zero. They are part of 11493
10587 // "Land Impact" calculations. These calculations are probably not applicable 11494 // costs below may need to be diferent for root parts, need to check
10588 // to OpenSim and are not yet complete in SL
10589 case ScriptBaseClass.OBJECT_SERVER_COST: 11495 case ScriptBaseClass.OBJECT_SERVER_COST:
10590 // The linden calculation is here 11496 // The linden calculation is here
10591 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight 11497 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
@@ -10593,16 +11499,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10593 ret.Add(new LSL_Float(0)); 11499 ret.Add(new LSL_Float(0));
10594 break; 11500 break;
10595 case ScriptBaseClass.OBJECT_STREAMING_COST: 11501 case ScriptBaseClass.OBJECT_STREAMING_COST:
10596 // The linden calculation is here 11502 // The value returned in SL for normal prims is prim count * 0.06
10597 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost 11503 ret.Add(new LSL_Float(obj.StreamingCost));
10598 // The value returned in SL for normal prims looks like the prim count * 0.06
10599 ret.Add(new LSL_Float(0));
10600 break; 11504 break;
10601 case ScriptBaseClass.OBJECT_PHYSICS_COST: 11505 case ScriptBaseClass.OBJECT_PHYSICS_COST:
10602 // The linden calculation is here 11506 // The value returned in SL for normal prims is prim count
10603 // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics 11507 ret.Add(new LSL_Float(obj.PhysicsCost));
10604 // The value returned in SL for normal prims looks like the prim count
10605 ret.Add(new LSL_Float(0));
10606 break; 11508 break;
10607 default: 11509 default:
10608 // Invalid or unhandled constant. 11510 // Invalid or unhandled constant.
@@ -10813,15 +11715,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10813 return result; 11715 return result;
10814 } 11716 }
10815 11717
10816 public void print(string str) 11718 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10817 { 11719 {
10818 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11720 List<SceneObjectPart> parts = GetLinkParts(link);
10819 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11721 if (parts.Count < 1)
10820 if (ossl != null) 11722 return 0;
10821 { 11723
10822 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11724 return GetNumberOfSides(parts[0]);
10823 m_log.Info("LSL print():" + str);
10824 }
10825 } 11725 }
10826 11726
10827 private string Name2Username(string name) 11727 private string Name2Username(string name)
@@ -10866,7 +11766,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10866 11766
10867 return rq.ToString(); 11767 return rq.ToString();
10868 } 11768 }
10869 11769/*
11770 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11771 {
11772 m_SayShoutCount = 0;
11773 }
11774*/
10870 private struct Tri 11775 private struct Tri
10871 { 11776 {
10872 public Vector3 p1; 11777 public Vector3 p1;
@@ -11006,9 +11911,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11006 11911
11007 ContactResult result = new ContactResult (); 11912 ContactResult result = new ContactResult ();
11008 result.ConsumerID = group.LocalId; 11913 result.ConsumerID = group.LocalId;
11009 result.Depth = intersection.distance; 11914// result.Depth = intersection.distance;
11010 result.Normal = intersection.normal; 11915 result.Normal = intersection.normal;
11011 result.Pos = intersection.ipoint; 11916 result.Pos = intersection.ipoint;
11917 result.Depth = Vector3.Mag(rayStart - result.Pos);
11012 11918
11013 contacts.Add(result); 11919 contacts.Add(result);
11014 }); 11920 });
@@ -11141,6 +12047,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11141 12047
11142 return contacts[0]; 12048 return contacts[0];
11143 } 12049 }
12050/*
12051 // not done:
12052 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
12053 {
12054 ContactResult[] contacts = null;
12055 World.ForEachSOG(delegate(SceneObjectGroup group)
12056 {
12057 if (m_host.ParentGroup == group)
12058 return;
12059
12060 if (group.IsAttachment)
12061 return;
12062
12063 if(group.RootPart.PhysActor != null)
12064 return;
12065
12066 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
12067 });
12068 return contacts;
12069 }
12070*/
11144 12071
11145 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 12072 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
11146 { 12073 {
@@ -11182,32 +12109,96 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11182 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 12109 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
11183 12110
11184 12111
11185 if (checkTerrain) 12112 if (World.SuportsRayCastFiltered())
11186 { 12113 {
11187 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); 12114 if (dist == 0)
11188 if (groundContact != null) 12115 return list;
11189 results.Add((ContactResult)groundContact);
11190 }
11191 12116
11192 if (checkAgents) 12117 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
11193 { 12118 if (checkTerrain)
11194 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); 12119 rayfilter |= RayFilterFlags.land;
11195 foreach (ContactResult r in agentHits) 12120// if (checkAgents)
11196 results.Add(r); 12121// rayfilter |= RayFilterFlags.agent;
11197 } 12122 if (checkPhysical)
12123 rayfilter |= RayFilterFlags.physical;
12124 if (checkNonPhysical)
12125 rayfilter |= RayFilterFlags.nonphysical;
12126 if (detectPhantom)
12127 rayfilter |= RayFilterFlags.LSLPhanton;
12128
12129 Vector3 direction = dir * ( 1/dist);
12130
12131 if(rayfilter == 0)
12132 {
12133 list.Add(new LSL_Integer(0));
12134 return list;
12135 }
12136
12137 // get some more contacts to sort ???
12138 int physcount = 4 * count;
12139 if (physcount > 20)
12140 physcount = 20;
12141
12142 object physresults;
12143 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
12144
12145 if (physresults == null)
12146 {
12147 list.Add(new LSL_Integer(-3)); // timeout error
12148 return list;
12149 }
12150
12151 results = (List<ContactResult>)physresults;
12152
12153 // for now physics doesn't detect sitted avatars so do it outside physics
12154 if (checkAgents)
12155 {
12156 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
12157 foreach (ContactResult r in agentHits)
12158 results.Add(r);
12159 }
11198 12160
11199 if (checkPhysical || checkNonPhysical || detectPhantom) 12161 // TODO: Replace this with a better solution. ObjectIntersection can only
12162 // detect nonphysical phantoms. They are detected by virtue of being
12163 // nonphysical (e.g. no PhysActor) so will not conflict with detecting
12164 // physicsl phantoms as done by the physics scene
12165 // We don't want anything else but phantoms here.
12166 if (detectPhantom)
12167 {
12168 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, false, false, true);
12169 foreach (ContactResult r in objectHits)
12170 results.Add(r);
12171 }
12172 }
12173 else
11200 { 12174 {
11201 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); 12175 if (checkTerrain)
11202 foreach (ContactResult r in objectHits) 12176 {
11203 results.Add(r); 12177 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
12178 if (groundContact != null)
12179 results.Add((ContactResult)groundContact);
12180 }
12181
12182 if (checkAgents)
12183 {
12184 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
12185 foreach (ContactResult r in agentHits)
12186 results.Add(r);
12187 }
12188
12189 if (checkPhysical || checkNonPhysical || detectPhantom)
12190 {
12191 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
12192 foreach (ContactResult r in objectHits)
12193 results.Add(r);
12194 }
11204 } 12195 }
11205 12196
11206 results.Sort(delegate(ContactResult a, ContactResult b) 12197 results.Sort(delegate(ContactResult a, ContactResult b)
11207 { 12198 {
11208 return a.Depth.CompareTo(b.Depth); 12199 return a.Depth.CompareTo(b.Depth);
11209 }); 12200 });
11210 12201
11211 int values = 0; 12202 int values = 0;
11212 SceneObjectGroup thisgrp = m_host.ParentGroup; 12203 SceneObjectGroup thisgrp = m_host.ParentGroup;
11213 12204
@@ -11300,7 +12291,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11300 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 12291 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
11301 if (!isAccount) return 0; 12292 if (!isAccount) return 0;
11302 if (estate.HasAccess(id)) return 1; 12293 if (estate.HasAccess(id)) return 1;
11303 if (estate.IsBanned(id)) 12294 if (estate.IsBanned(id, World.GetUserFlags(id)))
11304 estate.RemoveBan(id); 12295 estate.RemoveBan(id);
11305 estate.AddEstateUser(id); 12296 estate.AddEstateUser(id);
11306 break; 12297 break;
@@ -11319,14 +12310,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11319 break; 12310 break;
11320 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 12311 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
11321 if (!isAccount) return 0; 12312 if (!isAccount) return 0;
11322 if (estate.IsBanned(id)) return 1; 12313 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
11323 EstateBan ban = new EstateBan(); 12314 EstateBan ban = new EstateBan();
11324 ban.EstateID = estate.EstateID; 12315 ban.EstateID = estate.EstateID;
11325 ban.BannedUserID = id; 12316 ban.BannedUserID = id;
11326 estate.AddBan(ban); 12317 estate.AddBan(ban);
11327 break; 12318 break;
11328 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 12319 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
11329 if (!isAccount || !estate.IsBanned(id)) return 0; 12320 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
11330 estate.RemoveBan(id); 12321 estate.RemoveBan(id);
11331 break; 12322 break;
11332 default: return 0; 12323 default: return 0;
@@ -11355,7 +12346,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11355 return 16384; 12346 return 16384;
11356 } 12347 }
11357 12348
11358 public LSL_Integer llGetUsedMemory() 12349 public virtual LSL_Integer llGetUsedMemory()
11359 { 12350 {
11360 m_host.AddScriptLPS(1); 12351 m_host.AddScriptLPS(1);
11361 // The value returned for LSO scripts in SL 12352 // The value returned for LSO scripts in SL
@@ -11383,7 +12374,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11383 public void llSetSoundQueueing(int queue) 12374 public void llSetSoundQueueing(int queue)
11384 { 12375 {
11385 m_host.AddScriptLPS(1); 12376 m_host.AddScriptLPS(1);
11386 NotImplemented("llSetSoundQueueing");
11387 } 12377 }
11388 12378
11389 public void llCollisionSprite(string impact_sprite) 12379 public void llCollisionSprite(string impact_sprite)
@@ -11395,10 +12385,719 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11395 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12385 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
11396 { 12386 {
11397 m_host.AddScriptLPS(1); 12387 m_host.AddScriptLPS(1);
11398 NotImplemented("llGodLikeRezObject"); 12388
12389 if (!World.Permissions.IsGod(m_host.OwnerID))
12390 NotImplemented("llGodLikeRezObject");
12391
12392 AssetBase rezAsset = World.AssetService.Get(inventory);
12393 if (rezAsset == null)
12394 {
12395 llSay(0, "Asset not found");
12396 return;
12397 }
12398
12399 SceneObjectGroup group = null;
12400
12401 try
12402 {
12403 string xmlData = Utils.BytesToString(rezAsset.Data);
12404 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12405 }
12406 catch
12407 {
12408 llSay(0, "Asset not found");
12409 return;
12410 }
12411
12412 if (group == null)
12413 {
12414 llSay(0, "Asset not found");
12415 return;
12416 }
12417
12418 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12419 group.RootPart.AttachOffset = group.AbsolutePosition;
12420
12421 group.ResetIDs();
12422
12423 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12424 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12425 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12426 group.ScheduleGroupForFullUpdate();
12427
12428 // objects rezzed with this method are die_at_edge by default.
12429 group.RootPart.SetDieAtEdge(true);
12430
12431 group.ResumeScripts();
12432
12433 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12434 "object_rez", new Object[] {
12435 new LSL_String(
12436 group.RootPart.UUID.ToString()) },
12437 new DetectParams[0]));
12438 }
12439
12440 public LSL_String llTransferLindenDollars(string destination, int amount)
12441 {
12442 UUID txn = UUID.Random();
12443
12444 Util.FireAndForget(delegate(object x)
12445 {
12446 int replycode = 0;
12447 string replydata = destination + "," + amount.ToString();
12448
12449 try
12450 {
12451 TaskInventoryItem item = m_item;
12452 if (item == null)
12453 {
12454 replydata = "SERVICE_ERROR";
12455 return;
12456 }
12457
12458 m_host.AddScriptLPS(1);
12459
12460 if (item.PermsGranter == UUID.Zero)
12461 {
12462 replydata = "MISSING_PERMISSION_DEBIT";
12463 return;
12464 }
12465
12466 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
12467 {
12468 replydata = "MISSING_PERMISSION_DEBIT";
12469 return;
12470 }
12471
12472 UUID toID = new UUID();
12473
12474 if (!UUID.TryParse(destination, out toID))
12475 {
12476 replydata = "INVALID_AGENT";
12477 return;
12478 }
12479
12480 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
12481
12482 if (money == null)
12483 {
12484 replydata = "TRANSFERS_DISABLED";
12485 return;
12486 }
12487
12488 bool result = money.ObjectGiveMoney(
12489 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
12490
12491 if (result)
12492 {
12493 replycode = 1;
12494 return;
12495 }
12496
12497 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
12498 }
12499 finally
12500 {
12501 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
12502 "transaction_result", new Object[] {
12503 new LSL_String(txn.ToString()),
12504 new LSL_Integer(replycode),
12505 new LSL_String(replydata) },
12506 new DetectParams[0]));
12507 }
12508 });
12509
12510 return txn.ToString();
11399 } 12511 }
11400 12512
11401 #endregion 12513 #endregion
12514
12515 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12516 {
12517 SceneObjectGroup group = m_host.ParentGroup;
12518
12519 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12520 return;
12521 if (group.IsAttachment)
12522 return;
12523
12524 if (frames.Data.Length > 0) // We are getting a new motion
12525 {
12526 if (group.RootPart.KeyframeMotion != null)
12527 group.RootPart.KeyframeMotion.Stop();
12528 group.RootPart.KeyframeMotion = null;
12529
12530 int idx = 0;
12531
12532 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12533 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12534
12535 while (idx < options.Data.Length)
12536 {
12537 int option = (int)options.GetLSLIntegerItem(idx++);
12538 int remain = options.Data.Length - idx;
12539
12540 switch (option)
12541 {
12542 case ScriptBaseClass.KFM_MODE:
12543 if (remain < 1)
12544 break;
12545 int modeval = (int)options.GetLSLIntegerItem(idx++);
12546 switch(modeval)
12547 {
12548 case ScriptBaseClass.KFM_FORWARD:
12549 mode = KeyframeMotion.PlayMode.Forward;
12550 break;
12551 case ScriptBaseClass.KFM_REVERSE:
12552 mode = KeyframeMotion.PlayMode.Reverse;
12553 break;
12554 case ScriptBaseClass.KFM_LOOP:
12555 mode = KeyframeMotion.PlayMode.Loop;
12556 break;
12557 case ScriptBaseClass.KFM_PING_PONG:
12558 mode = KeyframeMotion.PlayMode.PingPong;
12559 break;
12560 }
12561 break;
12562 case ScriptBaseClass.KFM_DATA:
12563 if (remain < 1)
12564 break;
12565 int dataval = (int)options.GetLSLIntegerItem(idx++);
12566 data = (KeyframeMotion.DataFormat)dataval;
12567 break;
12568 }
12569 }
12570
12571 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12572
12573 idx = 0;
12574
12575 int elemLength = 2;
12576 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12577 elemLength = 3;
12578
12579 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12580 while (idx < frames.Data.Length)
12581 {
12582 int remain = frames.Data.Length - idx;
12583
12584 if (remain < elemLength)
12585 break;
12586
12587 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12588 frame.Position = null;
12589 frame.Rotation = null;
12590
12591 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12592 {
12593 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12594 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12595 }
12596 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12597 {
12598 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12599 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12600 }
12601
12602 float tempf = (float)frames.GetLSLFloatItem(idx++);
12603 frame.TimeMS = (int)(tempf * 1000.0f);
12604
12605 keyframes.Add(frame);
12606 }
12607
12608 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12609 group.RootPart.KeyframeMotion.Start();
12610 }
12611 else
12612 {
12613 if (group.RootPart.KeyframeMotion == null)
12614 return;
12615
12616 if (options.Data.Length == 0)
12617 {
12618 group.RootPart.KeyframeMotion.Stop();
12619 return;
12620 }
12621
12622 int code = (int)options.GetLSLIntegerItem(0);
12623
12624 int idx = 0;
12625
12626 while (idx < options.Data.Length)
12627 {
12628 int option = (int)options.GetLSLIntegerItem(idx++);
12629 int remain = options.Data.Length - idx;
12630
12631 switch (option)
12632 {
12633 case ScriptBaseClass.KFM_COMMAND:
12634 int cmd = (int)options.GetLSLIntegerItem(idx++);
12635 switch (cmd)
12636 {
12637 case ScriptBaseClass.KFM_CMD_PLAY:
12638 group.RootPart.KeyframeMotion.Start();
12639 break;
12640 case ScriptBaseClass.KFM_CMD_STOP:
12641 group.RootPart.KeyframeMotion.Stop();
12642 break;
12643 case ScriptBaseClass.KFM_CMD_PAUSE:
12644 group.RootPart.KeyframeMotion.Pause();
12645 break;
12646 }
12647 break;
12648 }
12649 }
12650 }
12651 }
12652
12653 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed)
12654 {
12655 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
12656
12657 int idx = 0;
12658 int idxStart = 0;
12659
12660 bool positionChanged = false;
12661 Vector3 finalPos = Vector3.Zero;
12662
12663 try
12664 {
12665 while (idx < rules.Length)
12666 {
12667 ++rulesParsed;
12668 int code = rules.GetLSLIntegerItem(idx++);
12669
12670 int remain = rules.Length - idx;
12671 idxStart = idx;
12672
12673 switch (code)
12674 {
12675 case (int)ScriptBaseClass.PRIM_POSITION:
12676 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
12677 {
12678 if (remain < 1)
12679 return null;
12680
12681 LSL_Vector v;
12682 v = rules.GetVector3Item(idx++);
12683
12684 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12685 if (part == null)
12686 break;
12687
12688 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12689 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12690 if (part.LinkNum > 1)
12691 {
12692 localRot = GetPartLocalRot(part);
12693 localPos = GetPartLocalPos(part);
12694 }
12695
12696 v -= localPos;
12697 v /= localRot;
12698
12699 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
12700
12701 v = v + 2 * sitOffset;
12702
12703 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
12704 av.SendAvatarDataToAllAgents();
12705
12706 }
12707 break;
12708
12709 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
12710 case (int)ScriptBaseClass.PRIM_ROTATION:
12711 {
12712 if (remain < 1)
12713 return null;
12714
12715 LSL_Rotation r;
12716 r = rules.GetQuaternionItem(idx++);
12717
12718 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12719 if (part == null)
12720 break;
12721
12722 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12723 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12724
12725 if (part.LinkNum > 1)
12726 localRot = GetPartLocalRot(part);
12727
12728 r = r * llGetRootRotation() / localRot;
12729 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
12730 av.SendAvatarDataToAllAgents();
12731 }
12732 break;
12733
12734 // parse rest doing nothing but number of parameters error check
12735 case (int)ScriptBaseClass.PRIM_SIZE:
12736 case (int)ScriptBaseClass.PRIM_MATERIAL:
12737 case (int)ScriptBaseClass.PRIM_PHANTOM:
12738 case (int)ScriptBaseClass.PRIM_PHYSICS:
12739 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
12740 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
12741 case (int)ScriptBaseClass.PRIM_NAME:
12742 case (int)ScriptBaseClass.PRIM_DESC:
12743 if (remain < 1)
12744 return null;
12745 idx++;
12746 break;
12747
12748 case (int)ScriptBaseClass.PRIM_GLOW:
12749 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
12750 case (int)ScriptBaseClass.PRIM_TEXGEN:
12751 if (remain < 2)
12752 return null;
12753 idx += 2;
12754 break;
12755
12756 case (int)ScriptBaseClass.PRIM_TYPE:
12757 if (remain < 3)
12758 return null;
12759 code = (int)rules.GetLSLIntegerItem(idx++);
12760 remain = rules.Length - idx;
12761 switch (code)
12762 {
12763 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
12764 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
12765 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
12766 if (remain < 6)
12767 return null;
12768 idx += 6;
12769 break;
12770
12771 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
12772 if (remain < 5)
12773 return null;
12774 idx += 5;
12775 break;
12776
12777 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
12778 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
12779 case (int)ScriptBaseClass.PRIM_TYPE_RING:
12780 if (remain < 11)
12781 return null;
12782 idx += 11;
12783 break;
12784
12785 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
12786 if (remain < 2)
12787 return null;
12788 idx += 2;
12789 break;
12790 }
12791 break;
12792
12793 case (int)ScriptBaseClass.PRIM_COLOR:
12794 case (int)ScriptBaseClass.PRIM_TEXT:
12795 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
12796 case (int)ScriptBaseClass.PRIM_OMEGA:
12797 if (remain < 3)
12798 return null;
12799 idx += 3;
12800 break;
12801
12802 case (int)ScriptBaseClass.PRIM_TEXTURE:
12803 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
12804 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
12805 if (remain < 5)
12806 return null;
12807 idx += 5;
12808 break;
12809
12810 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
12811 if (remain < 7)
12812 return null;
12813
12814 idx += 7;
12815 break;
12816
12817 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
12818 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
12819 return null;
12820
12821 return rules.GetSublist(idx, -1);
12822 }
12823 }
12824 }
12825 catch (InvalidCastException e)
12826 {
12827 ShoutError(string.Format(
12828 "{0} error running rule #{1}: arg #{2} ",
12829 originFunc, rulesParsed, idx - idxStart) + e.Message);
12830 }
12831 finally
12832 {
12833 if (positionChanged)
12834 {
12835 av.OffsetPosition = finalPos;
12836// av.SendAvatarDataToAllAgents();
12837 av.SendTerseUpdateToAllClients();
12838 positionChanged = false;
12839 }
12840 }
12841 return null;
12842 }
12843
12844 public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res)
12845 {
12846 // avatars case
12847 // replies as SL wiki
12848
12849// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
12850 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
12851
12852 int idx = 0;
12853 while (idx < rules.Length)
12854 {
12855 int code = (int)rules.GetLSLIntegerItem(idx++);
12856 int remain = rules.Length - idx;
12857
12858 switch (code)
12859 {
12860 case (int)ScriptBaseClass.PRIM_MATERIAL:
12861 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
12862 break;
12863
12864 case (int)ScriptBaseClass.PRIM_PHYSICS:
12865 res.Add(new LSL_Integer(0));
12866 break;
12867
12868 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
12869 res.Add(new LSL_Integer(0));
12870 break;
12871
12872 case (int)ScriptBaseClass.PRIM_PHANTOM:
12873 res.Add(new LSL_Integer(0));
12874 break;
12875
12876 case (int)ScriptBaseClass.PRIM_POSITION:
12877
12878 Vector3 pos = avatar.OffsetPosition;
12879
12880 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
12881 pos -= sitOffset;
12882
12883 if( sitPart != null)
12884 pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation();
12885
12886 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
12887 break;
12888
12889 case (int)ScriptBaseClass.PRIM_SIZE:
12890 // as in llGetAgentSize above
12891 res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight));
12892 break;
12893
12894 case (int)ScriptBaseClass.PRIM_ROTATION:
12895 Quaternion rot = avatar.Rotation;
12896 if (sitPart != null)
12897 {
12898 rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation
12899 }
12900
12901 res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W));
12902 break;
12903
12904 case (int)ScriptBaseClass.PRIM_TYPE:
12905 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
12906 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
12907 res.Add(new LSL_Vector(0f,1.0f,0f));
12908 res.Add(new LSL_Float(0.0f));
12909 res.Add(new LSL_Vector(0, 0, 0));
12910 res.Add(new LSL_Vector(1.0f,1.0f,0f));
12911 res.Add(new LSL_Vector(0, 0, 0));
12912 break;
12913
12914 case (int)ScriptBaseClass.PRIM_TEXTURE:
12915 if (remain < 1)
12916 return null;
12917
12918 int face = (int)rules.GetLSLIntegerItem(idx++);
12919 if (face == ScriptBaseClass.ALL_SIDES)
12920 {
12921 for (face = 0; face < 21; face++)
12922 {
12923 res.Add(new LSL_String(""));
12924 res.Add(new LSL_Vector(0,0,0));
12925 res.Add(new LSL_Vector(0,0,0));
12926 res.Add(new LSL_Float(0.0));
12927 }
12928 }
12929 else
12930 {
12931 if (face >= 0 && face < 21)
12932 {
12933 res.Add(new LSL_String(""));
12934 res.Add(new LSL_Vector(0,0,0));
12935 res.Add(new LSL_Vector(0,0,0));
12936 res.Add(new LSL_Float(0.0));
12937 }
12938 }
12939 break;
12940
12941 case (int)ScriptBaseClass.PRIM_COLOR:
12942 if (remain < 1)
12943 return null;
12944
12945 face = (int)rules.GetLSLIntegerItem(idx++);
12946
12947 if (face == ScriptBaseClass.ALL_SIDES)
12948 {
12949 for (face = 0; face < 21; face++)
12950 {
12951 res.Add(new LSL_Vector(0,0,0));
12952 res.Add(new LSL_Float(0));
12953 }
12954 }
12955 else
12956 {
12957 res.Add(new LSL_Vector(0,0,0));
12958 res.Add(new LSL_Float(0));
12959 }
12960 break;
12961
12962 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
12963 if (remain < 1)
12964 return null;
12965 face = (int)rules.GetLSLIntegerItem(idx++);
12966
12967 if (face == ScriptBaseClass.ALL_SIDES)
12968 {
12969 for (face = 0; face < 21; face++)
12970 {
12971 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
12972 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
12973 }
12974 }
12975 else
12976 {
12977 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
12978 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
12979 }
12980 break;
12981
12982 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
12983 if (remain < 1)
12984 return null;
12985 face = (int)rules.GetLSLIntegerItem(idx++);
12986
12987 if (face == ScriptBaseClass.ALL_SIDES)
12988 {
12989 for (face = 0; face < 21; face++)
12990 {
12991 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
12992 }
12993 }
12994 else
12995 {
12996 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
12997 }
12998 break;
12999
13000 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
13001 res.Add(new LSL_Integer(0));
13002 res.Add(new LSL_Integer(0));// softness
13003 res.Add(new LSL_Float(0.0f)); // gravity
13004 res.Add(new LSL_Float(0.0f)); // friction
13005 res.Add(new LSL_Float(0.0f)); // wind
13006 res.Add(new LSL_Float(0.0f)); // tension
13007 res.Add(new LSL_Vector(0f,0f,0f));
13008 break;
13009
13010 case (int)ScriptBaseClass.PRIM_TEXGEN:
13011 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
13012 if (remain < 1)
13013 return null;
13014 face = (int)rules.GetLSLIntegerItem(idx++);
13015
13016 if (face == ScriptBaseClass.ALL_SIDES)
13017 {
13018 for (face = 0; face < 21; face++)
13019 {
13020 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13021 }
13022 }
13023 else
13024 {
13025 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13026 }
13027 break;
13028
13029 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
13030 res.Add(new LSL_Integer(0));
13031 res.Add(new LSL_Vector(0f,0f,0f));
13032 res.Add(new LSL_Float(0f)); // intensity
13033 res.Add(new LSL_Float(0f)); // radius
13034 res.Add(new LSL_Float(0f)); // falloff
13035 break;
13036
13037 case (int)ScriptBaseClass.PRIM_GLOW:
13038 if (remain < 1)
13039 return null;
13040 face = (int)rules.GetLSLIntegerItem(idx++);
13041
13042 if (face == ScriptBaseClass.ALL_SIDES)
13043 {
13044 for (face = 0; face < 21; face++)
13045 {
13046 res.Add(new LSL_Float(0f));
13047 }
13048 }
13049 else
13050 {
13051 res.Add(new LSL_Float(0f));
13052 }
13053 break;
13054
13055 case (int)ScriptBaseClass.PRIM_TEXT:
13056 res.Add(new LSL_String(""));
13057 res.Add(new LSL_Vector(0f,0f,0f));
13058 res.Add(new LSL_Float(1.0f));
13059 break;
13060
13061 case (int)ScriptBaseClass.PRIM_NAME:
13062 res.Add(new LSL_String(avatar.Name));
13063 break;
13064
13065 case (int)ScriptBaseClass.PRIM_DESC:
13066 res.Add(new LSL_String(""));
13067 break;
13068
13069 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
13070 Quaternion lrot = avatar.Rotation;
13071
13072 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13073 {
13074 lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset
13075 }
13076 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
13077 break;
13078
13079 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
13080 Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part
13081 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
13082 lpos -= lsitOffset;
13083
13084 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13085 {
13086 lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim
13087 }
13088 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
13089 break;
13090
13091 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
13092 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
13093 return null;
13094
13095 return rules.GetSublist(idx, -1);
13096 }
13097 }
13098
13099 return null;
13100 }
11402 } 13101 }
11403 13102
11404 public class NotecardCache 13103 public class NotecardCache