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.cs3142
1 files changed, 2371 insertions, 771 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index ab087af..29476b9 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);
4308
4309 GridInstantMessage msg = new GridInstantMessage(World,
4310 m_host.OwnerID, m_host.Name, destId,
4311 (byte)InstantMessageDialog.TaskInventoryOffered,
4312 false, item.Name+". "+m_host.Name+" is located at "+
4313 World.RegionInfo.RegionName+" "+
4314 m_host.AbsolutePosition.ToString(),
4315 agentItem.ID, true, m_host.AbsolutePosition,
4316 bucket, true);
3940 4317
3941 GridInstantMessage msg = new GridInstantMessage(World, 4318 ScenePresence sp;
3942 m_host.OwnerID, m_host.Name, destId,
3943 (byte)InstantMessageDialog.TaskInventoryOffered,
3944 false, item.Name+". "+m_host.Name+" is located at "+
3945 World.RegionInfo.RegionName+" "+
3946 m_host.AbsolutePosition.ToString(),
3947 agentItem.ID, true, m_host.AbsolutePosition,
3948 bucket, true);
3949 4319
3950 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4320 if (World.TryGetScenePresence(destId, out sp))
4321 {
4322 sp.ControllingClient.SendInstantMessage(msg);
3951 } 4323 }
3952 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,6 @@ 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");
4284 return; 4681 return;
4285 } 4682 }
4286 4683
@@ -4312,10 +4709,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4312 public void llCollisionSound(string impact_sound, double impact_volume) 4709 public void llCollisionSound(string impact_sound, double impact_volume)
4313 { 4710 {
4314 m_host.AddScriptLPS(1); 4711 m_host.AddScriptLPS(1);
4315 4712
4713 if(impact_sound == "")
4714 {
4715 m_host.CollisionSoundVolume = (float)impact_volume;
4716 m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
4717 m_host.CollisionSoundType = 0;
4718 return;
4719 }
4316 // TODO: Parameter check logic required. 4720 // TODO: Parameter check logic required.
4317 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound); 4721 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
4318 m_host.CollisionSoundVolume = (float)impact_volume; 4722 m_host.CollisionSoundVolume = (float)impact_volume;
4723 m_host.CollisionSoundType = 1;
4319 } 4724 }
4320 4725
4321 public LSL_String llGetAnimation(string id) 4726 public LSL_String llGetAnimation(string id)
@@ -4329,14 +4734,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4329 4734
4330 if (m_host.RegionHandle == presence.RegionHandle) 4735 if (m_host.RegionHandle == presence.RegionHandle)
4331 { 4736 {
4332 Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames;
4333
4334 if (presence != null) 4737 if (presence != null)
4335 { 4738 {
4336 AnimationSet currentAnims = presence.Animator.Animations; 4739 if (presence.SitGround)
4337 string currentAnimationState = String.Empty; 4740 return "Sitting on Ground";
4338 if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState)) 4741 if (presence.ParentID != 0 || presence.ParentUUID != UUID.Zero)
4339 return currentAnimationState; 4742 return "Sitting";
4743
4744 string movementAnimation = presence.Animator.CurrentMovementAnimation;
4745 string lslMovementAnimation;
4746
4747 if (MovementAnimationsForLSL.TryGetValue(movementAnimation, out lslMovementAnimation))
4748 return lslMovementAnimation;
4340 } 4749 }
4341 } 4750 }
4342 4751
@@ -4484,7 +4893,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4484 { 4893 {
4485 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4894 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4486 float distance_term = distance * distance * distance; // Script Energy 4895 float distance_term = distance * distance * distance; // Script Energy
4487 float pusher_mass = m_host.GetMass(); 4896 // use total object mass and not part
4897 float pusher_mass = m_host.ParentGroup.GetMass();
4488 4898
4489 float PUSH_ATTENUATION_DISTANCE = 17f; 4899 float PUSH_ATTENUATION_DISTANCE = 17f;
4490 float PUSH_ATTENUATION_SCALE = 5f; 4900 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4738,6 +5148,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4738 { 5148 {
4739 return item.AssetID.ToString(); 5149 return item.AssetID.ToString();
4740 } 5150 }
5151 m_host.TaskInventory.LockItemsForRead(false);
4741 5152
4742 return UUID.Zero.ToString(); 5153 return UUID.Zero.ToString();
4743 } 5154 }
@@ -4890,14 +5301,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4890 { 5301 {
4891 m_host.AddScriptLPS(1); 5302 m_host.AddScriptLPS(1);
4892 5303
4893 if (src == null) 5304 return src.Length;
4894 {
4895 return 0;
4896 }
4897 else
4898 {
4899 return src.Length;
4900 }
4901 } 5305 }
4902 5306
4903 public LSL_Integer llList2Integer(LSL_List src, int index) 5307 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -4968,7 +5372,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4968 else if (src.Data[index] is LSL_Float) 5372 else if (src.Data[index] is LSL_Float)
4969 return Convert.ToDouble(((LSL_Float)src.Data[index]).value); 5373 return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
4970 else if (src.Data[index] is LSL_String) 5374 else if (src.Data[index] is LSL_String)
4971 return Convert.ToDouble(((LSL_String)src.Data[index]).m_string); 5375 {
5376 string str = ((LSL_String) src.Data[index]).m_string;
5377 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5378 if (m != Match.Empty)
5379 {
5380 str = m.Value;
5381 double d = 0.0;
5382 if (!Double.TryParse(str, out d))
5383 return 0.0;
5384
5385 return d;
5386 }
5387 return 0.0;
5388 }
4972 return Convert.ToDouble(src.Data[index]); 5389 return Convert.ToDouble(src.Data[index]);
4973 } 5390 }
4974 catch (FormatException) 5391 catch (FormatException)
@@ -5010,7 +5427,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5010 // for completion and should LSL_Key ever be implemented 5427 // for completion and should LSL_Key ever be implemented
5011 // as it's own struct 5428 // as it's own struct
5012 else if (!(src.Data[index] is LSL_String || 5429 else if (!(src.Data[index] is LSL_String ||
5013 src.Data[index] is LSL_Key)) 5430 src.Data[index] is LSL_Key ||
5431 src.Data[index] is String))
5014 { 5432 {
5015 return ""; 5433 return "";
5016 } 5434 }
@@ -5268,7 +5686,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5268 } 5686 }
5269 } 5687 }
5270 } 5688 }
5271 else { 5689 else
5690 {
5272 object[] array = new object[src.Length]; 5691 object[] array = new object[src.Length];
5273 Array.Copy(src.Data, 0, array, 0, src.Length); 5692 Array.Copy(src.Data, 0, array, 0, src.Length);
5274 result = new LSL_List(array); 5693 result = new LSL_List(array);
@@ -5375,7 +5794,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5375 public LSL_Integer llGetRegionAgentCount() 5794 public LSL_Integer llGetRegionAgentCount()
5376 { 5795 {
5377 m_host.AddScriptLPS(1); 5796 m_host.AddScriptLPS(1);
5378 return new LSL_Integer(World.GetRootAgentCount()); 5797
5798 int count = 0;
5799 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
5800 count++;
5801 });
5802
5803 return new LSL_Integer(count);
5379 } 5804 }
5380 5805
5381 public LSL_Vector llGetRegionCorner() 5806 public LSL_Vector llGetRegionCorner()
@@ -5616,6 +6041,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5616 flags |= ScriptBaseClass.AGENT_AWAY; 6041 flags |= ScriptBaseClass.AGENT_AWAY;
5617 } 6042 }
5618 6043
6044 UUID busy = new UUID("efcf670c-2d18-8128-973a-034ebc806b67");
6045 UUID[] anims = agent.Animator.GetAnimationArray();
6046 if (Array.Exists<UUID>(anims, a => { return a == busy; }))
6047 {
6048 flags |= ScriptBaseClass.AGENT_BUSY;
6049 }
6050
5619 // seems to get unset, even if in mouselook, when avatar is sitting on a prim??? 6051 // seems to get unset, even if in mouselook, when avatar is sitting on a prim???
5620 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) 6052 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
5621 { 6053 {
@@ -5663,6 +6095,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5663 flags |= ScriptBaseClass.AGENT_SITTING; 6095 flags |= ScriptBaseClass.AGENT_SITTING;
5664 } 6096 }
5665 6097
6098 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
6099 {
6100 flags |= ScriptBaseClass.AGENT_MALE;
6101 }
6102
5666 return flags; 6103 return flags;
5667 } 6104 }
5668 6105
@@ -5810,9 +6247,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5810 6247
5811 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6248 List<SceneObjectPart> parts = GetLinkParts(linknumber);
5812 6249
5813 foreach (SceneObjectPart part in parts) 6250 try
6251 {
6252 foreach (SceneObjectPart part in parts)
6253 {
6254 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6255 }
6256 }
6257 finally
5814 { 6258 {
5815 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
5816 } 6259 }
5817 } 6260 }
5818 6261
@@ -5866,13 +6309,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5866 6309
5867 if (m_host.OwnerID == land.LandData.OwnerID) 6310 if (m_host.OwnerID == land.LandData.OwnerID)
5868 { 6311 {
5869 World.TeleportClientHome(agentID, presence.ControllingClient); 6312 Vector3 pos = World.GetNearestAllowedPosition(presence, land);
6313 presence.TeleportWithMomentum(pos, null);
6314 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
5870 } 6315 }
5871 } 6316 }
5872 } 6317 }
5873 ScriptSleep(5000); 6318 ScriptSleep(5000);
5874 } 6319 }
5875 6320
6321 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6322 {
6323 return ParseString2List(str, separators, in_spacers, false);
6324 }
6325
5876 public LSL_Integer llOverMyLand(string id) 6326 public LSL_Integer llOverMyLand(string id)
5877 { 6327 {
5878 m_host.AddScriptLPS(1); 6328 m_host.AddScriptLPS(1);
@@ -5926,25 +6376,55 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5926 } 6376 }
5927 else 6377 else
5928 { 6378 {
5929 agentSize = new LSL_Vector(0.45, 0.6, avatar.Appearance.AvatarHeight); 6379// agentSize = new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight);
6380 Vector3 s = avatar.Appearance.AvatarSize;
6381 agentSize = new LSL_Vector(s.X, s.Y, s.Z);
5930 } 6382 }
5931 return agentSize; 6383 return agentSize;
5932 } 6384 }
5933 6385
5934 public LSL_Integer llSameGroup(string agent) 6386 public LSL_Integer llSameGroup(string id)
5935 { 6387 {
5936 m_host.AddScriptLPS(1); 6388 m_host.AddScriptLPS(1);
5937 UUID agentId = new UUID(); 6389 UUID uuid = new UUID();
5938 if (!UUID.TryParse(agent, out agentId)) 6390 if (!UUID.TryParse(id, out uuid))
5939 return new LSL_Integer(0); 6391 return new LSL_Integer(0);
5940 ScenePresence presence = World.GetScenePresence(agentId); 6392
5941 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6393 // Check if it's a group key
5942 return new LSL_Integer(0); 6394 if (uuid == m_host.ParentGroup.RootPart.GroupID)
5943 IClientAPI client = presence.ControllingClient;
5944 if (m_host.GroupID == client.ActiveGroupId)
5945 return new LSL_Integer(1); 6395 return new LSL_Integer(1);
5946 else 6396
6397 // We got passed a UUID.Zero
6398 if (uuid == UUID.Zero)
6399 return new LSL_Integer(0);
6400
6401 // Handle the case where id names an avatar
6402 ScenePresence presence = World.GetScenePresence(uuid);
6403 if (presence != null)
6404 {
6405 if (presence.IsChildAgent)
6406 return new LSL_Integer(0);
6407
6408 IClientAPI client = presence.ControllingClient;
6409 if (m_host.ParentGroup.RootPart.GroupID == client.ActiveGroupId)
6410 return new LSL_Integer(1);
6411
6412 return new LSL_Integer(0);
6413 }
6414
6415 // Handle object case
6416 SceneObjectPart part = World.GetSceneObjectPart(uuid);
6417 if (part != null)
6418 {
6419 // This will handle both deed and non-deed and also the no
6420 // group case
6421 if (part.ParentGroup.RootPart.GroupID == m_host.ParentGroup.RootPart.GroupID)
6422 return new LSL_Integer(1);
6423
5947 return new LSL_Integer(0); 6424 return new LSL_Integer(0);
6425 }
6426
6427 return new LSL_Integer(0);
5948 } 6428 }
5949 6429
5950 public void llUnSit(string id) 6430 public void llUnSit(string id)
@@ -6069,7 +6549,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6069 return m_host.ParentGroup.AttachmentPoint; 6549 return m_host.ParentGroup.AttachmentPoint;
6070 } 6550 }
6071 6551
6072 public LSL_Integer llGetFreeMemory() 6552 public virtual LSL_Integer llGetFreeMemory()
6073 { 6553 {
6074 m_host.AddScriptLPS(1); 6554 m_host.AddScriptLPS(1);
6075 // Make scripts designed for LSO happy 6555 // Make scripts designed for LSO happy
@@ -6501,6 +6981,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6501 6981
6502 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot) 6982 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot)
6503 { 6983 {
6984 // LSL quaternions can normalize to 0, normal Quaternions can't.
6985 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
6986 rot.s = 1; // ZERO_ROTATION = 0,0,0,1
6987
6504 part.SitTargetPosition = offset; 6988 part.SitTargetPosition = offset;
6505 part.SitTargetOrientation = rot; 6989 part.SitTargetOrientation = rot;
6506 part.ParentGroup.HasGroupChanged = true; 6990 part.ParentGroup.HasGroupChanged = true;
@@ -6686,30 +7170,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6686 UUID av = new UUID(); 7170 UUID av = new UUID();
6687 if (!UUID.TryParse(avatar,out av)) 7171 if (!UUID.TryParse(avatar,out av))
6688 { 7172 {
6689 LSLError("First parameter to llDialog needs to be a key"); 7173 //LSLError("First parameter to llDialog needs to be a key");
6690 return; 7174 return;
6691 } 7175 }
6692 if (buttons.Length < 1) 7176 if (buttons.Length < 1)
6693 { 7177 {
6694 LSLError("No less than 1 button can be shown"); 7178 buttons.Add("OK");
6695 return;
6696 } 7179 }
6697 if (buttons.Length > 12) 7180 if (buttons.Length > 12)
6698 { 7181 {
6699 LSLError("No more than 12 buttons can be shown"); 7182 ShoutError("button list too long, must be 12 or fewer entries");
6700 return;
6701 } 7183 }
6702 string[] buts = new string[buttons.Length]; 7184 int length = buttons.Length;
6703 for (int i = 0; i < buttons.Length; i++) 7185 if (length > 12)
7186 length = 12;
7187
7188 string[] buts = new string[length];
7189 for (int i = 0; i < length; i++)
6704 { 7190 {
6705 if (buttons.Data[i].ToString() == String.Empty) 7191 if (buttons.Data[i].ToString() == String.Empty)
6706 { 7192 {
6707 LSLError("button label cannot be blank"); 7193 ShoutError("button label cannot be blank");
6708 return; 7194 return;
6709 } 7195 }
6710 if (buttons.Data[i].ToString().Length > 24) 7196 if (buttons.Data[i].ToString().Length > 24)
6711 { 7197 {
6712 LSLError("button label cannot be longer than 24 characters"); 7198 ShoutError("button label cannot be longer than 24 characters");
6713 return; 7199 return;
6714 } 7200 }
6715 buts[i] = buttons.Data[i].ToString(); 7201 buts[i] = buttons.Data[i].ToString();
@@ -6776,9 +7262,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6776 return; 7262 return;
6777 } 7263 }
6778 7264
6779 // the rest of the permission checks are done in RezScript, so check the pin there as well 7265 SceneObjectPart dest = World.GetSceneObjectPart(destId);
6780 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); 7266 if (dest != null)
7267 {
7268 if ((item.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7269 {
7270 // the rest of the permission checks are done in RezScript, so check the pin there as well
7271 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
6781 7272
7273 if ((item.BasePermissions & (uint)PermissionMask.Copy) == 0)
7274 m_host.Inventory.RemoveInventoryItem(item.ItemID);
7275 }
7276 }
6782 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7277 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6783 ScriptSleep(3000); 7278 ScriptSleep(3000);
6784 } 7279 }
@@ -6852,19 +7347,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6852 public LSL_String llMD5String(string src, int nonce) 7347 public LSL_String llMD5String(string src, int nonce)
6853 { 7348 {
6854 m_host.AddScriptLPS(1); 7349 m_host.AddScriptLPS(1);
6855 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7350 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
6856 } 7351 }
6857 7352
6858 public LSL_String llSHA1String(string src) 7353 public LSL_String llSHA1String(string src)
6859 { 7354 {
6860 m_host.AddScriptLPS(1); 7355 m_host.AddScriptLPS(1);
6861 return Util.SHA1Hash(src).ToLower(); 7356 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
6862 } 7357 }
6863 7358
6864 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7359 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6865 { 7360 {
6866 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7361 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6867 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7362 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7363 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7364 return shapeBlock;
6868 7365
6869 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7366 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
6870 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7367 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -6969,6 +7466,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6969 // Prim type box, cylinder and prism. 7466 // Prim type box, cylinder and prism.
6970 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) 7467 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)
6971 { 7468 {
7469 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7470 return;
7471
6972 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7472 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6973 ObjectShapePacket.ObjectDataBlock shapeBlock; 7473 ObjectShapePacket.ObjectDataBlock shapeBlock;
6974 7474
@@ -7022,6 +7522,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7022 // Prim type sphere. 7522 // Prim type sphere.
7023 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7523 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
7024 { 7524 {
7525 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7526 return;
7527
7025 ObjectShapePacket.ObjectDataBlock shapeBlock; 7528 ObjectShapePacket.ObjectDataBlock shapeBlock;
7026 7529
7027 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7530 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -7063,6 +7566,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7063 // Prim type torus, tube and ring. 7566 // Prim type torus, tube and ring.
7064 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) 7567 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)
7065 { 7568 {
7569 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7570 return;
7571
7066 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7572 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7067 ObjectShapePacket.ObjectDataBlock shapeBlock; 7573 ObjectShapePacket.ObjectDataBlock shapeBlock;
7068 7574
@@ -7198,6 +7704,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7198 // Prim type sculpt. 7704 // Prim type sculpt.
7199 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7705 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7200 { 7706 {
7707 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7708 return;
7709
7201 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7710 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7202 UUID sculptId; 7711 UUID sculptId;
7203 7712
@@ -7220,7 +7729,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7220 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7729 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7221 { 7730 {
7222 // default 7731 // default
7223 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7732 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7224 } 7733 }
7225 7734
7226 part.Shape.SetSculptProperties((byte)type, sculptId); 7735 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7237,48 +7746,130 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7237 ScriptSleep(200); 7746 ScriptSleep(200);
7238 } 7747 }
7239 7748
7240 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7749 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7241 { 7750 {
7242 m_host.AddScriptLPS(1); 7751 m_host.AddScriptLPS(1);
7243 7752
7244 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); 7753 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
7754 }
7245 7755
7246 ScriptSleep(200); 7756 private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
7757 {
7758 List<object> parts = new List<object>();
7759 List<SceneObjectPart> prims = GetLinkParts(linknumber);
7760 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7761 foreach (SceneObjectPart p in prims)
7762 parts.Add(p);
7763 foreach (ScenePresence p in avatars)
7764 parts.Add(p);
7765
7766 LSL_List remaining = null;
7767 uint rulesParsed = 0;
7768
7769 if (parts.Count > 0)
7770 {
7771 foreach (object part in parts)
7772 {
7773 if (part is SceneObjectPart)
7774 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7775 else
7776 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7777 }
7778
7779 while ((object)remaining != null && remaining.Length > 2)
7780 {
7781 linknumber = remaining.GetLSLIntegerItem(0);
7782 rules = remaining.GetSublist(1, -1);
7783 parts.Clear();
7784 prims = GetLinkParts(linknumber);
7785 avatars = GetLinkAvatars(linknumber);
7786 foreach (SceneObjectPart p in prims)
7787 parts.Add(p);
7788 foreach (ScenePresence p in avatars)
7789 parts.Add(p);
7790
7791 remaining = null;
7792 foreach (object part in parts)
7793 {
7794 if (part is SceneObjectPart)
7795 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7796 else
7797 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7798 }
7799 }
7800 }
7247 } 7801 }
7248 7802
7249 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7803 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
7804 float material_density, float material_friction,
7805 float material_restitution, float material_gravity_modifier)
7250 { 7806 {
7251 m_host.AddScriptLPS(1); 7807 ExtraPhysicsData physdata = new ExtraPhysicsData();
7808 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7809 physdata.Density = part.Density;
7810 physdata.Friction = part.Friction;
7811 physdata.Bounce = part.Restitution;
7812 physdata.GravitationModifier = part.GravityModifier;
7252 7813
7253 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); 7814 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
7815 physdata.Density = material_density;
7816 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
7817 physdata.Friction = material_friction;
7818 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
7819 physdata.Bounce = material_restitution;
7820 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
7821 physdata.GravitationModifier = material_gravity_modifier;
7822
7823 part.UpdateExtraPhysics(physdata);
7254 } 7824 }
7255 7825
7256 protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) 7826 public void llSetPhysicsMaterial(int material_bits,
7827 float material_gravity_modifier, float material_restitution,
7828 float material_friction, float material_density)
7257 { 7829 {
7258 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7830 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
7831 }
7259 7832
7260 LSL_List remaining = null; 7833 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7261 uint rulesParsed = 0; 7834 {
7835 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
7836 llSetLinkPrimitiveParamsFast(linknumber, rules);
7837 ScriptSleep(200);
7838 }
7262 7839
7263 foreach (SceneObjectPart part in parts) 7840 // vector up using libomv (c&p from sop )
7264 remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); 7841 // vector up rotated by r
7842 private Vector3 Zrot(Quaternion r)
7843 {
7844 double x, y, z, m;
7265 7845
7266 while (remaining != null && remaining.Length > 2) 7846 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
7847 if (Math.Abs(1.0 - m) > 0.000001)
7267 { 7848 {
7268 linknumber = remaining.GetLSLIntegerItem(0); 7849 m = 1.0 / Math.Sqrt(m);
7269 rules = remaining.GetSublist(1, -1); 7850 r.X *= (float)m;
7270 parts = GetLinkParts(linknumber); 7851 r.Y *= (float)m;
7271 7852 r.Z *= (float)m;
7272 foreach (SceneObjectPart part in parts) 7853 r.W *= (float)m;
7273 remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed);
7274 } 7854 }
7855
7856 x = 2 * (r.X * r.Z + r.Y * r.W);
7857 y = 2 * (-r.X * r.W + r.Y * r.Z);
7858 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
7859
7860 return new Vector3((float)x, (float)y, (float)z);
7275 } 7861 }
7276 7862
7277 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) 7863 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
7278 { 7864 {
7865 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7866 return null;
7867
7279 int idx = 0; 7868 int idx = 0;
7280 int idxStart = 0; 7869 int idxStart = 0;
7281 7870
7871 SceneObjectGroup parentgrp = part.ParentGroup;
7872
7282 bool positionChanged = false; 7873 bool positionChanged = false;
7283 LSL_Vector currentPosition = GetPartLocalPos(part); 7874 LSL_Vector currentPosition = GetPartLocalPos(part);
7284 7875
@@ -7303,8 +7894,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7303 return null; 7894 return null;
7304 7895
7305 v=rules.GetVector3Item(idx++); 7896 v=rules.GetVector3Item(idx++);
7897 if (part.IsRoot && !part.ParentGroup.IsAttachment)
7898 currentPosition = GetSetPosTarget(part, v, currentPosition, true);
7899 else
7900 currentPosition = GetSetPosTarget(part, v, currentPosition, false);
7306 positionChanged = true; 7901 positionChanged = true;
7307 currentPosition = GetSetPosTarget(part, v, currentPosition);
7308 7902
7309 break; 7903 break;
7310 case (int)ScriptBaseClass.PRIM_SIZE: 7904 case (int)ScriptBaseClass.PRIM_SIZE:
@@ -7321,7 +7915,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7321 7915
7322 LSL_Rotation q = rules.GetQuaternionItem(idx++); 7916 LSL_Rotation q = rules.GetQuaternionItem(idx++);
7323 // try to let this work as in SL... 7917 // try to let this work as in SL...
7324 if (part.ParentID == 0) 7918 if (part.ParentID == 0 || (part.ParentGroup != null && part == part.ParentGroup.RootPart))
7325 { 7919 {
7326 // special case: If we are root, rotate complete SOG to new rotation 7920 // special case: If we are root, rotate complete SOG to new rotation
7327 SetRot(part, q); 7921 SetRot(part, q);
@@ -7581,7 +8175,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7581 return null; 8175 return null;
7582 8176
7583 string ph = rules.Data[idx++].ToString(); 8177 string ph = rules.Data[idx++].ToString();
7584 m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); 8178 parentgrp.ScriptSetPhantomStatus(ph.Equals("1"));
7585 8179
7586 break; 8180 break;
7587 8181
@@ -7615,12 +8209,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7615 8209
7616 break; 8210 break;
7617 8211
8212 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8213 if (remain < 5)
8214 return null;
8215
8216 int material_bits = rules.GetLSLIntegerItem(idx++);
8217 float material_density = (float)rules.GetLSLFloatItem(idx++);
8218 float material_friction = (float)rules.GetLSLFloatItem(idx++);
8219 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
8220 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
8221
8222 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8223
8224 break;
8225
7618 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8226 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7619 if (remain < 1) 8227 if (remain < 1)
7620 return null; 8228 return null;
7621 string temp = rules.Data[idx++].ToString(); 8229 string temp = rules.Data[idx++].ToString();
7622 8230
7623 m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); 8231 parentgrp.ScriptSetTemporaryStatus(temp.Equals("1"));
7624 8232
7625 break; 8233 break;
7626 8234
@@ -7694,14 +8302,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7694 if (part.ParentGroup.RootPart == part) 8302 if (part.ParentGroup.RootPart == part)
7695 { 8303 {
7696 SceneObjectGroup parent = part.ParentGroup; 8304 SceneObjectGroup parent = part.ParentGroup;
7697 parent.UpdateGroupPosition(currentPosition); 8305 Util.FireAndForget(delegate(object x) {
8306 parent.UpdateGroupPosition(currentPosition);
8307 });
7698 } 8308 }
7699 else 8309 else
7700 { 8310 {
7701 part.OffsetPosition = currentPosition; 8311 part.OffsetPosition = currentPosition;
7702 SceneObjectGroup parent = part.ParentGroup; 8312// SceneObjectGroup parent = part.ParentGroup;
7703 parent.HasGroupChanged = true; 8313// parent.HasGroupChanged = true;
7704 parent.ScheduleGroupForTerseUpdate(); 8314// parent.ScheduleGroupForTerseUpdate();
8315 part.ScheduleTerseUpdate();
7705 } 8316 }
7706 } 8317 }
7707 } 8318 }
@@ -7739,10 +8350,91 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7739 8350
7740 public LSL_String llXorBase64Strings(string str1, string str2) 8351 public LSL_String llXorBase64Strings(string str1, string str2)
7741 { 8352 {
7742 m_host.AddScriptLPS(1); 8353 string b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7743 Deprecated("llXorBase64Strings"); 8354
7744 ScriptSleep(300); 8355 ScriptSleep(300);
7745 return String.Empty; 8356 m_host.AddScriptLPS(1);
8357
8358 if (str1 == String.Empty)
8359 return String.Empty;
8360 if (str2 == String.Empty)
8361 return str1;
8362
8363 int len = str2.Length;
8364 if ((len % 4) != 0) // LL is EVIL!!!!
8365 {
8366 while (str2.EndsWith("="))
8367 str2 = str2.Substring(0, str2.Length - 1);
8368
8369 len = str2.Length;
8370 int mod = len % 4;
8371
8372 if (mod == 1)
8373 str2 = str2.Substring(0, str2.Length - 1);
8374 else if (mod == 2)
8375 str2 += "==";
8376 else if (mod == 3)
8377 str2 += "=";
8378 }
8379
8380 byte[] data1;
8381 byte[] data2;
8382 try
8383 {
8384 data1 = Convert.FromBase64String(str1);
8385 data2 = Convert.FromBase64String(str2);
8386 }
8387 catch (Exception)
8388 {
8389 return new LSL_String(String.Empty);
8390 }
8391
8392 // For cases where the decoded length of s2 is greater
8393 // than the decoded length of s1, simply perform a normal
8394 // decode and XOR
8395 //
8396 if (data2.Length >= data1.Length)
8397 {
8398 for (int pos = 0 ; pos < data1.Length ; pos++ )
8399 data1[pos] ^= data2[pos];
8400
8401 return Convert.ToBase64String(data1);
8402 }
8403
8404 // Remove padding
8405 while (str1.EndsWith("="))
8406 str1 = str1.Substring(0, str1.Length - 1);
8407 while (str2.EndsWith("="))
8408 str2 = str2.Substring(0, str2.Length - 1);
8409
8410 byte[] d1 = new byte[str1.Length];
8411 byte[] d2 = new byte[str2.Length];
8412
8413 for (int i = 0 ; i < str1.Length ; i++)
8414 {
8415 int idx = b64.IndexOf(str1.Substring(i, 1));
8416 if (idx == -1)
8417 idx = 0;
8418 d1[i] = (byte)idx;
8419 }
8420
8421 for (int i = 0 ; i < str2.Length ; i++)
8422 {
8423 int idx = b64.IndexOf(str2.Substring(i, 1));
8424 if (idx == -1)
8425 idx = 0;
8426 d2[i] = (byte)idx;
8427 }
8428
8429 string output = String.Empty;
8430
8431 for (int pos = 0 ; pos < d1.Length ; pos++)
8432 output += b64[d1[pos] ^ d2[pos % d2.Length]];
8433
8434 while (output.Length % 3 > 0)
8435 output += "=";
8436
8437 return output;
7746 } 8438 }
7747 8439
7748 public void llRemoteDataSetRegion() 8440 public void llRemoteDataSetRegion()
@@ -7866,8 +8558,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7866 public LSL_Integer llGetNumberOfPrims() 8558 public LSL_Integer llGetNumberOfPrims()
7867 { 8559 {
7868 m_host.AddScriptLPS(1); 8560 m_host.AddScriptLPS(1);
7869 8561 int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count;
7870 return m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount(); 8562
8563 return m_host.ParentGroup.PrimCount + avatarCount;
7871 } 8564 }
7872 8565
7873 /// <summary> 8566 /// <summary>
@@ -7882,55 +8575,114 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7882 m_host.AddScriptLPS(1); 8575 m_host.AddScriptLPS(1);
7883 UUID objID = UUID.Zero; 8576 UUID objID = UUID.Zero;
7884 LSL_List result = new LSL_List(); 8577 LSL_List result = new LSL_List();
8578
8579 // If the ID is not valid, return null result
7885 if (!UUID.TryParse(obj, out objID)) 8580 if (!UUID.TryParse(obj, out objID))
7886 { 8581 {
7887 result.Add(new LSL_Vector()); 8582 result.Add(new LSL_Vector());
7888 result.Add(new LSL_Vector()); 8583 result.Add(new LSL_Vector());
7889 return result; 8584 return result;
7890 } 8585 }
8586
8587 // Check if this is an attached prim. If so, replace
8588 // the UUID with the avatar UUID and report it's bounding box
8589 SceneObjectPart part = World.GetSceneObjectPart(objID);
8590 if (part != null && part.ParentGroup.IsAttachment)
8591 objID = part.ParentGroup.AttachedAvatar;
8592
8593 // Find out if this is an avatar ID. If so, return it's box
7891 ScenePresence presence = World.GetScenePresence(objID); 8594 ScenePresence presence = World.GetScenePresence(objID);
7892 if (presence != null) 8595 if (presence != null)
7893 { 8596 {
7894 if (presence.ParentID == 0) // not sat on an object 8597 // As per LSL Wiki, there is no difference between sitting
8598 // and standing avatar since server 1.36
8599 LSL_Vector lower;
8600 LSL_Vector upper;
8601
8602 Vector3 box = presence.Appearance.AvatarBoxSize * 0.5f;
8603
8604 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID
8605 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
8606/*
7895 { 8607 {
7896 LSL_Vector lower; 8608 // This is for ground sitting avatars
7897 LSL_Vector upper; 8609 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7898 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID 8610 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7899 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8611 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7900 {
7901 // This is for ground sitting avatars
7902 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7903 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7904 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7905 }
7906 else
7907 {
7908 // This is for standing/flying avatars
7909 float height = presence.Appearance.AvatarHeight / 2.0f;
7910 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7911 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7912 }
7913 result.Add(lower);
7914 result.Add(upper);
7915 return result;
7916 } 8612 }
7917 else 8613 else
7918 { 8614 {
7919 // sitting on an object so we need the bounding box of that 8615 // This is for standing/flying avatars
7920 // which should include the avatar so set the UUID to the 8616 float height = presence.Appearance.AvatarHeight / 2.0f;
7921 // UUID of the object the avatar is sat on and allow it to fall through 8617 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
7922 // to processing an object 8618 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
7923 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID);
7924 objID = p.UUID;
7925 } 8619 }
8620
8621 // Adjust to the documented error offsets (see LSL Wiki)
8622 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
8623 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
8624*/
8625 {
8626 // This is for ground sitting avatars TODO!
8627 lower = new LSL_Vector(-box.X - 0.1125, -box.Y, box.Z * -1.0f);
8628 upper = new LSL_Vector(box.X + 0.1125, box.Y, box.Z * -1.0f);
8629 }
8630 else
8631 {
8632 // This is for standing/flying avatars
8633 lower = new LSL_Vector(-box.X, -box.Y, -box.Z);
8634 upper = new LSL_Vector(box.X, box.Y, box.Z);
8635 }
8636
8637 if (lower.x > upper.x)
8638 lower.x = upper.x;
8639 if (lower.y > upper.y)
8640 lower.y = upper.y;
8641 if (lower.z > upper.z)
8642 lower.z = upper.z;
8643
8644 result.Add(lower);
8645 result.Add(upper);
8646 return result;
7926 } 8647 }
7927 SceneObjectPart part = World.GetSceneObjectPart(objID); 8648
8649 part = World.GetSceneObjectPart(objID);
7928 // Currently only works for single prims without a sitting avatar 8650 // Currently only works for single prims without a sitting avatar
7929 if (part != null) 8651 if (part != null)
7930 { 8652 {
7931 Vector3 halfSize = part.Scale / 2.0f; 8653 float minX;
7932 LSL_Vector lower = (new LSL_Vector(halfSize)) * -1.0f; 8654 float maxX;
7933 LSL_Vector upper = new LSL_Vector(halfSize); 8655 float minY;
8656 float maxY;
8657 float minZ;
8658 float maxZ;
8659
8660 // This BBox is in sim coordinates, with the offset being
8661 // a contained point.
8662 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
8663 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
8664
8665 minX -= offsets[0].X;
8666 maxX -= offsets[0].X;
8667 minY -= offsets[0].Y;
8668 maxY -= offsets[0].Y;
8669 minZ -= offsets[0].Z;
8670 maxZ -= offsets[0].Z;
8671
8672 LSL_Vector lower;
8673 LSL_Vector upper;
8674
8675 // Adjust to the documented error offsets (see LSL Wiki)
8676 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
8677 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
8678
8679 if (lower.x > upper.x)
8680 lower.x = upper.x;
8681 if (lower.y > upper.y)
8682 lower.y = upper.y;
8683 if (lower.z > upper.z)
8684 lower.z = upper.z;
8685
7934 result.Add(lower); 8686 result.Add(lower);
7935 result.Add(upper); 8687 result.Add(upper);
7936 return result; 8688 return result;
@@ -7944,7 +8696,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7944 8696
7945 public LSL_Vector llGetGeometricCenter() 8697 public LSL_Vector llGetGeometricCenter()
7946 { 8698 {
7947 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 8699 Vector3 tmp = m_host.GetGeometricCenter();
8700 return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
7948 } 8701 }
7949 8702
7950 public LSL_List llGetPrimitiveParams(LSL_List rules) 8703 public LSL_List llGetPrimitiveParams(LSL_List rules)
@@ -7955,7 +8708,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7955 8708
7956 LSL_List remaining = GetPrimParams(m_host, rules, ref result); 8709 LSL_List remaining = GetPrimParams(m_host, rules, ref result);
7957 8710
7958 while (remaining != null && remaining.Length > 2) 8711 while ((object)remaining != null && remaining.Length > 2)
7959 { 8712 {
7960 int linknumber = remaining.GetLSLIntegerItem(0); 8713 int linknumber = remaining.GetLSLIntegerItem(0);
7961 rules = remaining.GetSublist(1, -1); 8714 rules = remaining.GetSublist(1, -1);
@@ -7972,24 +8725,37 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7972 { 8725 {
7973 m_host.AddScriptLPS(1); 8726 m_host.AddScriptLPS(1);
7974 8727
7975 List<SceneObjectPart> parts = GetLinkParts(linknumber); 8728 // acording to SL wiki this must indicate a single link number or link_root or link_this.
8729 // keep other options as before
7976 8730
8731 List<SceneObjectPart> parts;
8732 List<ScenePresence> avatars;
8733
7977 LSL_List res = new LSL_List(); 8734 LSL_List res = new LSL_List();
7978 LSL_List remaining = null; 8735 LSL_List remaining = null;
7979 8736
7980 foreach (SceneObjectPart part in parts) 8737 while (rules.Length > 0)
7981 {
7982 remaining = GetPrimParams(part, rules, ref res);
7983 }
7984
7985 while (remaining != null && remaining.Length > 2)
7986 { 8738 {
7987 linknumber = remaining.GetLSLIntegerItem(0);
7988 rules = remaining.GetSublist(1, -1);
7989 parts = GetLinkParts(linknumber); 8739 parts = GetLinkParts(linknumber);
8740 avatars = GetLinkAvatars(linknumber);
7990 8741
8742 remaining = null;
7991 foreach (SceneObjectPart part in parts) 8743 foreach (SceneObjectPart part in parts)
8744 {
7992 remaining = GetPrimParams(part, rules, ref res); 8745 remaining = GetPrimParams(part, rules, ref res);
8746 }
8747 foreach (ScenePresence avatar in avatars)
8748 {
8749 remaining = GetPrimParams(avatar, rules, ref res);
8750 }
8751
8752 if ((object)remaining != null && remaining.Length > 0)
8753 {
8754 linknumber = remaining.GetLSLIntegerItem(0);
8755 rules = remaining.GetSublist(1, -1);
8756 }
8757 else
8758 break;
7993 } 8759 }
7994 8760
7995 return res; 8761 return res;
@@ -8034,13 +8800,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8034 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 8800 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
8035 part.AbsolutePosition.Y, 8801 part.AbsolutePosition.Y,
8036 part.AbsolutePosition.Z); 8802 part.AbsolutePosition.Z);
8037 // For some reason, the part.AbsolutePosition.* values do not change if the
8038 // linkset is rotated; they always reflect the child prim's world position
8039 // as though the linkset is unrotated. This is incompatible behavior with SL's
8040 // implementation, so will break scripts imported from there (not to mention it
8041 // makes it more difficult to determine a child prim's actual inworld position).
8042 if (part.ParentID != 0)
8043 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
8044 res.Add(v); 8803 res.Add(v);
8045 break; 8804 break;
8046 8805
@@ -8212,30 +8971,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8212 if (remain < 1) 8971 if (remain < 1)
8213 return null; 8972 return null;
8214 8973
8215 face=(int)rules.GetLSLIntegerItem(idx++); 8974 face = (int)rules.GetLSLIntegerItem(idx++);
8216 8975
8217 tex = part.Shape.Textures; 8976 tex = part.Shape.Textures;
8977 int shiny;
8218 if (face == ScriptBaseClass.ALL_SIDES) 8978 if (face == ScriptBaseClass.ALL_SIDES)
8219 { 8979 {
8220 for (face = 0; face < GetNumberOfSides(part); face++) 8980 for (face = 0; face < GetNumberOfSides(part); face++)
8221 { 8981 {
8222 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 8982 Shininess shinyness = tex.GetFace((uint)face).Shiny;
8223 // Convert Shininess to PRIM_SHINY_* 8983 if (shinyness == Shininess.High)
8224 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 8984 {
8225 // PRIM_BUMP_* 8985 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8226 res.Add(new LSL_Integer((int)texface.Bump)); 8986 }
8987 else if (shinyness == Shininess.Medium)
8988 {
8989 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
8990 }
8991 else if (shinyness == Shininess.Low)
8992 {
8993 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
8994 }
8995 else
8996 {
8997 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8998 }
8999 res.Add(new LSL_Integer(shiny));
9000 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8227 } 9001 }
8228 } 9002 }
8229 else 9003 else
8230 { 9004 {
8231 if (face >= 0 && face < GetNumberOfSides(part)) 9005 Shininess shinyness = tex.GetFace((uint)face).Shiny;
9006 if (shinyness == Shininess.High)
8232 { 9007 {
8233 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9008 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
8234 // Convert Shininess to PRIM_SHINY_* 9009 }
8235 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 9010 else if (shinyness == Shininess.Medium)
8236 // PRIM_BUMP_* 9011 {
8237 res.Add(new LSL_Integer((int)texface.Bump)); 9012 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
9013 }
9014 else if (shinyness == Shininess.Low)
9015 {
9016 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
9017 }
9018 else
9019 {
9020 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
8238 } 9021 }
9022 res.Add(new LSL_Integer(shiny));
9023 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
8239 } 9024 }
8240 break; 9025 break;
8241 9026
@@ -8243,24 +9028,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8243 if (remain < 1) 9028 if (remain < 1)
8244 return null; 9029 return null;
8245 9030
8246 face=(int)rules.GetLSLIntegerItem(idx++); 9031 face = (int)rules.GetLSLIntegerItem(idx++);
8247 9032
8248 tex = part.Shape.Textures; 9033 tex = part.Shape.Textures;
9034 int fullbright;
8249 if (face == ScriptBaseClass.ALL_SIDES) 9035 if (face == ScriptBaseClass.ALL_SIDES)
8250 { 9036 {
8251 for (face = 0; face < GetNumberOfSides(part); face++) 9037 for (face = 0; face < GetNumberOfSides(part); face++)
8252 { 9038 {
8253 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9039 if (tex.GetFace((uint)face).Fullbright == true)
8254 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 9040 {
9041 fullbright = ScriptBaseClass.TRUE;
9042 }
9043 else
9044 {
9045 fullbright = ScriptBaseClass.FALSE;
9046 }
9047 res.Add(new LSL_Integer(fullbright));
8255 } 9048 }
8256 } 9049 }
8257 else 9050 else
8258 { 9051 {
8259 if (face >= 0 && face < GetNumberOfSides(part)) 9052 if (tex.GetFace((uint)face).Fullbright == true)
8260 { 9053 {
8261 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9054 fullbright = ScriptBaseClass.TRUE;
8262 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 9055 }
9056 else
9057 {
9058 fullbright = ScriptBaseClass.FALSE;
8263 } 9059 }
9060 res.Add(new LSL_Integer(fullbright));
8264 } 9061 }
8265 break; 9062 break;
8266 9063
@@ -8282,27 +9079,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8282 break; 9079 break;
8283 9080
8284 case (int)ScriptBaseClass.PRIM_TEXGEN: 9081 case (int)ScriptBaseClass.PRIM_TEXGEN:
9082 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
8285 if (remain < 1) 9083 if (remain < 1)
8286 return null; 9084 return null;
8287 9085
8288 face=(int)rules.GetLSLIntegerItem(idx++); 9086 face = (int)rules.GetLSLIntegerItem(idx++);
8289 9087
8290 tex = part.Shape.Textures; 9088 tex = part.Shape.Textures;
8291 if (face == ScriptBaseClass.ALL_SIDES) 9089 if (face == ScriptBaseClass.ALL_SIDES)
8292 { 9090 {
8293 for (face = 0; face < GetNumberOfSides(part); face++) 9091 for (face = 0; face < GetNumberOfSides(part); face++)
8294 { 9092 {
8295 MappingType texgen = tex.GetFace((uint)face).TexMapType; 9093 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8296 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 9094 {
8297 res.Add(new LSL_Integer((uint)texgen >> 1)); 9095 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
9096 }
9097 else
9098 {
9099 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
9100 }
8298 } 9101 }
8299 } 9102 }
8300 else 9103 else
8301 { 9104 {
8302 if (face >= 0 && face < GetNumberOfSides(part)) 9105 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
8303 { 9106 {
8304 MappingType texgen = tex.GetFace((uint)face).TexMapType; 9107 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
8305 res.Add(new LSL_Integer((uint)texgen >> 1)); 9108 }
9109 else
9110 {
9111 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
8306 } 9112 }
8307 } 9113 }
8308 break; 9114 break;
@@ -8326,24 +9132,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8326 if (remain < 1) 9132 if (remain < 1)
8327 return null; 9133 return null;
8328 9134
8329 face=(int)rules.GetLSLIntegerItem(idx++); 9135 face = (int)rules.GetLSLIntegerItem(idx++);
8330 9136
8331 tex = part.Shape.Textures; 9137 tex = part.Shape.Textures;
9138 float primglow;
8332 if (face == ScriptBaseClass.ALL_SIDES) 9139 if (face == ScriptBaseClass.ALL_SIDES)
8333 { 9140 {
8334 for (face = 0; face < GetNumberOfSides(part); face++) 9141 for (face = 0; face < GetNumberOfSides(part); face++)
8335 { 9142 {
8336 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 9143 primglow = tex.GetFace((uint)face).Glow;
8337 res.Add(new LSL_Float(texface.Glow)); 9144 res.Add(new LSL_Float(primglow));
8338 } 9145 }
8339 } 9146 }
8340 else 9147 else
8341 { 9148 {
8342 if (face >= 0 && face < GetNumberOfSides(part)) 9149 primglow = tex.GetFace((uint)face).Glow;
8343 { 9150 res.Add(new LSL_Float(primglow));
8344 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
8345 res.Add(new LSL_Float(texface.Glow));
8346 }
8347 } 9151 }
8348 break; 9152 break;
8349 9153
@@ -8355,15 +9159,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8355 textColor.B)); 9159 textColor.B));
8356 res.Add(new LSL_Float(textColor.A)); 9160 res.Add(new LSL_Float(textColor.A));
8357 break; 9161 break;
9162
8358 case (int)ScriptBaseClass.PRIM_NAME: 9163 case (int)ScriptBaseClass.PRIM_NAME:
8359 res.Add(new LSL_String(part.Name)); 9164 res.Add(new LSL_String(part.Name));
8360 break; 9165 break;
9166
8361 case (int)ScriptBaseClass.PRIM_DESC: 9167 case (int)ScriptBaseClass.PRIM_DESC:
8362 res.Add(new LSL_String(part.Description)); 9168 res.Add(new LSL_String(part.Description));
8363 break; 9169 break;
9170
8364 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 9171 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8365 res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); 9172 res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W));
8366 break; 9173 break;
9174
8367 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 9175 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
8368 res.Add(new LSL_Vector(GetPartLocalPos(part))); 9176 res.Add(new LSL_Vector(GetPartLocalPos(part)));
8369 break; 9177 break;
@@ -8974,8 +9782,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8974 // The function returns an ordered list 9782 // The function returns an ordered list
8975 // representing the tokens found in the supplied 9783 // representing the tokens found in the supplied
8976 // sources string. If two successive tokenizers 9784 // sources string. If two successive tokenizers
8977 // are encountered, then a NULL entry is added 9785 // are encountered, then a null-string entry is
8978 // to the list. 9786 // added to the list.
8979 // 9787 //
8980 // It is a precondition that the source and 9788 // It is a precondition that the source and
8981 // toekizer lisst are non-null. If they are null, 9789 // toekizer lisst are non-null. If they are null,
@@ -8983,7 +9791,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8983 // while their lengths are being determined. 9791 // while their lengths are being determined.
8984 // 9792 //
8985 // A small amount of working memoryis required 9793 // A small amount of working memoryis required
8986 // of approximately 8*#tokenizers. 9794 // of approximately 8*#tokenizers + 8*srcstrlen.
8987 // 9795 //
8988 // There are many ways in which this function 9796 // There are many ways in which this function
8989 // can be implemented, this implementation is 9797 // can be implemented, this implementation is
@@ -8999,155 +9807,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8999 // and eliminates redundant tokenizers as soon 9807 // and eliminates redundant tokenizers as soon
9000 // as is possible. 9808 // as is possible.
9001 // 9809 //
9002 // The implementation tries to avoid any copying 9810 // The implementation tries to minimize temporary
9003 // of arrays or other objects. 9811 // garbage generation.
9004 // </remarks> 9812 // </remarks>
9005 9813
9006 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 9814 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
9007 { 9815 {
9008 int beginning = 0; 9816 return ParseString2List(src, separators, spacers, true);
9009 int srclen = src.Length; 9817 }
9010 int seplen = separators.Length;
9011 object[] separray = separators.Data;
9012 int spclen = spacers.Length;
9013 object[] spcarray = spacers.Data;
9014 int mlen = seplen+spclen;
9015
9016 int[] offset = new int[mlen+1];
9017 bool[] active = new bool[mlen];
9018
9019 int best;
9020 int j;
9021
9022 // Initial capacity reduces resize cost
9023 9818
9024 LSL_List tokens = new LSL_List(); 9819 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
9820 {
9821 int srclen = src.Length;
9822 int seplen = separators.Length;
9823 object[] separray = separators.Data;
9824 int spclen = spacers.Length;
9825 object[] spcarray = spacers.Data;
9826 int dellen = 0;
9827 string[] delarray = new string[seplen+spclen];
9025 9828
9026 // All entries are initially valid 9829 int outlen = 0;
9830 string[] outarray = new string[srclen*2+1];
9027 9831
9028 for (int i = 0; i < mlen; i++) 9832 int i, j;
9029 active[i] = true; 9833 string d;
9030 9834
9031 offset[mlen] = srclen; 9835 m_host.AddScriptLPS(1);
9032 9836
9033 while (beginning < srclen) 9837 /*
9838 * Convert separator and spacer lists to C# strings.
9839 * Also filter out null strings so we don't hang.
9840 */
9841 for (i = 0; i < seplen; i ++)
9034 { 9842 {
9843 d = separray[i].ToString();
9844 if (d.Length > 0)
9845 {
9846 delarray[dellen++] = d;
9847 }
9848 }
9849 seplen = dellen;
9035 9850
9036 best = mlen; // as bad as it gets 9851 for (i = 0; i < spclen; i ++)
9852 {
9853 d = spcarray[i].ToString();
9854 if (d.Length > 0)
9855 {
9856 delarray[dellen++] = d;
9857 }
9858 }
9037 9859
9038 // Scan for separators 9860 /*
9861 * Scan through source string from beginning to end.
9862 */
9863 for (i = 0;;)
9864 {
9039 9865
9040 for (j = 0; j < seplen; j++) 9866 /*
9867 * Find earliest delimeter in src starting at i (if any).
9868 */
9869 int earliestDel = -1;
9870 int earliestSrc = srclen;
9871 string earliestStr = null;
9872 for (j = 0; j < dellen; j ++)
9041 { 9873 {
9042 if (separray[j].ToString() == String.Empty) 9874 d = delarray[j];
9043 active[j] = false; 9875 if (d != null)
9044
9045 if (active[j])
9046 { 9876 {
9047 // scan all of the markers 9877 int index = src.IndexOf(d, i);
9048 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 9878 if (index < 0)
9049 { 9879 {
9050 // not present at all 9880 delarray[j] = null; // delim nowhere in src, don't check it anymore
9051 active[j] = false;
9052 } 9881 }
9053 else 9882 else if (index < earliestSrc)
9054 { 9883 {
9055 // present and correct 9884 earliestSrc = index; // where delimeter starts in source string
9056 if (offset[j] < offset[best]) 9885 earliestDel = j; // where delimeter is in delarray[]
9057 { 9886 earliestStr = d; // the delimeter string from delarray[]
9058 // closest so far 9887 if (index == i) break; // can't do any better than found at beg of string
9059 best = j;
9060 if (offset[best] == beginning)
9061 break;
9062 }
9063 } 9888 }
9064 } 9889 }
9065 } 9890 }
9066 9891
9067 // Scan for spacers 9892 /*
9068 9893 * Output source string starting at i through start of earliest delimeter.
9069 if (offset[best] != beginning) 9894 */
9895 if (keepNulls || (earliestSrc > i))
9070 { 9896 {
9071 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 9897 outarray[outlen++] = src.Substring(i, earliestSrc - i);
9072 {
9073 if (spcarray[j-seplen].ToString() == String.Empty)
9074 active[j] = false;
9075
9076 if (active[j])
9077 {
9078 // scan all of the markers
9079 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
9080 {
9081 // not present at all
9082 active[j] = false;
9083 }
9084 else
9085 {
9086 // present and correct
9087 if (offset[j] < offset[best])
9088 {
9089 // closest so far
9090 best = j;
9091 }
9092 }
9093 }
9094 }
9095 } 9898 }
9096 9899
9097 // This is the normal exit from the scanning loop 9900 /*
9901 * If no delimeter found at or after i, we're done scanning.
9902 */
9903 if (earliestDel < 0) break;
9098 9904
9099 if (best == mlen) 9905 /*
9906 * If delimeter was a spacer, output the spacer.
9907 */
9908 if (earliestDel >= seplen)
9100 { 9909 {
9101 // no markers were found on this pass 9910 outarray[outlen++] = earliestStr;
9102 // so we're pretty much done
9103 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
9104 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
9105 break;
9106 } 9911 }
9107 9912
9108 // Otherwise we just add the newly delimited token 9913 /*
9109 // and recalculate where the search should continue. 9914 * Look at rest of src string following delimeter.
9110 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 9915 */
9111 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 9916 i = earliestSrc + earliestStr.Length;
9112
9113 if (best < seplen)
9114 {
9115 beginning = offset[best] + (separray[best].ToString()).Length;
9116 }
9117 else
9118 {
9119 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
9120 string str = spcarray[best - seplen].ToString();
9121 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
9122 tokens.Add(new LSL_String(str));
9123 }
9124 } 9917 }
9125 9918
9126 // This an awkward an not very intuitive boundary case. If the 9919 /*
9127 // last substring is a tokenizer, then there is an implied trailing 9920 * Make up an exact-sized output array suitable for an LSL_List object.
9128 // null list entry. Hopefully the single comparison will not be too 9921 */
9129 // arduous. Alternatively the 'break' could be replced with a return 9922 object[] outlist = new object[outlen];
9130 // but that's shabby programming. 9923 for (i = 0; i < outlen; i ++)
9131
9132 if ((beginning == srclen) && (keepNulls))
9133 { 9924 {
9134 if (srclen != 0) 9925 outlist[i] = new LSL_String(outarray[i]);
9135 tokens.Add(new LSL_String(""));
9136 } 9926 }
9137 9927 return new LSL_List(outlist);
9138 return tokens;
9139 }
9140
9141 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
9142 {
9143 m_host.AddScriptLPS(1);
9144 return this.ParseString(src, separators, spacers, false);
9145 }
9146
9147 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
9148 {
9149 m_host.AddScriptLPS(1);
9150 return this.ParseString(src, separators, spacers, true);
9151 } 9928 }
9152 9929
9153 public LSL_Integer llGetObjectPermMask(int mask) 9930 public LSL_Integer llGetObjectPermMask(int mask)
@@ -9242,6 +10019,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9242 case 4: 10019 case 4:
9243 return (int)item.NextPermissions; 10020 return (int)item.NextPermissions;
9244 } 10021 }
10022 m_host.TaskInventory.LockItemsForRead(false);
9245 10023
9246 return -1; 10024 return -1;
9247 } 10025 }
@@ -9445,31 +10223,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9445 UUID key = new UUID(); 10223 UUID key = new UUID();
9446 if (UUID.TryParse(id, out key)) 10224 if (UUID.TryParse(id, out key))
9447 { 10225 {
9448 try 10226 // return total object mass
9449 { 10227 SceneObjectPart part = World.GetSceneObjectPart(key);
9450 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 10228 if (part != null)
9451 if (obj != null) 10229 return part.ParentGroup.GetMass();
9452 return (double)obj.GetMass(); 10230
9453 // the object is null so the key is for an avatar 10231 // the object is null so the key is for an avatar
9454 ScenePresence avatar = World.GetScenePresence(key); 10232 ScenePresence avatar = World.GetScenePresence(key);
9455 if (avatar != null) 10233 if (avatar != null)
9456 if (avatar.IsChildAgent)
9457 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
9458 // child agents have a mass of 1.0
9459 return 1;
9460 else
9461 return (double)avatar.GetMass();
9462 }
9463 catch (KeyNotFoundException)
9464 { 10234 {
9465 return 0; // The Object/Agent not in the region so just return zero 10235 if (avatar.IsChildAgent)
10236 {
10237 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
10238 // child agents have a mass of 1.0
10239 return 1;
10240 }
10241 else
10242 {
10243 return (double)avatar.GetMass();
10244 }
9466 } 10245 }
9467 } 10246 }
9468 return 0; 10247 return 0;
9469 } 10248 }
9470 10249
9471 /// <summary> 10250 /// <summary>
9472 /// illListReplaceList removes the sub-list defined by the inclusive indices 10251 /// llListReplaceList removes the sub-list defined by the inclusive indices
9473 /// start and end and inserts the src list in its place. The inclusive 10252 /// start and end and inserts the src list in its place. The inclusive
9474 /// nature of the indices means that at least one element must be deleted 10253 /// nature of the indices means that at least one element must be deleted
9475 /// if the indices are within the bounds of the existing list. I.e. 2,2 10254 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -9526,16 +10305,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9526 // based upon end. Note that if end exceeds the upper 10305 // based upon end. Note that if end exceeds the upper
9527 // bound in this case, the entire destination list 10306 // bound in this case, the entire destination list
9528 // is removed. 10307 // is removed.
9529 else 10308 else if (start == 0)
9530 { 10309 {
9531 if (end + 1 < dest.Length) 10310 if (end + 1 < dest.Length)
9532 {
9533 return src + dest.GetSublist(end + 1, -1); 10311 return src + dest.GetSublist(end + 1, -1);
9534 }
9535 else 10312 else
9536 {
9537 return src; 10313 return src;
9538 } 10314 }
10315 else // Start < 0
10316 {
10317 if (end + 1 < dest.Length)
10318 return dest.GetSublist(end + 1, -1);
10319 else
10320 return new LSL_List();
9539 } 10321 }
9540 } 10322 }
9541 // Finally, if start > end, we strip away a prefix and 10323 // Finally, if start > end, we strip away a prefix and
@@ -9586,17 +10368,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9586 int width = 0; 10368 int width = 0;
9587 int height = 0; 10369 int height = 0;
9588 10370
9589 ParcelMediaCommandEnum? commandToSend = null; 10371 uint commandToSend = 0;
9590 float time = 0.0f; // default is from start 10372 float time = 0.0f; // default is from start
9591 10373
9592 ScenePresence presence = null; 10374 ScenePresence presence = null;
9593 10375
9594 for (int i = 0; i < commandList.Data.Length; i++) 10376 for (int i = 0; i < commandList.Data.Length; i++)
9595 { 10377 {
9596 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 10378 uint command = (uint)(commandList.GetLSLIntegerItem(i));
9597 switch (command) 10379 switch (command)
9598 { 10380 {
9599 case ParcelMediaCommandEnum.Agent: 10381 case (uint)ParcelMediaCommandEnum.Agent:
9600 // we send only to one agent 10382 // we send only to one agent
9601 if ((i + 1) < commandList.Length) 10383 if ((i + 1) < commandList.Length)
9602 { 10384 {
@@ -9613,25 +10395,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9613 } 10395 }
9614 break; 10396 break;
9615 10397
9616 case ParcelMediaCommandEnum.Loop: 10398 case (uint)ParcelMediaCommandEnum.Loop:
9617 loop = 1; 10399 loop = 1;
9618 commandToSend = command; 10400 commandToSend = command;
9619 update = true; //need to send the media update packet to set looping 10401 update = true; //need to send the media update packet to set looping
9620 break; 10402 break;
9621 10403
9622 case ParcelMediaCommandEnum.Play: 10404 case (uint)ParcelMediaCommandEnum.Play:
9623 loop = 0; 10405 loop = 0;
9624 commandToSend = command; 10406 commandToSend = command;
9625 update = true; //need to send the media update packet to make sure it doesn't loop 10407 update = true; //need to send the media update packet to make sure it doesn't loop
9626 break; 10408 break;
9627 10409
9628 case ParcelMediaCommandEnum.Pause: 10410 case (uint)ParcelMediaCommandEnum.Pause:
9629 case ParcelMediaCommandEnum.Stop: 10411 case (uint)ParcelMediaCommandEnum.Stop:
9630 case ParcelMediaCommandEnum.Unload: 10412 case (uint)ParcelMediaCommandEnum.Unload:
9631 commandToSend = command; 10413 commandToSend = command;
9632 break; 10414 break;
9633 10415
9634 case ParcelMediaCommandEnum.Url: 10416 case (uint)ParcelMediaCommandEnum.Url:
9635 if ((i + 1) < commandList.Length) 10417 if ((i + 1) < commandList.Length)
9636 { 10418 {
9637 if (commandList.Data[i + 1] is LSL_String) 10419 if (commandList.Data[i + 1] is LSL_String)
@@ -9644,7 +10426,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9644 } 10426 }
9645 break; 10427 break;
9646 10428
9647 case ParcelMediaCommandEnum.Texture: 10429 case (uint)ParcelMediaCommandEnum.Texture:
9648 if ((i + 1) < commandList.Length) 10430 if ((i + 1) < commandList.Length)
9649 { 10431 {
9650 if (commandList.Data[i + 1] is LSL_String) 10432 if (commandList.Data[i + 1] is LSL_String)
@@ -9657,7 +10439,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9657 } 10439 }
9658 break; 10440 break;
9659 10441
9660 case ParcelMediaCommandEnum.Time: 10442 case (uint)ParcelMediaCommandEnum.Time:
9661 if ((i + 1) < commandList.Length) 10443 if ((i + 1) < commandList.Length)
9662 { 10444 {
9663 if (commandList.Data[i + 1] is LSL_Float) 10445 if (commandList.Data[i + 1] is LSL_Float)
@@ -9669,7 +10451,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9669 } 10451 }
9670 break; 10452 break;
9671 10453
9672 case ParcelMediaCommandEnum.AutoAlign: 10454 case (uint)ParcelMediaCommandEnum.AutoAlign:
9673 if ((i + 1) < commandList.Length) 10455 if ((i + 1) < commandList.Length)
9674 { 10456 {
9675 if (commandList.Data[i + 1] is LSL_Integer) 10457 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9683,7 +10465,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9683 } 10465 }
9684 break; 10466 break;
9685 10467
9686 case ParcelMediaCommandEnum.Type: 10468 case (uint)ParcelMediaCommandEnum.Type:
9687 if ((i + 1) < commandList.Length) 10469 if ((i + 1) < commandList.Length)
9688 { 10470 {
9689 if (commandList.Data[i + 1] is LSL_String) 10471 if (commandList.Data[i + 1] is LSL_String)
@@ -9696,7 +10478,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9696 } 10478 }
9697 break; 10479 break;
9698 10480
9699 case ParcelMediaCommandEnum.Desc: 10481 case (uint)ParcelMediaCommandEnum.Desc:
9700 if ((i + 1) < commandList.Length) 10482 if ((i + 1) < commandList.Length)
9701 { 10483 {
9702 if (commandList.Data[i + 1] is LSL_String) 10484 if (commandList.Data[i + 1] is LSL_String)
@@ -9709,7 +10491,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9709 } 10491 }
9710 break; 10492 break;
9711 10493
9712 case ParcelMediaCommandEnum.Size: 10494 case (uint)ParcelMediaCommandEnum.Size:
9713 if ((i + 2) < commandList.Length) 10495 if ((i + 2) < commandList.Length)
9714 { 10496 {
9715 if (commandList.Data[i + 1] is LSL_Integer) 10497 if (commandList.Data[i + 1] is LSL_Integer)
@@ -9779,7 +10561,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9779 } 10561 }
9780 } 10562 }
9781 10563
9782 if (commandToSend != null) 10564 if (commandToSend != 0)
9783 { 10565 {
9784 // the commandList contained a start/stop/... command, too 10566 // the commandList contained a start/stop/... command, too
9785 if (presence == null) 10567 if (presence == null)
@@ -9816,7 +10598,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9816 10598
9817 if (aList.Data[i] != null) 10599 if (aList.Data[i] != null)
9818 { 10600 {
9819 switch ((ParcelMediaCommandEnum) aList.Data[i]) 10601 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
9820 { 10602 {
9821 case ParcelMediaCommandEnum.Url: 10603 case ParcelMediaCommandEnum.Url:
9822 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); 10604 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL));
@@ -9873,15 +10655,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9873 10655
9874 if (quick_pay_buttons.Data.Length < 4) 10656 if (quick_pay_buttons.Data.Length < 4)
9875 { 10657 {
9876 LSLError("List must have at least 4 elements"); 10658 int x;
9877 return; 10659 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
10660 {
10661 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
10662 }
9878 } 10663 }
9879 m_host.ParentGroup.RootPart.PayPrice[0]=price; 10664 int[] nPrice = new int[5];
9880 10665 nPrice[0] = price;
9881 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 10666 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
9882 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 10667 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
9883 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 10668 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
9884 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 10669 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
10670 m_host.ParentGroup.RootPart.PayPrice = nPrice;
9885 m_host.ParentGroup.HasGroupChanged = true; 10671 m_host.ParentGroup.HasGroupChanged = true;
9886 } 10672 }
9887 10673
@@ -9898,7 +10684,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9898 return new LSL_Vector(); 10684 return new LSL_Vector();
9899 } 10685 }
9900 10686
9901 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10687// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10688 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9902 if (presence != null) 10689 if (presence != null)
9903 { 10690 {
9904 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); 10691 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
@@ -9920,7 +10707,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9920 return new LSL_Rotation(); 10707 return new LSL_Rotation();
9921 } 10708 }
9922 10709
9923 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 10710// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
10711 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
9924 if (presence != null) 10712 if (presence != null)
9925 { 10713 {
9926 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); 10714 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W);
@@ -9980,14 +10768,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9980 { 10768 {
9981 m_host.AddScriptLPS(1); 10769 m_host.AddScriptLPS(1);
9982 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 10770 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
9983 if (detectedParams == null) return; // only works on the first detected avatar 10771 if (detectedParams == null)
9984 10772 {
10773 if (m_host.ParentGroup.IsAttachment == true)
10774 {
10775 detectedParams = new DetectParams();
10776 detectedParams.Key = m_host.OwnerID;
10777 }
10778 else
10779 {
10780 return;
10781 }
10782 }
10783
9985 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10784 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
9986 if (avatar != null) 10785 if (avatar != null)
9987 { 10786 {
9988 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, 10787 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name,
9989 simname, pos, lookAt); 10788 simname, pos, lookAt);
9990 } 10789 }
10790
9991 ScriptSleep(1000); 10791 ScriptSleep(1000);
9992 } 10792 }
9993 10793
@@ -10111,12 +10911,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10111 10911
10112 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 10912 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
10113 object[] data = rules.Data; 10913 object[] data = rules.Data;
10114 for (int i = 0; i < data.Length; ++i) { 10914 for (int i = 0; i < data.Length; ++i)
10915 {
10115 int type = Convert.ToInt32(data[i++].ToString()); 10916 int type = Convert.ToInt32(data[i++].ToString());
10116 if (i >= data.Length) break; // odd number of entries => ignore the last 10917 if (i >= data.Length) break; // odd number of entries => ignore the last
10117 10918
10118 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 10919 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
10119 switch (type) { 10920 switch (type)
10921 {
10120 case ScriptBaseClass.CAMERA_FOCUS: 10922 case ScriptBaseClass.CAMERA_FOCUS:
10121 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 10923 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
10122 case ScriptBaseClass.CAMERA_POSITION: 10924 case ScriptBaseClass.CAMERA_POSITION:
@@ -10221,19 +11023,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10221 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 11023 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
10222 { 11024 {
10223 m_host.AddScriptLPS(1); 11025 m_host.AddScriptLPS(1);
10224 string ret = String.Empty; 11026
10225 string src1 = llBase64ToString(str1); 11027 if (str1 == String.Empty)
10226 string src2 = llBase64ToString(str2); 11028 return String.Empty;
10227 int c = 0; 11029 if (str2 == String.Empty)
10228 for (int i = 0; i < src1.Length; i++) 11030 return str1;
11031
11032 int len = str2.Length;
11033 if ((len % 4) != 0) // LL is EVIL!!!!
11034 {
11035 while (str2.EndsWith("="))
11036 str2 = str2.Substring(0, str2.Length - 1);
11037
11038 len = str2.Length;
11039 int mod = len % 4;
11040
11041 if (mod == 1)
11042 str2 = str2.Substring(0, str2.Length - 1);
11043 else if (mod == 2)
11044 str2 += "==";
11045 else if (mod == 3)
11046 str2 += "=";
11047 }
11048
11049 byte[] data1;
11050 byte[] data2;
11051 try
10229 { 11052 {
10230 ret += (char) (src1[i] ^ src2[c]); 11053 data1 = Convert.FromBase64String(str1);
11054 data2 = Convert.FromBase64String(str2);
11055 }
11056 catch (Exception)
11057 {
11058 return new LSL_String(String.Empty);
11059 }
10231 11060
10232 c++; 11061 byte[] d2 = new Byte[data1.Length];
10233 if (c >= src2.Length) 11062 int pos = 0;
10234 c = 0; 11063
11064 if (data1.Length <= data2.Length)
11065 {
11066 Array.Copy(data2, 0, d2, 0, data1.Length);
10235 } 11067 }
10236 return llStringToBase64(ret); 11068 else
11069 {
11070 while (pos < data1.Length)
11071 {
11072 len = data1.Length - pos;
11073 if (len > data2.Length)
11074 len = data2.Length;
11075
11076 Array.Copy(data2, 0, d2, pos, len);
11077 pos += len;
11078 }
11079 }
11080
11081 for (pos = 0 ; pos < data1.Length ; pos++ )
11082 data1[pos] ^= d2[pos];
11083
11084 return Convert.ToBase64String(data1);
10237 } 11085 }
10238 11086
10239 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 11087 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -10286,16 +11134,72 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10286 if (userAgent != null) 11134 if (userAgent != null)
10287 httpHeaders["User-Agent"] = userAgent; 11135 httpHeaders["User-Agent"] = userAgent;
10288 11136
11137 // See if the URL contains any header hacks
11138 string[] urlParts = url.Split(new char[] {'\n'});
11139 if (urlParts.Length > 1)
11140 {
11141 // Iterate the passed headers and parse them
11142 for (int i = 1 ; i < urlParts.Length ; i++ )
11143 {
11144 // The rest of those would be added to the body in SL.
11145 // Let's not do that.
11146 if (urlParts[i] == String.Empty)
11147 break;
11148
11149 // See if this could be a valid header
11150 string[] headerParts = urlParts[i].Split(new char[] {':'}, 2);
11151 if (headerParts.Length != 2)
11152 continue;
11153
11154 string headerName = headerParts[0].Trim();
11155 string headerValue = headerParts[1].Trim();
11156
11157 // Filter out headers that could be used to abuse
11158 // another system or cloak the request
11159 if (headerName.ToLower() == "x-secondlife-shard" ||
11160 headerName.ToLower() == "x-secondlife-object-name" ||
11161 headerName.ToLower() == "x-secondlife-object-key" ||
11162 headerName.ToLower() == "x-secondlife-region" ||
11163 headerName.ToLower() == "x-secondlife-local-position" ||
11164 headerName.ToLower() == "x-secondlife-local-velocity" ||
11165 headerName.ToLower() == "x-secondlife-local-rotation" ||
11166 headerName.ToLower() == "x-secondlife-owner-name" ||
11167 headerName.ToLower() == "x-secondlife-owner-key" ||
11168 headerName.ToLower() == "connection" ||
11169 headerName.ToLower() == "content-length" ||
11170 headerName.ToLower() == "from" ||
11171 headerName.ToLower() == "host" ||
11172 headerName.ToLower() == "proxy-authorization" ||
11173 headerName.ToLower() == "referer" ||
11174 headerName.ToLower() == "trailer" ||
11175 headerName.ToLower() == "transfer-encoding" ||
11176 headerName.ToLower() == "via" ||
11177 headerName.ToLower() == "authorization")
11178 continue;
11179
11180 httpHeaders[headerName] = headerValue;
11181 }
11182
11183 // Finally, strip any protocol specifier from the URL
11184 url = urlParts[0].Trim();
11185 int idx = url.IndexOf(" HTTP/");
11186 if (idx != -1)
11187 url = url.Substring(0, idx);
11188 }
11189
10289 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$"; 11190 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$";
10290 Regex r = new Regex(authregex); 11191 Regex r = new Regex(authregex);
10291 int[] gnums = r.GetGroupNumbers(); 11192 int[] gnums = r.GetGroupNumbers();
10292 Match m = r.Match(url); 11193 Match m = r.Match(url);
10293 if (m.Success) { 11194 if (m.Success)
10294 for (int i = 1; i < gnums.Length; i++) { 11195 {
11196 for (int i = 1; i < gnums.Length; i++)
11197 {
10295 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 11198 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
10296 //CaptureCollection cc = g.Captures; 11199 //CaptureCollection cc = g.Captures;
10297 } 11200 }
10298 if (m.Groups.Count == 5) { 11201 if (m.Groups.Count == 5)
11202 {
10299 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 11203 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
10300 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 11204 url = m.Groups[1].ToString() + m.Groups[4].ToString();
10301 } 11205 }
@@ -10498,6 +11402,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10498 11402
10499 LSL_List ret = new LSL_List(); 11403 LSL_List ret = new LSL_List();
10500 UUID key = new UUID(); 11404 UUID key = new UUID();
11405
11406
10501 if (UUID.TryParse(id, out key)) 11407 if (UUID.TryParse(id, out key))
10502 { 11408 {
10503 ScenePresence av = World.GetScenePresence(key); 11409 ScenePresence av = World.GetScenePresence(key);
@@ -10515,13 +11421,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10515 ret.Add(new LSL_String("")); 11421 ret.Add(new LSL_String(""));
10516 break; 11422 break;
10517 case ScriptBaseClass.OBJECT_POS: 11423 case ScriptBaseClass.OBJECT_POS:
10518 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); 11424 Vector3 avpos;
11425
11426 if (av.ParentID != 0 && av.ParentPart != null)
11427 {
11428 avpos = av.OffsetPosition;
11429
11430 Vector3 sitOffset = (Zrot(av.Rotation)) * (av.Appearance.AvatarHeight * 0.02638f *2.0f);
11431 avpos -= sitOffset;
11432
11433 avpos = av.ParentPart.GetWorldPosition() + avpos * av.ParentPart.GetWorldRotation();
11434 }
11435 else
11436 avpos = av.AbsolutePosition;
11437
11438 ret.Add(new LSL_Vector((double)avpos.X, (double)avpos.Y, (double)avpos.Z));
10519 break; 11439 break;
10520 case ScriptBaseClass.OBJECT_ROT: 11440 case ScriptBaseClass.OBJECT_ROT:
10521 ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W)); 11441 Quaternion avrot = av.Rotation;
11442 if (av.ParentID != 0 && av.ParentPart != null)
11443 {
11444 avrot = av.ParentPart.GetWorldRotation() * avrot;
11445 }
11446 ret.Add(new LSL_Rotation((double)avrot.X, (double)avrot.Y, (double)avrot.Z, (double)avrot.W));
10522 break; 11447 break;
10523 case ScriptBaseClass.OBJECT_VELOCITY: 11448 case ScriptBaseClass.OBJECT_VELOCITY:
10524 ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); 11449 Vector3 avvel = av.Velocity;
11450 ret.Add(new LSL_Vector((double)avvel.X, (double)avvel.Y, (double)avvel.Z));
10525 break; 11451 break;
10526 case ScriptBaseClass.OBJECT_OWNER: 11452 case ScriptBaseClass.OBJECT_OWNER:
10527 ret.Add(new LSL_String(id)); 11453 ret.Add(new LSL_String(id));
@@ -10606,11 +11532,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10606 case ScriptBaseClass.OBJECT_NAME: 11532 case ScriptBaseClass.OBJECT_NAME:
10607 ret.Add(new LSL_String(obj.Name)); 11533 ret.Add(new LSL_String(obj.Name));
10608 break; 11534 break;
10609 case ScriptBaseClass.OBJECT_DESC: 11535 case ScriptBaseClass.OBJECT_DESC:
10610 ret.Add(new LSL_String(obj.Description)); 11536 ret.Add(new LSL_String(obj.Description));
10611 break; 11537 break;
10612 case ScriptBaseClass.OBJECT_POS: 11538 case ScriptBaseClass.OBJECT_POS:
10613 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); 11539 Vector3 opos = obj.AbsolutePosition;
11540 ret.Add(new LSL_Vector(opos.X, opos.Y, opos.Z));
10614 break; 11541 break;
10615 case ScriptBaseClass.OBJECT_ROT: 11542 case ScriptBaseClass.OBJECT_ROT:
10616 { 11543 {
@@ -10660,9 +11587,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10660 // The value returned in SL for normal prims is prim count 11587 // The value returned in SL for normal prims is prim count
10661 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount)); 11588 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
10662 break; 11589 break;
10663 // The following 3 costs I have intentionaly coded to return zero. They are part of 11590
10664 // "Land Impact" calculations. These calculations are probably not applicable 11591 // costs below may need to be diferent for root parts, need to check
10665 // to OpenSim and are not yet complete in SL
10666 case ScriptBaseClass.OBJECT_SERVER_COST: 11592 case ScriptBaseClass.OBJECT_SERVER_COST:
10667 // The linden calculation is here 11593 // The linden calculation is here
10668 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight 11594 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
@@ -10670,16 +11596,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10670 ret.Add(new LSL_Float(0)); 11596 ret.Add(new LSL_Float(0));
10671 break; 11597 break;
10672 case ScriptBaseClass.OBJECT_STREAMING_COST: 11598 case ScriptBaseClass.OBJECT_STREAMING_COST:
10673 // The linden calculation is here 11599 // The value returned in SL for normal prims is prim count * 0.06
10674 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost 11600 ret.Add(new LSL_Float(obj.StreamingCost));
10675 // The value returned in SL for normal prims looks like the prim count * 0.06
10676 ret.Add(new LSL_Float(0));
10677 break; 11601 break;
10678 case ScriptBaseClass.OBJECT_PHYSICS_COST: 11602 case ScriptBaseClass.OBJECT_PHYSICS_COST:
10679 // The linden calculation is here 11603 // The value returned in SL for normal prims is prim count
10680 // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics 11604 ret.Add(new LSL_Float(obj.PhysicsCost));
10681 // The value returned in SL for normal prims looks like the prim count
10682 ret.Add(new LSL_Float(0));
10683 break; 11605 break;
10684 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding 11606 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
10685 ret.Add(new LSL_Float(0)); 11607 ret.Add(new LSL_Float(0));
@@ -10938,15 +11860,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10938 return result; 11860 return result;
10939 } 11861 }
10940 11862
10941 public void print(string str) 11863 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
10942 { 11864 {
10943 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 11865 List<SceneObjectPart> parts = GetLinkParts(link);
10944 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11866 if (parts.Count < 1)
10945 if (ossl != null) 11867 return 0;
10946 { 11868
10947 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 11869 return GetNumberOfSides(parts[0]);
10948 m_log.Info("LSL print():" + str);
10949 }
10950 } 11870 }
10951 11871
10952 private string Name2Username(string name) 11872 private string Name2Username(string name)
@@ -10991,7 +11911,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10991 11911
10992 return rq.ToString(); 11912 return rq.ToString();
10993 } 11913 }
10994 11914/*
11915 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
11916 {
11917 m_SayShoutCount = 0;
11918 }
11919*/
10995 private struct Tri 11920 private struct Tri
10996 { 11921 {
10997 public Vector3 p1; 11922 public Vector3 p1;
@@ -11140,9 +12065,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11140 12065
11141 ContactResult result = new ContactResult (); 12066 ContactResult result = new ContactResult ();
11142 result.ConsumerID = group.LocalId; 12067 result.ConsumerID = group.LocalId;
11143 result.Depth = intersection.distance; 12068// result.Depth = intersection.distance;
11144 result.Normal = intersection.normal; 12069 result.Normal = intersection.normal;
11145 result.Pos = intersection.ipoint; 12070 result.Pos = intersection.ipoint;
12071 result.Depth = Vector3.Mag(rayStart - result.Pos);
11146 12072
11147 contacts.Add(result); 12073 contacts.Add(result);
11148 }); 12074 });
@@ -11275,6 +12201,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11275 12201
11276 return contacts[0]; 12202 return contacts[0];
11277 } 12203 }
12204/*
12205 // not done:
12206 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
12207 {
12208 ContactResult[] contacts = null;
12209 World.ForEachSOG(delegate(SceneObjectGroup group)
12210 {
12211 if (m_host.ParentGroup == group)
12212 return;
12213
12214 if (group.IsAttachment)
12215 return;
12216
12217 if(group.RootPart.PhysActor != null)
12218 return;
12219
12220 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
12221 });
12222 return contacts;
12223 }
12224*/
11278 12225
11279 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 12226 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
11280 { 12227 {
@@ -11398,18 +12345,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11398 } 12345 }
11399 } 12346 }
11400 12347
12348 // Double check this
11401 if (checkTerrain) 12349 if (checkTerrain)
11402 { 12350 {
11403 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); 12351 bool skipGroundCheck = false;
11404 if (groundContact != null) 12352
11405 results.Add((ContactResult)groundContact); 12353 foreach (ContactResult c in results)
12354 {
12355 if (c.ConsumerID == 0) // Physics gave us a ground collision
12356 skipGroundCheck = true;
12357 }
12358
12359 if (!skipGroundCheck)
12360 {
12361 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
12362 if (groundContact != null)
12363 results.Add((ContactResult)groundContact);
12364 }
11406 } 12365 }
11407 12366
11408 results.Sort(delegate(ContactResult a, ContactResult b) 12367 results.Sort(delegate(ContactResult a, ContactResult b)
11409 { 12368 {
11410 return a.Depth.CompareTo(b.Depth); 12369 return a.Depth.CompareTo(b.Depth);
11411 }); 12370 });
11412 12371
11413 int values = 0; 12372 int values = 0;
11414 SceneObjectGroup thisgrp = m_host.ParentGroup; 12373 SceneObjectGroup thisgrp = m_host.ParentGroup;
11415 12374
@@ -11502,7 +12461,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11502 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 12461 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
11503 if (!isAccount) return 0; 12462 if (!isAccount) return 0;
11504 if (estate.HasAccess(id)) return 1; 12463 if (estate.HasAccess(id)) return 1;
11505 if (estate.IsBanned(id)) 12464 if (estate.IsBanned(id, World.GetUserFlags(id)))
11506 estate.RemoveBan(id); 12465 estate.RemoveBan(id);
11507 estate.AddEstateUser(id); 12466 estate.AddEstateUser(id);
11508 break; 12467 break;
@@ -11521,14 +12480,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11521 break; 12480 break;
11522 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 12481 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
11523 if (!isAccount) return 0; 12482 if (!isAccount) return 0;
11524 if (estate.IsBanned(id)) return 1; 12483 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
11525 EstateBan ban = new EstateBan(); 12484 EstateBan ban = new EstateBan();
11526 ban.EstateID = estate.EstateID; 12485 ban.EstateID = estate.EstateID;
11527 ban.BannedUserID = id; 12486 ban.BannedUserID = id;
11528 estate.AddBan(ban); 12487 estate.AddBan(ban);
11529 break; 12488 break;
11530 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 12489 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
11531 if (!isAccount || !estate.IsBanned(id)) return 0; 12490 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
11532 estate.RemoveBan(id); 12491 estate.RemoveBan(id);
11533 break; 12492 break;
11534 default: return 0; 12493 default: return 0;
@@ -11557,7 +12516,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11557 return 16384; 12516 return 16384;
11558 } 12517 }
11559 12518
11560 public LSL_Integer llGetUsedMemory() 12519 public virtual LSL_Integer llGetUsedMemory()
11561 { 12520 {
11562 m_host.AddScriptLPS(1); 12521 m_host.AddScriptLPS(1);
11563 // The value returned for LSO scripts in SL 12522 // The value returned for LSO scripts in SL
@@ -11585,19 +12544,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11585 public void llSetSoundQueueing(int queue) 12544 public void llSetSoundQueueing(int queue)
11586 { 12545 {
11587 m_host.AddScriptLPS(1); 12546 m_host.AddScriptLPS(1);
11588 NotImplemented("llSetSoundQueueing");
11589 } 12547 }
11590 12548
11591 public void llCollisionSprite(string impact_sprite) 12549 public void llCollisionSprite(string impact_sprite)
11592 { 12550 {
11593 m_host.AddScriptLPS(1); 12551 m_host.AddScriptLPS(1);
11594 NotImplemented("llCollisionSprite"); 12552 // Viewer 2.0 broke this and it's likely LL has no intention
12553 // of fixing it. Therefore, letting this be a NOP seems appropriate.
11595 } 12554 }
11596 12555
11597 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12556 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
11598 { 12557 {
11599 m_host.AddScriptLPS(1); 12558 m_host.AddScriptLPS(1);
11600 NotImplemented("llGodLikeRezObject"); 12559
12560 if (!World.Permissions.IsGod(m_host.OwnerID))
12561 NotImplemented("llGodLikeRezObject");
12562
12563 AssetBase rezAsset = World.AssetService.Get(inventory);
12564 if (rezAsset == null)
12565 {
12566 llSay(0, "Asset not found");
12567 return;
12568 }
12569
12570 SceneObjectGroup group = null;
12571
12572 try
12573 {
12574 string xmlData = Utils.BytesToString(rezAsset.Data);
12575 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
12576 }
12577 catch
12578 {
12579 llSay(0, "Asset not found");
12580 return;
12581 }
12582
12583 if (group == null)
12584 {
12585 llSay(0, "Asset not found");
12586 return;
12587 }
12588
12589 group.RootPart.AttachPoint = group.RootPart.Shape.State;
12590 group.RootPart.AttachOffset = group.AbsolutePosition;
12591
12592 group.ResetIDs();
12593
12594 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
12595 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
12596 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
12597 group.ScheduleGroupForFullUpdate();
12598
12599 // objects rezzed with this method are die_at_edge by default.
12600 group.RootPart.SetDieAtEdge(true);
12601
12602 group.ResumeScripts();
12603
12604 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
12605 "object_rez", new Object[] {
12606 new LSL_String(
12607 group.RootPart.UUID.ToString()) },
12608 new DetectParams[0]));
11601 } 12609 }
11602 12610
11603 public LSL_String llTransferLindenDollars(string destination, int amount) 12611 public LSL_String llTransferLindenDollars(string destination, int amount)
@@ -11649,7 +12657,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11649 } 12657 }
11650 12658
11651 bool result = money.ObjectGiveMoney( 12659 bool result = money.ObjectGiveMoney(
11652 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 12660 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount, txn);
11653 12661
11654 if (result) 12662 if (result)
11655 { 12663 {
@@ -11674,6 +12682,598 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11674 } 12682 }
11675 12683
11676 #endregion 12684 #endregion
12685
12686 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
12687 {
12688 SceneObjectGroup group = m_host.ParentGroup;
12689
12690 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
12691 return;
12692 if (group.IsAttachment)
12693 return;
12694
12695 if (frames.Data.Length > 0) // We are getting a new motion
12696 {
12697 if (group.RootPart.KeyframeMotion != null)
12698 group.RootPart.KeyframeMotion.Delete();
12699 group.RootPart.KeyframeMotion = null;
12700
12701 int idx = 0;
12702
12703 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
12704 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
12705
12706 while (idx < options.Data.Length)
12707 {
12708 int option = (int)options.GetLSLIntegerItem(idx++);
12709 int remain = options.Data.Length - idx;
12710
12711 switch (option)
12712 {
12713 case ScriptBaseClass.KFM_MODE:
12714 if (remain < 1)
12715 break;
12716 int modeval = (int)options.GetLSLIntegerItem(idx++);
12717 switch(modeval)
12718 {
12719 case ScriptBaseClass.KFM_FORWARD:
12720 mode = KeyframeMotion.PlayMode.Forward;
12721 break;
12722 case ScriptBaseClass.KFM_REVERSE:
12723 mode = KeyframeMotion.PlayMode.Reverse;
12724 break;
12725 case ScriptBaseClass.KFM_LOOP:
12726 mode = KeyframeMotion.PlayMode.Loop;
12727 break;
12728 case ScriptBaseClass.KFM_PING_PONG:
12729 mode = KeyframeMotion.PlayMode.PingPong;
12730 break;
12731 }
12732 break;
12733 case ScriptBaseClass.KFM_DATA:
12734 if (remain < 1)
12735 break;
12736 int dataval = (int)options.GetLSLIntegerItem(idx++);
12737 data = (KeyframeMotion.DataFormat)dataval;
12738 break;
12739 }
12740 }
12741
12742 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
12743
12744 idx = 0;
12745
12746 int elemLength = 2;
12747 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
12748 elemLength = 3;
12749
12750 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
12751 while (idx < frames.Data.Length)
12752 {
12753 int remain = frames.Data.Length - idx;
12754
12755 if (remain < elemLength)
12756 break;
12757
12758 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
12759 frame.Position = null;
12760 frame.Rotation = null;
12761
12762 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
12763 {
12764 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
12765 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
12766 }
12767 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
12768 {
12769 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
12770 Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
12771 q.Normalize();
12772 frame.Rotation = q;
12773 }
12774
12775 float tempf = (float)frames.GetLSLFloatItem(idx++);
12776 frame.TimeMS = (int)(tempf * 1000.0f);
12777
12778 keyframes.Add(frame);
12779 }
12780
12781 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
12782 group.RootPart.KeyframeMotion.Start();
12783 }
12784 else
12785 {
12786 if (group.RootPart.KeyframeMotion == null)
12787 return;
12788
12789 if (options.Data.Length == 0)
12790 {
12791 group.RootPart.KeyframeMotion.Stop();
12792 return;
12793 }
12794
12795 int code = (int)options.GetLSLIntegerItem(0);
12796
12797 int idx = 0;
12798
12799 while (idx < options.Data.Length)
12800 {
12801 int option = (int)options.GetLSLIntegerItem(idx++);
12802 int remain = options.Data.Length - idx;
12803
12804 switch (option)
12805 {
12806 case ScriptBaseClass.KFM_COMMAND:
12807 int cmd = (int)options.GetLSLIntegerItem(idx++);
12808 switch (cmd)
12809 {
12810 case ScriptBaseClass.KFM_CMD_PLAY:
12811 group.RootPart.KeyframeMotion.Start();
12812 break;
12813 case ScriptBaseClass.KFM_CMD_STOP:
12814 group.RootPart.KeyframeMotion.Stop();
12815 break;
12816 case ScriptBaseClass.KFM_CMD_PAUSE:
12817 group.RootPart.KeyframeMotion.Pause();
12818 break;
12819 }
12820 break;
12821 }
12822 }
12823 }
12824 }
12825
12826 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed)
12827 {
12828 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
12829
12830 int idx = 0;
12831 int idxStart = 0;
12832
12833 bool positionChanged = false;
12834 Vector3 finalPos = Vector3.Zero;
12835
12836 try
12837 {
12838 while (idx < rules.Length)
12839 {
12840 ++rulesParsed;
12841 int code = rules.GetLSLIntegerItem(idx++);
12842
12843 int remain = rules.Length - idx;
12844 idxStart = idx;
12845
12846 switch (code)
12847 {
12848 case (int)ScriptBaseClass.PRIM_POSITION:
12849 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
12850 {
12851 if (remain < 1)
12852 return null;
12853
12854 LSL_Vector v;
12855 v = rules.GetVector3Item(idx++);
12856
12857 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12858 if (part == null)
12859 break;
12860
12861 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12862 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12863 if (part.LinkNum > 1)
12864 {
12865 localRot = GetPartLocalRot(part);
12866 localPos = GetPartLocalPos(part);
12867 }
12868
12869 v -= localPos;
12870 v /= localRot;
12871
12872 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
12873
12874 v = v + 2 * sitOffset;
12875
12876 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
12877 av.SendAvatarDataToAllAgents();
12878
12879 }
12880 break;
12881
12882 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
12883 case (int)ScriptBaseClass.PRIM_ROTATION:
12884 {
12885 if (remain < 1)
12886 return null;
12887
12888 LSL_Rotation r;
12889 r = rules.GetQuaternionItem(idx++);
12890
12891 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12892 if (part == null)
12893 break;
12894
12895 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12896 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12897
12898 if (part.LinkNum > 1)
12899 localRot = GetPartLocalRot(part);
12900
12901 r = r * llGetRootRotation() / localRot;
12902 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
12903 av.SendAvatarDataToAllAgents();
12904 }
12905 break;
12906
12907 // parse rest doing nothing but number of parameters error check
12908 case (int)ScriptBaseClass.PRIM_SIZE:
12909 case (int)ScriptBaseClass.PRIM_MATERIAL:
12910 case (int)ScriptBaseClass.PRIM_PHANTOM:
12911 case (int)ScriptBaseClass.PRIM_PHYSICS:
12912 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
12913 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
12914 case (int)ScriptBaseClass.PRIM_NAME:
12915 case (int)ScriptBaseClass.PRIM_DESC:
12916 if (remain < 1)
12917 return null;
12918 idx++;
12919 break;
12920
12921 case (int)ScriptBaseClass.PRIM_GLOW:
12922 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
12923 case (int)ScriptBaseClass.PRIM_TEXGEN:
12924 if (remain < 2)
12925 return null;
12926 idx += 2;
12927 break;
12928
12929 case (int)ScriptBaseClass.PRIM_TYPE:
12930 if (remain < 3)
12931 return null;
12932 code = (int)rules.GetLSLIntegerItem(idx++);
12933 remain = rules.Length - idx;
12934 switch (code)
12935 {
12936 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
12937 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
12938 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
12939 if (remain < 6)
12940 return null;
12941 idx += 6;
12942 break;
12943
12944 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
12945 if (remain < 5)
12946 return null;
12947 idx += 5;
12948 break;
12949
12950 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
12951 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
12952 case (int)ScriptBaseClass.PRIM_TYPE_RING:
12953 if (remain < 11)
12954 return null;
12955 idx += 11;
12956 break;
12957
12958 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
12959 if (remain < 2)
12960 return null;
12961 idx += 2;
12962 break;
12963 }
12964 break;
12965
12966 case (int)ScriptBaseClass.PRIM_COLOR:
12967 case (int)ScriptBaseClass.PRIM_TEXT:
12968 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
12969 case (int)ScriptBaseClass.PRIM_OMEGA:
12970 if (remain < 3)
12971 return null;
12972 idx += 3;
12973 break;
12974
12975 case (int)ScriptBaseClass.PRIM_TEXTURE:
12976 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
12977 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
12978 if (remain < 5)
12979 return null;
12980 idx += 5;
12981 break;
12982
12983 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
12984 if (remain < 7)
12985 return null;
12986
12987 idx += 7;
12988 break;
12989
12990 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
12991 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
12992 return null;
12993
12994 return rules.GetSublist(idx, -1);
12995 }
12996 }
12997 }
12998 catch (InvalidCastException e)
12999 {
13000 ShoutError(string.Format(
13001 "{0} error running rule #{1}: arg #{2} ",
13002 originFunc, rulesParsed, idx - idxStart) + e.Message);
13003 }
13004 finally
13005 {
13006 if (positionChanged)
13007 {
13008 av.OffsetPosition = finalPos;
13009// av.SendAvatarDataToAllAgents();
13010 av.SendTerseUpdateToAllClients();
13011 positionChanged = false;
13012 }
13013 }
13014 return null;
13015 }
13016
13017 public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res)
13018 {
13019 // avatars case
13020 // replies as SL wiki
13021
13022// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
13023 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
13024
13025 int idx = 0;
13026 while (idx < rules.Length)
13027 {
13028 int code = (int)rules.GetLSLIntegerItem(idx++);
13029 int remain = rules.Length - idx;
13030
13031 switch (code)
13032 {
13033 case (int)ScriptBaseClass.PRIM_MATERIAL:
13034 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
13035 break;
13036
13037 case (int)ScriptBaseClass.PRIM_PHYSICS:
13038 res.Add(new LSL_Integer(0));
13039 break;
13040
13041 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
13042 res.Add(new LSL_Integer(0));
13043 break;
13044
13045 case (int)ScriptBaseClass.PRIM_PHANTOM:
13046 res.Add(new LSL_Integer(0));
13047 break;
13048
13049 case (int)ScriptBaseClass.PRIM_POSITION:
13050
13051 Vector3 pos = avatar.OffsetPosition;
13052
13053 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
13054 pos -= sitOffset;
13055
13056 if( sitPart != null)
13057 pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation();
13058
13059 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
13060 break;
13061
13062 case (int)ScriptBaseClass.PRIM_SIZE:
13063 // as in llGetAgentSize above
13064// res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight));
13065 Vector3 s = avatar.Appearance.AvatarSize;
13066 res.Add(new LSL_Vector(s.X, s.Y, s.Z));
13067
13068 break;
13069
13070 case (int)ScriptBaseClass.PRIM_ROTATION:
13071 Quaternion rot = avatar.Rotation;
13072 if (sitPart != null)
13073 {
13074 rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation
13075 }
13076
13077 res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W));
13078 break;
13079
13080 case (int)ScriptBaseClass.PRIM_TYPE:
13081 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
13082 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
13083 res.Add(new LSL_Vector(0f,1.0f,0f));
13084 res.Add(new LSL_Float(0.0f));
13085 res.Add(new LSL_Vector(0, 0, 0));
13086 res.Add(new LSL_Vector(1.0f,1.0f,0f));
13087 res.Add(new LSL_Vector(0, 0, 0));
13088 break;
13089
13090 case (int)ScriptBaseClass.PRIM_TEXTURE:
13091 if (remain < 1)
13092 return null;
13093
13094 int face = (int)rules.GetLSLIntegerItem(idx++);
13095 if (face == ScriptBaseClass.ALL_SIDES)
13096 {
13097 for (face = 0; face < 21; face++)
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 else
13106 {
13107 if (face >= 0 && face < 21)
13108 {
13109 res.Add(new LSL_String(""));
13110 res.Add(new LSL_Vector(0,0,0));
13111 res.Add(new LSL_Vector(0,0,0));
13112 res.Add(new LSL_Float(0.0));
13113 }
13114 }
13115 break;
13116
13117 case (int)ScriptBaseClass.PRIM_COLOR:
13118 if (remain < 1)
13119 return null;
13120
13121 face = (int)rules.GetLSLIntegerItem(idx++);
13122
13123 if (face == ScriptBaseClass.ALL_SIDES)
13124 {
13125 for (face = 0; face < 21; face++)
13126 {
13127 res.Add(new LSL_Vector(0,0,0));
13128 res.Add(new LSL_Float(0));
13129 }
13130 }
13131 else
13132 {
13133 res.Add(new LSL_Vector(0,0,0));
13134 res.Add(new LSL_Float(0));
13135 }
13136 break;
13137
13138 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
13139 if (remain < 1)
13140 return null;
13141 face = (int)rules.GetLSLIntegerItem(idx++);
13142
13143 if (face == ScriptBaseClass.ALL_SIDES)
13144 {
13145 for (face = 0; face < 21; face++)
13146 {
13147 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
13148 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
13149 }
13150 }
13151 else
13152 {
13153 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
13154 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
13155 }
13156 break;
13157
13158 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
13159 if (remain < 1)
13160 return null;
13161 face = (int)rules.GetLSLIntegerItem(idx++);
13162
13163 if (face == ScriptBaseClass.ALL_SIDES)
13164 {
13165 for (face = 0; face < 21; face++)
13166 {
13167 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
13168 }
13169 }
13170 else
13171 {
13172 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
13173 }
13174 break;
13175
13176 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
13177 res.Add(new LSL_Integer(0));
13178 res.Add(new LSL_Integer(0));// softness
13179 res.Add(new LSL_Float(0.0f)); // gravity
13180 res.Add(new LSL_Float(0.0f)); // friction
13181 res.Add(new LSL_Float(0.0f)); // wind
13182 res.Add(new LSL_Float(0.0f)); // tension
13183 res.Add(new LSL_Vector(0f,0f,0f));
13184 break;
13185
13186 case (int)ScriptBaseClass.PRIM_TEXGEN:
13187 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
13188 if (remain < 1)
13189 return null;
13190 face = (int)rules.GetLSLIntegerItem(idx++);
13191
13192 if (face == ScriptBaseClass.ALL_SIDES)
13193 {
13194 for (face = 0; face < 21; face++)
13195 {
13196 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13197 }
13198 }
13199 else
13200 {
13201 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13202 }
13203 break;
13204
13205 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
13206 res.Add(new LSL_Integer(0));
13207 res.Add(new LSL_Vector(0f,0f,0f));
13208 res.Add(new LSL_Float(0f)); // intensity
13209 res.Add(new LSL_Float(0f)); // radius
13210 res.Add(new LSL_Float(0f)); // falloff
13211 break;
13212
13213 case (int)ScriptBaseClass.PRIM_GLOW:
13214 if (remain < 1)
13215 return null;
13216 face = (int)rules.GetLSLIntegerItem(idx++);
13217
13218 if (face == ScriptBaseClass.ALL_SIDES)
13219 {
13220 for (face = 0; face < 21; face++)
13221 {
13222 res.Add(new LSL_Float(0f));
13223 }
13224 }
13225 else
13226 {
13227 res.Add(new LSL_Float(0f));
13228 }
13229 break;
13230
13231 case (int)ScriptBaseClass.PRIM_TEXT:
13232 res.Add(new LSL_String(""));
13233 res.Add(new LSL_Vector(0f,0f,0f));
13234 res.Add(new LSL_Float(1.0f));
13235 break;
13236
13237 case (int)ScriptBaseClass.PRIM_NAME:
13238 res.Add(new LSL_String(avatar.Name));
13239 break;
13240
13241 case (int)ScriptBaseClass.PRIM_DESC:
13242 res.Add(new LSL_String(""));
13243 break;
13244
13245 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
13246 Quaternion lrot = avatar.Rotation;
13247
13248 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13249 {
13250 lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset
13251 }
13252 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
13253 break;
13254
13255 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
13256 Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part
13257 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
13258 lpos -= lsitOffset;
13259
13260 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13261 {
13262 lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim
13263 }
13264 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
13265 break;
13266
13267 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
13268 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
13269 return null;
13270
13271 return rules.GetSublist(idx, -1);
13272 }
13273 }
13274
13275 return null;
13276 }
11677 } 13277 }
11678 13278
11679 public class NotecardCache 13279 public class NotecardCache