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.cs3146
1 files changed, 2380 insertions, 766 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 4fa3c60..8be39a7 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;
70 74
71namespace OpenSim.Region.ScriptEngine.Shared.Api 75namespace OpenSim.Region.ScriptEngine.Shared.Api
72{ 76{
@@ -113,17 +117,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
113 protected int m_notecardLineReadCharsMax = 255; 117 protected int m_notecardLineReadCharsMax = 255;
114 protected int m_scriptConsoleChannel = 0; 118 protected int m_scriptConsoleChannel = 0;
115 protected bool m_scriptConsoleChannelEnabled = false; 119 protected bool m_scriptConsoleChannelEnabled = false;
120 protected bool m_debuggerSafe = false;
116 protected IUrlModule m_UrlModule = null; 121 protected IUrlModule m_UrlModule = null;
117 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); 122 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
118 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 123 new Dictionary<UUID, UserInfoCacheEntry>();
124 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
119 protected ISoundModule m_SoundModule = null; 125 protected ISoundModule m_SoundModule = null;
120 126
127// protected Timer m_ShoutSayTimer;
128 protected int m_SayShoutCount = 0;
129 DateTime m_lastSayShoutCheck;
130
131 private Dictionary<string, string> MovementAnimationsForLSL =
132 new Dictionary<string, string> {
133 {"FLY", "Flying"},
134 {"FLYSLOW", "FlyingSlow"},
135 {"HOVER_UP", "Hovering Up"},
136 {"HOVER_DOWN", "Hovering Down"},
137 {"HOVER", "Hovering"},
138 {"LAND", "Landing"},
139 {"FALLDOWN", "Falling Down"},
140 {"PREJUMP", "PreJumping"},
141 {"JUMP", "Jumping"},
142 {"STANDUP", "Standing Up"},
143 {"SOFT_LAND", "Soft Landing"},
144 {"STAND", "Standing"},
145 {"CROUCHWALK", "CrouchWalking"},
146 {"RUN", "Running"},
147 {"WALK", "Walking"},
148 {"CROUCH", "Crouching"},
149 {"TURNLEFT", "Turning Left"},
150 {"TURNRIGHT", "Turning Right"}
151 };
152
121 public void Initialize( 153 public void Initialize(
122 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle) 154 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
123 { 155 {
156 m_lastSayShoutCheck = DateTime.UtcNow;
157
124 m_ScriptEngine = scriptEngine; 158 m_ScriptEngine = scriptEngine;
125 m_host = host; 159 m_host = host;
126 m_item = item; 160 m_item = item;
161 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
127 m_coopSleepHandle = coopSleepHandle; 162 m_coopSleepHandle = coopSleepHandle;
128 163
129 LoadConfig(); 164 LoadConfig();
@@ -212,6 +247,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
212 get { return m_ScriptEngine.World; } 247 get { return m_ScriptEngine.World; }
213 } 248 }
214 249
250 [DebuggerNonUserCode]
215 public void state(string newState) 251 public void state(string newState)
216 { 252 {
217 m_ScriptEngine.SetState(m_item.ItemID, newState); 253 m_ScriptEngine.SetState(m_item.ItemID, newState);
@@ -221,6 +257,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
221 /// Reset the named script. The script must be present 257 /// Reset the named script. The script must be present
222 /// in the same prim. 258 /// in the same prim.
223 /// </summary> 259 /// </summary>
260 [DebuggerNonUserCode]
224 public void llResetScript() 261 public void llResetScript()
225 { 262 {
226 m_host.AddScriptLPS(1); 263 m_host.AddScriptLPS(1);
@@ -283,6 +320,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
283 } 320 }
284 } 321 }
285 322
323 public List<ScenePresence> GetLinkAvatars(int linkType)
324 {
325 List<ScenePresence> ret = new List<ScenePresence>();
326 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
327 return ret;
328
329 List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
330
331 switch (linkType)
332 {
333 case ScriptBaseClass.LINK_SET:
334 return avs;
335
336 case ScriptBaseClass.LINK_ROOT:
337 return ret;
338
339 case ScriptBaseClass.LINK_ALL_OTHERS:
340 return avs;
341
342 case ScriptBaseClass.LINK_ALL_CHILDREN:
343 return avs;
344
345 case ScriptBaseClass.LINK_THIS:
346 return ret;
347
348 default:
349 if (linkType < 0)
350 return ret;
351
352 int partCount = m_host.ParentGroup.GetPartCount();
353
354 if (linkType <= partCount)
355 {
356 return ret;
357 }
358 else
359 {
360 linkType = linkType - partCount;
361 if (linkType > avs.Count)
362 {
363 return ret;
364 }
365 else
366 {
367 ret.Add(avs[linkType-1]);
368 return ret;
369 }
370 }
371 }
372 }
373
286 public List<SceneObjectPart> GetLinkParts(int linkType) 374 public List<SceneObjectPart> GetLinkParts(int linkType)
287 { 375 {
288 return GetLinkParts(m_host, linkType); 376 return GetLinkParts(m_host, linkType);
@@ -291,6 +379,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
291 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) 379 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
292 { 380 {
293 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 381 List<SceneObjectPart> ret = new List<SceneObjectPart>();
382 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
383 return ret;
294 ret.Add(part); 384 ret.Add(part);
295 385
296 switch (linkType) 386 switch (linkType)
@@ -444,31 +534,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
444 534
445 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 535 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
446 536
447 /// <summary> 537 // Utility function for llRot2Euler
448 /// Convert an LSL rotation to a Euler vector. 538
449 /// </summary> 539 // normalize an angle between -PI and PI (-180 to +180 degrees)
450 /// <remarks> 540 protected double NormalizeAngle(double angle)
451 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
452 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
453 /// </remarks>
454 /// <param name="r"></param>
455 /// <returns></returns>
456 public LSL_Vector llRot2Euler(LSL_Rotation r)
457 { 541 {
458 m_host.AddScriptLPS(1); 542 if (angle > -Math.PI && angle < Math.PI)
543 return angle;
459 544
460 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 545 int numPis = (int)(Math.PI / angle);
461 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 546 double remainder = angle - Math.PI * numPis;
462 if (m == 0.0) return new LSL_Vector(); 547 if (numPis % 2 == 1)
463 double x = Math.Atan2(-v.y, v.z); 548 return Math.PI - angle;
464 double sin = v.x / m; 549 return remainder;
465 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. 550 }
466 double y = Math.Asin(sin);
467 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
468 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)));
469 double z = Math.Atan2(v.y, v.x);
470 551
471 return new LSL_Vector(x, y, z); 552 public LSL_Vector llRot2Euler(LSL_Rotation q1)
553 {
554 m_host.AddScriptLPS(1);
555 LSL_Vector eul = new LSL_Vector();
556
557 double sqw = q1.s*q1.s;
558 double sqx = q1.x*q1.x;
559 double sqy = q1.z*q1.z;
560 double sqz = q1.y*q1.y;
561 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
562 double test = q1.x*q1.z + q1.y*q1.s;
563 if (test > 0.4999*unit) { // singularity at north pole
564 eul.z = 2 * Math.Atan2(q1.x,q1.s);
565 eul.y = Math.PI/2;
566 eul.x = 0;
567 return eul;
568 }
569 if (test < -0.4999*unit) { // singularity at south pole
570 eul.z = -2 * Math.Atan2(q1.x,q1.s);
571 eul.y = -Math.PI/2;
572 eul.x = 0;
573 return eul;
574 }
575 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
576 eul.y = Math.Asin(2*test/unit);
577 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
578 return eul;
472 } 579 }
473 580
474 /* From wiki: 581 /* From wiki:
@@ -521,18 +628,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
521 m_host.AddScriptLPS(1); 628 m_host.AddScriptLPS(1);
522 629
523 double x,y,z,s; 630 double x,y,z,s;
524 631 v.x *= 0.5;
525 double c1 = Math.Cos(v.x * 0.5); 632 v.y *= 0.5;
526 double c2 = Math.Cos(v.y * 0.5); 633 v.z *= 0.5;
527 double c3 = Math.Cos(v.z * 0.5); 634 double c1 = Math.Cos(v.x);
528 double s1 = Math.Sin(v.x * 0.5); 635 double c2 = Math.Cos(v.y);
529 double s2 = Math.Sin(v.y * 0.5); 636 double c1c2 = c1 * c2;
530 double s3 = Math.Sin(v.z * 0.5); 637 double s1 = Math.Sin(v.x);
531 638 double s2 = Math.Sin(v.y);
532 x = s1 * c2 * c3 + c1 * s2 * s3; 639 double s1s2 = s1 * s2;
533 y = c1 * s2 * c3 - s1 * c2 * s3; 640 double c1s2 = c1 * s2;
534 z = s1 * s2 * c3 + c1 * c2 * s3; 641 double s1c2 = s1 * c2;
535 s = c1 * c2 * c3 - s1 * s2 * s3; 642 double c3 = Math.Cos(v.z);
643 double s3 = Math.Sin(v.z);
644
645 x = s1c2 * c3 + c1s2 * s3;
646 y = c1s2 * c3 - s1c2 * s3;
647 z = s1s2 * c3 + c1c2 * s3;
648 s = c1c2 * c3 - s1s2 * s3;
536 649
537 return new LSL_Rotation(x, y, z, s); 650 return new LSL_Rotation(x, y, z, s);
538 } 651 }
@@ -670,77 +783,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
670 { 783 {
671 //A and B should both be normalized 784 //A and B should both be normalized
672 m_host.AddScriptLPS(1); 785 m_host.AddScriptLPS(1);
673 LSL_Rotation rotBetween; 786 /* This method is more accurate than the SL one, and thus causes problems
674 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 787 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
675 // continue calculation. 788
676 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 789 double dotProduct = LSL_Vector.Dot(a, b);
790 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
791 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
792 double angle = Math.Acos(dotProduct / magProduct);
793 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
794 double s = Math.Sin(angle / 2);
795
796 double x = axis.x * s;
797 double y = axis.y * s;
798 double z = axis.z * s;
799 double w = Math.Cos(angle / 2);
800
801 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
802 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
803
804 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
805 */
806
807 // This method mimics the 180 errors found in SL
808 // See www.euclideanspace.com... angleBetween
809 LSL_Vector vec_a = a;
810 LSL_Vector vec_b = b;
811
812 // Eliminate zero length
813 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
814 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
815 if (vec_a_mag < 0.00001 ||
816 vec_b_mag < 0.00001)
677 { 817 {
678 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 818 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
679 } 819 }
680 else 820
821 // Normalize
822 vec_a = llVecNorm(vec_a);
823 vec_b = llVecNorm(vec_b);
824
825 // Calculate axis and rotation angle
826 LSL_Vector axis = vec_a % vec_b;
827 LSL_Float cos_theta = vec_a * vec_b;
828
829 // Check if parallel
830 if (cos_theta > 0.99999)
681 { 831 {
682 a = LSL_Vector.Norm(a); 832 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
683 b = LSL_Vector.Norm(b); 833 }
684 double dotProduct = LSL_Vector.Dot(a, b); 834
685 // There are two degenerate cases possible. These are for vectors 180 or 835 // Check if anti-parallel
686 // 0 degrees apart. These have to be detected and handled individually. 836 else if (cos_theta < -0.99999)
687 // 837 {
688 // Check for vectors 180 degrees apart. 838 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
689 // A dot product of -1 would mean the angle between vectors is 180 degrees. 839 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
690 if (dotProduct < -0.9999999f) 840 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
691 { 841 }
692 // First assume X axis is orthogonal to the vectors. 842 else // other rotation
693 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 843 {
694 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 844 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
695 // Check for near zero vector. A very small non-zero number here will create 845 axis = llVecNorm(axis);
696 // a rotation in an undesired direction. 846 double x, y, z, s, t;
697 if (LSL_Vector.Mag(orthoVector) > 0.0001) 847 s = Math.Cos(theta);
698 { 848 t = Math.Sin(theta);
699 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 849 x = axis.x * t;
700 } 850 y = axis.y * t;
701 // If the magnitude of the vector was near zero, then assume the X axis is not 851 z = axis.z * t;
702 // orthogonal and use the Z axis instead. 852 return new LSL_Rotation(x,y,z,s);
703 else
704 {
705 // Set 180 z rotation.
706 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
707 }
708 }
709 // Check for parallel vectors.
710 // A dot product of 1 would mean the angle between vectors is 0 degrees.
711 else if (dotProduct > 0.9999999f)
712 {
713 // Set zero rotation.
714 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
715 }
716 else
717 {
718 // All special checks have been performed so get the axis of rotation.
719 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
720 // Quarternion s value is the length of the unit vector + dot product.
721 double qs = 1.0 + dotProduct;
722 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
723 // Normalize the rotation.
724 double mag = LSL_Rotation.Mag(rotBetween);
725 // We shouldn't have to worry about a divide by zero here. The qs value will be
726 // non-zero because we already know if we're here, then the dotProduct is not -1 so
727 // qs will not be zero. Also, we've already handled the input vectors being zero so the
728 // crossProduct vector should also not be zero.
729 rotBetween.x = rotBetween.x / mag;
730 rotBetween.y = rotBetween.y / mag;
731 rotBetween.z = rotBetween.z / mag;
732 rotBetween.s = rotBetween.s / mag;
733 // Check for undefined values and set zero rotation if any found. This code might not actually be required
734 // any longer since zero vectors are checked for at the top.
735 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
736 {
737 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
738 }
739 }
740 } 853 }
741 return rotBetween;
742 } 854 }
743 855
744 public void llWhisper(int channelID, string text) 856 public void llWhisper(int channelID, string text)
745 { 857 {
746 m_host.AddScriptLPS(1); 858 m_host.AddScriptLPS(1);
@@ -756,10 +868,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
756 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text); 868 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
757 } 869 }
758 870
871 private void CheckSayShoutTime()
872 {
873 DateTime now = DateTime.UtcNow;
874 if ((now - m_lastSayShoutCheck).Ticks > 10000000) // 1sec
875 {
876 m_lastSayShoutCheck = now;
877 m_SayShoutCount = 0;
878 }
879 else
880 m_SayShoutCount++;
881 }
882
759 public void llSay(int channelID, string text) 883 public void llSay(int channelID, string text)
760 { 884 {
761 m_host.AddScriptLPS(1); 885 m_host.AddScriptLPS(1);
762 886
887 if (channelID == 0)
888// m_SayShoutCount++;
889 CheckSayShoutTime();
890
891 if (m_SayShoutCount >= 11)
892 ScriptSleep(2000);
893
763 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 894 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
764 { 895 {
765 Console.WriteLine(text); 896 Console.WriteLine(text);
@@ -782,6 +913,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
782 { 913 {
783 m_host.AddScriptLPS(1); 914 m_host.AddScriptLPS(1);
784 915
916 if (channelID == 0)
917// m_SayShoutCount++;
918 CheckSayShoutTime();
919
920 if (m_SayShoutCount >= 11)
921 ScriptSleep(2000);
922
785 if (text.Length > 1023) 923 if (text.Length > 1023)
786 text = text.Substring(0, 1023); 924 text = text.Substring(0, 1023);
787 925
@@ -813,22 +951,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
813 951
814 public void llRegionSayTo(string target, int channel, string msg) 952 public void llRegionSayTo(string target, int channel, string msg)
815 { 953 {
954 string error = String.Empty;
955
816 if (msg.Length > 1023) 956 if (msg.Length > 1023)
817 msg = msg.Substring(0, 1023); 957 msg = msg.Substring(0, 1023);
818 958
819 m_host.AddScriptLPS(1); 959 m_host.AddScriptLPS(1);
820 960
821 if (channel == ScriptBaseClass.DEBUG_CHANNEL)
822 {
823 return;
824 }
825
826 UUID TargetID; 961 UUID TargetID;
827 UUID.TryParse(target, out TargetID); 962 UUID.TryParse(target, out TargetID);
828 963
829 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 964 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
830 if (wComm != null) 965 if (wComm != null)
831 wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg); 966 if (!wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg, out error))
967 LSLError(error);
832 } 968 }
833 969
834 public LSL_Integer llListen(int channelID, string name, string ID, string msg) 970 public LSL_Integer llListen(int channelID, string name, string ID, string msg)
@@ -1084,10 +1220,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1084 return detectedParams.TouchUV; 1220 return detectedParams.TouchUV;
1085 } 1221 }
1086 1222
1223 [DebuggerNonUserCode]
1087 public virtual void llDie() 1224 public virtual void llDie()
1088 { 1225 {
1089 m_host.AddScriptLPS(1); 1226 m_host.AddScriptLPS(1);
1090 throw new SelfDeleteException(); 1227 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1091 } 1228 }
1092 1229
1093 public LSL_Float llGround(LSL_Vector offset) 1230 public LSL_Float llGround(LSL_Vector offset)
@@ -1158,6 +1295,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1158 1295
1159 public void llSetStatus(int status, int value) 1296 public void llSetStatus(int status, int value)
1160 { 1297 {
1298 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1299 return;
1161 m_host.AddScriptLPS(1); 1300 m_host.AddScriptLPS(1);
1162 1301
1163 int statusrotationaxis = 0; 1302 int statusrotationaxis = 0;
@@ -1181,6 +1320,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1181 if (!allow) 1320 if (!allow)
1182 return; 1321 return;
1183 1322
1323 if (m_host.ParentGroup.RootPart.PhysActor != null &&
1324 m_host.ParentGroup.RootPart.PhysActor.IsPhysical)
1325 return;
1326
1184 m_host.ScriptSetPhysicsStatus(true); 1327 m_host.ScriptSetPhysicsStatus(true);
1185 } 1328 }
1186 else 1329 else
@@ -1381,6 +1524,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1381 { 1524 {
1382 m_host.AddScriptLPS(1); 1525 m_host.AddScriptLPS(1);
1383 1526
1527 SetColor(m_host, color, face);
1528 }
1529
1530 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1531 {
1532 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1533 return;
1534
1535 Primitive.TextureEntry tex = part.Shape.Textures;
1536 Color4 texcolor;
1537 if (face >= 0 && face < GetNumberOfSides(part))
1538 {
1539 texcolor = tex.CreateFace((uint)face).RGBA;
1540 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1541 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1542 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1543 tex.FaceTextures[face].RGBA = texcolor;
1544 part.UpdateTextureEntry(tex.GetBytes());
1545 return;
1546 }
1547 else if (face == ScriptBaseClass.ALL_SIDES)
1548 {
1549 for (uint i = 0; i < GetNumberOfSides(part); i++)
1550 {
1551 if (tex.FaceTextures[i] != null)
1552 {
1553 texcolor = tex.FaceTextures[i].RGBA;
1554 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1555 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1556 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1557 tex.FaceTextures[i].RGBA = texcolor;
1558 }
1559 texcolor = tex.DefaultTexture.RGBA;
1560 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1561 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1562 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1563 tex.DefaultTexture.RGBA = texcolor;
1564 }
1565 part.UpdateTextureEntry(tex.GetBytes());
1566 return;
1567 }
1568
1384 if (face == ScriptBaseClass.ALL_SIDES) 1569 if (face == ScriptBaseClass.ALL_SIDES)
1385 face = SceneObjectPart.ALL_SIDES; 1570 face = SceneObjectPart.ALL_SIDES;
1386 1571
@@ -1389,6 +1574,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1389 1574
1390 public void SetTexGen(SceneObjectPart part, int face,int style) 1575 public void SetTexGen(SceneObjectPart part, int face,int style)
1391 { 1576 {
1577 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1578 return;
1579
1392 Primitive.TextureEntry tex = part.Shape.Textures; 1580 Primitive.TextureEntry tex = part.Shape.Textures;
1393 MappingType textype; 1581 MappingType textype;
1394 textype = MappingType.Default; 1582 textype = MappingType.Default;
@@ -1419,6 +1607,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1419 1607
1420 public void SetGlow(SceneObjectPart part, int face, float glow) 1608 public void SetGlow(SceneObjectPart part, int face, float glow)
1421 { 1609 {
1610 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1611 return;
1612
1422 Primitive.TextureEntry tex = part.Shape.Textures; 1613 Primitive.TextureEntry tex = part.Shape.Textures;
1423 if (face >= 0 && face < GetNumberOfSides(part)) 1614 if (face >= 0 && face < GetNumberOfSides(part))
1424 { 1615 {
@@ -1444,6 +1635,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1444 1635
1445 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1636 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1446 { 1637 {
1638 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1639 return;
1447 1640
1448 Shininess sval = new Shininess(); 1641 Shininess sval = new Shininess();
1449 1642
@@ -1494,6 +1687,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1494 1687
1495 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1688 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1496 { 1689 {
1690 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1691 return;
1692
1497 Primitive.TextureEntry tex = part.Shape.Textures; 1693 Primitive.TextureEntry tex = part.Shape.Textures;
1498 if (face >= 0 && face < GetNumberOfSides(part)) 1694 if (face >= 0 && face < GetNumberOfSides(part))
1499 { 1695 {
@@ -1554,13 +1750,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1554 m_host.AddScriptLPS(1); 1750 m_host.AddScriptLPS(1);
1555 1751
1556 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1752 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1557 1753 if (parts.Count > 0)
1558 foreach (SceneObjectPart part in parts) 1754 {
1559 SetAlpha(part, alpha, face); 1755 try
1756 {
1757 foreach (SceneObjectPart part in parts)
1758 SetAlpha(part, alpha, face);
1759 }
1760 finally
1761 {
1762 }
1763 }
1560 } 1764 }
1561 1765
1562 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1766 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1563 { 1767 {
1768 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1769 return;
1770
1564 Primitive.TextureEntry tex = part.Shape.Textures; 1771 Primitive.TextureEntry tex = part.Shape.Textures;
1565 Color4 texcolor; 1772 Color4 texcolor;
1566 if (face >= 0 && face < GetNumberOfSides(part)) 1773 if (face >= 0 && face < GetNumberOfSides(part))
@@ -1613,7 +1820,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1613 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 1820 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1614 float wind, float tension, LSL_Vector Force) 1821 float wind, float tension, LSL_Vector Force)
1615 { 1822 {
1616 if (part == null) 1823 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1617 return; 1824 return;
1618 1825
1619 if (flexi) 1826 if (flexi)
@@ -1654,7 +1861,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1654 /// <param name="falloff"></param> 1861 /// <param name="falloff"></param>
1655 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 1862 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1656 { 1863 {
1657 if (part == null) 1864 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1658 return; 1865 return;
1659 1866
1660 if (light) 1867 if (light)
@@ -1687,11 +1894,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1687 Primitive.TextureEntry tex = part.Shape.Textures; 1894 Primitive.TextureEntry tex = part.Shape.Textures;
1688 Color4 texcolor; 1895 Color4 texcolor;
1689 LSL_Vector rgb = new LSL_Vector(); 1896 LSL_Vector rgb = new LSL_Vector();
1897 int nsides = GetNumberOfSides(part);
1898
1690 if (face == ScriptBaseClass.ALL_SIDES) 1899 if (face == ScriptBaseClass.ALL_SIDES)
1691 { 1900 {
1692 int i; 1901 int i;
1693 1902 for (i = 0; i < nsides; i++)
1694 for (i = 0 ; i < GetNumberOfSides(part); i++)
1695 { 1903 {
1696 texcolor = tex.GetFace((uint)i).RGBA; 1904 texcolor = tex.GetFace((uint)i).RGBA;
1697 rgb.x += texcolor.R; 1905 rgb.x += texcolor.R;
@@ -1699,14 +1907,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1699 rgb.z += texcolor.B; 1907 rgb.z += texcolor.B;
1700 } 1908 }
1701 1909
1702 rgb.x /= (float)GetNumberOfSides(part); 1910 float invnsides = 1.0f / (float)nsides;
1703 rgb.y /= (float)GetNumberOfSides(part); 1911
1704 rgb.z /= (float)GetNumberOfSides(part); 1912 rgb.x *= invnsides;
1913 rgb.y *= invnsides;
1914 rgb.z *= invnsides;
1705 1915
1706 return rgb; 1916 return rgb;
1707 } 1917 }
1708 1918 if (face >= 0 && face < nsides)
1709 if (face >= 0 && face < GetNumberOfSides(part))
1710 { 1919 {
1711 texcolor = tex.GetFace((uint)face).RGBA; 1920 texcolor = tex.GetFace((uint)face).RGBA;
1712 rgb.x = texcolor.R; 1921 rgb.x = texcolor.R;
@@ -1733,15 +1942,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1733 m_host.AddScriptLPS(1); 1942 m_host.AddScriptLPS(1);
1734 1943
1735 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1944 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1736 1945 if (parts.Count > 0)
1737 foreach (SceneObjectPart part in parts) 1946 {
1738 SetTexture(part, texture, face); 1947 try
1739 1948 {
1949 foreach (SceneObjectPart part in parts)
1950 SetTexture(part, texture, face);
1951 }
1952 finally
1953 {
1954 }
1955 }
1740 ScriptSleep(200); 1956 ScriptSleep(200);
1741 } 1957 }
1742 1958
1743 protected void SetTexture(SceneObjectPart part, string texture, int face) 1959 protected void SetTexture(SceneObjectPart part, string texture, int face)
1744 { 1960 {
1961 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1962 return;
1963
1745 UUID textureID = new UUID(); 1964 UUID textureID = new UUID();
1746 1965
1747 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture); 1966 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
@@ -1786,6 +2005,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1786 2005
1787 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 2006 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1788 { 2007 {
2008 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2009 return;
2010
1789 Primitive.TextureEntry tex = part.Shape.Textures; 2011 Primitive.TextureEntry tex = part.Shape.Textures;
1790 if (face >= 0 && face < GetNumberOfSides(part)) 2012 if (face >= 0 && face < GetNumberOfSides(part))
1791 { 2013 {
@@ -1822,6 +2044,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1822 2044
1823 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2045 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1824 { 2046 {
2047 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2048 return;
2049
1825 Primitive.TextureEntry tex = part.Shape.Textures; 2050 Primitive.TextureEntry tex = part.Shape.Textures;
1826 if (face >= 0 && face < GetNumberOfSides(part)) 2051 if (face >= 0 && face < GetNumberOfSides(part))
1827 { 2052 {
@@ -1858,6 +2083,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1858 2083
1859 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2084 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
1860 { 2085 {
2086 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2087 return;
2088
1861 Primitive.TextureEntry tex = part.Shape.Textures; 2089 Primitive.TextureEntry tex = part.Shape.Textures;
1862 if (face >= 0 && face < GetNumberOfSides(part)) 2090 if (face >= 0 && face < GetNumberOfSides(part))
1863 { 2091 {
@@ -1999,7 +2227,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1999 return end; 2227 return end;
2000 } 2228 }
2001 2229
2002 protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos) 2230 protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos, bool adjust)
2003 { 2231 {
2004 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 2232 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2005 return fromPos; 2233 return fromPos;
@@ -2015,9 +2243,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2015 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) 2243 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
2016 targetPos.z = ground; 2244 targetPos.z = ground;
2017 } 2245 }
2018 LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos); 2246 if (adjust)
2247 return SetPosAdjust(fromPos, targetPos);
2019 2248
2020 return real_vec; 2249 return targetPos;
2021 } 2250 }
2022 2251
2023 /// <summary> 2252 /// <summary>
@@ -2028,27 +2257,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2028 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param> 2257 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param>
2029 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust) 2258 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
2030 { 2259 {
2031 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2260 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2261 return;
2262
2032 LSL_Vector currentPos = GetPartLocalPos(part); 2263 LSL_Vector currentPos = GetPartLocalPos(part);
2264 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos, adjust);
2033 2265
2034 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
2035 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
2036 2266
2037 if (part.ParentGroup.RootPart == part) 2267 if (part.ParentGroup.RootPart == part)
2038 { 2268 {
2039 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
2040 targetPos.z = ground;
2041 SceneObjectGroup parent = part.ParentGroup; 2269 SceneObjectGroup parent = part.ParentGroup;
2042 parent.UpdateGroupPosition(!adjust ? targetPos : 2270 if (!World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos))
2043 SetPosAdjust(currentPos, targetPos)); 2271 return;
2272 Util.FireAndForget(delegate(object x) {
2273 parent.UpdateGroupPosition((Vector3)toPos);
2274 });
2044 } 2275 }
2045 else 2276 else
2046 { 2277 {
2047 part.OffsetPosition = !adjust ? targetPos : 2278 part.OffsetPosition = (Vector3)toPos;
2048 SetPosAdjust(currentPos, targetPos); 2279// SceneObjectGroup parent = part.ParentGroup;
2049 SceneObjectGroup parent = part.ParentGroup; 2280// parent.HasGroupChanged = true;
2050 parent.HasGroupChanged = true; 2281// parent.ScheduleGroupForTerseUpdate();
2051 parent.ScheduleGroupForTerseUpdate(); 2282 part.ScheduleTerseUpdate();
2052 } 2283 }
2053 } 2284 }
2054 2285
@@ -2077,13 +2308,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2077 else 2308 else
2078 { 2309 {
2079 if (part.ParentGroup.IsAttachment) 2310 if (part.ParentGroup.IsAttachment)
2080 {
2081 pos = part.AttachedPos; 2311 pos = part.AttachedPos;
2082 }
2083 else 2312 else
2084 {
2085 pos = part.AbsolutePosition; 2313 pos = part.AbsolutePosition;
2086 }
2087 } 2314 }
2088 2315
2089// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); 2316// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
@@ -2095,8 +2322,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2095 { 2322 {
2096 m_host.AddScriptLPS(1); 2323 m_host.AddScriptLPS(1);
2097 2324
2325
2326 // 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
2327 // which is then treated like a child prim rotation and it's offset gets cumulatively multiplied against.
2328 // 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.
2329 // RootPart != null should shortcircuit
2330
2098 // try to let this work as in SL... 2331 // try to let this work as in SL...
2099 if (m_host.ParentID == 0) 2332 if (m_host.ParentID == 0 || (m_host.ParentGroup != null && m_host == m_host.ParentGroup.RootPart))
2100 { 2333 {
2101 // special case: If we are root, rotate complete SOG to new rotation 2334 // special case: If we are root, rotate complete SOG to new rotation
2102 SetRot(m_host, rot); 2335 SetRot(m_host, rot);
@@ -2123,25 +2356,46 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2123 2356
2124 protected void SetRot(SceneObjectPart part, Quaternion rot) 2357 protected void SetRot(SceneObjectPart part, Quaternion rot)
2125 { 2358 {
2126 part.UpdateRotation(rot); 2359 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2127 // Update rotation does not move the object in the physics scene if it's a linkset. 2360 return;
2128 2361
2129//KF: Do NOT use this next line if using ODE physics engine. This need a switch based on .ini Phys Engine type 2362 bool isroot = (part == part.ParentGroup.RootPart);
2130// part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition; 2363 bool isphys;
2131 2364
2132 // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line
2133 // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt
2134 // It's perfectly okay when the object is not an active physical body though.
2135 // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against
2136 // but only if the object is not physial and active. This is important for rotating doors.
2137 // without the absoluteposition = absoluteposition happening, the doors do not move in the physics
2138 // scene
2139 PhysicsActor pa = part.PhysActor; 2365 PhysicsActor pa = part.PhysActor;
2140 2366
2141 if (pa != null && !pa.IsPhysical) 2367 // keep using physactor ideia of isphysical
2368 // it should be SOP ideia of that
2369 // not much of a issue with ubitODE
2370 if (pa != null && pa.IsPhysical)
2371 isphys = true;
2372 else
2373 isphys = false;
2374
2375 // SL doesn't let scripts rotate root of physical linksets
2376 if (isroot && isphys)
2377 return;
2378
2379 part.UpdateRotation(rot);
2380
2381 // Update rotation does not move the object in the physics engine if it's a non physical linkset
2382 // so do a nasty update of parts positions if is a root part rotation
2383 if (isroot && pa != null) // with if above implies non physical root part
2142 { 2384 {
2143 part.ParentGroup.ResetChildPrimPhysicsPositions(); 2385 part.ParentGroup.ResetChildPrimPhysicsPositions();
2144 } 2386 }
2387 else // fix sitting avatars. This is only needed bc of how we link avas to child parts, not root part
2388 {
2389 List<ScenePresence> sittingavas = part.ParentGroup.GetLinkedAvatars();
2390 if (sittingavas.Count > 0)
2391 {
2392 foreach (ScenePresence av in sittingavas)
2393 {
2394 if (isroot || part.LocalId == av.ParentID)
2395 av.SendTerseUpdateToAllClients();
2396 }
2397 }
2398 }
2145 } 2399 }
2146 2400
2147 /// <summary> 2401 /// <summary>
@@ -2158,6 +2412,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2158 2412
2159 m_host.AddScriptLPS(1); 2413 m_host.AddScriptLPS(1);
2160 Quaternion q = m_host.GetWorldRotation(); 2414 Quaternion q = m_host.GetWorldRotation();
2415
2416 if (m_host.ParentGroup != null && m_host.ParentGroup.AttachmentPoint != 0)
2417 {
2418 ScenePresence avatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2419 if (avatar != null)
2420 {
2421 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2422 q = avatar.CameraRotation * q; // Mouselook
2423 else
2424 q = avatar.Rotation * q; // Currently infrequently updated so may be inaccurate
2425 }
2426 }
2427
2161 return new LSL_Rotation(q.X, q.Y, q.Z, q.W); 2428 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
2162 } 2429 }
2163 2430
@@ -2183,14 +2450,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2183 q = part.ParentGroup.GroupRotation; // just the group rotation 2450 q = part.ParentGroup.GroupRotation; // just the group rotation
2184 return new LSL_Rotation(q.X, q.Y, q.Z, q.W); 2451 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
2185 } 2452 }
2453
2186 q = part.GetWorldRotation(); 2454 q = part.GetWorldRotation();
2455 if (part.ParentGroup.AttachmentPoint != 0)
2456 {
2457 ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar);
2458 if (avatar != null)
2459 {
2460 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2461 q = avatar.CameraRotation * q; // Mouselook
2462 else
2463 q = avatar.Rotation * q; // Currently infrequently updated so may be inaccurate
2464 }
2465 }
2466
2187 return new LSL_Rotation(q.X, q.Y, q.Z, q.W); 2467 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
2188 } 2468 }
2189 2469
2190 public LSL_Rotation llGetLocalRot() 2470 public LSL_Rotation llGetLocalRot()
2191 { 2471 {
2472 return GetPartLocalRot(m_host);
2473 }
2474
2475 private LSL_Rotation GetPartLocalRot(SceneObjectPart part)
2476 {
2192 m_host.AddScriptLPS(1); 2477 m_host.AddScriptLPS(1);
2193 return new LSL_Rotation(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W); 2478 Quaternion rot = part.RotationOffset;
2479 return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
2194 } 2480 }
2195 2481
2196 public void llSetForce(LSL_Vector force, int local) 2482 public void llSetForce(LSL_Vector force, int local)
@@ -2270,16 +2556,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2270 m_host.ApplyImpulse(v, local != 0); 2556 m_host.ApplyImpulse(v, local != 0);
2271 } 2557 }
2272 2558
2559
2273 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2560 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2274 { 2561 {
2275 m_host.AddScriptLPS(1); 2562 m_host.AddScriptLPS(1);
2276 m_host.ApplyAngularImpulse(force, local != 0); 2563 m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0);
2277 } 2564 }
2278 2565
2279 public void llSetTorque(LSL_Vector torque, int local) 2566 public void llSetTorque(LSL_Vector torque, int local)
2280 { 2567 {
2281 m_host.AddScriptLPS(1); 2568 m_host.AddScriptLPS(1);
2282 m_host.SetAngularImpulse(torque, local != 0); 2569 m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0);
2283 } 2570 }
2284 2571
2285 public LSL_Vector llGetTorque() 2572 public LSL_Vector llGetTorque()
@@ -2296,20 +2583,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2296 llSetTorque(torque, local); 2583 llSetTorque(torque, local);
2297 } 2584 }
2298 2585
2586 public void llSetVelocity(LSL_Vector vel, int local)
2587 {
2588 m_host.AddScriptLPS(1);
2589 m_host.SetVelocity(new Vector3((float)vel.x, (float)vel.y, (float)vel.z), local != 0);
2590 }
2591
2299 public LSL_Vector llGetVel() 2592 public LSL_Vector llGetVel()
2300 { 2593 {
2301 m_host.AddScriptLPS(1); 2594 m_host.AddScriptLPS(1);
2302 2595
2303 Vector3 vel; 2596 Vector3 vel = Vector3.Zero;
2304 2597
2305 if (m_host.ParentGroup.IsAttachment) 2598 if (m_host.ParentGroup.IsAttachment)
2306 { 2599 {
2307 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); 2600 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2308 vel = avatar.Velocity; 2601 if (avatar != null)
2602 vel = avatar.Velocity;
2309 } 2603 }
2310 else 2604 else
2311 { 2605 {
2312 vel = m_host.Velocity; 2606 vel = m_host.ParentGroup.RootPart.Velocity;
2313 } 2607 }
2314 2608
2315 return new LSL_Vector(vel.X, vel.Y, vel.Z); 2609 return new LSL_Vector(vel.X, vel.Y, vel.Z);
@@ -2321,10 +2615,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2321 return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z); 2615 return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z);
2322 } 2616 }
2323 2617
2618 public void llSetAngularVelocity(LSL_Vector avel, int local)
2619 {
2620 m_host.AddScriptLPS(1);
2621 m_host.SetAngularVelocity(new Vector3((float)avel.x, (float)avel.y, (float)avel.z), local != 0);
2622 }
2623
2324 public LSL_Vector llGetOmega() 2624 public LSL_Vector llGetOmega()
2325 { 2625 {
2326 m_host.AddScriptLPS(1); 2626 m_host.AddScriptLPS(1);
2327 return new LSL_Vector(m_host.AngularVelocity.X, m_host.AngularVelocity.Y, m_host.AngularVelocity.Z); 2627 Vector3 avel = m_host.AngularVelocity;
2628 return new LSL_Vector(avel.X, avel.Y, avel.Z);
2328 } 2629 }
2329 2630
2330 public LSL_Float llGetTimeOfDay() 2631 public LSL_Float llGetTimeOfDay()
@@ -2683,7 +2984,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2683 return src.ToLower(); 2984 return src.ToLower();
2684 } 2985 }
2685 2986
2686 public void llGiveMoney(string destination, int amount) 2987 public LSL_Integer llGiveMoney(string destination, int amount)
2687 { 2988 {
2688 Util.FireAndForget(x => 2989 Util.FireAndForget(x =>
2689 { 2990 {
@@ -2715,8 +3016,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2715 } 3016 }
2716 3017
2717 money.ObjectGiveMoney( 3018 money.ObjectGiveMoney(
2718 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 3019 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero);
2719 }); 3020 });
3021
3022 return 0;
2720 } 3023 }
2721 3024
2722 public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) 3025 public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
@@ -2795,13 +3098,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2795 new_group.RootPart.UUID.ToString()) }, 3098 new_group.RootPart.UUID.ToString()) },
2796 new DetectParams[0])); 3099 new DetectParams[0]));
2797 3100
2798 float groupmass = new_group.GetMass(); 3101 // do recoil
3102 SceneObjectGroup hostgrp = m_host.ParentGroup;
3103 if (hostgrp == null)
3104 return;
3105
3106 if (hostgrp.IsAttachment) // don't recoil avatars
3107 return;
2799 3108
2800 PhysicsActor pa = new_group.RootPart.PhysActor; 3109 PhysicsActor pa = new_group.RootPart.PhysActor;
2801 3110
2802 //Recoil. 3111 //Recoil.
2803 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3112 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
2804 { 3113 {
3114 float groupmass = new_group.GetMass();
2805 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor; 3115 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
2806 if (recoil != Vector3.Zero) 3116 if (recoil != Vector3.Zero)
2807 { 3117 {
@@ -2809,6 +3119,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2809 } 3119 }
2810 } 3120 }
2811 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3121 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3122 return;
3123
2812 }); 3124 });
2813 3125
2814 //ScriptSleep((int)((groupmass * velmag) / 10)); 3126 //ScriptSleep((int)((groupmass * velmag) / 10));
@@ -2823,35 +3135,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2823 public void llLookAt(LSL_Vector target, double strength, double damping) 3135 public void llLookAt(LSL_Vector target, double strength, double damping)
2824 { 3136 {
2825 m_host.AddScriptLPS(1); 3137 m_host.AddScriptLPS(1);
2826 // Determine where we are looking from
2827 LSL_Vector from = llGetPos();
2828 3138
2829 // Work out the normalised vector from the source to the target 3139 // Get the normalized vector to the target
2830 LSL_Vector delta = llVecNorm(target - from); 3140 LSL_Vector d1 = llVecNorm(target - llGetPos());
2831 LSL_Vector angle = new LSL_Vector(0,0,0);
2832 3141
2833 // Calculate the yaw 3142 // Get the bearing (yaw)
2834 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3143 LSL_Vector a1 = new LSL_Vector(0,0,0);
2835 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; 3144 a1.z = llAtan2(d1.y, d1.x);
2836 3145
2837 // Calculate pitch 3146 // Get the elevation (pitch)
2838 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); 3147 LSL_Vector a2 = new LSL_Vector(0,0,0);
3148 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
2839 3149
2840 // we need to convert from a vector describing 3150 LSL_Rotation r1 = llEuler2Rot(a1);
2841 // the angles of rotation in radians into rotation value 3151 LSL_Rotation r2 = llEuler2Rot(a2);
2842 LSL_Rotation rot = llEuler2Rot(angle); 3152 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
2843
2844 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2845 // set the rotation of the object, copy that behavior
2846 PhysicsActor pa = m_host.PhysActor;
2847 3153
2848 if (strength == 0 || pa == null || !pa.IsPhysical) 3154 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
2849 { 3155 {
2850 llSetRot(rot); 3156 // Do nothing if either value is 0 (this has been checked in SL)
3157 if (strength <= 0.0 || damping <= 0.0)
3158 return;
3159
3160 llSetRot(r3 * r2 * r1);
2851 } 3161 }
2852 else 3162 else
2853 { 3163 {
2854 m_host.StartLookAt(rot, (float)strength, (float)damping); 3164 if (strength == 0)
3165 {
3166 llSetRot(r3 * r2 * r1);
3167 return;
3168 }
3169
3170 m_host.StartLookAt((Quaternion)(r3 * r2 * r1), (float)strength, (float)damping);
2855 } 3171 }
2856 } 3172 }
2857 3173
@@ -2898,17 +3214,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2898 } 3214 }
2899 else 3215 else
2900 { 3216 {
2901 if (m_host.IsRoot) 3217 // new SL always returns object mass
2902 { 3218// if (m_host.IsRoot)
3219// {
2903 return m_host.ParentGroup.GetMass(); 3220 return m_host.ParentGroup.GetMass();
2904 } 3221// }
2905 else 3222// else
2906 { 3223// {
2907 return m_host.GetMass(); 3224// return m_host.GetMass();
2908 } 3225// }
2909 } 3226 }
2910 } 3227 }
2911 3228
3229
3230 public LSL_Float llGetMassMKS()
3231 {
3232 return 100f * llGetMass();
3233 }
3234
2912 public void llCollisionFilter(string name, string id, int accept) 3235 public void llCollisionFilter(string name, string id, int accept)
2913 { 3236 {
2914 m_host.AddScriptLPS(1); 3237 m_host.AddScriptLPS(1);
@@ -2956,8 +3279,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2956 { 3279 {
2957 // Unregister controls from Presence 3280 // Unregister controls from Presence
2958 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID); 3281 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID);
2959 // Remove Take Control permission.
2960 m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
2961 } 3282 }
2962 } 3283 }
2963 } 3284 }
@@ -2985,7 +3306,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2985 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3306 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
2986 3307
2987 if (attachmentsModule != null) 3308 if (attachmentsModule != null)
2988 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, false); 3309 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, false);
2989 else 3310 else
2990 return false; 3311 return false;
2991 } 3312 }
@@ -3015,9 +3336,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3015 { 3336 {
3016 m_host.AddScriptLPS(1); 3337 m_host.AddScriptLPS(1);
3017 3338
3018// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3019// return;
3020
3021 if (m_item.PermsGranter != m_host.OwnerID) 3339 if (m_item.PermsGranter != m_host.OwnerID)
3022 return; 3340 return;
3023 3341
@@ -3060,6 +3378,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3060 3378
3061 public void llInstantMessage(string user, string message) 3379 public void llInstantMessage(string user, string message)
3062 { 3380 {
3381 UUID result;
3382 if (!UUID.TryParse(user, out result) || result == UUID.Zero)
3383 {
3384 ShoutError("An invalid key was passed to llInstantMessage");
3385 ScriptSleep(2000);
3386 return;
3387 }
3388
3389
3063 m_host.AddScriptLPS(1); 3390 m_host.AddScriptLPS(1);
3064 3391
3065 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3392 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -3074,14 +3401,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3074 UUID friendTransactionID = UUID.Random(); 3401 UUID friendTransactionID = UUID.Random();
3075 3402
3076 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 3403 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3077 3404
3078 GridInstantMessage msg = new GridInstantMessage(); 3405 GridInstantMessage msg = new GridInstantMessage();
3079 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3406 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
3080 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3407 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3081 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3408 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
3082// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3409// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3083// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3410// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3084 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3411// DateTime dt = DateTime.UtcNow;
3412//
3413// // Ticks from UtcNow, but make it look like local. Evil, huh?
3414// dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
3415//
3416// try
3417// {
3418// // Convert that to the PST timezone
3419// TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
3420// dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
3421// }
3422// catch
3423// {
3424// // No logging here, as it could be VERY spammy
3425// }
3426//
3427// // And make it look local again to fool the unix time util
3428// dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
3429
3430 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3431
3085 //if (client != null) 3432 //if (client != null)
3086 //{ 3433 //{
3087 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3434 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
@@ -3095,12 +3442,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3095 msg.message = message.Substring(0, 1024); 3442 msg.message = message.Substring(0, 1024);
3096 else 3443 else
3097 msg.message = message; 3444 msg.message = message;
3098 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3445 msg.dialog = (byte)19; // MessageFromObject
3099 msg.fromGroup = false;// fromGroup; 3446 msg.fromGroup = false;// fromGroup;
3100 msg.offline = (byte)0; //offline; 3447 msg.offline = (byte)0; //offline;
3101 msg.ParentEstateID = 0; //ParentEstateID; 3448 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3102 msg.Position = new Vector3(m_host.AbsolutePosition); 3449 msg.Position = new Vector3(m_host.AbsolutePosition);
3103 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3450 msg.RegionID = World.RegionInfo.RegionID.Guid;
3104 msg.binaryBucket 3451 msg.binaryBucket
3105 = Util.StringToBytes256( 3452 = Util.StringToBytes256(
3106 "{0}/{1}/{2}/{3}", 3453 "{0}/{1}/{2}/{3}",
@@ -3128,7 +3475,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3128 } 3475 }
3129 3476
3130 emailModule.SendEmail(m_host.UUID, address, subject, message); 3477 emailModule.SendEmail(m_host.UUID, address, subject, message);
3131 llSleep(EMAIL_PAUSE_TIME); 3478 ScriptSleep(EMAIL_PAUSE_TIME * 1000);
3132 } 3479 }
3133 3480
3134 public void llGetNextEmail(string address, string subject) 3481 public void llGetNextEmail(string address, string subject)
@@ -3374,7 +3721,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3374 implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3721 implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3375 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3722 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3376 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3723 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3724 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3377 ScriptBaseClass.PERMISSION_ATTACH; 3725 ScriptBaseClass.PERMISSION_ATTACH;
3726
3378 } 3727 }
3379 else 3728 else
3380 { 3729 {
@@ -3391,15 +3740,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3391 if (World.GetExtraSetting("auto_grant_attach_perms") == "true") 3740 if (World.GetExtraSetting("auto_grant_attach_perms") == "true")
3392 implicitPerms = ScriptBaseClass.PERMISSION_ATTACH; 3741 implicitPerms = ScriptBaseClass.PERMISSION_ATTACH;
3393 } 3742 }
3743 if (World.GetExtraSetting("auto_grant_all_perms") == "true")
3744 {
3745 implicitPerms = perm;
3746 }
3394 } 3747 }
3395 3748
3396 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3749 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3397 { 3750 {
3398 lock (m_host.TaskInventory) 3751 m_host.TaskInventory.LockItemsForWrite(true);
3399 { 3752 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3400 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3753 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3401 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3754 m_host.TaskInventory.LockItemsForWrite(false);
3402 }
3403 3755
3404 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3756 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3405 "run_time_permissions", new Object[] { 3757 "run_time_permissions", new Object[] {
@@ -3442,11 +3794,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3442 3794
3443 if (!m_waitingForScriptAnswer) 3795 if (!m_waitingForScriptAnswer)
3444 { 3796 {
3445 lock (m_host.TaskInventory) 3797 m_host.TaskInventory.LockItemsForWrite(true);
3446 { 3798 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3447 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3799 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3448 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 3800 m_host.TaskInventory.LockItemsForWrite(false);
3449 }
3450 3801
3451 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3802 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3452 m_waitingForScriptAnswer=true; 3803 m_waitingForScriptAnswer=true;
@@ -3475,14 +3826,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3475 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3826 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3476 llReleaseControls(); 3827 llReleaseControls();
3477 3828
3478 lock (m_host.TaskInventory) 3829 m_host.TaskInventory.LockItemsForWrite(true);
3479 { 3830 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3480 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 3831 m_host.TaskInventory.LockItemsForWrite(false);
3481 } 3832
3482 3833 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3483 m_ScriptEngine.PostScriptEvent( 3834 "run_time_permissions", new Object[] {
3484 m_item.ItemID, 3835 new LSL_Integer(answer) },
3485 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); 3836 new DetectParams[0]));
3486 } 3837 }
3487 3838
3488 public LSL_String llGetPermissionsKey() 3839 public LSL_String llGetPermissionsKey()
@@ -3521,14 +3872,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3521 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 3872 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3522 { 3873 {
3523 List<SceneObjectPart> parts = GetLinkParts(linknumber); 3874 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3524 3875 if (parts.Count > 0)
3525 foreach (SceneObjectPart part in parts) 3876 {
3526 part.SetFaceColorAlpha(face, color, null); 3877 try
3878 {
3879 foreach (SceneObjectPart part in parts)
3880 part.SetFaceColorAlpha(face, color, null);
3881 }
3882 finally
3883 {
3884 }
3885 }
3527 } 3886 }
3528 3887
3529 public void llCreateLink(string target, int parent) 3888 public void llCreateLink(string target, int parent)
3530 { 3889 {
3531 m_host.AddScriptLPS(1); 3890 m_host.AddScriptLPS(1);
3891
3532 UUID targetID; 3892 UUID targetID;
3533 3893
3534 if (!UUID.TryParse(target, out targetID)) 3894 if (!UUID.TryParse(target, out targetID))
@@ -3634,10 +3994,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3634 // Restructuring Multiple Prims. 3994 // Restructuring Multiple Prims.
3635 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 3995 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3636 parts.Remove(parentPrim.RootPart); 3996 parts.Remove(parentPrim.RootPart);
3637 foreach (SceneObjectPart part in parts) 3997 if (parts.Count > 0)
3638 { 3998 {
3639 parentPrim.DelinkFromGroup(part.LocalId, true); 3999 try
4000 {
4001 foreach (SceneObjectPart part in parts)
4002 {
4003 parentPrim.DelinkFromGroup(part.LocalId, true);
4004 }
4005 }
4006 finally
4007 {
4008 }
3640 } 4009 }
4010
3641 parentPrim.HasGroupChanged = true; 4011 parentPrim.HasGroupChanged = true;
3642 parentPrim.ScheduleGroupForFullUpdate(); 4012 parentPrim.ScheduleGroupForFullUpdate();
3643 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4013 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -3646,12 +4016,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3646 { 4016 {
3647 SceneObjectPart newRoot = parts[0]; 4017 SceneObjectPart newRoot = parts[0];
3648 parts.Remove(newRoot); 4018 parts.Remove(newRoot);
3649 foreach (SceneObjectPart part in parts) 4019
4020 try
3650 { 4021 {
3651 // Required for linking 4022 foreach (SceneObjectPart part in parts)
3652 part.ClearUpdateSchedule(); 4023 {
3653 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4024 part.ClearUpdateSchedule();
4025 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4026 }
3654 } 4027 }
4028 finally
4029 {
4030 }
4031
4032
3655 newRoot.ParentGroup.HasGroupChanged = true; 4033 newRoot.ParentGroup.HasGroupChanged = true;
3656 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4034 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3657 } 4035 }
@@ -3671,6 +4049,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3671 public void llBreakAllLinks() 4049 public void llBreakAllLinks()
3672 { 4050 {
3673 m_host.AddScriptLPS(1); 4051 m_host.AddScriptLPS(1);
4052
4053 TaskInventoryItem item = m_item;
4054
4055 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4056 && !m_automaticLinkPermission)
4057 {
4058 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4059 return;
4060 }
4061
3674 SceneObjectGroup parentPrim = m_host.ParentGroup; 4062 SceneObjectGroup parentPrim = m_host.ParentGroup;
3675 if (parentPrim.AttachmentPoint != 0) 4063 if (parentPrim.AttachmentPoint != 0)
3676 return; // Fail silently if attached 4064 return; // Fail silently if attached
@@ -3690,47 +4078,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3690 public LSL_String llGetLinkKey(int linknum) 4078 public LSL_String llGetLinkKey(int linknum)
3691 { 4079 {
3692 m_host.AddScriptLPS(1); 4080 m_host.AddScriptLPS(1);
3693 4081 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
3694 if (linknum < 0) 4082 if (part != null)
3695 {
3696 if (linknum == ScriptBaseClass.LINK_THIS)
3697 return m_host.UUID.ToString();
3698 else
3699 return ScriptBaseClass.NULL_KEY;
3700 }
3701
3702 int actualPrimCount = m_host.ParentGroup.PrimCount;
3703 List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars();
3704 int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count;
3705
3706 // Special case for a single prim. In this case the linknum is zero. However, this will not match a single
3707 // prim that has any avatars sat upon it (in which case the root prim is link 1).
3708 if (linknum == 0)
3709 {
3710 if (actualPrimCount == 1 && sittingAvatarIds.Count == 0)
3711 return m_host.UUID.ToString();
3712
3713 return ScriptBaseClass.NULL_KEY;
3714 }
3715 // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but
3716 // here we must match 1 (ScriptBaseClass.LINK_ROOT).
3717 else if (linknum == 1 && actualPrimCount == 1)
3718 {
3719 if (sittingAvatarIds.Count > 0)
3720 return m_host.ParentGroup.RootPart.UUID.ToString();
3721 else
3722 return ScriptBaseClass.NULL_KEY;
3723 }
3724 else if (linknum <= adjustedPrimCount)
3725 { 4083 {
3726 if (linknum <= actualPrimCount) 4084 return part.UUID.ToString();
3727 return m_host.ParentGroup.GetLinkNumPart(linknum).UUID.ToString();
3728 else
3729 return sittingAvatarIds[linknum - actualPrimCount - 1].ToString();
3730 } 4085 }
3731 else 4086 else
3732 { 4087 {
3733 return ScriptBaseClass.NULL_KEY; 4088 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4089 {
4090 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4091
4092 if (linknum < 0)
4093 return UUID.Zero.ToString();
4094
4095 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4096 if (avatars.Count > linknum)
4097 {
4098 return avatars[linknum].UUID.ToString();
4099 }
4100 }
4101 return UUID.Zero.ToString();
3734 } 4102 }
3735 } 4103 }
3736 4104
@@ -3833,17 +4201,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3833 m_host.AddScriptLPS(1); 4201 m_host.AddScriptLPS(1);
3834 int count = 0; 4202 int count = 0;
3835 4203
3836 lock (m_host.TaskInventory) 4204 m_host.TaskInventory.LockItemsForRead(true);
4205 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3837 { 4206 {
3838 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4207 if (inv.Value.Type == type || type == -1)
3839 { 4208 {
3840 if (inv.Value.Type == type || type == -1) 4209 count = count + 1;
3841 {
3842 count = count + 1;
3843 }
3844 } 4210 }
3845 } 4211 }
3846 4212
4213 m_host.TaskInventory.LockItemsForRead(false);
3847 return count; 4214 return count;
3848 } 4215 }
3849 4216
@@ -3852,16 +4219,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3852 m_host.AddScriptLPS(1); 4219 m_host.AddScriptLPS(1);
3853 ArrayList keys = new ArrayList(); 4220 ArrayList keys = new ArrayList();
3854 4221
3855 lock (m_host.TaskInventory) 4222 m_host.TaskInventory.LockItemsForRead(true);
4223 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3856 { 4224 {
3857 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4225 if (inv.Value.Type == type || type == -1)
3858 { 4226 {
3859 if (inv.Value.Type == type || type == -1) 4227 keys.Add(inv.Value.Name);
3860 {
3861 keys.Add(inv.Value.Name);
3862 }
3863 } 4228 }
3864 } 4229 }
4230 m_host.TaskInventory.LockItemsForRead(false);
3865 4231
3866 if (keys.Count == 0) 4232 if (keys.Count == 0)
3867 { 4233 {
@@ -3899,7 +4265,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3899 if (item == null) 4265 if (item == null)
3900 { 4266 {
3901 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4267 llSay(0, String.Format("Could not find object '{0}'", inventory));
3902 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4268 return;
4269// throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
3903 } 4270 }
3904 4271
3905 UUID objId = item.ItemID; 4272 UUID objId = item.ItemID;
@@ -3927,33 +4294,45 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3927 return; 4294 return;
3928 } 4295 }
3929 } 4296 }
4297
3930 // destination is an avatar 4298 // destination is an avatar
3931 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4299 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId);
3932 4300
3933 if (agentItem == null) 4301 if (agentItem == null)
3934 return; 4302 return;
3935 4303
3936 if (m_TransferModule != null) 4304 byte[] bucket = new byte[1];
3937 { 4305 bucket[0] = (byte)item.Type;
3938 byte[] bucket = new byte[1]; 4306 //byte[] objBytes = agentItem.ID.GetBytes();
3939 bucket[0] = (byte)item.Type; 4307 //Array.Copy(objBytes, 0, bucket, 1, 16);
3940 4308
3941 GridInstantMessage msg = new GridInstantMessage(World, 4309 GridInstantMessage msg = new GridInstantMessage(World,
3942 m_host.OwnerID, m_host.Name, destId, 4310 m_host.OwnerID, m_host.Name, destId,
3943 (byte)InstantMessageDialog.TaskInventoryOffered, 4311 (byte)InstantMessageDialog.TaskInventoryOffered,
3944 false, item.Name+". "+m_host.Name+" is located at "+ 4312 false, item.Name+". "+m_host.Name+" is located at "+
3945 World.RegionInfo.RegionName+" "+ 4313 World.RegionInfo.RegionName+" "+
3946 m_host.AbsolutePosition.ToString(), 4314 m_host.AbsolutePosition.ToString(),
3947 agentItem.ID, true, m_host.AbsolutePosition, 4315 agentItem.ID, true, m_host.AbsolutePosition,
3948 bucket, true); 4316 bucket, true);
3949 4317
3950 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4318 ScenePresence sp;
3951 }
3952 4319
4320 if (World.TryGetScenePresence(destId, out sp))
4321 {
4322 sp.ControllingClient.SendInstantMessage(msg);
4323 }
4324 else
4325 {
4326 if (m_TransferModule != null)
4327 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4328 }
4329
4330 //This delay should only occur when giving inventory to avatars.
3953 ScriptSleep(3000); 4331 ScriptSleep(3000);
3954 } 4332 }
3955 } 4333 }
3956 4334
4335 [DebuggerNonUserCode]
3957 public void llRemoveInventory(string name) 4336 public void llRemoveInventory(string name)
3958 { 4337 {
3959 m_host.AddScriptLPS(1); 4338 m_host.AddScriptLPS(1);
@@ -4008,109 +4387,115 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4008 { 4387 {
4009 m_host.AddScriptLPS(1); 4388 m_host.AddScriptLPS(1);
4010 4389
4011 UUID uuid = (UUID)id; 4390 UUID uuid;
4012 PresenceInfo pinfo = null; 4391 if (UUID.TryParse(id, out uuid))
4013 UserAccount account;
4014
4015 UserInfoCacheEntry ce;
4016 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4017 { 4392 {
4018 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4393 PresenceInfo pinfo = null;
4019 if (account == null) 4394 UserAccount account;
4395
4396 UserInfoCacheEntry ce;
4397 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4020 { 4398 {
4021 m_userInfoCache[uuid] = null; // Cache negative 4399 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4022 return UUID.Zero.ToString(); 4400 if (account == null)
4023 } 4401 {
4402 m_userInfoCache[uuid] = null; // Cache negative
4403 return UUID.Zero.ToString();
4404 }
4024 4405
4025 4406
4026 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4407 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4027 if (pinfos != null && pinfos.Length > 0) 4408 if (pinfos != null && pinfos.Length > 0)
4028 {
4029 foreach (PresenceInfo p in pinfos)
4030 { 4409 {
4031 if (p.RegionID != UUID.Zero) 4410 foreach (PresenceInfo p in pinfos)
4032 { 4411 {
4033 pinfo = p; 4412 if (p.RegionID != UUID.Zero)
4413 {
4414 pinfo = p;
4415 }
4034 } 4416 }
4035 } 4417 }
4036 }
4037 4418
4038 ce = new UserInfoCacheEntry(); 4419 ce = new UserInfoCacheEntry();
4039 ce.time = Util.EnvironmentTickCount(); 4420 ce.time = Util.EnvironmentTickCount();
4040 ce.account = account; 4421 ce.account = account;
4041 ce.pinfo = pinfo; 4422 ce.pinfo = pinfo;
4042 } 4423 m_userInfoCache[uuid] = ce;
4043 else 4424 }
4044 { 4425 else
4045 if (ce == null) 4426 {
4046 return UUID.Zero.ToString(); 4427 if (ce == null)
4428 return UUID.Zero.ToString();
4047 4429
4048 account = ce.account; 4430 account = ce.account;
4049 pinfo = ce.pinfo; 4431 pinfo = ce.pinfo;
4050 } 4432 }
4051 4433
4052 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4434 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4053 {
4054 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4055 if (pinfos != null && pinfos.Length > 0)
4056 { 4435 {
4057 foreach (PresenceInfo p in pinfos) 4436 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4437 if (pinfos != null && pinfos.Length > 0)
4058 { 4438 {
4059 if (p.RegionID != UUID.Zero) 4439 foreach (PresenceInfo p in pinfos)
4060 { 4440 {
4061 pinfo = p; 4441 if (p.RegionID != UUID.Zero)
4442 {
4443 pinfo = p;
4444 }
4062 } 4445 }
4063 } 4446 }
4064 } 4447 else
4065 else 4448 pinfo = null;
4066 pinfo = null;
4067 4449
4068 ce.time = Util.EnvironmentTickCount(); 4450 ce.time = Util.EnvironmentTickCount();
4069 ce.pinfo = pinfo; 4451 ce.pinfo = pinfo;
4070 } 4452 }
4071 4453
4072 string reply = String.Empty; 4454 string reply = String.Empty;
4073 4455
4074 switch (data) 4456 switch (data)
4075 { 4457 {
4076 case 1: // DATA_ONLINE (0|1) 4458 case 1: // DATA_ONLINE (0|1)
4077 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4459 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4078 reply = "1"; 4460 reply = "1";
4079 else 4461 else
4080 reply = "0"; 4462 reply = "0";
4081 break; 4463 break;
4082 case 2: // DATA_NAME (First Last) 4464 case 2: // DATA_NAME (First Last)
4083 reply = account.FirstName + " " + account.LastName; 4465 reply = account.FirstName + " " + account.LastName;
4084 break; 4466 break;
4085 case 3: // DATA_BORN (YYYY-MM-DD) 4467 case 3: // DATA_BORN (YYYY-MM-DD)
4086 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4468 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4087 born = born.AddSeconds(account.Created); 4469 born = born.AddSeconds(account.Created);
4088 reply = born.ToString("yyyy-MM-dd"); 4470 reply = born.ToString("yyyy-MM-dd");
4089 break; 4471 break;
4090 case 4: // DATA_RATING (0,0,0,0,0,0) 4472 case 4: // DATA_RATING (0,0,0,0,0,0)
4091 reply = "0,0,0,0,0,0"; 4473 reply = "0,0,0,0,0,0";
4092 break; 4474 break;
4093 case 7: // DATA_USERLEVEL (integer) 4475 case 8: // DATA_PAYINFO (0|1|2|3)
4094 reply = account.UserLevel.ToString(); 4476 reply = "0";
4095 break; 4477 break;
4096 case 8: // DATA_PAYINFO (0|1|2|3) 4478 default:
4097 reply = "0"; 4479 return UUID.Zero.ToString(); // Raise no event
4098 break; 4480 }
4099 default:
4100 return UUID.Zero.ToString(); // Raise no event
4101 }
4102 4481
4103 UUID rq = UUID.Random(); 4482 UUID rq = UUID.Random();
4104 4483
4105 UUID tid = AsyncCommands. 4484 UUID tid = AsyncCommands.
4106 DataserverPlugin.RegisterRequest(m_host.LocalId, 4485 DataserverPlugin.RegisterRequest(m_host.LocalId,
4107 m_item.ItemID, rq.ToString()); 4486 m_item.ItemID, rq.ToString());
4108 4487
4109 AsyncCommands. 4488 AsyncCommands.
4110 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4489 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4111 4490
4112 ScriptSleep(100); 4491 ScriptSleep(100);
4113 return tid.ToString(); 4492 return tid.ToString();
4493 }
4494 else
4495 {
4496 ShoutError("Invalid UUID passed to llRequestAgentData.");
4497 }
4498 return "";
4114 } 4499 }
4115 4500
4116 public LSL_String llRequestInventoryData(string name) 4501 public LSL_String llRequestInventoryData(string name)
@@ -4167,13 +4552,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4167 if (UUID.TryParse(agent, out agentId)) 4552 if (UUID.TryParse(agent, out agentId))
4168 { 4553 {
4169 ScenePresence presence = World.GetScenePresence(agentId); 4554 ScenePresence presence = World.GetScenePresence(agentId);
4170 if (presence != null) 4555 if (presence != null && presence.PresenceType != PresenceType.Npc)
4171 { 4556 {
4557 // agent must not be a god
4558 if (presence.UserLevel >= 200) return;
4559
4172 // agent must be over the owners land 4560 // agent must be over the owners land
4173 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4561 if (m_host.OwnerID == World.LandChannel.GetLandObject(
4174 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 4562 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4175 { 4563 {
4176 World.TeleportClientHome(agentId, presence.ControllingClient); 4564 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4565 {
4566 // They can't be teleported home for some reason
4567 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4568 if (regionInfo != null)
4569 {
4570 World.RequestTeleportLocation(
4571 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4572 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4573 }
4574 }
4177 } 4575 }
4178 } 4576 }
4179 } 4577 }
@@ -4280,7 +4678,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4280 UUID av = new UUID(); 4678 UUID av = new UUID();
4281 if (!UUID.TryParse(agent,out av)) 4679 if (!UUID.TryParse(agent,out av))
4282 { 4680 {
4283 LSLError("First parameter to llDialog needs to be a key"); 4681 //LSLError("First parameter to llDialog needs to be a key");
4284 return; 4682 return;
4285 } 4683 }
4286 4684
@@ -4312,10 +4710,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4312 public void llCollisionSound(string impact_sound, double impact_volume) 4710 public void llCollisionSound(string impact_sound, double impact_volume)
4313 { 4711 {
4314 m_host.AddScriptLPS(1); 4712 m_host.AddScriptLPS(1);
4315 4713
4714 if(impact_sound == "")
4715 {
4716 m_host.CollisionSoundVolume = (float)impact_volume;
4717 m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
4718 m_host.CollisionSoundType = 0;
4719 return;
4720 }
4316 // TODO: Parameter check logic required. 4721 // TODO: Parameter check logic required.
4317 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound); 4722 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
4318 m_host.CollisionSoundVolume = (float)impact_volume; 4723 m_host.CollisionSoundVolume = (float)impact_volume;
4724 m_host.CollisionSoundType = 1;
4319 } 4725 }
4320 4726
4321 public LSL_String llGetAnimation(string id) 4727 public LSL_String llGetAnimation(string id)
@@ -4329,14 +4735,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4329 4735
4330 if (m_host.RegionHandle == presence.RegionHandle) 4736 if (m_host.RegionHandle == presence.RegionHandle)
4331 { 4737 {
4332 Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames;
4333
4334 if (presence != null) 4738 if (presence != null)
4335 { 4739 {
4336 AnimationSet currentAnims = presence.Animator.Animations; 4740 if (presence.SitGround)
4337 string currentAnimationState = String.Empty; 4741 return "Sitting on Ground";
4338 if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState)) 4742 if (presence.ParentID != 0 || presence.ParentUUID != UUID.Zero)
4339 return currentAnimationState; 4743 return "Sitting";
4744
4745 string movementAnimation = presence.Animator.CurrentMovementAnimation;
4746 string lslMovementAnimation;
4747
4748 if (MovementAnimationsForLSL.TryGetValue(movementAnimation, out lslMovementAnimation))
4749 return lslMovementAnimation;
4340 } 4750 }
4341 } 4751 }
4342 4752
@@ -4483,7 +4893,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4483 { 4893 {
4484 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4894 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4485 float distance_term = distance * distance * distance; // Script Energy 4895 float distance_term = distance * distance * distance; // Script Energy
4486 float pusher_mass = m_host.GetMass(); 4896 // use total object mass and not part
4897 float pusher_mass = m_host.ParentGroup.GetMass();
4487 4898
4488 float PUSH_ATTENUATION_DISTANCE = 17f; 4899 float PUSH_ATTENUATION_DISTANCE = 17f;
4489 float PUSH_ATTENUATION_SCALE = 5f; 4900 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4733,6 +5144,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4733 { 5144 {
4734 return item.AssetID.ToString(); 5145 return item.AssetID.ToString();
4735 } 5146 }
5147 m_host.TaskInventory.LockItemsForRead(false);
4736 5148
4737 return UUID.Zero.ToString(); 5149 return UUID.Zero.ToString();
4738 } 5150 }
@@ -4885,14 +5297,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4885 { 5297 {
4886 m_host.AddScriptLPS(1); 5298 m_host.AddScriptLPS(1);
4887 5299
4888 if (src == null) 5300 return src.Length;
4889 {
4890 return 0;
4891 }
4892 else
4893 {
4894 return src.Length;
4895 }
4896 } 5301 }
4897 5302
4898 public LSL_Integer llList2Integer(LSL_List src, int index) 5303 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4963,7 +5368,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4963 else if (src.Data[index] is LSL_Float) 5368 else if (src.Data[index] is LSL_Float)
4964 return Convert.ToDouble(((LSL_Float)src.Data[index]).value); 5369 return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
4965 else if (src.Data[index] is LSL_String) 5370 else if (src.Data[index] is LSL_String)
4966 return Convert.ToDouble(((LSL_String)src.Data[index]).m_string); 5371 {
5372 string str = ((LSL_String) src.Data[index]).m_string;
5373 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5374 if (m != Match.Empty)
5375 {
5376 str = m.Value;
5377 double d = 0.0;
5378 if (!Double.TryParse(str, out d))
5379 return 0.0;
5380
5381 return d;
5382 }
5383 return 0.0;
5384 }
4967 return Convert.ToDouble(src.Data[index]); 5385 return Convert.ToDouble(src.Data[index]);
4968 } 5386 }
4969 catch (FormatException) 5387 catch (FormatException)
@@ -5005,7 +5423,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5005 // for completion and should LSL_Key ever be implemented 5423 // for completion and should LSL_Key ever be implemented
5006 // as it's own struct 5424 // as it's own struct
5007 else if (!(src.Data[index] is LSL_String || 5425 else if (!(src.Data[index] is LSL_String ||
5008 src.Data[index] is LSL_Key)) 5426 src.Data[index] is LSL_Key ||
5427 src.Data[index] is String))
5009 { 5428 {
5010 return ""; 5429 return "";
5011 } 5430 }
@@ -5263,7 +5682,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5263 } 5682 }
5264 } 5683 }
5265 } 5684 }
5266 else { 5685 else
5686 {
5267 object[] array = new object[src.Length]; 5687 object[] array = new object[src.Length];
5268 Array.Copy(src.Data, 0, array, 0, src.Length); 5688 Array.Copy(src.Data, 0, array, 0, src.Length);
5269 result = new LSL_List(array); 5689 result = new LSL_List(array);
@@ -5370,7 +5790,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5370 public LSL_Integer llGetRegionAgentCount() 5790 public LSL_Integer llGetRegionAgentCount()
5371 { 5791 {
5372 m_host.AddScriptLPS(1); 5792 m_host.AddScriptLPS(1);
5373 return new LSL_Integer(World.GetRootAgentCount()); 5793
5794 int count = 0;
5795 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5796 count++;
5797 });
5798
5799 return new LSL_Integer(count);
5374 } 5800 }
5375 5801
5376 public LSL_Vector llGetRegionCorner() 5802 public LSL_Vector llGetRegionCorner()
@@ -5611,6 +6037,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5611 flags |= ScriptBaseClass.AGENT_AWAY; 6037 flags |= ScriptBaseClass.AGENT_AWAY;
5612 } 6038 }
5613 6039
6040 UUID busy = new UUID("efcf670c-2d18-8128-973a-034ebc806b67");
6041 UUID[] anims = agent.Animator.GetAnimationArray();
6042 if (Array.Exists<UUID>(anims, a => { return a == busy; }))
6043 {
6044 flags |= ScriptBaseClass.AGENT_BUSY;
6045 }
6046
5614 // seems to get unset, even if in mouselook, when avatar is sitting on a prim??? 6047 // seems to get unset, even if in mouselook, when avatar is sitting on a prim???
5615 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) 6048 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
5616 { 6049 {
@@ -5658,6 +6091,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5658 flags |= ScriptBaseClass.AGENT_SITTING; 6091 flags |= ScriptBaseClass.AGENT_SITTING;
5659 } 6092 }
5660 6093
6094 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
6095 {
6096 flags |= ScriptBaseClass.AGENT_MALE;
6097 }
6098
5661 return flags; 6099 return flags;
5662 } 6100 }
5663 6101
@@ -5805,9 +6243,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5805 6243
5806 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6244 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5807 6245
5808 foreach (SceneObjectPart part in parts) 6246 try
6247 {
6248 foreach (SceneObjectPart part in parts)
6249 {
6250 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6251 }
6252 }
6253 finally
5809 { 6254 {
5810 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
5811 } 6255 }
5812 } 6256 }
5813 6257
@@ -5861,13 +6305,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5861 6305
5862 if (m_host.OwnerID == land.LandData.OwnerID) 6306 if (m_host.OwnerID == land.LandData.OwnerID)
5863 { 6307 {
5864 World.TeleportClientHome(agentID, presence.ControllingClient); 6308 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6309 presence.TeleportWithMomentum(pos, null);
6310 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5865 } 6311 }
5866 } 6312 }
5867 } 6313 }
5868 ScriptSleep(5000); 6314 ScriptSleep(5000);
5869 } 6315 }
5870 6316
6317 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6318 {
6319 return ParseString2List(str, separators, in_spacers, false);
6320 }
6321
5871 public LSL_Integer llOverMyLand(string id) 6322 public LSL_Integer llOverMyLand(string id)
5872 { 6323 {
5873 m_host.AddScriptLPS(1); 6324 m_host.AddScriptLPS(1);
@@ -5921,25 +6372,55 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5921 } 6372 }
5922 else 6373 else
5923 { 6374 {
5924 agentSize = new LSL_Vector(0.45, 0.6, avatar.Appearance.AvatarHeight); 6375// agentSize = new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight);
6376 Vector3 s = avatar.Appearance.AvatarSize;
6377 agentSize = new LSL_Vector(s.X, s.Y, s.Z);
5925 } 6378 }
5926 return agentSize; 6379 return agentSize;
5927 } 6380 }
5928 6381
5929 public LSL_Integer llSameGroup(string agent) 6382 public LSL_Integer llSameGroup(string id)
5930 { 6383 {
5931 m_host.AddScriptLPS(1); 6384 m_host.AddScriptLPS(1);
5932 UUID agentId = new UUID(); 6385 UUID uuid = new UUID();
5933 if (!UUID.TryParse(agent, out agentId)) 6386 if (!UUID.TryParse(id, out uuid))
5934 return new LSL_Integer(0);
5935 ScenePresence presence = World.GetScenePresence(agentId);
5936 if (presence == null || presence.IsChildAgent) // Return flase for child agents
5937 return new LSL_Integer(0); 6387 return new LSL_Integer(0);
5938 IClientAPI client = presence.ControllingClient; 6388
5939 if (m_host.GroupID == client.ActiveGroupId) 6389 // Check if it's a group key
6390 if (uuid == m_host.ParentGroup.RootPart.GroupID)
5940 return new LSL_Integer(1); 6391 return new LSL_Integer(1);
5941 else 6392
6393 // We got passed a UUID.Zero
6394 if (uuid == UUID.Zero)
6395 return new LSL_Integer(0);
6396
6397 // Handle the case where id names an avatar
6398 ScenePresence presence = World.GetScenePresence(uuid);
6399 if (presence != null)
6400 {
6401 if (presence.IsChildAgent)
6402 return new LSL_Integer(0);
6403
6404 IClientAPI client = presence.ControllingClient;
6405 if (m_host.ParentGroup.RootPart.GroupID == client.ActiveGroupId)
6406 return new LSL_Integer(1);
6407
6408 return new LSL_Integer(0);
6409 }
6410
6411 // Handle object case
6412 SceneObjectPart part = World.GetSceneObjectPart(uuid);
6413 if (part != null)
6414 {
6415 // This will handle both deed and non-deed and also the no
6416 // group case
6417 if (part.ParentGroup.RootPart.GroupID == m_host.ParentGroup.RootPart.GroupID)
6418 return new LSL_Integer(1);
6419
5942 return new LSL_Integer(0); 6420 return new LSL_Integer(0);
6421 }
6422
6423 return new LSL_Integer(0);
5943 } 6424 }
5944 6425
5945 public void llUnSit(string id) 6426 public void llUnSit(string id)
@@ -6064,7 +6545,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6064 return m_host.ParentGroup.AttachmentPoint; 6545 return m_host.ParentGroup.AttachmentPoint;
6065 } 6546 }
6066 6547
6067 public LSL_Integer llGetFreeMemory() 6548 public virtual LSL_Integer llGetFreeMemory()
6068 { 6549 {
6069 m_host.AddScriptLPS(1); 6550 m_host.AddScriptLPS(1);
6070 // Make scripts designed for LSO happy 6551 // Make scripts designed for LSO happy
@@ -6496,6 +6977,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6496 6977
6497 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot) 6978 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot)
6498 { 6979 {
6980 // LSL quaternions can normalize to 0, normal Quaternions can't.
6981 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
6982 rot.s = 1; // ZERO_ROTATION = 0,0,0,1
6983
6499 part.SitTargetPosition = offset; 6984 part.SitTargetPosition = offset;
6500 part.SitTargetOrientation = rot; 6985 part.SitTargetOrientation = rot;
6501 part.ParentGroup.HasGroupChanged = true; 6986 part.ParentGroup.HasGroupChanged = true;
@@ -6681,13 +7166,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6681 UUID av = new UUID(); 7166 UUID av = new UUID();
6682 if (!UUID.TryParse(avatar,out av)) 7167 if (!UUID.TryParse(avatar,out av))
6683 { 7168 {
6684 LSLError("First parameter to llDialog needs to be a key"); 7169 //LSLError("First parameter to llDialog needs to be a key");
6685 return; 7170 return;
6686 } 7171 }
6687 if (buttons.Length < 1) 7172 if (buttons.Length < 1)
6688 { 7173 {
6689 LSLError("No less than 1 button can be shown"); 7174 buttons.Add("OK");
6690 return;
6691 } 7175 }
6692 if (buttons.Length > 12) 7176 if (buttons.Length > 12)
6693 { 7177 {
@@ -6704,7 +7188,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6704 } 7188 }
6705 if (buttons.Data[i].ToString().Length > 24) 7189 if (buttons.Data[i].ToString().Length > 24)
6706 { 7190 {
6707 LSLError("button label cannot be longer than 24 characters"); 7191 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
6708 return; 7192 return;
6709 } 7193 }
6710 buts[i] = buttons.Data[i].ToString(); 7194 buts[i] = buttons.Data[i].ToString();
@@ -6771,9 +7255,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6771 return; 7255 return;
6772 } 7256 }
6773 7257
6774 // the rest of the permission checks are done in RezScript, so check the pin there as well 7258 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6775 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); 7259 if (dest != null)
7260 {
7261 if ((item.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7262 {
7263 // the rest of the permission checks are done in RezScript, so check the pin there as well
7264 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
6776 7265
7266 if ((item.BasePermissions & (uint)PermissionMask.Copy) == 0)
7267 m_host.Inventory.RemoveInventoryItem(item.ItemID);
7268 }
7269 }
6777 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7270 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6778 ScriptSleep(3000); 7271 ScriptSleep(3000);
6779 } 7272 }
@@ -6847,19 +7340,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6847 public LSL_String llMD5String(string src, int nonce) 7340 public LSL_String llMD5String(string src, int nonce)
6848 { 7341 {
6849 m_host.AddScriptLPS(1); 7342 m_host.AddScriptLPS(1);
6850 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7343 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6851 } 7344 }
6852 7345
6853 public LSL_String llSHA1String(string src) 7346 public LSL_String llSHA1String(string src)
6854 { 7347 {
6855 m_host.AddScriptLPS(1); 7348 m_host.AddScriptLPS(1);
6856 return Util.SHA1Hash(src).ToLower(); 7349 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6857 } 7350 }
6858 7351
6859 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7352 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6860 { 7353 {
6861 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7354 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6862 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7355 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7356 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7357 return shapeBlock;
6863 7358
6864 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7359 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6865 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7360 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6964,6 +7459,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6964 // Prim type box, cylinder and prism. 7459 // Prim type box, cylinder and prism.
6965 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) 7460 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)
6966 { 7461 {
7462 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7463 return;
7464
6967 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7465 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6968 ObjectShapePacket.ObjectDataBlock shapeBlock; 7466 ObjectShapePacket.ObjectDataBlock shapeBlock;
6969 7467
@@ -7017,6 +7515,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7017 // Prim type sphere. 7515 // Prim type sphere.
7018 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7516 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
7019 { 7517 {
7518 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7519 return;
7520
7020 ObjectShapePacket.ObjectDataBlock shapeBlock; 7521 ObjectShapePacket.ObjectDataBlock shapeBlock;
7021 7522
7022 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7523 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -7058,6 +7559,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7058 // Prim type torus, tube and ring. 7559 // Prim type torus, tube and ring.
7059 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) 7560 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)
7060 { 7561 {
7562 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7563 return;
7564
7061 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7565 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7062 ObjectShapePacket.ObjectDataBlock shapeBlock; 7566 ObjectShapePacket.ObjectDataBlock shapeBlock;
7063 7567
@@ -7193,6 +7697,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7193 // Prim type sculpt. 7697 // Prim type sculpt.
7194 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7698 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7195 { 7699 {
7700 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7701 return;
7702
7196 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7703 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7197 UUID sculptId; 7704 UUID sculptId;
7198 7705
@@ -7215,7 +7722,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7215 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7722 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7216 { 7723 {
7217 // default 7724 // default
7218 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7725 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7219 } 7726 }
7220 7727
7221 part.Shape.SetSculptProperties((byte)type, sculptId); 7728 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7232,48 +7739,130 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7232 ScriptSleep(200); 7739 ScriptSleep(200);
7233 } 7740 }
7234 7741
7235 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7742 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7236 { 7743 {
7237 m_host.AddScriptLPS(1); 7744 m_host.AddScriptLPS(1);
7238 7745
7239 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); 7746 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
7747 }
7240 7748
7241 ScriptSleep(200); 7749 private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
7750 {
7751 List<object> parts = new List<object>();
7752 List<SceneObjectPart> prims = GetLinkParts(linknumber);
7753 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7754 foreach (SceneObjectPart p in prims)
7755 parts.Add(p);
7756 foreach (ScenePresence p in avatars)
7757 parts.Add(p);
7758
7759 LSL_List remaining = null;
7760 uint rulesParsed = 0;
7761
7762 if (parts.Count > 0)
7763 {
7764 foreach (object part in parts)
7765 {
7766 if (part is SceneObjectPart)
7767 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7768 else
7769 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7770 }
7771
7772 while ((object)remaining != null && remaining.Length > 2)
7773 {
7774 linknumber = remaining.GetLSLIntegerItem(0);
7775 rules = remaining.GetSublist(1, -1);
7776 parts.Clear();
7777 prims = GetLinkParts(linknumber);
7778 avatars = GetLinkAvatars(linknumber);
7779 foreach (SceneObjectPart p in prims)
7780 parts.Add(p);
7781 foreach (ScenePresence p in avatars)
7782 parts.Add(p);
7783
7784 remaining = null;
7785 foreach (object part in parts)
7786 {
7787 if (part is SceneObjectPart)
7788 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7789 else
7790 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7791 }
7792 }
7793 }
7242 } 7794 }
7243 7795
7244 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7796 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7797 float material_density, float material_friction,
7798 float material_restitution, float material_gravity_modifier)
7245 { 7799 {
7246 m_host.AddScriptLPS(1); 7800 ExtraPhysicsData physdata = new ExtraPhysicsData();
7801 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7802 physdata.Density = part.Density;
7803 physdata.Friction = part.Friction;
7804 physdata.Bounce = part.Bounciness;
7805 physdata.GravitationModifier = part.GravityModifier;
7247 7806
7248 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); 7807 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7808 physdata.Density = material_density;
7809 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7810 physdata.Friction = material_friction;
7811 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7812 physdata.Bounce = material_restitution;
7813 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7814 physdata.GravitationModifier = material_gravity_modifier;
7815
7816 part.UpdateExtraPhysics(physdata);
7249 } 7817 }
7250 7818
7251 protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) 7819 public void llSetPhysicsMaterial(int material_bits,
7820 float material_gravity_modifier, float material_restitution,
7821 float material_friction, float material_density)
7252 { 7822 {
7253 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7823 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7824 }
7254 7825
7255 LSL_List remaining = null; 7826 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7256 uint rulesParsed = 0; 7827 {
7828 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
7829 llSetLinkPrimitiveParamsFast(linknumber, rules);
7830 ScriptSleep(200);
7831 }
7257 7832
7258 foreach (SceneObjectPart part in parts) 7833 // vector up using libomv (c&p from sop )
7259 remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); 7834 // vector up rotated by r
7835 private Vector3 Zrot(Quaternion r)
7836 {
7837 double x, y, z, m;
7260 7838
7261 while (remaining != null && remaining.Length > 2) 7839 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
7840 if (Math.Abs(1.0 - m) > 0.000001)
7262 { 7841 {
7263 linknumber = remaining.GetLSLIntegerItem(0); 7842 m = 1.0 / Math.Sqrt(m);
7264 rules = remaining.GetSublist(1, -1); 7843 r.X *= (float)m;
7265 parts = GetLinkParts(linknumber); 7844 r.Y *= (float)m;
7266 7845 r.Z *= (float)m;
7267 foreach (SceneObjectPart part in parts) 7846 r.W *= (float)m;
7268 remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed);
7269 } 7847 }
7848
7849 x = 2 * (r.X * r.Z + r.Y * r.W);
7850 y = 2 * (-r.X * r.W + r.Y * r.Z);
7851 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
7852
7853 return new Vector3((float)x, (float)y, (float)z);
7270 } 7854 }
7271 7855
7272 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) 7856 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
7273 { 7857 {
7858 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7859 return null;
7860
7274 int idx = 0; 7861 int idx = 0;
7275 int idxStart = 0; 7862 int idxStart = 0;
7276 7863
7864 SceneObjectGroup parentgrp = part.ParentGroup;
7865
7277 bool positionChanged = false; 7866 bool positionChanged = false;
7278 LSL_Vector currentPosition = GetPartLocalPos(part); 7867 LSL_Vector currentPosition = GetPartLocalPos(part);
7279 7868
@@ -7298,8 +7887,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7298 return null; 7887 return null;
7299 7888
7300 v=rules.GetVector3Item(idx++); 7889 v=rules.GetVector3Item(idx++);
7890 if (part.IsRoot && !part.ParentGroup.IsAttachment)
7891 currentPosition = GetSetPosTarget(part, v, currentPosition, true);
7892 else
7893 currentPosition = GetSetPosTarget(part, v, currentPosition, false);
7301 positionChanged = true; 7894 positionChanged = true;
7302 currentPosition = GetSetPosTarget(part, v, currentPosition);
7303 7895
7304 break; 7896 break;
7305 case (int)ScriptBaseClass.PRIM_SIZE: 7897 case (int)ScriptBaseClass.PRIM_SIZE:
@@ -7316,7 +7908,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7316 7908
7317 LSL_Rotation q = rules.GetQuaternionItem(idx++); 7909 LSL_Rotation q = rules.GetQuaternionItem(idx++);
7318 // try to let this work as in SL... 7910 // try to let this work as in SL...
7319 if (part.ParentID == 0) 7911 if (part.ParentID == 0 || (part.ParentGroup != null && part == part.ParentGroup.RootPart))
7320 { 7912 {
7321 // special case: If we are root, rotate complete SOG to new rotation 7913 // special case: If we are root, rotate complete SOG to new rotation
7322 SetRot(part, q); 7914 SetRot(part, q);
@@ -7576,7 +8168,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7576 return null; 8168 return null;
7577 8169
7578 string ph = rules.Data[idx++].ToString(); 8170 string ph = rules.Data[idx++].ToString();
7579 m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); 8171 parentgrp.ScriptSetPhantomStatus(ph.Equals("1"));
7580 8172
7581 break; 8173 break;
7582 8174
@@ -7594,12 +8186,42 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7594 part.ScriptSetPhysicsStatus(physics); 8186 part.ScriptSetPhysicsStatus(physics);
7595 break; 8187 break;
7596 8188
8189 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
8190 if (remain < 1)
8191 return null;
8192
8193 int shape_type = rules.GetLSLIntegerItem(idx++);
8194
8195 ExtraPhysicsData physdata = new ExtraPhysicsData();
8196 physdata.Density = part.Density;
8197 physdata.Bounce = part.Bounciness;
8198 physdata.GravitationModifier = part.GravityModifier;
8199 physdata.PhysShapeType = (PhysShapeType)shape_type;
8200
8201 part.UpdateExtraPhysics(physdata);
8202
8203 break;
8204
8205 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8206 if (remain < 5)
8207 return null;
8208
8209 int material_bits = rules.GetLSLIntegerItem(idx++);
8210 float material_density = (float)rules.GetLSLFloatItem(idx++);
8211 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8212 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8213 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8214
8215 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8216
8217 break;
8218
7597 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8219 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7598 if (remain < 1) 8220 if (remain < 1)
7599 return null; 8221 return null;
7600 string temp = rules.Data[idx++].ToString(); 8222 string temp = rules.Data[idx++].ToString();
7601 8223
7602 m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); 8224 parentgrp.ScriptSetTemporaryStatus(temp.Equals("1"));
7603 8225
7604 break; 8226 break;
7605 8227
@@ -7673,14 +8295,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7673 if (part.ParentGroup.RootPart == part) 8295 if (part.ParentGroup.RootPart == part)
7674 { 8296 {
7675 SceneObjectGroup parent = part.ParentGroup; 8297 SceneObjectGroup parent = part.ParentGroup;
7676 parent.UpdateGroupPosition(currentPosition); 8298 Util.FireAndForget(delegate(object x) {
8299 parent.UpdateGroupPosition(currentPosition);
8300 });
7677 } 8301 }
7678 else 8302 else
7679 { 8303 {
7680 part.OffsetPosition = currentPosition; 8304 part.OffsetPosition = currentPosition;
7681 SceneObjectGroup parent = part.ParentGroup; 8305// SceneObjectGroup parent = part.ParentGroup;
7682 parent.HasGroupChanged = true; 8306// parent.HasGroupChanged = true;
7683 parent.ScheduleGroupForTerseUpdate(); 8307// parent.ScheduleGroupForTerseUpdate();
8308 part.ScheduleTerseUpdate();
7684 } 8309 }
7685 } 8310 }
7686 } 8311 }
@@ -7718,10 +8343,91 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7718 8343
7719 public LSL_String llXorBase64Strings(string str1, string str2) 8344 public LSL_String llXorBase64Strings(string str1, string str2)
7720 { 8345 {
7721 m_host.AddScriptLPS(1); 8346 string b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7722 Deprecated("llXorBase64Strings"); 8347
7723 ScriptSleep(300); 8348 ScriptSleep(300);
7724 return String.Empty; 8349 m_host.AddScriptLPS(1);
8350
8351 if (str1 == String.Empty)
8352 return String.Empty;
8353 if (str2 == String.Empty)
8354 return str1;
8355
8356 int len = str2.Length;
8357 if ((len % 4) != 0) // LL is EVIL!!!!
8358 {
8359 while (str2.EndsWith("="))
8360 str2 = str2.Substring(0, str2.Length - 1);
8361
8362 len = str2.Length;
8363 int mod = len % 4;
8364
8365 if (mod == 1)
8366 str2 = str2.Substring(0, str2.Length - 1);
8367 else if (mod == 2)
8368 str2 += "==";
8369 else if (mod == 3)
8370 str2 += "=";
8371 }
8372
8373 byte[] data1;
8374 byte[] data2;
8375 try
8376 {
8377 data1 = Convert.FromBase64String(str1);
8378 data2 = Convert.FromBase64String(str2);
8379 }
8380 catch (Exception)
8381 {
8382 return new LSL_String(String.Empty);
8383 }
8384
8385 // For cases where the decoded length of s2 is greater
8386 // than the decoded length of s1, simply perform a normal
8387 // decode and XOR
8388 //
8389 if (data2.Length >= data1.Length)
8390 {
8391 for (int pos = 0 ; pos < data1.Length ; pos++ )
8392 data1[pos] ^= data2[pos];
8393
8394 return Convert.ToBase64String(data1);
8395 }
8396
8397 // Remove padding
8398 while (str1.EndsWith("="))
8399 str1 = str1.Substring(0, str1.Length - 1);
8400 while (str2.EndsWith("="))
8401 str2 = str2.Substring(0, str2.Length - 1);
8402
8403 byte[] d1 = new byte[str1.Length];
8404 byte[] d2 = new byte[str2.Length];
8405
8406 for (int i = 0 ; i < str1.Length ; i++)
8407 {
8408 int idx = b64.IndexOf(str1.Substring(i, 1));
8409 if (idx == -1)
8410 idx = 0;
8411 d1[i] = (byte)idx;
8412 }
8413
8414 for (int i = 0 ; i < str2.Length ; i++)
8415 {
8416 int idx = b64.IndexOf(str2.Substring(i, 1));
8417 if (idx == -1)
8418 idx = 0;
8419 d2[i] = (byte)idx;
8420 }
8421
8422 string output = String.Empty;
8423
8424 for (int pos = 0 ; pos < d1.Length ; pos++)
8425 output += b64[d1[pos] ^ d2[pos % d2.Length]];
8426
8427 while (output.Length % 3 > 0)
8428 output += "=";
8429
8430 return output;
7725 } 8431 }
7726 8432
7727 public void llRemoteDataSetRegion() 8433 public void llRemoteDataSetRegion()
@@ -7845,8 +8551,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7845 public LSL_Integer llGetNumberOfPrims() 8551 public LSL_Integer llGetNumberOfPrims()
7846 { 8552 {
7847 m_host.AddScriptLPS(1); 8553 m_host.AddScriptLPS(1);
7848 8554 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7849 return m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount(); 8555
8556 return m_host.ParentGroup.PrimCount + avatarCount;
7850 } 8557 }
7851 8558
7852 /// <summary> 8559 /// <summary>
@@ -7861,55 +8568,114 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7861 m_host.AddScriptLPS(1); 8568 m_host.AddScriptLPS(1);
7862 UUID objID = UUID.Zero; 8569 UUID objID = UUID.Zero;
7863 LSL_List result = new LSL_List(); 8570 LSL_List result = new LSL_List();
8571
8572 // If the ID is not valid, return null result
7864 if (!UUID.TryParse(obj, out objID)) 8573 if (!UUID.TryParse(obj, out objID))
7865 { 8574 {
7866 result.Add(new LSL_Vector()); 8575 result.Add(new LSL_Vector());
7867 result.Add(new LSL_Vector()); 8576 result.Add(new LSL_Vector());
7868 return result; 8577 return result;
7869 } 8578 }
8579
8580 // Check if this is an attached prim. If so, replace
8581 // the UUID with the avatar UUID and report it's bounding box
8582 SceneObjectPart part = World.GetSceneObjectPart(objID);
8583 if (part != null && part.ParentGroup.IsAttachment)
8584 objID = part.ParentGroup.AttachedAvatar;
8585
8586 // Find out if this is an avatar ID. If so, return it's box
7870 ScenePresence presence = World.GetScenePresence(objID); 8587 ScenePresence presence = World.GetScenePresence(objID);
7871 if (presence != null) 8588 if (presence != null)
7872 { 8589 {
7873 if (presence.ParentID == 0) // not sat on an object 8590 // As per LSL Wiki, there is no difference between sitting
8591 // and standing avatar since server 1.36
8592 LSL_Vector lower;
8593 LSL_Vector upper;
8594
8595 Vector3 box = presence.Appearance.AvatarBoxSize * 0.5f;
8596
8597 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID
8598 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
8599/*
7874 { 8600 {
7875 LSL_Vector lower; 8601 // This is for ground sitting avatars
7876 LSL_Vector upper; 8602 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7877 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID 8603 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7878 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8604 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7879 { 8605 }
7880 // This is for ground sitting avatars 8606 else
7881 float height = presence.Appearance.AvatarHeight / 2.66666667f; 8607 {
7882 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f); 8608 // This is for standing/flying avatars
7883 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f); 8609 float height = presence.Appearance.AvatarHeight / 2.0f;
7884 } 8610 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7885 else 8611 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7886 { 8612 }
7887 // This is for standing/flying avatars 8613
7888 float height = presence.Appearance.AvatarHeight / 2.0f; 8614 // Adjust to the documented error offsets (see LSL Wiki)
7889 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f); 8615 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
7890 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f); 8616 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
7891 } 8617*/
7892 result.Add(lower); 8618 {
7893 result.Add(upper); 8619 // This is for ground sitting avatars TODO!
7894 return result; 8620 lower = new LSL_Vector(-box.X - 0.1125, -box.Y, box.Z * -1.0f);
8621 upper = new LSL_Vector(box.X + 0.1125, box.Y, box.Z * -1.0f);
7895 } 8622 }
7896 else 8623 else
7897 { 8624 {
7898 // sitting on an object so we need the bounding box of that 8625 // This is for standing/flying avatars
7899 // which should include the avatar so set the UUID to the 8626 lower = new LSL_Vector(-box.X, -box.Y, -box.Z);
7900 // UUID of the object the avatar is sat on and allow it to fall through 8627 upper = new LSL_Vector(box.X, box.Y, box.Z);
7901 // to processing an object
7902 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7903 objID = p.UUID;
7904 } 8628 }
8629
8630 if (lower.x > upper.x)
8631 lower.x = upper.x;
8632 if (lower.y > upper.y)
8633 lower.y = upper.y;
8634 if (lower.z > upper.z)
8635 lower.z = upper.z;
8636
8637 result.Add(lower);
8638 result.Add(upper);
8639 return result;
7905 } 8640 }
7906 SceneObjectPart part = World.GetSceneObjectPart(objID); 8641
8642 part = World.GetSceneObjectPart(objID);
7907 // Currently only works for single prims without a sitting avatar 8643 // Currently only works for single prims without a sitting avatar
7908 if (part != null) 8644 if (part != null)
7909 { 8645 {
7910 Vector3 halfSize = part.Scale / 2.0f; 8646 float minX;
7911 LSL_Vector lower = (new LSL_Vector(halfSize)) * -1.0f; 8647 float maxX;
7912 LSL_Vector upper = new LSL_Vector(halfSize); 8648 float minY;
8649 float maxY;
8650 float minZ;
8651 float maxZ;
8652
8653 // This BBox is in sim coordinates, with the offset being
8654 // a contained point.
8655 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8656 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8657
8658 minX -= offsets[0].X;
8659 maxX -= offsets[0].X;
8660 minY -= offsets[0].Y;
8661 maxY -= offsets[0].Y;
8662 minZ -= offsets[0].Z;
8663 maxZ -= offsets[0].Z;
8664
8665 LSL_Vector lower;
8666 LSL_Vector upper;
8667
8668 // Adjust to the documented error offsets (see LSL Wiki)
8669 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8670 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8671
8672 if (lower.x > upper.x)
8673 lower.x = upper.x;
8674 if (lower.y > upper.y)
8675 lower.y = upper.y;
8676 if (lower.z > upper.z)
8677 lower.z = upper.z;
8678
7913 result.Add(lower); 8679 result.Add(lower);
7914 result.Add(upper); 8680 result.Add(upper);
7915 return result; 8681 return result;
@@ -7923,7 +8689,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7923 8689
7924 public LSL_Vector llGetGeometricCenter() 8690 public LSL_Vector llGetGeometricCenter()
7925 { 8691 {
7926 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 8692 Vector3 tmp = m_host.GetGeometricCenter();
8693 return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
7927 } 8694 }
7928 8695
7929 public LSL_List llGetPrimitiveParams(LSL_List rules) 8696 public LSL_List llGetPrimitiveParams(LSL_List rules)
@@ -7934,7 +8701,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7934 8701
7935 LSL_List remaining = GetPrimParams(m_host, rules, ref result); 8702 LSL_List remaining = GetPrimParams(m_host, rules, ref result);
7936 8703
7937 while (remaining != null && remaining.Length > 2) 8704 while ((object)remaining != null && remaining.Length > 2)
7938 { 8705 {
7939 int linknumber = remaining.GetLSLIntegerItem(0); 8706 int linknumber = remaining.GetLSLIntegerItem(0);
7940 rules = remaining.GetSublist(1, -1); 8707 rules = remaining.GetSublist(1, -1);
@@ -7951,24 +8718,37 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7951 { 8718 {
7952 m_host.AddScriptLPS(1); 8719 m_host.AddScriptLPS(1);
7953 8720
7954 List<SceneObjectPart> parts = GetLinkParts(linknumber); 8721 // acording to SL wiki this must indicate a single link number or link_root or link_this.
8722 // keep other options as before
7955 8723
8724 List<SceneObjectPart> parts;
8725 List<ScenePresence> avatars;
8726
7956 LSL_List res = new LSL_List(); 8727 LSL_List res = new LSL_List();
7957 LSL_List remaining = null; 8728 LSL_List remaining = null;
7958 8729
7959 foreach (SceneObjectPart part in parts) 8730 while (rules.Length > 0)
7960 {
7961 remaining = GetPrimParams(part, rules, ref res);
7962 }
7963
7964 while (remaining != null && remaining.Length > 2)
7965 { 8731 {
7966 linknumber = remaining.GetLSLIntegerItem(0);
7967 rules = remaining.GetSublist(1, -1);
7968 parts = GetLinkParts(linknumber); 8732 parts = GetLinkParts(linknumber);
8733 avatars = GetLinkAvatars(linknumber);
7969 8734
8735 remaining = null;
7970 foreach (SceneObjectPart part in parts) 8736 foreach (SceneObjectPart part in parts)
8737 {
7971 remaining = GetPrimParams(part, rules, ref res); 8738 remaining = GetPrimParams(part, rules, ref res);
8739 }
8740 foreach (ScenePresence avatar in avatars)
8741 {
8742 remaining = GetPrimParams(avatar, rules, ref res);
8743 }
8744
8745 if ((object)remaining != null && remaining.Length > 0)
8746 {
8747 linknumber = remaining.GetLSLIntegerItem(0);
8748 rules = remaining.GetSublist(1, -1);
8749 }
8750 else
8751 break;
7972 } 8752 }
7973 8753
7974 return res; 8754 return res;
@@ -8013,13 +8793,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8013 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8793 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
8014 part.AbsolutePosition.Y, 8794 part.AbsolutePosition.Y,
8015 part.AbsolutePosition.Z); 8795 part.AbsolutePosition.Z);
8016 // For some reason, the part.AbsolutePosition.* values do not change if the
8017 // linkset is rotated; they always reflect the child prim's world position
8018 // as though the linkset is unrotated. This is incompatible behavior with SL's
8019 // implementation, so will break scripts imported from there (not to mention it
8020 // makes it more difficult to determine a child prim's actual inworld position).
8021 if (part.ParentID != 0)
8022 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
8023 res.Add(v); 8796 res.Add(v);
8024 break; 8797 break;
8025 8798
@@ -8191,30 +8964,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8191 if (remain < 1) 8964 if (remain < 1)
8192 return null; 8965 return null;
8193 8966
8194 face=(int)rules.GetLSLIntegerItem(idx++); 8967 face = (int)rules.GetLSLIntegerItem(idx++);
8195 8968
8196 tex = part.Shape.Textures; 8969 tex = part.Shape.Textures;
8970 int shiny;
8197 if (face == ScriptBaseClass.ALL_SIDES) 8971 if (face == ScriptBaseClass.ALL_SIDES)
8198 { 8972 {
8199 for (face = 0; face < GetNumberOfSides(part); face++) 8973 for (face = 0; face < GetNumberOfSides(part); face++)
8200 { 8974 {
8201 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8975 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8202 // Convert Shininess to PRIM_SHINY_* 8976 if (shinyness == Shininess.High)
8203 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8977 {
8204 // PRIM_BUMP_* 8978 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8205 res.Add(new LSL_Integer((int)texface.Bump)); 8979 }
8980 else if (shinyness == Shininess.Medium)
8981 {
8982 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8983 }
8984 else if (shinyness == Shininess.Low)
8985 {
8986 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8987 }
8988 else
8989 {
8990 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8991 }
8992 res.Add(new LSL_Integer(shiny));
8993 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8206 } 8994 }
8207 } 8995 }
8208 else 8996 else
8209 { 8997 {
8210 if (face >= 0 && face < GetNumberOfSides(part)) 8998 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8999 if (shinyness == Shininess.High)
8211 { 9000 {
8212 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9001 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8213 // Convert Shininess to PRIM_SHINY_* 9002 }
8214 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 9003 else if (shinyness == Shininess.Medium)
8215 // PRIM_BUMP_* 9004 {
8216 res.Add(new LSL_Integer((int)texface.Bump)); 9005 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
9006 }
9007 else if (shinyness == Shininess.Low)
9008 {
9009 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8217 } 9010 }
9011 else
9012 {
9013 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
9014 }
9015 res.Add(new LSL_Integer(shiny));
9016 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8218 } 9017 }
8219 break; 9018 break;
8220 9019
@@ -8222,24 +9021,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8222 if (remain < 1) 9021 if (remain < 1)
8223 return null; 9022 return null;
8224 9023
8225 face=(int)rules.GetLSLIntegerItem(idx++); 9024 face = (int)rules.GetLSLIntegerItem(idx++);
8226 9025
8227 tex = part.Shape.Textures; 9026 tex = part.Shape.Textures;
9027 int fullbright;
8228 if (face == ScriptBaseClass.ALL_SIDES) 9028 if (face == ScriptBaseClass.ALL_SIDES)
8229 { 9029 {
8230 for (face = 0; face < GetNumberOfSides(part); face++) 9030 for (face = 0; face < GetNumberOfSides(part); face++)
8231 { 9031 {
8232 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9032 if (tex.GetFace((uint)face).Fullbright == true)
8233 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 9033 {
9034 fullbright = ScriptBaseClass.TRUE;
9035 }
9036 else
9037 {
9038 fullbright = ScriptBaseClass.FALSE;
9039 }
9040 res.Add(new LSL_Integer(fullbright));
8234 } 9041 }
8235 } 9042 }
8236 else 9043 else
8237 { 9044 {
8238 if (face >= 0 && face < GetNumberOfSides(part)) 9045 if (tex.GetFace((uint)face).Fullbright == true)
8239 { 9046 {
8240 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9047 fullbright = ScriptBaseClass.TRUE;
8241 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 9048 }
9049 else
9050 {
9051 fullbright = ScriptBaseClass.FALSE;
8242 } 9052 }
9053 res.Add(new LSL_Integer(fullbright));
8243 } 9054 }
8244 break; 9055 break;
8245 9056
@@ -8261,27 +9072,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8261 break; 9072 break;
8262 9073
8263 case (int)ScriptBaseClass.PRIM_TEXGEN: 9074 case (int)ScriptBaseClass.PRIM_TEXGEN:
9075 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8264 if (remain < 1) 9076 if (remain < 1)
8265 return null; 9077 return null;
8266 9078
8267 face=(int)rules.GetLSLIntegerItem(idx++); 9079 face = (int)rules.GetLSLIntegerItem(idx++);
8268 9080
8269 tex = part.Shape.Textures; 9081 tex = part.Shape.Textures;
8270 if (face == ScriptBaseClass.ALL_SIDES) 9082 if (face == ScriptBaseClass.ALL_SIDES)
8271 { 9083 {
8272 for (face = 0; face < GetNumberOfSides(part); face++) 9084 for (face = 0; face < GetNumberOfSides(part); face++)
8273 { 9085 {
8274 MappingType texgen = tex.GetFace((uint)face).TexMapType; 9086 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8275 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 9087 {
8276 res.Add(new LSL_Integer((uint)texgen >> 1)); 9088 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
9089 }
9090 else
9091 {
9092 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
9093 }
8277 } 9094 }
8278 } 9095 }
8279 else 9096 else
8280 { 9097 {
8281 if (face >= 0 && face < GetNumberOfSides(part)) 9098 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8282 { 9099 {
8283 MappingType texgen = tex.GetFace((uint)face).TexMapType; 9100 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8284 res.Add(new LSL_Integer((uint)texgen >> 1)); 9101 }
9102 else
9103 {
9104 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8285 } 9105 }
8286 } 9106 }
8287 break; 9107 break;
@@ -8305,24 +9125,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8305 if (remain < 1) 9125 if (remain < 1)
8306 return null; 9126 return null;
8307 9127
8308 face=(int)rules.GetLSLIntegerItem(idx++); 9128 face = (int)rules.GetLSLIntegerItem(idx++);
8309 9129
8310 tex = part.Shape.Textures; 9130 tex = part.Shape.Textures;
9131 float primglow;
8311 if (face == ScriptBaseClass.ALL_SIDES) 9132 if (face == ScriptBaseClass.ALL_SIDES)
8312 { 9133 {
8313 for (face = 0; face < GetNumberOfSides(part); face++) 9134 for (face = 0; face < GetNumberOfSides(part); face++)
8314 { 9135 {
8315 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9136 primglow = tex.GetFace((uint)face).Glow;
8316 res.Add(new LSL_Float(texface.Glow)); 9137 res.Add(new LSL_Float(primglow));
8317 } 9138 }
8318 } 9139 }
8319 else 9140 else
8320 { 9141 {
8321 if (face >= 0 && face < GetNumberOfSides(part)) 9142 primglow = tex.GetFace((uint)face).Glow;
8322 { 9143 res.Add(new LSL_Float(primglow));
8323 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8324 res.Add(new LSL_Float(texface.Glow));
8325 }
8326 } 9144 }
8327 break; 9145 break;
8328 9146
@@ -8334,15 +9152,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8334 textColor.B)); 9152 textColor.B));
8335 res.Add(new LSL_Float(textColor.A)); 9153 res.Add(new LSL_Float(textColor.A));
8336 break; 9154 break;
9155
8337 case (int)ScriptBaseClass.PRIM_NAME: 9156 case (int)ScriptBaseClass.PRIM_NAME:
8338 res.Add(new LSL_String(part.Name)); 9157 res.Add(new LSL_String(part.Name));
8339 break; 9158 break;
9159
8340 case (int)ScriptBaseClass.PRIM_DESC: 9160 case (int)ScriptBaseClass.PRIM_DESC:
8341 res.Add(new LSL_String(part.Description)); 9161 res.Add(new LSL_String(part.Description));
8342 break; 9162 break;
9163
8343 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 9164 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8344 res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); 9165 res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W));
8345 break; 9166 break;
9167
8346 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 9168 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
8347 res.Add(new LSL_Vector(GetPartLocalPos(part))); 9169 res.Add(new LSL_Vector(GetPartLocalPos(part)));
8348 break; 9170 break;
@@ -8953,8 +9775,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8953 // The function returns an ordered list 9775 // The function returns an ordered list
8954 // representing the tokens found in the supplied 9776 // representing the tokens found in the supplied
8955 // sources string. If two successive tokenizers 9777 // sources string. If two successive tokenizers
8956 // are encountered, then a NULL entry is added 9778 // are encountered, then a null-string entry is
8957 // to the list. 9779 // added to the list.
8958 // 9780 //
8959 // It is a precondition that the source and 9781 // It is a precondition that the source and
8960 // toekizer lisst are non-null. If they are null, 9782 // toekizer lisst are non-null. If they are null,
@@ -8962,7 +9784,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8962 // while their lengths are being determined. 9784 // while their lengths are being determined.
8963 // 9785 //
8964 // A small amount of working memoryis required 9786 // A small amount of working memoryis required
8965 // of approximately 8*#tokenizers. 9787 // of approximately 8*#tokenizers + 8*srcstrlen.
8966 // 9788 //
8967 // There are many ways in which this function 9789 // There are many ways in which this function
8968 // can be implemented, this implementation is 9790 // can be implemented, this implementation is
@@ -8978,155 +9800,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8978 // and eliminates redundant tokenizers as soon 9800 // and eliminates redundant tokenizers as soon
8979 // as is possible. 9801 // as is possible.
8980 // 9802 //
8981 // The implementation tries to avoid any copying 9803 // The implementation tries to minimize temporary
8982 // of arrays or other objects. 9804 // garbage generation.
8983 // </remarks> 9805 // </remarks>
8984 9806
8985 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9807 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
8986 { 9808 {
8987 int beginning = 0; 9809 return ParseString2List(src, separators, spacers, true);
8988 int srclen = src.Length; 9810 }
8989 int seplen = separators.Length;
8990 object[] separray = separators.Data;
8991 int spclen = spacers.Length;
8992 object[] spcarray = spacers.Data;
8993 int mlen = seplen+spclen;
8994
8995 int[] offset = new int[mlen+1];
8996 bool[] active = new bool[mlen];
8997
8998 int best;
8999 int j;
9000
9001 // Initial capacity reduces resize cost
9002 9811
9003 LSL_List tokens = new LSL_List(); 9812 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9813 {
9814 int srclen = src.Length;
9815 int seplen = separators.Length;
9816 object[] separray = separators.Data;
9817 int spclen = spacers.Length;
9818 object[] spcarray = spacers.Data;
9819 int dellen = 0;
9820 string[] delarray = new string[seplen+spclen];
9004 9821
9005 // All entries are initially valid 9822 int outlen = 0;
9823 string[] outarray = new string[srclen*2+1];
9006 9824
9007 for (int i = 0; i < mlen; i++) 9825 int i, j;
9008 active[i] = true; 9826 string d;
9009 9827
9010 offset[mlen] = srclen; 9828 m_host.AddScriptLPS(1);
9011 9829
9012 while (beginning < srclen) 9830 /*
9831 * Convert separator and spacer lists to C# strings.
9832 * Also filter out null strings so we don't hang.
9833 */
9834 for (i = 0; i < seplen; i ++)
9013 { 9835 {
9836 d = separray[i].ToString();
9837 if (d.Length > 0)
9838 {
9839 delarray[dellen++] = d;
9840 }
9841 }
9842 seplen = dellen;
9014 9843
9015 best = mlen; // as bad as it gets 9844 for (i = 0; i < spclen; i ++)
9845 {
9846 d = spcarray[i].ToString();
9847 if (d.Length > 0)
9848 {
9849 delarray[dellen++] = d;
9850 }
9851 }
9016 9852
9017 // Scan for separators 9853 /*
9854 * Scan through source string from beginning to end.
9855 */
9856 for (i = 0;;)
9857 {
9018 9858
9019 for (j = 0; j < seplen; j++) 9859 /*
9860 * Find earliest delimeter in src starting at i (if any).
9861 */
9862 int earliestDel = -1;
9863 int earliestSrc = srclen;
9864 string earliestStr = null;
9865 for (j = 0; j < dellen; j ++)
9020 { 9866 {
9021 if (separray[j].ToString() == String.Empty) 9867 d = delarray[j];
9022 active[j] = false; 9868 if (d != null)
9023
9024 if (active[j])
9025 { 9869 {
9026 // scan all of the markers 9870 int index = src.IndexOf(d, i);
9027 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9871 if (index < 0)
9028 { 9872 {
9029 // not present at all 9873 delarray[j] = null; // delim nowhere in src, don't check it anymore
9030 active[j] = false;
9031 } 9874 }
9032 else 9875 else if (index < earliestSrc)
9033 { 9876 {
9034 // present and correct 9877 earliestSrc = index; // where delimeter starts in source string
9035 if (offset[j] < offset[best]) 9878 earliestDel = j; // where delimeter is in delarray[]
9036 { 9879 earliestStr = d; // the delimeter string from delarray[]
9037 // closest so far 9880 if (index == i) break; // can't do any better than found at beg of string
9038 best = j;
9039 if (offset[best] == beginning)
9040 break;
9041 }
9042 } 9881 }
9043 } 9882 }
9044 } 9883 }
9045 9884
9046 // Scan for spacers 9885 /*
9047 9886 * Output source string starting at i through start of earliest delimeter.
9048 if (offset[best] != beginning) 9887 */
9888 if (keepNulls || (earliestSrc > i))
9049 { 9889 {
9050 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9890 outarray[outlen++] = src.Substring(i, earliestSrc - i);
9051 {
9052 if (spcarray[j-seplen].ToString() == String.Empty)
9053 active[j] = false;
9054
9055 if (active[j])
9056 {
9057 // scan all of the markers
9058 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
9059 {
9060 // not present at all
9061 active[j] = false;
9062 }
9063 else
9064 {
9065 // present and correct
9066 if (offset[j] < offset[best])
9067 {
9068 // closest so far
9069 best = j;
9070 }
9071 }
9072 }
9073 }
9074 } 9891 }
9075 9892
9076 // This is the normal exit from the scanning loop 9893 /*
9894 * If no delimeter found at or after i, we're done scanning.
9895 */
9896 if (earliestDel < 0) break;
9077 9897
9078 if (best == mlen) 9898 /*
9899 * If delimeter was a spacer, output the spacer.
9900 */
9901 if (earliestDel >= seplen)
9079 { 9902 {
9080 // no markers were found on this pass 9903 outarray[outlen++] = earliestStr;
9081 // so we're pretty much done
9082 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
9083 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
9084 break;
9085 } 9904 }
9086 9905
9087 // Otherwise we just add the newly delimited token 9906 /*
9088 // and recalculate where the search should continue. 9907 * Look at rest of src string following delimeter.
9089 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9908 */
9090 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9909 i = earliestSrc + earliestStr.Length;
9091
9092 if (best < seplen)
9093 {
9094 beginning = offset[best] + (separray[best].ToString()).Length;
9095 }
9096 else
9097 {
9098 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
9099 string str = spcarray[best - seplen].ToString();
9100 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
9101 tokens.Add(new LSL_String(str));
9102 }
9103 } 9910 }
9104 9911
9105 // This an awkward an not very intuitive boundary case. If the 9912 /*
9106 // last substring is a tokenizer, then there is an implied trailing 9913 * Make up an exact-sized output array suitable for an LSL_List object.
9107 // null list entry. Hopefully the single comparison will not be too 9914 */
9108 // arduous. Alternatively the 'break' could be replced with a return 9915 object[] outlist = new object[outlen];
9109 // but that's shabby programming. 9916 for (i = 0; i < outlen; i ++)
9110
9111 if ((beginning == srclen) && (keepNulls))
9112 { 9917 {
9113 if (srclen != 0) 9918 outlist[i] = new LSL_String(outarray[i]);
9114 tokens.Add(new LSL_String(""));
9115 } 9919 }
9116 9920 return new LSL_List(outlist);
9117 return tokens;
9118 }
9119
9120 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
9121 {
9122 m_host.AddScriptLPS(1);
9123 return this.ParseString(src, separators, spacers, false);
9124 }
9125
9126 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
9127 {
9128 m_host.AddScriptLPS(1);
9129 return this.ParseString(src, separators, spacers, true);
9130 } 9921 }
9131 9922
9132 public LSL_Integer llGetObjectPermMask(int mask) 9923 public LSL_Integer llGetObjectPermMask(int mask)
@@ -9221,6 +10012,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9221 case 4: 10012 case 4:
9222 return (int)item.NextPermissions; 10013 return (int)item.NextPermissions;
9223 } 10014 }
10015 m_host.TaskInventory.LockItemsForRead(false);
9224 10016
9225 return -1; 10017 return -1;
9226 } 10018 }
@@ -9423,31 +10215,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9423 UUID key = new UUID(); 10215 UUID key = new UUID();
9424 if (UUID.TryParse(id, out key)) 10216 if (UUID.TryParse(id, out key))
9425 { 10217 {
9426 try 10218 // return total object mass
9427 { 10219 SceneObjectPart part = World.GetSceneObjectPart(key);
9428 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 10220 if (part != null)
9429 if (obj != null) 10221 return part.ParentGroup.GetMass();
9430 return (double)obj.GetMass(); 10222
9431 // the object is null so the key is for an avatar 10223 // the object is null so the key is for an avatar
9432 ScenePresence avatar = World.GetScenePresence(key); 10224 ScenePresence avatar = World.GetScenePresence(key);
9433 if (avatar != null) 10225 if (avatar != null)
9434 if (avatar.IsChildAgent)
9435 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
9436 // child agents have a mass of 1.0
9437 return 1;
9438 else
9439 return (double)avatar.GetMass();
9440 }
9441 catch (KeyNotFoundException)
9442 { 10226 {
9443 return 0; // The Object/Agent not in the region so just return zero 10227 if (avatar.IsChildAgent)
10228 {
10229 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
10230 // child agents have a mass of 1.0
10231 return 1;
10232 }
10233 else
10234 {
10235 return (double)avatar.GetMass();
10236 }
9444 } 10237 }
9445 } 10238 }
9446 return 0; 10239 return 0;
9447 } 10240 }
9448 10241
9449 /// <summary> 10242 /// <summary>
9450 /// illListReplaceList removes the sub-list defined by the inclusive indices 10243 /// llListReplaceList removes the sub-list defined by the inclusive indices
9451 /// start and end and inserts the src list in its place. The inclusive 10244 /// start and end and inserts the src list in its place. The inclusive
9452 /// nature of the indices means that at least one element must be deleted 10245 /// nature of the indices means that at least one element must be deleted
9453 /// if the indices are within the bounds of the existing list. I.e. 2,2 10246 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9504,16 +10297,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9504 // based upon end. Note that if end exceeds the upper 10297 // based upon end. Note that if end exceeds the upper
9505 // bound in this case, the entire destination list 10298 // bound in this case, the entire destination list
9506 // is removed. 10299 // is removed.
9507 else 10300 else if (start == 0)
9508 { 10301 {
9509 if (end + 1 < dest.Length) 10302 if (end + 1 < dest.Length)
9510 {
9511 return src + dest.GetSublist(end + 1, -1); 10303 return src + dest.GetSublist(end + 1, -1);
9512 }
9513 else 10304 else
9514 {
9515 return src; 10305 return src;
9516 } 10306 }
10307 else // Start < 0
10308 {
10309 if (end + 1 < dest.Length)
10310 return dest.GetSublist(end + 1, -1);
10311 else
10312 return new LSL_List();
9517 } 10313 }
9518 } 10314 }
9519 // Finally, if start > end, we strip away a prefix and 10315 // Finally, if start > end, we strip away a prefix and
@@ -9564,17 +10360,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9564 int width = 0; 10360 int width = 0;
9565 int height = 0; 10361 int height = 0;
9566 10362
9567 ParcelMediaCommandEnum? commandToSend = null; 10363 uint commandToSend = 0;
9568 float time = 0.0f; // default is from start 10364 float time = 0.0f; // default is from start
9569 10365
9570 ScenePresence presence = null; 10366 ScenePresence presence = null;
9571 10367
9572 for (int i = 0; i < commandList.Data.Length; i++) 10368 for (int i = 0; i < commandList.Data.Length; i++)
9573 { 10369 {
9574 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10370 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9575 switch (command) 10371 switch (command)
9576 { 10372 {
9577 case ParcelMediaCommandEnum.Agent: 10373 case (uint)ParcelMediaCommandEnum.Agent:
9578 // we send only to one agent 10374 // we send only to one agent
9579 if ((i + 1) < commandList.Length) 10375 if ((i + 1) < commandList.Length)
9580 { 10376 {
@@ -9591,25 +10387,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9591 } 10387 }
9592 break; 10388 break;
9593 10389
9594 case ParcelMediaCommandEnum.Loop: 10390 case (uint)ParcelMediaCommandEnum.Loop:
9595 loop = 1; 10391 loop = 1;
9596 commandToSend = command; 10392 commandToSend = command;
9597 update = true; //need to send the media update packet to set looping 10393 update = true; //need to send the media update packet to set looping
9598 break; 10394 break;
9599 10395
9600 case ParcelMediaCommandEnum.Play: 10396 case (uint)ParcelMediaCommandEnum.Play:
9601 loop = 0; 10397 loop = 0;
9602 commandToSend = command; 10398 commandToSend = command;
9603 update = true; //need to send the media update packet to make sure it doesn't loop 10399 update = true; //need to send the media update packet to make sure it doesn't loop
9604 break; 10400 break;
9605 10401
9606 case ParcelMediaCommandEnum.Pause: 10402 case (uint)ParcelMediaCommandEnum.Pause:
9607 case ParcelMediaCommandEnum.Stop: 10403 case (uint)ParcelMediaCommandEnum.Stop:
9608 case ParcelMediaCommandEnum.Unload: 10404 case (uint)ParcelMediaCommandEnum.Unload:
9609 commandToSend = command; 10405 commandToSend = command;
9610 break; 10406 break;
9611 10407
9612 case ParcelMediaCommandEnum.Url: 10408 case (uint)ParcelMediaCommandEnum.Url:
9613 if ((i + 1) < commandList.Length) 10409 if ((i + 1) < commandList.Length)
9614 { 10410 {
9615 if (commandList.Data[i + 1] is LSL_String) 10411 if (commandList.Data[i + 1] is LSL_String)
@@ -9622,7 +10418,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9622 } 10418 }
9623 break; 10419 break;
9624 10420
9625 case ParcelMediaCommandEnum.Texture: 10421 case (uint)ParcelMediaCommandEnum.Texture:
9626 if ((i + 1) < commandList.Length) 10422 if ((i + 1) < commandList.Length)
9627 { 10423 {
9628 if (commandList.Data[i + 1] is LSL_String) 10424 if (commandList.Data[i + 1] is LSL_String)
@@ -9635,7 +10431,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9635 } 10431 }
9636 break; 10432 break;
9637 10433
9638 case ParcelMediaCommandEnum.Time: 10434 case (uint)ParcelMediaCommandEnum.Time:
9639 if ((i + 1) < commandList.Length) 10435 if ((i + 1) < commandList.Length)
9640 { 10436 {
9641 if (commandList.Data[i + 1] is LSL_Float) 10437 if (commandList.Data[i + 1] is LSL_Float)
@@ -9647,7 +10443,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9647 } 10443 }
9648 break; 10444 break;
9649 10445
9650 case ParcelMediaCommandEnum.AutoAlign: 10446 case (uint)ParcelMediaCommandEnum.AutoAlign:
9651 if ((i + 1) < commandList.Length) 10447 if ((i + 1) < commandList.Length)
9652 { 10448 {
9653 if (commandList.Data[i + 1] is LSL_Integer) 10449 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9661,7 +10457,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9661 } 10457 }
9662 break; 10458 break;
9663 10459
9664 case ParcelMediaCommandEnum.Type: 10460 case (uint)ParcelMediaCommandEnum.Type:
9665 if ((i + 1) < commandList.Length) 10461 if ((i + 1) < commandList.Length)
9666 { 10462 {
9667 if (commandList.Data[i + 1] is LSL_String) 10463 if (commandList.Data[i + 1] is LSL_String)
@@ -9674,7 +10470,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9674 } 10470 }
9675 break; 10471 break;
9676 10472
9677 case ParcelMediaCommandEnum.Desc: 10473 case (uint)ParcelMediaCommandEnum.Desc:
9678 if ((i + 1) < commandList.Length) 10474 if ((i + 1) < commandList.Length)
9679 { 10475 {
9680 if (commandList.Data[i + 1] is LSL_String) 10476 if (commandList.Data[i + 1] is LSL_String)
@@ -9687,7 +10483,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9687 } 10483 }
9688 break; 10484 break;
9689 10485
9690 case ParcelMediaCommandEnum.Size: 10486 case (uint)ParcelMediaCommandEnum.Size:
9691 if ((i + 2) < commandList.Length) 10487 if ((i + 2) < commandList.Length)
9692 { 10488 {
9693 if (commandList.Data[i + 1] is LSL_Integer) 10489 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9757,7 +10553,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9757 } 10553 }
9758 } 10554 }
9759 10555
9760 if (commandToSend != null) 10556 if (commandToSend != 0)
9761 { 10557 {
9762 // the commandList contained a start/stop/... command, too 10558 // the commandList contained a start/stop/... command, too
9763 if (presence == null) 10559 if (presence == null)
@@ -9794,7 +10590,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9794 10590
9795 if (aList.Data[i] != null) 10591 if (aList.Data[i] != null)
9796 { 10592 {
9797 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10593 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9798 { 10594 {
9799 case ParcelMediaCommandEnum.Url: 10595 case ParcelMediaCommandEnum.Url:
9800 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); 10596 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL));
@@ -9851,15 +10647,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9851 10647
9852 if (quick_pay_buttons.Data.Length < 4) 10648 if (quick_pay_buttons.Data.Length < 4)
9853 { 10649 {
9854 LSLError("List must have at least 4 elements"); 10650 int x;
9855 return; 10651 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10652 {
10653 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10654 }
9856 } 10655 }
9857 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10656 int[] nPrice = new int[5];
9858 10657 nPrice[0] = price;
9859 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10658 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9860 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10659 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9861 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10660 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9862 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10661 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10662 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9863 m_host.ParentGroup.HasGroupChanged = true; 10663 m_host.ParentGroup.HasGroupChanged = true;
9864 } 10664 }
9865 10665
@@ -9876,7 +10676,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9876 return new LSL_Vector(); 10676 return new LSL_Vector();
9877 } 10677 }
9878 10678
9879 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10679// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10680 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9880 if (presence != null) 10681 if (presence != null)
9881 { 10682 {
9882 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); 10683 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
@@ -9898,7 +10699,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9898 return new LSL_Rotation(); 10699 return new LSL_Rotation();
9899 } 10700 }
9900 10701
9901 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10702// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10703 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9902 if (presence != null) 10704 if (presence != null)
9903 { 10705 {
9904 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); 10706 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W);
@@ -9958,14 +10760,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9958 { 10760 {
9959 m_host.AddScriptLPS(1); 10761 m_host.AddScriptLPS(1);
9960 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 10762 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
9961 if (detectedParams == null) return; // only works on the first detected avatar 10763 if (detectedParams == null)
9962 10764 {
10765 if (m_host.ParentGroup.IsAttachment == true)
10766 {
10767 detectedParams = new DetectParams();
10768 detectedParams.Key = m_host.OwnerID;
10769 }
10770 else
10771 {
10772 return;
10773 }
10774 }
10775
9963 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10776 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9964 if (avatar != null) 10777 if (avatar != null)
9965 { 10778 {
9966 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, 10779 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name,
9967 simname, pos, lookAt); 10780 simname, pos, lookAt);
9968 } 10781 }
10782
9969 ScriptSleep(1000); 10783 ScriptSleep(1000);
9970 } 10784 }
9971 10785
@@ -10089,12 +10903,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10089 10903
10090 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10904 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
10091 object[] data = rules.Data; 10905 object[] data = rules.Data;
10092 for (int i = 0; i < data.Length; ++i) { 10906 for (int i = 0; i < data.Length; ++i)
10907 {
10093 int type = Convert.ToInt32(data[i++].ToString()); 10908 int type = Convert.ToInt32(data[i++].ToString());
10094 if (i >= data.Length) break; // odd number of entries => ignore the last 10909 if (i >= data.Length) break; // odd number of entries => ignore the last
10095 10910
10096 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10911 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
10097 switch (type) { 10912 switch (type)
10913 {
10098 case ScriptBaseClass.CAMERA_FOCUS: 10914 case ScriptBaseClass.CAMERA_FOCUS:
10099 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10915 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
10100 case ScriptBaseClass.CAMERA_POSITION: 10916 case ScriptBaseClass.CAMERA_POSITION:
@@ -10199,19 +11015,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10199 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 11015 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
10200 { 11016 {
10201 m_host.AddScriptLPS(1); 11017 m_host.AddScriptLPS(1);
10202 string ret = String.Empty; 11018
10203 string src1 = llBase64ToString(str1); 11019 if (str1 == String.Empty)
10204 string src2 = llBase64ToString(str2); 11020 return String.Empty;
10205 int c = 0; 11021 if (str2 == String.Empty)
10206 for (int i = 0; i < src1.Length; i++) 11022 return str1;
11023
11024 int len = str2.Length;
11025 if ((len % 4) != 0) // LL is EVIL!!!!
10207 { 11026 {
10208 ret += (char) (src1[i] ^ src2[c]); 11027 while (str2.EndsWith("="))
11028 str2 = str2.Substring(0, str2.Length - 1);
10209 11029
10210 c++; 11030 len = str2.Length;
10211 if (c >= src2.Length) 11031 int mod = len % 4;
10212 c = 0; 11032
11033 if (mod == 1)
11034 str2 = str2.Substring(0, str2.Length - 1);
11035 else if (mod == 2)
11036 str2 += "==";
11037 else if (mod == 3)
11038 str2 += "=";
11039 }
11040
11041 byte[] data1;
11042 byte[] data2;
11043 try
11044 {
11045 data1 = Convert.FromBase64String(str1);
11046 data2 = Convert.FromBase64String(str2);
11047 }
11048 catch (Exception)
11049 {
11050 return new LSL_String(String.Empty);
11051 }
11052
11053 byte[] d2 = new Byte[data1.Length];
11054 int pos = 0;
11055
11056 if (data1.Length <= data2.Length)
11057 {
11058 Array.Copy(data2, 0, d2, 0, data1.Length);
10213 } 11059 }
10214 return llStringToBase64(ret); 11060 else
11061 {
11062 while (pos < data1.Length)
11063 {
11064 len = data1.Length - pos;
11065 if (len > data2.Length)
11066 len = data2.Length;
11067
11068 Array.Copy(data2, 0, d2, pos, len);
11069 pos += len;
11070 }
11071 }
11072
11073 for (pos = 0 ; pos < data1.Length ; pos++ )
11074 data1[pos] ^= d2[pos];
11075
11076 return Convert.ToBase64String(data1);
10215 } 11077 }
10216 11078
10217 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 11079 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10264,16 +11126,72 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10264 if (userAgent != null) 11126 if (userAgent != null)
10265 httpHeaders["User-Agent"] = userAgent; 11127 httpHeaders["User-Agent"] = userAgent;
10266 11128
11129 // See if the URL contains any header hacks
11130 string[] urlParts = url.Split(new char[] {'\n'});
11131 if (urlParts.Length > 1)
11132 {
11133 // Iterate the passed headers and parse them
11134 for (int i = 1 ; i < urlParts.Length ; i++ )
11135 {
11136 // The rest of those would be added to the body in SL.
11137 // Let's not do that.
11138 if (urlParts[i] == String.Empty)
11139 break;
11140
11141 // See if this could be a valid header
11142 string[] headerParts = urlParts[i].Split(new char[] {':'}, 2);
11143 if (headerParts.Length != 2)
11144 continue;
11145
11146 string headerName = headerParts[0].Trim();
11147 string headerValue = headerParts[1].Trim();
11148
11149 // Filter out headers that could be used to abuse
11150 // another system or cloak the request
11151 if (headerName.ToLower() == "x-secondlife-shard" ||
11152 headerName.ToLower() == "x-secondlife-object-name" ||
11153 headerName.ToLower() == "x-secondlife-object-key" ||
11154 headerName.ToLower() == "x-secondlife-region" ||
11155 headerName.ToLower() == "x-secondlife-local-position" ||
11156 headerName.ToLower() == "x-secondlife-local-velocity" ||
11157 headerName.ToLower() == "x-secondlife-local-rotation" ||
11158 headerName.ToLower() == "x-secondlife-owner-name" ||
11159 headerName.ToLower() == "x-secondlife-owner-key" ||
11160 headerName.ToLower() == "connection" ||
11161 headerName.ToLower() == "content-length" ||
11162 headerName.ToLower() == "from" ||
11163 headerName.ToLower() == "host" ||
11164 headerName.ToLower() == "proxy-authorization" ||
11165 headerName.ToLower() == "referer" ||
11166 headerName.ToLower() == "trailer" ||
11167 headerName.ToLower() == "transfer-encoding" ||
11168 headerName.ToLower() == "via" ||
11169 headerName.ToLower() == "authorization")
11170 continue;
11171
11172 httpHeaders[headerName] = headerValue;
11173 }
11174
11175 // Finally, strip any protocol specifier from the URL
11176 url = urlParts[0].Trim();
11177 int idx = url.IndexOf(" HTTP/");
11178 if (idx != -1)
11179 url = url.Substring(0, idx);
11180 }
11181
10267 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$"; 11182 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$";
10268 Regex r = new Regex(authregex); 11183 Regex r = new Regex(authregex);
10269 int[] gnums = r.GetGroupNumbers(); 11184 int[] gnums = r.GetGroupNumbers();
10270 Match m = r.Match(url); 11185 Match m = r.Match(url);
10271 if (m.Success) { 11186 if (m.Success)
10272 for (int i = 1; i < gnums.Length; i++) { 11187 {
11188 for (int i = 1; i < gnums.Length; i++)
11189 {
10273 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 11190 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10274 //CaptureCollection cc = g.Captures; 11191 //CaptureCollection cc = g.Captures;
10275 } 11192 }
10276 if (m.Groups.Count == 5) { 11193 if (m.Groups.Count == 5)
11194 {
10277 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 11195 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10278 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 11196 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10279 } 11197 }
@@ -10476,6 +11394,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10476 11394
10477 LSL_List ret = new LSL_List(); 11395 LSL_List ret = new LSL_List();
10478 UUID key = new UUID(); 11396 UUID key = new UUID();
11397
11398
10479 if (UUID.TryParse(id, out key)) 11399 if (UUID.TryParse(id, out key))
10480 { 11400 {
10481 ScenePresence av = World.GetScenePresence(key); 11401 ScenePresence av = World.GetScenePresence(key);
@@ -10493,13 +11413,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10493 ret.Add(new LSL_String("")); 11413 ret.Add(new LSL_String(""));
10494 break; 11414 break;
10495 case ScriptBaseClass.OBJECT_POS: 11415 case ScriptBaseClass.OBJECT_POS:
10496 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); 11416 Vector3 avpos;
11417
11418 if (av.ParentID != 0 && av.ParentPart != null)
11419 {
11420 avpos = av.OffsetPosition;
11421
11422 Vector3 sitOffset = (Zrot(av.Rotation)) * (av.Appearance.AvatarHeight * 0.02638f *2.0f);
11423 avpos -= sitOffset;
11424
11425 avpos = av.ParentPart.GetWorldPosition() + avpos * av.ParentPart.GetWorldRotation();
11426 }
11427 else
11428 avpos = av.AbsolutePosition;
11429
11430 ret.Add(new LSL_Vector((double)avpos.X, (double)avpos.Y, (double)avpos.Z));
10497 break; 11431 break;
10498 case ScriptBaseClass.OBJECT_ROT: 11432 case ScriptBaseClass.OBJECT_ROT:
10499 ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W)); 11433 Quaternion avrot = av.Rotation;
11434 if (av.ParentID != 0 && av.ParentPart != null)
11435 {
11436 avrot = av.ParentPart.GetWorldRotation() * avrot;
11437 }
11438 ret.Add(new LSL_Rotation((double)avrot.X, (double)avrot.Y, (double)avrot.Z, (double)avrot.W));
10500 break; 11439 break;
10501 case ScriptBaseClass.OBJECT_VELOCITY: 11440 case ScriptBaseClass.OBJECT_VELOCITY:
10502 ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); 11441 Vector3 avvel = av.Velocity;
11442 ret.Add(new LSL_Vector((double)avvel.X, (double)avvel.Y, (double)avvel.Z));
10503 break; 11443 break;
10504 case ScriptBaseClass.OBJECT_OWNER: 11444 case ScriptBaseClass.OBJECT_OWNER:
10505 ret.Add(new LSL_String(id)); 11445 ret.Add(new LSL_String(id));
@@ -10584,11 +11524,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10584 case ScriptBaseClass.OBJECT_NAME: 11524 case ScriptBaseClass.OBJECT_NAME:
10585 ret.Add(new LSL_String(obj.Name)); 11525 ret.Add(new LSL_String(obj.Name));
10586 break; 11526 break;
10587 case ScriptBaseClass.OBJECT_DESC: 11527 case ScriptBaseClass.OBJECT_DESC:
10588 ret.Add(new LSL_String(obj.Description)); 11528 ret.Add(new LSL_String(obj.Description));
10589 break; 11529 break;
10590 case ScriptBaseClass.OBJECT_POS: 11530 case ScriptBaseClass.OBJECT_POS:
10591 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); 11531 Vector3 opos = obj.AbsolutePosition;
11532 ret.Add(new LSL_Vector(opos.X, opos.Y, opos.Z));
10592 break; 11533 break;
10593 case ScriptBaseClass.OBJECT_ROT: 11534 case ScriptBaseClass.OBJECT_ROT:
10594 { 11535 {
@@ -10638,9 +11579,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10638 // The value returned in SL for normal prims is prim count 11579 // The value returned in SL for normal prims is prim count
10639 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount)); 11580 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
10640 break; 11581 break;
10641 // The following 3 costs I have intentionaly coded to return zero. They are part of 11582
10642 // "Land Impact" calculations. These calculations are probably not applicable 11583 // costs below may need to be diferent for root parts, need to check
10643 // to OpenSim and are not yet complete in SL
10644 case ScriptBaseClass.OBJECT_SERVER_COST: 11584 case ScriptBaseClass.OBJECT_SERVER_COST:
10645 // The linden calculation is here 11585 // The linden calculation is here
10646 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight 11586 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
@@ -10648,16 +11588,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10648 ret.Add(new LSL_Float(0)); 11588 ret.Add(new LSL_Float(0));
10649 break; 11589 break;
10650 case ScriptBaseClass.OBJECT_STREAMING_COST: 11590 case ScriptBaseClass.OBJECT_STREAMING_COST:
10651 // The linden calculation is here 11591 // The value returned in SL for normal prims is prim count * 0.06
10652 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost 11592 ret.Add(new LSL_Float(obj.StreamingCost));
10653 // The value returned in SL for normal prims looks like the prim count * 0.06
10654 ret.Add(new LSL_Float(0));
10655 break; 11593 break;
10656 case ScriptBaseClass.OBJECT_PHYSICS_COST: 11594 case ScriptBaseClass.OBJECT_PHYSICS_COST:
10657 // The linden calculation is here 11595 // The value returned in SL for normal prims is prim count
10658 // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics 11596 ret.Add(new LSL_Float(obj.PhysicsCost));
10659 // The value returned in SL for normal prims looks like the prim count
10660 ret.Add(new LSL_Float(0));
10661 break; 11597 break;
10662 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding 11598 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
10663 ret.Add(new LSL_Float(0)); 11599 ret.Add(new LSL_Float(0));
@@ -10914,15 +11850,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10914 return result; 11850 return result;
10915 } 11851 }
10916 11852
10917 public void print(string str) 11853 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10918 { 11854 {
10919 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11855 List<SceneObjectPart> parts = GetLinkParts(link);
10920 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11856 if (parts.Count < 1)
10921 if (ossl != null) 11857 return 0;
10922 { 11858
10923 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11859 return GetNumberOfSides(parts[0]);
10924 m_log.Info("LSL print():" + str);
10925 }
10926 } 11860 }
10927 11861
10928 private string Name2Username(string name) 11862 private string Name2Username(string name)
@@ -10967,7 +11901,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10967 11901
10968 return rq.ToString(); 11902 return rq.ToString();
10969 } 11903 }
10970 11904/*
11905 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11906 {
11907 m_SayShoutCount = 0;
11908 }
11909*/
10971 private struct Tri 11910 private struct Tri
10972 { 11911 {
10973 public Vector3 p1; 11912 public Vector3 p1;
@@ -11116,9 +12055,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11116 12055
11117 ContactResult result = new ContactResult (); 12056 ContactResult result = new ContactResult ();
11118 result.ConsumerID = group.LocalId; 12057 result.ConsumerID = group.LocalId;
11119 result.Depth = intersection.distance; 12058// result.Depth = intersection.distance;
11120 result.Normal = intersection.normal; 12059 result.Normal = intersection.normal;
11121 result.Pos = intersection.ipoint; 12060 result.Pos = intersection.ipoint;
12061 result.Depth = Vector3.Mag(rayStart - result.Pos);
11122 12062
11123 contacts.Add(result); 12063 contacts.Add(result);
11124 }); 12064 });
@@ -11251,6 +12191,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11251 12191
11252 return contacts[0]; 12192 return contacts[0];
11253 } 12193 }
12194/*
12195 // not done:
12196 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
12197 {
12198 ContactResult[] contacts = null;
12199 World.ForEachSOG(delegate(SceneObjectGroup group)
12200 {
12201 if (m_host.ParentGroup == group)
12202 return;
12203
12204 if (group.IsAttachment)
12205 return;
12206
12207 if(group.RootPart.PhysActor != null)
12208 return;
12209
12210 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
12211 });
12212 return contacts;
12213 }
12214*/
11254 12215
11255 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 12216 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
11256 { 12217 {
@@ -11374,18 +12335,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11374 } 12335 }
11375 } 12336 }
11376 12337
12338 // Double check this
11377 if (checkTerrain) 12339 if (checkTerrain)
11378 { 12340 {
11379 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); 12341 bool skipGroundCheck = false;
11380 if (groundContact != null) 12342
11381 results.Add((ContactResult)groundContact); 12343 foreach (ContactResult c in results)
12344 {
12345 if (c.ConsumerID == 0) // Physics gave us a ground collision
12346 skipGroundCheck = true;
12347 }
12348
12349 if (!skipGroundCheck)
12350 {
12351 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
12352 if (groundContact != null)
12353 results.Add((ContactResult)groundContact);
12354 }
11382 } 12355 }
11383 12356
11384 results.Sort(delegate(ContactResult a, ContactResult b) 12357 results.Sort(delegate(ContactResult a, ContactResult b)
11385 { 12358 {
11386 return a.Depth.CompareTo(b.Depth); 12359 return a.Depth.CompareTo(b.Depth);
11387 }); 12360 });
11388 12361
11389 int values = 0; 12362 int values = 0;
11390 SceneObjectGroup thisgrp = m_host.ParentGroup; 12363 SceneObjectGroup thisgrp = m_host.ParentGroup;
11391 12364
@@ -11478,7 +12451,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11478 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 12451 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
11479 if (!isAccount) return 0; 12452 if (!isAccount) return 0;
11480 if (estate.HasAccess(id)) return 1; 12453 if (estate.HasAccess(id)) return 1;
11481 if (estate.IsBanned(id)) 12454 if (estate.IsBanned(id, World.GetUserFlags(id)))
11482 estate.RemoveBan(id); 12455 estate.RemoveBan(id);
11483 estate.AddEstateUser(id); 12456 estate.AddEstateUser(id);
11484 break; 12457 break;
@@ -11497,14 +12470,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11497 break; 12470 break;
11498 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 12471 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
11499 if (!isAccount) return 0; 12472 if (!isAccount) return 0;
11500 if (estate.IsBanned(id)) return 1; 12473 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
11501 EstateBan ban = new EstateBan(); 12474 EstateBan ban = new EstateBan();
11502 ban.EstateID = estate.EstateID; 12475 ban.EstateID = estate.EstateID;
11503 ban.BannedUserID = id; 12476 ban.BannedUserID = id;
11504 estate.AddBan(ban); 12477 estate.AddBan(ban);
11505 break; 12478 break;
11506 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 12479 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
11507 if (!isAccount || !estate.IsBanned(id)) return 0; 12480 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
11508 estate.RemoveBan(id); 12481 estate.RemoveBan(id);
11509 break; 12482 break;
11510 default: return 0; 12483 default: return 0;
@@ -11533,7 +12506,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11533 return 16384; 12506 return 16384;
11534 } 12507 }
11535 12508
11536 public LSL_Integer llGetUsedMemory() 12509 public virtual LSL_Integer llGetUsedMemory()
11537 { 12510 {
11538 m_host.AddScriptLPS(1); 12511 m_host.AddScriptLPS(1);
11539 // The value returned for LSO scripts in SL 12512 // The value returned for LSO scripts in SL
@@ -11561,19 +12534,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11561 public void llSetSoundQueueing(int queue) 12534 public void llSetSoundQueueing(int queue)
11562 { 12535 {
11563 m_host.AddScriptLPS(1); 12536 m_host.AddScriptLPS(1);
11564 NotImplemented("llSetSoundQueueing");
11565 } 12537 }
11566 12538
11567 public void llCollisionSprite(string impact_sprite) 12539 public void llCollisionSprite(string impact_sprite)
11568 { 12540 {
11569 m_host.AddScriptLPS(1); 12541 m_host.AddScriptLPS(1);
11570 NotImplemented("llCollisionSprite"); 12542 // Viewer 2.0 broke this and it's likely LL has no intention
12543 // of fixing it. Therefore, letting this be a NOP seems appropriate.
11571 } 12544 }
11572 12545
11573 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12546 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
11574 { 12547 {
11575 m_host.AddScriptLPS(1); 12548 m_host.AddScriptLPS(1);
11576 NotImplemented("llGodLikeRezObject"); 12549
12550 if (!World.Permissions.IsGod(m_host.OwnerID))
12551 NotImplemented("llGodLikeRezObject");
12552
12553 AssetBase rezAsset = World.AssetService.Get(inventory);
12554 if (rezAsset == null)
12555 {
12556 llSay(0, "Asset not found");
12557 return;
12558 }
12559
12560 SceneObjectGroup group = null;
12561
12562 try
12563 {
12564 string xmlData = Utils.BytesToString(rezAsset.Data);
12565 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12566 }
12567 catch
12568 {
12569 llSay(0, "Asset not found");
12570 return;
12571 }
12572
12573 if (group == null)
12574 {
12575 llSay(0, "Asset not found");
12576 return;
12577 }
12578
12579 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12580 group.RootPart.AttachOffset = group.AbsolutePosition;
12581
12582 group.ResetIDs();
12583
12584 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12585 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12586 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12587 group.ScheduleGroupForFullUpdate();
12588
12589 // objects rezzed with this method are die_at_edge by default.
12590 group.RootPart.SetDieAtEdge(true);
12591
12592 group.ResumeScripts();
12593
12594 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12595 "object_rez", new Object[] {
12596 new LSL_String(
12597 group.RootPart.UUID.ToString()) },
12598 new DetectParams[0]));
11577 } 12599 }
11578 12600
11579 public LSL_String llTransferLindenDollars(string destination, int amount) 12601 public LSL_String llTransferLindenDollars(string destination, int amount)
@@ -11625,7 +12647,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11625 } 12647 }
11626 12648
11627 bool result = money.ObjectGiveMoney( 12649 bool result = money.ObjectGiveMoney(
11628 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 12650 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount, txn);
11629 12651
11630 if (result) 12652 if (result)
11631 { 12653 {
@@ -11650,6 +12672,598 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11650 } 12672 }
11651 12673
11652 #endregion 12674 #endregion
12675
12676 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12677 {
12678 SceneObjectGroup group = m_host.ParentGroup;
12679
12680 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12681 return;
12682 if (group.IsAttachment)
12683 return;
12684
12685 if (frames.Data.Length > 0) // We are getting a new motion
12686 {
12687 if (group.RootPart.KeyframeMotion != null)
12688 group.RootPart.KeyframeMotion.Delete();
12689 group.RootPart.KeyframeMotion = null;
12690
12691 int idx = 0;
12692
12693 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12694 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12695
12696 while (idx < options.Data.Length)
12697 {
12698 int option = (int)options.GetLSLIntegerItem(idx++);
12699 int remain = options.Data.Length - idx;
12700
12701 switch (option)
12702 {
12703 case ScriptBaseClass.KFM_MODE:
12704 if (remain < 1)
12705 break;
12706 int modeval = (int)options.GetLSLIntegerItem(idx++);
12707 switch(modeval)
12708 {
12709 case ScriptBaseClass.KFM_FORWARD:
12710 mode = KeyframeMotion.PlayMode.Forward;
12711 break;
12712 case ScriptBaseClass.KFM_REVERSE:
12713 mode = KeyframeMotion.PlayMode.Reverse;
12714 break;
12715 case ScriptBaseClass.KFM_LOOP:
12716 mode = KeyframeMotion.PlayMode.Loop;
12717 break;
12718 case ScriptBaseClass.KFM_PING_PONG:
12719 mode = KeyframeMotion.PlayMode.PingPong;
12720 break;
12721 }
12722 break;
12723 case ScriptBaseClass.KFM_DATA:
12724 if (remain < 1)
12725 break;
12726 int dataval = (int)options.GetLSLIntegerItem(idx++);
12727 data = (KeyframeMotion.DataFormat)dataval;
12728 break;
12729 }
12730 }
12731
12732 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12733
12734 idx = 0;
12735
12736 int elemLength = 2;
12737 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12738 elemLength = 3;
12739
12740 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12741 while (idx < frames.Data.Length)
12742 {
12743 int remain = frames.Data.Length - idx;
12744
12745 if (remain < elemLength)
12746 break;
12747
12748 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12749 frame.Position = null;
12750 frame.Rotation = null;
12751
12752 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12753 {
12754 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12755 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12756 }
12757 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12758 {
12759 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12760 Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12761 q.Normalize();
12762 frame.Rotation = q;
12763 }
12764
12765 float tempf = (float)frames.GetLSLFloatItem(idx++);
12766 frame.TimeMS = (int)(tempf * 1000.0f);
12767
12768 keyframes.Add(frame);
12769 }
12770
12771 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12772 group.RootPart.KeyframeMotion.Start();
12773 }
12774 else
12775 {
12776 if (group.RootPart.KeyframeMotion == null)
12777 return;
12778
12779 if (options.Data.Length == 0)
12780 {
12781 group.RootPart.KeyframeMotion.Stop();
12782 return;
12783 }
12784
12785 int code = (int)options.GetLSLIntegerItem(0);
12786
12787 int idx = 0;
12788
12789 while (idx < options.Data.Length)
12790 {
12791 int option = (int)options.GetLSLIntegerItem(idx++);
12792 int remain = options.Data.Length - idx;
12793
12794 switch (option)
12795 {
12796 case ScriptBaseClass.KFM_COMMAND:
12797 int cmd = (int)options.GetLSLIntegerItem(idx++);
12798 switch (cmd)
12799 {
12800 case ScriptBaseClass.KFM_CMD_PLAY:
12801 group.RootPart.KeyframeMotion.Start();
12802 break;
12803 case ScriptBaseClass.KFM_CMD_STOP:
12804 group.RootPart.KeyframeMotion.Stop();
12805 break;
12806 case ScriptBaseClass.KFM_CMD_PAUSE:
12807 group.RootPart.KeyframeMotion.Pause();
12808 break;
12809 }
12810 break;
12811 }
12812 }
12813 }
12814 }
12815
12816 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed)
12817 {
12818 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
12819
12820 int idx = 0;
12821 int idxStart = 0;
12822
12823 bool positionChanged = false;
12824 Vector3 finalPos = Vector3.Zero;
12825
12826 try
12827 {
12828 while (idx < rules.Length)
12829 {
12830 ++rulesParsed;
12831 int code = rules.GetLSLIntegerItem(idx++);
12832
12833 int remain = rules.Length - idx;
12834 idxStart = idx;
12835
12836 switch (code)
12837 {
12838 case (int)ScriptBaseClass.PRIM_POSITION:
12839 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
12840 {
12841 if (remain < 1)
12842 return null;
12843
12844 LSL_Vector v;
12845 v = rules.GetVector3Item(idx++);
12846
12847 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12848 if (part == null)
12849 break;
12850
12851 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12852 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12853 if (part.LinkNum > 1)
12854 {
12855 localRot = GetPartLocalRot(part);
12856 localPos = GetPartLocalPos(part);
12857 }
12858
12859 v -= localPos;
12860 v /= localRot;
12861
12862 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
12863
12864 v = v + 2 * sitOffset;
12865
12866 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
12867 av.SendAvatarDataToAllAgents();
12868
12869 }
12870 break;
12871
12872 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
12873 case (int)ScriptBaseClass.PRIM_ROTATION:
12874 {
12875 if (remain < 1)
12876 return null;
12877
12878 LSL_Rotation r;
12879 r = rules.GetQuaternionItem(idx++);
12880
12881 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12882 if (part == null)
12883 break;
12884
12885 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12886 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12887
12888 if (part.LinkNum > 1)
12889 localRot = GetPartLocalRot(part);
12890
12891 r = r * llGetRootRotation() / localRot;
12892 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
12893 av.SendAvatarDataToAllAgents();
12894 }
12895 break;
12896
12897 // parse rest doing nothing but number of parameters error check
12898 case (int)ScriptBaseClass.PRIM_SIZE:
12899 case (int)ScriptBaseClass.PRIM_MATERIAL:
12900 case (int)ScriptBaseClass.PRIM_PHANTOM:
12901 case (int)ScriptBaseClass.PRIM_PHYSICS:
12902 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
12903 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
12904 case (int)ScriptBaseClass.PRIM_NAME:
12905 case (int)ScriptBaseClass.PRIM_DESC:
12906 if (remain < 1)
12907 return null;
12908 idx++;
12909 break;
12910
12911 case (int)ScriptBaseClass.PRIM_GLOW:
12912 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
12913 case (int)ScriptBaseClass.PRIM_TEXGEN:
12914 if (remain < 2)
12915 return null;
12916 idx += 2;
12917 break;
12918
12919 case (int)ScriptBaseClass.PRIM_TYPE:
12920 if (remain < 3)
12921 return null;
12922 code = (int)rules.GetLSLIntegerItem(idx++);
12923 remain = rules.Length - idx;
12924 switch (code)
12925 {
12926 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
12927 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
12928 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
12929 if (remain < 6)
12930 return null;
12931 idx += 6;
12932 break;
12933
12934 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
12935 if (remain < 5)
12936 return null;
12937 idx += 5;
12938 break;
12939
12940 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
12941 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
12942 case (int)ScriptBaseClass.PRIM_TYPE_RING:
12943 if (remain < 11)
12944 return null;
12945 idx += 11;
12946 break;
12947
12948 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
12949 if (remain < 2)
12950 return null;
12951 idx += 2;
12952 break;
12953 }
12954 break;
12955
12956 case (int)ScriptBaseClass.PRIM_COLOR:
12957 case (int)ScriptBaseClass.PRIM_TEXT:
12958 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
12959 case (int)ScriptBaseClass.PRIM_OMEGA:
12960 if (remain < 3)
12961 return null;
12962 idx += 3;
12963 break;
12964
12965 case (int)ScriptBaseClass.PRIM_TEXTURE:
12966 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
12967 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
12968 if (remain < 5)
12969 return null;
12970 idx += 5;
12971 break;
12972
12973 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
12974 if (remain < 7)
12975 return null;
12976
12977 idx += 7;
12978 break;
12979
12980 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
12981 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
12982 return null;
12983
12984 return rules.GetSublist(idx, -1);
12985 }
12986 }
12987 }
12988 catch (InvalidCastException e)
12989 {
12990 ShoutError(string.Format(
12991 "{0} error running rule #{1}: arg #{2} ",
12992 originFunc, rulesParsed, idx - idxStart) + e.Message);
12993 }
12994 finally
12995 {
12996 if (positionChanged)
12997 {
12998 av.OffsetPosition = finalPos;
12999// av.SendAvatarDataToAllAgents();
13000 av.SendTerseUpdateToAllClients();
13001 positionChanged = false;
13002 }
13003 }
13004 return null;
13005 }
13006
13007 public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res)
13008 {
13009 // avatars case
13010 // replies as SL wiki
13011
13012// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
13013 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
13014
13015 int idx = 0;
13016 while (idx < rules.Length)
13017 {
13018 int code = (int)rules.GetLSLIntegerItem(idx++);
13019 int remain = rules.Length - idx;
13020
13021 switch (code)
13022 {
13023 case (int)ScriptBaseClass.PRIM_MATERIAL:
13024 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
13025 break;
13026
13027 case (int)ScriptBaseClass.PRIM_PHYSICS:
13028 res.Add(new LSL_Integer(0));
13029 break;
13030
13031 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
13032 res.Add(new LSL_Integer(0));
13033 break;
13034
13035 case (int)ScriptBaseClass.PRIM_PHANTOM:
13036 res.Add(new LSL_Integer(0));
13037 break;
13038
13039 case (int)ScriptBaseClass.PRIM_POSITION:
13040
13041 Vector3 pos = avatar.OffsetPosition;
13042
13043 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
13044 pos -= sitOffset;
13045
13046 if( sitPart != null)
13047 pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation();
13048
13049 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
13050 break;
13051
13052 case (int)ScriptBaseClass.PRIM_SIZE:
13053 // as in llGetAgentSize above
13054// res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight));
13055 Vector3 s = avatar.Appearance.AvatarSize;
13056 res.Add(new LSL_Vector(s.X, s.Y, s.Z));
13057
13058 break;
13059
13060 case (int)ScriptBaseClass.PRIM_ROTATION:
13061 Quaternion rot = avatar.Rotation;
13062 if (sitPart != null)
13063 {
13064 rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation
13065 }
13066
13067 res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W));
13068 break;
13069
13070 case (int)ScriptBaseClass.PRIM_TYPE:
13071 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
13072 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
13073 res.Add(new LSL_Vector(0f,1.0f,0f));
13074 res.Add(new LSL_Float(0.0f));
13075 res.Add(new LSL_Vector(0, 0, 0));
13076 res.Add(new LSL_Vector(1.0f,1.0f,0f));
13077 res.Add(new LSL_Vector(0, 0, 0));
13078 break;
13079
13080 case (int)ScriptBaseClass.PRIM_TEXTURE:
13081 if (remain < 1)
13082 return null;
13083
13084 int face = (int)rules.GetLSLIntegerItem(idx++);
13085 if (face == ScriptBaseClass.ALL_SIDES)
13086 {
13087 for (face = 0; face < 21; face++)
13088 {
13089 res.Add(new LSL_String(""));
13090 res.Add(new LSL_Vector(0,0,0));
13091 res.Add(new LSL_Vector(0,0,0));
13092 res.Add(new LSL_Float(0.0));
13093 }
13094 }
13095 else
13096 {
13097 if (face >= 0 && face < 21)
13098 {
13099 res.Add(new LSL_String(""));
13100 res.Add(new LSL_Vector(0,0,0));
13101 res.Add(new LSL_Vector(0,0,0));
13102 res.Add(new LSL_Float(0.0));
13103 }
13104 }
13105 break;
13106
13107 case (int)ScriptBaseClass.PRIM_COLOR:
13108 if (remain < 1)
13109 return null;
13110
13111 face = (int)rules.GetLSLIntegerItem(idx++);
13112
13113 if (face == ScriptBaseClass.ALL_SIDES)
13114 {
13115 for (face = 0; face < 21; face++)
13116 {
13117 res.Add(new LSL_Vector(0,0,0));
13118 res.Add(new LSL_Float(0));
13119 }
13120 }
13121 else
13122 {
13123 res.Add(new LSL_Vector(0,0,0));
13124 res.Add(new LSL_Float(0));
13125 }
13126 break;
13127
13128 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
13129 if (remain < 1)
13130 return null;
13131 face = (int)rules.GetLSLIntegerItem(idx++);
13132
13133 if (face == ScriptBaseClass.ALL_SIDES)
13134 {
13135 for (face = 0; face < 21; face++)
13136 {
13137 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
13138 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
13139 }
13140 }
13141 else
13142 {
13143 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
13144 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
13145 }
13146 break;
13147
13148 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
13149 if (remain < 1)
13150 return null;
13151 face = (int)rules.GetLSLIntegerItem(idx++);
13152
13153 if (face == ScriptBaseClass.ALL_SIDES)
13154 {
13155 for (face = 0; face < 21; face++)
13156 {
13157 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
13158 }
13159 }
13160 else
13161 {
13162 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
13163 }
13164 break;
13165
13166 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
13167 res.Add(new LSL_Integer(0));
13168 res.Add(new LSL_Integer(0));// softness
13169 res.Add(new LSL_Float(0.0f)); // gravity
13170 res.Add(new LSL_Float(0.0f)); // friction
13171 res.Add(new LSL_Float(0.0f)); // wind
13172 res.Add(new LSL_Float(0.0f)); // tension
13173 res.Add(new LSL_Vector(0f,0f,0f));
13174 break;
13175
13176 case (int)ScriptBaseClass.PRIM_TEXGEN:
13177 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
13178 if (remain < 1)
13179 return null;
13180 face = (int)rules.GetLSLIntegerItem(idx++);
13181
13182 if (face == ScriptBaseClass.ALL_SIDES)
13183 {
13184 for (face = 0; face < 21; face++)
13185 {
13186 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13187 }
13188 }
13189 else
13190 {
13191 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13192 }
13193 break;
13194
13195 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
13196 res.Add(new LSL_Integer(0));
13197 res.Add(new LSL_Vector(0f,0f,0f));
13198 res.Add(new LSL_Float(0f)); // intensity
13199 res.Add(new LSL_Float(0f)); // radius
13200 res.Add(new LSL_Float(0f)); // falloff
13201 break;
13202
13203 case (int)ScriptBaseClass.PRIM_GLOW:
13204 if (remain < 1)
13205 return null;
13206 face = (int)rules.GetLSLIntegerItem(idx++);
13207
13208 if (face == ScriptBaseClass.ALL_SIDES)
13209 {
13210 for (face = 0; face < 21; face++)
13211 {
13212 res.Add(new LSL_Float(0f));
13213 }
13214 }
13215 else
13216 {
13217 res.Add(new LSL_Float(0f));
13218 }
13219 break;
13220
13221 case (int)ScriptBaseClass.PRIM_TEXT:
13222 res.Add(new LSL_String(""));
13223 res.Add(new LSL_Vector(0f,0f,0f));
13224 res.Add(new LSL_Float(1.0f));
13225 break;
13226
13227 case (int)ScriptBaseClass.PRIM_NAME:
13228 res.Add(new LSL_String(avatar.Name));
13229 break;
13230
13231 case (int)ScriptBaseClass.PRIM_DESC:
13232 res.Add(new LSL_String(""));
13233 break;
13234
13235 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
13236 Quaternion lrot = avatar.Rotation;
13237
13238 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13239 {
13240 lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset
13241 }
13242 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
13243 break;
13244
13245 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
13246 Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part
13247 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
13248 lpos -= lsitOffset;
13249
13250 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13251 {
13252 lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim
13253 }
13254 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
13255 break;
13256
13257 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
13258 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
13259 return null;
13260
13261 return rules.GetSublist(idx, -1);
13262 }
13263 }
13264
13265 return null;
13266 }
11653 } 13267 }
11654 13268
11655 public class NotecardCache 13269 public class NotecardCache