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.cs3317
1 files changed, 2390 insertions, 927 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 969243c..bc35272 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.Framework.Scenes.Scripting; 51using OpenSim.Region.Framework.Scenes.Scripting;
49using OpenSim.Region.Physics.Manager; 52using OpenSim.Region.Physics.Manager;
@@ -67,6 +70,7 @@ using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
67using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 70using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
68using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; 71using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
69using System.Reflection; 72using System.Reflection;
73using Timer = System.Timers.Timer;
70using System.Linq; 74using System.Linq;
71using PermissionMask = OpenSim.Framework.PermissionMask; 75using PermissionMask = OpenSim.Framework.PermissionMask;
72 76
@@ -115,11 +119,38 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
115 protected int m_notecardLineReadCharsMax = 255; 119 protected int m_notecardLineReadCharsMax = 255;
116 protected int m_scriptConsoleChannel = 0; 120 protected int m_scriptConsoleChannel = 0;
117 protected bool m_scriptConsoleChannelEnabled = false; 121 protected bool m_scriptConsoleChannelEnabled = false;
122 protected bool m_debuggerSafe = false;
118 protected IUrlModule m_UrlModule = null; 123 protected IUrlModule m_UrlModule = null;
119 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); 124 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
120 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 125 new Dictionary<UUID, UserInfoCacheEntry>();
126 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
121 protected ISoundModule m_SoundModule = null; 127 protected ISoundModule m_SoundModule = null;
122 128
129// protected Timer m_ShoutSayTimer;
130 protected int m_SayShoutCount = 0;
131 DateTime m_lastSayShoutCheck;
132
133 private Dictionary<string, string> MovementAnimationsForLSL =
134 new Dictionary<string, string> {
135 {"FLY", "Flying"},
136 {"FLYSLOW", "FlyingSlow"},
137 {"HOVER_UP", "Hovering Up"},
138 {"HOVER_DOWN", "Hovering Down"},
139 {"HOVER", "Hovering"},
140 {"LAND", "Landing"},
141 {"FALLDOWN", "Falling Down"},
142 {"PREJUMP", "PreJumping"},
143 {"JUMP", "Jumping"},
144 {"STANDUP", "Standing Up"},
145 {"SOFT_LAND", "Soft Landing"},
146 {"STAND", "Standing"},
147 {"CROUCHWALK", "CrouchWalking"},
148 {"RUN", "Running"},
149 {"WALK", "Walking"},
150 {"CROUCH", "Crouching"},
151 {"TURNLEFT", "Turning Left"},
152 {"TURNRIGHT", "Turning Right"}
153 };
123 //An array of HTTP/1.1 headers that are not allowed to be used 154 //An array of HTTP/1.1 headers that are not allowed to be used
124 //as custom headers by llHTTPRequest. 155 //as custom headers by llHTTPRequest.
125 private string[] HttpStandardHeaders = 156 private string[] HttpStandardHeaders =
@@ -140,9 +171,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
140 public void Initialize( 171 public void Initialize(
141 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle) 172 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
142 { 173 {
174 m_lastSayShoutCheck = DateTime.UtcNow;
175
143 m_ScriptEngine = scriptEngine; 176 m_ScriptEngine = scriptEngine;
144 m_host = host; 177 m_host = host;
145 m_item = item; 178 m_item = item;
179 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
146 m_coopSleepHandle = coopSleepHandle; 180 m_coopSleepHandle = coopSleepHandle;
147 181
148 LoadConfig(); 182 LoadConfig();
@@ -231,6 +265,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
231 get { return m_ScriptEngine.World; } 265 get { return m_ScriptEngine.World; }
232 } 266 }
233 267
268 [DebuggerNonUserCode]
234 public void state(string newState) 269 public void state(string newState)
235 { 270 {
236 m_ScriptEngine.SetState(m_item.ItemID, newState); 271 m_ScriptEngine.SetState(m_item.ItemID, newState);
@@ -240,6 +275,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
240 /// Reset the named script. The script must be present 275 /// Reset the named script. The script must be present
241 /// in the same prim. 276 /// in the same prim.
242 /// </summary> 277 /// </summary>
278 [DebuggerNonUserCode]
243 public void llResetScript() 279 public void llResetScript()
244 { 280 {
245 m_host.AddScriptLPS(1); 281 m_host.AddScriptLPS(1);
@@ -302,6 +338,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
302 } 338 }
303 } 339 }
304 340
341 public List<ScenePresence> GetLinkAvatars(int linkType)
342 {
343 List<ScenePresence> ret = new List<ScenePresence>();
344 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
345 return ret;
346
347 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
348
349 switch (linkType)
350 {
351 case ScriptBaseClass.LINK_SET:
352 return avs;
353
354 case ScriptBaseClass.LINK_ROOT:
355 return ret;
356
357 case ScriptBaseClass.LINK_ALL_OTHERS:
358 return avs;
359
360 case ScriptBaseClass.LINK_ALL_CHILDREN:
361 return avs;
362
363 case ScriptBaseClass.LINK_THIS:
364 return ret;
365
366 default:
367 if (linkType < 0)
368 return ret;
369
370 int partCount = m_host.ParentGroup.GetPartCount();
371
372 if (linkType <= partCount)
373 {
374 return ret;
375 }
376 else
377 {
378 linkType = linkType - partCount;
379 if (linkType > avs.Count)
380 {
381 return ret;
382 }
383 else
384 {
385 ret.Add(avs[linkType-1]);
386 return ret;
387 }
388 }
389 }
390 }
391
305 /// <summary> 392 /// <summary>
306 /// Get a given link entity from a linkset (linked objects and any sitting avatars). 393 /// Get a given link entity from a linkset (linked objects and any sitting avatars).
307 /// </summary> 394 /// </summary>
@@ -384,6 +471,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
384 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) 471 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
385 { 472 {
386 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 473 List<SceneObjectPart> ret = new List<SceneObjectPart>();
474 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
475 return ret;
387 ret.Add(part); 476 ret.Add(part);
388 477
389 switch (linkType) 478 switch (linkType)
@@ -537,31 +626,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
537 626
538 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 627 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
539 628
540 /// <summary> 629 // Utility function for llRot2Euler
541 /// Convert an LSL rotation to a Euler vector. 630
542 /// </summary> 631 // normalize an angle between -PI and PI (-180 to +180 degrees)
543 /// <remarks> 632 protected double NormalizeAngle(double angle)
544 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
545 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
546 /// </remarks>
547 /// <param name="r"></param>
548 /// <returns></returns>
549 public LSL_Vector llRot2Euler(LSL_Rotation r)
550 { 633 {
551 m_host.AddScriptLPS(1); 634 if (angle > -Math.PI && angle < Math.PI)
635 return angle;
552 636
553 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 637 int numPis = (int)(Math.PI / angle);
554 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 638 double remainder = angle - Math.PI * numPis;
555 if (m == 0.0) return new LSL_Vector(); 639 if (numPis % 2 == 1)
556 double x = Math.Atan2(-v.y, v.z); 640 return Math.PI - angle;
557 double sin = v.x / m; 641 return remainder;
558 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. 642 }
559 double y = Math.Asin(sin);
560 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
561 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)));
562 double z = Math.Atan2(v.y, v.x);
563 643
564 return new LSL_Vector(x, y, z); 644 public LSL_Vector llRot2Euler(LSL_Rotation q1)
645 {
646 m_host.AddScriptLPS(1);
647 LSL_Vector eul = new LSL_Vector();
648
649 double sqw = q1.s*q1.s;
650 double sqx = q1.x*q1.x;
651 double sqy = q1.z*q1.z;
652 double sqz = q1.y*q1.y;
653 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
654 double test = q1.x*q1.z + q1.y*q1.s;
655 if (test > 0.4999*unit) { // singularity at north pole
656 eul.z = 2 * Math.Atan2(q1.x,q1.s);
657 eul.y = Math.PI/2;
658 eul.x = 0;
659 return eul;
660 }
661 if (test < -0.4999*unit) { // singularity at south pole
662 eul.z = -2 * Math.Atan2(q1.x,q1.s);
663 eul.y = -Math.PI/2;
664 eul.x = 0;
665 return eul;
666 }
667 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
668 eul.y = Math.Asin(2*test/unit);
669 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
670 return eul;
565 } 671 }
566 672
567 /* From wiki: 673 /* From wiki:
@@ -614,18 +720,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
614 m_host.AddScriptLPS(1); 720 m_host.AddScriptLPS(1);
615 721
616 double x,y,z,s; 722 double x,y,z,s;
617 723 v.x *= 0.5;
618 double c1 = Math.Cos(v.x * 0.5); 724 v.y *= 0.5;
619 double c2 = Math.Cos(v.y * 0.5); 725 v.z *= 0.5;
620 double c3 = Math.Cos(v.z * 0.5); 726 double c1 = Math.Cos(v.x);
621 double s1 = Math.Sin(v.x * 0.5); 727 double c2 = Math.Cos(v.y);
622 double s2 = Math.Sin(v.y * 0.5); 728 double c1c2 = c1 * c2;
623 double s3 = Math.Sin(v.z * 0.5); 729 double s1 = Math.Sin(v.x);
624 730 double s2 = Math.Sin(v.y);
625 x = s1 * c2 * c3 + c1 * s2 * s3; 731 double s1s2 = s1 * s2;
626 y = c1 * s2 * c3 - s1 * c2 * s3; 732 double c1s2 = c1 * s2;
627 z = s1 * s2 * c3 + c1 * c2 * s3; 733 double s1c2 = s1 * c2;
628 s = c1 * c2 * c3 - s1 * s2 * s3; 734 double c3 = Math.Cos(v.z);
735 double s3 = Math.Sin(v.z);
736
737 x = s1c2 * c3 + c1s2 * s3;
738 y = c1s2 * c3 - s1c2 * s3;
739 z = s1s2 * c3 + c1c2 * s3;
740 s = c1c2 * c3 - s1s2 * s3;
629 741
630 return new LSL_Rotation(x, y, z, s); 742 return new LSL_Rotation(x, y, z, s);
631 } 743 }
@@ -763,77 +875,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
763 { 875 {
764 //A and B should both be normalized 876 //A and B should both be normalized
765 m_host.AddScriptLPS(1); 877 m_host.AddScriptLPS(1);
766 LSL_Rotation rotBetween; 878 /* This method is more accurate than the SL one, and thus causes problems
767 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 879 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
768 // continue calculation. 880
769 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 881 double dotProduct = LSL_Vector.Dot(a, b);
770 { 882 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
771 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 883 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
772 } 884 double angle = Math.Acos(dotProduct / magProduct);
773 else 885 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
774 { 886 double s = Math.Sin(angle / 2);
775 a = LSL_Vector.Norm(a); 887
776 b = LSL_Vector.Norm(b); 888 double x = axis.x * s;
777 double dotProduct = LSL_Vector.Dot(a, b); 889 double y = axis.y * s;
778 // There are two degenerate cases possible. These are for vectors 180 or 890 double z = axis.z * s;
779 // 0 degrees apart. These have to be detected and handled individually. 891 double w = Math.Cos(angle / 2);
780 // 892
781 // Check for vectors 180 degrees apart. 893 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
782 // A dot product of -1 would mean the angle between vectors is 180 degrees. 894 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
783 if (dotProduct < -0.9999999f) 895
784 { 896 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
785 // First assume X axis is orthogonal to the vectors. 897 */
786 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 898
787 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 899 // This method mimics the 180 errors found in SL
788 // Check for near zero vector. A very small non-zero number here will create 900 // See www.euclideanspace.com... angleBetween
789 // a rotation in an undesired direction. 901 LSL_Vector vec_a = a;
790 if (LSL_Vector.Mag(orthoVector) > 0.0001) 902 LSL_Vector vec_b = b;
791 { 903
792 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 904 // Eliminate zero length
793 } 905 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
794 // If the magnitude of the vector was near zero, then assume the X axis is not 906 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
795 // orthogonal and use the Z axis instead. 907 if (vec_a_mag < 0.00001 ||
796 else 908 vec_b_mag < 0.00001)
797 { 909 {
798 // Set 180 z rotation. 910 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
799 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f); 911 }
800 } 912
801 } 913 // Normalize
802 // Check for parallel vectors. 914 vec_a = llVecNorm(vec_a);
803 // A dot product of 1 would mean the angle between vectors is 0 degrees. 915 vec_b = llVecNorm(vec_b);
804 else if (dotProduct > 0.9999999f) 916
805 { 917 // Calculate axis and rotation angle
806 // Set zero rotation. 918 LSL_Vector axis = vec_a % vec_b;
807 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 919 LSL_Float cos_theta = vec_a * vec_b;
808 } 920
809 else 921 // Check if parallel
810 { 922 if (cos_theta > 0.99999)
811 // All special checks have been performed so get the axis of rotation. 923 {
812 LSL_Vector crossProduct = LSL_Vector.Cross(a, b); 924 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
813 // Quarternion s value is the length of the unit vector + dot product. 925 }
814 double qs = 1.0 + dotProduct; 926
815 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs); 927 // Check if anti-parallel
816 // Normalize the rotation. 928 else if (cos_theta < -0.99999)
817 double mag = LSL_Rotation.Mag(rotBetween); 929 {
818 // We shouldn't have to worry about a divide by zero here. The qs value will be 930 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
819 // non-zero because we already know if we're here, then the dotProduct is not -1 so 931 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
820 // qs will not be zero. Also, we've already handled the input vectors being zero so the 932 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
821 // crossProduct vector should also not be zero. 933 }
822 rotBetween.x = rotBetween.x / mag; 934 else // other rotation
823 rotBetween.y = rotBetween.y / mag; 935 {
824 rotBetween.z = rotBetween.z / mag; 936 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
825 rotBetween.s = rotBetween.s / mag; 937 axis = llVecNorm(axis);
826 // Check for undefined values and set zero rotation if any found. This code might not actually be required 938 double x, y, z, s, t;
827 // any longer since zero vectors are checked for at the top. 939 s = Math.Cos(theta);
828 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s)) 940 t = Math.Sin(theta);
829 { 941 x = axis.x * t;
830 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 942 y = axis.y * t;
831 } 943 z = axis.z * t;
832 } 944 return new LSL_Rotation(x,y,z,s);
833 } 945 }
834 return rotBetween; 946 }
835 } 947
836
837 public void llWhisper(int channelID, string text) 948 public void llWhisper(int channelID, string text)
838 { 949 {
839 m_host.AddScriptLPS(1); 950 m_host.AddScriptLPS(1);
@@ -849,10 +960,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
849 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text); 960 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
850 } 961 }
851 962
963 private void CheckSayShoutTime()
964 {
965 DateTime now = DateTime.UtcNow;
966 if ((now - m_lastSayShoutCheck).Ticks > 10000000) // 1sec
967 {
968 m_lastSayShoutCheck = now;
969 m_SayShoutCount = 0;
970 }
971 else
972 m_SayShoutCount++;
973 }
974
852 public void llSay(int channelID, string text) 975 public void llSay(int channelID, string text)
853 { 976 {
854 m_host.AddScriptLPS(1); 977 m_host.AddScriptLPS(1);
855 978
979 if (channelID == 0)
980// m_SayShoutCount++;
981 CheckSayShoutTime();
982
983 if (m_SayShoutCount >= 11)
984 ScriptSleep(2000);
985
856 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 986 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
857 { 987 {
858 Console.WriteLine(text); 988 Console.WriteLine(text);
@@ -875,6 +1005,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
875 { 1005 {
876 m_host.AddScriptLPS(1); 1006 m_host.AddScriptLPS(1);
877 1007
1008 if (channelID == 0)
1009// m_SayShoutCount++;
1010 CheckSayShoutTime();
1011
1012 if (m_SayShoutCount >= 11)
1013 ScriptSleep(2000);
1014
878 if (text.Length > 1023) 1015 if (text.Length > 1023)
879 text = text.Substring(0, 1023); 1016 text = text.Substring(0, 1023);
880 1017
@@ -906,22 +1043,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
906 1043
907 public void llRegionSayTo(string target, int channel, string msg) 1044 public void llRegionSayTo(string target, int channel, string msg)
908 { 1045 {
1046 string error = String.Empty;
1047
909 if (msg.Length > 1023) 1048 if (msg.Length > 1023)
910 msg = msg.Substring(0, 1023); 1049 msg = msg.Substring(0, 1023);
911 1050
912 m_host.AddScriptLPS(1); 1051 m_host.AddScriptLPS(1);
913 1052
914 if (channel == ScriptBaseClass.DEBUG_CHANNEL)
915 {
916 return;
917 }
918
919 UUID TargetID; 1053 UUID TargetID;
920 UUID.TryParse(target, out TargetID); 1054 UUID.TryParse(target, out TargetID);
921 1055
922 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1056 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
923 if (wComm != null) 1057 if (wComm != null)
924 wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg); 1058 if (!wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg, out error))
1059 LSLError(error);
925 } 1060 }
926 1061
927 public LSL_Integer llListen(int channelID, string name, string ID, string msg) 1062 public LSL_Integer llListen(int channelID, string name, string ID, string msg)
@@ -1177,10 +1312,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1177 return detectedParams.TouchUV; 1312 return detectedParams.TouchUV;
1178 } 1313 }
1179 1314
1315 [DebuggerNonUserCode]
1180 public virtual void llDie() 1316 public virtual void llDie()
1181 { 1317 {
1182 m_host.AddScriptLPS(1); 1318 m_host.AddScriptLPS(1);
1183 throw new SelfDeleteException(); 1319 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1184 } 1320 }
1185 1321
1186 public LSL_Float llGround(LSL_Vector offset) 1322 public LSL_Float llGround(LSL_Vector offset)
@@ -1251,6 +1387,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1251 1387
1252 public void llSetStatus(int status, int value) 1388 public void llSetStatus(int status, int value)
1253 { 1389 {
1390 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1391 return;
1254 m_host.AddScriptLPS(1); 1392 m_host.AddScriptLPS(1);
1255 1393
1256 int statusrotationaxis = 0; 1394 int statusrotationaxis = 0;
@@ -1274,6 +1412,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1274 if (!allow) 1412 if (!allow)
1275 return; 1413 return;
1276 1414
1415 if (m_host.ParentGroup.RootPart.PhysActor != null &&
1416 m_host.ParentGroup.RootPart.PhysActor.IsPhysical)
1417 return;
1418
1277 m_host.ScriptSetPhysicsStatus(true); 1419 m_host.ScriptSetPhysicsStatus(true);
1278 } 1420 }
1279 else 1421 else
@@ -1474,6 +1616,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1474 { 1616 {
1475 m_host.AddScriptLPS(1); 1617 m_host.AddScriptLPS(1);
1476 1618
1619 SetColor(m_host, color, face);
1620 }
1621
1622 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1623 {
1624 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1625 return;
1626
1627 Primitive.TextureEntry tex = part.Shape.Textures;
1628 Color4 texcolor;
1629 if (face >= 0 && face < GetNumberOfSides(part))
1630 {
1631 texcolor = tex.CreateFace((uint)face).RGBA;
1632 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1633 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1634 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1635 tex.FaceTextures[face].RGBA = texcolor;
1636 part.UpdateTextureEntry(tex.GetBytes());
1637 return;
1638 }
1639 else if (face == ScriptBaseClass.ALL_SIDES)
1640 {
1641 for (uint i = 0; i < GetNumberOfSides(part); i++)
1642 {
1643 if (tex.FaceTextures[i] != null)
1644 {
1645 texcolor = tex.FaceTextures[i].RGBA;
1646 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1647 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1648 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1649 tex.FaceTextures[i].RGBA = texcolor;
1650 }
1651 texcolor = tex.DefaultTexture.RGBA;
1652 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1653 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1654 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1655 tex.DefaultTexture.RGBA = texcolor;
1656 }
1657 part.UpdateTextureEntry(tex.GetBytes());
1658 return;
1659 }
1660
1477 if (face == ScriptBaseClass.ALL_SIDES) 1661 if (face == ScriptBaseClass.ALL_SIDES)
1478 face = SceneObjectPart.ALL_SIDES; 1662 face = SceneObjectPart.ALL_SIDES;
1479 1663
@@ -1482,6 +1666,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1482 1666
1483 public void SetTexGen(SceneObjectPart part, int face,int style) 1667 public void SetTexGen(SceneObjectPart part, int face,int style)
1484 { 1668 {
1669 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1670 return;
1671
1485 Primitive.TextureEntry tex = part.Shape.Textures; 1672 Primitive.TextureEntry tex = part.Shape.Textures;
1486 MappingType textype; 1673 MappingType textype;
1487 textype = MappingType.Default; 1674 textype = MappingType.Default;
@@ -1512,6 +1699,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1512 1699
1513 public void SetGlow(SceneObjectPart part, int face, float glow) 1700 public void SetGlow(SceneObjectPart part, int face, float glow)
1514 { 1701 {
1702 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1703 return;
1704
1515 Primitive.TextureEntry tex = part.Shape.Textures; 1705 Primitive.TextureEntry tex = part.Shape.Textures;
1516 if (face >= 0 && face < GetNumberOfSides(part)) 1706 if (face >= 0 && face < GetNumberOfSides(part))
1517 { 1707 {
@@ -1537,6 +1727,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1537 1727
1538 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1728 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1539 { 1729 {
1730 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1731 return;
1540 1732
1541 Shininess sval = new Shininess(); 1733 Shininess sval = new Shininess();
1542 1734
@@ -1587,6 +1779,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1587 1779
1588 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1780 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1589 { 1781 {
1782 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1783 return;
1784
1590 Primitive.TextureEntry tex = part.Shape.Textures; 1785 Primitive.TextureEntry tex = part.Shape.Textures;
1591 if (face >= 0 && face < GetNumberOfSides(part)) 1786 if (face >= 0 && face < GetNumberOfSides(part))
1592 { 1787 {
@@ -1647,13 +1842,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1647 m_host.AddScriptLPS(1); 1842 m_host.AddScriptLPS(1);
1648 1843
1649 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1844 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1650 1845 if (parts.Count > 0)
1651 foreach (SceneObjectPart part in parts) 1846 {
1652 SetAlpha(part, alpha, face); 1847 try
1848 {
1849 foreach (SceneObjectPart part in parts)
1850 SetAlpha(part, alpha, face);
1851 }
1852 finally
1853 {
1854 }
1855 }
1653 } 1856 }
1654 1857
1655 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1858 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1656 { 1859 {
1860 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1861 return;
1862
1657 Primitive.TextureEntry tex = part.Shape.Textures; 1863 Primitive.TextureEntry tex = part.Shape.Textures;
1658 Color4 texcolor; 1864 Color4 texcolor;
1659 if (face >= 0 && face < GetNumberOfSides(part)) 1865 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1706,7 +1912,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1706 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1912 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1707 float wind, float tension, LSL_Vector Force) 1913 float wind, float tension, LSL_Vector Force)
1708 { 1914 {
1709 if (part == null) 1915 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1710 return; 1916 return;
1711 1917
1712 if (flexi) 1918 if (flexi)
@@ -1747,7 +1953,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1747 /// <param name="falloff"></param> 1953 /// <param name="falloff"></param>
1748 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1954 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1749 { 1955 {
1750 if (part == null) 1956 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1751 return; 1957 return;
1752 1958
1753 if (light) 1959 if (light)
@@ -1780,11 +1986,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1780 Primitive.TextureEntry tex = part.Shape.Textures; 1986 Primitive.TextureEntry tex = part.Shape.Textures;
1781 Color4 texcolor; 1987 Color4 texcolor;
1782 LSL_Vector rgb = new LSL_Vector(); 1988 LSL_Vector rgb = new LSL_Vector();
1989 int nsides = GetNumberOfSides(part);
1990
1783 if (face == ScriptBaseClass.ALL_SIDES) 1991 if (face == ScriptBaseClass.ALL_SIDES)
1784 { 1992 {
1785 int i; 1993 int i;
1786 1994 for (i = 0; i < nsides; i++)
1787 for (i = 0 ; i < GetNumberOfSides(part); i++)
1788 { 1995 {
1789 texcolor = tex.GetFace((uint)i).RGBA; 1996 texcolor = tex.GetFace((uint)i).RGBA;
1790 rgb.x += texcolor.R; 1997 rgb.x += texcolor.R;
@@ -1792,14 +1999,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1792 rgb.z += texcolor.B; 1999 rgb.z += texcolor.B;
1793 } 2000 }
1794 2001
1795 rgb.x /= (float)GetNumberOfSides(part); 2002 float invnsides = 1.0f / (float)nsides;
1796 rgb.y /= (float)GetNumberOfSides(part); 2003
1797 rgb.z /= (float)GetNumberOfSides(part); 2004 rgb.x *= invnsides;
2005 rgb.y *= invnsides;
2006 rgb.z *= invnsides;
1798 2007
1799 return rgb; 2008 return rgb;
1800 } 2009 }
1801 2010 if (face >= 0 && face < nsides)
1802 if (face >= 0 && face < GetNumberOfSides(part))
1803 { 2011 {
1804 texcolor = tex.GetFace((uint)face).RGBA; 2012 texcolor = tex.GetFace((uint)face).RGBA;
1805 rgb.x = texcolor.R; 2013 rgb.x = texcolor.R;
@@ -1826,15 +2034,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1826 m_host.AddScriptLPS(1); 2034 m_host.AddScriptLPS(1);
1827 2035
1828 List<SceneObjectPart> parts = GetLinkParts(linknumber); 2036 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1829 2037 if (parts.Count > 0)
1830 foreach (SceneObjectPart part in parts) 2038 {
1831 SetTexture(part, texture, face); 2039 try
1832 2040 {
2041 foreach (SceneObjectPart part in parts)
2042 SetTexture(part, texture, face);
2043 }
2044 finally
2045 {
2046 }
2047 }
1833 ScriptSleep(200); 2048 ScriptSleep(200);
1834 } 2049 }
1835 2050
1836 protected void SetTexture(SceneObjectPart part, string texture, int face) 2051 protected void SetTexture(SceneObjectPart part, string texture, int face)
1837 { 2052 {
2053 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2054 return;
2055
1838 UUID textureID = new UUID(); 2056 UUID textureID = new UUID();
1839 2057
1840 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture); 2058 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
@@ -1879,6 +2097,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1879 2097
1880 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 2098 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1881 { 2099 {
2100 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2101 return;
2102
1882 Primitive.TextureEntry tex = part.Shape.Textures; 2103 Primitive.TextureEntry tex = part.Shape.Textures;
1883 if (face >= 0 && face < GetNumberOfSides(part)) 2104 if (face >= 0 && face < GetNumberOfSides(part))
1884 { 2105 {
@@ -1915,6 +2136,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1915 2136
1916 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2137 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1917 { 2138 {
2139 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2140 return;
2141
1918 Primitive.TextureEntry tex = part.Shape.Textures; 2142 Primitive.TextureEntry tex = part.Shape.Textures;
1919 if (face >= 0 && face < GetNumberOfSides(part)) 2143 if (face >= 0 && face < GetNumberOfSides(part))
1920 { 2144 {
@@ -1951,6 +2175,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1951 2175
1952 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2176 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1953 { 2177 {
2178 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2179 return;
2180
1954 Primitive.TextureEntry tex = part.Shape.Textures; 2181 Primitive.TextureEntry tex = part.Shape.Textures;
1955 if (face >= 0 && face < GetNumberOfSides(part)) 2182 if (face >= 0 && face < GetNumberOfSides(part))
1956 { 2183 {
@@ -2092,7 +2319,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2092 return end; 2319 return end;
2093 } 2320 }
2094 2321
2095 protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos) 2322 protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos, bool adjust)
2096 { 2323 {
2097 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 2324 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2098 return fromPos; 2325 return fromPos;
@@ -2108,9 +2335,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2108 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) 2335 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
2109 targetPos.z = ground; 2336 targetPos.z = ground;
2110 } 2337 }
2111 LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos); 2338 if (adjust)
2339 return SetPosAdjust(fromPos, targetPos);
2112 2340
2113 return real_vec; 2341 return targetPos;
2114 } 2342 }
2115 2343
2116 /// <summary> 2344 /// <summary>
@@ -2121,27 +2349,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2121 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param> 2349 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param>
2122 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust) 2350 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
2123 { 2351 {
2124 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2352 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2353 return;
2354
2125 LSL_Vector currentPos = GetPartLocalPos(part); 2355 LSL_Vector currentPos = GetPartLocalPos(part);
2356 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos, adjust);
2126 2357
2127 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
2128 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
2129 2358
2130 if (part.ParentGroup.RootPart == part) 2359 if (part.ParentGroup.RootPart == part)
2131 { 2360 {
2132 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
2133 targetPos.z = ground;
2134 SceneObjectGroup parent = part.ParentGroup; 2361 SceneObjectGroup parent = part.ParentGroup;
2135 parent.UpdateGroupPosition(!adjust ? targetPos : 2362 if (!World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos))
2136 SetPosAdjust(currentPos, targetPos)); 2363 return;
2364 Util.FireAndForget(delegate(object x) {
2365 parent.UpdateGroupPosition((Vector3)toPos);
2366 });
2137 } 2367 }
2138 else 2368 else
2139 { 2369 {
2140 part.OffsetPosition = !adjust ? targetPos : 2370 part.OffsetPosition = (Vector3)toPos;
2141 SetPosAdjust(currentPos, targetPos); 2371// SceneObjectGroup parent = part.ParentGroup;
2142 SceneObjectGroup parent = part.ParentGroup; 2372// parent.HasGroupChanged = true;
2143 parent.HasGroupChanged = true; 2373// parent.ScheduleGroupForTerseUpdate();
2144 parent.ScheduleGroupForTerseUpdate(); 2374 part.ScheduleTerseUpdate();
2145 } 2375 }
2146 } 2376 }
2147 2377
@@ -2170,13 +2400,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2170 else 2400 else
2171 { 2401 {
2172 if (part.ParentGroup.IsAttachment) 2402 if (part.ParentGroup.IsAttachment)
2173 {
2174 pos = part.AttachedPos; 2403 pos = part.AttachedPos;
2175 }
2176 else 2404 else
2177 {
2178 pos = part.AbsolutePosition; 2405 pos = part.AbsolutePosition;
2179 }
2180 } 2406 }
2181 2407
2182// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); 2408// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
@@ -2188,8 +2414,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2188 { 2414 {
2189 m_host.AddScriptLPS(1); 2415 m_host.AddScriptLPS(1);
2190 2416
2417
2418 // Teravus: if (m_host.ParentID == 0) is bug code because the ParentID for the Avatar will cause this to be nonzero for root prim attachments
2419 // which is then treated like a child prim rotation and it's offset gets cumulatively multiplied against.
2420 // to fix the scripted rotations we also have to check to see if the root part localid is the same as the host's localid.
2421 // RootPart != null should shortcircuit
2422
2191 // try to let this work as in SL... 2423 // try to let this work as in SL...
2192 if (m_host.ParentID == 0) 2424 if (m_host.ParentID == 0 || (m_host.ParentGroup != null && m_host == m_host.ParentGroup.RootPart))
2193 { 2425 {
2194 // special case: If we are root, rotate complete SOG to new rotation 2426 // special case: If we are root, rotate complete SOG to new rotation
2195 SetRot(m_host, rot); 2427 SetRot(m_host, rot);
@@ -2216,25 +2448,46 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2216 2448
2217 protected void SetRot(SceneObjectPart part, Quaternion rot) 2449 protected void SetRot(SceneObjectPart part, Quaternion rot)
2218 { 2450 {
2219 part.UpdateRotation(rot); 2451 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2220 // Update rotation does not move the object in the physics scene if it's a linkset. 2452 return;
2221 2453
2222//KF: Do NOT use this next line if using ODE physics engine. This need a switch based on .ini Phys Engine type 2454 bool isroot = (part == part.ParentGroup.RootPart);
2223// part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition; 2455 bool isphys;
2224 2456
2225 // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line
2226 // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt
2227 // It's perfectly okay when the object is not an active physical body though.
2228 // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against
2229 // but only if the object is not physial and active. This is important for rotating doors.
2230 // without the absoluteposition = absoluteposition happening, the doors do not move in the physics
2231 // scene
2232 PhysicsActor pa = part.PhysActor; 2457 PhysicsActor pa = part.PhysActor;
2233 2458
2234 if (pa != null && !pa.IsPhysical) 2459 // keep using physactor ideia of isphysical
2460 // it should be SOP ideia of that
2461 // not much of a issue with ubitODE
2462 if (pa != null && pa.IsPhysical)
2463 isphys = true;
2464 else
2465 isphys = false;
2466
2467 // SL doesn't let scripts rotate root of physical linksets
2468 if (isroot && isphys)
2469 return;
2470
2471 part.UpdateRotation(rot);
2472
2473 // Update rotation does not move the object in the physics engine if it's a non physical linkset
2474 // so do a nasty update of parts positions if is a root part rotation
2475 if (isroot && pa != null) // with if above implies non physical root part
2235 { 2476 {
2236 part.ParentGroup.ResetChildPrimPhysicsPositions(); 2477 part.ParentGroup.ResetChildPrimPhysicsPositions();
2237 } 2478 }
2479 else // fix sitting avatars. This is only needed bc of how we link avas to child parts, not root part
2480 {
2481 List<ScenePresence> sittingavas = part.ParentGroup.GetLinkedAvatars();
2482 if (sittingavas.Count > 0)
2483 {
2484 foreach (ScenePresence av in sittingavas)
2485 {
2486 if (isroot || part.LocalId == av.ParentID)
2487 av.SendTerseUpdateToAllClients();
2488 }
2489 }
2490 }
2238 } 2491 }
2239 2492
2240 /// <summary> 2493 /// <summary>
@@ -2251,6 +2504,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2251 2504
2252 m_host.AddScriptLPS(1); 2505 m_host.AddScriptLPS(1);
2253 Quaternion q = m_host.GetWorldRotation(); 2506 Quaternion q = m_host.GetWorldRotation();
2507
2508 if (m_host.ParentGroup != null && m_host.ParentGroup.AttachmentPoint != 0)
2509 {
2510 ScenePresence avatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2511 if (avatar != null)
2512 {
2513 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2514 q = avatar.CameraRotation * q; // Mouselook
2515 else
2516 q = avatar.Rotation * q; // Currently infrequently updated so may be inaccurate
2517 }
2518 }
2519
2254 return new LSL_Rotation(q.X, q.Y, q.Z, q.W); 2520 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
2255 } 2521 }
2256 2522
@@ -2278,14 +2544,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2278 return new LSL_Rotation(q); 2544 return new LSL_Rotation(q);
2279 } 2545 }
2280 2546
2281 return new LSL_Rotation(part.GetWorldRotation()); 2547 q = part.GetWorldRotation();
2548 if (part.ParentGroup.AttachmentPoint != 0)
2549 {
2550 ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar);
2551 if (avatar != null)
2552 {
2553 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2554 q = avatar.CameraRotation * q; // Mouselook
2555 else
2556 q = avatar.Rotation * q; // Currently infrequently updated so may be inaccurate
2557 }
2558 }
2559
2560 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
2282 } 2561 }
2283 2562
2284 public LSL_Rotation llGetLocalRot() 2563 public LSL_Rotation llGetLocalRot()
2285 { 2564 {
2286 m_host.AddScriptLPS(1); 2565 return GetPartLocalRot(m_host);
2566 }
2287 2567
2288 return new LSL_Rotation(m_host.RotationOffset); 2568 private LSL_Rotation GetPartLocalRot(SceneObjectPart part)
2569 {
2570 m_host.AddScriptLPS(1);
2571 Quaternion rot = part.RotationOffset;
2572 return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
2289 } 2573 }
2290 2574
2291 public void llSetForce(LSL_Vector force, int local) 2575 public void llSetForce(LSL_Vector force, int local)
@@ -2365,16 +2649,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2365 m_host.ApplyImpulse(v, local != 0); 2649 m_host.ApplyImpulse(v, local != 0);
2366 } 2650 }
2367 2651
2652
2368 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2653 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2369 { 2654 {
2370 m_host.AddScriptLPS(1); 2655 m_host.AddScriptLPS(1);
2371 m_host.ApplyAngularImpulse(force, local != 0); 2656 m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0);
2372 } 2657 }
2373 2658
2374 public void llSetTorque(LSL_Vector torque, int local) 2659 public void llSetTorque(LSL_Vector torque, int local)
2375 { 2660 {
2376 m_host.AddScriptLPS(1); 2661 m_host.AddScriptLPS(1);
2377 m_host.SetAngularImpulse(torque, local != 0); 2662 m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0);
2378 } 2663 }
2379 2664
2380 public LSL_Vector llGetTorque() 2665 public LSL_Vector llGetTorque()
@@ -2391,20 +2676,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2391 llSetTorque(torque, local); 2676 llSetTorque(torque, local);
2392 } 2677 }
2393 2678
2679 public void llSetVelocity(LSL_Vector vel, int local)
2680 {
2681 m_host.AddScriptLPS(1);
2682 m_host.SetVelocity(new Vector3((float)vel.x, (float)vel.y, (float)vel.z), local != 0);
2683 }
2684
2394 public LSL_Vector llGetVel() 2685 public LSL_Vector llGetVel()
2395 { 2686 {
2396 m_host.AddScriptLPS(1); 2687 m_host.AddScriptLPS(1);
2397 2688
2398 Vector3 vel; 2689 Vector3 vel = Vector3.Zero;
2399 2690
2400 if (m_host.ParentGroup.IsAttachment) 2691 if (m_host.ParentGroup.IsAttachment)
2401 { 2692 {
2402 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); 2693 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2403 vel = avatar.Velocity; 2694 if (avatar != null)
2695 vel = avatar.Velocity;
2404 } 2696 }
2405 else 2697 else
2406 { 2698 {
2407 vel = m_host.Velocity; 2699 vel = m_host.ParentGroup.RootPart.Velocity;
2408 } 2700 }
2409 2701
2410 return new LSL_Vector(vel); 2702 return new LSL_Vector(vel);
@@ -2417,11 +2709,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2417 return new LSL_Vector(m_host.Acceleration); 2709 return new LSL_Vector(m_host.Acceleration);
2418 } 2710 }
2419 2711
2420 public LSL_Vector llGetOmega() 2712 public void llSetAngularVelocity(LSL_Vector avel, int local)
2421 { 2713 {
2422 m_host.AddScriptLPS(1); 2714 m_host.AddScriptLPS(1);
2715 m_host.SetAngularVelocity(new Vector3((float)avel.x, (float)avel.y, (float)avel.z), local != 0);
2716 }
2423 2717
2424 return new LSL_Vector(m_host.AngularVelocity); 2718 public LSL_Vector llGetOmega()
2719 {
2720 m_host.AddScriptLPS(1);
2721 Vector3 avel = m_host.AngularVelocity;
2722 return new LSL_Vector(avel.X, avel.Y, avel.Z);
2425 } 2723 }
2426 2724
2427 public LSL_Float llGetTimeOfDay() 2725 public LSL_Float llGetTimeOfDay()
@@ -2780,7 +3078,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2780 return src.ToLower(); 3078 return src.ToLower();
2781 } 3079 }
2782 3080
2783 public void llGiveMoney(string destination, int amount) 3081 public LSL_Integer llGiveMoney(string destination, int amount)
2784 { 3082 {
2785 Util.FireAndForget(x => 3083 Util.FireAndForget(x =>
2786 { 3084 {
@@ -2812,8 +3110,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2812 } 3110 }
2813 3111
2814 money.ObjectGiveMoney( 3112 money.ObjectGiveMoney(
2815 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 3113 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero);
2816 }); 3114 });
3115
3116 return 0;
2817 } 3117 }
2818 3118
2819 public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) 3119 public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
@@ -2892,13 +3192,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2892 new_group.RootPart.UUID.ToString()) }, 3192 new_group.RootPart.UUID.ToString()) },
2893 new DetectParams[0])); 3193 new DetectParams[0]));
2894 3194
2895 float groupmass = new_group.GetMass(); 3195 // do recoil
3196 SceneObjectGroup hostgrp = m_host.ParentGroup;
3197 if (hostgrp == null)
3198 return;
3199
3200 if (hostgrp.IsAttachment) // don't recoil avatars
3201 return;
2896 3202
2897 PhysicsActor pa = new_group.RootPart.PhysActor; 3203 PhysicsActor pa = new_group.RootPart.PhysActor;
2898 3204
2899 //Recoil. 3205 //Recoil.
2900 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3206 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
2901 { 3207 {
3208 float groupmass = new_group.GetMass();
2902 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor; 3209 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
2903 if (recoil != Vector3.Zero) 3210 if (recoil != Vector3.Zero)
2904 { 3211 {
@@ -2906,6 +3213,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2906 } 3213 }
2907 } 3214 }
2908 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3215 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3216 return;
3217
2909 }); 3218 });
2910 3219
2911 //ScriptSleep((int)((groupmass * velmag) / 10)); 3220 //ScriptSleep((int)((groupmass * velmag) / 10));
@@ -2920,35 +3229,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2920 public void llLookAt(LSL_Vector target, double strength, double damping) 3229 public void llLookAt(LSL_Vector target, double strength, double damping)
2921 { 3230 {
2922 m_host.AddScriptLPS(1); 3231 m_host.AddScriptLPS(1);
2923 // Determine where we are looking from
2924 LSL_Vector from = llGetPos();
2925
2926 // Work out the normalised vector from the source to the target
2927 LSL_Vector delta = llVecNorm(target - from);
2928 LSL_Vector angle = new LSL_Vector(0,0,0);
2929 3232
2930 // Calculate the yaw 3233 // Get the normalized vector to the target
2931 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3234 LSL_Vector d1 = llVecNorm(target - llGetPos());
2932 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO;
2933 3235
2934 // Calculate pitch 3236 // Get the bearing (yaw)
2935 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3237 LSL_Vector a1 = new LSL_Vector(0,0,0);
3238 a1.z = llAtan2(d1.y, d1.x);
2936 3239
2937 // we need to convert from a vector describing 3240 // Get the elevation (pitch)
2938 // the angles of rotation in radians into rotation value 3241 LSL_Vector a2 = new LSL_Vector(0,0,0);
2939 LSL_Rotation rot = llEuler2Rot(angle); 3242 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2940 3243
2941 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply 3244 LSL_Rotation r1 = llEuler2Rot(a1);
2942 // set the rotation of the object, copy that behavior 3245 LSL_Rotation r2 = llEuler2Rot(a2);
2943 PhysicsActor pa = m_host.PhysActor; 3246 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2944 3247
2945 if (strength == 0 || pa == null || !pa.IsPhysical) 3248 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2946 { 3249 {
2947 llSetRot(rot); 3250 // Do nothing if either value is 0 (this has been checked in SL)
3251 if (strength <= 0.0 || damping <= 0.0)
3252 return;
3253
3254 llSetRot(r3 * r2 * r1);
2948 } 3255 }
2949 else 3256 else
2950 { 3257 {
2951 m_host.StartLookAt(rot, (float)strength, (float)damping); 3258 if (strength == 0)
3259 {
3260 llSetRot(r3 * r2 * r1);
3261 return;
3262 }
3263
3264 m_host.StartLookAt((Quaternion)(r3 * r2 * r1), (float)strength, (float)damping);
2952 } 3265 }
2953 } 3266 }
2954 3267
@@ -2995,17 +3308,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2995 } 3308 }
2996 else 3309 else
2997 { 3310 {
2998 if (m_host.IsRoot) 3311 // new SL always returns object mass
2999 { 3312// if (m_host.IsRoot)
3313// {
3000 return m_host.ParentGroup.GetMass(); 3314 return m_host.ParentGroup.GetMass();
3001 } 3315// }
3002 else 3316// else
3003 { 3317// {
3004 return m_host.GetMass(); 3318// return m_host.GetMass();
3005 } 3319// }
3006 } 3320 }
3007 } 3321 }
3008 3322
3323
3324 public LSL_Float llGetMassMKS()
3325 {
3326 return 100f * llGetMass();
3327 }
3328
3009 public void llCollisionFilter(string name, string id, int accept) 3329 public void llCollisionFilter(string name, string id, int accept)
3010 { 3330 {
3011 m_host.AddScriptLPS(1); 3331 m_host.AddScriptLPS(1);
@@ -3053,8 +3373,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3053 { 3373 {
3054 // Unregister controls from Presence 3374 // Unregister controls from Presence
3055 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID); 3375 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID);
3056 // Remove Take Control permission.
3057 m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3058 } 3376 }
3059 } 3377 }
3060 } 3378 }
@@ -3082,7 +3400,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3082 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3400 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3083 3401
3084 if (attachmentsModule != null) 3402 if (attachmentsModule != null)
3085 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, true); 3403 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, false, true);
3086 else 3404 else
3087 return false; 3405 return false;
3088 } 3406 }
@@ -3112,9 +3430,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3112 { 3430 {
3113 m_host.AddScriptLPS(1); 3431 m_host.AddScriptLPS(1);
3114 3432
3115// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3116// return;
3117
3118 if (m_item.PermsGranter != m_host.OwnerID) 3433 if (m_item.PermsGranter != m_host.OwnerID)
3119 return; 3434 return;
3120 3435
@@ -3157,6 +3472,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3157 3472
3158 public void llInstantMessage(string user, string message) 3473 public void llInstantMessage(string user, string message)
3159 { 3474 {
3475 UUID result;
3476 if (!UUID.TryParse(user, out result) || result == UUID.Zero)
3477 {
3478 ShoutError("An invalid key was passed to llInstantMessage");
3479 ScriptSleep(2000);
3480 return;
3481 }
3482
3483
3160 m_host.AddScriptLPS(1); 3484 m_host.AddScriptLPS(1);
3161 3485
3162 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3486 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3171,14 +3495,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3171 UUID friendTransactionID = UUID.Random(); 3495 UUID friendTransactionID = UUID.Random();
3172 3496
3173 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3497 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3174 3498
3175 GridInstantMessage msg = new GridInstantMessage(); 3499 GridInstantMessage msg = new GridInstantMessage();
3176 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3500 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3177 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3501 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3178 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3502 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3179// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3503// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3180// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3504// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3181 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3505// DateTime dt = DateTime.UtcNow;
3506//
3507// // Ticks from UtcNow, but make it look like local. Evil, huh?
3508// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3509//
3510// try
3511// {
3512// // Convert that to the PST timezone
3513// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3514// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3515// }
3516// catch
3517// {
3518// // No logging here, as it could be VERY spammy
3519// }
3520//
3521// // And make it look local again to fool the unix time util
3522// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3523
3524 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3525
3182 //if (client != null) 3526 //if (client != null)
3183 //{ 3527 //{
3184 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3528 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3192,10 +3536,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3192 msg.message = message.Substring(0, 1024); 3536 msg.message = message.Substring(0, 1024);
3193 else 3537 else
3194 msg.message = message; 3538 msg.message = message;
3195 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3539 msg.dialog = (byte)19; // MessageFromObject
3196 msg.fromGroup = false;// fromGroup; 3540 msg.fromGroup = false;// fromGroup;
3197 msg.offline = (byte)0; //offline; 3541 msg.offline = (byte)0; //offline;
3198 msg.ParentEstateID = 0; //ParentEstateID; 3542 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3199 msg.Position = new Vector3(m_host.AbsolutePosition); 3543 msg.Position = new Vector3(m_host.AbsolutePosition);
3200 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3544 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
3201 3545
@@ -3227,7 +3571,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3227 } 3571 }
3228 3572
3229 emailModule.SendEmail(m_host.UUID, address, subject, message); 3573 emailModule.SendEmail(m_host.UUID, address, subject, message);
3230 llSleep(EMAIL_PAUSE_TIME); 3574 ScriptSleep(EMAIL_PAUSE_TIME * 1000);
3231 } 3575 }
3232 3576
3233 public void llGetNextEmail(string address, string subject) 3577 public void llGetNextEmail(string address, string subject)
@@ -3473,7 +3817,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3473 implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3817 implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3474 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3818 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3475 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3819 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3820 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3476 ScriptBaseClass.PERMISSION_ATTACH; 3821 ScriptBaseClass.PERMISSION_ATTACH;
3822
3477 } 3823 }
3478 else 3824 else
3479 { 3825 {
@@ -3490,15 +3836,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3490 if (World.GetExtraSetting("auto_grant_attach_perms") == "true") 3836 if (World.GetExtraSetting("auto_grant_attach_perms") == "true")
3491 implicitPerms = ScriptBaseClass.PERMISSION_ATTACH; 3837 implicitPerms = ScriptBaseClass.PERMISSION_ATTACH;
3492 } 3838 }
3839 if (World.GetExtraSetting("auto_grant_all_perms") == "true")
3840 {
3841 implicitPerms = perm;
3842 }
3493 } 3843 }
3494 3844
3495 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3845 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3496 { 3846 {
3497 lock (m_host.TaskInventory) 3847 m_host.TaskInventory.LockItemsForWrite(true);
3498 { 3848 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3499 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3849 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3500 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3850 m_host.TaskInventory.LockItemsForWrite(false);
3501 }
3502 3851
3503 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3852 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3504 "run_time_permissions", new Object[] { 3853 "run_time_permissions", new Object[] {
@@ -3541,11 +3890,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3541 3890
3542 if (!m_waitingForScriptAnswer) 3891 if (!m_waitingForScriptAnswer)
3543 { 3892 {
3544 lock (m_host.TaskInventory) 3893 m_host.TaskInventory.LockItemsForWrite(true);
3545 { 3894 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3546 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3895 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3547 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 3896 m_host.TaskInventory.LockItemsForWrite(false);
3548 }
3549 3897
3550 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3898 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3551 m_waitingForScriptAnswer=true; 3899 m_waitingForScriptAnswer=true;
@@ -3574,14 +3922,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3574 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3922 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3575 llReleaseControls(); 3923 llReleaseControls();
3576 3924
3577 lock (m_host.TaskInventory) 3925 m_host.TaskInventory.LockItemsForWrite(true);
3578 { 3926 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3579 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 3927 m_host.TaskInventory.LockItemsForWrite(false);
3580 } 3928
3581 3929 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3582 m_ScriptEngine.PostScriptEvent( 3930 "run_time_permissions", new Object[] {
3583 m_item.ItemID, 3931 new LSL_Integer(answer) },
3584 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); 3932 new DetectParams[0]));
3585 } 3933 }
3586 3934
3587 public LSL_String llGetPermissionsKey() 3935 public LSL_String llGetPermissionsKey()
@@ -3620,14 +3968,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3620 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3968 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3621 { 3969 {
3622 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3970 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3623 3971 if (parts.Count > 0)
3624 foreach (SceneObjectPart part in parts) 3972 {
3625 part.SetFaceColorAlpha(face, color, null); 3973 try
3974 {
3975 foreach (SceneObjectPart part in parts)
3976 part.SetFaceColorAlpha(face, color, null);
3977 }
3978 finally
3979 {
3980 }
3981 }
3626 } 3982 }
3627 3983
3628 public void llCreateLink(string target, int parent) 3984 public void llCreateLink(string target, int parent)
3629 { 3985 {
3630 m_host.AddScriptLPS(1); 3986 m_host.AddScriptLPS(1);
3987
3631 UUID targetID; 3988 UUID targetID;
3632 3989
3633 if (!UUID.TryParse(target, out targetID)) 3990 if (!UUID.TryParse(target, out targetID))
@@ -3733,10 +4090,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3733 // Restructuring Multiple Prims. 4090 // Restructuring Multiple Prims.
3734 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4091 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3735 parts.Remove(parentPrim.RootPart); 4092 parts.Remove(parentPrim.RootPart);
3736 foreach (SceneObjectPart part in parts) 4093 if (parts.Count > 0)
3737 { 4094 {
3738 parentPrim.DelinkFromGroup(part.LocalId, true); 4095 try
4096 {
4097 foreach (SceneObjectPart part in parts)
4098 {
4099 parentPrim.DelinkFromGroup(part.LocalId, true);
4100 }
4101 }
4102 finally
4103 {
4104 }
3739 } 4105 }
4106
3740 parentPrim.HasGroupChanged = true; 4107 parentPrim.HasGroupChanged = true;
3741 parentPrim.ScheduleGroupForFullUpdate(); 4108 parentPrim.ScheduleGroupForFullUpdate();
3742 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4109 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3745,12 +4112,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3745 { 4112 {
3746 SceneObjectPart newRoot = parts[0]; 4113 SceneObjectPart newRoot = parts[0];
3747 parts.Remove(newRoot); 4114 parts.Remove(newRoot);
3748 foreach (SceneObjectPart part in parts) 4115
4116 try
3749 { 4117 {
3750 // Required for linking 4118 foreach (SceneObjectPart part in parts)
3751 part.ClearUpdateSchedule(); 4119 {
3752 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4120 part.ClearUpdateSchedule();
4121 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4122 }
3753 } 4123 }
4124 finally
4125 {
4126 }
4127
4128
3754 newRoot.ParentGroup.HasGroupChanged = true; 4129 newRoot.ParentGroup.HasGroupChanged = true;
3755 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4130 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3756 } 4131 }
@@ -3770,6 +4145,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3770 public void llBreakAllLinks() 4145 public void llBreakAllLinks()
3771 { 4146 {
3772 m_host.AddScriptLPS(1); 4147 m_host.AddScriptLPS(1);
4148
4149 TaskInventoryItem item = m_item;
4150
4151 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4152 && !m_automaticLinkPermission)
4153 {
4154 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4155 return;
4156 }
4157
3773 SceneObjectGroup parentPrim = m_host.ParentGroup; 4158 SceneObjectGroup parentPrim = m_host.ParentGroup;
3774 if (parentPrim.AttachmentPoint != 0) 4159 if (parentPrim.AttachmentPoint != 0)
3775 return; // Fail silently if attached 4160 return; // Fail silently if attached
@@ -3789,13 +4174,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3789 public LSL_String llGetLinkKey(int linknum) 4174 public LSL_String llGetLinkKey(int linknum)
3790 { 4175 {
3791 m_host.AddScriptLPS(1); 4176 m_host.AddScriptLPS(1);
4177 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
4178 if (part != null)
4179 {
4180 return part.UUID.ToString();
4181 }
4182 else
4183 {
4184 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4185 {
4186 linknum -= (m_host.ParentGroup.PrimCount) + 1;
3792 4187
3793 ISceneEntity entity = GetLinkEntity(linknum); 4188 if (linknum < 0)
4189 return UUID.Zero.ToString();
3794 4190
3795 if (entity != null) 4191 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
3796 return entity.UUID.ToString(); 4192 if (avatars.Count > linknum)
3797 else 4193 {
3798 return ScriptBaseClass.NULL_KEY; 4194 return avatars[linknum].UUID.ToString();
4195 }
4196 }
4197 return UUID.Zero.ToString();
4198 }
3799 } 4199 }
3800 4200
3801 /// <summary> 4201 /// <summary>
@@ -3854,17 +4254,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3854 m_host.AddScriptLPS(1); 4254 m_host.AddScriptLPS(1);
3855 int count = 0; 4255 int count = 0;
3856 4256
3857 lock (m_host.TaskInventory) 4257 m_host.TaskInventory.LockItemsForRead(true);
4258 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3858 { 4259 {
3859 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4260 if (inv.Value.Type == type || type == -1)
3860 { 4261 {
3861 if (inv.Value.Type == type || type == -1) 4262 count = count + 1;
3862 {
3863 count = count + 1;
3864 }
3865 } 4263 }
3866 } 4264 }
3867 4265
4266 m_host.TaskInventory.LockItemsForRead(false);
3868 return count; 4267 return count;
3869 } 4268 }
3870 4269
@@ -3873,16 +4272,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3873 m_host.AddScriptLPS(1); 4272 m_host.AddScriptLPS(1);
3874 ArrayList keys = new ArrayList(); 4273 ArrayList keys = new ArrayList();
3875 4274
3876 lock (m_host.TaskInventory) 4275 m_host.TaskInventory.LockItemsForRead(true);
4276 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3877 { 4277 {
3878 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4278 if (inv.Value.Type == type || type == -1)
3879 { 4279 {
3880 if (inv.Value.Type == type || type == -1) 4280 keys.Add(inv.Value.Name);
3881 {
3882 keys.Add(inv.Value.Name);
3883 }
3884 } 4281 }
3885 } 4282 }
4283 m_host.TaskInventory.LockItemsForRead(false);
3886 4284
3887 if (keys.Count == 0) 4285 if (keys.Count == 0)
3888 { 4286 {
@@ -3920,7 +4318,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3920 if (item == null) 4318 if (item == null)
3921 { 4319 {
3922 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4320 llSay(0, String.Format("Could not find object '{0}'", inventory));
3923 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4321 return;
4322// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3924 } 4323 }
3925 4324
3926 UUID objId = item.ItemID; 4325 UUID objId = item.ItemID;
@@ -3948,33 +4347,45 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3948 return; 4347 return;
3949 } 4348 }
3950 } 4349 }
4350
3951 // destination is an avatar 4351 // destination is an avatar
3952 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4352 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3953 4353
3954 if (agentItem == null) 4354 if (agentItem == null)
3955 return; 4355 return;
3956 4356
3957 if (m_TransferModule != null) 4357 byte[] bucket = new byte[1];
3958 { 4358 bucket[0] = (byte)item.Type;
3959 byte[] bucket = new byte[1]; 4359 //byte[] objBytes = agentItem.ID.GetBytes();
3960 bucket[0] = (byte)item.Type; 4360 //Array.Copy(objBytes, 0, bucket, 1, 16);
3961 4361
3962 GridInstantMessage msg = new GridInstantMessage(World, 4362 GridInstantMessage msg = new GridInstantMessage(World,
3963 m_host.OwnerID, m_host.Name, destId, 4363 m_host.OwnerID, m_host.Name, destId,
3964 (byte)InstantMessageDialog.TaskInventoryOffered, 4364 (byte)InstantMessageDialog.TaskInventoryOffered,
3965 false, item.Name+". "+m_host.Name+" is located at "+ 4365 false, item.Name+". "+m_host.Name+" is located at "+
3966 World.RegionInfo.RegionName+" "+ 4366 World.RegionInfo.RegionName+" "+
3967 m_host.AbsolutePosition.ToString(), 4367 m_host.AbsolutePosition.ToString(),
3968 agentItem.ID, true, m_host.AbsolutePosition, 4368 agentItem.ID, true, m_host.AbsolutePosition,
3969 bucket, true); 4369 bucket, true);
3970 4370
3971 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4371 ScenePresence sp;
3972 }
3973 4372
4373 if (World.TryGetScenePresence(destId, out sp))
4374 {
4375 sp.ControllingClient.SendInstantMessage(msg);
4376 }
4377 else
4378 {
4379 if (m_TransferModule != null)
4380 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4381 }
4382
4383 //This delay should only occur when giving inventory to avatars.
3974 ScriptSleep(3000); 4384 ScriptSleep(3000);
3975 } 4385 }
3976 } 4386 }
3977 4387
4388 [DebuggerNonUserCode]
3978 public void llRemoveInventory(string name) 4389 public void llRemoveInventory(string name)
3979 { 4390 {
3980 m_host.AddScriptLPS(1); 4391 m_host.AddScriptLPS(1);
@@ -4029,109 +4440,115 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4029 { 4440 {
4030 m_host.AddScriptLPS(1); 4441 m_host.AddScriptLPS(1);
4031 4442
4032 UUID uuid = (UUID)id; 4443 UUID uuid;
4033 PresenceInfo pinfo = null; 4444 if (UUID.TryParse(id, out uuid))
4034 UserAccount account;
4035
4036 UserInfoCacheEntry ce;
4037 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4038 { 4445 {
4039 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4446 PresenceInfo pinfo = null;
4040 if (account == null) 4447 UserAccount account;
4448
4449 UserInfoCacheEntry ce;
4450 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4041 { 4451 {
4042 m_userInfoCache[uuid] = null; // Cache negative 4452 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4043 return UUID.Zero.ToString(); 4453 if (account == null)
4044 } 4454 {
4455 m_userInfoCache[uuid] = null; // Cache negative
4456 return UUID.Zero.ToString();
4457 }
4045 4458
4046 4459
4047 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4460 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4048 if (pinfos != null && pinfos.Length > 0) 4461 if (pinfos != null && pinfos.Length > 0)
4049 {
4050 foreach (PresenceInfo p in pinfos)
4051 { 4462 {
4052 if (p.RegionID != UUID.Zero) 4463 foreach (PresenceInfo p in pinfos)
4053 { 4464 {
4054 pinfo = p; 4465 if (p.RegionID != UUID.Zero)
4466 {
4467 pinfo = p;
4468 }
4055 } 4469 }
4056 } 4470 }
4057 }
4058 4471
4059 ce = new UserInfoCacheEntry(); 4472 ce = new UserInfoCacheEntry();
4060 ce.time = Util.EnvironmentTickCount(); 4473 ce.time = Util.EnvironmentTickCount();
4061 ce.account = account; 4474 ce.account = account;
4062 ce.pinfo = pinfo; 4475 ce.pinfo = pinfo;
4063 } 4476 m_userInfoCache[uuid] = ce;
4064 else 4477 }
4065 { 4478 else
4066 if (ce == null) 4479 {
4067 return UUID.Zero.ToString(); 4480 if (ce == null)
4481 return UUID.Zero.ToString();
4068 4482
4069 account = ce.account; 4483 account = ce.account;
4070 pinfo = ce.pinfo; 4484 pinfo = ce.pinfo;
4071 } 4485 }
4072 4486
4073 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4487 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4074 {
4075 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4076 if (pinfos != null && pinfos.Length > 0)
4077 { 4488 {
4078 foreach (PresenceInfo p in pinfos) 4489 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4490 if (pinfos != null && pinfos.Length > 0)
4079 { 4491 {
4080 if (p.RegionID != UUID.Zero) 4492 foreach (PresenceInfo p in pinfos)
4081 { 4493 {
4082 pinfo = p; 4494 if (p.RegionID != UUID.Zero)
4495 {
4496 pinfo = p;
4497 }
4083 } 4498 }
4084 } 4499 }
4085 } 4500 else
4086 else 4501 pinfo = null;
4087 pinfo = null;
4088 4502
4089 ce.time = Util.EnvironmentTickCount(); 4503 ce.time = Util.EnvironmentTickCount();
4090 ce.pinfo = pinfo; 4504 ce.pinfo = pinfo;
4091 } 4505 }
4092 4506
4093 string reply = String.Empty; 4507 string reply = String.Empty;
4094 4508
4095 switch (data) 4509 switch (data)
4096 { 4510 {
4097 case 1: // DATA_ONLINE (0|1) 4511 case 1: // DATA_ONLINE (0|1)
4098 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4512 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4099 reply = "1"; 4513 reply = "1";
4100 else 4514 else
4101 reply = "0"; 4515 reply = "0";
4102 break; 4516 break;
4103 case 2: // DATA_NAME (First Last) 4517 case 2: // DATA_NAME (First Last)
4104 reply = account.FirstName + " " + account.LastName; 4518 reply = account.FirstName + " " + account.LastName;
4105 break; 4519 break;
4106 case 3: // DATA_BORN (YYYY-MM-DD) 4520 case 3: // DATA_BORN (YYYY-MM-DD)
4107 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4521 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4108 born = born.AddSeconds(account.Created); 4522 born = born.AddSeconds(account.Created);
4109 reply = born.ToString("yyyy-MM-dd"); 4523 reply = born.ToString("yyyy-MM-dd");
4110 break; 4524 break;
4111 case 4: // DATA_RATING (0,0,0,0,0,0) 4525 case 4: // DATA_RATING (0,0,0,0,0,0)
4112 reply = "0,0,0,0,0,0"; 4526 reply = "0,0,0,0,0,0";
4113 break; 4527 break;
4114 case 7: // DATA_USERLEVEL (integer) 4528 case 8: // DATA_PAYINFO (0|1|2|3)
4115 reply = account.UserLevel.ToString(); 4529 reply = "0";
4116 break; 4530 break;
4117 case 8: // DATA_PAYINFO (0|1|2|3) 4531 default:
4118 reply = "0"; 4532 return UUID.Zero.ToString(); // Raise no event
4119 break; 4533 }
4120 default:
4121 return UUID.Zero.ToString(); // Raise no event
4122 }
4123 4534
4124 UUID rq = UUID.Random(); 4535 UUID rq = UUID.Random();
4125 4536
4126 UUID tid = AsyncCommands. 4537 UUID tid = AsyncCommands.
4127 DataserverPlugin.RegisterRequest(m_host.LocalId, 4538 DataserverPlugin.RegisterRequest(m_host.LocalId,
4128 m_item.ItemID, rq.ToString()); 4539 m_item.ItemID, rq.ToString());
4129 4540
4130 AsyncCommands. 4541 AsyncCommands.
4131 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4542 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4132 4543
4133 ScriptSleep(100); 4544 ScriptSleep(100);
4134 return tid.ToString(); 4545 return tid.ToString();
4546 }
4547 else
4548 {
4549 ShoutError("Invalid UUID passed to llRequestAgentData.");
4550 }
4551 return "";
4135 } 4552 }
4136 4553
4137 public LSL_String llRequestInventoryData(string name) 4554 public LSL_String llRequestInventoryData(string name)
@@ -4188,12 +4605,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4188 if (UUID.TryParse(agent, out agentId)) 4605 if (UUID.TryParse(agent, out agentId))
4189 { 4606 {
4190 ScenePresence presence = World.GetScenePresence(agentId); 4607 ScenePresence presence = World.GetScenePresence(agentId);
4191 if (presence != null) 4608 if (presence != null && presence.PresenceType != PresenceType.Npc)
4192 { 4609 {
4610 // agent must not be a god
4611 if (presence.UserLevel >= 200) return;
4612
4193 // agent must be over the owners land 4613 // agent must be over the owners land
4194 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) 4614 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
4195 { 4615 {
4196 World.TeleportClientHome(agentId, presence.ControllingClient); 4616 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4617 {
4618 // They can't be teleported home for some reason
4619 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4620 if (regionInfo != null)
4621 {
4622 World.RequestTeleportLocation(
4623 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4624 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4625 }
4626 }
4197 } 4627 }
4198 } 4628 }
4199 } 4629 }
@@ -4299,7 +4729,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4299 UUID av = new UUID(); 4729 UUID av = new UUID();
4300 if (!UUID.TryParse(agent,out av)) 4730 if (!UUID.TryParse(agent,out av))
4301 { 4731 {
4302 LSLError("First parameter to llDialog needs to be a key");
4303 return; 4732 return;
4304 } 4733 }
4305 4734
@@ -4332,9 +4761,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4332 { 4761 {
4333 m_host.AddScriptLPS(1); 4762 m_host.AddScriptLPS(1);
4334 4763
4764 if(impact_sound == "")
4765 {
4766 m_host.CollisionSoundVolume = (float)impact_volume;
4767 m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
4768 m_host.CollisionSoundType = 0;
4769 return;
4770 }
4335 // TODO: Parameter check logic required. 4771 // TODO: Parameter check logic required.
4336 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound); 4772 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
4337 m_host.CollisionSoundVolume = (float)impact_volume; 4773 m_host.CollisionSoundVolume = (float)impact_volume;
4774 m_host.CollisionSoundType = 1;
4338 } 4775 }
4339 4776
4340 public LSL_String llGetAnimation(string id) 4777 public LSL_String llGetAnimation(string id)
@@ -4348,14 +4785,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4348 4785
4349 if (m_host.RegionHandle == presence.RegionHandle) 4786 if (m_host.RegionHandle == presence.RegionHandle)
4350 { 4787 {
4351 Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames;
4352
4353 if (presence != null) 4788 if (presence != null)
4354 { 4789 {
4355 AnimationSet currentAnims = presence.Animator.Animations; 4790 if (presence.SitGround)
4356 string currentAnimationState = String.Empty; 4791 return "Sitting on Ground";
4357 if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState)) 4792 if (presence.ParentID != 0 || presence.ParentUUID != UUID.Zero)
4358 return currentAnimationState; 4793 return "Sitting";
4794
4795 string movementAnimation = presence.Animator.CurrentMovementAnimation;
4796 string lslMovementAnimation;
4797
4798 if (MovementAnimationsForLSL.TryGetValue(movementAnimation, out lslMovementAnimation))
4799 return lslMovementAnimation;
4359 } 4800 }
4360 } 4801 }
4361 4802
@@ -4503,7 +4944,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4503 { 4944 {
4504 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4945 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4505 float distance_term = distance * distance * distance; // Script Energy 4946 float distance_term = distance * distance * distance; // Script Energy
4506 float pusher_mass = m_host.GetMass(); 4947 // use total object mass and not part
4948 float pusher_mass = m_host.ParentGroup.GetMass();
4507 4949
4508 float PUSH_ATTENUATION_DISTANCE = 17f; 4950 float PUSH_ATTENUATION_DISTANCE = 17f;
4509 float PUSH_ATTENUATION_SCALE = 5f; 4951 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4757,6 +5199,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4757 { 5199 {
4758 return item.AssetID.ToString(); 5200 return item.AssetID.ToString();
4759 } 5201 }
5202 m_host.TaskInventory.LockItemsForRead(false);
4760 5203
4761 return UUID.Zero.ToString(); 5204 return UUID.Zero.ToString();
4762 } 5205 }
@@ -4909,14 +5352,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4909 { 5352 {
4910 m_host.AddScriptLPS(1); 5353 m_host.AddScriptLPS(1);
4911 5354
4912 if (src == null) 5355 return src.Length;
4913 {
4914 return 0;
4915 }
4916 else
4917 {
4918 return src.Length;
4919 }
4920 } 5356 }
4921 5357
4922 public LSL_Integer llList2Integer(LSL_List src, int index) 5358 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4987,7 +5423,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4987 else if (src.Data[index] is LSL_Float) 5423 else if (src.Data[index] is LSL_Float)
4988 return Convert.ToDouble(((LSL_Float)src.Data[index]).value); 5424 return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
4989 else if (src.Data[index] is LSL_String) 5425 else if (src.Data[index] is LSL_String)
4990 return Convert.ToDouble(((LSL_String)src.Data[index]).m_string); 5426 {
5427 string str = ((LSL_String) src.Data[index]).m_string;
5428 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5429 if (m != Match.Empty)
5430 {
5431 str = m.Value;
5432 double d = 0.0;
5433 if (!Double.TryParse(str, out d))
5434 return 0.0;
5435
5436 return d;
5437 }
5438 return 0.0;
5439 }
4991 return Convert.ToDouble(src.Data[index]); 5440 return Convert.ToDouble(src.Data[index]);
4992 } 5441 }
4993 catch (FormatException) 5442 catch (FormatException)
@@ -5029,7 +5478,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5029 // for completion and should LSL_Key ever be implemented 5478 // for completion and should LSL_Key ever be implemented
5030 // as it's own struct 5479 // as it's own struct
5031 else if (!(src.Data[index] is LSL_String || 5480 else if (!(src.Data[index] is LSL_String ||
5032 src.Data[index] is LSL_Key)) 5481 src.Data[index] is LSL_Key ||
5482 src.Data[index] is String))
5033 { 5483 {
5034 return ""; 5484 return "";
5035 } 5485 }
@@ -5287,7 +5737,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5287 } 5737 }
5288 } 5738 }
5289 } 5739 }
5290 else { 5740 else
5741 {
5291 object[] array = new object[src.Length]; 5742 object[] array = new object[src.Length];
5292 Array.Copy(src.Data, 0, array, 0, src.Length); 5743 Array.Copy(src.Data, 0, array, 0, src.Length);
5293 result = new LSL_List(array); 5744 result = new LSL_List(array);
@@ -5394,7 +5845,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5394 public LSL_Integer llGetRegionAgentCount() 5845 public LSL_Integer llGetRegionAgentCount()
5395 { 5846 {
5396 m_host.AddScriptLPS(1); 5847 m_host.AddScriptLPS(1);
5397 return new LSL_Integer(World.GetRootAgentCount()); 5848
5849 int count = 0;
5850 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5851 count++;
5852 });
5853
5854 return new LSL_Integer(count);
5398 } 5855 }
5399 5856
5400 public LSL_Vector llGetRegionCorner() 5857 public LSL_Vector llGetRegionCorner()
@@ -5635,6 +6092,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5635 flags |= ScriptBaseClass.AGENT_AWAY; 6092 flags |= ScriptBaseClass.AGENT_AWAY;
5636 } 6093 }
5637 6094
6095 UUID busy = new UUID("efcf670c-2d18-8128-973a-034ebc806b67");
6096 UUID[] anims = agent.Animator.GetAnimationArray();
6097 if (Array.Exists<UUID>(anims, a => { return a == busy; }))
6098 {
6099 flags |= ScriptBaseClass.AGENT_BUSY;
6100 }
6101
5638 // seems to get unset, even if in mouselook, when avatar is sitting on a prim??? 6102 // seems to get unset, even if in mouselook, when avatar is sitting on a prim???
5639 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) 6103 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
5640 { 6104 {
@@ -5682,6 +6146,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5682 flags |= ScriptBaseClass.AGENT_SITTING; 6146 flags |= ScriptBaseClass.AGENT_SITTING;
5683 } 6147 }
5684 6148
6149 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
6150 {
6151 flags |= ScriptBaseClass.AGENT_MALE;
6152 }
6153
5685 return flags; 6154 return flags;
5686 } 6155 }
5687 6156
@@ -5827,9 +6296,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5827 6296
5828 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6297 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5829 6298
5830 foreach (SceneObjectPart part in parts) 6299 try
6300 {
6301 foreach (SceneObjectPart part in parts)
6302 {
6303 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6304 }
6305 }
6306 finally
5831 { 6307 {
5832 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
5833 } 6308 }
5834 } 6309 }
5835 6310
@@ -5883,13 +6358,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5883 6358
5884 if (m_host.OwnerID == land.LandData.OwnerID) 6359 if (m_host.OwnerID == land.LandData.OwnerID)
5885 { 6360 {
5886 World.TeleportClientHome(agentID, presence.ControllingClient); 6361 Vector3 p = World.GetNearestAllowedPosition(presence, land);
6362 presence.TeleportWithMomentum(p, null);
6363 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5887 } 6364 }
5888 } 6365 }
5889 } 6366 }
5890 ScriptSleep(5000); 6367 ScriptSleep(5000);
5891 } 6368 }
5892 6369
6370 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6371 {
6372 return ParseString2List(str, separators, in_spacers, false);
6373 }
6374
5893 public LSL_Integer llOverMyLand(string id) 6375 public LSL_Integer llOverMyLand(string id)
5894 { 6376 {
5895 m_host.AddScriptLPS(1); 6377 m_host.AddScriptLPS(1);
@@ -5942,26 +6424,55 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5942 } 6424 }
5943 else 6425 else
5944 { 6426 {
5945 agentSize = GetAgentSize(avatar); 6427// agentSize = new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight);
6428 Vector3 s = avatar.Appearance.AvatarSize;
6429 agentSize = new LSL_Vector(s.X, s.Y, s.Z);
5946 } 6430 }
5947
5948 return agentSize; 6431 return agentSize;
5949 } 6432 }
5950 6433
5951 public LSL_Integer llSameGroup(string agent) 6434 public LSL_Integer llSameGroup(string id)
5952 { 6435 {
5953 m_host.AddScriptLPS(1); 6436 m_host.AddScriptLPS(1);
5954 UUID agentId = new UUID(); 6437 UUID uuid = new UUID();
5955 if (!UUID.TryParse(agent, out agentId)) 6438 if (!UUID.TryParse(id, out uuid))
5956 return new LSL_Integer(0);
5957 ScenePresence presence = World.GetScenePresence(agentId);
5958 if (presence == null || presence.IsChildAgent) // Return flase for child agents
5959 return new LSL_Integer(0); 6439 return new LSL_Integer(0);
5960 IClientAPI client = presence.ControllingClient; 6440
5961 if (m_host.GroupID == client.ActiveGroupId) 6441 // Check if it's a group key
6442 if (uuid == m_host.ParentGroup.RootPart.GroupID)
5962 return new LSL_Integer(1); 6443 return new LSL_Integer(1);
5963 else 6444
6445 // We got passed a UUID.Zero
6446 if (uuid == UUID.Zero)
6447 return new LSL_Integer(0);
6448
6449 // Handle the case where id names an avatar
6450 ScenePresence presence = World.GetScenePresence(uuid);
6451 if (presence != null)
6452 {
6453 if (presence.IsChildAgent)
6454 return new LSL_Integer(0);
6455
6456 IClientAPI client = presence.ControllingClient;
6457 if (m_host.ParentGroup.RootPart.GroupID == client.ActiveGroupId)
6458 return new LSL_Integer(1);
6459
6460 return new LSL_Integer(0);
6461 }
6462
6463 // Handle object case
6464 SceneObjectPart part = World.GetSceneObjectPart(uuid);
6465 if (part != null)
6466 {
6467 // This will handle both deed and non-deed and also the no
6468 // group case
6469 if (part.ParentGroup.RootPart.GroupID == m_host.ParentGroup.RootPart.GroupID)
6470 return new LSL_Integer(1);
6471
5964 return new LSL_Integer(0); 6472 return new LSL_Integer(0);
6473 }
6474
6475 return new LSL_Integer(0);
5965 } 6476 }
5966 6477
5967 public void llUnSit(string id) 6478 public void llUnSit(string id)
@@ -6520,6 +7031,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6520 7031
6521 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot) 7032 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot)
6522 { 7033 {
7034 // LSL quaternions can normalize to 0, normal Quaternions can't.
7035 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
7036 rot.s = 1; // ZERO_ROTATION = 0,0,0,1
7037
6523 part.SitTargetPosition = offset; 7038 part.SitTargetPosition = offset;
6524 part.SitTargetOrientation = rot; 7039 part.SitTargetOrientation = rot;
6525 part.ParentGroup.HasGroupChanged = true; 7040 part.ParentGroup.HasGroupChanged = true;
@@ -6706,30 +7221,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6706 UUID av = new UUID(); 7221 UUID av = new UUID();
6707 if (!UUID.TryParse(avatar,out av)) 7222 if (!UUID.TryParse(avatar,out av))
6708 { 7223 {
6709 LSLError("First parameter to llDialog needs to be a key"); 7224 //LSLError("First parameter to llDialog needs to be a key");
6710 return; 7225 return;
6711 } 7226 }
6712 if (buttons.Length < 1) 7227 if (buttons.Length < 1)
6713 { 7228 {
6714 LSLError("No less than 1 button can be shown"); 7229 buttons.Add("OK");
6715 return;
6716 } 7230 }
6717 if (buttons.Length > 12) 7231 if (buttons.Length > 12)
6718 { 7232 {
6719 LSLError("No more than 12 buttons can be shown"); 7233 ShoutError("button list too long, must be 12 or fewer entries");
6720 return;
6721 } 7234 }
6722 string[] buts = new string[buttons.Length]; 7235 int length = buttons.Length;
6723 for (int i = 0; i < buttons.Length; i++) 7236 if (length > 12)
7237 length = 12;
7238
7239 string[] buts = new string[length];
7240 for (int i = 0; i < length; i++)
6724 { 7241 {
6725 if (buttons.Data[i].ToString() == String.Empty) 7242 if (buttons.Data[i].ToString() == String.Empty)
6726 { 7243 {
6727 LSLError("button label cannot be blank"); 7244 ShoutError("button label cannot be blank");
6728 return; 7245 return;
6729 } 7246 }
6730 if (buttons.Data[i].ToString().Length > 24) 7247 if (buttons.Data[i].ToString().Length > 24)
6731 { 7248 {
6732 LSLError("button label cannot be longer than 24 characters"); 7249 ShoutError("button label cannot be longer than 24 characters");
6733 return; 7250 return;
6734 } 7251 }
6735 buts[i] = buttons.Data[i].ToString(); 7252 buts[i] = buttons.Data[i].ToString();
@@ -6796,9 +7313,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6796 return; 7313 return;
6797 } 7314 }
6798 7315
6799 // the rest of the permission checks are done in RezScript, so check the pin there as well 7316 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6800 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); 7317 if (dest != null)
7318 {
7319 if ((item.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7320 {
7321 // the rest of the permission checks are done in RezScript, so check the pin there as well
7322 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
6801 7323
7324 if ((item.BasePermissions & (uint)PermissionMask.Copy) == 0)
7325 m_host.Inventory.RemoveInventoryItem(item.ItemID);
7326 }
7327 }
6802 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7328 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6803 ScriptSleep(3000); 7329 ScriptSleep(3000);
6804 } 7330 }
@@ -6872,19 +7398,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6872 public LSL_String llMD5String(string src, int nonce) 7398 public LSL_String llMD5String(string src, int nonce)
6873 { 7399 {
6874 m_host.AddScriptLPS(1); 7400 m_host.AddScriptLPS(1);
6875 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7401 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6876 } 7402 }
6877 7403
6878 public LSL_String llSHA1String(string src) 7404 public LSL_String llSHA1String(string src)
6879 { 7405 {
6880 m_host.AddScriptLPS(1); 7406 m_host.AddScriptLPS(1);
6881 return Util.SHA1Hash(src).ToLower(); 7407 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6882 } 7408 }
6883 7409
6884 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7410 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6885 { 7411 {
6886 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7412 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6887 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7413 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7414 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7415 return shapeBlock;
6888 7416
6889 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7417 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6890 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7418 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6989,6 +7517,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6989 // Prim type box, cylinder and prism. 7517 // Prim type box, cylinder and prism.
6990 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) 7518 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)
6991 { 7519 {
7520 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7521 return;
7522
6992 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7523 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6993 ObjectShapePacket.ObjectDataBlock shapeBlock; 7524 ObjectShapePacket.ObjectDataBlock shapeBlock;
6994 7525
@@ -7042,6 +7573,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7042 // Prim type sphere. 7573 // Prim type sphere.
7043 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7574 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
7044 { 7575 {
7576 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7577 return;
7578
7045 ObjectShapePacket.ObjectDataBlock shapeBlock; 7579 ObjectShapePacket.ObjectDataBlock shapeBlock;
7046 7580
7047 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7581 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -7083,6 +7617,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7083 // Prim type torus, tube and ring. 7617 // Prim type torus, tube and ring.
7084 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) 7618 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)
7085 { 7619 {
7620 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7621 return;
7622
7086 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7623 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7087 ObjectShapePacket.ObjectDataBlock shapeBlock; 7624 ObjectShapePacket.ObjectDataBlock shapeBlock;
7088 7625
@@ -7218,6 +7755,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7218 // Prim type sculpt. 7755 // Prim type sculpt.
7219 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7756 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7220 { 7757 {
7758 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7759 return;
7760
7221 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7761 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7222 UUID sculptId; 7762 UUID sculptId;
7223 7763
@@ -7240,7 +7780,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7240 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7780 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7241 { 7781 {
7242 // default 7782 // default
7243 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7783 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7244 } 7784 }
7245 7785
7246 part.Shape.SetSculptProperties((byte)type, sculptId); 7786 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7257,48 +7797,130 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7257 ScriptSleep(200); 7797 ScriptSleep(200);
7258 } 7798 }
7259 7799
7260 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7800 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7261 { 7801 {
7262 m_host.AddScriptLPS(1); 7802 m_host.AddScriptLPS(1);
7263 7803
7264 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); 7804 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
7805 }
7265 7806
7266 ScriptSleep(200); 7807 private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
7808 {
7809 List<object> parts = new List<object>();
7810 List<SceneObjectPart> prims = GetLinkParts(linknumber);
7811 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7812 foreach (SceneObjectPart p in prims)
7813 parts.Add(p);
7814 foreach (ScenePresence p in avatars)
7815 parts.Add(p);
7816
7817 LSL_List remaining = null;
7818 uint rulesParsed = 0;
7819
7820 if (parts.Count > 0)
7821 {
7822 foreach (object part in parts)
7823 {
7824 if (part is SceneObjectPart)
7825 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7826 else
7827 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7828 }
7829
7830 while ((object)remaining != null && remaining.Length > 2)
7831 {
7832 linknumber = remaining.GetLSLIntegerItem(0);
7833 rules = remaining.GetSublist(1, -1);
7834 parts.Clear();
7835 prims = GetLinkParts(linknumber);
7836 avatars = GetLinkAvatars(linknumber);
7837 foreach (SceneObjectPart p in prims)
7838 parts.Add(p);
7839 foreach (ScenePresence p in avatars)
7840 parts.Add(p);
7841
7842 remaining = null;
7843 foreach (object part in parts)
7844 {
7845 if (part is SceneObjectPart)
7846 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7847 else
7848 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7849 }
7850 }
7851 }
7267 } 7852 }
7268 7853
7269 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7854 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7855 float material_density, float material_friction,
7856 float material_restitution, float material_gravity_modifier)
7270 { 7857 {
7271 m_host.AddScriptLPS(1); 7858 ExtraPhysicsData physdata = new ExtraPhysicsData();
7859 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7860 physdata.Density = part.Density;
7861 physdata.Friction = part.Friction;
7862 physdata.Bounce = part.Restitution;
7863 physdata.GravitationModifier = part.GravityModifier;
7272 7864
7273 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); 7865 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7866 physdata.Density = material_density;
7867 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7868 physdata.Friction = material_friction;
7869 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7870 physdata.Bounce = material_restitution;
7871 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7872 physdata.GravitationModifier = material_gravity_modifier;
7873
7874 part.UpdateExtraPhysics(physdata);
7274 } 7875 }
7275 7876
7276 protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) 7877 public void llSetPhysicsMaterial(int material_bits,
7878 float material_gravity_modifier, float material_restitution,
7879 float material_friction, float material_density)
7277 { 7880 {
7278 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7881 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7882 }
7279 7883
7280 LSL_List remaining = null; 7884 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7281 uint rulesParsed = 0; 7885 {
7886 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
7887 llSetLinkPrimitiveParamsFast(linknumber, rules);
7888 ScriptSleep(200);
7889 }
7282 7890
7283 foreach (SceneObjectPart part in parts) 7891 // vector up using libomv (c&p from sop )
7284 remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); 7892 // vector up rotated by r
7893 private Vector3 Zrot(Quaternion r)
7894 {
7895 double x, y, z, m;
7285 7896
7286 while (remaining != null && remaining.Length > 2) 7897 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
7898 if (Math.Abs(1.0 - m) > 0.000001)
7287 { 7899 {
7288 linknumber = remaining.GetLSLIntegerItem(0); 7900 m = 1.0 / Math.Sqrt(m);
7289 rules = remaining.GetSublist(1, -1); 7901 r.X *= (float)m;
7290 parts = GetLinkParts(linknumber); 7902 r.Y *= (float)m;
7291 7903 r.Z *= (float)m;
7292 foreach (SceneObjectPart part in parts) 7904 r.W *= (float)m;
7293 remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed);
7294 } 7905 }
7906
7907 x = 2 * (r.X * r.Z + r.Y * r.W);
7908 y = 2 * (-r.X * r.W + r.Y * r.Z);
7909 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
7910
7911 return new Vector3((float)x, (float)y, (float)z);
7295 } 7912 }
7296 7913
7297 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) 7914 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
7298 { 7915 {
7916 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7917 return null;
7918
7299 int idx = 0; 7919 int idx = 0;
7300 int idxStart = 0; 7920 int idxStart = 0;
7301 7921
7922 SceneObjectGroup parentgrp = part.ParentGroup;
7923
7302 bool positionChanged = false; 7924 bool positionChanged = false;
7303 LSL_Vector currentPosition = GetPartLocalPos(part); 7925 LSL_Vector currentPosition = GetPartLocalPos(part);
7304 7926
@@ -7323,8 +7945,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7323 return null; 7945 return null;
7324 7946
7325 v=rules.GetVector3Item(idx++); 7947 v=rules.GetVector3Item(idx++);
7948 if (part.IsRoot && !part.ParentGroup.IsAttachment)
7949 currentPosition = GetSetPosTarget(part, v, currentPosition, true);
7950 else
7951 currentPosition = GetSetPosTarget(part, v, currentPosition, false);
7326 positionChanged = true; 7952 positionChanged = true;
7327 currentPosition = GetSetPosTarget(part, v, currentPosition);
7328 7953
7329 break; 7954 break;
7330 case (int)ScriptBaseClass.PRIM_SIZE: 7955 case (int)ScriptBaseClass.PRIM_SIZE:
@@ -7341,7 +7966,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7341 7966
7342 LSL_Rotation q = rules.GetQuaternionItem(idx++); 7967 LSL_Rotation q = rules.GetQuaternionItem(idx++);
7343 // try to let this work as in SL... 7968 // try to let this work as in SL...
7344 if (part.ParentID == 0) 7969 if (part.ParentID == 0 || (part.ParentGroup != null && part == part.ParentGroup.RootPart))
7345 { 7970 {
7346 // special case: If we are root, rotate complete SOG to new rotation 7971 // special case: If we are root, rotate complete SOG to new rotation
7347 SetRot(part, q); 7972 SetRot(part, q);
@@ -7601,7 +8226,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7601 return null; 8226 return null;
7602 8227
7603 string ph = rules.Data[idx++].ToString(); 8228 string ph = rules.Data[idx++].ToString();
7604 m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); 8229 parentgrp.ScriptSetPhantomStatus(ph.Equals("1"));
7605 8230
7606 break; 8231 break;
7607 8232
@@ -7635,12 +8260,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7635 8260
7636 break; 8261 break;
7637 8262
8263 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8264 if (remain < 5)
8265 return null;
8266
8267 int material_bits = rules.GetLSLIntegerItem(idx++);
8268 float material_density = (float)rules.GetLSLFloatItem(idx++);
8269 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8270 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8271 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8272
8273 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8274
8275 break;
8276
7638 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8277 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7639 if (remain < 1) 8278 if (remain < 1)
7640 return null; 8279 return null;
7641 string temp = rules.Data[idx++].ToString(); 8280 string temp = rules.Data[idx++].ToString();
7642 8281
7643 m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); 8282 parentgrp.ScriptSetTemporaryStatus(temp.Equals("1"));
7644 8283
7645 break; 8284 break;
7646 8285
@@ -7714,14 +8353,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7714 if (part.ParentGroup.RootPart == part) 8353 if (part.ParentGroup.RootPart == part)
7715 { 8354 {
7716 SceneObjectGroup parent = part.ParentGroup; 8355 SceneObjectGroup parent = part.ParentGroup;
7717 parent.UpdateGroupPosition(currentPosition); 8356 Util.FireAndForget(delegate(object x) {
8357 parent.UpdateGroupPosition(currentPosition);
8358 });
7718 } 8359 }
7719 else 8360 else
7720 { 8361 {
7721 part.OffsetPosition = currentPosition; 8362 part.OffsetPosition = currentPosition;
7722 SceneObjectGroup parent = part.ParentGroup; 8363// SceneObjectGroup parent = part.ParentGroup;
7723 parent.HasGroupChanged = true; 8364// parent.HasGroupChanged = true;
7724 parent.ScheduleGroupForTerseUpdate(); 8365// parent.ScheduleGroupForTerseUpdate();
8366 part.ScheduleTerseUpdate();
7725 } 8367 }
7726 } 8368 }
7727 } 8369 }
@@ -7759,10 +8401,91 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7759 8401
7760 public LSL_String llXorBase64Strings(string str1, string str2) 8402 public LSL_String llXorBase64Strings(string str1, string str2)
7761 { 8403 {
7762 m_host.AddScriptLPS(1); 8404 string b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7763 Deprecated("llXorBase64Strings"); 8405
7764 ScriptSleep(300); 8406 ScriptSleep(300);
7765 return String.Empty; 8407 m_host.AddScriptLPS(1);
8408
8409 if (str1 == String.Empty)
8410 return String.Empty;
8411 if (str2 == String.Empty)
8412 return str1;
8413
8414 int len = str2.Length;
8415 if ((len % 4) != 0) // LL is EVIL!!!!
8416 {
8417 while (str2.EndsWith("="))
8418 str2 = str2.Substring(0, str2.Length - 1);
8419
8420 len = str2.Length;
8421 int mod = len % 4;
8422
8423 if (mod == 1)
8424 str2 = str2.Substring(0, str2.Length - 1);
8425 else if (mod == 2)
8426 str2 += "==";
8427 else if (mod == 3)
8428 str2 += "=";
8429 }
8430
8431 byte[] data1;
8432 byte[] data2;
8433 try
8434 {
8435 data1 = Convert.FromBase64String(str1);
8436 data2 = Convert.FromBase64String(str2);
8437 }
8438 catch (Exception)
8439 {
8440 return new LSL_String(String.Empty);
8441 }
8442
8443 // For cases where the decoded length of s2 is greater
8444 // than the decoded length of s1, simply perform a normal
8445 // decode and XOR
8446 //
8447 if (data2.Length >= data1.Length)
8448 {
8449 for (int pos = 0 ; pos < data1.Length ; pos++ )
8450 data1[pos] ^= data2[pos];
8451
8452 return Convert.ToBase64String(data1);
8453 }
8454
8455 // Remove padding
8456 while (str1.EndsWith("="))
8457 str1 = str1.Substring(0, str1.Length - 1);
8458 while (str2.EndsWith("="))
8459 str2 = str2.Substring(0, str2.Length - 1);
8460
8461 byte[] d1 = new byte[str1.Length];
8462 byte[] d2 = new byte[str2.Length];
8463
8464 for (int i = 0 ; i < str1.Length ; i++)
8465 {
8466 int idx = b64.IndexOf(str1.Substring(i, 1));
8467 if (idx == -1)
8468 idx = 0;
8469 d1[i] = (byte)idx;
8470 }
8471
8472 for (int i = 0 ; i < str2.Length ; i++)
8473 {
8474 int idx = b64.IndexOf(str2.Substring(i, 1));
8475 if (idx == -1)
8476 idx = 0;
8477 d2[i] = (byte)idx;
8478 }
8479
8480 string output = String.Empty;
8481
8482 for (int pos = 0 ; pos < d1.Length ; pos++)
8483 output += b64[d1[pos] ^ d2[pos % d2.Length]];
8484
8485 while (output.Length % 3 > 0)
8486 output += "=";
8487
8488 return output;
7766 } 8489 }
7767 8490
7768 public void llRemoteDataSetRegion() 8491 public void llRemoteDataSetRegion()
@@ -7887,8 +8610,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7887 public LSL_Integer llGetNumberOfPrims() 8610 public LSL_Integer llGetNumberOfPrims()
7888 { 8611 {
7889 m_host.AddScriptLPS(1); 8612 m_host.AddScriptLPS(1);
7890 8613 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7891 return m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount(); 8614
8615 return m_host.ParentGroup.PrimCount + avatarCount;
7892 } 8616 }
7893 8617
7894 /// <summary> 8618 /// <summary>
@@ -7903,55 +8627,114 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7903 m_host.AddScriptLPS(1); 8627 m_host.AddScriptLPS(1);
7904 UUID objID = UUID.Zero; 8628 UUID objID = UUID.Zero;
7905 LSL_List result = new LSL_List(); 8629 LSL_List result = new LSL_List();
8630
8631 // If the ID is not valid, return null result
7906 if (!UUID.TryParse(obj, out objID)) 8632 if (!UUID.TryParse(obj, out objID))
7907 { 8633 {
7908 result.Add(new LSL_Vector()); 8634 result.Add(new LSL_Vector());
7909 result.Add(new LSL_Vector()); 8635 result.Add(new LSL_Vector());
7910 return result; 8636 return result;
7911 } 8637 }
8638
8639 // Check if this is an attached prim. If so, replace
8640 // the UUID with the avatar UUID and report it's bounding box
8641 SceneObjectPart part = World.GetSceneObjectPart(objID);
8642 if (part != null && part.ParentGroup.IsAttachment)
8643 objID = part.ParentGroup.AttachedAvatar;
8644
8645 // Find out if this is an avatar ID. If so, return it's box
7912 ScenePresence presence = World.GetScenePresence(objID); 8646 ScenePresence presence = World.GetScenePresence(objID);
7913 if (presence != null) 8647 if (presence != null)
7914 { 8648 {
7915 if (presence.ParentID == 0) // not sat on an object 8649 // As per LSL Wiki, there is no difference between sitting
8650 // and standing avatar since server 1.36
8651 LSL_Vector lower;
8652 LSL_Vector upper;
8653
8654 Vector3 box = presence.Appearance.AvatarBoxSize * 0.5f;
8655
8656 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID
8657 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
8658/*
7916 { 8659 {
7917 LSL_Vector lower; 8660 // This is for ground sitting avatars
7918 LSL_Vector upper; 8661 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7919 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID 8662 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7920 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8663 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7921 { 8664 }
7922 // This is for ground sitting avatars 8665 else
7923 float height = presence.Appearance.AvatarHeight / 2.66666667f; 8666 {
7924 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f); 8667 // This is for standing/flying avatars
7925 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f); 8668 float height = presence.Appearance.AvatarHeight / 2.0f;
7926 } 8669 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7927 else 8670 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7928 { 8671 }
7929 // This is for standing/flying avatars 8672
7930 float height = presence.Appearance.AvatarHeight / 2.0f; 8673 // Adjust to the documented error offsets (see LSL Wiki)
7931 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f); 8674 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
7932 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f); 8675 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
7933 } 8676*/
7934 result.Add(lower); 8677 {
7935 result.Add(upper); 8678 // This is for ground sitting avatars TODO!
7936 return result; 8679 lower = new LSL_Vector(-box.X - 0.1125, -box.Y, box.Z * -1.0f);
8680 upper = new LSL_Vector(box.X + 0.1125, box.Y, box.Z * -1.0f);
7937 } 8681 }
7938 else 8682 else
7939 { 8683 {
7940 // sitting on an object so we need the bounding box of that 8684 // This is for standing/flying avatars
7941 // which should include the avatar so set the UUID to the 8685 lower = new LSL_Vector(-box.X, -box.Y, -box.Z);
7942 // UUID of the object the avatar is sat on and allow it to fall through 8686 upper = new LSL_Vector(box.X, box.Y, box.Z);
7943 // to processing an object
7944 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7945 objID = p.UUID;
7946 } 8687 }
8688
8689 if (lower.x > upper.x)
8690 lower.x = upper.x;
8691 if (lower.y > upper.y)
8692 lower.y = upper.y;
8693 if (lower.z > upper.z)
8694 lower.z = upper.z;
8695
8696 result.Add(lower);
8697 result.Add(upper);
8698 return result;
7947 } 8699 }
7948 SceneObjectPart part = World.GetSceneObjectPart(objID); 8700
8701 part = World.GetSceneObjectPart(objID);
7949 // Currently only works for single prims without a sitting avatar 8702 // Currently only works for single prims without a sitting avatar
7950 if (part != null) 8703 if (part != null)
7951 { 8704 {
7952 Vector3 halfSize = part.Scale / 2.0f; 8705 float minX;
7953 LSL_Vector lower = (new LSL_Vector(halfSize)) * -1.0f; 8706 float maxX;
7954 LSL_Vector upper = new LSL_Vector(halfSize); 8707 float minY;
8708 float maxY;
8709 float minZ;
8710 float maxZ;
8711
8712 // This BBox is in sim coordinates, with the offset being
8713 // a contained point.
8714 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8715 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8716
8717 minX -= offsets[0].X;
8718 maxX -= offsets[0].X;
8719 minY -= offsets[0].Y;
8720 maxY -= offsets[0].Y;
8721 minZ -= offsets[0].Z;
8722 maxZ -= offsets[0].Z;
8723
8724 LSL_Vector lower;
8725 LSL_Vector upper;
8726
8727 // Adjust to the documented error offsets (see LSL Wiki)
8728 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8729 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8730
8731 if (lower.x > upper.x)
8732 lower.x = upper.x;
8733 if (lower.y > upper.y)
8734 lower.y = upper.y;
8735 if (lower.z > upper.z)
8736 lower.z = upper.z;
8737
7955 result.Add(lower); 8738 result.Add(lower);
7956 result.Add(upper); 8739 result.Add(upper);
7957 return result; 8740 return result;
@@ -7968,224 +8751,74 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7968 return new LSL_Vector(m_host.GetGeometricCenter()); 8751 return new LSL_Vector(m_host.GetGeometricCenter());
7969 } 8752 }
7970 8753
7971 public LSL_List GetEntityParams(ISceneEntity entity, LSL_List rules) 8754 public LSL_List llGetPrimitiveParams(LSL_List rules)
7972 { 8755 {
7973 LSL_List result = new LSL_List(); 8756 m_host.AddScriptLPS(1);
7974 LSL_List remaining = null;
7975 8757
7976 while (true) 8758 LSL_List result = new LSL_List();
7977 {
7978 if (entity is SceneObjectPart)
7979 remaining = GetPrimParams((SceneObjectPart)entity, rules, ref result);
7980 else
7981 remaining = GetAgentParams((ScenePresence)entity, rules, ref result);
7982 8759
7983 if (remaining == null || remaining.Length <= 2) 8760 LSL_List remaining = GetPrimParams(m_host, rules, ref result);
7984 return result;
7985 8761
8762 while ((object)remaining != null && remaining.Length > 2)
8763 {
7986 int linknumber = remaining.GetLSLIntegerItem(0); 8764 int linknumber = remaining.GetLSLIntegerItem(0);
7987 rules = remaining.GetSublist(1, -1); 8765 rules = remaining.GetSublist(1, -1);
7988 entity = GetLinkEntity(linknumber); 8766 List<SceneObjectPart> parts = GetLinkParts(linknumber);
7989 }
7990 }
7991 8767
7992 public LSL_List llGetPrimitiveParams(LSL_List rules) 8768 foreach (SceneObjectPart part in parts)
7993 { 8769 remaining = GetPrimParams(part, rules, ref result);
7994 m_host.AddScriptLPS(1); 8770 }
7995 8771
7996 return GetEntityParams(m_host, rules); 8772 return result;
7997 } 8773 }
7998 8774
7999 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) 8775 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
8000 { 8776 {
8001 m_host.AddScriptLPS(1); 8777 m_host.AddScriptLPS(1);
8002 8778
8003 return GetEntityParams(GetLinkEntity(linknumber), rules); 8779 // acording to SL wiki this must indicate a single link number or link_root or link_this.
8004 } 8780 // keep other options as before
8005 8781
8006 public LSL_Vector GetAgentSize(ScenePresence sp) 8782 List<SceneObjectPart> parts;
8007 { 8783 List<ScenePresence> avatars;
8008 return new LSL_Vector(0.45, 0.6, sp.Appearance.AvatarHeight); 8784
8009 } 8785 LSL_List res = new LSL_List();
8786 LSL_List remaining = null;
8010 8787
8011 /// <summary> 8788 while (rules.Length > 0)
8012 /// Gets params for a seated avatar in a linkset.
8013 /// </summary>
8014 /// <returns></returns>
8015 /// <param name='sp'></param>
8016 /// <param name='rules'></param>
8017 /// <param name='res'></param>
8018 public LSL_List GetAgentParams(ScenePresence sp, LSL_List rules, ref LSL_List res)
8019 {
8020 int idx = 0;
8021 while (idx < rules.Length)
8022 { 8789 {
8023 int code = (int)rules.GetLSLIntegerItem(idx++); 8790 parts = GetLinkParts(linknumber);
8024 int remain = rules.Length-idx; 8791 avatars = GetLinkAvatars(linknumber);
8025 8792
8026 switch (code) 8793 remaining = null;
8794 foreach (SceneObjectPart part in parts)
8027 { 8795 {
8028 case (int)ScriptBaseClass.PRIM_MATERIAL: 8796 remaining = GetPrimParams(part, rules, ref res);
8029 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MATERIAL_FLESH)); 8797 }
8030 break; 8798 foreach (ScenePresence avatar in avatars)
8031 8799 {
8032 case (int)ScriptBaseClass.PRIM_PHYSICS: 8800 remaining = GetPrimParams(avatar, rules, ref res);
8033 res.Add(ScriptBaseClass.FALSE); 8801 }
8034 break;
8035
8036 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
8037 res.Add(ScriptBaseClass.FALSE);
8038 break;
8039
8040 case (int)ScriptBaseClass.PRIM_PHANTOM:
8041 res.Add(ScriptBaseClass.FALSE);
8042 break;
8043
8044 case (int)ScriptBaseClass.PRIM_POSITION:
8045 res.Add(new LSL_Vector(sp.AbsolutePosition));
8046 break;
8047
8048 case (int)ScriptBaseClass.PRIM_SIZE:
8049 res.Add(GetAgentSize(sp));
8050 break;
8051
8052 case (int)ScriptBaseClass.PRIM_ROTATION:
8053 res.Add(sp.GetWorldRotation());
8054 break;
8055
8056 case (int)ScriptBaseClass.PRIM_TYPE:
8057 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
8058 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
8059 res.Add(new LSL_Vector(0, 1, 0));
8060 res.Add(new LSL_Float(0));
8061 res.Add(new LSL_Vector(0, 0, 0));
8062 res.Add(new LSL_Vector(1, 1, 0));
8063 res.Add(new LSL_Vector(0, 0, 0));
8064 break;
8065
8066 case (int)ScriptBaseClass.PRIM_TEXTURE:
8067 if (remain < 1)
8068 return null;
8069
8070 int face = (int)rules.GetLSLIntegerItem(idx++);
8071 if (face > 21)
8072 break;
8073
8074 res.Add(new LSL_String(""));
8075 res.Add(ScriptBaseClass.ZERO_VECTOR);
8076 res.Add(ScriptBaseClass.ZERO_VECTOR);
8077 res.Add(new LSL_Float(0));
8078 break;
8079
8080 case (int)ScriptBaseClass.PRIM_COLOR:
8081 if (remain < 1)
8082 return null;
8083
8084 face = (int)rules.GetLSLIntegerItem(idx++);
8085 if (face > 21)
8086 break;
8087
8088 res.Add(ScriptBaseClass.ZERO_VECTOR);
8089 res.Add(new LSL_Float(0));
8090 break;
8091
8092 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8093 if (remain < 1)
8094 return null;
8095
8096 face = (int)rules.GetLSLIntegerItem(idx++);
8097 if (face > 21)
8098 break;
8099
8100 res.Add(ScriptBaseClass.PRIM_SHINY_NONE);
8101 res.Add(ScriptBaseClass.PRIM_BUMP_NONE);
8102 break;
8103
8104 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8105 if (remain < 1)
8106 return null;
8107
8108 face = (int)rules.GetLSLIntegerItem(idx++);
8109 if (face > 21)
8110 break;
8111
8112 res.Add(ScriptBaseClass.FALSE);
8113 break;
8114
8115 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
8116 res.Add(ScriptBaseClass.FALSE);
8117 res.Add(new LSL_Integer(0));
8118 res.Add(new LSL_Float(0));
8119 res.Add(new LSL_Float(0));
8120 res.Add(new LSL_Float(0));
8121 res.Add(new LSL_Float(0));
8122 res.Add(ScriptBaseClass.ZERO_VECTOR);
8123 break;
8124
8125 case (int)ScriptBaseClass.PRIM_TEXGEN:
8126 if (remain < 1)
8127 return null;
8128
8129 face = (int)rules.GetLSLIntegerItem(idx++);
8130 if (face > 21)
8131 break;
8132
8133 res.Add(ScriptBaseClass.PRIM_TEXGEN_DEFAULT);
8134 break;
8135
8136 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
8137 res.Add(ScriptBaseClass.FALSE);
8138 res.Add(ScriptBaseClass.ZERO_VECTOR);
8139 res.Add(ScriptBaseClass.ZERO_VECTOR);
8140 break;
8141
8142 case (int)ScriptBaseClass.PRIM_GLOW:
8143 if (remain < 1)
8144 return null;
8145
8146 face = (int)rules.GetLSLIntegerItem(idx++);
8147 if (face > 21)
8148 break;
8149
8150 res.Add(new LSL_Float(0));
8151 break;
8152
8153 case (int)ScriptBaseClass.PRIM_TEXT:
8154 res.Add(new LSL_String(""));
8155 res.Add(ScriptBaseClass.ZERO_VECTOR);
8156 res.Add(new LSL_Float(1));
8157 break;
8158
8159 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8160 res.Add(new LSL_Rotation(sp.Rotation));
8161 break;
8162
8163 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
8164 res.Add(new LSL_Vector(sp.OffsetPosition));
8165 break;
8166
8167 case (int)ScriptBaseClass.PRIM_SLICE:
8168 res.Add(new LSL_Vector(0, 1, 0));
8169 break;
8170
8171 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
8172 if(remain < 3)
8173 return null;
8174 8802
8175 return rules.GetSublist(idx, -1); 8803 if ((object)remaining != null && remaining.Length > 0)
8804 {
8805 linknumber = remaining.GetLSLIntegerItem(0);
8806 rules = remaining.GetSublist(1, -1);
8176 } 8807 }
8808 else
8809 break;
8177 } 8810 }
8178 8811
8179 return null; 8812 return res;
8180 } 8813 }
8181 8814
8182 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) 8815 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res)
8183 { 8816 {
8184 int idx = 0; 8817 int idx=0;
8185 while (idx < rules.Length) 8818 while (idx < rules.Length)
8186 { 8819 {
8187 int code = (int)rules.GetLSLIntegerItem(idx++); 8820 int code=(int)rules.GetLSLIntegerItem(idx++);
8188 int remain = rules.Length-idx; 8821 int remain=rules.Length-idx;
8189 8822
8190 switch (code) 8823 switch (code)
8191 { 8824 {
@@ -8215,19 +8848,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8215 break; 8848 break;
8216 8849
8217 case (int)ScriptBaseClass.PRIM_POSITION: 8850 case (int)ScriptBaseClass.PRIM_POSITION:
8218 LSL_Vector v = new LSL_Vector(part.AbsolutePosition); 8851 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
8219 8852 part.AbsolutePosition.Y,
8220 // For some reason, the part.AbsolutePosition.* values do not change if the 8853 part.AbsolutePosition.Z);
8221 // linkset is rotated; they always reflect the child prim's world position
8222 // as though the linkset is unrotated. This is incompatible behavior with SL's
8223 // implementation, so will break scripts imported from there (not to mention it
8224 // makes it more difficult to determine a child prim's actual inworld position).
8225 if (!part.IsRoot)
8226 {
8227 LSL_Vector rootPos = new LSL_Vector(m_host.ParentGroup.AbsolutePosition);
8228 v = ((v - rootPos) * llGetRootRotation()) + rootPos;
8229 }
8230
8231 res.Add(v); 8854 res.Add(v);
8232 break; 8855 break;
8233 8856
@@ -8397,30 +9020,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8397 if (remain < 1) 9020 if (remain < 1)
8398 return null; 9021 return null;
8399 9022
8400 face=(int)rules.GetLSLIntegerItem(idx++); 9023 face = (int)rules.GetLSLIntegerItem(idx++);
8401 9024
8402 tex = part.Shape.Textures; 9025 tex = part.Shape.Textures;
9026 int shiny;
8403 if (face == ScriptBaseClass.ALL_SIDES) 9027 if (face == ScriptBaseClass.ALL_SIDES)
8404 { 9028 {
8405 for (face = 0; face < GetNumberOfSides(part); face++) 9029 for (face = 0; face < GetNumberOfSides(part); face++)
8406 { 9030 {
8407 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9031 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8408 // Convert Shininess to PRIM_SHINY_* 9032 if (shinyness == Shininess.High)
8409 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 9033 {
8410 // PRIM_BUMP_* 9034 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8411 res.Add(new LSL_Integer((int)texface.Bump)); 9035 }
9036 else if (shinyness == Shininess.Medium)
9037 {
9038 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
9039 }
9040 else if (shinyness == Shininess.Low)
9041 {
9042 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
9043 }
9044 else
9045 {
9046 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
9047 }
9048 res.Add(new LSL_Integer(shiny));
9049 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8412 } 9050 }
8413 } 9051 }
8414 else 9052 else
8415 { 9053 {
8416 if (face >= 0 && face < GetNumberOfSides(part)) 9054 Shininess shinyness = tex.GetFace((uint)face).Shiny;
9055 if (shinyness == Shininess.High)
8417 { 9056 {
8418 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9057 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8419 // Convert Shininess to PRIM_SHINY_*
8420 res.Add(new LSL_Integer((uint)texface.Shiny >> 6));
8421 // PRIM_BUMP_*
8422 res.Add(new LSL_Integer((int)texface.Bump));
8423 } 9058 }
9059 else if (shinyness == Shininess.Medium)
9060 {
9061 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
9062 }
9063 else if (shinyness == Shininess.Low)
9064 {
9065 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
9066 }
9067 else
9068 {
9069 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
9070 }
9071 res.Add(new LSL_Integer(shiny));
9072 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8424 } 9073 }
8425 break; 9074 break;
8426 9075
@@ -8431,21 +9080,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8431 face = (int)rules.GetLSLIntegerItem(idx++); 9080 face = (int)rules.GetLSLIntegerItem(idx++);
8432 9081
8433 tex = part.Shape.Textures; 9082 tex = part.Shape.Textures;
9083 int fullbright;
8434 if (face == ScriptBaseClass.ALL_SIDES) 9084 if (face == ScriptBaseClass.ALL_SIDES)
8435 { 9085 {
8436 for (face = 0; face < GetNumberOfSides(part); face++) 9086 for (face = 0; face < GetNumberOfSides(part); face++)
8437 { 9087 {
8438 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9088 if (tex.GetFace((uint)face).Fullbright == true)
8439 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 9089 {
9090 fullbright = ScriptBaseClass.TRUE;
9091 }
9092 else
9093 {
9094 fullbright = ScriptBaseClass.FALSE;
9095 }
9096 res.Add(new LSL_Integer(fullbright));
8440 } 9097 }
8441 } 9098 }
8442 else 9099 else
8443 { 9100 {
8444 if (face >= 0 && face < GetNumberOfSides(part)) 9101 if (tex.GetFace((uint)face).Fullbright == true)
8445 { 9102 {
8446 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9103 fullbright = ScriptBaseClass.TRUE;
8447 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 9104 }
9105 else
9106 {
9107 fullbright = ScriptBaseClass.FALSE;
8448 } 9108 }
9109 res.Add(new LSL_Integer(fullbright));
8449 } 9110 }
8450 break; 9111 break;
8451 9112
@@ -8467,27 +9128,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8467 break; 9128 break;
8468 9129
8469 case (int)ScriptBaseClass.PRIM_TEXGEN: 9130 case (int)ScriptBaseClass.PRIM_TEXGEN:
9131 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8470 if (remain < 1) 9132 if (remain < 1)
8471 return null; 9133 return null;
8472 9134
8473 face=(int)rules.GetLSLIntegerItem(idx++); 9135 face = (int)rules.GetLSLIntegerItem(idx++);
8474 9136
8475 tex = part.Shape.Textures; 9137 tex = part.Shape.Textures;
8476 if (face == ScriptBaseClass.ALL_SIDES) 9138 if (face == ScriptBaseClass.ALL_SIDES)
8477 { 9139 {
8478 for (face = 0; face < GetNumberOfSides(part); face++) 9140 for (face = 0; face < GetNumberOfSides(part); face++)
8479 { 9141 {
8480 MappingType texgen = tex.GetFace((uint)face).TexMapType; 9142 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8481 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 9143 {
8482 res.Add(new LSL_Integer((uint)texgen >> 1)); 9144 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
9145 }
9146 else
9147 {
9148 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
9149 }
8483 } 9150 }
8484 } 9151 }
8485 else 9152 else
8486 { 9153 {
8487 if (face >= 0 && face < GetNumberOfSides(part)) 9154 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
9155 {
9156 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
9157 }
9158 else
8488 { 9159 {
8489 MappingType texgen = tex.GetFace((uint)face).TexMapType; 9160 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8490 res.Add(new LSL_Integer((uint)texgen >> 1));
8491 } 9161 }
8492 } 9162 }
8493 break; 9163 break;
@@ -8511,24 +9181,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8511 if (remain < 1) 9181 if (remain < 1)
8512 return null; 9182 return null;
8513 9183
8514 face=(int)rules.GetLSLIntegerItem(idx++); 9184 face = (int)rules.GetLSLIntegerItem(idx++);
8515 9185
8516 tex = part.Shape.Textures; 9186 tex = part.Shape.Textures;
9187 float primglow;
8517 if (face == ScriptBaseClass.ALL_SIDES) 9188 if (face == ScriptBaseClass.ALL_SIDES)
8518 { 9189 {
8519 for (face = 0; face < GetNumberOfSides(part); face++) 9190 for (face = 0; face < GetNumberOfSides(part); face++)
8520 { 9191 {
8521 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9192 primglow = tex.GetFace((uint)face).Glow;
8522 res.Add(new LSL_Float(texface.Glow)); 9193 res.Add(new LSL_Float(primglow));
8523 } 9194 }
8524 } 9195 }
8525 else 9196 else
8526 { 9197 {
8527 if (face >= 0 && face < GetNumberOfSides(part)) 9198 primglow = tex.GetFace((uint)face).Glow;
8528 { 9199 res.Add(new LSL_Float(primglow));
8529 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8530 res.Add(new LSL_Float(texface.Glow));
8531 }
8532 } 9200 }
8533 break; 9201 break;
8534 9202
@@ -8540,15 +9208,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8540 textColor.B)); 9208 textColor.B));
8541 res.Add(new LSL_Float(textColor.A)); 9209 res.Add(new LSL_Float(textColor.A));
8542 break; 9210 break;
9211
8543 case (int)ScriptBaseClass.PRIM_NAME: 9212 case (int)ScriptBaseClass.PRIM_NAME:
8544 res.Add(new LSL_String(part.Name)); 9213 res.Add(new LSL_String(part.Name));
8545 break; 9214 break;
9215
8546 case (int)ScriptBaseClass.PRIM_DESC: 9216 case (int)ScriptBaseClass.PRIM_DESC:
8547 res.Add(new LSL_String(part.Description)); 9217 res.Add(new LSL_String(part.Description));
8548 break; 9218 break;
8549 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 9219 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8550 res.Add(new LSL_Rotation(part.RotationOffset)); 9220 res.Add(new LSL_Rotation(part.RotationOffset));
8551 break; 9221 break;
9222
8552 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 9223 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
8553 res.Add(new LSL_Vector(GetPartLocalPos(part))); 9224 res.Add(new LSL_Vector(GetPartLocalPos(part)));
8554 break; 9225 break;
@@ -9159,8 +9830,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9159 // The function returns an ordered list 9830 // The function returns an ordered list
9160 // representing the tokens found in the supplied 9831 // representing the tokens found in the supplied
9161 // sources string. If two successive tokenizers 9832 // sources string. If two successive tokenizers
9162 // are encountered, then a NULL entry is added 9833 // are encountered, then a null-string entry is
9163 // to the list. 9834 // added to the list.
9164 // 9835 //
9165 // It is a precondition that the source and 9836 // It is a precondition that the source and
9166 // toekizer lisst are non-null. If they are null, 9837 // toekizer lisst are non-null. If they are null,
@@ -9168,7 +9839,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9168 // while their lengths are being determined. 9839 // while their lengths are being determined.
9169 // 9840 //
9170 // A small amount of working memoryis required 9841 // A small amount of working memoryis required
9171 // of approximately 8*#tokenizers. 9842 // of approximately 8*#tokenizers + 8*srcstrlen.
9172 // 9843 //
9173 // There are many ways in which this function 9844 // There are many ways in which this function
9174 // can be implemented, this implementation is 9845 // can be implemented, this implementation is
@@ -9184,155 +9855,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9184 // and eliminates redundant tokenizers as soon 9855 // and eliminates redundant tokenizers as soon
9185 // as is possible. 9856 // as is possible.
9186 // 9857 //
9187 // The implementation tries to avoid any copying 9858 // The implementation tries to minimize temporary
9188 // of arrays or other objects. 9859 // garbage generation.
9189 // </remarks> 9860 // </remarks>
9190 9861
9191 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9862 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
9192 { 9863 {
9193 int beginning = 0; 9864 return ParseString2List(src, separators, spacers, true);
9194 int srclen = src.Length; 9865 }
9195 int seplen = separators.Length;
9196 object[] separray = separators.Data;
9197 int spclen = spacers.Length;
9198 object[] spcarray = spacers.Data;
9199 int mlen = seplen+spclen;
9200
9201 int[] offset = new int[mlen+1];
9202 bool[] active = new bool[mlen];
9203
9204 int best;
9205 int j;
9206
9207 // Initial capacity reduces resize cost
9208 9866
9209 LSL_List tokens = new LSL_List(); 9867 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9868 {
9869 int srclen = src.Length;
9870 int seplen = separators.Length;
9871 object[] separray = separators.Data;
9872 int spclen = spacers.Length;
9873 object[] spcarray = spacers.Data;
9874 int dellen = 0;
9875 string[] delarray = new string[seplen+spclen];
9210 9876
9211 // All entries are initially valid 9877 int outlen = 0;
9878 string[] outarray = new string[srclen*2+1];
9212 9879
9213 for (int i = 0; i < mlen; i++) 9880 int i, j;
9214 active[i] = true; 9881 string d;
9215 9882
9216 offset[mlen] = srclen; 9883 m_host.AddScriptLPS(1);
9217 9884
9218 while (beginning < srclen) 9885 /*
9886 * Convert separator and spacer lists to C# strings.
9887 * Also filter out null strings so we don't hang.
9888 */
9889 for (i = 0; i < seplen; i ++)
9219 { 9890 {
9891 d = separray[i].ToString();
9892 if (d.Length > 0)
9893 {
9894 delarray[dellen++] = d;
9895 }
9896 }
9897 seplen = dellen;
9220 9898
9221 best = mlen; // as bad as it gets 9899 for (i = 0; i < spclen; i ++)
9900 {
9901 d = spcarray[i].ToString();
9902 if (d.Length > 0)
9903 {
9904 delarray[dellen++] = d;
9905 }
9906 }
9222 9907
9223 // Scan for separators 9908 /*
9909 * Scan through source string from beginning to end.
9910 */
9911 for (i = 0;;)
9912 {
9224 9913
9225 for (j = 0; j < seplen; j++) 9914 /*
9915 * Find earliest delimeter in src starting at i (if any).
9916 */
9917 int earliestDel = -1;
9918 int earliestSrc = srclen;
9919 string earliestStr = null;
9920 for (j = 0; j < dellen; j ++)
9226 { 9921 {
9227 if (separray[j].ToString() == String.Empty) 9922 d = delarray[j];
9228 active[j] = false; 9923 if (d != null)
9229
9230 if (active[j])
9231 { 9924 {
9232 // scan all of the markers 9925 int index = src.IndexOf(d, i);
9233 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9926 if (index < 0)
9234 { 9927 {
9235 // not present at all 9928 delarray[j] = null; // delim nowhere in src, don't check it anymore
9236 active[j] = false;
9237 } 9929 }
9238 else 9930 else if (index < earliestSrc)
9239 { 9931 {
9240 // present and correct 9932 earliestSrc = index; // where delimeter starts in source string
9241 if (offset[j] < offset[best]) 9933 earliestDel = j; // where delimeter is in delarray[]
9242 { 9934 earliestStr = d; // the delimeter string from delarray[]
9243 // closest so far 9935 if (index == i) break; // can't do any better than found at beg of string
9244 best = j;
9245 if (offset[best] == beginning)
9246 break;
9247 }
9248 } 9936 }
9249 } 9937 }
9250 } 9938 }
9251 9939
9252 // Scan for spacers 9940 /*
9253 9941 * Output source string starting at i through start of earliest delimeter.
9254 if (offset[best] != beginning) 9942 */
9943 if (keepNulls || (earliestSrc > i))
9255 { 9944 {
9256 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9945 outarray[outlen++] = src.Substring(i, earliestSrc - i);
9257 {
9258 if (spcarray[j-seplen].ToString() == String.Empty)
9259 active[j] = false;
9260
9261 if (active[j])
9262 {
9263 // scan all of the markers
9264 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
9265 {
9266 // not present at all
9267 active[j] = false;
9268 }
9269 else
9270 {
9271 // present and correct
9272 if (offset[j] < offset[best])
9273 {
9274 // closest so far
9275 best = j;
9276 }
9277 }
9278 }
9279 }
9280 } 9946 }
9281 9947
9282 // This is the normal exit from the scanning loop 9948 /*
9949 * If no delimeter found at or after i, we're done scanning.
9950 */
9951 if (earliestDel < 0) break;
9283 9952
9284 if (best == mlen) 9953 /*
9954 * If delimeter was a spacer, output the spacer.
9955 */
9956 if (earliestDel >= seplen)
9285 { 9957 {
9286 // no markers were found on this pass 9958 outarray[outlen++] = earliestStr;
9287 // so we're pretty much done
9288 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
9289 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
9290 break;
9291 } 9959 }
9292 9960
9293 // Otherwise we just add the newly delimited token 9961 /*
9294 // and recalculate where the search should continue. 9962 * Look at rest of src string following delimeter.
9295 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9963 */
9296 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9964 i = earliestSrc + earliestStr.Length;
9297
9298 if (best < seplen)
9299 {
9300 beginning = offset[best] + (separray[best].ToString()).Length;
9301 }
9302 else
9303 {
9304 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
9305 string str = spcarray[best - seplen].ToString();
9306 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
9307 tokens.Add(new LSL_String(str));
9308 }
9309 } 9965 }
9310 9966
9311 // This an awkward an not very intuitive boundary case. If the 9967 /*
9312 // last substring is a tokenizer, then there is an implied trailing 9968 * Make up an exact-sized output array suitable for an LSL_List object.
9313 // null list entry. Hopefully the single comparison will not be too 9969 */
9314 // arduous. Alternatively the 'break' could be replced with a return 9970 object[] outlist = new object[outlen];
9315 // but that's shabby programming. 9971 for (i = 0; i < outlen; i ++)
9316
9317 if ((beginning == srclen) && (keepNulls))
9318 { 9972 {
9319 if (srclen != 0) 9973 outlist[i] = new LSL_String(outarray[i]);
9320 tokens.Add(new LSL_String(""));
9321 } 9974 }
9322 9975 return new LSL_List(outlist);
9323 return tokens;
9324 }
9325
9326 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
9327 {
9328 m_host.AddScriptLPS(1);
9329 return this.ParseString(src, separators, spacers, false);
9330 }
9331
9332 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
9333 {
9334 m_host.AddScriptLPS(1);
9335 return this.ParseString(src, separators, spacers, true);
9336 } 9976 }
9337 9977
9338 public LSL_Integer llGetObjectPermMask(int mask) 9978 public LSL_Integer llGetObjectPermMask(int mask)
@@ -9427,6 +10067,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9427 case 4: 10067 case 4:
9428 return (int)item.NextPermissions; 10068 return (int)item.NextPermissions;
9429 } 10069 }
10070 m_host.TaskInventory.LockItemsForRead(false);
9430 10071
9431 return -1; 10072 return -1;
9432 } 10073 }
@@ -9630,31 +10271,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9630 UUID key = new UUID(); 10271 UUID key = new UUID();
9631 if (UUID.TryParse(id, out key)) 10272 if (UUID.TryParse(id, out key))
9632 { 10273 {
9633 try 10274 // return total object mass
9634 { 10275 SceneObjectPart part = World.GetSceneObjectPart(key);
9635 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 10276 if (part != null)
9636 if (obj != null) 10277 return part.ParentGroup.GetMass();
9637 return (double)obj.GetMass(); 10278
9638 // the object is null so the key is for an avatar 10279 // the object is null so the key is for an avatar
9639 ScenePresence avatar = World.GetScenePresence(key); 10280 ScenePresence avatar = World.GetScenePresence(key);
9640 if (avatar != null) 10281 if (avatar != null)
9641 if (avatar.IsChildAgent)
9642 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
9643 // child agents have a mass of 1.0
9644 return 1;
9645 else
9646 return (double)avatar.GetMass();
9647 }
9648 catch (KeyNotFoundException)
9649 { 10282 {
9650 return 0; // The Object/Agent not in the region so just return zero 10283 if (avatar.IsChildAgent)
10284 {
10285 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
10286 // child agents have a mass of 1.0
10287 return 1;
10288 }
10289 else
10290 {
10291 return (double)avatar.GetMass();
10292 }
9651 } 10293 }
9652 } 10294 }
9653 return 0; 10295 return 0;
9654 } 10296 }
9655 10297
9656 /// <summary> 10298 /// <summary>
9657 /// illListReplaceList removes the sub-list defined by the inclusive indices 10299 /// llListReplaceList removes the sub-list defined by the inclusive indices
9658 /// start and end and inserts the src list in its place. The inclusive 10300 /// start and end and inserts the src list in its place. The inclusive
9659 /// nature of the indices means that at least one element must be deleted 10301 /// nature of the indices means that at least one element must be deleted
9660 /// if the indices are within the bounds of the existing list. I.e. 2,2 10302 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9711,16 +10353,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9711 // based upon end. Note that if end exceeds the upper 10353 // based upon end. Note that if end exceeds the upper
9712 // bound in this case, the entire destination list 10354 // bound in this case, the entire destination list
9713 // is removed. 10355 // is removed.
9714 else 10356 else if (start == 0)
9715 { 10357 {
9716 if (end + 1 < dest.Length) 10358 if (end + 1 < dest.Length)
9717 {
9718 return src + dest.GetSublist(end + 1, -1); 10359 return src + dest.GetSublist(end + 1, -1);
9719 }
9720 else 10360 else
9721 {
9722 return src; 10361 return src;
9723 } 10362 }
10363 else // Start < 0
10364 {
10365 if (end + 1 < dest.Length)
10366 return dest.GetSublist(end + 1, -1);
10367 else
10368 return new LSL_List();
9724 } 10369 }
9725 } 10370 }
9726 // Finally, if start > end, we strip away a prefix and 10371 // Finally, if start > end, we strip away a prefix and
@@ -9771,17 +10416,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9771 int width = 0; 10416 int width = 0;
9772 int height = 0; 10417 int height = 0;
9773 10418
9774 ParcelMediaCommandEnum? commandToSend = null; 10419 uint commandToSend = 0;
9775 float time = 0.0f; // default is from start 10420 float time = 0.0f; // default is from start
9776 10421
9777 ScenePresence presence = null; 10422 ScenePresence presence = null;
9778 10423
9779 for (int i = 0; i < commandList.Data.Length; i++) 10424 for (int i = 0; i < commandList.Data.Length; i++)
9780 { 10425 {
9781 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10426 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9782 switch (command) 10427 switch (command)
9783 { 10428 {
9784 case ParcelMediaCommandEnum.Agent: 10429 case (uint)ParcelMediaCommandEnum.Agent:
9785 // we send only to one agent 10430 // we send only to one agent
9786 if ((i + 1) < commandList.Length) 10431 if ((i + 1) < commandList.Length)
9787 { 10432 {
@@ -9798,25 +10443,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9798 } 10443 }
9799 break; 10444 break;
9800 10445
9801 case ParcelMediaCommandEnum.Loop: 10446 case (uint)ParcelMediaCommandEnum.Loop:
9802 loop = 1; 10447 loop = 1;
9803 commandToSend = command; 10448 commandToSend = command;
9804 update = true; //need to send the media update packet to set looping 10449 update = true; //need to send the media update packet to set looping
9805 break; 10450 break;
9806 10451
9807 case ParcelMediaCommandEnum.Play: 10452 case (uint)ParcelMediaCommandEnum.Play:
9808 loop = 0; 10453 loop = 0;
9809 commandToSend = command; 10454 commandToSend = command;
9810 update = true; //need to send the media update packet to make sure it doesn't loop 10455 update = true; //need to send the media update packet to make sure it doesn't loop
9811 break; 10456 break;
9812 10457
9813 case ParcelMediaCommandEnum.Pause: 10458 case (uint)ParcelMediaCommandEnum.Pause:
9814 case ParcelMediaCommandEnum.Stop: 10459 case (uint)ParcelMediaCommandEnum.Stop:
9815 case ParcelMediaCommandEnum.Unload: 10460 case (uint)ParcelMediaCommandEnum.Unload:
9816 commandToSend = command; 10461 commandToSend = command;
9817 break; 10462 break;
9818 10463
9819 case ParcelMediaCommandEnum.Url: 10464 case (uint)ParcelMediaCommandEnum.Url:
9820 if ((i + 1) < commandList.Length) 10465 if ((i + 1) < commandList.Length)
9821 { 10466 {
9822 if (commandList.Data[i + 1] is LSL_String) 10467 if (commandList.Data[i + 1] is LSL_String)
@@ -9829,7 +10474,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9829 } 10474 }
9830 break; 10475 break;
9831 10476
9832 case ParcelMediaCommandEnum.Texture: 10477 case (uint)ParcelMediaCommandEnum.Texture:
9833 if ((i + 1) < commandList.Length) 10478 if ((i + 1) < commandList.Length)
9834 { 10479 {
9835 if (commandList.Data[i + 1] is LSL_String) 10480 if (commandList.Data[i + 1] is LSL_String)
@@ -9842,7 +10487,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9842 } 10487 }
9843 break; 10488 break;
9844 10489
9845 case ParcelMediaCommandEnum.Time: 10490 case (uint)ParcelMediaCommandEnum.Time:
9846 if ((i + 1) < commandList.Length) 10491 if ((i + 1) < commandList.Length)
9847 { 10492 {
9848 if (commandList.Data[i + 1] is LSL_Float) 10493 if (commandList.Data[i + 1] is LSL_Float)
@@ -9854,7 +10499,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9854 } 10499 }
9855 break; 10500 break;
9856 10501
9857 case ParcelMediaCommandEnum.AutoAlign: 10502 case (uint)ParcelMediaCommandEnum.AutoAlign:
9858 if ((i + 1) < commandList.Length) 10503 if ((i + 1) < commandList.Length)
9859 { 10504 {
9860 if (commandList.Data[i + 1] is LSL_Integer) 10505 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9868,7 +10513,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9868 } 10513 }
9869 break; 10514 break;
9870 10515
9871 case ParcelMediaCommandEnum.Type: 10516 case (uint)ParcelMediaCommandEnum.Type:
9872 if ((i + 1) < commandList.Length) 10517 if ((i + 1) < commandList.Length)
9873 { 10518 {
9874 if (commandList.Data[i + 1] is LSL_String) 10519 if (commandList.Data[i + 1] is LSL_String)
@@ -9881,7 +10526,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9881 } 10526 }
9882 break; 10527 break;
9883 10528
9884 case ParcelMediaCommandEnum.Desc: 10529 case (uint)ParcelMediaCommandEnum.Desc:
9885 if ((i + 1) < commandList.Length) 10530 if ((i + 1) < commandList.Length)
9886 { 10531 {
9887 if (commandList.Data[i + 1] is LSL_String) 10532 if (commandList.Data[i + 1] is LSL_String)
@@ -9894,7 +10539,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9894 } 10539 }
9895 break; 10540 break;
9896 10541
9897 case ParcelMediaCommandEnum.Size: 10542 case (uint)ParcelMediaCommandEnum.Size:
9898 if ((i + 2) < commandList.Length) 10543 if ((i + 2) < commandList.Length)
9899 { 10544 {
9900 if (commandList.Data[i + 1] is LSL_Integer) 10545 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9964,7 +10609,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9964 } 10609 }
9965 } 10610 }
9966 10611
9967 if (commandToSend != null) 10612 if (commandToSend != 0)
9968 { 10613 {
9969 // the commandList contained a start/stop/... command, too 10614 // the commandList contained a start/stop/... command, too
9970 if (presence == null) 10615 if (presence == null)
@@ -10001,7 +10646,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10001 10646
10002 if (aList.Data[i] != null) 10647 if (aList.Data[i] != null)
10003 { 10648 {
10004 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10649 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
10005 { 10650 {
10006 case ParcelMediaCommandEnum.Url: 10651 case ParcelMediaCommandEnum.Url:
10007 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); 10652 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL));
@@ -10058,15 +10703,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10058 10703
10059 if (quick_pay_buttons.Data.Length < 4) 10704 if (quick_pay_buttons.Data.Length < 4)
10060 { 10705 {
10061 LSLError("List must have at least 4 elements"); 10706 int x;
10062 return; 10707 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10708 {
10709 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10710 }
10063 } 10711 }
10064 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10712 int[] nPrice = new int[5];
10065 10713 nPrice[0] = price;
10066 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10714 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
10067 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10715 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
10068 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10716 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
10069 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10717 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10718 m_host.ParentGroup.RootPart.PayPrice = nPrice;
10070 m_host.ParentGroup.HasGroupChanged = true; 10719 m_host.ParentGroup.HasGroupChanged = true;
10071 } 10720 }
10072 10721
@@ -10083,7 +10732,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10083 return Vector3.Zero; 10732 return Vector3.Zero;
10084 } 10733 }
10085 10734
10086 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10735// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10736 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
10087 if (presence != null) 10737 if (presence != null)
10088 { 10738 {
10089 LSL_Vector pos = new LSL_Vector(presence.CameraPosition); 10739 LSL_Vector pos = new LSL_Vector(presence.CameraPosition);
@@ -10106,7 +10756,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10106 return Quaternion.Identity; 10756 return Quaternion.Identity;
10107 } 10757 }
10108 10758
10109 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10759// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10760 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
10110 if (presence != null) 10761 if (presence != null)
10111 { 10762 {
10112 return new LSL_Rotation(presence.CameraRotation); 10763 return new LSL_Rotation(presence.CameraRotation);
@@ -10166,14 +10817,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10166 { 10817 {
10167 m_host.AddScriptLPS(1); 10818 m_host.AddScriptLPS(1);
10168 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 10819 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
10169 if (detectedParams == null) return; // only works on the first detected avatar 10820 if (detectedParams == null)
10170 10821 {
10822 if (m_host.ParentGroup.IsAttachment == true)
10823 {
10824 detectedParams = new DetectParams();
10825 detectedParams.Key = m_host.OwnerID;
10826 }
10827 else
10828 {
10829 return;
10830 }
10831 }
10832
10171 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10833 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
10172 if (avatar != null) 10834 if (avatar != null)
10173 { 10835 {
10174 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, 10836 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name,
10175 simname, pos, lookAt); 10837 simname, pos, lookAt);
10176 } 10838 }
10839
10177 ScriptSleep(1000); 10840 ScriptSleep(1000);
10178 } 10841 }
10179 10842
@@ -10297,12 +10960,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10297 10960
10298 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10961 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
10299 object[] data = rules.Data; 10962 object[] data = rules.Data;
10300 for (int i = 0; i < data.Length; ++i) { 10963 for (int i = 0; i < data.Length; ++i)
10964 {
10301 int type = Convert.ToInt32(data[i++].ToString()); 10965 int type = Convert.ToInt32(data[i++].ToString());
10302 if (i >= data.Length) break; // odd number of entries => ignore the last 10966 if (i >= data.Length) break; // odd number of entries => ignore the last
10303 10967
10304 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10968 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
10305 switch (type) { 10969 switch (type)
10970 {
10306 case ScriptBaseClass.CAMERA_FOCUS: 10971 case ScriptBaseClass.CAMERA_FOCUS:
10307 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10972 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
10308 case ScriptBaseClass.CAMERA_POSITION: 10973 case ScriptBaseClass.CAMERA_POSITION:
@@ -10407,19 +11072,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10407 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 11072 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
10408 { 11073 {
10409 m_host.AddScriptLPS(1); 11074 m_host.AddScriptLPS(1);
10410 string ret = String.Empty; 11075
10411 string src1 = llBase64ToString(str1); 11076 if (str1 == String.Empty)
10412 string src2 = llBase64ToString(str2); 11077 return String.Empty;
10413 int c = 0; 11078 if (str2 == String.Empty)
10414 for (int i = 0; i < src1.Length; i++) 11079 return str1;
11080
11081 int len = str2.Length;
11082 if ((len % 4) != 0) // LL is EVIL!!!!
10415 { 11083 {
10416 ret += (char) (src1[i] ^ src2[c]); 11084 while (str2.EndsWith("="))
11085 str2 = str2.Substring(0, str2.Length - 1);
11086
11087 len = str2.Length;
11088 int mod = len % 4;
11089
11090 if (mod == 1)
11091 str2 = str2.Substring(0, str2.Length - 1);
11092 else if (mod == 2)
11093 str2 += "==";
11094 else if (mod == 3)
11095 str2 += "=";
11096 }
10417 11097
10418 c++; 11098 byte[] data1;
10419 if (c >= src2.Length) 11099 byte[] data2;
10420 c = 0; 11100 try
11101 {
11102 data1 = Convert.FromBase64String(str1);
11103 data2 = Convert.FromBase64String(str2);
11104 }
11105 catch (Exception)
11106 {
11107 return new LSL_String(String.Empty);
10421 } 11108 }
10422 return llStringToBase64(ret); 11109
11110 byte[] d2 = new Byte[data1.Length];
11111 int pos = 0;
11112
11113 if (data1.Length <= data2.Length)
11114 {
11115 Array.Copy(data2, 0, d2, 0, data1.Length);
11116 }
11117 else
11118 {
11119 while (pos < data1.Length)
11120 {
11121 len = data1.Length - pos;
11122 if (len > data2.Length)
11123 len = data2.Length;
11124
11125 Array.Copy(data2, 0, d2, pos, len);
11126 pos += len;
11127 }
11128 }
11129
11130 for (pos = 0 ; pos < data1.Length ; pos++ )
11131 data1[pos] ^= d2[pos];
11132
11133 return Convert.ToBase64String(data1);
10423 } 11134 }
10424 11135
10425 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 11136 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10523,16 +11234,72 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10523 if (userAgent != null) 11234 if (userAgent != null)
10524 httpHeaders["User-Agent"] = userAgent; 11235 httpHeaders["User-Agent"] = userAgent;
10525 11236
11237 // See if the URL contains any header hacks
11238 string[] urlParts = url.Split(new char[] {'\n'});
11239 if (urlParts.Length > 1)
11240 {
11241 // Iterate the passed headers and parse them
11242 for (int i = 1 ; i < urlParts.Length ; i++ )
11243 {
11244 // The rest of those would be added to the body in SL.
11245 // Let's not do that.
11246 if (urlParts[i] == String.Empty)
11247 break;
11248
11249 // See if this could be a valid header
11250 string[] headerParts = urlParts[i].Split(new char[] {':'}, 2);
11251 if (headerParts.Length != 2)
11252 continue;
11253
11254 string headerName = headerParts[0].Trim();
11255 string headerValue = headerParts[1].Trim();
11256
11257 // Filter out headers that could be used to abuse
11258 // another system or cloak the request
11259 if (headerName.ToLower() == "x-secondlife-shard" ||
11260 headerName.ToLower() == "x-secondlife-object-name" ||
11261 headerName.ToLower() == "x-secondlife-object-key" ||
11262 headerName.ToLower() == "x-secondlife-region" ||
11263 headerName.ToLower() == "x-secondlife-local-position" ||
11264 headerName.ToLower() == "x-secondlife-local-velocity" ||
11265 headerName.ToLower() == "x-secondlife-local-rotation" ||
11266 headerName.ToLower() == "x-secondlife-owner-name" ||
11267 headerName.ToLower() == "x-secondlife-owner-key" ||
11268 headerName.ToLower() == "connection" ||
11269 headerName.ToLower() == "content-length" ||
11270 headerName.ToLower() == "from" ||
11271 headerName.ToLower() == "host" ||
11272 headerName.ToLower() == "proxy-authorization" ||
11273 headerName.ToLower() == "referer" ||
11274 headerName.ToLower() == "trailer" ||
11275 headerName.ToLower() == "transfer-encoding" ||
11276 headerName.ToLower() == "via" ||
11277 headerName.ToLower() == "authorization")
11278 continue;
11279
11280 httpHeaders[headerName] = headerValue;
11281 }
11282
11283 // Finally, strip any protocol specifier from the URL
11284 url = urlParts[0].Trim();
11285 int idx = url.IndexOf(" HTTP/");
11286 if (idx != -1)
11287 url = url.Substring(0, idx);
11288 }
11289
10526 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$"; 11290 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$";
10527 Regex r = new Regex(authregex); 11291 Regex r = new Regex(authregex);
10528 int[] gnums = r.GetGroupNumbers(); 11292 int[] gnums = r.GetGroupNumbers();
10529 Match m = r.Match(url); 11293 Match m = r.Match(url);
10530 if (m.Success) { 11294 if (m.Success)
10531 for (int i = 1; i < gnums.Length; i++) { 11295 {
11296 for (int i = 1; i < gnums.Length; i++)
11297 {
10532 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 11298 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10533 //CaptureCollection cc = g.Captures; 11299 //CaptureCollection cc = g.Captures;
10534 } 11300 }
10535 if (m.Groups.Count == 5) { 11301 if (m.Groups.Count == 5)
11302 {
10536 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 11303 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10537 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 11304 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10538 } 11305 }
@@ -10735,6 +11502,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10735 11502
10736 LSL_List ret = new LSL_List(); 11503 LSL_List ret = new LSL_List();
10737 UUID key = new UUID(); 11504 UUID key = new UUID();
11505
11506
10738 if (UUID.TryParse(id, out key)) 11507 if (UUID.TryParse(id, out key))
10739 { 11508 {
10740 ScenePresence av = World.GetScenePresence(key); 11509 ScenePresence av = World.GetScenePresence(key);
@@ -10752,13 +11521,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10752 ret.Add(new LSL_String("")); 11521 ret.Add(new LSL_String(""));
10753 break; 11522 break;
10754 case ScriptBaseClass.OBJECT_POS: 11523 case ScriptBaseClass.OBJECT_POS:
10755 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); 11524 Vector3 avpos;
11525
11526 if (av.ParentID != 0 && av.ParentPart != null)
11527 {
11528 avpos = av.OffsetPosition;
11529
11530 Vector3 sitOffset = (Zrot(av.Rotation)) * (av.Appearance.AvatarHeight * 0.02638f *2.0f);
11531 avpos -= sitOffset;
11532
11533 avpos = av.ParentPart.GetWorldPosition() + avpos * av.ParentPart.GetWorldRotation();
11534 }
11535 else
11536 avpos = av.AbsolutePosition;
11537
11538 ret.Add(new LSL_Vector((double)avpos.X, (double)avpos.Y, (double)avpos.Z));
10756 break; 11539 break;
10757 case ScriptBaseClass.OBJECT_ROT: 11540 case ScriptBaseClass.OBJECT_ROT:
10758 ret.Add(new LSL_Rotation(av.GetWorldRotation())); 11541 Quaternion avrot = av.Rotation;
11542 if (av.ParentID != 0 && av.ParentPart != null)
11543 {
11544 avrot = av.ParentPart.GetWorldRotation() * avrot;
11545 }
11546 ret.Add(new LSL_Rotation((double)avrot.X, (double)avrot.Y, (double)avrot.Z, (double)avrot.W));
10759 break; 11547 break;
10760 case ScriptBaseClass.OBJECT_VELOCITY: 11548 case ScriptBaseClass.OBJECT_VELOCITY:
10761 ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); 11549 Vector3 avvel = av.Velocity;
11550 ret.Add(new LSL_Vector((double)avvel.X, (double)avvel.Y, (double)avvel.Z));
10762 break; 11551 break;
10763 case ScriptBaseClass.OBJECT_OWNER: 11552 case ScriptBaseClass.OBJECT_OWNER:
10764 ret.Add(new LSL_String(id)); 11553 ret.Add(new LSL_String(id));
@@ -10843,11 +11632,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10843 case ScriptBaseClass.OBJECT_NAME: 11632 case ScriptBaseClass.OBJECT_NAME:
10844 ret.Add(new LSL_String(obj.Name)); 11633 ret.Add(new LSL_String(obj.Name));
10845 break; 11634 break;
10846 case ScriptBaseClass.OBJECT_DESC: 11635 case ScriptBaseClass.OBJECT_DESC:
10847 ret.Add(new LSL_String(obj.Description)); 11636 ret.Add(new LSL_String(obj.Description));
10848 break; 11637 break;
10849 case ScriptBaseClass.OBJECT_POS: 11638 case ScriptBaseClass.OBJECT_POS:
10850 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); 11639 Vector3 opos = obj.AbsolutePosition;
11640 ret.Add(new LSL_Vector(opos.X, opos.Y, opos.Z));
10851 break; 11641 break;
10852 case ScriptBaseClass.OBJECT_ROT: 11642 case ScriptBaseClass.OBJECT_ROT:
10853 { 11643 {
@@ -10897,9 +11687,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10897 // The value returned in SL for normal prims is prim count 11687 // The value returned in SL for normal prims is prim count
10898 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount)); 11688 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
10899 break; 11689 break;
10900 // The following 3 costs I have intentionaly coded to return zero. They are part of 11690
10901 // "Land Impact" calculations. These calculations are probably not applicable 11691 // costs below may need to be diferent for root parts, need to check
10902 // to OpenSim and are not yet complete in SL
10903 case ScriptBaseClass.OBJECT_SERVER_COST: 11692 case ScriptBaseClass.OBJECT_SERVER_COST:
10904 // The linden calculation is here 11693 // The linden calculation is here
10905 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight 11694 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
@@ -10907,16 +11696,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10907 ret.Add(new LSL_Float(0)); 11696 ret.Add(new LSL_Float(0));
10908 break; 11697 break;
10909 case ScriptBaseClass.OBJECT_STREAMING_COST: 11698 case ScriptBaseClass.OBJECT_STREAMING_COST:
10910 // The linden calculation is here 11699 // The value returned in SL for normal prims is prim count * 0.06
10911 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost 11700 ret.Add(new LSL_Float(obj.StreamingCost));
10912 // The value returned in SL for normal prims looks like the prim count * 0.06
10913 ret.Add(new LSL_Float(0));
10914 break; 11701 break;
10915 case ScriptBaseClass.OBJECT_PHYSICS_COST: 11702 case ScriptBaseClass.OBJECT_PHYSICS_COST:
10916 // The linden calculation is here 11703 // The value returned in SL for normal prims is prim count
10917 // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics 11704 ret.Add(new LSL_Float(obj.PhysicsCost));
10918 // The value returned in SL for normal prims looks like the prim count
10919 ret.Add(new LSL_Float(0));
10920 break; 11705 break;
10921 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding 11706 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
10922 ret.Add(new LSL_Float(0)); 11707 ret.Add(new LSL_Float(0));
@@ -11175,15 +11960,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11175 return result; 11960 return result;
11176 } 11961 }
11177 11962
11178 public void print(string str) 11963 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
11179 { 11964 {
11180 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11965 List<SceneObjectPart> parts = GetLinkParts(link);
11181 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11966 if (parts.Count < 1)
11182 if (ossl != null) 11967 return 0;
11183 { 11968
11184 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11969 return GetNumberOfSides(parts[0]);
11185 m_log.Info("LSL print():" + str);
11186 }
11187 } 11970 }
11188 11971
11189 private string Name2Username(string name) 11972 private string Name2Username(string name)
@@ -11228,7 +12011,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11228 12011
11229 return rq.ToString(); 12012 return rq.ToString();
11230 } 12013 }
11231 12014/*
12015 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
12016 {
12017 m_SayShoutCount = 0;
12018 }
12019*/
11232 private struct Tri 12020 private struct Tri
11233 { 12021 {
11234 public Vector3 p1; 12022 public Vector3 p1;
@@ -11377,9 +12165,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11377 12165
11378 ContactResult result = new ContactResult (); 12166 ContactResult result = new ContactResult ();
11379 result.ConsumerID = group.LocalId; 12167 result.ConsumerID = group.LocalId;
11380 result.Depth = intersection.distance; 12168// result.Depth = intersection.distance;
11381 result.Normal = intersection.normal; 12169 result.Normal = intersection.normal;
11382 result.Pos = intersection.ipoint; 12170 result.Pos = intersection.ipoint;
12171 result.Depth = Vector3.Mag(rayStart - result.Pos);
11383 12172
11384 contacts.Add(result); 12173 contacts.Add(result);
11385 }); 12174 });
@@ -11512,6 +12301,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11512 12301
11513 return contacts[0]; 12302 return contacts[0];
11514 } 12303 }
12304/*
12305 // not done:
12306 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
12307 {
12308 ContactResult[] contacts = null;
12309 World.ForEachSOG(delegate(SceneObjectGroup group)
12310 {
12311 if (m_host.ParentGroup == group)
12312 return;
12313
12314 if (group.IsAttachment)
12315 return;
12316
12317 if(group.RootPart.PhysActor != null)
12318 return;
12319
12320 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
12321 });
12322 return contacts;
12323 }
12324*/
11515 12325
11516 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 12326 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
11517 { 12327 {
@@ -11635,18 +12445,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11635 } 12445 }
11636 } 12446 }
11637 12447
12448 // Double check this
11638 if (checkTerrain) 12449 if (checkTerrain)
11639 { 12450 {
11640 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); 12451 bool skipGroundCheck = false;
11641 if (groundContact != null) 12452
11642 results.Add((ContactResult)groundContact); 12453 foreach (ContactResult c in results)
12454 {
12455 if (c.ConsumerID == 0) // Physics gave us a ground collision
12456 skipGroundCheck = true;
12457 }
12458
12459 if (!skipGroundCheck)
12460 {
12461 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
12462 if (groundContact != null)
12463 results.Add((ContactResult)groundContact);
12464 }
11643 } 12465 }
11644 12466
11645 results.Sort(delegate(ContactResult a, ContactResult b) 12467 results.Sort(delegate(ContactResult a, ContactResult b)
11646 { 12468 {
11647 return a.Depth.CompareTo(b.Depth); 12469 return a.Depth.CompareTo(b.Depth);
11648 }); 12470 });
11649 12471
11650 int values = 0; 12472 int values = 0;
11651 SceneObjectGroup thisgrp = m_host.ParentGroup; 12473 SceneObjectGroup thisgrp = m_host.ParentGroup;
11652 12474
@@ -11739,7 +12561,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11739 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 12561 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
11740 if (!isAccount) return 0; 12562 if (!isAccount) return 0;
11741 if (estate.HasAccess(id)) return 1; 12563 if (estate.HasAccess(id)) return 1;
11742 if (estate.IsBanned(id)) 12564 if (estate.IsBanned(id, World.GetUserFlags(id)))
11743 estate.RemoveBan(id); 12565 estate.RemoveBan(id);
11744 estate.AddEstateUser(id); 12566 estate.AddEstateUser(id);
11745 break; 12567 break;
@@ -11758,14 +12580,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11758 break; 12580 break;
11759 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 12581 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
11760 if (!isAccount) return 0; 12582 if (!isAccount) return 0;
11761 if (estate.IsBanned(id)) return 1; 12583 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
11762 EstateBan ban = new EstateBan(); 12584 EstateBan ban = new EstateBan();
11763 ban.EstateID = estate.EstateID; 12585 ban.EstateID = estate.EstateID;
11764 ban.BannedUserID = id; 12586 ban.BannedUserID = id;
11765 estate.AddBan(ban); 12587 estate.AddBan(ban);
11766 break; 12588 break;
11767 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 12589 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
11768 if (!isAccount || !estate.IsBanned(id)) return 0; 12590 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
11769 estate.RemoveBan(id); 12591 estate.RemoveBan(id);
11770 break; 12592 break;
11771 default: return 0; 12593 default: return 0;
@@ -11822,19 +12644,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11822 public void llSetSoundQueueing(int queue) 12644 public void llSetSoundQueueing(int queue)
11823 { 12645 {
11824 m_host.AddScriptLPS(1); 12646 m_host.AddScriptLPS(1);
11825 NotImplemented("llSetSoundQueueing");
11826 } 12647 }
11827 12648
11828 public void llCollisionSprite(string impact_sprite) 12649 public void llCollisionSprite(string impact_sprite)
11829 { 12650 {
11830 m_host.AddScriptLPS(1); 12651 m_host.AddScriptLPS(1);
11831 NotImplemented("llCollisionSprite"); 12652 // Viewer 2.0 broke this and it's likely LL has no intention
12653 // of fixing it. Therefore, letting this be a NOP seems appropriate.
11832 } 12654 }
11833 12655
11834 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12656 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
11835 { 12657 {
11836 m_host.AddScriptLPS(1); 12658 m_host.AddScriptLPS(1);
11837 NotImplemented("llGodLikeRezObject"); 12659
12660 if (!World.Permissions.IsGod(m_host.OwnerID))
12661 NotImplemented("llGodLikeRezObject");
12662
12663 AssetBase rezAsset = World.AssetService.Get(inventory);
12664 if (rezAsset == null)
12665 {
12666 llSay(0, "Asset not found");
12667 return;
12668 }
12669
12670 SceneObjectGroup group = null;
12671
12672 try
12673 {
12674 string xmlData = Utils.BytesToString(rezAsset.Data);
12675 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12676 }
12677 catch
12678 {
12679 llSay(0, "Asset not found");
12680 return;
12681 }
12682
12683 if (group == null)
12684 {
12685 llSay(0, "Asset not found");
12686 return;
12687 }
12688
12689 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12690 group.RootPart.AttachOffset = group.AbsolutePosition;
12691
12692 group.ResetIDs();
12693
12694 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12695 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12696 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12697 group.ScheduleGroupForFullUpdate();
12698
12699 // objects rezzed with this method are die_at_edge by default.
12700 group.RootPart.SetDieAtEdge(true);
12701
12702 group.ResumeScripts();
12703
12704 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12705 "object_rez", new Object[] {
12706 new LSL_String(
12707 group.RootPart.UUID.ToString()) },
12708 new DetectParams[0]));
11838 } 12709 }
11839 12710
11840 public LSL_String llTransferLindenDollars(string destination, int amount) 12711 public LSL_String llTransferLindenDollars(string destination, int amount)
@@ -11886,7 +12757,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11886 } 12757 }
11887 12758
11888 bool result = money.ObjectGiveMoney( 12759 bool result = money.ObjectGiveMoney(
11889 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 12760 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount, txn);
11890 12761
11891 if (result) 12762 if (result)
11892 { 12763 {
@@ -11911,6 +12782,598 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11911 } 12782 }
11912 12783
11913 #endregion 12784 #endregion
12785
12786 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12787 {
12788 SceneObjectGroup group = m_host.ParentGroup;
12789
12790 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12791 return;
12792 if (group.IsAttachment)
12793 return;
12794
12795 if (frames.Data.Length > 0) // We are getting a new motion
12796 {
12797 if (group.RootPart.KeyframeMotion != null)
12798 group.RootPart.KeyframeMotion.Delete();
12799 group.RootPart.KeyframeMotion = null;
12800
12801 int idx = 0;
12802
12803 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12804 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12805
12806 while (idx < options.Data.Length)
12807 {
12808 int option = (int)options.GetLSLIntegerItem(idx++);
12809 int remain = options.Data.Length - idx;
12810
12811 switch (option)
12812 {
12813 case ScriptBaseClass.KFM_MODE:
12814 if (remain < 1)
12815 break;
12816 int modeval = (int)options.GetLSLIntegerItem(idx++);
12817 switch(modeval)
12818 {
12819 case ScriptBaseClass.KFM_FORWARD:
12820 mode = KeyframeMotion.PlayMode.Forward;
12821 break;
12822 case ScriptBaseClass.KFM_REVERSE:
12823 mode = KeyframeMotion.PlayMode.Reverse;
12824 break;
12825 case ScriptBaseClass.KFM_LOOP:
12826 mode = KeyframeMotion.PlayMode.Loop;
12827 break;
12828 case ScriptBaseClass.KFM_PING_PONG:
12829 mode = KeyframeMotion.PlayMode.PingPong;
12830 break;
12831 }
12832 break;
12833 case ScriptBaseClass.KFM_DATA:
12834 if (remain < 1)
12835 break;
12836 int dataval = (int)options.GetLSLIntegerItem(idx++);
12837 data = (KeyframeMotion.DataFormat)dataval;
12838 break;
12839 }
12840 }
12841
12842 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12843
12844 idx = 0;
12845
12846 int elemLength = 2;
12847 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12848 elemLength = 3;
12849
12850 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12851 while (idx < frames.Data.Length)
12852 {
12853 int remain = frames.Data.Length - idx;
12854
12855 if (remain < elemLength)
12856 break;
12857
12858 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12859 frame.Position = null;
12860 frame.Rotation = null;
12861
12862 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12863 {
12864 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12865 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12866 }
12867 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12868 {
12869 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12870 Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12871 q.Normalize();
12872 frame.Rotation = q;
12873 }
12874
12875 float tempf = (float)frames.GetLSLFloatItem(idx++);
12876 frame.TimeMS = (int)(tempf * 1000.0f);
12877
12878 keyframes.Add(frame);
12879 }
12880
12881 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12882 group.RootPart.KeyframeMotion.Start();
12883 }
12884 else
12885 {
12886 if (group.RootPart.KeyframeMotion == null)
12887 return;
12888
12889 if (options.Data.Length == 0)
12890 {
12891 group.RootPart.KeyframeMotion.Stop();
12892 return;
12893 }
12894
12895 int code = (int)options.GetLSLIntegerItem(0);
12896
12897 int idx = 0;
12898
12899 while (idx < options.Data.Length)
12900 {
12901 int option = (int)options.GetLSLIntegerItem(idx++);
12902 int remain = options.Data.Length - idx;
12903
12904 switch (option)
12905 {
12906 case ScriptBaseClass.KFM_COMMAND:
12907 int cmd = (int)options.GetLSLIntegerItem(idx++);
12908 switch (cmd)
12909 {
12910 case ScriptBaseClass.KFM_CMD_PLAY:
12911 group.RootPart.KeyframeMotion.Start();
12912 break;
12913 case ScriptBaseClass.KFM_CMD_STOP:
12914 group.RootPart.KeyframeMotion.Stop();
12915 break;
12916 case ScriptBaseClass.KFM_CMD_PAUSE:
12917 group.RootPart.KeyframeMotion.Pause();
12918 break;
12919 }
12920 break;
12921 }
12922 }
12923 }
12924 }
12925
12926 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed)
12927 {
12928 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
12929
12930 int idx = 0;
12931 int idxStart = 0;
12932
12933 bool positionChanged = false;
12934 Vector3 finalPos = Vector3.Zero;
12935
12936 try
12937 {
12938 while (idx < rules.Length)
12939 {
12940 ++rulesParsed;
12941 int code = rules.GetLSLIntegerItem(idx++);
12942
12943 int remain = rules.Length - idx;
12944 idxStart = idx;
12945
12946 switch (code)
12947 {
12948 case (int)ScriptBaseClass.PRIM_POSITION:
12949 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
12950 {
12951 if (remain < 1)
12952 return null;
12953
12954 LSL_Vector v;
12955 v = rules.GetVector3Item(idx++);
12956
12957 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12958 if (part == null)
12959 break;
12960
12961 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12962 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12963 if (part.LinkNum > 1)
12964 {
12965 localRot = GetPartLocalRot(part);
12966 localPos = GetPartLocalPos(part);
12967 }
12968
12969 v -= localPos;
12970 v /= localRot;
12971
12972 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
12973
12974 v = v + 2 * sitOffset;
12975
12976 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
12977 av.SendAvatarDataToAllAgents();
12978
12979 }
12980 break;
12981
12982 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
12983 case (int)ScriptBaseClass.PRIM_ROTATION:
12984 {
12985 if (remain < 1)
12986 return null;
12987
12988 LSL_Rotation r;
12989 r = rules.GetQuaternionItem(idx++);
12990
12991 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12992 if (part == null)
12993 break;
12994
12995 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12996 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12997
12998 if (part.LinkNum > 1)
12999 localRot = GetPartLocalRot(part);
13000
13001 r = r * llGetRootRotation() / localRot;
13002 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
13003 av.SendAvatarDataToAllAgents();
13004 }
13005 break;
13006
13007 // parse rest doing nothing but number of parameters error check
13008 case (int)ScriptBaseClass.PRIM_SIZE:
13009 case (int)ScriptBaseClass.PRIM_MATERIAL:
13010 case (int)ScriptBaseClass.PRIM_PHANTOM:
13011 case (int)ScriptBaseClass.PRIM_PHYSICS:
13012 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
13013 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
13014 case (int)ScriptBaseClass.PRIM_NAME:
13015 case (int)ScriptBaseClass.PRIM_DESC:
13016 if (remain < 1)
13017 return null;
13018 idx++;
13019 break;
13020
13021 case (int)ScriptBaseClass.PRIM_GLOW:
13022 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
13023 case (int)ScriptBaseClass.PRIM_TEXGEN:
13024 if (remain < 2)
13025 return null;
13026 idx += 2;
13027 break;
13028
13029 case (int)ScriptBaseClass.PRIM_TYPE:
13030 if (remain < 3)
13031 return null;
13032 code = (int)rules.GetLSLIntegerItem(idx++);
13033 remain = rules.Length - idx;
13034 switch (code)
13035 {
13036 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
13037 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
13038 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
13039 if (remain < 6)
13040 return null;
13041 idx += 6;
13042 break;
13043
13044 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
13045 if (remain < 5)
13046 return null;
13047 idx += 5;
13048 break;
13049
13050 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
13051 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
13052 case (int)ScriptBaseClass.PRIM_TYPE_RING:
13053 if (remain < 11)
13054 return null;
13055 idx += 11;
13056 break;
13057
13058 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
13059 if (remain < 2)
13060 return null;
13061 idx += 2;
13062 break;
13063 }
13064 break;
13065
13066 case (int)ScriptBaseClass.PRIM_COLOR:
13067 case (int)ScriptBaseClass.PRIM_TEXT:
13068 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
13069 case (int)ScriptBaseClass.PRIM_OMEGA:
13070 if (remain < 3)
13071 return null;
13072 idx += 3;
13073 break;
13074
13075 case (int)ScriptBaseClass.PRIM_TEXTURE:
13076 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
13077 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
13078 if (remain < 5)
13079 return null;
13080 idx += 5;
13081 break;
13082
13083 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
13084 if (remain < 7)
13085 return null;
13086
13087 idx += 7;
13088 break;
13089
13090 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
13091 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
13092 return null;
13093
13094 return rules.GetSublist(idx, -1);
13095 }
13096 }
13097 }
13098 catch (InvalidCastException e)
13099 {
13100 ShoutError(string.Format(
13101 "{0} error running rule #{1}: arg #{2} ",
13102 originFunc, rulesParsed, idx - idxStart) + e.Message);
13103 }
13104 finally
13105 {
13106 if (positionChanged)
13107 {
13108 av.OffsetPosition = finalPos;
13109// av.SendAvatarDataToAllAgents();
13110 av.SendTerseUpdateToAllClients();
13111 positionChanged = false;
13112 }
13113 }
13114 return null;
13115 }
13116
13117 public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res)
13118 {
13119 // avatars case
13120 // replies as SL wiki
13121
13122// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
13123 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
13124
13125 int idx = 0;
13126 while (idx < rules.Length)
13127 {
13128 int code = (int)rules.GetLSLIntegerItem(idx++);
13129 int remain = rules.Length - idx;
13130
13131 switch (code)
13132 {
13133 case (int)ScriptBaseClass.PRIM_MATERIAL:
13134 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
13135 break;
13136
13137 case (int)ScriptBaseClass.PRIM_PHYSICS:
13138 res.Add(new LSL_Integer(0));
13139 break;
13140
13141 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
13142 res.Add(new LSL_Integer(0));
13143 break;
13144
13145 case (int)ScriptBaseClass.PRIM_PHANTOM:
13146 res.Add(new LSL_Integer(0));
13147 break;
13148
13149 case (int)ScriptBaseClass.PRIM_POSITION:
13150
13151 Vector3 pos = avatar.OffsetPosition;
13152
13153 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
13154 pos -= sitOffset;
13155
13156 if( sitPart != null)
13157 pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation();
13158
13159 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
13160 break;
13161
13162 case (int)ScriptBaseClass.PRIM_SIZE:
13163 // as in llGetAgentSize above
13164// res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight));
13165 Vector3 s = avatar.Appearance.AvatarSize;
13166 res.Add(new LSL_Vector(s.X, s.Y, s.Z));
13167
13168 break;
13169
13170 case (int)ScriptBaseClass.PRIM_ROTATION:
13171 Quaternion rot = avatar.Rotation;
13172 if (sitPart != null)
13173 {
13174 rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation
13175 }
13176
13177 res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W));
13178 break;
13179
13180 case (int)ScriptBaseClass.PRIM_TYPE:
13181 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
13182 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
13183 res.Add(new LSL_Vector(0f,1.0f,0f));
13184 res.Add(new LSL_Float(0.0f));
13185 res.Add(new LSL_Vector(0, 0, 0));
13186 res.Add(new LSL_Vector(1.0f,1.0f,0f));
13187 res.Add(new LSL_Vector(0, 0, 0));
13188 break;
13189
13190 case (int)ScriptBaseClass.PRIM_TEXTURE:
13191 if (remain < 1)
13192 return null;
13193
13194 int face = (int)rules.GetLSLIntegerItem(idx++);
13195 if (face == ScriptBaseClass.ALL_SIDES)
13196 {
13197 for (face = 0; face < 21; face++)
13198 {
13199 res.Add(new LSL_String(""));
13200 res.Add(new LSL_Vector(0,0,0));
13201 res.Add(new LSL_Vector(0,0,0));
13202 res.Add(new LSL_Float(0.0));
13203 }
13204 }
13205 else
13206 {
13207 if (face >= 0 && face < 21)
13208 {
13209 res.Add(new LSL_String(""));
13210 res.Add(new LSL_Vector(0,0,0));
13211 res.Add(new LSL_Vector(0,0,0));
13212 res.Add(new LSL_Float(0.0));
13213 }
13214 }
13215 break;
13216
13217 case (int)ScriptBaseClass.PRIM_COLOR:
13218 if (remain < 1)
13219 return null;
13220
13221 face = (int)rules.GetLSLIntegerItem(idx++);
13222
13223 if (face == ScriptBaseClass.ALL_SIDES)
13224 {
13225 for (face = 0; face < 21; face++)
13226 {
13227 res.Add(new LSL_Vector(0,0,0));
13228 res.Add(new LSL_Float(0));
13229 }
13230 }
13231 else
13232 {
13233 res.Add(new LSL_Vector(0,0,0));
13234 res.Add(new LSL_Float(0));
13235 }
13236 break;
13237
13238 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
13239 if (remain < 1)
13240 return null;
13241 face = (int)rules.GetLSLIntegerItem(idx++);
13242
13243 if (face == ScriptBaseClass.ALL_SIDES)
13244 {
13245 for (face = 0; face < 21; face++)
13246 {
13247 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
13248 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
13249 }
13250 }
13251 else
13252 {
13253 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
13254 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
13255 }
13256 break;
13257
13258 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
13259 if (remain < 1)
13260 return null;
13261 face = (int)rules.GetLSLIntegerItem(idx++);
13262
13263 if (face == ScriptBaseClass.ALL_SIDES)
13264 {
13265 for (face = 0; face < 21; face++)
13266 {
13267 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
13268 }
13269 }
13270 else
13271 {
13272 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
13273 }
13274 break;
13275
13276 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
13277 res.Add(new LSL_Integer(0));
13278 res.Add(new LSL_Integer(0));// softness
13279 res.Add(new LSL_Float(0.0f)); // gravity
13280 res.Add(new LSL_Float(0.0f)); // friction
13281 res.Add(new LSL_Float(0.0f)); // wind
13282 res.Add(new LSL_Float(0.0f)); // tension
13283 res.Add(new LSL_Vector(0f,0f,0f));
13284 break;
13285
13286 case (int)ScriptBaseClass.PRIM_TEXGEN:
13287 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
13288 if (remain < 1)
13289 return null;
13290 face = (int)rules.GetLSLIntegerItem(idx++);
13291
13292 if (face == ScriptBaseClass.ALL_SIDES)
13293 {
13294 for (face = 0; face < 21; face++)
13295 {
13296 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13297 }
13298 }
13299 else
13300 {
13301 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13302 }
13303 break;
13304
13305 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
13306 res.Add(new LSL_Integer(0));
13307 res.Add(new LSL_Vector(0f,0f,0f));
13308 res.Add(new LSL_Float(0f)); // intensity
13309 res.Add(new LSL_Float(0f)); // radius
13310 res.Add(new LSL_Float(0f)); // falloff
13311 break;
13312
13313 case (int)ScriptBaseClass.PRIM_GLOW:
13314 if (remain < 1)
13315 return null;
13316 face = (int)rules.GetLSLIntegerItem(idx++);
13317
13318 if (face == ScriptBaseClass.ALL_SIDES)
13319 {
13320 for (face = 0; face < 21; face++)
13321 {
13322 res.Add(new LSL_Float(0f));
13323 }
13324 }
13325 else
13326 {
13327 res.Add(new LSL_Float(0f));
13328 }
13329 break;
13330
13331 case (int)ScriptBaseClass.PRIM_TEXT:
13332 res.Add(new LSL_String(""));
13333 res.Add(new LSL_Vector(0f,0f,0f));
13334 res.Add(new LSL_Float(1.0f));
13335 break;
13336
13337 case (int)ScriptBaseClass.PRIM_NAME:
13338 res.Add(new LSL_String(avatar.Name));
13339 break;
13340
13341 case (int)ScriptBaseClass.PRIM_DESC:
13342 res.Add(new LSL_String(""));
13343 break;
13344
13345 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
13346 Quaternion lrot = avatar.Rotation;
13347
13348 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13349 {
13350 lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset
13351 }
13352 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
13353 break;
13354
13355 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
13356 Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part
13357 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
13358 lpos -= lsitOffset;
13359
13360 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13361 {
13362 lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim
13363 }
13364 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
13365 break;
13366
13367 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
13368 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
13369 return null;
13370
13371 return rules.GetSublist(idx, -1);
13372 }
13373 }
13374
13375 return null;
13376 }
11914 } 13377 }
11915 13378
11916 public class NotecardCache 13379 public class NotecardCache