aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
diff options
context:
space:
mode:
authoronefang2019-05-19 21:24:15 +1000
committeronefang2019-05-19 21:24:15 +1000
commit5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch)
treea9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
parentAdd a build script. (diff)
downloadopensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs5948
1 files changed, 4235 insertions, 1713 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 1399880..bac1468 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Collections.Specialized;
31using System.Diagnostics; 32using System.Diagnostics;
32using System.Drawing; 33using System.Drawing;
33using System.Drawing.Imaging; 34using System.Drawing.Imaging;
@@ -35,10 +36,12 @@ using System.Runtime.Remoting.Lifetime;
35using System.Text; 36using System.Text;
36using System.Threading; 37using System.Threading;
37using System.Text.RegularExpressions; 38using System.Text.RegularExpressions;
39using System.Timers;
38using Nini.Config; 40using Nini.Config;
39using log4net; 41using log4net;
40using OpenMetaverse; 42using OpenMetaverse;
41using OpenMetaverse.Assets; 43using OpenMetaverse.Assets;
44using OpenMetaverse.StructuredData; // LitJson is hidden on this
42using OpenMetaverse.Packets; 45using OpenMetaverse.Packets;
43using OpenMetaverse.Rendering; 46using OpenMetaverse.Rendering;
44using OpenSim; 47using OpenSim;
@@ -49,6 +52,7 @@ using OpenSim.Region.CoreModules.World.Land;
49using OpenSim.Region.CoreModules.World.Terrain; 52using OpenSim.Region.CoreModules.World.Terrain;
50using OpenSim.Region.Framework.Interfaces; 53using OpenSim.Region.Framework.Interfaces;
51using OpenSim.Region.Framework.Scenes; 54using OpenSim.Region.Framework.Scenes;
55using OpenSim.Region.Framework.Scenes.Serialization;
52using OpenSim.Region.Framework.Scenes.Animation; 56using OpenSim.Region.Framework.Scenes.Animation;
53using OpenSim.Region.Framework.Scenes.Scripting; 57using OpenSim.Region.Framework.Scenes.Scripting;
54using OpenSim.Region.PhysicsModules.SharedBase; 58using OpenSim.Region.PhysicsModules.SharedBase;
@@ -72,6 +76,7 @@ using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
72using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 76using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
73using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; 77using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
74using System.Reflection; 78using System.Reflection;
79using Timer = System.Timers.Timer;
75using System.Linq; 80using System.Linq;
76using PermissionMask = OpenSim.Framework.PermissionMask; 81using PermissionMask = OpenSim.Framework.PermissionMask;
77 82
@@ -98,30 +103,87 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
98 protected SceneObjectPart m_host; 103 protected SceneObjectPart m_host;
99 104
100 /// <summary> 105 /// <summary>
101 /// Used for script sleeps when we are using co-operative script termination.
102 /// </summary>
103 /// <remarks>null if co-operative script termination is not active</remarks>
104 /// <summary>
105 /// The item that hosts this script 106 /// The item that hosts this script
106 /// </summary> 107 /// </summary>
107 protected TaskInventoryItem m_item; 108 protected TaskInventoryItem m_item;
108 109
109 protected bool throwErrorOnNotImplemented = false; 110 protected bool throwErrorOnNotImplemented = false;
110 protected AsyncCommandManager AsyncCommands = null; 111 protected AsyncCommandManager AsyncCommands = null;
112 protected float m_ScriptDelayFactor = 1.0f;
111 protected float m_ScriptDistanceFactor = 1.0f; 113 protected float m_ScriptDistanceFactor = 1.0f;
112 protected float m_MinTimerInterval = 0.5f; 114 protected float m_MinTimerInterval = 0.5f;
113 protected float m_recoilScaleFactor = 0.0f; 115 protected float m_recoilScaleFactor = 0.0f;
114 116
115 protected DateTime m_timer = DateTime.Now; 117 protected double m_timer = Util.GetTimeStampMS();
116 protected bool m_waitingForScriptAnswer = false; 118 protected bool m_waitingForScriptAnswer = false;
117 protected bool m_automaticLinkPermission = false; 119 protected bool m_automaticLinkPermission = false;
118 protected IMessageTransferModule m_TransferModule = null; 120 protected IMessageTransferModule m_TransferModule = null;
119 protected int m_notecardLineReadCharsMax = 255; 121 protected int m_notecardLineReadCharsMax = 255;
120 protected int m_scriptConsoleChannel = 0; 122 protected int m_scriptConsoleChannel = 0;
121 protected bool m_scriptConsoleChannelEnabled = false; 123 protected bool m_scriptConsoleChannelEnabled = false;
124 protected bool m_debuggerSafe = false;
122 protected IUrlModule m_UrlModule = null; 125 protected IUrlModule m_UrlModule = null;
126
123 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); 127 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>();
124 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 128 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
129 protected int m_sleepMsOnSetTexture = 200;
130 protected int m_sleepMsOnSetLinkTexture = 200;
131 protected int m_sleepMsOnScaleTexture = 200;
132 protected int m_sleepMsOnOffsetTexture = 200;
133 protected int m_sleepMsOnRotateTexture = 200;
134 protected int m_sleepMsOnSetPos = 200;
135 protected int m_sleepMsOnSetRot = 200;
136 protected int m_sleepMsOnSetLocalRot = 200;
137 protected int m_sleepMsOnPreloadSound = 1000;
138 protected int m_sleepMsOnMakeExplosion = 100;
139 protected int m_sleepMsOnMakeFountain = 100;
140 protected int m_sleepMsOnMakeSmoke = 100;
141 protected int m_sleepMsOnMakeFire = 100;
142 protected int m_sleepMsOnRezAtRoot = 100;
143 protected int m_sleepMsOnInstantMessage = 2000;
144 protected int m_sleepMsOnEmail = 20000;
145 protected int m_sleepMsOnCreateLink = 1000;
146 protected int m_sleepMsOnGiveInventory = 3000;
147 protected int m_sleepMsOnRequestAgentData = 100;
148 protected int m_sleepMsOnRequestInventoryData = 1000;
149 protected int m_sleepMsOnSetDamage = 5000;
150 protected int m_sleepMsOnTextBox = 1000;
151 protected int m_sleepMsOnAdjustSoundVolume = 100;
152 protected int m_sleepMsOnEjectFromLand = 5000;
153 protected int m_sleepMsOnAddToLandPassList = 100;
154 protected int m_sleepMsOnDialog = 1000;
155 protected int m_sleepMsOnRemoteLoadScript = 3000;
156 protected int m_sleepMsOnRemoteLoadScriptPin = 3000;
157 protected int m_sleepMsOnOpenRemoteDataChannel = 1000;
158 protected int m_sleepMsOnSendRemoteData = 3000;
159 protected int m_sleepMsOnRemoteDataReply = 3000;
160 protected int m_sleepMsOnCloseRemoteDataChannel = 1000;
161 protected int m_sleepMsOnSetPrimitiveParams = 200;
162 protected int m_sleepMsOnSetLinkPrimitiveParams = 200;
163 protected int m_sleepMsOnXorBase64Strings = 300;
164 protected int m_sleepMsOnSetParcelMusicURL = 2000;
165 protected int m_sleepMsOnGetPrimMediaParams = 1000;
166 protected int m_sleepMsOnGetLinkMedia = 1000;
167 protected int m_sleepMsOnSetPrimMediaParams = 1000;
168 protected int m_sleepMsOnSetLinkMedia = 1000;
169 protected int m_sleepMsOnClearPrimMedia = 1000;
170 protected int m_sleepMsOnClearLinkMedia = 1000;
171 protected int m_sleepMsOnRequestSimulatorData = 1000;
172 protected int m_sleepMsOnLoadURL = 10000;
173 protected int m_sleepMsOnParcelMediaCommandList = 2000;
174 protected int m_sleepMsOnParcelMediaQuery = 2000;
175 protected int m_sleepMsOnModPow = 1000;
176 protected int m_sleepMsOnSetPrimURL = 2000;
177 protected int m_sleepMsOnRefreshPrimURL = 20000;
178 protected int m_sleepMsOnMapDestination = 1000;
179 protected int m_sleepMsOnAddToLandBanList = 100;
180 protected int m_sleepMsOnRemoveFromLandPassList = 100;
181 protected int m_sleepMsOnRemoveFromLandBanList = 100;
182 protected int m_sleepMsOnResetLandBanList = 100;
183 protected int m_sleepMsOnResetLandPassList = 100;
184 protected int m_sleepMsOnGetParcelPrimOwners = 2000;
185 protected int m_sleepMsOnGetNumberOfNotecardLines = 100;
186 protected int m_sleepMsOnGetNotecardLine = 100;
125 protected string m_internalObjectHost = "lsl.opensim.local"; 187 protected string m_internalObjectHost = "lsl.opensim.local";
126 protected bool m_restrictEmail = false; 188 protected bool m_restrictEmail = false;
127 protected ISoundModule m_SoundModule = null; 189 protected ISoundModule m_SoundModule = null;
@@ -172,7 +234,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
172 protected int m_maxHitsPerPrimInCastRay = 16; 234 protected int m_maxHitsPerPrimInCastRay = 16;
173 protected int m_maxHitsPerObjectInCastRay = 16; 235 protected int m_maxHitsPerObjectInCastRay = 16;
174 protected bool m_detectExitsInCastRay = false; 236 protected bool m_detectExitsInCastRay = false;
175 protected bool m_filterPartsInCastRay = false;
176 protected bool m_doAttachmentsInCastRay = false; 237 protected bool m_doAttachmentsInCastRay = false;
177 protected int m_msThrottleInCastRay = 200; 238 protected int m_msThrottleInCastRay = 200;
178 protected int m_msPerRegionInCastRay = 40; 239 protected int m_msPerRegionInCastRay = 40;
@@ -183,6 +244,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
183 protected bool m_useMeshCacheInCastRay = true; 244 protected bool m_useMeshCacheInCastRay = true;
184 protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>(); 245 protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>();
185 246
247// protected Timer m_ShoutSayTimer;
248 protected int m_SayShoutCount = 0;
249 DateTime m_lastSayShoutCheck;
250
251 private Dictionary<string, string> MovementAnimationsForLSL =
252 new Dictionary<string, string> {
253 {"CROUCH", "Crouching"},
254 {"CROUCHWALK", "CrouchWalking"},
255 {"FALLDOWN", "Falling Down"},
256 {"FLY", "Flying"},
257 {"FLYSLOW", "FlyingSlow"},
258 {"HOVER", "Hovering"},
259 {"HOVER_UP", "Hovering Up"},
260 {"HOVER_DOWN", "Hovering Down"},
261 {"JUMP", "Jumping"},
262 {"LAND", "Landing"},
263 {"PREJUMP", "PreJumping"},
264 {"RUN", "Running"},
265 {"SIT","Sitting"},
266 {"SITGROUND","Sitting on Ground"},
267 {"STAND", "Standing"},
268 {"STANDUP", "Standing Up"},
269 {"STRIDE","Striding"},
270 {"SOFT_LAND", "Soft Landing"},
271 {"TURNLEFT", "Turning Left"},
272 {"TURNRIGHT", "Turning Right"},
273 {"WALK", "Walking"}
274 };
275
186 //An array of HTTP/1.1 headers that are not allowed to be used 276 //An array of HTTP/1.1 headers that are not allowed to be used
187 //as custom headers by llHTTPRequest. 277 //as custom headers by llHTTPRequest.
188 private string[] HttpStandardHeaders = 278 private string[] HttpStandardHeaders =
@@ -203,9 +293,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
203 public void Initialize( 293 public void Initialize(
204 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item) 294 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item)
205 { 295 {
296 m_lastSayShoutCheck = DateTime.UtcNow;
297
206 m_ScriptEngine = scriptEngine; 298 m_ScriptEngine = scriptEngine;
207 m_host = host; 299 m_host = host;
208 m_item = item; 300 m_item = item;
301 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
209 302
210 LoadConfig(); 303 LoadConfig();
211 304
@@ -228,6 +321,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
228 321
229 if (seConfig != null) 322 if (seConfig != null)
230 { 323 {
324 m_ScriptDelayFactor =
325 seConfig.GetFloat("ScriptDelayFactor", m_ScriptDelayFactor);
231 m_ScriptDistanceFactor = 326 m_ScriptDistanceFactor =
232 seConfig.GetFloat("ScriptDistanceLimitFactor", m_ScriptDistanceFactor); 327 seConfig.GetFloat("ScriptDistanceLimitFactor", m_ScriptDistanceFactor);
233 m_MinTimerInterval = 328 m_MinTimerInterval =
@@ -296,7 +391,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
296 m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay); 391 m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay);
297 m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay); 392 m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay);
298 m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay); 393 m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay);
299 m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay);
300 m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay); 394 m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay);
301 m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay); 395 m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay);
302 m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay); 396 m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay);
@@ -307,7 +401,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
307 } 401 }
308 402
309 IConfig smtpConfig = seConfigSource.Configs["SMTP"]; 403 IConfig smtpConfig = seConfigSource.Configs["SMTP"];
310 if (smtpConfig != null) 404 if (smtpConfig != null)
311 { 405 {
312 // there's an smtp config, so load in the snooze time. 406 // there's an smtp config, so load in the snooze time.
313 EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME); 407 EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
@@ -315,6 +409,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
315 m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost); 409 m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost);
316 } 410 }
317 } 411 }
412 m_sleepMsOnEmail = EMAIL_PAUSE_TIME * 1000;
318 } 413 }
319 414
320 public override Object InitializeLifetimeService() 415 public override Object InitializeLifetimeService()
@@ -330,6 +425,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
330 return lease; 425 return lease;
331 } 426 }
332 427
428 protected SceneObjectPart MonitoringObject()
429 {
430 UUID m = m_host.ParentGroup.MonitoringObject;
431 if (m == UUID.Zero)
432 return null;
433
434 SceneObjectPart p = m_ScriptEngine.World.GetSceneObjectPart(m);
435 if (p == null)
436 m_host.ParentGroup.MonitoringObject = UUID.Zero;
437
438 return p;
439 }
440
441 protected virtual void ScriptSleep(int delay)
442 {
443 delay = (int)((float)delay * m_ScriptDelayFactor);
444 if (delay == 0)
445 return;
446
447 Sleep(delay);
448 }
449
333 protected virtual void Sleep(int delay) 450 protected virtual void Sleep(int delay)
334 { 451 {
335 if (m_item == null) // Some unit tests don't set this 452 if (m_item == null) // Some unit tests don't set this
@@ -351,6 +468,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
351 get { return m_ScriptEngine.World; } 468 get { return m_ScriptEngine.World; }
352 } 469 }
353 470
471 [DebuggerNonUserCode]
354 public void state(string newState) 472 public void state(string newState)
355 { 473 {
356 m_ScriptEngine.SetState(m_item.ItemID, newState); 474 m_ScriptEngine.SetState(m_item.ItemID, newState);
@@ -360,6 +478,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
360 /// Reset the named script. The script must be present 478 /// Reset the named script. The script must be present
361 /// in the same prim. 479 /// in the same prim.
362 /// </summary> 480 /// </summary>
481 [DebuggerNonUserCode]
363 public void llResetScript() 482 public void llResetScript()
364 { 483 {
365 m_host.AddScriptLPS(1); 484 m_host.AddScriptLPS(1);
@@ -376,12 +495,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
376 { 495 {
377 UUID item; 496 UUID item;
378 497
379 m_host.AddScriptLPS(1); 498 if ((item = GetScriptByName(name)) == UUID.Zero)
380 499 {
381 if ((item = GetScriptByName(name)) != UUID.Zero) 500 m_host.AddScriptLPS(1);
382 m_ScriptEngine.ResetScript(item);
383 else
384 Error("llResetOtherScript", "Can't find script '" + name + "'"); 501 Error("llResetOtherScript", "Can't find script '" + name + "'");
502 return;
503 }
504 if(item == m_item.ItemID)
505 llResetScript();
506 else
507 {
508 m_host.AddScriptLPS(1);
509 m_ScriptEngine.ResetScript(item);
510 }
385 } 511 }
386 512
387 public LSL_Integer llGetScriptState(string name) 513 public LSL_Integer llGetScriptState(string name)
@@ -414,7 +540,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
414 540
415 if ((item = GetScriptByName(name)) != UUID.Zero) 541 if ((item = GetScriptByName(name)) != UUID.Zero)
416 { 542 {
417 m_ScriptEngine.SetScriptState(item, run == 0 ? false : true); 543 m_ScriptEngine.SetScriptState(item, run == 0 ? false : true, item == m_item.ItemID);
418 } 544 }
419 else 545 else
420 { 546 {
@@ -422,6 +548,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
422 } 548 }
423 } 549 }
424 550
551 public List<ScenePresence> GetLinkAvatars(int linkType)
552 {
553 List<ScenePresence> ret = new List<ScenePresence>();
554 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
555 return ret;
556
557 // List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
558 // this needs check
559 List<ScenePresence> avs = m_host.ParentGroup.GetSittingAvatars();
560 switch (linkType)
561 {
562 case ScriptBaseClass.LINK_SET:
563 return avs;
564
565 case ScriptBaseClass.LINK_ROOT:
566 return ret;
567
568 case ScriptBaseClass.LINK_ALL_OTHERS:
569 return avs;
570
571 case ScriptBaseClass.LINK_ALL_CHILDREN:
572 return avs;
573
574 case ScriptBaseClass.LINK_THIS:
575 return ret;
576
577 default:
578 if (linkType < 0)
579 return ret;
580
581 int partCount = m_host.ParentGroup.GetPartCount();
582
583 if (linkType <= partCount)
584 {
585 return ret;
586 }
587 else
588 {
589 linkType = linkType - partCount;
590 if (linkType > avs.Count)
591 {
592 return ret;
593 }
594 else
595 {
596 ret.Add(avs[linkType-1]);
597 return ret;
598 }
599 }
600 }
601 }
602
425 /// <summary> 603 /// <summary>
426 /// Get a given link entity from a linkset (linked objects and any sitting avatars). 604 /// Get a given link entity from a linkset (linked objects and any sitting avatars).
427 /// </summary> 605 /// </summary>
@@ -501,7 +679,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
501 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) 679 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
502 { 680 {
503 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 681 List<SceneObjectPart> ret = new List<SceneObjectPart>();
504 ret.Add(part); 682 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
683 return ret;
505 684
506 switch (linkType) 685 switch (linkType)
507 { 686 {
@@ -509,7 +688,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
509 return new List<SceneObjectPart>(part.ParentGroup.Parts); 688 return new List<SceneObjectPart>(part.ParentGroup.Parts);
510 689
511 case ScriptBaseClass.LINK_ROOT: 690 case ScriptBaseClass.LINK_ROOT:
512 ret = new List<SceneObjectPart>();
513 ret.Add(part.ParentGroup.RootPart); 691 ret.Add(part.ParentGroup.RootPart);
514 return ret; 692 return ret;
515 693
@@ -529,16 +707,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
529 return ret; 707 return ret;
530 708
531 case ScriptBaseClass.LINK_THIS: 709 case ScriptBaseClass.LINK_THIS:
710 ret.Add(part);
532 return ret; 711 return ret;
533 712
534 default: 713 default:
535 if (linkType < 0) 714 if (linkType < 0)
536 return new List<SceneObjectPart>(); 715 return ret;
537 716
538 SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType); 717 SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType);
539 if (target == null) 718 if (target == null)
540 return new List<SceneObjectPart>(); 719 return ret;
541 ret = new List<SceneObjectPart>();
542 ret.Add(target); 720 ret.Add(target);
543 return ret; 721 return ret;
544 } 722 }
@@ -648,8 +826,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
648 public LSL_Float llFrand(double mag) 826 public LSL_Float llFrand(double mag)
649 { 827 {
650 m_host.AddScriptLPS(1); 828 m_host.AddScriptLPS(1);
651 829 lock (Util.RandomClass)
652 return Util.RandomClass.NextDouble() * mag; 830 {
831 return Util.RandomClass.NextDouble() * mag;
832 }
653 } 833 }
654 834
655 public LSL_Integer llFloor(double f) 835 public LSL_Integer llFloor(double f)
@@ -700,31 +880,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
700 880
701 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 881 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
702 882
703 /// <summary> 883 // Utility function for llRot2Euler
704 /// Convert an LSL rotation to a Euler vector. 884
705 /// </summary> 885 public LSL_Vector llRot2Euler(LSL_Rotation q1)
706 /// <remarks>
707 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
708 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
709 /// </remarks>
710 /// <param name="r"></param>
711 /// <returns></returns>
712 public LSL_Vector llRot2Euler(LSL_Rotation r)
713 { 886 {
714 m_host.AddScriptLPS(1); 887 m_host.AddScriptLPS(1);
888 LSL_Vector eul = new LSL_Vector();
715 889
716 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 890 double sqw = q1.s*q1.s;
717 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 891 double sqx = q1.x*q1.x;
718 if (m == 0.0) return new LSL_Vector(); 892 double sqy = q1.z*q1.z;
719 double x = Math.Atan2(-v.y, v.z); 893 double sqz = q1.y*q1.y;
720 double sin = v.x / m; 894 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
721 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. 895 double test = q1.x*q1.z + q1.y*q1.s;
722 double y = Math.Asin(sin); 896 if (test > 0.4999*unit) { // singularity at north pole
723 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation 897 eul.z = 2 * Math.Atan2(q1.x,q1.s);
724 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))); 898 eul.y = Math.PI/2;
725 double z = Math.Atan2(v.y, v.x); 899 eul.x = 0;
726 900 return eul;
727 return new LSL_Vector(x, y, z); 901 }
902 if (test < -0.4999*unit) { // singularity at south pole
903 eul.z = -2 * Math.Atan2(q1.x,q1.s);
904 eul.y = -Math.PI/2;
905 eul.x = 0;
906 return eul;
907 }
908 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
909 eul.y = Math.Asin(2*test/unit);
910 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
911 return eul;
728 } 912 }
729 913
730 /* From wiki: 914 /* From wiki:
@@ -777,18 +961,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
777 m_host.AddScriptLPS(1); 961 m_host.AddScriptLPS(1);
778 962
779 double x,y,z,s; 963 double x,y,z,s;
780 964 v.x *= 0.5;
781 double c1 = Math.Cos(v.x * 0.5); 965 v.y *= 0.5;
782 double c2 = Math.Cos(v.y * 0.5); 966 v.z *= 0.5;
783 double c3 = Math.Cos(v.z * 0.5); 967 double c1 = Math.Cos(v.x);
784 double s1 = Math.Sin(v.x * 0.5); 968 double c2 = Math.Cos(v.y);
785 double s2 = Math.Sin(v.y * 0.5); 969 double c1c2 = c1 * c2;
786 double s3 = Math.Sin(v.z * 0.5); 970 double s1 = Math.Sin(v.x);
787 971 double s2 = Math.Sin(v.y);
788 x = s1 * c2 * c3 + c1 * s2 * s3; 972 double s1s2 = s1 * s2;
789 y = c1 * s2 * c3 - s1 * c2 * s3; 973 double c1s2 = c1 * s2;
790 z = s1 * s2 * c3 + c1 * c2 * s3; 974 double s1c2 = s1 * c2;
791 s = c1 * c2 * c3 - s1 * s2 * s3; 975 double c3 = Math.Cos(v.z);
976 double s3 = Math.Sin(v.z);
977
978 x = s1c2 * c3 + c1s2 * s3;
979 y = c1s2 * c3 - s1c2 * s3;
980 z = s1s2 * c3 + c1c2 * s3;
981 s = c1c2 * c3 - s1s2 * s3;
792 982
793 return new LSL_Rotation(x, y, z, s); 983 return new LSL_Rotation(x, y, z, s);
794 } 984 }
@@ -926,75 +1116,74 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
926 { 1116 {
927 //A and B should both be normalized 1117 //A and B should both be normalized
928 m_host.AddScriptLPS(1); 1118 m_host.AddScriptLPS(1);
929 LSL_Rotation rotBetween; 1119 /* This method is more accurate than the SL one, and thus causes problems
930 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 1120 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
931 // continue calculation. 1121
932 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 1122 double dotProduct = LSL_Vector.Dot(a, b);
1123 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
1124 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
1125 double angle = Math.Acos(dotProduct / magProduct);
1126 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
1127 double s = Math.Sin(angle / 2);
1128
1129 double x = axis.x * s;
1130 double y = axis.y * s;
1131 double z = axis.z * s;
1132 double w = Math.Cos(angle / 2);
1133
1134 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
1135 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
1136
1137 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
1138 */
1139
1140 // This method mimics the 180 errors found in SL
1141 // See www.euclideanspace.com... angleBetween
1142 LSL_Vector vec_a = a;
1143 LSL_Vector vec_b = b;
1144
1145 // Eliminate zero length
1146 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
1147 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
1148 if (vec_a_mag < 0.00001 ||
1149 vec_b_mag < 0.00001)
933 { 1150 {
934 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 1151 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
935 } 1152 }
936 else 1153
1154 // Normalize
1155 vec_a = llVecNorm(vec_a);
1156 vec_b = llVecNorm(vec_b);
1157
1158 // Calculate axis and rotation angle
1159 LSL_Vector axis = vec_a % vec_b;
1160 LSL_Float cos_theta = vec_a * vec_b;
1161
1162 // Check if parallel
1163 if (cos_theta > 0.99999)
937 { 1164 {
938 a = LSL_Vector.Norm(a); 1165 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
939 b = LSL_Vector.Norm(b); 1166 }
940 double dotProduct = LSL_Vector.Dot(a, b); 1167
941 // There are two degenerate cases possible. These are for vectors 180 or 1168 // Check if anti-parallel
942 // 0 degrees apart. These have to be detected and handled individually. 1169 else if (cos_theta < -0.99999)
943 // 1170 {
944 // Check for vectors 180 degrees apart. 1171 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
945 // A dot product of -1 would mean the angle between vectors is 180 degrees. 1172 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
946 if (dotProduct < -0.9999999f) 1173 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
947 { 1174 }
948 // First assume X axis is orthogonal to the vectors. 1175 else // other rotation
949 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 1176 {
950 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 1177 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
951 // Check for near zero vector. A very small non-zero number here will create 1178 axis = llVecNorm(axis);
952 // a rotation in an undesired direction. 1179 double x, y, z, s, t;
953 if (LSL_Vector.Mag(orthoVector) > 0.0001) 1180 s = Math.Cos(theta);
954 { 1181 t = Math.Sin(theta);
955 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 1182 x = axis.x * t;
956 } 1183 y = axis.y * t;
957 // If the magnitude of the vector was near zero, then assume the X axis is not 1184 z = axis.z * t;
958 // orthogonal and use the Z axis instead. 1185 return new LSL_Rotation(x,y,z,s);
959 else
960 {
961 // Set 180 z rotation.
962 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
963 }
964 }
965 // Check for parallel vectors.
966 // A dot product of 1 would mean the angle between vectors is 0 degrees.
967 else if (dotProduct > 0.9999999f)
968 {
969 // Set zero rotation.
970 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
971 }
972 else
973 {
974 // All special checks have been performed so get the axis of rotation.
975 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
976 // Quarternion s value is the length of the unit vector + dot product.
977 double qs = 1.0 + dotProduct;
978 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
979 // Normalize the rotation.
980 double mag = LSL_Rotation.Mag(rotBetween);
981 // We shouldn't have to worry about a divide by zero here. The qs value will be
982 // non-zero because we already know if we're here, then the dotProduct is not -1 so
983 // qs will not be zero. Also, we've already handled the input vectors being zero so the
984 // crossProduct vector should also not be zero.
985 rotBetween.x = rotBetween.x / mag;
986 rotBetween.y = rotBetween.y / mag;
987 rotBetween.z = rotBetween.z / mag;
988 rotBetween.s = rotBetween.s / mag;
989 // Check for undefined values and set zero rotation if any found. This code might not actually be required
990 // any longer since zero vectors are checked for at the top.
991 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
992 {
993 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
994 }
995 }
996 } 1186 }
997 return rotBetween;
998 } 1187 }
999 1188
1000 public void llWhisper(int channelID, string text) 1189 public void llWhisper(int channelID, string text)
@@ -1012,10 +1201,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1012 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text); 1201 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
1013 } 1202 }
1014 1203
1204 private void CheckSayShoutTime()
1205 {
1206 DateTime now = DateTime.UtcNow;
1207 if ((now - m_lastSayShoutCheck).Ticks > 10000000) // 1sec
1208 {
1209 m_lastSayShoutCheck = now;
1210 m_SayShoutCount = 0;
1211 }
1212 else
1213 m_SayShoutCount++;
1214 }
1215
1015 public void llSay(int channelID, string text) 1216 public void llSay(int channelID, string text)
1016 { 1217 {
1017 m_host.AddScriptLPS(1); 1218 m_host.AddScriptLPS(1);
1018 1219
1220 if (channelID == 0)
1221// m_SayShoutCount++;
1222 CheckSayShoutTime();
1223
1224 if (m_SayShoutCount >= 11)
1225 ScriptSleep(2000);
1226
1019 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 1227 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
1020 { 1228 {
1021 Console.WriteLine(text); 1229 Console.WriteLine(text);
@@ -1038,6 +1246,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1038 { 1246 {
1039 m_host.AddScriptLPS(1); 1247 m_host.AddScriptLPS(1);
1040 1248
1249 if (channelID == 0)
1250// m_SayShoutCount++;
1251 CheckSayShoutTime();
1252
1253 if (m_SayShoutCount >= 11)
1254 ScriptSleep(2000);
1255
1041 if (text.Length > 1023) 1256 if (text.Length > 1023)
1042 text = text.Substring(0, 1023); 1257 text = text.Substring(0, 1023);
1043 1258
@@ -1062,8 +1277,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1062 1277
1063 m_host.AddScriptLPS(1); 1278 m_host.AddScriptLPS(1);
1064 1279
1065 World.SimChat(Utils.StringToBytes(text), 1280 // debug channel is also sent to avatars
1066 ChatTypeEnum.Region, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); 1281 if (channelID == ScriptBaseClass.DEBUG_CHANNEL)
1282 {
1283 World.SimChat(Utils.StringToBytes(text),
1284 ChatTypeEnum.Shout, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
1285
1286 }
1067 1287
1068 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1288 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1069 if (wComm != null) 1289 if (wComm != null)
@@ -1078,16 +1298,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1078 m_host.AddScriptLPS(1); 1298 m_host.AddScriptLPS(1);
1079 1299
1080 if (channel == ScriptBaseClass.DEBUG_CHANNEL) 1300 if (channel == ScriptBaseClass.DEBUG_CHANNEL)
1081 {
1082 return; 1301 return;
1083 }
1084 1302
1085 UUID TargetID; 1303 UUID TargetID;
1086 UUID.TryParse(target, out TargetID); 1304 UUID.TryParse(target, out TargetID);
1087 1305
1088 World.SimChatToAgent(TargetID, Utils.StringToBytes(msg),
1089 channel, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
1090
1091 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1306 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1092 if (wComm != null) 1307 if (wComm != null)
1093 wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg); 1308 wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg);
@@ -1346,10 +1561,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1346 return detectedParams.TouchUV; 1561 return detectedParams.TouchUV;
1347 } 1562 }
1348 1563
1564 [DebuggerNonUserCode]
1349 public virtual void llDie() 1565 public virtual void llDie()
1350 { 1566 {
1351 m_host.AddScriptLPS(1); 1567 m_host.AddScriptLPS(1);
1352 throw new SelfDeleteException(); 1568 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1353 } 1569 }
1354 1570
1355 public LSL_Float llGround(LSL_Vector offset) 1571 public LSL_Float llGround(LSL_Vector offset)
@@ -1420,6 +1636,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1420 1636
1421 public void llSetStatus(int status, int value) 1637 public void llSetStatus(int status, int value)
1422 { 1638 {
1639 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1640 return;
1423 m_host.AddScriptLPS(1); 1641 m_host.AddScriptLPS(1);
1424 1642
1425 int statusrotationaxis = 0; 1643 int statusrotationaxis = 0;
@@ -1431,18 +1649,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1431 SceneObjectGroup group = m_host.ParentGroup; 1649 SceneObjectGroup group = m_host.ParentGroup;
1432 bool allow = true; 1650 bool allow = true;
1433 1651
1652 int maxprims = World.m_linksetPhysCapacity;
1653 bool checkShape = (maxprims > 0 && group.PrimCount > maxprims);
1654
1434 foreach (SceneObjectPart part in group.Parts) 1655 foreach (SceneObjectPart part in group.Parts)
1435 { 1656 {
1657 if (part.PhysicsShapeType == (byte)PhysicsShapeType.None)
1658 continue;
1659
1436 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) 1660 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
1437 { 1661 {
1438 allow = false; 1662 allow = false;
1439 break; 1663 break;
1440 } 1664 }
1665 if (checkShape)
1666 {
1667 if (--maxprims < 0)
1668 {
1669 allow = false;
1670 break;
1671 }
1672 }
1441 } 1673 }
1442 1674
1443 if (!allow) 1675 if (!allow)
1444 return; 1676 return;
1445 1677
1678 if (m_host.ParentGroup.RootPart.PhysActor != null &&
1679 m_host.ParentGroup.RootPart.PhysActor.IsPhysical)
1680 return;
1681
1446 m_host.ScriptSetPhysicsStatus(true); 1682 m_host.ScriptSetPhysicsStatus(true);
1447 } 1683 }
1448 else 1684 else
@@ -1586,6 +1822,53 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1586 return 0; 1822 return 0;
1587 } 1823 }
1588 1824
1825 public LSL_Integer llScaleByFactor(double scaling_factor)
1826 {
1827 m_host.AddScriptLPS(1);
1828 SceneObjectGroup group = m_host.ParentGroup;
1829
1830 if(scaling_factor < 1e-6)
1831 return ScriptBaseClass.FALSE;
1832 if(scaling_factor > 1e6)
1833 return ScriptBaseClass.FALSE;
1834
1835 if (group == null || group.IsDeleted || group.inTransit)
1836 return ScriptBaseClass.FALSE;
1837
1838 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
1839 return ScriptBaseClass.FALSE;
1840
1841 if (group.RootPart.KeyframeMotion != null)
1842 return ScriptBaseClass.FALSE;
1843
1844 if(group.GroupResize(scaling_factor))
1845 return ScriptBaseClass.TRUE;
1846 else
1847 return ScriptBaseClass.FALSE;
1848 }
1849
1850 public LSL_Float llGetMaxScaleFactor()
1851 {
1852 m_host.AddScriptLPS(1);
1853 SceneObjectGroup group = m_host.ParentGroup;
1854
1855 if (group == null || group.IsDeleted || group.inTransit)
1856 return 1.0f;
1857
1858 return (LSL_Float)group.GetMaxGroupResizeScale();
1859 }
1860
1861 public LSL_Float llGetMinScaleFactor()
1862 {
1863 m_host.AddScriptLPS(1);
1864 SceneObjectGroup group = m_host.ParentGroup;
1865
1866 if (group == null || group.IsDeleted || group.inTransit)
1867 return 1.0f;
1868
1869 return (LSL_Float)group.GetMinGroupResizeScale();
1870 }
1871
1589 public void llSetScale(LSL_Vector scale) 1872 public void llSetScale(LSL_Vector scale)
1590 { 1873 {
1591 m_host.AddScriptLPS(1); 1874 m_host.AddScriptLPS(1);
@@ -1641,6 +1924,50 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1641 { 1924 {
1642 m_host.AddScriptLPS(1); 1925 m_host.AddScriptLPS(1);
1643 1926
1927 SetColor(m_host, color, face);
1928 }
1929
1930 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1931 {
1932 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1933 return;
1934
1935 Primitive.TextureEntry tex = part.Shape.Textures;
1936 int nsides = GetNumberOfSides(part);
1937 Color4 texcolor;
1938
1939 if (face >= 0 && face < nsides)
1940 {
1941 texcolor = tex.CreateFace((uint)face).RGBA;
1942 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1943 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1944 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1945 tex.FaceTextures[face].RGBA = texcolor;
1946 part.UpdateTextureEntry(tex.GetBytes());
1947 return;
1948 }
1949 else if (face == ScriptBaseClass.ALL_SIDES)
1950 {
1951 for (uint i = 0; i < nsides; i++)
1952 {
1953 if (tex.FaceTextures[i] != null)
1954 {
1955 texcolor = tex.FaceTextures[i].RGBA;
1956 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1957 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1958 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1959 tex.FaceTextures[i].RGBA = texcolor;
1960 }
1961 texcolor = tex.DefaultTexture.RGBA;
1962 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1963 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1964 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1965 tex.DefaultTexture.RGBA = texcolor;
1966 }
1967 part.UpdateTextureEntry(tex.GetBytes());
1968 return;
1969 }
1970
1644 if (face == ScriptBaseClass.ALL_SIDES) 1971 if (face == ScriptBaseClass.ALL_SIDES)
1645 face = SceneObjectPart.ALL_SIDES; 1972 face = SceneObjectPart.ALL_SIDES;
1646 1973
@@ -1714,15 +2041,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1714 } 2041 }
1715 } 2042 }
1716 2043
2044/*
2045 public void llSetContentType(LSL_Key id, LSL_Integer content_type)
2046 {
2047 if (m_UrlModule != null)
2048 {
2049 string type = "text.plain";
2050 if (content_type == (int)ScriptBaseClass.CONTENT_TYPE_HTML)
2051 type = "text/html";
2052
2053 m_UrlModule.HttpContentType(new UUID(id),type);
2054 }
2055 }
2056*/
1717 public void SetTexGen(SceneObjectPart part, int face,int style) 2057 public void SetTexGen(SceneObjectPart part, int face,int style)
1718 { 2058 {
2059 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2060 return;
2061
1719 Primitive.TextureEntry tex = part.Shape.Textures; 2062 Primitive.TextureEntry tex = part.Shape.Textures;
1720 MappingType textype; 2063 MappingType textype;
1721 textype = MappingType.Default; 2064 textype = MappingType.Default;
1722 if (style == (int)ScriptBaseClass.PRIM_TEXGEN_PLANAR) 2065 if (style == (int)ScriptBaseClass.PRIM_TEXGEN_PLANAR)
1723 textype = MappingType.Planar; 2066 textype = MappingType.Planar;
1724 2067
1725 if (face >= 0 && face < GetNumberOfSides(part)) 2068 int nsides = GetNumberOfSides(part);
2069
2070 if (face >= 0 && face < nsides)
1726 { 2071 {
1727 tex.CreateFace((uint) face); 2072 tex.CreateFace((uint) face);
1728 tex.FaceTextures[face].TexMapType = textype; 2073 tex.FaceTextures[face].TexMapType = textype;
@@ -1731,7 +2076,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1731 } 2076 }
1732 else if (face == ScriptBaseClass.ALL_SIDES) 2077 else if (face == ScriptBaseClass.ALL_SIDES)
1733 { 2078 {
1734 for (uint i = 0; i < GetNumberOfSides(part); i++) 2079 for (uint i = 0; i < nsides; i++)
1735 { 2080 {
1736 if (tex.FaceTextures[i] != null) 2081 if (tex.FaceTextures[i] != null)
1737 { 2082 {
@@ -1746,8 +2091,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1746 2091
1747 public void SetGlow(SceneObjectPart part, int face, float glow) 2092 public void SetGlow(SceneObjectPart part, int face, float glow)
1748 { 2093 {
2094 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2095 return;
2096
1749 Primitive.TextureEntry tex = part.Shape.Textures; 2097 Primitive.TextureEntry tex = part.Shape.Textures;
1750 if (face >= 0 && face < GetNumberOfSides(part)) 2098 int nsides = GetNumberOfSides(part);
2099
2100 if (face >= 0 && face < nsides)
1751 { 2101 {
1752 tex.CreateFace((uint) face); 2102 tex.CreateFace((uint) face);
1753 tex.FaceTextures[face].Glow = glow; 2103 tex.FaceTextures[face].Glow = glow;
@@ -1756,7 +2106,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1756 } 2106 }
1757 else if (face == ScriptBaseClass.ALL_SIDES) 2107 else if (face == ScriptBaseClass.ALL_SIDES)
1758 { 2108 {
1759 for (uint i = 0; i < GetNumberOfSides(part); i++) 2109 for (uint i = 0; i < nsides; i++)
1760 { 2110 {
1761 if (tex.FaceTextures[i] != null) 2111 if (tex.FaceTextures[i] != null)
1762 { 2112 {
@@ -1771,6 +2121,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1771 2121
1772 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 2122 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1773 { 2123 {
2124 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2125 return;
1774 2126
1775 Shininess sval = new Shininess(); 2127 Shininess sval = new Shininess();
1776 2128
@@ -1793,8 +2145,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1793 break; 2145 break;
1794 } 2146 }
1795 2147
2148 int nsides = GetNumberOfSides(part);
2149
1796 Primitive.TextureEntry tex = part.Shape.Textures; 2150 Primitive.TextureEntry tex = part.Shape.Textures;
1797 if (face >= 0 && face < GetNumberOfSides(part)) 2151 if (face >= 0 && face < nsides)
1798 { 2152 {
1799 tex.CreateFace((uint) face); 2153 tex.CreateFace((uint) face);
1800 tex.FaceTextures[face].Shiny = sval; 2154 tex.FaceTextures[face].Shiny = sval;
@@ -1804,7 +2158,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1804 } 2158 }
1805 else if (face == ScriptBaseClass.ALL_SIDES) 2159 else if (face == ScriptBaseClass.ALL_SIDES)
1806 { 2160 {
1807 for (uint i = 0; i < GetNumberOfSides(part); i++) 2161 for (uint i = 0; i < nsides; i++)
1808 { 2162 {
1809 if (tex.FaceTextures[i] != null) 2163 if (tex.FaceTextures[i] != null)
1810 { 2164 {
@@ -1821,8 +2175,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1821 2175
1822 public void SetFullBright(SceneObjectPart part, int face, bool bright) 2176 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1823 { 2177 {
2178 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2179 return;
2180
2181 int nsides = GetNumberOfSides(part);
1824 Primitive.TextureEntry tex = part.Shape.Textures; 2182 Primitive.TextureEntry tex = part.Shape.Textures;
1825 if (face >= 0 && face < GetNumberOfSides(part)) 2183 if (face >= 0 && face < nsides)
1826 { 2184 {
1827 tex.CreateFace((uint) face); 2185 tex.CreateFace((uint) face);
1828 tex.FaceTextures[face].Fullbright = bright; 2186 tex.FaceTextures[face].Fullbright = bright;
@@ -1831,7 +2189,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1831 } 2189 }
1832 else if (face == ScriptBaseClass.ALL_SIDES) 2190 else if (face == ScriptBaseClass.ALL_SIDES)
1833 { 2191 {
1834 for (uint i = 0; i < GetNumberOfSides(part); i++) 2192 for (uint i = 0; i < nsides; i++)
1835 { 2193 {
1836 if (tex.FaceTextures[i] != null) 2194 if (tex.FaceTextures[i] != null)
1837 { 2195 {
@@ -1854,15 +2212,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1854 protected LSL_Float GetAlpha(SceneObjectPart part, int face) 2212 protected LSL_Float GetAlpha(SceneObjectPart part, int face)
1855 { 2213 {
1856 Primitive.TextureEntry tex = part.Shape.Textures; 2214 Primitive.TextureEntry tex = part.Shape.Textures;
2215 int nsides = GetNumberOfSides(part);
1857 if (face == ScriptBaseClass.ALL_SIDES) 2216 if (face == ScriptBaseClass.ALL_SIDES)
1858 { 2217 {
1859 int i; 2218 int i;
1860 double sum = 0.0; 2219 double sum = 0.0;
1861 for (i = 0 ; i < GetNumberOfSides(part); i++) 2220 for (i = 0 ; i < nsides; i++)
1862 sum += (double)tex.GetFace((uint)i).RGBA.A; 2221 sum += (double)tex.GetFace((uint)i).RGBA.A;
1863 return sum; 2222 return sum;
1864 } 2223 }
1865 if (face >= 0 && face < GetNumberOfSides(part)) 2224 if (face >= 0 && face < nsides)
1866 { 2225 {
1867 return (double)tex.GetFace((uint)face).RGBA.A; 2226 return (double)tex.GetFace((uint)face).RGBA.A;
1868 } 2227 }
@@ -1881,16 +2240,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1881 m_host.AddScriptLPS(1); 2240 m_host.AddScriptLPS(1);
1882 2241
1883 List<SceneObjectPart> parts = GetLinkParts(linknumber); 2242 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1884 2243 if (parts.Count > 0)
1885 foreach (SceneObjectPart part in parts) 2244 {
1886 SetAlpha(part, alpha, face); 2245 try
2246 {
2247 foreach (SceneObjectPart part in parts)
2248 SetAlpha(part, alpha, face);
2249 }
2250 finally { }
2251 }
1887 } 2252 }
1888 2253
1889 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 2254 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1890 { 2255 {
2256 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2257 return;
2258
1891 Primitive.TextureEntry tex = part.Shape.Textures; 2259 Primitive.TextureEntry tex = part.Shape.Textures;
2260 int nsides = GetNumberOfSides(part);
1892 Color4 texcolor; 2261 Color4 texcolor;
1893 if (face >= 0 && face < GetNumberOfSides(part)) 2262
2263 if (face >= 0 && face < nsides)
1894 { 2264 {
1895 texcolor = tex.CreateFace((uint)face).RGBA; 2265 texcolor = tex.CreateFace((uint)face).RGBA;
1896 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); 2266 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
@@ -1900,7 +2270,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1900 } 2270 }
1901 else if (face == ScriptBaseClass.ALL_SIDES) 2271 else if (face == ScriptBaseClass.ALL_SIDES)
1902 { 2272 {
1903 for (int i = 0; i < GetNumberOfSides(part); i++) 2273 for (int i = 0; i < nsides; i++)
1904 { 2274 {
1905 if (tex.FaceTextures[i] != null) 2275 if (tex.FaceTextures[i] != null)
1906 { 2276 {
@@ -1940,7 +2310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1940 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 2310 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
1941 float wind, float tension, LSL_Vector Force) 2311 float wind, float tension, LSL_Vector Force)
1942 { 2312 {
1943 if (part == null) 2313 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1944 return; 2314 return;
1945 2315
1946 if (flexi) 2316 if (flexi)
@@ -1981,7 +2351,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1981 /// <param name="falloff"></param> 2351 /// <param name="falloff"></param>
1982 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 2352 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
1983 { 2353 {
1984 if (part == null) 2354 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1985 return; 2355 return;
1986 2356
1987 if (light) 2357 if (light)
@@ -2014,11 +2384,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2014 Primitive.TextureEntry tex = part.Shape.Textures; 2384 Primitive.TextureEntry tex = part.Shape.Textures;
2015 Color4 texcolor; 2385 Color4 texcolor;
2016 LSL_Vector rgb = new LSL_Vector(); 2386 LSL_Vector rgb = new LSL_Vector();
2387 int nsides = GetNumberOfSides(part);
2388
2017 if (face == ScriptBaseClass.ALL_SIDES) 2389 if (face == ScriptBaseClass.ALL_SIDES)
2018 { 2390 {
2019 int i; 2391 int i;
2020 2392 for (i = 0; i < nsides; i++)
2021 for (i = 0 ; i < GetNumberOfSides(part); i++)
2022 { 2393 {
2023 texcolor = tex.GetFace((uint)i).RGBA; 2394 texcolor = tex.GetFace((uint)i).RGBA;
2024 rgb.x += texcolor.R; 2395 rgb.x += texcolor.R;
@@ -2026,14 +2397,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2026 rgb.z += texcolor.B; 2397 rgb.z += texcolor.B;
2027 } 2398 }
2028 2399
2029 rgb.x /= (float)GetNumberOfSides(part); 2400 float invnsides = 1.0f / (float)nsides;
2030 rgb.y /= (float)GetNumberOfSides(part); 2401
2031 rgb.z /= (float)GetNumberOfSides(part); 2402 rgb.x *= invnsides;
2403 rgb.y *= invnsides;
2404 rgb.z *= invnsides;
2032 2405
2033 return rgb; 2406 return rgb;
2034 } 2407 }
2035 2408 if (face >= 0 && face < nsides)
2036 if (face >= 0 && face < GetNumberOfSides(part))
2037 { 2409 {
2038 texcolor = tex.GetFace((uint)face).RGBA; 2410 texcolor = tex.GetFace((uint)face).RGBA;
2039 rgb.x = texcolor.R; 2411 rgb.x = texcolor.R;
@@ -2052,6 +2424,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2052 { 2424 {
2053 m_host.AddScriptLPS(1); 2425 m_host.AddScriptLPS(1);
2054 SetTexture(m_host, texture, face); 2426 SetTexture(m_host, texture, face);
2427 ScriptSleep(m_sleepMsOnSetTexture);
2055 } 2428 }
2056 2429
2057 public void llSetLinkTexture(int linknumber, string texture, int face) 2430 public void llSetLinkTexture(int linknumber, string texture, int face)
@@ -2059,13 +2432,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2059 m_host.AddScriptLPS(1); 2432 m_host.AddScriptLPS(1);
2060 2433
2061 List<SceneObjectPart> parts = GetLinkParts(linknumber); 2434 List<SceneObjectPart> parts = GetLinkParts(linknumber);
2062 2435 if (parts.Count > 0)
2063 foreach (SceneObjectPart part in parts) 2436 {
2064 SetTexture(part, texture, face); 2437 try
2438 {
2439 foreach (SceneObjectPart part in parts)
2440 SetTexture(part, texture, face);
2441 }
2442 finally { }
2443 }
2444 ScriptSleep(m_sleepMsOnSetLinkTexture);
2065 } 2445 }
2066 2446
2067 protected void SetTexture(SceneObjectPart part, string texture, int face) 2447 protected void SetTexture(SceneObjectPart part, string texture, int face)
2068 { 2448 {
2449 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2450 return;
2451
2069 UUID textureID = new UUID(); 2452 UUID textureID = new UUID();
2070 2453
2071 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture); 2454 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
@@ -2075,9 +2458,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2075 return; 2458 return;
2076 } 2459 }
2077 2460
2461
2078 Primitive.TextureEntry tex = part.Shape.Textures; 2462 Primitive.TextureEntry tex = part.Shape.Textures;
2463 int nsides = GetNumberOfSides(part);
2079 2464
2080 if (face >= 0 && face < GetNumberOfSides(part)) 2465 if (face >= 0 && face < nsides)
2081 { 2466 {
2082 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); 2467 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
2083 texface.TextureID = textureID; 2468 texface.TextureID = textureID;
@@ -2087,7 +2472,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2087 } 2472 }
2088 else if (face == ScriptBaseClass.ALL_SIDES) 2473 else if (face == ScriptBaseClass.ALL_SIDES)
2089 { 2474 {
2090 for (uint i = 0; i < GetNumberOfSides(part); i++) 2475 for (uint i = 0; i < nsides; i++)
2091 { 2476 {
2092 if (tex.FaceTextures[i] != null) 2477 if (tex.FaceTextures[i] != null)
2093 { 2478 {
@@ -2105,12 +2490,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2105 m_host.AddScriptLPS(1); 2490 m_host.AddScriptLPS(1);
2106 2491
2107 ScaleTexture(m_host, u, v, face); 2492 ScaleTexture(m_host, u, v, face);
2493 ScriptSleep(m_sleepMsOnScaleTexture);
2108 } 2494 }
2109 2495
2110 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 2496 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
2111 { 2497 {
2498 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2499 return;
2500
2112 Primitive.TextureEntry tex = part.Shape.Textures; 2501 Primitive.TextureEntry tex = part.Shape.Textures;
2113 if (face >= 0 && face < GetNumberOfSides(part)) 2502 int nsides = GetNumberOfSides(part);
2503
2504 if (face >= 0 && face < nsides)
2114 { 2505 {
2115 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); 2506 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
2116 texface.RepeatU = (float)u; 2507 texface.RepeatU = (float)u;
@@ -2121,7 +2512,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2121 } 2512 }
2122 if (face == ScriptBaseClass.ALL_SIDES) 2513 if (face == ScriptBaseClass.ALL_SIDES)
2123 { 2514 {
2124 for (int i = 0; i < GetNumberOfSides(part); i++) 2515 for (int i = 0; i < nsides; i++)
2125 { 2516 {
2126 if (tex.FaceTextures[i] != null) 2517 if (tex.FaceTextures[i] != null)
2127 { 2518 {
@@ -2140,12 +2531,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2140 { 2531 {
2141 m_host.AddScriptLPS(1); 2532 m_host.AddScriptLPS(1);
2142 OffsetTexture(m_host, u, v, face); 2533 OffsetTexture(m_host, u, v, face);
2534 ScriptSleep(m_sleepMsOnOffsetTexture);
2143 } 2535 }
2144 2536
2145 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2537 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
2146 { 2538 {
2539 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2540 return;
2541
2147 Primitive.TextureEntry tex = part.Shape.Textures; 2542 Primitive.TextureEntry tex = part.Shape.Textures;
2148 if (face >= 0 && face < GetNumberOfSides(part)) 2543 int nsides = GetNumberOfSides(part);
2544
2545 if (face >= 0 && face < nsides)
2149 { 2546 {
2150 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); 2547 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
2151 texface.OffsetU = (float)u; 2548 texface.OffsetU = (float)u;
@@ -2156,7 +2553,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2156 } 2553 }
2157 if (face == ScriptBaseClass.ALL_SIDES) 2554 if (face == ScriptBaseClass.ALL_SIDES)
2158 { 2555 {
2159 for (int i = 0; i < GetNumberOfSides(part); i++) 2556 for (int i = 0; i < nsides; i++)
2160 { 2557 {
2161 if (tex.FaceTextures[i] != null) 2558 if (tex.FaceTextures[i] != null)
2162 { 2559 {
@@ -2175,12 +2572,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2175 { 2572 {
2176 m_host.AddScriptLPS(1); 2573 m_host.AddScriptLPS(1);
2177 RotateTexture(m_host, rotation, face); 2574 RotateTexture(m_host, rotation, face);
2575 ScriptSleep(m_sleepMsOnRotateTexture);
2178 } 2576 }
2179 2577
2180 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2578 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
2181 { 2579 {
2580 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2581 return;
2582
2182 Primitive.TextureEntry tex = part.Shape.Textures; 2583 Primitive.TextureEntry tex = part.Shape.Textures;
2183 if (face >= 0 && face < GetNumberOfSides(part)) 2584 int nsides = GetNumberOfSides(part);
2585
2586 if (face >= 0 && face < nsides)
2184 { 2587 {
2185 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); 2588 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
2186 texface.Rotation = (float)rotation; 2589 texface.Rotation = (float)rotation;
@@ -2190,7 +2593,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2190 } 2593 }
2191 if (face == ScriptBaseClass.ALL_SIDES) 2594 if (face == ScriptBaseClass.ALL_SIDES)
2192 { 2595 {
2193 for (int i = 0; i < GetNumberOfSides(part); i++) 2596 for (int i = 0; i < nsides; i++)
2194 { 2597 {
2195 if (tex.FaceTextures[i] != null) 2598 if (tex.FaceTextures[i] != null)
2196 { 2599 {
@@ -2212,12 +2615,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2212 protected LSL_String GetTexture(SceneObjectPart part, int face) 2615 protected LSL_String GetTexture(SceneObjectPart part, int face)
2213 { 2616 {
2214 Primitive.TextureEntry tex = part.Shape.Textures; 2617 Primitive.TextureEntry tex = part.Shape.Textures;
2618 int nsides = GetNumberOfSides(part);
2619
2215 if (face == ScriptBaseClass.ALL_SIDES) 2620 if (face == ScriptBaseClass.ALL_SIDES)
2216 { 2621 {
2217 face = 0; 2622 face = 0;
2218 } 2623 }
2219 2624
2220 if (face >= 0 && face < GetNumberOfSides(part)) 2625 if (face >= 0 && face < nsides)
2221 { 2626 {
2222 Primitive.TextureEntryFace texface; 2627 Primitive.TextureEntryFace texface;
2223 texface = tex.GetFace((uint)face); 2628 texface = tex.GetFace((uint)face);
@@ -2248,6 +2653,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2248 m_host.AddScriptLPS(1); 2653 m_host.AddScriptLPS(1);
2249 2654
2250 SetPos(m_host, pos, true); 2655 SetPos(m_host, pos, true);
2656
2657 ScriptSleep(m_sleepMsOnSetPos);
2251 } 2658 }
2252 2659
2253 /// <summary> 2660 /// <summary>
@@ -2278,7 +2685,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2278 pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region. 2685 pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
2279 pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region. 2686 pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
2280 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. 2687 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
2281 pos.y > (World.RegionInfo.RegionSizeY + 10) // return FALSE if more than 10 meters into a north-adjacent region. 2688 pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
2689 pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
2282 ) 2690 )
2283 ) 2691 )
2284 { 2692 {
@@ -2317,7 +2725,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2317 return end; 2725 return end;
2318 } 2726 }
2319 2727
2320 protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos) 2728 protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos, bool adjust)
2321 { 2729 {
2322 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 2730 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2323 return fromPos; 2731 return fromPos;
@@ -2333,9 +2741,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2333 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) 2741 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
2334 targetPos.z = ground; 2742 targetPos.z = ground;
2335 } 2743 }
2336 LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos); 2744 if (adjust)
2745 return SetPosAdjust(fromPos, targetPos);
2337 2746
2338 return real_vec; 2747 return targetPos;
2339 } 2748 }
2340 2749
2341 /// <summary> 2750 /// <summary>
@@ -2346,27 +2755,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2346 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param> 2755 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param>
2347 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust) 2756 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
2348 { 2757 {
2349 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2758 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted || part.ParentGroup.inTransit)
2759 return;
2760
2761
2350 LSL_Vector currentPos = GetPartLocalPos(part); 2762 LSL_Vector currentPos = GetPartLocalPos(part);
2763 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos, adjust);
2351 2764
2352 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
2353 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
2354 2765
2355 if (part.ParentGroup.RootPart == part) 2766 if (part.ParentGroup.RootPart == part)
2356 { 2767 {
2357 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
2358 targetPos.z = ground;
2359 SceneObjectGroup parent = part.ParentGroup; 2768 SceneObjectGroup parent = part.ParentGroup;
2360 parent.UpdateGroupPosition(!adjust ? targetPos : 2769 if (!parent.IsAttachment && !World.Permissions.CanObjectEntry(parent, false, (Vector3)toPos))
2361 SetPosAdjust(currentPos, targetPos)); 2770 return;
2771 parent.UpdateGroupPosition((Vector3)toPos);
2362 } 2772 }
2363 else 2773 else
2364 { 2774 {
2365 part.OffsetPosition = !adjust ? targetPos : 2775 part.OffsetPosition = (Vector3)toPos;
2366 SetPosAdjust(currentPos, targetPos); 2776// SceneObjectGroup parent = part.ParentGroup;
2367 SceneObjectGroup parent = part.ParentGroup; 2777// parent.HasGroupChanged = true;
2368 parent.HasGroupChanged = true; 2778// parent.ScheduleGroupForTerseUpdate();
2369 parent.ScheduleGroupForTerseUpdate(); 2779 part.ScheduleTerseUpdate();
2370 } 2780 }
2371 } 2781 }
2372 2782
@@ -2395,13 +2805,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2395 else 2805 else
2396 { 2806 {
2397 if (part.ParentGroup.IsAttachment) 2807 if (part.ParentGroup.IsAttachment)
2398 {
2399 pos = part.AttachedPos; 2808 pos = part.AttachedPos;
2400 }
2401 else 2809 else
2402 {
2403 pos = part.AbsolutePosition; 2810 pos = part.AbsolutePosition;
2404 }
2405 } 2811 }
2406 2812
2407// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); 2813// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
@@ -2414,7 +2820,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2414 m_host.AddScriptLPS(1); 2820 m_host.AddScriptLPS(1);
2415 2821
2416 // try to let this work as in SL... 2822 // try to let this work as in SL...
2417 if (m_host.ParentID == 0) 2823 if (m_host.ParentID == 0 || (m_host.ParentGroup != null && m_host == m_host.ParentGroup.RootPart))
2418 { 2824 {
2419 // special case: If we are root, rotate complete SOG to new rotation 2825 // special case: If we are root, rotate complete SOG to new rotation
2420 SetRot(m_host, rot); 2826 SetRot(m_host, rot);
@@ -2428,35 +2834,60 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2428 SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); 2834 SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot);
2429 } 2835 }
2430 } 2836 }
2837
2838 ScriptSleep(m_sleepMsOnSetRot);
2431 } 2839 }
2432 2840
2433 public void llSetLocalRot(LSL_Rotation rot) 2841 public void llSetLocalRot(LSL_Rotation rot)
2434 { 2842 {
2435 m_host.AddScriptLPS(1); 2843 m_host.AddScriptLPS(1);
2436 SetRot(m_host, rot); 2844 SetRot(m_host, rot);
2845 ScriptSleep(m_sleepMsOnSetLocalRot);
2437 } 2846 }
2438 2847
2439 protected void SetRot(SceneObjectPart part, Quaternion rot) 2848 protected void SetRot(SceneObjectPart part, Quaternion rot)
2440 { 2849 {
2441 part.UpdateRotation(rot); 2850 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2442 // Update rotation does not move the object in the physics scene if it's a linkset. 2851 return;
2443 2852
2444//KF: Do NOT use this next line if using ODE physics engine. This need a switch based on .ini Phys Engine type 2853 bool isroot = (part == part.ParentGroup.RootPart);
2445// part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition; 2854 bool isphys;
2446 2855
2447 // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line
2448 // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt
2449 // It's perfectly okay when the object is not an active physical body though.
2450 // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against
2451 // but only if the object is not physial and active. This is important for rotating doors.
2452 // without the absoluteposition = absoluteposition happening, the doors do not move in the physics
2453 // scene
2454 PhysicsActor pa = part.PhysActor; 2856 PhysicsActor pa = part.PhysActor;
2455 2857
2456 if (pa != null && !pa.IsPhysical) 2858 // keep using physactor ideia of isphysical
2859 // it should be SOP ideia of that
2860 // not much of a issue with ubOde
2861 if (pa != null && pa.IsPhysical)
2862 isphys = true;
2863 else
2864 isphys = false;
2865
2866 // SL doesn't let scripts rotate root of physical linksets
2867 if (isroot && isphys)
2868 return;
2869
2870 part.UpdateRotation(rot);
2871
2872 // Update rotation does not move the object in the physics engine if it's a non physical linkset
2873 // so do a nasty update of parts positions if is a root part rotation
2874 if (isroot && pa != null) // with if above implies non physical root part
2457 { 2875 {
2458 part.ParentGroup.ResetChildPrimPhysicsPositions(); 2876 part.ParentGroup.ResetChildPrimPhysicsPositions();
2459 } 2877 }
2878 else // fix sitting avatars. This is only needed bc of how we link avas to child parts, not root part
2879 {
2880 // List<ScenePresence> sittingavas = part.ParentGroup.GetLinkedAvatars();
2881 List<ScenePresence> sittingavas = part.ParentGroup.GetSittingAvatars();
2882 if (sittingavas.Count > 0)
2883 {
2884 foreach (ScenePresence av in sittingavas)
2885 {
2886 if (isroot || part.LocalId == av.ParentID)
2887 av.SendTerseUpdateToAllClients();
2888 }
2889 }
2890 }
2460 } 2891 }
2461 2892
2462 /// <summary> 2893 /// <summary>
@@ -2473,6 +2904,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2473 2904
2474 m_host.AddScriptLPS(1); 2905 m_host.AddScriptLPS(1);
2475 Quaternion q = m_host.GetWorldRotation(); 2906 Quaternion q = m_host.GetWorldRotation();
2907
2908 if (m_host.ParentGroup != null && m_host.ParentGroup.AttachmentPoint != 0)
2909 {
2910 ScenePresence avatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2911 if (avatar != null)
2912 {
2913 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2914 q = avatar.CameraRotation * q; // Mouselook
2915 else
2916 q = avatar.Rotation * q; // Currently infrequently updated so may be inaccurate
2917 }
2918 }
2919
2476 return new LSL_Rotation(q.X, q.Y, q.Z, q.W); 2920 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
2477 } 2921 }
2478 2922
@@ -2500,14 +2944,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2500 return new LSL_Rotation(q); 2944 return new LSL_Rotation(q);
2501 } 2945 }
2502 2946
2503 return new LSL_Rotation(part.GetWorldRotation()); 2947 q = part.GetWorldRotation();
2948 if (part.ParentGroup.AttachmentPoint != 0)
2949 {
2950 ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar);
2951 if (avatar != null)
2952 {
2953 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2954 q = avatar.CameraRotation * q; // Mouselook
2955 else
2956 q = avatar.Rotation * q; // Currently infrequently updated so may be inaccurate
2957 }
2958 }
2959
2960 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
2504 } 2961 }
2505 2962
2506 public LSL_Rotation llGetLocalRot() 2963 public LSL_Rotation llGetLocalRot()
2507 { 2964 {
2508 m_host.AddScriptLPS(1); 2965 return GetPartLocalRot(m_host);
2966 }
2509 2967
2510 return new LSL_Rotation(m_host.RotationOffset); 2968 private LSL_Rotation GetPartLocalRot(SceneObjectPart part)
2969 {
2970 m_host.AddScriptLPS(1);
2971 Quaternion rot = part.RotationOffset;
2972 return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
2511 } 2973 }
2512 2974
2513 public void llSetForce(LSL_Vector force, int local) 2975 public void llSetForce(LSL_Vector force, int local)
@@ -2537,32 +2999,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2537 return force; 2999 return force;
2538 } 3000 }
2539 3001
2540 public void llSetVelocity(LSL_Vector velocity, int local) 3002 public void llSetVelocity(LSL_Vector vel, int local)
2541 { 3003 {
2542 m_host.AddScriptLPS(1); 3004 m_host.AddScriptLPS(1);
2543 3005 m_host.SetVelocity(new Vector3((float)vel.x, (float)vel.y, (float)vel.z), local != 0);
2544 if (!m_host.ParentGroup.IsDeleted)
2545 {
2546 if (local != 0)
2547 velocity *= llGetRot();
2548
2549 m_host.ParentGroup.RootPart.Velocity = velocity;
2550 }
2551 } 3006 }
2552 3007
2553 public void llSetAngularVelocity(LSL_Vector angularVelocity, int local) 3008 public void llSetAngularVelocity(LSL_Vector avel, int local)
2554 { 3009 {
2555 m_host.AddScriptLPS(1); 3010 m_host.AddScriptLPS(1);
2556 3011 m_host.SetAngularVelocity(new Vector3((float)avel.x, (float)avel.y, (float)avel.z), local != 0);
2557 if (!m_host.ParentGroup.IsDeleted)
2558 {
2559 if (local != 0)
2560 angularVelocity *= llGetRot();
2561
2562 m_host.ParentGroup.RootPart.AngularVelocity = angularVelocity;
2563 }
2564 } 3012 }
2565
2566 public LSL_Integer llTarget(LSL_Vector position, double range) 3013 public LSL_Integer llTarget(LSL_Vector position, double range)
2567 { 3014 {
2568 m_host.AddScriptLPS(1); 3015 m_host.AddScriptLPS(1);
@@ -2613,16 +3060,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2613 m_host.ApplyImpulse(v, local != 0); 3060 m_host.ApplyImpulse(v, local != 0);
2614 } 3061 }
2615 3062
3063
2616 public void llApplyRotationalImpulse(LSL_Vector force, int local) 3064 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2617 { 3065 {
2618 m_host.AddScriptLPS(1); 3066 m_host.AddScriptLPS(1);
2619 m_host.ApplyAngularImpulse(force, local != 0); 3067 m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0);
2620 } 3068 }
2621 3069
2622 public void llSetTorque(LSL_Vector torque, int local) 3070 public void llSetTorque(LSL_Vector torque, int local)
2623 { 3071 {
2624 m_host.AddScriptLPS(1); 3072 m_host.AddScriptLPS(1);
2625 m_host.SetAngularImpulse(torque, local != 0); 3073 m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0);
2626 } 3074 }
2627 3075
2628 public LSL_Vector llGetTorque() 3076 public LSL_Vector llGetTorque()
@@ -2639,20 +3087,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2639 llSetTorque(torque, local); 3087 llSetTorque(torque, local);
2640 } 3088 }
2641 3089
3090
2642 public LSL_Vector llGetVel() 3091 public LSL_Vector llGetVel()
2643 { 3092 {
2644 m_host.AddScriptLPS(1); 3093 m_host.AddScriptLPS(1);
2645 3094
2646 Vector3 vel; 3095 Vector3 vel = Vector3.Zero;
2647 3096
2648 if (m_host.ParentGroup.IsAttachment) 3097 if (m_host.ParentGroup.IsAttachment)
2649 { 3098 {
2650 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); 3099 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2651 vel = avatar.GetWorldVelocity(); 3100 if (avatar != null)
3101 vel = avatar.GetWorldVelocity();
2652 } 3102 }
2653 else 3103 else
2654 { 3104 {
2655 vel = m_host.Velocity; 3105 vel = m_host.ParentGroup.RootPart.Velocity;
2656 } 3106 }
2657 3107
2658 return new LSL_Vector(vel); 3108 return new LSL_Vector(vel);
@@ -2668,8 +3118,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2668 public LSL_Vector llGetOmega() 3118 public LSL_Vector llGetOmega()
2669 { 3119 {
2670 m_host.AddScriptLPS(1); 3120 m_host.AddScriptLPS(1);
2671 3121 Vector3 avel = m_host.AngularVelocity;
2672 return new LSL_Vector(m_host.AngularVelocity); 3122 return new LSL_Vector(avel.X, avel.Y, avel.Z);
2673 } 3123 }
2674 3124
2675 public LSL_Float llGetTimeOfDay() 3125 public LSL_Float llGetTimeOfDay()
@@ -2687,22 +3137,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2687 public LSL_Float llGetTime() 3137 public LSL_Float llGetTime()
2688 { 3138 {
2689 m_host.AddScriptLPS(1); 3139 m_host.AddScriptLPS(1);
2690 TimeSpan ScriptTime = DateTime.Now - m_timer; 3140 double ScriptTime = Util.GetTimeStampMS() - m_timer;
2691 return (double)(ScriptTime.TotalMilliseconds / 1000); 3141 return (float)Math.Round((ScriptTime / 1000.0), 3);
2692 } 3142 }
2693 3143
2694 public void llResetTime() 3144 public void llResetTime()
2695 { 3145 {
2696 m_host.AddScriptLPS(1); 3146 m_host.AddScriptLPS(1);
2697 m_timer = DateTime.Now; 3147 m_timer = Util.GetTimeStampMS();
2698 } 3148 }
2699 3149
2700 public LSL_Float llGetAndResetTime() 3150 public LSL_Float llGetAndResetTime()
2701 { 3151 {
2702 m_host.AddScriptLPS(1); 3152 m_host.AddScriptLPS(1);
2703 TimeSpan ScriptTime = DateTime.Now - m_timer; 3153 double now = Util.GetTimeStampMS();
2704 m_timer = DateTime.Now; 3154 double ScriptTime = now - m_timer;
2705 return (double)(ScriptTime.TotalMilliseconds / 1000); 3155 m_timer = now;
3156 return (float)Math.Round((ScriptTime / 1000.0), 3);
2706 } 3157 }
2707 3158
2708 public void llSound(string sound, double volume, int queue, int loop) 3159 public void llSound(string sound, double volume, int queue, int loop)
@@ -2722,8 +3173,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2722 { 3173 {
2723 m_SoundModule.SendSound( 3174 m_SoundModule.SendSound(
2724 m_host.UUID, 3175 m_host.UUID,
2725 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), 3176 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound),
2726 volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None, 3177 volume, false, 0,
2727 0, false, false); 3178 0, false, false);
2728 } 3179 }
2729 } 3180 }
@@ -2734,7 +3185,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2734 if (m_SoundModule != null) 3185 if (m_SoundModule != null)
2735 { 3186 {
2736 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 3187 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
2737 volume, 20, false); 3188 volume, 20, false,false);
2738 } 3189 }
2739 } 3190 }
2740 3191
@@ -2744,16 +3195,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2744 if (m_SoundModule != null) 3195 if (m_SoundModule != null)
2745 { 3196 {
2746 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 3197 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
2747 volume, 20, true); 3198 volume, 20, true, false);
2748 } 3199 }
2749 } 3200 }
2750 3201
2751 public void llLoopSoundSlave(string sound, double volume) 3202 public void llLoopSoundSlave(string sound, double volume)
2752 { 3203 {
2753 m_host.AddScriptLPS(1); 3204 m_host.AddScriptLPS(1);
2754 lock (m_host.ParentGroup.LoopSoundSlavePrims) 3205 if (m_SoundModule != null)
2755 { 3206 {
2756 m_host.ParentGroup.LoopSoundSlavePrims.Add(m_host); 3207 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
3208 volume, 20, false, true);
2757 } 3209 }
2758 } 3210 }
2759 3211
@@ -2795,6 +3247,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2795 m_host.AddScriptLPS(1); 3247 m_host.AddScriptLPS(1);
2796 if (m_SoundModule != null) 3248 if (m_SoundModule != null)
2797 m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0); 3249 m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0);
3250 ScriptSleep(m_sleepMsOnPreloadSound);
2798 } 3251 }
2799 3252
2800 /// <summary> 3253 /// <summary>
@@ -3027,7 +3480,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3027 return src.ToLower(); 3480 return src.ToLower();
3028 } 3481 }
3029 3482
3030 public void llGiveMoney(string destination, int amount) 3483 public LSL_Integer llGiveMoney(string destination, int amount)
3031 { 3484 {
3032 Util.FireAndForget(x => 3485 Util.FireAndForget(x =>
3033 { 3486 {
@@ -3058,69 +3511,86 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3058 return; 3511 return;
3059 } 3512 }
3060 3513
3514 string reason;
3061 money.ObjectGiveMoney( 3515 money.ObjectGiveMoney(
3062 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 3516
3517 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero, out reason);
3063 }, null, "LSL_Api.llGiveMoney"); 3518 }, null, "LSL_Api.llGiveMoney");
3519
3520 return 0;
3064 } 3521 }
3065 3522
3066 public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) 3523 public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
3067 { 3524 {
3068 m_host.AddScriptLPS(1); 3525 m_host.AddScriptLPS(1);
3069 Deprecated("llMakeExplosion", "Use llParticleSystem instead"); 3526 Deprecated("llMakeExplosion", "Use llParticleSystem instead");
3527 ScriptSleep(m_sleepMsOnMakeExplosion);
3070 } 3528 }
3071 3529
3072 public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset) 3530 public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset)
3073 { 3531 {
3074 m_host.AddScriptLPS(1); 3532 m_host.AddScriptLPS(1);
3075 Deprecated("llMakeFountain", "Use llParticleSystem instead"); 3533 Deprecated("llMakeFountain", "Use llParticleSystem instead");
3534 ScriptSleep(m_sleepMsOnMakeFountain);
3076 } 3535 }
3077 3536
3078 public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) 3537 public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
3079 { 3538 {
3080 m_host.AddScriptLPS(1); 3539 m_host.AddScriptLPS(1);
3081 Deprecated("llMakeSmoke", "Use llParticleSystem instead"); 3540 Deprecated("llMakeSmoke", "Use llParticleSystem instead");
3541 ScriptSleep(m_sleepMsOnMakeSmoke);
3082 } 3542 }
3083 3543
3084 public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) 3544 public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
3085 { 3545 {
3086 m_host.AddScriptLPS(1); 3546 m_host.AddScriptLPS(1);
3087 Deprecated("llMakeFire", "Use llParticleSystem instead"); 3547 Deprecated("llMakeFire", "Use llParticleSystem instead");
3548 ScriptSleep(m_sleepMsOnMakeFire);
3088 } 3549 }
3089 3550
3090 public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) 3551 public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
3091 { 3552 {
3553 doObjectRez(inventory, pos, vel, rot, param, true);
3554 }
3555
3556 public void doObjectRez(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param, bool atRoot)
3557 {
3092 m_host.AddScriptLPS(1); 3558 m_host.AddScriptLPS(1);
3559 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
3560 return;
3093 3561
3094 Util.FireAndForget(x => 3562 float dist = (float)llVecDist(llGetPos(), pos);
3095 {
3096 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
3097 return;
3098 3563
3099 float dist = (float)llVecDist(llGetPos(), pos); 3564 if (dist > m_ScriptDistanceFactor * 10.0f)
3565 return;
3100 3566
3101 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory); 3567 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory);
3102 3568
3103 if (item == null) 3569 if (item == null)
3104 { 3570 {
3105 Error("llRezAtRoot", "Can't find object '" + inventory + "'"); 3571 Error("llRez(AtRoot/Object)", "Can't find object '" + inventory + "'");
3106 return; 3572 return;
3107 } 3573 }
3108 3574
3109 if (item.InvType != (int)InventoryType.Object) 3575 if (item.InvType != (int)InventoryType.Object)
3110 { 3576 {
3111 Error("llRezAtRoot", "Can't create requested object; object is missing from database"); 3577 Error("llRez(AtRoot/Object)", "Can't create requested object; object is missing from database");
3112 return; 3578 return;
3113 } 3579 }
3114 3580
3115 // need the magnitude later 3581 Util.FireAndForget(x =>
3116 // float velmag = (float)Util.GetMagnitude(llvel); 3582 {
3117 3583
3118 List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param); 3584 Quaternion wrot = rot;
3585 wrot.Normalize();
3586 List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, wrot, vel, param, atRoot);
3119 3587
3120 // If either of these are null, then there was an unknown error. 3588 // If either of these are null, then there was an unknown error.
3121 if (new_groups == null) 3589 if (new_groups == null)
3122 return; 3590 return;
3123 3591
3592 bool notAttachment = !m_host.ParentGroup.IsAttachment;
3593
3124 foreach (SceneObjectGroup group in new_groups) 3594 foreach (SceneObjectGroup group in new_groups)
3125 { 3595 {
3126 // objects rezzed with this method are die_at_edge by default. 3596 // objects rezzed with this method are die_at_edge by default.
@@ -3134,58 +3604,79 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3134 group.RootPart.UUID.ToString()) }, 3604 group.RootPart.UUID.ToString()) },
3135 new DetectParams[0])); 3605 new DetectParams[0]));
3136 3606
3137 float groupmass = group.GetMass(); 3607 if (notAttachment)
3608 {
3609 float groupmass = group.GetMass();
3138 3610
3139 PhysicsActor pa = group.RootPart.PhysActor; 3611 PhysicsActor pa = group.RootPart.PhysActor;
3140 3612
3141 //Recoil. 3613 //Recoil.
3142 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3614 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3143 {
3144 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3145 if (recoil != Vector3.Zero)
3146 { 3615 {
3147 llApplyImpulse(recoil, 0); 3616 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3617 if (recoil != Vector3.Zero)
3618 {
3619 llApplyImpulse(recoil, 0);
3620 }
3148 } 3621 }
3149 } 3622 }
3150 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3623 }
3151 } 3624 }, null, "LSL_Api.doObjectRez");
3152 }, null, "LSL_Api.llRezAtRoot"); 3625
3626 //ScriptSleep((int)((groupmass * velmag) / 10));
3627 ScriptSleep(m_sleepMsOnRezAtRoot);
3153 } 3628 }
3154 3629
3155 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) 3630 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
3156 { 3631 {
3157 llRezAtRoot(inventory, pos, vel, rot, param); 3632 doObjectRez(inventory, pos, vel, rot, param, false);
3158 } 3633 }
3159 3634
3160 public void llLookAt(LSL_Vector target, double strength, double damping) 3635 public void llLookAt(LSL_Vector target, double strength, double damping)
3161 { 3636 {
3162 m_host.AddScriptLPS(1); 3637 m_host.AddScriptLPS(1);
3163 // Determine where we are looking from 3638
3639 // Get the normalized vector to the target
3164 LSL_Vector from = llGetPos(); 3640 LSL_Vector from = llGetPos();
3165 3641
3166 // normalized direction to target 3642 // normalized direction to target
3167 LSL_Vector dir = llVecNorm(target - from); 3643 LSL_Vector dir = llVecNorm(target - from);
3644
3168 // use vertical to help compute left axis 3645 // use vertical to help compute left axis
3169 LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0); 3646// LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0);
3170 // find normalized left axis parallel to horizon 3647 // find normalized left axis parallel to horizon
3171 LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir)); 3648// LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir));
3649
3650 LSL_Vector left = new LSL_Vector(-dir.y, dir.x, 0.0f);
3651 left = llVecNorm(left);
3172 // make up orthogonal to left and dir 3652 // make up orthogonal to left and dir
3173 up = LSL_Vector.Cross(dir, left); 3653 LSL_Vector up = LSL_Vector.Cross(dir, left);
3174 3654
3175 // compute rotation based on orthogonal axes 3655 // compute rotation based on orthogonal axes
3656 // and rotate so Z points to target with X below horizont
3176 LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up); 3657 LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up);
3177 3658
3178 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply 3659 SceneObjectGroup sog = m_host.ParentGroup;
3179 // set the rotation of the object, copy that behavior 3660 if(sog == null || sog.IsDeleted)
3180 PhysicsActor pa = m_host.PhysActor; 3661 return;
3181 3662
3182 if (m_host.ParentGroup.IsAttachment || strength == 0 || pa == null || !pa.IsPhysical) 3663 if (!sog.UsesPhysics || sog.IsAttachment)
3183 { 3664 {
3184 llSetRot(rot); 3665 // Do nothing if either value is 0 (this has been checked in SL)
3666 if (strength <= 0.0 || damping <= 0.0)
3667 return;
3668
3669 llSetLocalRot(rot);
3185 } 3670 }
3186 else 3671 else
3187 { 3672 {
3188 m_host.StartLookAt(rot, (float)strength, (float)damping); 3673 if (strength == 0)
3674 {
3675 llSetLocalRot(rot);
3676 return;
3677 }
3678
3679 sog.StartLookAt(rot, (float)strength, (float)damping);
3189 } 3680 }
3190 } 3681 }
3191 3682
@@ -3231,22 +3722,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3231 } 3722 }
3232 else 3723 else
3233 { 3724 {
3234 if (m_host.IsRoot) 3725 // new SL always returns object mass
3235 { 3726// if (m_host.IsRoot)
3727// {
3236 return m_host.ParentGroup.GetMass(); 3728 return m_host.ParentGroup.GetMass();
3237 } 3729// }
3238 else 3730// else
3239 { 3731// {
3240 return m_host.GetMass(); 3732// return m_host.GetMass();
3241 } 3733// }
3242 } 3734 }
3243 } 3735 }
3244 3736
3245 public LSL_Float llGetMassMKS() 3737 public LSL_Float llGetMassMKS()
3246 { 3738 {
3247 // this is what the wiki says it does! 3739 return 100f * llGetMass();
3248 // http://wiki.secondlife.com/wiki/LlGetMassMKS
3249 return llGetMass() * 100.0;
3250 } 3740 }
3251 3741
3252 public void llCollisionFilter(string name, string id, int accept) 3742 public void llCollisionFilter(string name, string id, int accept)
@@ -3296,7 +3786,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3296 { 3786 {
3297 // Unregister controls from Presence 3787 // Unregister controls from Presence
3298 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID); 3788 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID);
3299 // Remove Take Control permission. 3789 // Remove Take Control permission.
3300 m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3790 m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3301 } 3791 }
3302 } 3792 }
@@ -3355,9 +3845,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3355 { 3845 {
3356 m_host.AddScriptLPS(1); 3846 m_host.AddScriptLPS(1);
3357 3847
3358// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3359// return;
3360
3361 if (m_item.PermsGranter != m_host.OwnerID) 3848 if (m_item.PermsGranter != m_host.OwnerID)
3362 return; 3849 return;
3363 3850
@@ -3401,6 +3888,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3401 public void llInstantMessage(string user, string message) 3888 public void llInstantMessage(string user, string message)
3402 { 3889 {
3403 m_host.AddScriptLPS(1); 3890 m_host.AddScriptLPS(1);
3891 UUID result;
3892 if (!UUID.TryParse(user, out result) || result == UUID.Zero)
3893 {
3894 Error("llInstantMessage","An invalid key was passed to llInstantMessage");
3895 ScriptSleep(2000);
3896 return;
3897 }
3404 3898
3405 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3899 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
3406 // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent, 3900 // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
@@ -3411,31 +3905,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3411 3905
3412 // TODO: figure out values for client, fromSession, and imSessionID 3906 // TODO: figure out values for client, fromSession, and imSessionID
3413 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch()); 3907 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
3908 UUID friendTransactionID = UUID.Random();
3909
3910 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3414 3911
3415 GridInstantMessage msg = new GridInstantMessage(); 3912 GridInstantMessage msg = new GridInstantMessage();
3416 msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid; 3913 msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid;
3417 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3914 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3418 msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here 3915 msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here
3419// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3916 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3420// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3917 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
3421 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3918
3422 //if (client != null)
3423 //{
3424 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
3425 //}
3426 //else
3427 //{
3428 // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it
3429 //}
3430 // Cap the message length at 1024.
3431 if (message != null && message.Length > 1024) 3919 if (message != null && message.Length > 1024)
3432 msg.message = message.Substring(0, 1024); 3920 msg.message = message.Substring(0, 1024);
3433 else 3921 else
3434 msg.message = message; 3922 msg.message = message;
3435 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3923 msg.dialog = (byte)19; // MessageFromObject
3436 msg.fromGroup = false;// fromGroup; 3924 msg.fromGroup = false;// fromGroup;
3437 msg.offline = (byte)0; //offline; 3925 msg.offline = (byte)0; //offline;
3438 msg.ParentEstateID = 0; //ParentEstateID; 3926 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3439 msg.Position = new Vector3(m_host.AbsolutePosition); 3927 msg.Position = new Vector3(m_host.AbsolutePosition);
3440 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3928 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
3441 3929
@@ -3452,6 +3940,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3452 { 3940 {
3453 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 3941 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
3454 } 3942 }
3943
3944 ScriptSleep(m_sleepMsOnInstantMessage);
3455 } 3945 }
3456 3946
3457 public void llEmail(string address, string subject, string message) 3947 public void llEmail(string address, string subject, string message)
@@ -3489,6 +3979,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3489 } 3979 }
3490 3980
3491 emailModule.SendEmail(m_host.UUID, address, subject, message); 3981 emailModule.SendEmail(m_host.UUID, address, subject, message);
3982 ScriptSleep(m_sleepMsOnEmail);
3492 } 3983 }
3493 3984
3494 public void llGetNextEmail(string address, string subject) 3985 public void llGetNextEmail(string address, string subject)
@@ -3551,25 +4042,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3551 { 4042 {
3552 m_host.AddScriptLPS(1); 4043 m_host.AddScriptLPS(1);
3553 4044
3554 if (m_host.PhysActor != null) 4045 PIDHoverType hoverType = PIDHoverType.Ground;
4046 if (water != 0)
3555 { 4047 {
3556 PIDHoverType hoverType = PIDHoverType.Ground; 4048 hoverType = PIDHoverType.GroundAndWater;
3557 if (water != 0)
3558 {
3559 hoverType = PIDHoverType.GroundAndWater;
3560 }
3561
3562 m_host.SetHoverHeight((float)height, hoverType, (float)tau);
3563 } 4049 }
4050 m_host.SetHoverHeight((float)height, hoverType, (float)tau);
3564 } 4051 }
3565 4052
3566 public void llStopHover() 4053 public void llStopHover()
3567 { 4054 {
3568 m_host.AddScriptLPS(1); 4055 m_host.AddScriptLPS(1);
3569 if (m_host.PhysActor != null) 4056 m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
3570 {
3571 m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
3572 }
3573 } 4057 }
3574 4058
3575 public void llMinEventDelay(double delay) 4059 public void llMinEventDelay(double delay)
@@ -3598,15 +4082,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3598 4082
3599 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply 4083 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
3600 // set the rotation of the object, copy that behavior 4084 // set the rotation of the object, copy that behavior
3601 PhysicsActor pa = m_host.PhysActor; 4085 SceneObjectGroup sog = m_host.ParentGroup;
4086 if(sog == null || sog.IsDeleted)
4087 return;
3602 4088
3603 if (strength == 0 || pa == null || !pa.IsPhysical) 4089 if (strength == 0 || !sog.UsesPhysics || sog.IsAttachment)
3604 { 4090 {
3605 llSetLocalRot(target); 4091 llSetLocalRot(target);
3606 } 4092 }
3607 else 4093 else
3608 { 4094 {
3609 m_host.RotLookAt(target, (float)strength, (float)damping); 4095 sog.RotLookAt(target, (float)strength, (float)damping);
3610 } 4096 }
3611 } 4097 }
3612 4098
@@ -3735,7 +4221,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3735 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 4221 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3736 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 4222 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3737 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 4223 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3738 ScriptBaseClass.PERMISSION_ATTACH; 4224 ScriptBaseClass.PERMISSION_ATTACH |
4225 ScriptBaseClass.PERMISSION_OVERRIDE_ANIMATIONS;
3739 } 4226 }
3740 else 4227 else
3741 { 4228 {
@@ -3752,15 +4239,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3752 if (World.GetExtraSetting("auto_grant_attach_perms") == "true") 4239 if (World.GetExtraSetting("auto_grant_attach_perms") == "true")
3753 implicitPerms = ScriptBaseClass.PERMISSION_ATTACH; 4240 implicitPerms = ScriptBaseClass.PERMISSION_ATTACH;
3754 } 4241 }
4242 if (World.GetExtraSetting("auto_grant_all_perms") == "true")
4243 {
4244 implicitPerms = perm;
4245 }
3755 } 4246 }
3756 4247
3757 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 4248 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3758 { 4249 {
3759 lock (m_host.TaskInventory) 4250 m_host.TaskInventory.LockItemsForWrite(true);
3760 { 4251 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3761 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 4252 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3762 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 4253 m_host.TaskInventory.LockItemsForWrite(false);
3763 }
3764 4254
3765 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 4255 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3766 "run_time_permissions", new Object[] { 4256 "run_time_permissions", new Object[] {
@@ -3771,7 +4261,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3771 } 4261 }
3772 4262
3773 ScenePresence presence = World.GetScenePresence(agentID); 4263 ScenePresence presence = World.GetScenePresence(agentID);
3774 4264
3775 if (presence != null) 4265 if (presence != null)
3776 { 4266 {
3777 // If permissions are being requested from an NPC and were not implicitly granted above then 4267 // If permissions are being requested from an NPC and were not implicitly granted above then
@@ -3804,11 +4294,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3804 4294
3805 if (!m_waitingForScriptAnswer) 4295 if (!m_waitingForScriptAnswer)
3806 { 4296 {
3807 lock (m_host.TaskInventory) 4297 m_host.TaskInventory.LockItemsForWrite(true);
3808 { 4298 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3809 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 4299 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3810 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 4300 m_host.TaskInventory.LockItemsForWrite(false);
3811 }
3812 4301
3813 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 4302 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3814 m_waitingForScriptAnswer=true; 4303 m_waitingForScriptAnswer=true;
@@ -3837,14 +4326,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3837 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 4326 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3838 llReleaseControls(); 4327 llReleaseControls();
3839 4328
3840 lock (m_host.TaskInventory) 4329 m_host.TaskInventory.LockItemsForWrite(true);
3841 { 4330 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3842 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 4331 m_host.TaskInventory.LockItemsForWrite(false);
3843 }
3844 4332
3845 m_ScriptEngine.PostScriptEvent( 4333 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3846 m_item.ItemID, 4334 "run_time_permissions", new Object[] {
3847 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); 4335 new LSL_Integer(answer) },
4336 new DetectParams[0]));
3848 } 4337 }
3849 4338
3850 public LSL_String llGetPermissionsKey() 4339 public LSL_String llGetPermissionsKey()
@@ -3883,15 +4372,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3883 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 4372 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3884 { 4373 {
3885 List<SceneObjectPart> parts = GetLinkParts(linknumber); 4374 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3886 4375 if (parts.Count > 0)
3887 foreach (SceneObjectPart part in parts) 4376 {
3888 part.SetFaceColorAlpha(face, color, null); 4377 try
4378 {
4379 foreach (SceneObjectPart part in parts)
4380 part.SetFaceColorAlpha(face, color, null);
4381 }
4382 finally { }
4383 }
3889 } 4384 }
3890 4385
3891 public void llCreateLink(string target, int parent) 4386 public void llCreateLink(string target, int parent)
3892 { 4387 {
3893 m_host.AddScriptLPS(1); 4388 m_host.AddScriptLPS(1);
3894 4389
4390 UUID targetID;
4391
4392 if (!UUID.TryParse(target, out targetID))
4393 return;
4394
3895 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 4395 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3896 && !m_automaticLinkPermission) 4396 && !m_automaticLinkPermission)
3897 { 4397 {
@@ -3907,9 +4407,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3907 UUID targetID; 4407 UUID targetID;
3908 4408
3909 if (!UUID.TryParse(target, out targetID)) 4409 if (!UUID.TryParse(target, out targetID))
3910 return; 4410 return;
3911 4411
3912 SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID); 4412 SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID);
4413 if (targetPart == null)
4414 return;
3913 4415
3914 if (targetPart.ParentGroup.AttachmentPoint != 0) 4416 if (targetPart.ParentGroup.AttachmentPoint != 0)
3915 return; // Fail silently if attached 4417 return; // Fail silently if attached
@@ -3919,24 +4421,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3919 4421
3920 SceneObjectGroup parentPrim = null, childPrim = null; 4422 SceneObjectGroup parentPrim = null, childPrim = null;
3921 4423
3922 if (targetPart != null) 4424 if (parent != 0)
3923 { 4425 {
3924 if (parent != 0) 4426 parentPrim = m_host.ParentGroup;
3925 { 4427 childPrim = targetPart.ParentGroup;
3926 parentPrim = m_host.ParentGroup; 4428 }
3927 childPrim = targetPart.ParentGroup; 4429 else
3928 } 4430 {
3929 else 4431 parentPrim = targetPart.ParentGroup;
3930 { 4432 childPrim = m_host.ParentGroup;
3931 parentPrim = targetPart.ParentGroup;
3932 childPrim = m_host.ParentGroup;
3933 }
3934
3935 // Required for linking
3936 childPrim.RootPart.ClearUpdateSchedule();
3937 parentPrim.LinkToGroup(childPrim, true);
3938 } 4433 }
3939 4434
4435 // Required for linking
4436 childPrim.RootPart.ClearUpdateSchedule();
4437 parentPrim.LinkToGroup(childPrim, true);
4438
4439
3940 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4440 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3941 parentPrim.RootPart.CreateSelected = true; 4441 parentPrim.RootPart.CreateSelected = true;
3942 parentPrim.HasGroupChanged = true; 4442 parentPrim.HasGroupChanged = true;
@@ -3949,6 +4449,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3949 4449
3950 if (client != null) 4450 if (client != null)
3951 parentPrim.SendPropertiesToClient(client); 4451 parentPrim.SendPropertiesToClient(client);
4452
4453 ScriptSleep(m_sleepMsOnCreateLink);
3952 } 4454 }
3953 4455
3954 public void llBreakLink(int linknum) 4456 public void llBreakLink(int linknum)
@@ -4005,10 +4507,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4005 // Restructuring Multiple Prims. 4507 // Restructuring Multiple Prims.
4006 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4508 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
4007 parts.Remove(parentPrim.RootPart); 4509 parts.Remove(parentPrim.RootPart);
4008 foreach (SceneObjectPart part in parts) 4510 if (parts.Count > 0)
4009 { 4511 {
4010 parentPrim.DelinkFromGroup(part.LocalId, true); 4512 try
4011 } 4513 {
4514 foreach (SceneObjectPart part in parts)
4515 {
4516 parentPrim.DelinkFromGroup(part.LocalId, true);
4517 }
4518 }
4519 finally { }
4520 }
4521
4012 parentPrim.HasGroupChanged = true; 4522 parentPrim.HasGroupChanged = true;
4013 parentPrim.ScheduleGroupForFullUpdate(); 4523 parentPrim.ScheduleGroupForFullUpdate();
4014 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4524 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -4017,12 +4527,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4017 { 4527 {
4018 SceneObjectPart newRoot = parts[0]; 4528 SceneObjectPart newRoot = parts[0];
4019 parts.Remove(newRoot); 4529 parts.Remove(newRoot);
4020 foreach (SceneObjectPart part in parts) 4530
4531 try
4021 { 4532 {
4022 // Required for linking 4533 foreach (SceneObjectPart part in parts)
4023 part.ClearUpdateSchedule(); 4534 {
4024 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4535 part.ClearUpdateSchedule();
4536 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4537 }
4025 } 4538 }
4539 finally { }
4540
4026 newRoot.ParentGroup.HasGroupChanged = true; 4541 newRoot.ParentGroup.HasGroupChanged = true;
4027 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4542 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
4028 } 4543 }
@@ -4043,13 +4558,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4043 { 4558 {
4044 m_host.AddScriptLPS(1); 4559 m_host.AddScriptLPS(1);
4045 4560
4046 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 4561 TaskInventoryItem item = m_item;
4562
4563 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4047 && !m_automaticLinkPermission) 4564 && !m_automaticLinkPermission)
4048 { 4565 {
4049 Error("llBreakAllLinks", "PERMISSION_CHANGE_LINKS permission not set"); 4566 Error("llBreakAllLinks","Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4050 return; 4567 return;
4051 } 4568 }
4052
4053 BreakAllLinks(); 4569 BreakAllLinks();
4054 } 4570 }
4055 4571
@@ -4074,13 +4590,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4074 public LSL_String llGetLinkKey(int linknum) 4590 public LSL_String llGetLinkKey(int linknum)
4075 { 4591 {
4076 m_host.AddScriptLPS(1); 4592 m_host.AddScriptLPS(1);
4593 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
4594 if (part != null)
4595 {
4596 return part.UUID.ToString();
4597 }
4598 else
4599 {
4600 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4601 {
4602 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4077 4603
4078 ISceneEntity entity = GetLinkEntity(m_host, linknum); 4604 if (linknum < 0)
4605 return UUID.Zero.ToString();
4079 4606
4080 if (entity != null) 4607 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4081 return entity.UUID.ToString(); 4608 if (avatars.Count > linknum)
4082 else 4609 {
4083 return ScriptBaseClass.NULL_KEY; 4610 return avatars[linknum].UUID.ToString();
4611 }
4612 }
4613 return UUID.Zero.ToString();
4614 }
4084 } 4615 }
4085 4616
4086 /// <summary> 4617 /// <summary>
@@ -4139,17 +4670,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4139 m_host.AddScriptLPS(1); 4670 m_host.AddScriptLPS(1);
4140 int count = 0; 4671 int count = 0;
4141 4672
4142 lock (m_host.TaskInventory) 4673 m_host.TaskInventory.LockItemsForRead(true);
4674 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4143 { 4675 {
4144 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4676 if (inv.Value.Type == type || type == -1)
4145 { 4677 {
4146 if (inv.Value.Type == type || type == -1) 4678 count = count + 1;
4147 {
4148 count = count + 1;
4149 }
4150 } 4679 }
4151 } 4680 }
4152 4681
4682 m_host.TaskInventory.LockItemsForRead(false);
4153 return count; 4683 return count;
4154 } 4684 }
4155 4685
@@ -4158,16 +4688,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4158 m_host.AddScriptLPS(1); 4688 m_host.AddScriptLPS(1);
4159 ArrayList keys = new ArrayList(); 4689 ArrayList keys = new ArrayList();
4160 4690
4161 lock (m_host.TaskInventory) 4691 m_host.TaskInventory.LockItemsForRead(true);
4692 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4162 { 4693 {
4163 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4694 if (inv.Value.Type == type || type == -1)
4164 { 4695 {
4165 if (inv.Value.Type == type || type == -1) 4696 keys.Add(inv.Value.Name);
4166 {
4167 keys.Add(inv.Value.Name);
4168 }
4169 } 4697 }
4170 } 4698 }
4699 m_host.TaskInventory.LockItemsForRead(false);
4171 4700
4172 if (keys.Count == 0) 4701 if (keys.Count == 0)
4173 { 4702 {
@@ -4237,35 +4766,49 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4237 } 4766 }
4238 } 4767 }
4239 } 4768 }
4769
4240 // destination is an avatar 4770 // destination is an avatar
4241 string message; 4771 string message;
4242 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message); 4772 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message);
4243 4773
4244 if (agentItem == null) 4774 if (agentItem == null)
4245 { 4775 {
4246 llSay(0, message); 4776 llSay(0, message);
4247 return; 4777 return;
4248 } 4778 }
4249 4779
4250 if (m_TransferModule != null) 4780 byte[] bucket = new byte[1];
4251 { 4781 bucket[0] = (byte)item.Type;
4252 byte[] bucket = new byte[1]; 4782 //byte[] objBytes = agentItem.ID.GetBytes();
4253 bucket[0] = (byte)item.Type; 4783 //Array.Copy(objBytes, 0, bucket, 1, 16);
4784
4785 GridInstantMessage msg = new GridInstantMessage(World,
4786 m_host.OwnerID, m_host.Name, destId,
4787 (byte)InstantMessageDialog.TaskInventoryOffered,
4788 false, item.Name+". "+m_host.Name+" is located at "+
4789 World.RegionInfo.RegionName+" "+
4790 m_host.AbsolutePosition.ToString(),
4791 agentItem.ID, true, m_host.AbsolutePosition,
4792 bucket, true);
4254 4793
4255 GridInstantMessage msg = new GridInstantMessage(World, 4794 ScenePresence sp;
4256 m_host.OwnerID, m_host.Name, destId,
4257 (byte)InstantMessageDialog.TaskInventoryOffered,
4258 false, item.Name+". "+m_host.Name+" is located at "+
4259 World.RegionInfo.RegionName+" "+
4260 m_host.AbsolutePosition.ToString(),
4261 agentItem.ID, true, m_host.AbsolutePosition,
4262 bucket, true);
4263 4795
4264 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4796 if (World.TryGetScenePresence(destId, out sp))
4797 {
4798 sp.ControllingClient.SendInstantMessage(msg);
4799 }
4800 else
4801 {
4802 if (m_TransferModule != null)
4803 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4265 } 4804 }
4805
4806 //This delay should only occur when giving inventory to avatars.
4807 ScriptSleep(m_sleepMsOnGiveInventory);
4266 } 4808 }
4267 } 4809 }
4268 4810
4811 [DebuggerNonUserCode]
4269 public void llRemoveInventory(string name) 4812 public void llRemoveInventory(string name)
4270 { 4813 {
4271 m_host.AddScriptLPS(1); 4814 m_host.AddScriptLPS(1);
@@ -4285,20 +4828,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4285 { 4828 {
4286 m_host.AddScriptLPS(1); 4829 m_host.AddScriptLPS(1);
4287 Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); 4830 Vector3 av3 = Util.Clip(color, 0.0f, 1.0f);
4288 if (text.Length > 254)
4289 text = text.Remove(254);
4290
4291 byte[] data; 4831 byte[] data;
4292 do 4832 data = Util.StringToBytes256(text);
4293 { 4833 text = Util.UTF8.GetString(data);
4294 data = Util.UTF8.GetBytes(text);
4295 if (data.Length > 254)
4296 text = text.Substring(0, text.Length - 1);
4297 } while (data.Length > 254);
4298
4299 m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); 4834 m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
4300 //m_host.ParentGroup.HasGroupChanged = true;
4301 //m_host.ParentGroup.ScheduleGroupForFullUpdate();
4302 } 4835 }
4303 4836
4304 public LSL_Float llWater(LSL_Vector offset) 4837 public LSL_Float llWater(LSL_Vector offset)
@@ -4320,14 +4853,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4320 { 4853 {
4321 m_host.AddScriptLPS(1); 4854 m_host.AddScriptLPS(1);
4322 4855
4323 UUID uuid = (UUID)id; 4856 UUID uuid;
4324 PresenceInfo pinfo = null; 4857 if (UUID.TryParse(id, out uuid))
4325 UserAccount account;
4326
4327 UserInfoCacheEntry ce;
4328
4329 lock (m_userInfoCache)
4330 { 4858 {
4859 PresenceInfo pinfo = null;
4860 UserAccount account;
4861
4862 UserInfoCacheEntry ce;
4331 if (!m_userInfoCache.TryGetValue(uuid, out ce)) 4863 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4332 { 4864 {
4333 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4865 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
@@ -4353,7 +4885,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4353 ce.time = Util.EnvironmentTickCount(); 4885 ce.time = Util.EnvironmentTickCount();
4354 ce.account = account; 4886 ce.account = account;
4355 ce.pinfo = pinfo; 4887 ce.pinfo = pinfo;
4356
4357 m_userInfoCache[uuid] = ce; 4888 m_userInfoCache[uuid] = ce;
4358 } 4889 }
4359 else 4890 else
@@ -4362,77 +4893,78 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4362 return UUID.Zero.ToString(); 4893 return UUID.Zero.ToString();
4363 4894
4364 account = ce.account; 4895 account = ce.account;
4896 pinfo = ce.pinfo;
4897 }
4365 4898
4366 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) 4899 if (Util.EnvironmentTickCount() < ce.time ||
4367 >= LlRequestAgentDataCacheTimeoutMs) 4900 (Util.EnvironmentTickCount() - ce.time) >= LlRequestAgentDataCacheTimeoutMs)
4901 {
4902 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4903 if (pinfos != null && pinfos.Length > 0)
4368 { 4904 {
4369 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4905 foreach (PresenceInfo p in pinfos)
4370 if (pinfos != null && pinfos.Length > 0)
4371 { 4906 {
4372 foreach (PresenceInfo p in pinfos) 4907 if (p.RegionID != UUID.Zero)
4373 { 4908 {
4374 if (p.RegionID != UUID.Zero) 4909 pinfo = p;
4375 {
4376 pinfo = p;
4377 }
4378 } 4910 }
4379 } 4911 }
4380 else
4381 {
4382 pinfo = null;
4383 }
4384
4385 ce.time = Util.EnvironmentTickCount();
4386 ce.pinfo = pinfo;
4387 } 4912 }
4388 else 4913 else
4389 { 4914 pinfo = null;
4390 pinfo = ce.pinfo; 4915
4391 } 4916 ce.time = Util.EnvironmentTickCount();
4917 ce.pinfo = pinfo;
4392 } 4918 }
4393 }
4394 4919
4395 string reply = String.Empty; 4920 string reply = String.Empty;
4396 4921
4397 switch (data) 4922 switch (data)
4398 { 4923 {
4399 case ScriptBaseClass.DATA_ONLINE: 4924 case ScriptBaseClass.DATA_ONLINE: // DATA_ONLINE (0|1)
4400 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4925 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4401 reply = "1"; 4926 reply = "1";
4402 else 4927 else
4403 reply = "0"; 4928 reply = "0";
4404 break; 4929 break;
4405 case ScriptBaseClass.DATA_NAME: // (First Last) 4930 case ScriptBaseClass.DATA_NAME: // DATA_NAME (First Last)
4406 reply = account.FirstName + " " + account.LastName; 4931 reply = account.FirstName + " " + account.LastName;
4407 break; 4932 break;
4408 case ScriptBaseClass.DATA_BORN: // (YYYY-MM-DD) 4933 case ScriptBaseClass.DATA_BORN: // DATA_BORN (YYYY-MM-DD)
4409 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4934 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4410 born = born.AddSeconds(account.Created); 4935 born = born.AddSeconds(account.Created);
4411 reply = born.ToString("yyyy-MM-dd"); 4936 reply = born.ToString("yyyy-MM-dd");
4412 break; 4937 break;
4413 case ScriptBaseClass.DATA_RATING: // (0,0,0,0,0,0) 4938 case ScriptBaseClass.DATA_RATING: // DATA_RATING (0,0,0,0,0,0)
4414 reply = "0,0,0,0,0,0"; 4939 reply = "0,0,0,0,0,0";
4415 break; 4940 break;
4416 case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant. 4941 case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant.
4417 reply = account.UserLevel.ToString(); 4942 reply = account.UserLevel.ToString();
4418 break; 4943 break;
4419 case ScriptBaseClass.DATA_PAYINFO: // (0|1|2|3) 4944 case ScriptBaseClass.DATA_PAYINFO: // DATA_PAYINFO (0|1|2|3)
4420 reply = "0"; 4945 reply = "0";
4421 break; 4946 break;
4422 default: 4947 default:
4423 return UUID.Zero.ToString(); // Raise no event 4948 return UUID.Zero.ToString(); // Raise no event
4424 } 4949 }
4425 4950
4426 UUID rq = UUID.Random(); 4951 UUID rq = UUID.Random();
4427 4952
4428 UUID tid = AsyncCommands. 4953 UUID tid = AsyncCommands.
4429 DataserverPlugin.RegisterRequest(m_host.LocalId, 4954 DataserverPlugin.RegisterRequest(m_host.LocalId,
4430 m_item.ItemID, rq.ToString()); 4955 m_item.ItemID, rq.ToString());
4431 4956
4432 AsyncCommands. 4957 AsyncCommands.
4433 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4958 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4434 4959
4435 return tid.ToString(); 4960 ScriptSleep(m_sleepMsOnRequestAgentData);
4961 return tid.ToString();
4962 }
4963 else
4964 {
4965 Error("llRequestAgentData","Invalid UUID passed to llRequestAgentData.");
4966 }
4967 return "";
4436 } 4968 }
4437 4969
4438 public LSL_String llRequestInventoryData(string name) 4970 public LSL_String llRequestInventoryData(string name)
@@ -4464,10 +4996,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4464 reply); 4996 reply);
4465 }); 4997 });
4466 4998
4999 ScriptSleep(m_sleepMsOnRequestInventoryData);
4467 return tid.ToString(); 5000 return tid.ToString();
4468 } 5001 }
4469 } 5002 }
4470 5003
5004 ScriptSleep(m_sleepMsOnRequestInventoryData);
4471 return String.Empty; 5005 return String.Empty;
4472 } 5006 }
4473 5007
@@ -4484,15 +5018,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4484 if (UUID.TryParse(agent, out agentId)) 5018 if (UUID.TryParse(agent, out agentId))
4485 { 5019 {
4486 ScenePresence presence = World.GetScenePresence(agentId); 5020 ScenePresence presence = World.GetScenePresence(agentId);
4487 if (presence != null) 5021 if (presence != null && presence.PresenceType != PresenceType.Npc)
4488 { 5022 {
5023 // agent must not be a god
5024 if (presence.GodController.UserLevel >= 200) return;
5025
4489 // agent must be over the owners land 5026 // agent must be over the owners land
4490 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) 5027 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
4491 { 5028 {
4492 World.TeleportClientHome(agentId, presence.ControllingClient); 5029 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
5030 {
5031 // They can't be teleported home for some reason
5032 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
5033 if (regionInfo != null)
5034 {
5035 World.RequestTeleportLocation(
5036 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
5037 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
5038 }
5039 }
4493 } 5040 }
4494 } 5041 }
4495 } 5042 }
5043
5044 ScriptSleep(m_sleepMsOnSetDamage);
4496 } 5045 }
4497 5046
4498 public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) 5047 public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt)
@@ -4505,20 +5054,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4505 ScenePresence presence = World.GetScenePresence(agentId); 5054 ScenePresence presence = World.GetScenePresence(agentId);
4506 if (presence != null && presence.PresenceType != PresenceType.Npc) 5055 if (presence != null && presence.PresenceType != PresenceType.Npc)
4507 { 5056 {
4508 // agent must not be a god
4509 if (presence.GodLevel >= 200) return;
4510
4511 if (destination == String.Empty) 5057 if (destination == String.Empty)
4512 destination = World.RegionInfo.RegionName; 5058 destination = World.RegionInfo.RegionName;
4513 5059
4514 // agent must be over the owners land 5060 if (m_item.PermsGranter == agentId)
4515 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) 5061 {
5062 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) != 0)
5063 {
5064 DoLLTeleport(presence, destination, targetPos, targetLookAt);
5065 }
5066 }
5067
5068 // agent must be wearing the object
5069 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4516 { 5070 {
4517 DoLLTeleport(presence, destination, targetPos, targetLookAt); 5071 DoLLTeleport(presence, destination, targetPos, targetLookAt);
4518 } 5072 }
4519 else // or must be wearing the prim 5073 else
4520 { 5074 {
4521 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID) 5075 // agent must not be a god
5076 if (presence.IsViewerUIGod) return;
5077
5078 // agent must be over the owners land
5079 ILandObject agentLand = World.LandChannel.GetLandObject(presence.AbsolutePosition);
5080 ILandObject objectLand = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
5081 if (m_host.OwnerID == objectLand.LandData.OwnerID && m_host.OwnerID == agentLand.LandData.OwnerID)
4522 { 5082 {
4523 DoLLTeleport(presence, destination, targetPos, targetLookAt); 5083 DoLLTeleport(presence, destination, targetPos, targetLookAt);
4524 } 5084 }
@@ -4536,23 +5096,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4536 5096
4537 if (UUID.TryParse(agent, out agentId)) 5097 if (UUID.TryParse(agent, out agentId))
4538 { 5098 {
5099 // This function is owner only!
5100 if (m_host.OwnerID != agentId)
5101 return;
5102
4539 ScenePresence presence = World.GetScenePresence(agentId); 5103 ScenePresence presence = World.GetScenePresence(agentId);
4540 if (presence != null && presence.PresenceType != PresenceType.Npc) 5104
5105 if (presence == null || presence.PresenceType == PresenceType.Npc)
5106 return;
5107
5108 // Can't TP sitting avatars
5109 if (presence.ParentID != 0) // Sitting
5110 return;
5111
5112 if (m_item.PermsGranter == agentId)
4541 { 5113 {
4542 // agent must not be a god 5114 // If attached using llAttachToAvatarTemp, cowardly refuse
4543 if (presence.GodLevel >= 200) return; 5115 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.ParentGroup.FromItemID == UUID.Zero)
5116 return;
4544 5117
4545 // agent must be over the owners land 5118 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) != 0)
4546 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
4547 {
4548 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
4549 }
4550 else // or must be wearing the prim
4551 { 5119 {
4552 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID) 5120 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
4553 {
4554 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
4555 }
4556 } 5121 }
4557 } 5122 }
4558 } 5123 }
@@ -4601,13 +5166,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4601 { 5166 {
4602 Error("llTextBox", "Empty message"); 5167 Error("llTextBox", "Empty message");
4603 } 5168 }
4604 else if (message.Length > 512) 5169 else if (Encoding.UTF8.GetByteCount(message) > 512)
4605 { 5170 {
4606 Error("llTextBox", "Message more than 512 characters"); 5171 Error("llTextBox", "Message longer than 512 bytes");
4607 } 5172 }
4608 else 5173 else
4609 { 5174 {
4610 dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID); 5175 dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID);
5176 ScriptSleep(m_sleepMsOnTextBox);
4611 } 5177 }
4612 } 5178 }
4613 5179
@@ -4625,9 +5191,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4625 { 5191 {
4626 m_host.AddScriptLPS(1); 5192 m_host.AddScriptLPS(1);
4627 5193
5194 if(impact_sound == "")
5195 {
5196 m_host.CollisionSoundVolume = (float)impact_volume;
5197 m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
5198 m_host.CollisionSoundType = -1; // disable all sounds
5199 m_host.aggregateScriptEvents();
5200 return;
5201 }
5202
4628 // TODO: Parameter check logic required. 5203 // TODO: Parameter check logic required.
4629 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound); 5204 UUID soundId = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
4630 m_host.CollisionSoundVolume = (float)impact_volume; 5205 if(soundId != UUID.Zero)
5206 {
5207 m_host.CollisionSound = soundId;
5208 m_host.CollisionSoundVolume = (float)impact_volume;
5209 m_host.CollisionSoundType = 1;
5210 }
5211 else
5212 m_host.CollisionSoundType = -1;
5213
5214 m_host.aggregateScriptEvents();
4631 } 5215 }
4632 5216
4633 public LSL_String llGetAnimation(string id) 5217 public LSL_String llGetAnimation(string id)
@@ -4641,14 +5225,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4641 5225
4642 if (m_host.RegionHandle == presence.RegionHandle) 5226 if (m_host.RegionHandle == presence.RegionHandle)
4643 { 5227 {
4644 Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames;
4645
4646 if (presence != null) 5228 if (presence != null)
4647 { 5229 {
4648 AnimationSet currentAnims = presence.Animator.Animations; 5230// if (presence.SitGround)
4649 string currentAnimationState = String.Empty; 5231// return "Sitting on Ground";
4650 if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState)) 5232// if (presence.ParentID != 0 || presence.ParentUUID != UUID.Zero)
4651 return currentAnimationState; 5233// return "Sitting";
5234
5235 string movementAnimation = presence.Animator.CurrentMovementAnimation;
5236 string lslMovementAnimation;
5237
5238 if (MovementAnimationsForLSL.TryGetValue(movementAnimation, out lslMovementAnimation))
5239 return lslMovementAnimation;
4652 } 5240 }
4653 } 5241 }
4654 5242
@@ -4712,7 +5300,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4712 return; 5300 return;
4713 5301
4714 // Pushee is in GodMode this pushing object isn't owned by them 5302 // Pushee is in GodMode this pushing object isn't owned by them
4715 if (avatar.GodLevel > 0 && m_host.OwnerID != targetID) 5303 if (avatar.IsViewerUIGod && m_host.OwnerID != targetID)
4716 return; 5304 return;
4717 5305
4718 pusheeav = avatar; 5306 pusheeav = avatar;
@@ -4796,7 +5384,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4796 { 5384 {
4797 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 5385 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4798 float distance_term = distance * distance * distance; // Script Energy 5386 float distance_term = distance * distance * distance; // Script Energy
4799 float pusher_mass = m_host.GetMass(); 5387 // use total object mass and not part
5388 float pusher_mass = m_host.ParentGroup.GetMass();
4800 5389
4801 float PUSH_ATTENUATION_DISTANCE = 17f; 5390 float PUSH_ATTENUATION_DISTANCE = 17f;
4802 float PUSH_ATTENUATION_SCALE = 5f; 5391 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4831,7 +5420,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4831 { 5420 {
4832 if (local != 0) 5421 if (local != 0)
4833 { 5422 {
4834 applied_linear_impulse *= m_host.GetWorldRotation(); 5423// applied_linear_impulse *= m_host.GetWorldRotation();
5424 applied_linear_impulse *= pusheeav.GetWorldRotation();
4835 } 5425 }
4836 5426
4837 pa.AddForce(applied_linear_impulse, true); 5427 pa.AddForce(applied_linear_impulse, true);
@@ -4891,20 +5481,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4891 { 5481 {
4892 m_host.AddScriptLPS(1); 5482 m_host.AddScriptLPS(1);
4893 5483
4894 return GetNumberOfSides(m_host); 5484 return m_host.GetNumberOfSides();
4895 } 5485 }
4896 5486
4897 protected int GetNumberOfSides(SceneObjectPart part) 5487 protected int GetNumberOfSides(SceneObjectPart part)
4898 { 5488 {
4899 int sides = part.GetNumberOfSides(); 5489 return part.GetNumberOfSides();
4900
4901 if (part.GetPrimType() == PrimType.SPHERE && part.Shape.ProfileHollow > 0)
4902 {
4903 // Make up for a bug where LSL shows 4 sides rather than 2
4904 sides += 2;
4905 }
4906
4907 return sides;
4908 } 5490 }
4909 5491
4910 5492
@@ -4959,20 +5541,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4959 { 5541 {
4960 m_host.AddScriptLPS(1); 5542 m_host.AddScriptLPS(1);
4961 5543
4962 if (Math.Abs(rot.s) > 1) // normalization needed 5544 rot.Normalize();
4963 rot.Normalize();
4964 5545
4965 double s = Math.Sqrt(1 - rot.s * rot.s); 5546 double s = Math.Sqrt(1 - rot.s * rot.s);
4966 if (s < 0.001) 5547 if (s < 1e-8)
4967 { 5548 return new LSL_Vector(0, 0, 0);
4968 return new LSL_Vector(1, 0, 0); 5549
4969 } 5550 double invS = 1.0 / s;
4970 else 5551 if (rot.s < 0)
4971 { 5552 invS = -invS;
4972 double invS = 1.0 / s; 5553 return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS);
4973 if (rot.s < 0) invS = -invS;
4974 return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS);
4975 }
4976 } 5554 }
4977 5555
4978 5556
@@ -4981,11 +5559,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4981 { 5559 {
4982 m_host.AddScriptLPS(1); 5560 m_host.AddScriptLPS(1);
4983 5561
4984 if (Math.Abs(rot.s) > 1) // normalization needed 5562 rot.Normalize();
4985 rot.Normalize();
4986 5563
4987 double angle = 2 * Math.Acos(rot.s); 5564 double angle = 2 * Math.Acos(rot.s);
4988 if (angle > Math.PI) 5565 if (angle > Math.PI)
4989 angle = 2 * Math.PI - angle; 5566 angle = 2 * Math.PI - angle;
4990 5567
4991 return angle; 5568 return angle;
@@ -5185,43 +5762,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5185 { 5762 {
5186 m_host.AddScriptLPS(1); 5763 m_host.AddScriptLPS(1);
5187 5764
5188 if (src == null) 5765 return src.Length;
5189 {
5190 return 0;
5191 }
5192 else
5193 {
5194 return src.Length;
5195 }
5196 } 5766 }
5197 5767
5198 public LSL_Integer llList2Integer(LSL_List src, int index) 5768 public LSL_Integer llList2Integer(LSL_List src, int index)
5199 { 5769 {
5200 m_host.AddScriptLPS(1); 5770 m_host.AddScriptLPS(1);
5201 if (index < 0) 5771 if (index < 0)
5202 {
5203 index = src.Length + index; 5772 index = src.Length + index;
5204 } 5773
5205 if (index >= src.Length || index < 0) 5774 if (index >= src.Length || index < 0)
5206 {
5207 return 0; 5775 return 0;
5208 } 5776
5777 object item = src.Data[index];
5209 5778
5210 // Vectors & Rotations always return zero in SL, but 5779 // Vectors & Rotations always return zero in SL, but
5211 // keys don't always return zero, it seems to be a bit complex. 5780 // keys don't always return zero, it seems to be a bit complex.
5212 else if (src.Data[index] is LSL_Vector || 5781 if (item is LSL_Vector || item is LSL_Rotation)
5213 src.Data[index] is LSL_Rotation)
5214 {
5215 return 0; 5782 return 0;
5216 } 5783
5217 try 5784 try
5218 { 5785 {
5219 5786 if (item is LSL_Integer)
5220 if (src.Data[index] is LSL_Integer) 5787 return (LSL_Integer)item;
5221 return (LSL_Integer)src.Data[index]; 5788 else if (item is LSL_Float)
5222 else if (src.Data[index] is LSL_Float) 5789 return Convert.ToInt32(((LSL_Float)item).value);;
5223 return Convert.ToInt32(((LSL_Float)src.Data[index]).value); 5790 return new LSL_Integer(item.ToString());
5224 return new LSL_Integer(src.Data[index].ToString());
5225 } 5791 }
5226 catch (FormatException) 5792 catch (FormatException)
5227 { 5793 {
@@ -5233,38 +5799,50 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5233 { 5799 {
5234 m_host.AddScriptLPS(1); 5800 m_host.AddScriptLPS(1);
5235 if (index < 0) 5801 if (index < 0)
5236 {
5237 index = src.Length + index; 5802 index = src.Length + index;
5238 } 5803
5239 if (index >= src.Length || index < 0) 5804 if (index >= src.Length || index < 0)
5240 { 5805 return 0;
5241 return 0.0; 5806
5242 } 5807 object item = src.Data[index];
5243 5808
5244 // Vectors & Rotations always return zero in SL 5809 // Vectors & Rotations always return zero in SL
5245 else if (src.Data[index] is LSL_Vector || 5810 if(item is LSL_Vector || item is LSL_Rotation)
5246 src.Data[index] is LSL_Rotation)
5247 {
5248 return 0; 5811 return 0;
5249 } 5812
5250 // valid keys seem to get parsed as integers then converted to floats 5813 // valid keys seem to get parsed as integers then converted to floats
5251 else 5814 if (item is LSL_Key)
5252 { 5815 {
5253 UUID uuidt; 5816 UUID uuidt;
5254 if (src.Data[index] is LSL_Key && UUID.TryParse(src.Data[index].ToString(), out uuidt)) 5817 string s = item.ToString();
5255 { 5818 if(UUID.TryParse(s, out uuidt))
5256 return Convert.ToDouble(new LSL_Integer(src.Data[index].ToString()).value); 5819 return Convert.ToDouble(new LSL_Integer(s).value);
5257 } 5820// we can't do this because a string is also a LSL_Key for now :(
5821// else
5822// return 0;
5258 } 5823 }
5824
5259 try 5825 try
5260 { 5826 {
5261 if (src.Data[index] is LSL_Integer) 5827 if (item is LSL_Integer)
5262 return Convert.ToDouble(((LSL_Integer)src.Data[index]).value); 5828 return Convert.ToDouble(((LSL_Integer)item).value);
5263 else if (src.Data[index] is LSL_Float) 5829 else if (item is LSL_Float)
5264 return Convert.ToDouble(((LSL_Float)src.Data[index]).value); 5830 return Convert.ToDouble(((LSL_Float)item).value);
5265 else if (src.Data[index] is LSL_String) 5831 else if (item is LSL_String)
5266 return Convert.ToDouble(((LSL_String)src.Data[index]).m_string); 5832 {
5267 return Convert.ToDouble(src.Data[index]); 5833 string str = ((LSL_String)item).m_string;
5834 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5835 if (m != Match.Empty)
5836 {
5837 str = m.Value;
5838 double d = 0.0;
5839 if (!Double.TryParse(str, out d))
5840 return 0.0;
5841 return d;
5842 }
5843 return 0.0;
5844 }
5845 return Convert.ToDouble(item);
5268 } 5846 }
5269 catch (FormatException) 5847 catch (FormatException)
5270 { 5848 {
@@ -5276,13 +5854,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5276 { 5854 {
5277 m_host.AddScriptLPS(1); 5855 m_host.AddScriptLPS(1);
5278 if (index < 0) 5856 if (index < 0)
5279 {
5280 index = src.Length + index; 5857 index = src.Length + index;
5281 } 5858
5282 if (index >= src.Length || index < 0) 5859 if (index >= src.Length || index < 0)
5283 {
5284 return String.Empty; 5860 return String.Empty;
5285 } 5861
5286 return src.Data[index].ToString(); 5862 return src.Data[index].ToString();
5287 } 5863 }
5288 5864
@@ -5290,14 +5866,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5290 { 5866 {
5291 m_host.AddScriptLPS(1); 5867 m_host.AddScriptLPS(1);
5292 if (index < 0) 5868 if (index < 0)
5293 {
5294 index = src.Length + index; 5869 index = src.Length + index;
5295 }
5296 5870
5297 if (index >= src.Length || index < 0) 5871 if (index >= src.Length || index < 0)
5298 { 5872 return String.Empty;
5299 return ""; 5873
5300 } 5874 object item = src.Data[index];
5301 5875
5302 // SL spits out an empty string for types other than key & string 5876 // SL spits out an empty string for types other than key & string
5303 // At the time of patching, LSL_Key is currently LSL_String, 5877 // At the time of patching, LSL_Key is currently LSL_String,
@@ -5306,31 +5880,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5306 // as it's own struct 5880 // as it's own struct
5307 // NOTE: 3rd case is needed because a NULL_KEY comes through as 5881 // NOTE: 3rd case is needed because a NULL_KEY comes through as
5308 // type 'obj' and wrongly returns "" 5882 // type 'obj' and wrongly returns ""
5309 else if (!(src.Data[index] is LSL_String || 5883 if (!(item is LSL_String ||
5310 src.Data[index] is LSL_Key || 5884 item is LSL_Key ||
5311 src.Data[index].ToString() == "00000000-0000-0000-0000-000000000000")) 5885 item.ToString() == "00000000-0000-0000-0000-000000000000"))
5312 { 5886 {
5313 return ""; 5887 return String.Empty;
5314 } 5888 }
5315 5889
5316 return src.Data[index].ToString(); 5890 return item.ToString();
5317 } 5891 }
5318 5892
5319 public LSL_Vector llList2Vector(LSL_List src, int index) 5893 public LSL_Vector llList2Vector(LSL_List src, int index)
5320 { 5894 {
5321 m_host.AddScriptLPS(1); 5895 m_host.AddScriptLPS(1);
5322 if (index < 0) 5896 if (index < 0)
5323 {
5324 index = src.Length + index; 5897 index = src.Length + index;
5325 } 5898
5326 if (index >= src.Length || index < 0) 5899 if (index >= src.Length || index < 0)
5327 {
5328 return new LSL_Vector(0, 0, 0); 5900 return new LSL_Vector(0, 0, 0);
5329 } 5901
5330 if (src.Data[index].GetType() == typeof(LSL_Vector)) 5902 object item = src.Data[index];
5331 { 5903
5332 return (LSL_Vector)src.Data[index]; 5904 if (item.GetType() == typeof(LSL_Vector))
5333 } 5905 return (LSL_Vector)item;
5334 5906
5335 // SL spits always out ZERO_VECTOR for anything other than 5907 // SL spits always out ZERO_VECTOR for anything other than
5336 // strings or vectors. Although keys always return ZERO_VECTOR, 5908 // strings or vectors. Although keys always return ZERO_VECTOR,
@@ -5338,28 +5910,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5338 // a string, a key as string and a string that by coincidence 5910 // a string, a key as string and a string that by coincidence
5339 // is a string, so we're going to leave that up to the 5911 // is a string, so we're going to leave that up to the
5340 // LSL_Vector constructor. 5912 // LSL_Vector constructor.
5341 else if (!(src.Data[index] is LSL_String || 5913 if(item is LSL_Vector)
5342 src.Data[index] is LSL_Vector)) 5914 return (LSL_Vector) item;
5343 { 5915
5344 return new LSL_Vector(0, 0, 0); 5916 if (item is LSL_String)
5345 } 5917 return new LSL_Vector(item.ToString());
5346 else 5918
5347 { 5919 return new LSL_Vector(0, 0, 0);
5348 return new LSL_Vector(src.Data[index].ToString());
5349 }
5350 } 5920 }
5351 5921
5352 public LSL_Rotation llList2Rot(LSL_List src, int index) 5922 public LSL_Rotation llList2Rot(LSL_List src, int index)
5353 { 5923 {
5354 m_host.AddScriptLPS(1); 5924 m_host.AddScriptLPS(1);
5355 if (index < 0) 5925 if (index < 0)
5356 {
5357 index = src.Length + index; 5926 index = src.Length + index;
5358 } 5927
5359 if (index >= src.Length || index < 0) 5928 if (index >= src.Length || index < 0)
5360 {
5361 return new LSL_Rotation(0, 0, 0, 1); 5929 return new LSL_Rotation(0, 0, 0, 1);
5362 } 5930
5931 object item = src.Data[index];
5363 5932
5364 // SL spits always out ZERO_ROTATION for anything other than 5933 // SL spits always out ZERO_ROTATION for anything other than
5365 // strings or vectors. Although keys always return ZERO_ROTATION, 5934 // strings or vectors. Although keys always return ZERO_ROTATION,
@@ -5367,19 +5936,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5367 // a string, a key as string and a string that by coincidence 5936 // a string, a key as string and a string that by coincidence
5368 // is a string, so we're going to leave that up to the 5937 // is a string, so we're going to leave that up to the
5369 // LSL_Rotation constructor. 5938 // LSL_Rotation constructor.
5370 else if (!(src.Data[index] is LSL_String || 5939
5371 src.Data[index] is LSL_Rotation)) 5940 if (item.GetType() == typeof(LSL_Rotation))
5372 { 5941 return (LSL_Rotation)item;
5373 return new LSL_Rotation(0, 0, 0, 1); 5942
5374 } 5943 if (item is LSL_String)
5375 else if (src.Data[index].GetType() == typeof(LSL_Rotation))
5376 {
5377 return (LSL_Rotation)src.Data[index];
5378 }
5379 else
5380 {
5381 return new LSL_Rotation(src.Data[index].ToString()); 5944 return new LSL_Rotation(src.Data[index].ToString());
5382 } 5945
5946 return new LSL_Rotation(0, 0, 0, 1);
5383 } 5947 }
5384 5948
5385 public LSL_List llList2List(LSL_List src, int start, int end) 5949 public LSL_List llList2List(LSL_List src, int start, int end)
@@ -5567,7 +6131,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5567 } 6131 }
5568 } 6132 }
5569 } 6133 }
5570 else { 6134 else
6135 {
5571 object[] array = new object[src.Length]; 6136 object[] array = new object[src.Length];
5572 Array.Copy(src.Data, 0, array, 0, src.Length); 6137 Array.Copy(src.Data, 0, array, 0, src.Length);
5573 result = new LSL_List(array); 6138 result = new LSL_List(array);
@@ -5674,7 +6239,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5674 public LSL_Integer llGetRegionAgentCount() 6239 public LSL_Integer llGetRegionAgentCount()
5675 { 6240 {
5676 m_host.AddScriptLPS(1); 6241 m_host.AddScriptLPS(1);
5677 return new LSL_Integer(World.GetRootAgentCount()); 6242
6243 int count = 0;
6244 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
6245 count++;
6246 });
6247
6248 return new LSL_Integer(count);
5678 } 6249 }
5679 6250
5680 public LSL_Vector llGetRegionCorner() 6251 public LSL_Vector llGetRegionCorner()
@@ -5742,10 +6313,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5742 IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>(); 6313 IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>();
5743 return UrlModule.ExternalHostNameForLSL; 6314 return UrlModule.ExternalHostNameForLSL;
5744 } 6315 }
6316 else if (name == "region_max_prims")
6317 {
6318 return World.RegionInfo.ObjectCapacity.ToString();
6319 }
6320 else if (name == "region_object_bonus")
6321 {
6322 return World.RegionInfo.RegionSettings.ObjectBonus.ToString();
6323 }
5745 else 6324 else
5746 { 6325 {
5747 return ""; 6326 return "";
5748 } 6327 }
6328
5749 } 6329 }
5750 6330
5751 /// <summary> 6331 /// <summary>
@@ -5821,17 +6401,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5821 { 6401 {
5822 for (int i = 0; i < length; i++) 6402 for (int i = 0; i < length; i++)
5823 { 6403 {
6404 int needle = llGetListEntryType(test, 0).value;
6405 int haystack = llGetListEntryType(src, i).value;
6406
5824 // Why this piece of insanity? This is because most script constants are C# value types (e.g. int) 6407 // Why this piece of insanity? This is because most script constants are C# value types (e.g. int)
5825 // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code 6408 // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code
5826 // and so the comparison fails even if the LSL_Integer conceptually has the same value. 6409 // and so the comparison fails even if the LSL_Integer conceptually has the same value.
5827 // Therefore, here we test Equals on both the source and destination objects. 6410 // Therefore, here we test Equals on both the source and destination objects.
5828 // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)). 6411 // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)).
5829 if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])) 6412 if ((needle == haystack) && (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])))
5830 { 6413 {
5831 int j; 6414 int j;
5832 for (j = 1; j < test.Length; j++) 6415 for (j = 1; j < test.Length; j++)
5833 if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))) 6416 {
6417 needle = llGetListEntryType(test, j).value;
6418 haystack = llGetListEntryType(src, i+j).value;
6419
6420 if ((needle != haystack) || (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))))
5834 break; 6421 break;
6422 }
5835 6423
5836 if (j == test.Length) 6424 if (j == test.Length)
5837 { 6425 {
@@ -5869,64 +6457,61 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5869 { 6457 {
5870 m_host.AddScriptLPS(1); 6458 m_host.AddScriptLPS(1);
5871 6459
5872 // edge will be used to pass the Region Coordinates offset 6460 if(dir.x == 0 && dir.y == 0)
5873 // we want to check for a neighboring sim 6461 return 1; // SL wiki
5874 LSL_Vector edge = new LSL_Vector(0, 0, 0); 6462
6463 float rsx = World.RegionInfo.RegionSizeX;
6464 float rsy = World.RegionInfo.RegionSizeY;
6465
6466 // can understand what sl does if position is not in region, so do something :)
6467 float px = (float)Util.Clamp(pos.x, 0.5, rsx - 0.5);
6468 float py = (float)Util.Clamp(pos.y, 0.5, rsy - 0.5);
6469
6470 float ex, ey;
5875 6471
5876 if (dir.x == 0) 6472 if (dir.x == 0)
5877 { 6473 {
5878 if (dir.y == 0) 6474 ex = px;
5879 { 6475 ey = dir.y > 0 ? rsy + 1.0f : -1.0f;
5880 // Direction vector is 0,0 so return 6476 }
5881 // false since we're staying in the sim 6477 else if(dir.y == 0)
5882 return 0; 6478 {
5883 } 6479 ex = dir.x > 0 ? rsx + 1.0f : -1.0f;
5884 else 6480 ey = py;
5885 {
5886 // Y is the only valid direction
5887 edge.y = dir.y / Math.Abs(dir.y);
5888 }
5889 } 6481 }
5890 else 6482 else
5891 { 6483 {
5892 LSL_Float mag; 6484 float dx = (float) dir.x;
5893 if (dir.x > 0) 6485 float dy = (float) dir.y;
5894 {
5895 mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x;
5896 }
5897 else
5898 {
5899 mag = (pos.x/dir.x);
5900 }
5901 6486
5902 mag = Math.Abs(mag); 6487 float t1 = dx * dx + dy * dy;
6488 t1 = (float)Math.Sqrt(t1);
6489 dx /= t1;
6490 dy /= t1;
5903 6491
5904 edge.y = pos.y + (dir.y * mag); 6492 if(dx > 0)
5905 6493 t1 = (rsx + 1f - px)/dx;
5906 if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0)
5907 {
5908 // Y goes out of bounds first
5909 edge.y = dir.y / Math.Abs(dir.y);
5910 }
5911 else 6494 else
5912 { 6495 t1 = -(px + 1f)/dx;
5913 // X goes out of bounds first or its a corner exit
5914 edge.y = 0;
5915 edge.x = dir.x / Math.Abs(dir.x);
5916 }
5917 }
5918 6496
5919 List<GridRegion> neighbors = World.GridService.GetNeighbours(World.RegionInfo.ScopeID, World.RegionInfo.RegionID); 6497 float t2;
6498 if(dy > 0)
6499 t2 = (rsy + 1f - py)/dy;
6500 else
6501 t2 = -(py + 1f)/dy;
5920 6502
5921 uint neighborX = World.RegionInfo.RegionLocX + (uint)dir.x; 6503 if(t1 > t2)
5922 uint neighborY = World.RegionInfo.RegionLocY + (uint)dir.y; 6504 t1 = t2;
5923 6505
5924 foreach (GridRegion sri in neighbors) 6506 ex = px + t1 * dx;
5925 { 6507 ey = py + t1 * dy;
5926 if (sri.RegionCoordX == neighborX && sri.RegionCoordY == neighborY)
5927 return 0;
5928 } 6508 }
5929 6509
6510 ex += World.RegionInfo.WorldLocX;
6511 ey += World.RegionInfo.WorldLocY;
6512
6513 if(World.GridService.GetRegionByPosition(World.RegionInfo.ScopeID, (int)ex, (int)ey) != null)
6514 return 0;
5930 return 1; 6515 return 1;
5931 } 6516 }
5932 6517
@@ -5980,6 +6565,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5980 flags |= ScriptBaseClass.AGENT_AWAY; 6565 flags |= ScriptBaseClass.AGENT_AWAY;
5981 } 6566 }
5982 6567
6568 UUID busy = new UUID("efcf670c-2d18-8128-973a-034ebc806b67");
6569 UUID[] anims = agent.Animator.GetAnimationArray();
6570 if (Array.Exists<UUID>(anims, a => { return a == busy; }))
6571 {
6572 flags |= ScriptBaseClass.AGENT_BUSY;
6573 }
6574
5983 // seems to get unset, even if in mouselook, when avatar is sitting on a prim??? 6575 // seems to get unset, even if in mouselook, when avatar is sitting on a prim???
5984 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) 6576 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
5985 { 6577 {
@@ -6027,6 +6619,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6027 flags |= ScriptBaseClass.AGENT_SITTING; 6619 flags |= ScriptBaseClass.AGENT_SITTING;
6028 } 6620 }
6029 6621
6622 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
6623 {
6624 flags |= ScriptBaseClass.AGENT_MALE;
6625 }
6626
6030 return flags; 6627 return flags;
6031 } 6628 }
6032 6629
@@ -6056,11 +6653,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6056 /// AGENT_LIST_PARCEL - all in the same parcel as the scripted object 6653 /// AGENT_LIST_PARCEL - all in the same parcel as the scripted object
6057 /// AGENT_LIST_PARCEL_OWNER - all in any parcel owned by the owner of the 6654 /// AGENT_LIST_PARCEL_OWNER - all in any parcel owned by the owner of the
6058 /// current parcel. 6655 /// current parcel.
6656 /// AGENT_LIST_EXCLUDENPC ignore NPCs (bit mask)
6059 /// </summary> 6657 /// </summary>
6060 public LSL_List llGetAgentList(LSL_Integer scope, LSL_List options) 6658 public LSL_List llGetAgentList(LSL_Integer scope, LSL_List options)
6061 { 6659 {
6062 m_host.AddScriptLPS(1); 6660 m_host.AddScriptLPS(1);
6063 6661
6662 // do our bit masks part
6663 bool noNPC = (scope & ScriptBaseClass.AGENT_LIST_EXCLUDENPC) !=0;
6664
6665 // remove bit masks part
6666 scope &= ~ ScriptBaseClass.AGENT_LIST_EXCLUDENPC;
6667
6064 // the constants are 1, 2 and 4 so bits are being set, but you 6668 // the constants are 1, 2 and 4 so bits are being set, but you
6065 // get an error "INVALID_SCOPE" if it is anything but 1, 2 and 4 6669 // get an error "INVALID_SCOPE" if it is anything but 1, 2 and 4
6066 bool regionWide = scope == ScriptBaseClass.AGENT_LIST_REGION; 6670 bool regionWide = scope == ScriptBaseClass.AGENT_LIST_REGION;
@@ -6101,8 +6705,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6101 World.ForEachRootScenePresence( 6705 World.ForEachRootScenePresence(
6102 delegate (ScenePresence ssp) 6706 delegate (ScenePresence ssp)
6103 { 6707 {
6708 if(noNPC && ssp.IsNPC)
6709 return;
6710
6104 // Gods are not listed in SL 6711 // Gods are not listed in SL
6105 if (!ssp.IsDeleted && ssp.GodLevel == 0.0 && !ssp.IsChildAgent) 6712 if (!ssp.IsDeleted && !ssp.IsViewerUIGod && !ssp.IsChildAgent)
6106 { 6713 {
6107 if (!regionWide) 6714 if (!regionWide)
6108 { 6715 {
@@ -6135,6 +6742,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6135 { 6742 {
6136 m_host.AddScriptLPS(1); 6743 m_host.AddScriptLPS(1);
6137 m_host.AdjustSoundGain(volume); 6744 m_host.AdjustSoundGain(volume);
6745 ScriptSleep(m_sleepMsOnAdjustSoundVolume);
6138 } 6746 }
6139 6747
6140 public void llSetSoundRadius(double radius) 6748 public void llSetSoundRadius(double radius)
@@ -6180,9 +6788,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6180 6788
6181 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6789 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6182 6790
6183 foreach (SceneObjectPart part in parts) 6791 try
6792 {
6793 foreach (SceneObjectPart part in parts)
6794 {
6795 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6796 }
6797 }
6798 finally
6184 { 6799 {
6185 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6186 } 6800 }
6187 } 6801 }
6188 6802
@@ -6236,10 +6850,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6236 6850
6237 if (m_host.OwnerID == land.LandData.OwnerID) 6851 if (m_host.OwnerID == land.LandData.OwnerID)
6238 { 6852 {
6239 World.TeleportClientHome(agentID, presence.ControllingClient); 6853 Vector3 p = World.GetNearestAllowedPosition(presence, land);
6854 presence.TeleportOnEject(p);
6855 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
6240 } 6856 }
6241 } 6857 }
6242 } 6858 }
6859 ScriptSleep(m_sleepMsOnEjectFromLand);
6860 }
6861
6862 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6863 {
6864 return ParseString2List(str, separators, in_spacers, false);
6243 } 6865 }
6244 6866
6245 public LSL_Integer llOverMyLand(string id) 6867 public LSL_Integer llOverMyLand(string id)
@@ -6294,26 +6916,59 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6294 } 6916 }
6295 else 6917 else
6296 { 6918 {
6297 agentSize = GetAgentSize(avatar); 6919// agentSize = new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight);
6920 Vector3 s = avatar.Appearance.AvatarSize;
6921 agentSize = new LSL_Vector(s.X, s.Y, s.Z);
6298 } 6922 }
6299
6300 return agentSize; 6923 return agentSize;
6301 } 6924 }
6302 6925
6303 public LSL_Integer llSameGroup(string agent) 6926 public LSL_Integer llSameGroup(string id)
6304 { 6927 {
6305 m_host.AddScriptLPS(1); 6928 m_host.AddScriptLPS(1);
6306 UUID agentId = new UUID(); 6929 UUID uuid = new UUID();
6307 if (!UUID.TryParse(agent, out agentId)) 6930 if (!UUID.TryParse(id, out uuid))
6308 return new LSL_Integer(0);
6309 ScenePresence presence = World.GetScenePresence(agentId);
6310 if (presence == null || presence.IsChildAgent) // Return flase for child agents
6311 return new LSL_Integer(0); 6931 return new LSL_Integer(0);
6312 IClientAPI client = presence.ControllingClient; 6932
6313 if (m_host.GroupID == client.ActiveGroupId) 6933 // Check if it's a group key
6934 if (uuid == m_host.ParentGroup.RootPart.GroupID)
6314 return new LSL_Integer(1); 6935 return new LSL_Integer(1);
6315 else 6936
6937 // Handle object case
6938 SceneObjectPart part = World.GetSceneObjectPart(uuid);
6939 if (part != null)
6940 {
6941
6942 if(part.ParentGroup.IsAttachment)
6943 {
6944 uuid = part.ParentGroup.AttachedAvatar;
6945 }
6946 else
6947 {
6948 // This will handle both deed and non-deed and also the no
6949 // group case
6950 if (part.ParentGroup.RootPart.GroupID == m_host.ParentGroup.RootPart.GroupID)
6951 return new LSL_Integer(1);
6952
6953 return new LSL_Integer(0);
6954 }
6955 }
6956
6957 // Handle the case where id names an avatar
6958 ScenePresence presence = World.GetScenePresence(uuid);
6959 if (presence != null)
6960 {
6961 if (presence.IsChildAgent)
6962 return new LSL_Integer(0);
6963
6964 IClientAPI client = presence.ControllingClient;
6965 if (m_host.ParentGroup.RootPart.GroupID == client.ActiveGroupId)
6966 return new LSL_Integer(1);
6967
6316 return new LSL_Integer(0); 6968 return new LSL_Integer(0);
6969 }
6970
6971 return new LSL_Integer(0);
6317 } 6972 }
6318 6973
6319 public void llUnSit(string id) 6974 public void llUnSit(string id)
@@ -6441,6 +7096,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6441 return m_host.ParentGroup.AttachmentPoint; 7096 return m_host.ParentGroup.AttachmentPoint;
6442 } 7097 }
6443 7098
7099 public LSL_List llGetAttachedList(string id)
7100 {
7101 m_host.AddScriptLPS(1);
7102
7103 ScenePresence av = World.GetScenePresence((UUID)id);
7104
7105 if (av == null || av.IsDeleted)
7106 return new LSL_List("NOT_FOUND");
7107
7108 if (av.IsChildAgent || av.IsInTransit)
7109 return new LSL_List("NOT_ON_REGION");
7110
7111 LSL_List AttachmentsList = new LSL_List();
7112 List<SceneObjectGroup> Attachments;
7113
7114 Attachments = av.GetAttachments();
7115
7116 foreach (SceneObjectGroup Attachment in Attachments)
7117 {
7118 if(Attachment.HasPrivateAttachmentPoint)
7119 continue;
7120 AttachmentsList.Add(new LSL_Key(Attachment.UUID.ToString()));
7121 }
7122
7123 return AttachmentsList;
7124 }
7125
6444 public virtual LSL_Integer llGetFreeMemory() 7126 public virtual LSL_Integer llGetFreeMemory()
6445 { 7127 {
6446 m_host.AddScriptLPS(1); 7128 m_host.AddScriptLPS(1);
@@ -7127,6 +7809,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7127 7809
7128 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot) 7810 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot)
7129 { 7811 {
7812 // LSL quaternions can normalize to 0, normal Quaternions can't.
7813 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
7814 rot.s = 1; // ZERO_ROTATION = 0,0,0,1
7815
7130 part.SitTargetPosition = offset; 7816 part.SitTargetPosition = offset;
7131 part.SitTargetOrientation = rot; 7817 part.SitTargetOrientation = rot;
7132 part.ParentGroup.HasGroupChanged = true; 7818 part.ParentGroup.HasGroupChanged = true;
@@ -7166,11 +7852,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7166 { 7852 {
7167 m_host.AddScriptLPS(1); 7853 m_host.AddScriptLPS(1);
7168 if(linknum == ScriptBaseClass.LINK_SET || 7854 if(linknum == ScriptBaseClass.LINK_SET ||
7169 linknum == ScriptBaseClass.LINK_ALL_CHILDREN || 7855 linknum == ScriptBaseClass.LINK_ALL_CHILDREN ||
7170 linknum == ScriptBaseClass.LINK_ALL_OTHERS) return UUID.Zero.ToString(); 7856 linknum == ScriptBaseClass.LINK_ALL_OTHERS ||
7857 linknum == 0)
7858 return UUID.Zero.ToString();
7171 7859
7172 List<SceneObjectPart> parts = GetLinkParts(linknum); 7860 List<SceneObjectPart> parts = GetLinkParts(linknum);
7173 if (parts.Count == 0) return UUID.Zero.ToString(); 7861 if (parts.Count == 0)
7862 return UUID.Zero.ToString();
7174 return parts[0].SitTargetAvatar.ToString(); 7863 return parts[0].SitTargetAvatar.ToString();
7175 } 7864 }
7176 7865
@@ -7181,7 +7870,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7181 UUID key; 7870 UUID key;
7182 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 7871 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
7183 7872
7184 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) 7873 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManagePasses, false))
7185 { 7874 {
7186 int expires = 0; 7875 int expires = 0;
7187 if (hours != 0) 7876 if (hours != 0)
@@ -7214,6 +7903,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7214 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); 7903 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
7215 } 7904 }
7216 } 7905 }
7906 ScriptSleep(m_sleepMsOnAddToLandPassList);
7217 } 7907 }
7218 7908
7219 public void llSetTouchText(string text) 7909 public void llSetTouchText(string text)
@@ -7295,7 +7985,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7295 public LSL_Integer llScriptDanger(LSL_Vector pos) 7985 public LSL_Integer llScriptDanger(LSL_Vector pos)
7296 { 7986 {
7297 m_host.AddScriptLPS(1); 7987 m_host.AddScriptLPS(1);
7298 bool result = World.ScriptDanger(m_host.LocalId, pos); 7988 bool result = World.LSLScriptDanger(m_host, pos);
7299 if (result) 7989 if (result)
7300 { 7990 {
7301 return 1; 7991 return 1;
@@ -7304,7 +7994,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7304 { 7994 {
7305 return 0; 7995 return 0;
7306 } 7996 }
7307
7308 } 7997 }
7309 7998
7310 public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel) 7999 public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel)
@@ -7321,35 +8010,51 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7321 Error("llDialog", "First parameter must be a key"); 8010 Error("llDialog", "First parameter must be a key");
7322 return; 8011 return;
7323 } 8012 }
7324 if (buttons.Length < 1) 8013
8014 int length = buttons.Length;
8015 if (length < 1)
7325 { 8016 {
7326 Error("llDialog", "At least 1 button must be shown"); 8017 Error("llDialog", "At least 1 button must be shown");
7327 return; 8018 return;
7328 } 8019 }
7329 if (buttons.Length > 12) 8020 if (length > 12)
7330 { 8021 {
7331 Error("llDialog", "No more than 12 buttons can be shown"); 8022 Error("llDialog", "No more than 12 buttons can be shown");
7332 return; 8023 return;
7333 } 8024 }
7334 string[] buts = new string[buttons.Length]; 8025
7335 for (int i = 0; i < buttons.Length; i++) 8026 if (message == string.Empty)
8027 {
8028 Error("llDialog", "Empty message");
8029 }
8030 else if (Encoding.UTF8.GetByteCount(message) > 512)
8031 {
8032 Error("llDialog", "Message longer than 512 bytes");
8033 }
8034
8035 string[] buts = new string[length];
8036 for (int i = 0; i < length; i++)
7336 { 8037 {
7337 if (buttons.Data[i].ToString() == String.Empty) 8038 if (buttons.Data[i].ToString() == String.Empty)
7338 { 8039 {
7339 Error("llDialog", "Button label cannot be blank"); 8040 Error("llDialog", "Button label cannot be blank");
7340 return; 8041 return;
7341 } 8042 }
8043/*
7342 if (buttons.Data[i].ToString().Length > 24) 8044 if (buttons.Data[i].ToString().Length > 24)
7343 { 8045 {
7344 Error("llDialog", "Button label cannot be longer than 24 characters"); 8046 Error("llDialog", "Button label cannot be longer than 24 characters");
7345 return; 8047 return;
7346 } 8048 }
8049*/
7347 buts[i] = buttons.Data[i].ToString(); 8050 buts[i] = buttons.Data[i].ToString();
7348 } 8051 }
7349 8052
7350 dm.SendDialogToUser( 8053 dm.SendDialogToUser(
7351 av, m_host.Name, m_host.UUID, m_host.OwnerID, 8054 av, m_host.Name, m_host.UUID, m_host.OwnerID,
7352 message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); 8055 message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
8056
8057 ScriptSleep(m_sleepMsOnDialog);
7353 } 8058 }
7354 8059
7355 public void llVolumeDetect(int detect) 8060 public void llVolumeDetect(int detect)
@@ -7364,6 +8069,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7364 { 8069 {
7365 m_host.AddScriptLPS(1); 8070 m_host.AddScriptLPS(1);
7366 Deprecated("llRemoteLoadScript", "Use llRemoteLoadScriptPin instead"); 8071 Deprecated("llRemoteLoadScript", "Use llRemoteLoadScriptPin instead");
8072 ScriptSleep(m_sleepMsOnRemoteLoadScript);
7367 } 8073 }
7368 8074
7369 public void llSetRemoteScriptAccessPin(int pin) 8075 public void llSetRemoteScriptAccessPin(int pin)
@@ -7400,8 +8106,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7400 return; 8106 return;
7401 } 8107 }
7402 8108
7403 // the rest of the permission checks are done in RezScript, so check the pin there as well 8109 SceneObjectPart dest = World.GetSceneObjectPart(destId);
7404 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); 8110 if (dest != null)
8111 {
8112 if ((item.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
8113 {
8114 // the rest of the permission checks are done in RezScript, so check the pin there as well
8115 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
8116
8117 if ((item.BasePermissions & (uint)PermissionMask.Copy) == 0)
8118 m_host.Inventory.RemoveInventoryItem(item.ItemID);
8119 }
8120 }
8121 // this will cause the delay even if the script pin or permissions were wrong - seems ok
8122 ScriptSleep(m_sleepMsOnRemoteLoadScriptPin);
7405 } 8123 }
7406 8124
7407 public void llOpenRemoteDataChannel() 8125 public void llOpenRemoteDataChannel()
@@ -7432,12 +8150,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7432 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj, 8150 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj,
7433 new DetectParams[0])); 8151 new DetectParams[0]));
7434 } 8152 }
8153 ScriptSleep(m_sleepMsOnOpenRemoteDataChannel);
7435 } 8154 }
7436 8155
7437 public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata) 8156 public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata)
7438 { 8157 {
7439 m_host.AddScriptLPS(1); 8158 m_host.AddScriptLPS(1);
7440 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 8159 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
8160 ScriptSleep(m_sleepMsOnSendRemoteData);
7441 if (xmlrpcMod == null) 8161 if (xmlrpcMod == null)
7442 return ""; 8162 return "";
7443 return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString(); 8163 return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString();
@@ -7449,6 +8169,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7449 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 8169 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
7450 if (xmlrpcMod != null) 8170 if (xmlrpcMod != null)
7451 xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); 8171 xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
8172 ScriptSleep(m_sleepMsOnRemoteDataReply);
7452 } 8173 }
7453 8174
7454 public void llCloseRemoteDataChannel(string channel) 8175 public void llCloseRemoteDataChannel(string channel)
@@ -7464,24 +8185,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7464 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 8185 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
7465 if (xmlrpcMod != null) 8186 if (xmlrpcMod != null)
7466 xmlrpcMod.CloseXMLRPCChannel((UUID)channel); 8187 xmlrpcMod.CloseXMLRPCChannel((UUID)channel);
8188 ScriptSleep(m_sleepMsOnCloseRemoteDataChannel);
7467 } 8189 }
7468 8190
7469 public LSL_String llMD5String(string src, int nonce) 8191 public LSL_String llMD5String(string src, int nonce)
7470 { 8192 {
7471 m_host.AddScriptLPS(1); 8193 m_host.AddScriptLPS(1);
7472 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 8194 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
7473 } 8195 }
7474 8196
7475 public LSL_String llSHA1String(string src) 8197 public LSL_String llSHA1String(string src)
7476 { 8198 {
7477 m_host.AddScriptLPS(1); 8199 m_host.AddScriptLPS(1);
7478 return Util.SHA1Hash(src).ToLower(); 8200 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
7479 } 8201 }
7480 8202
7481 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 8203 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
7482 { 8204 {
7483 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 8205 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7484 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 8206 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
8207 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8208 return shapeBlock;
7485 8209
7486 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 8210 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
7487 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 8211 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -7586,6 +8310,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7586 // Prim type box, cylinder and prism. 8310 // Prim type box, cylinder and prism.
7587 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) 8311 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)
7588 { 8312 {
8313 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8314 return;
8315
7589 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 8316 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7590 ObjectShapePacket.ObjectDataBlock shapeBlock; 8317 ObjectShapePacket.ObjectDataBlock shapeBlock;
7591 8318
@@ -7639,6 +8366,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7639 // Prim type sphere. 8366 // Prim type sphere.
7640 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 8367 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
7641 { 8368 {
8369 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8370 return;
8371
7642 ObjectShapePacket.ObjectDataBlock shapeBlock; 8372 ObjectShapePacket.ObjectDataBlock shapeBlock;
7643 8373
7644 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 8374 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -7685,6 +8415,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7685 // Prim type torus, tube and ring. 8415 // Prim type torus, tube and ring.
7686 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) 8416 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)
7687 { 8417 {
8418 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8419 return;
8420
7688 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 8421 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7689 ObjectShapePacket.ObjectDataBlock shapeBlock; 8422 ObjectShapePacket.ObjectDataBlock shapeBlock;
7690 8423
@@ -7820,6 +8553,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7820 // Prim type sculpt. 8553 // Prim type sculpt.
7821 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 8554 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7822 { 8555 {
8556 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8557 return;
8558
7823 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 8559 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7824 UUID sculptId; 8560 UUID sculptId;
7825 8561
@@ -7842,7 +8578,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7842 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 8578 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7843 { 8579 {
7844 // default 8580 // default
7845 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 8581 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7846 } 8582 }
7847 8583
7848 part.Shape.SetSculptProperties((byte)type, sculptId); 8584 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7855,6 +8591,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7855 m_host.AddScriptLPS(1); 8591 m_host.AddScriptLPS(1);
7856 8592
7857 SetLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); 8593 SetLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams");
8594
8595 ScriptSleep(m_sleepMsOnSetPrimitiveParams);
7858 } 8596 }
7859 8597
7860 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 8598 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
@@ -7862,6 +8600,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7862 m_host.AddScriptLPS(1); 8600 m_host.AddScriptLPS(1);
7863 8601
7864 SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); 8602 SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
8603
8604 ScriptSleep(m_sleepMsOnSetLinkPrimitiveParams);
7865 } 8605 }
7866 8606
7867 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 8607 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
@@ -7871,9 +8611,51 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7871 SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); 8611 SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
7872 } 8612 }
7873 8613
7874 protected void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc) 8614 private void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
7875 { 8615 {
7876 SetEntityParams(GetLinkEntities(linknumber), rules, originFunc); 8616 List<object> parts = new List<object>();
8617 List<SceneObjectPart> prims = GetLinkParts(linknumber);
8618 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
8619 foreach (SceneObjectPart p in prims)
8620 parts.Add(p);
8621 foreach (ScenePresence p in avatars)
8622 parts.Add(p);
8623
8624 LSL_List remaining = new LSL_List();
8625 uint rulesParsed = 0;
8626
8627 if (parts.Count > 0)
8628 {
8629 foreach (object part in parts)
8630 {
8631 if (part is SceneObjectPart)
8632 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
8633 else
8634 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
8635 }
8636
8637 while (remaining.Length > 2)
8638 {
8639 linknumber = remaining.GetLSLIntegerItem(0);
8640 rules = remaining.GetSublist(1, -1);
8641 parts.Clear();
8642 prims = GetLinkParts(linknumber);
8643 avatars = GetLinkAvatars(linknumber);
8644 foreach (SceneObjectPart p in prims)
8645 parts.Add(p);
8646 foreach (ScenePresence p in avatars)
8647 parts.Add(p);
8648
8649 remaining = new LSL_List();
8650 foreach (object part in parts)
8651 {
8652 if (part is SceneObjectPart)
8653 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
8654 else
8655 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
8656 }
8657 }
8658 }
7877 } 8659 }
7878 8660
7879 protected void SetEntityParams(List<ISceneEntity> entities, LSL_List rules, string originFunc) 8661 protected void SetEntityParams(List<ISceneEntity> entities, LSL_List rules, string originFunc)
@@ -8052,11 +8834,81 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8052 } 8834 }
8053 } 8835 }
8054 8836
8837 public LSL_List llGetPhysicsMaterial()
8838 {
8839 LSL_List result = new LSL_List();
8840
8841 result.Add(new LSL_Float(m_host.GravityModifier));
8842 result.Add(new LSL_Float(m_host.Restitution));
8843 result.Add(new LSL_Float(m_host.Friction));
8844 result.Add(new LSL_Float(m_host.Density));
8845
8846 return result;
8847 }
8848
8849 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
8850 float material_density, float material_friction,
8851 float material_restitution, float material_gravity_modifier)
8852 {
8853 ExtraPhysicsData physdata = new ExtraPhysicsData();
8854 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
8855 physdata.Density = part.Density;
8856 physdata.Friction = part.Friction;
8857 physdata.Bounce = part.Restitution;
8858 physdata.GravitationModifier = part.GravityModifier;
8859
8860 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
8861 physdata.Density = material_density;
8862 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
8863 physdata.Friction = material_friction;
8864 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
8865 physdata.Bounce = material_restitution;
8866 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
8867 physdata.GravitationModifier = material_gravity_modifier;
8868
8869 part.UpdateExtraPhysics(physdata);
8870 }
8871
8872 public void llSetPhysicsMaterial(int material_bits,
8873 LSL_Float material_gravity_modifier, LSL_Float material_restitution,
8874 LSL_Float material_friction, LSL_Float material_density)
8875 {
8876 SetPhysicsMaterial(m_host, material_bits, (float)material_density, (float)material_friction, (float)material_restitution, (float)material_gravity_modifier);
8877 }
8878
8879 // vector up using libomv (c&p from sop )
8880 // vector up rotated by r
8881 private Vector3 Zrot(Quaternion r)
8882 {
8883 double x, y, z, m;
8884
8885 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
8886 if (Math.Abs(1.0 - m) > 0.000001)
8887 {
8888 m = 1.0 / Math.Sqrt(m);
8889 r.X *= (float)m;
8890 r.Y *= (float)m;
8891 r.Z *= (float)m;
8892 r.W *= (float)m;
8893 }
8894
8895 x = 2 * (r.X * r.Z + r.Y * r.W);
8896 y = 2 * (-r.X * r.W + r.Y * r.Z);
8897 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
8898
8899 return new Vector3((float)x, (float)y, (float)z);
8900 }
8901
8055 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) 8902 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
8056 { 8903 {
8904 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8905 return new LSL_List();
8906
8057 int idx = 0; 8907 int idx = 0;
8058 int idxStart = 0; 8908 int idxStart = 0;
8059 8909
8910 SceneObjectGroup parentgrp = part.ParentGroup;
8911
8060 bool positionChanged = false; 8912 bool positionChanged = false;
8061 LSL_Vector currentPosition = GetPartLocalPos(part); 8913 LSL_Vector currentPosition = GetPartLocalPos(part);
8062 8914
@@ -8092,8 +8944,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8092 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1)); 8944 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1));
8093 return new LSL_List(); 8945 return new LSL_List();
8094 } 8946 }
8947 if (part.IsRoot && !part.ParentGroup.IsAttachment)
8948 currentPosition = GetSetPosTarget(part, v, currentPosition, true);
8949 else
8950 currentPosition = GetSetPosTarget(part, v, currentPosition, false);
8095 positionChanged = true; 8951 positionChanged = true;
8096 currentPosition = GetSetPosTarget(part, v, currentPosition);
8097 8952
8098 break; 8953 break;
8099 case ScriptBaseClass.PRIM_SIZE: 8954 case ScriptBaseClass.PRIM_SIZE:
@@ -8118,7 +8973,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8118 return new LSL_List(); 8973 return new LSL_List();
8119 } 8974 }
8120 // try to let this work as in SL... 8975 // try to let this work as in SL...
8121 if (part.ParentID == 0) 8976 if (part.ParentID == 0 || (part.ParentGroup != null && part == part.ParentGroup.RootPart))
8122 { 8977 {
8123 // special case: If we are root, rotate complete SOG to new rotation 8978 // special case: If we are root, rotate complete SOG to new rotation
8124 SetRot(part, q); 8979 SetRot(part, q);
@@ -9119,7 +9974,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9119 9974
9120 break; 9975 break;
9121 9976
9122 case ScriptBaseClass.PRIM_TEMP_ON_REZ: 9977 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
9978 if (remain < 5)
9979 return new LSL_List();
9980
9981 int material_bits = rules.GetLSLIntegerItem(idx++);
9982 float material_density = (float)rules.GetLSLFloatItem(idx++);
9983 float material_friction = (float)rules.GetLSLFloatItem(idx++);
9984 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
9985 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
9986
9987 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
9988
9989 break;
9990
9991 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
9123 if (remain < 1) 9992 if (remain < 1)
9124 return new LSL_List(); 9993 return new LSL_List();
9125 string temp = rules.Data[idx++].ToString(); 9994 string temp = rules.Data[idx++].ToString();
@@ -9290,6 +10159,53 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9290 part.UpdateSlice((float)slice.x, (float)slice.y); 10159 part.UpdateSlice((float)slice.x, (float)slice.y);
9291 break; 10160 break;
9292 10161
10162 case ScriptBaseClass.PRIM_SIT_TARGET:
10163 if (remain < 3)
10164 return new LSL_List();
10165
10166 int active;
10167 try
10168 {
10169 active = rules.GetLSLIntegerItem(idx++);
10170 }
10171 catch(InvalidCastException)
10172 {
10173 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SIT_TARGET: arg #{1} - parameter 1 must be integer", rulesParsed, idx - idxStart - 1));
10174 return new LSL_List();
10175 }
10176 LSL_Vector offset;
10177 try
10178 {
10179 offset = rules.GetVector3Item(idx++);
10180 }
10181 catch(InvalidCastException)
10182 {
10183 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SIT_TARGET: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
10184 return new LSL_List();
10185 }
10186 LSL_Rotation sitrot;
10187 try
10188 {
10189 sitrot = rules.GetQuaternionItem(idx++);
10190 }
10191 catch(InvalidCastException)
10192 {
10193 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SIT_TARGET: arg #{1} - parameter 3 must be rotation", rulesParsed, idx - idxStart - 1));
10194 return new LSL_List();
10195 }
10196
10197 // not SL compatible since we don't have a independent flag to control active target but use the values of offset and rotation
10198 if(active == 1)
10199 {
10200 if(offset.x == 0 && offset.y == 0 && offset.z == 0 && sitrot.s == 1.0)
10201 offset.z = 1e-5f; // hack
10202 SitTarget(part,offset,sitrot);
10203 }
10204 else if(active == 0)
10205 SitTarget(part, Vector3.Zero , Quaternion.Identity);
10206
10207 break;
10208
9293 case ScriptBaseClass.PRIM_LINK_TARGET: 10209 case ScriptBaseClass.PRIM_LINK_TARGET:
9294 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 10210 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
9295 return new LSL_List(); 10211 return new LSL_List();
@@ -9313,14 +10229,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9313 if (part.ParentGroup.RootPart == part) 10229 if (part.ParentGroup.RootPart == part)
9314 { 10230 {
9315 SceneObjectGroup parent = part.ParentGroup; 10231 SceneObjectGroup parent = part.ParentGroup;
9316 parent.UpdateGroupPosition(currentPosition); 10232// Util.FireAndForget(delegate(object x) {
10233 parent.UpdateGroupPosition(currentPosition);
10234// });
9317 } 10235 }
9318 else 10236 else
9319 { 10237 {
9320 part.OffsetPosition = currentPosition; 10238 part.OffsetPosition = currentPosition;
9321 SceneObjectGroup parent = part.ParentGroup; 10239// SceneObjectGroup parent = part.ParentGroup;
9322 parent.HasGroupChanged = true; 10240// parent.HasGroupChanged = true;
9323 parent.ScheduleGroupForTerseUpdate(); 10241// parent.ScheduleGroupForTerseUpdate();
10242 part.ScheduleTerseUpdate();
9324 } 10243 }
9325 } 10244 }
9326 } 10245 }
@@ -9368,7 +10287,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9368 } 10287 }
9369 break; 10288 break;
9370 10289
9371 case ScriptBaseClass.PRIM_ROTATION: 10290 case ScriptBaseClass.PRIM_ROTATION:
9372 if (remain < 1) 10291 if (remain < 1)
9373 return new LSL_List(); 10292 return new LSL_List();
9374 10293
@@ -9387,7 +10306,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9387 SceneObjectPart parentPart = sp.ParentPart; 10306 SceneObjectPart parentPart = sp.ParentPart;
9388 10307
9389 if (parentPart != null) 10308 if (parentPart != null)
9390 sp.Rotation = m_host.GetWorldRotation() * inRot; 10309 sp.Rotation = m_host.GetWorldRotation() * inRot;
9391 10310
9392 break; 10311 break;
9393 10312
@@ -9431,7 +10350,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9431 catch (InvalidCastException e) 10350 catch (InvalidCastException e)
9432 { 10351 {
9433 Error( 10352 Error(
9434 originFunc, 10353 originFunc,
9435 string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message); 10354 string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message);
9436 } 10355 }
9437 10356
@@ -9472,9 +10391,104 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9472 10391
9473 public LSL_String llXorBase64Strings(string str1, string str2) 10392 public LSL_String llXorBase64Strings(string str1, string str2)
9474 { 10393 {
10394 int padding = 0;
10395
10396 string b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
10397
10398 ScriptSleep(300);
9475 m_host.AddScriptLPS(1); 10399 m_host.AddScriptLPS(1);
9476 Deprecated("llXorBase64Strings", "Use llXorBase64 instead"); 10400
9477 return String.Empty; 10401 if (str1 == String.Empty)
10402 return String.Empty;
10403 if (str2 == String.Empty)
10404 return str1;
10405
10406 int len = str2.Length;
10407 if ((len % 4) != 0) // LL is EVIL!!!!
10408 {
10409 while (str2.EndsWith("="))
10410 str2 = str2.Substring(0, str2.Length - 1);
10411
10412 len = str2.Length;
10413 int mod = len % 4;
10414
10415 if (mod == 1)
10416 str2 = str2.Substring(0, str2.Length - 1);
10417 else if (mod == 2)
10418 str2 += "==";
10419 else if (mod == 3)
10420 str2 += "=";
10421 }
10422
10423 byte[] data1;
10424 byte[] data2;
10425 try
10426 {
10427 data1 = Convert.FromBase64String(str1);
10428 data2 = Convert.FromBase64String(str2);
10429 }
10430 catch (Exception)
10431 {
10432 return new LSL_String(String.Empty);
10433 }
10434
10435 // For cases where the decoded length of s2 is greater
10436 // than the decoded length of s1, simply perform a normal
10437 // decode and XOR
10438 //
10439 /*
10440 if (data2.Length >= data1.Length)
10441 {
10442 for (int pos = 0 ; pos < data1.Length ; pos++ )
10443 data1[pos] ^= data2[pos];
10444
10445 return Convert.ToBase64String(data1);
10446 }
10447 */
10448
10449 // Remove padding
10450 while (str1.EndsWith("="))
10451 {
10452 str1 = str1.Substring(0, str1.Length - 1);
10453 padding++;
10454 }
10455 while (str2.EndsWith("="))
10456 str2 = str2.Substring(0, str2.Length - 1);
10457
10458 byte[] d1 = new byte[str1.Length];
10459 byte[] d2 = new byte[str2.Length];
10460
10461 for (int i = 0 ; i < str1.Length ; i++)
10462 {
10463 int idx = b64.IndexOf(str1.Substring(i, 1));
10464 if (idx == -1)
10465 idx = 0;
10466 d1[i] = (byte)idx;
10467 }
10468
10469 for (int i = 0 ; i < str2.Length ; i++)
10470 {
10471 int idx = b64.IndexOf(str2.Substring(i, 1));
10472 if (idx == -1)
10473 idx = 0;
10474 d2[i] = (byte)idx;
10475 }
10476
10477 string output = String.Empty;
10478
10479 for (int pos = 0 ; pos < d1.Length ; pos++)
10480 output += b64[d1[pos] ^ d2[pos % d2.Length]];
10481
10482 // Here's a funny thing: LL blithely violate the base64
10483 // standard pretty much everywhere. Here, padding is
10484 // added only if the first input string had it, rather
10485 // than when the data actually needs it. This can result
10486 // in invalid base64 being returned. Go figure.
10487
10488 while (padding-- > 0)
10489 output += "=";
10490
10491 return output;
9478 } 10492 }
9479 10493
9480 public void llRemoteDataSetRegion() 10494 public void llRemoteDataSetRegion()
@@ -9520,6 +10534,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9520 return; 10534 return;
9521 10535
9522 land.SetMusicUrl(url); 10536 land.SetMusicUrl(url);
10537
10538 ScriptSleep(m_sleepMsOnSetParcelMusicURL);
9523 } 10539 }
9524 10540
9525 public LSL_String llGetParcelMusicURL() 10541 public LSL_String llGetParcelMusicURL()
@@ -9615,188 +10631,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9615 public LSL_List llGetBoundingBox(string obj) 10631 public LSL_List llGetBoundingBox(string obj)
9616 { 10632 {
9617 m_host.AddScriptLPS(1); 10633 m_host.AddScriptLPS(1);
9618
9619 // Get target avatar if non-seated avatar or attachment, or prim and object
9620 UUID objID = UUID.Zero; 10634 UUID objID = UUID.Zero;
9621 UUID.TryParse(obj, out objID);
9622 ScenePresence agent = World.GetScenePresence(objID);
9623 if (agent != null)
9624 {
9625 if (agent.ParentPart != null)
9626 {
9627 objID = agent.ParentPart.UUID;
9628 agent = null;
9629 }
9630 }
9631 SceneObjectGroup group = null;
9632 SceneObjectPart target = World.GetSceneObjectPart(objID);
9633 if (target != null)
9634 {
9635 group = target.ParentGroup;
9636 if (group.IsAttachment) {
9637 objID = group.AttachedAvatar;
9638 agent = World.GetScenePresence(objID);
9639 group = null;
9640 target = null;
9641 }
9642 }
9643
9644 // Initialize but break if no target
9645 LSL_List result = new LSL_List(); 10635 LSL_List result = new LSL_List();
9646 int groupCount = 0; 10636
9647 int partCount = 0; 10637 // If the ID is not valid, return null result
9648 int vertexCount = 0; 10638 if (!UUID.TryParse(obj, out objID))
9649 if (target == null && agent == null)
9650 { 10639 {
9651 result.Add(new LSL_Vector()); 10640 result.Add(new LSL_Vector());
9652 result.Add(new LSL_Vector()); 10641 result.Add(new LSL_Vector());
9653 if (m_addStatsInGetBoundingBox)
9654 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
9655 return result; 10642 return result;
9656 } 10643 }
9657 Vector3 minPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
9658 Vector3 maxPosition = new Vector3(float.MinValue, float.MinValue, float.MinValue);
9659 10644
9660 // Try to get a mesher 10645 // Check if this is an attached prim. If so, replace
9661 IRendering primMesher = null; 10646 // the UUID with the avatar UUID and report it's bounding box
9662 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); 10647 SceneObjectPart part = World.GetSceneObjectPart(objID);
9663 if (renderers.Count > 0) 10648 if (part != null && part.ParentGroup.IsAttachment)
9664 primMesher = RenderingLoader.LoadRenderer(renderers[0]); 10649 objID = part.ParentGroup.AttachedAvatar;
9665 10650
9666 // Get bounding box of just avatar, seated or not 10651 // Find out if this is an avatar ID. If so, return it's box
9667 if (agent != null) 10652 ScenePresence presence = World.GetScenePresence(objID);
9668 { 10653 if (presence != null)
9669 bool hasParent = false;
9670 Vector3 lower;
9671 Vector3 upper;
9672 BoundingBoxOfScenePresence(agent, out lower, out upper);
9673 Vector3 offset = Vector3.Zero;
9674
9675 // Since local bounding box unrotated and untilted, keep it simple
9676 AddBoundingBoxOfSimpleBox(lower, upper, offset, agent.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9677 partCount++;
9678 groupCount++;
9679
9680 // Return lower and upper bounding box corners
9681 result.Add(new LSL_Vector(minPosition));
9682 result.Add(new LSL_Vector(maxPosition));
9683 if (m_addStatsInGetBoundingBox)
9684 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
9685 return result;
9686 }
9687 // Get bounding box of object including seated avatars
9688 else if (group != null)
9689 { 10654 {
9690 // Merge bounding boxes of all parts (prims and mesh) 10655 // As per LSL Wiki, there is no difference between sitting
9691 foreach (SceneObjectPart part in group.Parts) 10656 // and standing avatar since server 1.36
9692 { 10657 LSL_Vector lower;
9693 bool hasParent = (!part.IsRoot); 10658 LSL_Vector upper;
9694 // When requested or if no mesher, keep it simple
9695 if (m_useSimpleBoxesInGetBoundingBox || primMesher == null)
9696 {
9697 AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9698 }
9699 // Do the full mounty
9700 else
9701 {
9702 Primitive omvPrim = part.Shape.ToOmvPrimitive(part.OffsetPosition, part.RotationOffset);
9703 byte[] sculptAsset = null;
9704 if (omvPrim.Sculpt != null)
9705 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
9706
9707 // When part is mesh
9708 // Quirk: Only imports as incompletely populated faceted mesh object, so needs an own handler.
9709 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
9710 {
9711 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
9712 FacetedMesh mesh = null;
9713 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh);
9714 meshAsset = null;
9715 if (mesh != null)
9716 {
9717 AddBoundingBoxOfFacetedMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9718 mesh = null;
9719 }
9720 }
9721
9722 // When part is sculpt
9723 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
9724 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
9725 {
9726 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>();
9727 if (imgDecoder != null)
9728 {
9729 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
9730 if (sculpt != null)
9731 {
9732 SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium);
9733 sculpt.Dispose();
9734 if (mesh != null)
9735 {
9736 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9737 mesh = null;
9738 }
9739 }
9740 }
9741 }
9742 10659
9743 // When part is prim 10660 Vector3 box = presence.Appearance.AvatarBoxSize * 0.5f;
9744 else if (omvPrim.Sculpt == null)
9745 {
9746 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium);
9747 if (mesh != null)
9748 {
9749 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9750 mesh = null;
9751 }
9752 }
9753 10661
9754 // When all else fails, try fallback to simple box 10662 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID
9755 else 10663 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
9756 { 10664/*
9757 AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); 10665 {
9758 } 10666 // This is for ground sitting avatars
9759 } 10667 float height = presence.Appearance.AvatarHeight / 2.66666667f;
9760 partCount++; 10668 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
10669 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
10670 }
10671 else
10672 {
10673 // This is for standing/flying avatars
10674 float height = presence.Appearance.AvatarHeight / 2.0f;
10675 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
10676 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
9761 } 10677 }
9762 }
9763
9764 // Merge bounding boxes of seated avatars
9765 foreach (ScenePresence sp in group.GetSittingAvatars())
9766 {
9767 Vector3 lower;
9768 Vector3 upper;
9769 BoundingBoxOfScenePresence(sp, out lower, out upper);
9770 Vector3 offset = sp.OffsetPosition;
9771 10678
9772 bool hasParent = true; 10679 // Adjust to the documented error offsets (see LSL Wiki)
9773 // When requested or if no mesher, keep it simple 10680 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
9774 if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) 10681 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
10682*/
9775 { 10683 {
9776 AddBoundingBoxOfSimpleBox(lower, upper, offset, sp.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); 10684 // This is for ground sitting avatars TODO!
10685 lower = new LSL_Vector(-box.X - 0.1125, -box.Y, box.Z * -1.0f);
10686 upper = new LSL_Vector(box.X + 0.1125, box.Y, box.Z * -1.0f);
9777 } 10687 }
9778 // Do the full mounty
9779 else 10688 else
9780 { 10689 {
9781 // Prim shapes don't do center offsets, so add it here. 10690 // This is for standing/flying avatars
9782 offset = offset + (lower + upper) * 0.5f * sp.Rotation; 10691 lower = new LSL_Vector(-box.X, -box.Y, -box.Z);
9783 Primitive omvPrim = MakeOpenMetaversePrim(upper - lower, offset, sp.Rotation, ScriptBaseClass.PRIM_TYPE_SPHERE); 10692 upper = new LSL_Vector(box.X, box.Y, box.Z);
9784 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium);
9785 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9786 mesh = null;
9787 } 10693 }
9788 partCount++; 10694
10695 if (lower.x > upper.x)
10696 lower.x = upper.x;
10697 if (lower.y > upper.y)
10698 lower.y = upper.y;
10699 if (lower.z > upper.z)
10700 lower.z = upper.z;
10701
10702 result.Add(lower);
10703 result.Add(upper);
10704 return result;
9789 } 10705 }
9790 10706
9791 groupCount++; 10707 part = World.GetSceneObjectPart(objID);
10708 // Currently only works for single prims without a sitting avatar
10709 if (part != null)
10710 {
10711 float minX;
10712 float maxX;
10713 float minY;
10714 float maxY;
10715 float minZ;
10716 float maxZ;
9792 10717
9793 // Return lower and upper bounding box corners 10718 // This BBox is in sim coordinates, with the offset being
9794 result.Add(new LSL_Vector(minPosition)); 10719 // a contained point.
9795 result.Add(new LSL_Vector(maxPosition)); 10720 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
9796 if (m_addStatsInGetBoundingBox) 10721 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
9797 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); 10722
10723 minX -= offsets[0].X;
10724 maxX -= offsets[0].X;
10725 minY -= offsets[0].Y;
10726 maxY -= offsets[0].Y;
10727 minZ -= offsets[0].Z;
10728 maxZ -= offsets[0].Z;
10729
10730 LSL_Vector lower;
10731 LSL_Vector upper;
10732
10733 // Adjust to the documented error offsets (see LSL Wiki)
10734 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
10735 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
10736
10737 if (lower.x > upper.x)
10738 lower.x = upper.x;
10739 if (lower.y > upper.y)
10740 lower.y = upper.y;
10741 if (lower.z > upper.z)
10742 lower.z = upper.z;
10743
10744 result.Add(lower);
10745 result.Add(upper);
10746 return result;
10747 }
9798 10748
9799 primMesher = null; 10749 // Not found so return empty values
10750 result.Add(new LSL_Vector());
10751 result.Add(new LSL_Vector());
9800 return result; 10752 return result;
9801 } 10753 }
9802 10754
@@ -9836,430 +10788,80 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9836 } 10788 }
9837 } 10789 }
9838 10790
9839 /// <summary>
9840 /// Helper to approximate a part with a simple box.
9841 /// </summary>
9842 private void AddBoundingBoxOfSimpleBox(Vector3 corner1, Vector3 corner2, Vector3 offset, Quaternion rotation, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
9843 {
9844 // Parse the 8 box corners
9845 for (int i = 0; i < 8; i++)
9846 {
9847 // Calculate each box corner
9848 Vector3 position = corner1;
9849 if ((i & 1) != 0)
9850 position.X = corner2.X;
9851 if ((i & 2) != 0)
9852 position.Y = corner2.Y;
9853 if ((i & 4) != 0)
9854 position.Z = corner2.Z;
9855 // Rotate part unless part is root
9856 if (hasParent)
9857 position = position * rotation;
9858 position = position + offset;
9859 // Adjust lower and upper bounding box corners if needed
9860 lower = Vector3.Min(lower, position);
9861 upper = Vector3.Max(upper, position);
9862 count++;
9863 }
9864 }
9865 10791
9866 /// <summary>
9867 /// Helper to parse a meshed prim and needed especially
9868 /// for accuracy with tortured prims and sculpts.
9869 /// </summary>
9870 private void AddBoundingBoxOfSimpleMesh(SimpleMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
9871 {
9872 // Quirk: A meshed box contains 10 instead of the 8 necessary vertices.
9873 if (mesh != null)
9874 {
9875 // Parse each vertex in mesh
9876 foreach (Vertex vertex in mesh.Vertices)
9877 {
9878 Vector3 position = vertex.Position;
9879 position = position * prim.Scale;
9880 // Rotate part unless part is root
9881 if (hasParent)
9882 position = position * prim.Rotation;
9883 position = position + prim.Position;
9884 // Adjust lower and upper bounding box corners if needed
9885 lower = Vector3.Min(lower, position);
9886 upper = Vector3.Max(upper, position);
9887 count++;
9888 }
9889 }
9890 }
9891
9892 /// <summary>
9893 /// Helper to parse mesh because no method exists
9894 /// to parse mesh assets to SimpleMesh.
9895 /// </summary>
9896 private void AddBoundingBoxOfFacetedMesh(FacetedMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
9897 {
9898 if (mesh != null)
9899 {
9900 // Parse each face in mesh
9901 // since vertex array isn't populated.
9902 // This parses each unique vertex 3-6 times.
9903 foreach (Face face in mesh.Faces)
9904 {
9905 // Parse each vertex in face
9906 foreach (Vertex vertex in face.Vertices)
9907 {
9908 Vector3 position = vertex.Position;
9909 position = position * prim.Scale;
9910 // Rotate part unless part is root
9911 if (hasParent)
9912 position = position * prim.Rotation;
9913 position = position + prim.Position;
9914 // Adjust lower and upper bounding box corners if needed
9915 lower = Vector3.Min(lower, position);
9916 upper = Vector3.Max(upper, position);
9917 count++;
9918 }
9919 }
9920 }
9921 }
9922
9923 /// <summary>
9924 /// Helper to make up an OpenMetaverse prim
9925 /// needed to create mesh from parts.
9926 /// </summary>
9927 private Primitive MakeOpenMetaversePrim(Vector3 scale, Vector3 position, Quaternion rotation, int primType)
9928 {
9929 // Initialize and set common parameters
9930 Primitive prim = new OpenMetaverse.Primitive();
9931 prim.Scale = scale;
9932 prim.Position = position;
9933 prim.Rotation = rotation;
9934 prim.PrimData.PathShearX = 0.0f;
9935 prim.PrimData.PathShearY = 0.0f;
9936 prim.PrimData.PathBegin = 0.0f;
9937 prim.PrimData.PathEnd = 1.0f;
9938 prim.PrimData.PathScaleX = 1.0f;
9939 prim.PrimData.PathScaleY = 1.0f;
9940 prim.PrimData.PathTaperX = 0.0f;
9941 prim.PrimData.PathTaperY = 0.0f;
9942 prim.PrimData.PathTwistBegin = 0.0f;
9943 prim.PrimData.PathTwist = 0.0f;
9944 prim.PrimData.ProfileBegin = 0.0f;
9945 prim.PrimData.ProfileEnd = 1.0f;
9946 prim.PrimData.ProfileHollow = 0.0f;
9947 prim.PrimData.ProfileCurve = (ProfileCurve)1;
9948 prim.PrimData.ProfileHole = (HoleType)0;
9949 prim.PrimData.PathCurve = (PathCurve)16;
9950 prim.PrimData.PathRadiusOffset = 0.0f;
9951 prim.PrimData.PathRevolutions = 1.0f;
9952 prim.PrimData.PathSkew = 0.0f;
9953 prim.PrimData.PCode = OpenMetaverse.PCode.Prim;
9954 prim.PrimData.State = (byte)0;
9955
9956 // Set type specific parameters
9957 switch (primType)
9958 {
9959 // Set specific parameters for box
9960 case ScriptBaseClass.PRIM_TYPE_BOX:
9961 prim.PrimData.PathScaleY = 1.0f;
9962 prim.PrimData.ProfileCurve = (ProfileCurve)1;
9963 prim.PrimData.PathCurve = (PathCurve)16;
9964 break;
9965 // Set specific parameters for cylinder
9966 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
9967 prim.PrimData.PathScaleY = 1.0f;
9968 prim.PrimData.ProfileCurve = (ProfileCurve)0;
9969 prim.PrimData.PathCurve = (PathCurve)16;
9970 break;
9971 // Set specific parameters for prism
9972 case ScriptBaseClass.PRIM_TYPE_PRISM:
9973 prim.PrimData.PathScaleY = 1.0f;
9974 prim.PrimData.ProfileCurve = (ProfileCurve)3;
9975 prim.PrimData.PathCurve = (PathCurve)16;
9976 break;
9977 // Set specific parameters for sphere
9978 case ScriptBaseClass.PRIM_TYPE_SPHERE:
9979 prim.PrimData.PathScaleY = 1.0f;
9980 prim.PrimData.ProfileCurve = (ProfileCurve)5;
9981 prim.PrimData.PathCurve = (PathCurve)32;
9982 break;
9983 // Set specific parameters for torus
9984 case ScriptBaseClass.PRIM_TYPE_TORUS:
9985 prim.PrimData.PathScaleY = 0.5f;
9986 prim.PrimData.ProfileCurve = (ProfileCurve)0;
9987 prim.PrimData.PathCurve = (PathCurve)32;
9988 break;
9989 // Set specific parameters for tube
9990 case ScriptBaseClass.PRIM_TYPE_TUBE:
9991 prim.PrimData.PathScaleY = 0.5f;
9992 prim.PrimData.ProfileCurve = (ProfileCurve)1;
9993 prim.PrimData.PathCurve = (PathCurve)32;
9994 break;
9995 // Set specific parameters for ring
9996 case ScriptBaseClass.PRIM_TYPE_RING:
9997 prim.PrimData.PathScaleY = 0.5f;
9998 prim.PrimData.ProfileCurve = (ProfileCurve)3;
9999 prim.PrimData.PathCurve = (PathCurve)32;
10000 break;
10001 // Set specific parameters for sculpt
10002 case ScriptBaseClass.PRIM_TYPE_SCULPT:
10003 prim.PrimData.PathScaleY = 1.0f;
10004 prim.PrimData.ProfileCurve = (ProfileCurve)5;
10005 prim.PrimData.PathCurve = (PathCurve)32;
10006 break;
10007 // Default to specific parameters for box
10008 default:
10009 prim.PrimData.PathScaleY = 1.0f;
10010 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10011 prim.PrimData.PathCurve = (PathCurve)16;
10012 break;
10013 }
10014
10015 return prim;
10016 }
10017
10018 /// <summary>
10019 /// Implementation of llGetGeometricCenter according to SL 2015-04-30.
10020 /// http://wiki.secondlife.com/wiki/LlGetGeometricCenter
10021 /// Returns the average position offset of all linked parts,
10022 /// including the root prim and seated avatars,
10023 /// relative to the root prim in local coordinates.
10024 /// </summary>
10025 public LSL_Vector llGetGeometricCenter() 10792 public LSL_Vector llGetGeometricCenter()
10026 { 10793 {
10027 // Subtract whatever position the root prim has to make it zero 10794 return new LSL_Vector(m_host.GetGeometricCenter());
10028 Vector3 offset = m_host.ParentGroup.RootPart.OffsetPosition * -1.0f;
10029
10030 // Add all prim/part position offsets
10031 foreach (SceneObjectPart part in m_host.ParentGroup.Parts)
10032 offset = offset + part.OffsetPosition;
10033 // Add all avatar/scene presence position offsets
10034 foreach (ScenePresence sp in m_host.ParentGroup.GetSittingAvatars())
10035 offset = offset + sp.OffsetPosition;
10036
10037 // Calculate and return the average offset
10038 offset = offset / (float)(m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount());
10039 return new LSL_Vector(offset);
10040 } 10795 }
10041 10796
10042 public LSL_List GetEntityParams(ISceneEntity entity, LSL_List rules) 10797 public LSL_List llGetPrimitiveParams(LSL_List rules)
10043 { 10798 {
10044 LSL_List result = new LSL_List(); 10799 m_host.AddScriptLPS(1);
10045 LSL_List remaining;
10046
10047 while (true)
10048 {
10049// m_log.DebugFormat(
10050// "[LSL API]: GetEntityParams has {0} rules with scene entity named {1}",
10051// rules.Length, entity != null ? entity.Name : "NULL");
10052
10053 if (entity == null)
10054 return result;
10055 10800
10056 if (entity is SceneObjectPart) 10801 LSL_List result = new LSL_List();
10057 remaining = GetPrimParams((SceneObjectPart)entity, rules, ref result);
10058 else
10059 remaining = GetAgentParams((ScenePresence)entity, rules, ref result);
10060 10802
10061 if (remaining == null || remaining.Length < 2) 10803 LSL_List remaining = GetPrimParams(m_host, rules, ref result);
10062 return result;
10063 10804
10805 while ((object)remaining != null && remaining.Length > 2)
10806 {
10064 int linknumber = remaining.GetLSLIntegerItem(0); 10807 int linknumber = remaining.GetLSLIntegerItem(0);
10065 rules = remaining.GetSublist(1, -1); 10808 rules = remaining.GetSublist(1, -1);
10066 entity = GetLinkEntity(m_host, linknumber); 10809 List<SceneObjectPart> parts = GetLinkParts(linknumber);
10067 }
10068 }
10069 10810
10070 public LSL_List llGetPrimitiveParams(LSL_List rules) 10811 foreach (SceneObjectPart part in parts)
10071 { 10812 remaining = GetPrimParams(part, rules, ref result);
10072 m_host.AddScriptLPS(1); 10813 }
10073 10814
10074 return GetEntityParams(m_host, rules); 10815 return result;
10075 } 10816 }
10076 10817
10077 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) 10818 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
10078 { 10819 {
10079 m_host.AddScriptLPS(1); 10820 m_host.AddScriptLPS(1);
10080 10821
10081 return GetEntityParams(GetLinkEntity(m_host, linknumber), rules); 10822 // acording to SL wiki this must indicate a single link number or link_root or link_this.
10082 } 10823 // keep other options as before
10083 10824
10084 public LSL_Vector GetAgentSize(ScenePresence sp) 10825 List<SceneObjectPart> parts;
10085 { 10826 List<ScenePresence> avatars;
10086 return new LSL_Vector(0.45, 0.6, sp.Appearance.AvatarHeight);
10087 }
10088 10827
10089 /// <summary> 10828 LSL_List res = new LSL_List();
10090 /// Gets params for a seated avatar in a linkset. 10829 LSL_List remaining = new LSL_List();
10091 /// </summary> 10830
10092 /// <returns></returns> 10831 while (rules.Length > 0)
10093 /// <param name='sp'></param>
10094 /// <param name='rules'></param>
10095 /// <param name='res'></param>
10096 public LSL_List GetAgentParams(ScenePresence sp, LSL_List rules, ref LSL_List res)
10097 {
10098 int idx = 0;
10099 while (idx < rules.Length)
10100 { 10832 {
10101 int code = (int)rules.GetLSLIntegerItem(idx++); 10833 parts = GetLinkParts(linknumber);
10102 int remain = rules.Length-idx; 10834 avatars = GetLinkAvatars(linknumber);
10103 10835
10104 switch (code) 10836 remaining = new LSL_List();
10837 foreach (SceneObjectPart part in parts)
10105 { 10838 {
10106 case (int)ScriptBaseClass.PRIM_MATERIAL: 10839 remaining = GetPrimParams(part, rules, ref res);
10107 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MATERIAL_FLESH)); 10840 }
10108 break; 10841 foreach (ScenePresence avatar in avatars)
10109 10842 {
10110 case (int)ScriptBaseClass.PRIM_PHYSICS: 10843 remaining = GetPrimParams(avatar, rules, ref res);
10111 res.Add(ScriptBaseClass.FALSE); 10844 }
10112 break;
10113
10114 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
10115 res.Add(ScriptBaseClass.FALSE);
10116 break;
10117
10118 case (int)ScriptBaseClass.PRIM_PHANTOM:
10119 res.Add(ScriptBaseClass.FALSE);
10120 break;
10121
10122 case (int)ScriptBaseClass.PRIM_POSITION:
10123 res.Add(new LSL_Vector(sp.AbsolutePosition));
10124 break;
10125
10126 case (int)ScriptBaseClass.PRIM_SIZE:
10127 res.Add(GetAgentSize(sp));
10128 break;
10129
10130 case (int)ScriptBaseClass.PRIM_ROTATION:
10131 res.Add(sp.GetWorldRotation());
10132 break;
10133
10134 case (int)ScriptBaseClass.PRIM_TYPE:
10135 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
10136 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
10137 res.Add(new LSL_Vector(0, 1, 0));
10138 res.Add(new LSL_Float(0));
10139 res.Add(new LSL_Vector(0, 0, 0));
10140 res.Add(new LSL_Vector(1, 1, 0));
10141 res.Add(new LSL_Vector(0, 0, 0));
10142 break;
10143
10144 case (int)ScriptBaseClass.PRIM_TEXTURE:
10145 if (remain < 1)
10146 return new LSL_List();
10147
10148 int face = (int)rules.GetLSLIntegerItem(idx++);
10149 if (face > 21)
10150 break;
10151
10152 res.Add(new LSL_String(""));
10153 res.Add(ScriptBaseClass.ZERO_VECTOR);
10154 res.Add(ScriptBaseClass.ZERO_VECTOR);
10155 res.Add(new LSL_Float(0));
10156 break;
10157
10158 case (int)ScriptBaseClass.PRIM_COLOR:
10159 if (remain < 1)
10160 return new LSL_List();
10161
10162 face = (int)rules.GetLSLIntegerItem(idx++);
10163 if (face > 21)
10164 break;
10165
10166 res.Add(ScriptBaseClass.ZERO_VECTOR);
10167 res.Add(new LSL_Float(0));
10168 break;
10169
10170 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
10171 if (remain < 1)
10172 return new LSL_List();
10173
10174 face = (int)rules.GetLSLIntegerItem(idx++);
10175 if (face > 21)
10176 break;
10177
10178 res.Add(ScriptBaseClass.PRIM_SHINY_NONE);
10179 res.Add(ScriptBaseClass.PRIM_BUMP_NONE);
10180 break;
10181
10182 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
10183 if (remain < 1)
10184 return new LSL_List();
10185
10186 face = (int)rules.GetLSLIntegerItem(idx++);
10187 if (face > 21)
10188 break;
10189
10190 res.Add(ScriptBaseClass.FALSE);
10191 break;
10192
10193 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
10194 res.Add(ScriptBaseClass.FALSE);
10195 res.Add(new LSL_Integer(0));
10196 res.Add(new LSL_Float(0));
10197 res.Add(new LSL_Float(0));
10198 res.Add(new LSL_Float(0));
10199 res.Add(new LSL_Float(0));
10200 res.Add(ScriptBaseClass.ZERO_VECTOR);
10201 break;
10202
10203 case (int)ScriptBaseClass.PRIM_TEXGEN:
10204 if (remain < 1)
10205 return new LSL_List();
10206
10207 face = (int)rules.GetLSLIntegerItem(idx++);
10208 if (face > 21)
10209 break;
10210
10211 res.Add(ScriptBaseClass.PRIM_TEXGEN_DEFAULT);
10212 break;
10213
10214 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
10215 res.Add(ScriptBaseClass.FALSE);
10216 res.Add(ScriptBaseClass.ZERO_VECTOR);
10217 res.Add(ScriptBaseClass.ZERO_VECTOR);
10218 break;
10219
10220 case (int)ScriptBaseClass.PRIM_GLOW:
10221 if (remain < 1)
10222 return new LSL_List();
10223
10224 face = (int)rules.GetLSLIntegerItem(idx++);
10225 if (face > 21)
10226 break;
10227
10228 res.Add(new LSL_Float(0));
10229 break;
10230
10231 case (int)ScriptBaseClass.PRIM_TEXT:
10232 res.Add(new LSL_String(""));
10233 res.Add(ScriptBaseClass.ZERO_VECTOR);
10234 res.Add(new LSL_Float(1));
10235 break;
10236
10237 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
10238 res.Add(new LSL_Rotation(sp.Rotation));
10239 break;
10240
10241 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
10242 res.Add(new LSL_Vector(sp.OffsetPosition));
10243 break;
10244
10245 case (int)ScriptBaseClass.PRIM_SLICE:
10246 res.Add(new LSL_Vector(0, 1, 0));
10247 break;
10248
10249 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
10250 if(remain < 3)
10251 return new LSL_List();
10252 10845
10253 return rules.GetSublist(idx, -1); 10846 if (remaining.Length > 0)
10847 {
10848 linknumber = remaining.GetLSLIntegerItem(0);
10849 rules = remaining.GetSublist(1, -1);
10254 } 10850 }
10851 else
10852 break;
10255 } 10853 }
10256 10854
10257 return new LSL_List(); 10855 return res;
10258 } 10856 }
10259 10857
10260 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) 10858 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res)
10261 { 10859 {
10262 int idx = 0; 10860 int idx = 0;
10861 int face;
10862 Primitive.TextureEntry tex;
10863 int nsides = GetNumberOfSides(part);
10864
10263 while (idx < rules.Length) 10865 while (idx < rules.Length)
10264 { 10866 {
10265 int code = (int)rules.GetLSLIntegerItem(idx++); 10867 int code = (int)rules.GetLSLIntegerItem(idx++);
@@ -10293,19 +10895,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10293 break; 10895 break;
10294 10896
10295 case (int)ScriptBaseClass.PRIM_POSITION: 10897 case (int)ScriptBaseClass.PRIM_POSITION:
10296 LSL_Vector v = new LSL_Vector(part.AbsolutePosition); 10898 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
10297 10899 part.AbsolutePosition.Y,
10298 // For some reason, the part.AbsolutePosition.* values do not change if the 10900 part.AbsolutePosition.Z);
10299 // linkset is rotated; they always reflect the child prim's world position
10300 // as though the linkset is unrotated. This is incompatible behavior with SL's
10301 // implementation, so will break scripts imported from there (not to mention it
10302 // makes it more difficult to determine a child prim's actual inworld position).
10303 if (!part.IsRoot)
10304 {
10305 LSL_Vector rootPos = new LSL_Vector(m_host.ParentGroup.AbsolutePosition);
10306 v = ((v - rootPos) * llGetRootRotation()) + rootPos;
10307 }
10308
10309 res.Add(v); 10901 res.Add(v);
10310 break; 10902 break;
10311 10903
@@ -10410,11 +11002,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10410 if (remain < 1) 11002 if (remain < 1)
10411 return new LSL_List(); 11003 return new LSL_List();
10412 11004
10413 int face = (int)rules.GetLSLIntegerItem(idx++); 11005 face = (int)rules.GetLSLIntegerItem(idx++);
10414 Primitive.TextureEntry tex = part.Shape.Textures; 11006 tex = part.Shape.Textures;
11007
10415 if (face == ScriptBaseClass.ALL_SIDES) 11008 if (face == ScriptBaseClass.ALL_SIDES)
10416 { 11009 {
10417 for (face = 0 ; face < GetNumberOfSides(part); face++) 11010 for (face = 0; face < nsides; face++)
10418 { 11011 {
10419 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 11012 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10420 11013
@@ -10430,7 +11023,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10430 } 11023 }
10431 else 11024 else
10432 { 11025 {
10433 if (face >= 0 && face < GetNumberOfSides(part)) 11026 if (face >= 0 && face < nsides)
10434 { 11027 {
10435 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 11028 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10436 11029
@@ -10450,13 +11043,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10450 if (remain < 1) 11043 if (remain < 1)
10451 return new LSL_List(); 11044 return new LSL_List();
10452 11045
10453 face=(int)rules.GetLSLIntegerItem(idx++); 11046 face = (int)rules.GetLSLIntegerItem(idx++);
10454
10455 tex = part.Shape.Textures; 11047 tex = part.Shape.Textures;
10456 Color4 texcolor; 11048 Color4 texcolor;
11049
10457 if (face == ScriptBaseClass.ALL_SIDES) 11050 if (face == ScriptBaseClass.ALL_SIDES)
10458 { 11051 {
10459 for (face = 0 ; face < GetNumberOfSides(part); face++) 11052 for (face = 0; face < nsides; face++)
10460 { 11053 {
10461 texcolor = tex.GetFace((uint)face).RGBA; 11054 texcolor = tex.GetFace((uint)face).RGBA;
10462 res.Add(new LSL_Vector(texcolor.R, 11055 res.Add(new LSL_Vector(texcolor.R,
@@ -10476,61 +11069,100 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10476 break; 11069 break;
10477 11070
10478 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 11071 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
11072 {
10479 if (remain < 1) 11073 if (remain < 1)
10480 return new LSL_List(); 11074 return new LSL_List();
10481 11075
10482 face=(int)rules.GetLSLIntegerItem(idx++); 11076 face = (int)rules.GetLSLIntegerItem(idx++);
10483
10484 tex = part.Shape.Textures; 11077 tex = part.Shape.Textures;
11078 int shiny;
10485 if (face == ScriptBaseClass.ALL_SIDES) 11079 if (face == ScriptBaseClass.ALL_SIDES)
10486 { 11080 {
10487 for (face = 0; face < GetNumberOfSides(part); face++) 11081 for (face = 0; face < nsides; face++)
10488 { 11082 {
10489 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 11083 Shininess shinyness = tex.GetFace((uint)face).Shiny;
10490 // Convert Shininess to PRIM_SHINY_* 11084 if (shinyness == Shininess.High)
10491 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 11085 {
10492 // PRIM_BUMP_* 11086 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
10493 res.Add(new LSL_Integer((int)texface.Bump)); 11087 }
11088 else if (shinyness == Shininess.Medium)
11089 {
11090 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
11091 }
11092 else if (shinyness == Shininess.Low)
11093 {
11094 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
11095 }
11096 else
11097 {
11098 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
11099 }
11100 res.Add(new LSL_Integer(shiny));
11101 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
10494 } 11102 }
10495 } 11103 }
10496 else 11104 else
10497 { 11105 {
10498 if (face >= 0 && face < GetNumberOfSides(part)) 11106 Shininess shinyness = tex.GetFace((uint)face).Shiny;
11107 if (shinyness == Shininess.High)
10499 { 11108 {
10500 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 11109 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
10501 // Convert Shininess to PRIM_SHINY_* 11110 }
10502 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 11111 else if (shinyness == Shininess.Medium)
10503 // PRIM_BUMP_* 11112 {
10504 res.Add(new LSL_Integer((int)texface.Bump)); 11113 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
11114 }
11115 else if (shinyness == Shininess.Low)
11116 {
11117 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
11118 }
11119 else
11120 {
11121 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
10505 } 11122 }
11123 res.Add(new LSL_Integer(shiny));
11124 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
10506 } 11125 }
10507 break; 11126 break;
10508 11127 }
10509 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 11128 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
11129 {
10510 if (remain < 1) 11130 if (remain < 1)
10511 return new LSL_List(); 11131 return new LSL_List();
10512 11132
10513 face = (int)rules.GetLSLIntegerItem(idx++); 11133 face = (int)rules.GetLSLIntegerItem(idx++);
10514 11134
10515 tex = part.Shape.Textures; 11135 tex = part.Shape.Textures;
11136 int fullbright;
10516 if (face == ScriptBaseClass.ALL_SIDES) 11137 if (face == ScriptBaseClass.ALL_SIDES)
10517 { 11138 {
10518 for (face = 0; face < GetNumberOfSides(part); face++) 11139 for (face = 0; face < nsides; face++)
10519 { 11140 {
10520 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 11141 if (tex.GetFace((uint)face).Fullbright == true)
10521 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 11142 {
11143 fullbright = ScriptBaseClass.TRUE;
11144 }
11145 else
11146 {
11147 fullbright = ScriptBaseClass.FALSE;
11148 }
11149 res.Add(new LSL_Integer(fullbright));
10522 } 11150 }
10523 } 11151 }
10524 else 11152 else
10525 { 11153 {
10526 if (face >= 0 && face < GetNumberOfSides(part)) 11154 if (tex.GetFace((uint)face).Fullbright == true)
10527 { 11155 {
10528 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 11156 fullbright = ScriptBaseClass.TRUE;
10529 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
10530 } 11157 }
11158 else
11159 {
11160 fullbright = ScriptBaseClass.FALSE;
11161 }
11162 res.Add(new LSL_Integer(fullbright));
10531 } 11163 }
10532 break; 11164 break;
10533 11165 }
10534 case (int)ScriptBaseClass.PRIM_FLEXIBLE: 11166 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
10535 PrimitiveBaseShape shape = part.Shape; 11167 PrimitiveBaseShape shape = part.Shape;
10536 11168
@@ -10549,27 +11181,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10549 break; 11181 break;
10550 11182
10551 case (int)ScriptBaseClass.PRIM_TEXGEN: 11183 case (int)ScriptBaseClass.PRIM_TEXGEN:
11184 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
10552 if (remain < 1) 11185 if (remain < 1)
10553 return new LSL_List(); 11186 return new LSL_List();
10554 11187
10555 face=(int)rules.GetLSLIntegerItem(idx++); 11188 face = (int)rules.GetLSLIntegerItem(idx++);
10556 11189
10557 tex = part.Shape.Textures; 11190 tex = part.Shape.Textures;
10558 if (face == ScriptBaseClass.ALL_SIDES) 11191 if (face == ScriptBaseClass.ALL_SIDES)
10559 { 11192 {
10560 for (face = 0; face < GetNumberOfSides(part); face++) 11193 for (face = 0; face < nsides; face++)
10561 { 11194 {
10562 MappingType texgen = tex.GetFace((uint)face).TexMapType; 11195 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
10563 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 11196 {
10564 res.Add(new LSL_Integer((uint)texgen >> 1)); 11197 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
11198 }
11199 else
11200 {
11201 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
11202 }
10565 } 11203 }
10566 } 11204 }
10567 else 11205 else
10568 { 11206 {
10569 if (face >= 0 && face < GetNumberOfSides(part)) 11207 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
11208 {
11209 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
11210 }
11211 else
10570 { 11212 {
10571 MappingType texgen = tex.GetFace((uint)face).TexMapType; 11213 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
10572 res.Add(new LSL_Integer((uint)texgen >> 1));
10573 } 11214 }
10574 } 11215 }
10575 break; 11216 break;
@@ -10593,24 +11234,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10593 if (remain < 1) 11234 if (remain < 1)
10594 return new LSL_List(); 11235 return new LSL_List();
10595 11236
10596 face=(int)rules.GetLSLIntegerItem(idx++); 11237 face = (int)rules.GetLSLIntegerItem(idx++);
10597 11238
10598 tex = part.Shape.Textures; 11239 tex = part.Shape.Textures;
11240 float primglow;
10599 if (face == ScriptBaseClass.ALL_SIDES) 11241 if (face == ScriptBaseClass.ALL_SIDES)
10600 { 11242 {
10601 for (face = 0; face < GetNumberOfSides(part); face++) 11243 for (face = 0; face < nsides; face++)
10602 { 11244 {
10603 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 11245 primglow = tex.GetFace((uint)face).Glow;
10604 res.Add(new LSL_Float(texface.Glow)); 11246 res.Add(new LSL_Float(primglow));
10605 } 11247 }
10606 } 11248 }
10607 else 11249 else
10608 { 11250 {
10609 if (face >= 0 && face < GetNumberOfSides(part)) 11251 primglow = tex.GetFace((uint)face).Glow;
10610 { 11252 res.Add(new LSL_Float(primglow));
10611 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10612 res.Add(new LSL_Float(texface.Glow));
10613 }
10614 } 11253 }
10615 break; 11254 break;
10616 11255
@@ -10620,17 +11259,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10620 res.Add(new LSL_Vector(textColor.R, 11259 res.Add(new LSL_Vector(textColor.R,
10621 textColor.G, 11260 textColor.G,
10622 textColor.B)); 11261 textColor.B));
10623 res.Add(new LSL_Float(1.0 - textColor.A)); 11262 res.Add(new LSL_Float(textColor.A));
10624 break; 11263 break;
11264
10625 case (int)ScriptBaseClass.PRIM_NAME: 11265 case (int)ScriptBaseClass.PRIM_NAME:
10626 res.Add(new LSL_String(part.Name)); 11266 res.Add(new LSL_String(part.Name));
10627 break; 11267 break;
11268
10628 case (int)ScriptBaseClass.PRIM_DESC: 11269 case (int)ScriptBaseClass.PRIM_DESC:
10629 res.Add(new LSL_String(part.Description)); 11270 res.Add(new LSL_String(part.Description));
10630 break; 11271 break;
10631 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 11272 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
10632 res.Add(new LSL_Rotation(part.RotationOffset)); 11273 res.Add(new LSL_Rotation(part.RotationOffset));
10633 break; 11274 break;
11275
10634 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 11276 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
10635 res.Add(new LSL_Vector(GetPartLocalPos(part))); 11277 res.Add(new LSL_Vector(GetPartLocalPos(part)));
10636 break; 11278 break;
@@ -10643,6 +11285,71 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10643 0 11285 0
10644 )); 11286 ));
10645 break; 11287 break;
11288
11289 case (int)ScriptBaseClass.PRIM_OMEGA:
11290 // this may return values diferent from SL since we don't handle set the same way
11291 float gain = 1.0f; // we don't use gain and don't store it
11292 Vector3 axis = part.AngularVelocity;
11293 float spin = axis.Length();
11294 if(spin < 1.0e-6)
11295 {
11296 axis = Vector3.Zero;
11297 gain = 0.0f;
11298 spin = 0.0f;
11299 }
11300 else
11301 {
11302 axis = axis * (1.0f/spin);
11303 }
11304
11305 res.Add(new LSL_Vector(axis.X,
11306 axis.Y,
11307 axis.Z));
11308 res.Add(new LSL_Float(spin));
11309 res.Add(new LSL_Float(gain));
11310 break;
11311
11312 case (int)ScriptBaseClass.PRIM_SIT_TARGET:
11313 if(part.IsSitTargetSet)
11314 {
11315 res.Add(new LSL_Integer(1));
11316 res.Add(new LSL_Vector(part.SitTargetPosition));
11317 res.Add(new LSL_Rotation(part.SitTargetOrientation));
11318 }
11319 else
11320 {
11321 res.Add(new LSL_Integer(0));
11322 res.Add(new LSL_Vector(Vector3.Zero));
11323 res.Add(new LSL_Rotation(Quaternion.Identity));
11324 }
11325 break;
11326
11327 case (int)ScriptBaseClass.PRIM_NORMAL:
11328 case (int)ScriptBaseClass.PRIM_SPECULAR:
11329 case (int)ScriptBaseClass.PRIM_ALPHA_MODE:
11330 if (remain < 1)
11331 return new LSL_List();
11332
11333 face = (int)rules.GetLSLIntegerItem(idx++);
11334 tex = part.Shape.Textures;
11335 if (face == ScriptBaseClass.ALL_SIDES)
11336 {
11337 for (face = 0; face < nsides; face++)
11338 {
11339 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
11340 getLSLFaceMaterial(ref res, code, part, texface);
11341 }
11342 }
11343 else
11344 {
11345 if (face >= 0 && face < nsides)
11346 {
11347 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
11348 getLSLFaceMaterial(ref res, code, part, texface);
11349 }
11350 }
11351 break;
11352
10646 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 11353 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
10647 11354
10648 // TODO: Should be issuing a runtime script warning in this case. 11355 // TODO: Should be issuing a runtime script warning in this case.
@@ -10656,15 +11363,120 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10656 return new LSL_List(); 11363 return new LSL_List();
10657 } 11364 }
10658 11365
11366/*
11367 private string filterTextureUUIDbyRights(UUID origID, SceneObjectPart part, bool checkTaskInventory, bool returnInvName)
11368 {
11369 if(checkTaskInventory)
11370 {
11371 lock (part.TaskInventory)
11372 {
11373 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in part.TaskInventory)
11374 {
11375 if (inv.Value.AssetID == origID)
11376 {
11377 if(inv.Value.InvType == (int)InventoryType.Texture)
11378 {
11379 if(returnInvName)
11380 return inv.Value.Name;
11381 else
11382 return origID.ToString();
11383 }
11384 else
11385 return UUID.Zero.ToString();
11386 }
11387 }
11388 }
11389 }
11390
11391 if(World.Permissions.CanEditObject(m_host.ParentGroup.UUID, m_host.ParentGroup.RootPart.OwnerID))
11392 return origID.ToString();
11393
11394 return UUID.Zero.ToString();
11395 }
11396*/
11397 private void getLSLFaceMaterial(ref LSL_List res, int code, SceneObjectPart part, Primitive.TextureEntryFace texface)
11398 {
11399 UUID matID = texface.MaterialID;
11400 if(matID != UUID.Zero)
11401 {
11402 AssetBase MatAsset = World.AssetService.Get(matID.ToString());
11403 if(MatAsset != null)
11404 {
11405 Byte[] data = MatAsset.Data;
11406 OSDMap osdmat = (OSDMap)OSDParser.DeserializeLLSDXml(data);
11407 if(osdmat != null && osdmat.ContainsKey("NormMap"))
11408 {
11409 string mapIDstr;
11410 FaceMaterial mat = new FaceMaterial(matID, osdmat);
11411 if(code == ScriptBaseClass.PRIM_NORMAL)
11412 {
11413// mapIDstr = filterTextureUUIDbyRights(mat.NormalMapID, part, true, false);
11414 mapIDstr = mat.NormalMapID.ToString();
11415 res.Add(new LSL_String(mapIDstr));
11416 res.Add(new LSL_Vector(mat.NormalRepeatX, mat.NormalRepeatY, 0));
11417 res.Add(new LSL_Vector(mat.NormalOffsetX, mat.NormalOffsetY, 0));
11418 res.Add(new LSL_Float(mat.NormalRotation));
11419 }
11420 else if(code == ScriptBaseClass.PRIM_SPECULAR )
11421 {
11422// mapIDstr = filterTextureUUIDbyRights(mat.SpecularMapID, part, true, false);
11423 const float colorScale = 1.0f/255f;
11424 mapIDstr = mat.SpecularMapID.ToString();
11425 res.Add(new LSL_String(mapIDstr));
11426 res.Add(new LSL_Vector(mat.SpecularRepeatX, mat.SpecularRepeatY, 0));
11427 res.Add(new LSL_Vector(mat.SpecularOffsetX, mat.SpecularOffsetY, 0));
11428 res.Add(new LSL_Float(mat.SpecularRotation));
11429 res.Add(new LSL_Vector(mat.SpecularLightColor.R * colorScale,
11430 mat.SpecularLightColor.G * colorScale,
11431 mat.SpecularLightColor.B * colorScale));
11432 res.Add(new LSL_Integer(mat.SpecularLightExponent));
11433 res.Add(new LSL_Integer(mat.EnvironmentIntensity));
11434 }
11435 else if(code == ScriptBaseClass.PRIM_ALPHA_MODE)
11436 {
11437 res.Add(new LSL_Integer(mat.DiffuseAlphaMode));
11438 res.Add(new LSL_Integer(mat.AlphaMaskCutoff));
11439 }
11440 return;
11441 }
11442 }
11443 matID = UUID.Zero;
11444 }
11445 if(matID == UUID.Zero)
11446 {
11447 if(code == (int)ScriptBaseClass.PRIM_NORMAL || code == (int)ScriptBaseClass.PRIM_SPECULAR )
11448 {
11449 res.Add(new LSL_String(UUID.Zero.ToString()));
11450 res.Add(new LSL_Vector(1.0, 1.0, 0));
11451 res.Add(new LSL_Vector(0, 0, 0));
11452 res.Add(new LSL_Float(0));
11453
11454 if(code == (int)ScriptBaseClass.PRIM_SPECULAR)
11455 {
11456 res.Add(new LSL_Vector(1.0, 1.0, 1.0));
11457 res.Add(new LSL_Integer(51));
11458 res.Add(new LSL_Integer(0));
11459 }
11460 }
11461 else if(code == (int)ScriptBaseClass.PRIM_ALPHA_MODE)
11462 {
11463 res.Add(new LSL_Integer(1));
11464 res.Add(new LSL_Integer(0));
11465 }
11466 }
11467 }
11468
10659 public LSL_List llGetPrimMediaParams(int face, LSL_List rules) 11469 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
10660 { 11470 {
10661 m_host.AddScriptLPS(1); 11471 m_host.AddScriptLPS(1);
11472 ScriptSleep(m_sleepMsOnGetPrimMediaParams);
10662 return GetPrimMediaParams(m_host, face, rules); 11473 return GetPrimMediaParams(m_host, face, rules);
10663 } 11474 }
10664 11475
10665 public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) 11476 public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
10666 { 11477 {
10667 m_host.AddScriptLPS(1); 11478 m_host.AddScriptLPS(1);
11479 ScriptSleep(m_sleepMsOnGetLinkMedia);
10668 if (link == ScriptBaseClass.LINK_ROOT) 11480 if (link == ScriptBaseClass.LINK_ROOT)
10669 return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); 11481 return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules);
10670 else if (link == ScriptBaseClass.LINK_THIS) 11482 else if (link == ScriptBaseClass.LINK_THIS)
@@ -10784,12 +11596,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10784 public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules) 11596 public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules)
10785 { 11597 {
10786 m_host.AddScriptLPS(1); 11598 m_host.AddScriptLPS(1);
11599 ScriptSleep(m_sleepMsOnSetPrimMediaParams);
10787 return SetPrimMediaParams(m_host, face, rules); 11600 return SetPrimMediaParams(m_host, face, rules);
10788 } 11601 }
10789 11602
10790 public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) 11603 public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
10791 { 11604 {
10792 m_host.AddScriptLPS(1); 11605 m_host.AddScriptLPS(1);
11606 ScriptSleep(m_sleepMsOnSetLinkMedia);
10793 if (link == ScriptBaseClass.LINK_ROOT) 11607 if (link == ScriptBaseClass.LINK_ROOT)
10794 return SetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); 11608 return SetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules);
10795 else if (link == ScriptBaseClass.LINK_THIS) 11609 else if (link == ScriptBaseClass.LINK_THIS)
@@ -10908,12 +11722,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10908 public LSL_Integer llClearPrimMedia(LSL_Integer face) 11722 public LSL_Integer llClearPrimMedia(LSL_Integer face)
10909 { 11723 {
10910 m_host.AddScriptLPS(1); 11724 m_host.AddScriptLPS(1);
11725 ScriptSleep(m_sleepMsOnClearPrimMedia);
10911 return ClearPrimMedia(m_host, face); 11726 return ClearPrimMedia(m_host, face);
10912 } 11727 }
10913 11728
10914 public LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face) 11729 public LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face)
10915 { 11730 {
10916 m_host.AddScriptLPS(1); 11731 m_host.AddScriptLPS(1);
11732 ScriptSleep(m_sleepMsOnClearLinkMedia);
10917 if (link == ScriptBaseClass.LINK_ROOT) 11733 if (link == ScriptBaseClass.LINK_ROOT)
10918 return ClearPrimMedia(m_host.ParentGroup.RootPart, face); 11734 return ClearPrimMedia(m_host.ParentGroup.RootPart, face);
10919 else if (link == ScriptBaseClass.LINK_THIS) 11735 else if (link == ScriptBaseClass.LINK_THIS)
@@ -11237,8 +12053,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11237 // The function returns an ordered list 12053 // The function returns an ordered list
11238 // representing the tokens found in the supplied 12054 // representing the tokens found in the supplied
11239 // sources string. If two successive tokenizers 12055 // sources string. If two successive tokenizers
11240 // are encountered, then a NULL entry is added 12056 // are encountered, then a null-string entry is
11241 // to the list. 12057 // added to the list.
11242 // 12058 //
11243 // It is a precondition that the source and 12059 // It is a precondition that the source and
11244 // toekizer lisst are non-null. If they are null, 12060 // toekizer lisst are non-null. If they are null,
@@ -11246,7 +12062,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11246 // while their lengths are being determined. 12062 // while their lengths are being determined.
11247 // 12063 //
11248 // A small amount of working memoryis required 12064 // A small amount of working memoryis required
11249 // of approximately 8*#tokenizers. 12065 // of approximately 8*#tokenizers + 8*srcstrlen.
11250 // 12066 //
11251 // There are many ways in which this function 12067 // There are many ways in which this function
11252 // can be implemented, this implementation is 12068 // can be implemented, this implementation is
@@ -11262,155 +12078,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11262 // and eliminates redundant tokenizers as soon 12078 // and eliminates redundant tokenizers as soon
11263 // as is possible. 12079 // as is possible.
11264 // 12080 //
11265 // The implementation tries to avoid any copying 12081 // The implementation tries to minimize temporary
11266 // of arrays or other objects. 12082 // garbage generation.
11267 // </remarks> 12083 // </remarks>
11268 12084
11269 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 12085 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
11270 { 12086 {
11271 int beginning = 0; 12087 return ParseString2List(src, separators, spacers, true);
11272 int srclen = src.Length; 12088 }
11273 int seplen = separators.Length;
11274 object[] separray = separators.Data;
11275 int spclen = spacers.Length;
11276 object[] spcarray = spacers.Data;
11277 int mlen = seplen+spclen;
11278
11279 int[] offset = new int[mlen+1];
11280 bool[] active = new bool[mlen];
11281
11282 int best;
11283 int j;
11284
11285 // Initial capacity reduces resize cost
11286 12089
11287 LSL_List tokens = new LSL_List(); 12090 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
12091 {
12092 int srclen = src.Length;
12093 int seplen = separators.Length;
12094 object[] separray = separators.Data;
12095 int spclen = spacers.Length;
12096 object[] spcarray = spacers.Data;
12097 int dellen = 0;
12098 string[] delarray = new string[seplen+spclen];
11288 12099
11289 // All entries are initially valid 12100 int outlen = 0;
12101 string[] outarray = new string[srclen*2+1];
11290 12102
11291 for (int i = 0; i < mlen; i++) 12103 int i, j;
11292 active[i] = true; 12104 string d;
11293 12105
11294 offset[mlen] = srclen; 12106 m_host.AddScriptLPS(1);
11295 12107
11296 while (beginning < srclen) 12108 /*
12109 * Convert separator and spacer lists to C# strings.
12110 * Also filter out null strings so we don't hang.
12111 */
12112 for (i = 0; i < seplen; i ++)
11297 { 12113 {
12114 d = separray[i].ToString();
12115 if (d.Length > 0)
12116 {
12117 delarray[dellen++] = d;
12118 }
12119 }
12120 seplen = dellen;
11298 12121
11299 best = mlen; // as bad as it gets 12122 for (i = 0; i < spclen; i ++)
12123 {
12124 d = spcarray[i].ToString();
12125 if (d.Length > 0)
12126 {
12127 delarray[dellen++] = d;
12128 }
12129 }
11300 12130
11301 // Scan for separators 12131 /*
12132 * Scan through source string from beginning to end.
12133 */
12134 for (i = 0;;)
12135 {
11302 12136
11303 for (j = 0; j < seplen; j++) 12137 /*
12138 * Find earliest delimeter in src starting at i (if any).
12139 */
12140 int earliestDel = -1;
12141 int earliestSrc = srclen;
12142 string earliestStr = null;
12143 for (j = 0; j < dellen; j ++)
11304 { 12144 {
11305 if (separray[j].ToString() == String.Empty) 12145 d = delarray[j];
11306 active[j] = false; 12146 if (d != null)
11307
11308 if (active[j])
11309 { 12147 {
11310 // scan all of the markers 12148 int index = src.IndexOf(d, i);
11311 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 12149 if (index < 0)
11312 { 12150 {
11313 // not present at all 12151 delarray[j] = null; // delim nowhere in src, don't check it anymore
11314 active[j] = false;
11315 } 12152 }
11316 else 12153 else if (index < earliestSrc)
11317 { 12154 {
11318 // present and correct 12155 earliestSrc = index; // where delimeter starts in source string
11319 if (offset[j] < offset[best]) 12156 earliestDel = j; // where delimeter is in delarray[]
11320 { 12157 earliestStr = d; // the delimeter string from delarray[]
11321 // closest so far 12158 if (index == i) break; // can't do any better than found at beg of string
11322 best = j;
11323 if (offset[best] == beginning)
11324 break;
11325 }
11326 } 12159 }
11327 } 12160 }
11328 } 12161 }
11329 12162
11330 // Scan for spacers 12163 /*
11331 12164 * Output source string starting at i through start of earliest delimeter.
11332 if (offset[best] != beginning) 12165 */
12166 if (keepNulls || (earliestSrc > i))
11333 { 12167 {
11334 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 12168 outarray[outlen++] = src.Substring(i, earliestSrc - i);
11335 {
11336 if (spcarray[j-seplen].ToString() == String.Empty)
11337 active[j] = false;
11338
11339 if (active[j])
11340 {
11341 // scan all of the markers
11342 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
11343 {
11344 // not present at all
11345 active[j] = false;
11346 }
11347 else
11348 {
11349 // present and correct
11350 if (offset[j] < offset[best])
11351 {
11352 // closest so far
11353 best = j;
11354 }
11355 }
11356 }
11357 }
11358 } 12169 }
11359 12170
11360 // This is the normal exit from the scanning loop 12171 /*
12172 * If no delimeter found at or after i, we're done scanning.
12173 */
12174 if (earliestDel < 0) break;
11361 12175
11362 if (best == mlen) 12176 /*
12177 * If delimeter was a spacer, output the spacer.
12178 */
12179 if (earliestDel >= seplen)
11363 { 12180 {
11364 // no markers were found on this pass 12181 outarray[outlen++] = earliestStr;
11365 // so we're pretty much done
11366 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
11367 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
11368 break;
11369 } 12182 }
11370 12183
11371 // Otherwise we just add the newly delimited token 12184 /*
11372 // and recalculate where the search should continue. 12185 * Look at rest of src string following delimeter.
11373 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 12186 */
11374 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 12187 i = earliestSrc + earliestStr.Length;
11375
11376 if (best < seplen)
11377 {
11378 beginning = offset[best] + (separray[best].ToString()).Length;
11379 }
11380 else
11381 {
11382 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
11383 string str = spcarray[best - seplen].ToString();
11384 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
11385 tokens.Add(new LSL_String(str));
11386 }
11387 } 12188 }
11388 12189
11389 // This an awkward an not very intuitive boundary case. If the 12190 /*
11390 // last substring is a tokenizer, then there is an implied trailing 12191 * Make up an exact-sized output array suitable for an LSL_List object.
11391 // null list entry. Hopefully the single comparison will not be too 12192 */
11392 // arduous. Alternatively the 'break' could be replced with a return 12193 object[] outlist = new object[outlen];
11393 // but that's shabby programming. 12194 for (i = 0; i < outlen; i ++)
11394
11395 if ((beginning == srclen) && (keepNulls))
11396 { 12195 {
11397 if (srclen != 0) 12196 outlist[i] = new LSL_String(outarray[i]);
11398 tokens.Add(new LSL_String(""));
11399 } 12197 }
11400 12198 return new LSL_List(outlist);
11401 return tokens;
11402 }
11403
11404 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
11405 {
11406 m_host.AddScriptLPS(1);
11407 return this.ParseString(src, separators, spacers, false);
11408 }
11409
11410 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
11411 {
11412 m_host.AddScriptLPS(1);
11413 return this.ParseString(src, separators, spacers, true);
11414 } 12199 }
11415 12200
11416 public LSL_Integer llGetObjectPermMask(int mask) 12201 public LSL_Integer llGetObjectPermMask(int mask)
@@ -11453,7 +12238,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11453 12238
11454 if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false)) 12239 if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
11455 { 12240 {
11456 if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) 12241 if (World.Permissions.IsAdministrator(m_host.OwnerID))
11457 { 12242 {
11458 if (mask == ScriptBaseClass.MASK_BASE)//0 12243 if (mask == ScriptBaseClass.MASK_BASE)//0
11459 { 12244 {
@@ -11515,7 +12300,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11515 12300
11516 if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false)) 12301 if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
11517 { 12302 {
11518 if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) 12303 if (World.Permissions.IsAdministrator(m_host.OwnerID))
11519 { 12304 {
11520 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); 12305 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
11521 12306
@@ -11574,7 +12359,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11574 { 12359 {
11575 m_host.AddScriptLPS(1); 12360 m_host.AddScriptLPS(1);
11576 if (m_UrlModule != null) 12361 if (m_UrlModule != null)
11577 return m_UrlModule.RequestSecureURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID).ToString(); 12362 return m_UrlModule.RequestSecureURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID, null).ToString();
11578 return UUID.Zero.ToString(); 12363 return UUID.Zero.ToString();
11579 } 12364 }
11580 12365
@@ -11600,6 +12385,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11600 case ScriptBaseClass.DATA_SIM_POS: 12385 case ScriptBaseClass.DATA_SIM_POS:
11601 if (info == null) 12386 if (info == null)
11602 { 12387 {
12388 ScriptSleep(m_sleepMsOnRequestSimulatorData);
11603 return UUID.Zero.ToString(); 12389 return UUID.Zero.ToString();
11604 } 12390 }
11605 12391
@@ -11646,6 +12432,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11646 case ScriptBaseClass.DATA_SIM_RATING: 12432 case ScriptBaseClass.DATA_SIM_RATING:
11647 if (info == null) 12433 if (info == null)
11648 { 12434 {
12435 ScriptSleep(m_sleepMsOnRequestSimulatorData);
11649 return UUID.Zero.ToString(); 12436 return UUID.Zero.ToString();
11650 } 12437 }
11651 int access = info.Maturity; 12438 int access = info.Maturity;
@@ -11660,14 +12447,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11660 break; 12447 break;
11661 case ScriptBaseClass.DATA_SIM_RELEASE: 12448 case ScriptBaseClass.DATA_SIM_RELEASE:
11662 if (ossl != null) 12449 if (ossl != null)
11663 { 12450 ossl.CheckThreatLevel(ThreatLevel.High, "llRequestSimulatorData");
11664//// TODO - double check this.
11665 if (!ossl.CheckThreatLevel(ThreatLevel.High, "llRequestSimulatorData"))
11666 return UUID.Zero.ToString(); // Raise no event
11667 }
11668 reply = "OpenSim"; 12451 reply = "OpenSim";
11669 break; 12452 break;
11670 default: 12453 default:
12454 ScriptSleep(m_sleepMsOnRequestSimulatorData);
11671 return UUID.Zero.ToString(); // Raise no event 12455 return UUID.Zero.ToString(); // Raise no event
11672 } 12456 }
11673 UUID rq = UUID.Random(); 12457 UUID rq = UUID.Random();
@@ -11678,6 +12462,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11678 AsyncCommands. 12462 AsyncCommands.
11679 DataserverPlugin.DataserverReply(rq.ToString(), reply); 12463 DataserverPlugin.DataserverReply(rq.ToString(), reply);
11680 12464
12465 ScriptSleep(m_sleepMsOnRequestSimulatorData);
11681 return tid.ToString(); 12466 return tid.ToString();
11682 } 12467 }
11683 catch(Exception) 12468 catch(Exception)
@@ -11692,7 +12477,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11692 m_host.AddScriptLPS(1); 12477 m_host.AddScriptLPS(1);
11693 12478
11694 if (m_UrlModule != null) 12479 if (m_UrlModule != null)
11695 return m_UrlModule.RequestURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID).ToString(); 12480 return m_UrlModule.RequestURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID, null).ToString();
11696 return UUID.Zero.ToString(); 12481 return UUID.Zero.ToString();
11697 } 12482 }
11698 12483
@@ -11708,31 +12493,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11708 UUID key = new UUID(); 12493 UUID key = new UUID();
11709 if (UUID.TryParse(id, out key)) 12494 if (UUID.TryParse(id, out key))
11710 { 12495 {
11711 try 12496 // return total object mass
11712 { 12497 SceneObjectPart part = World.GetSceneObjectPart(key);
11713 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 12498 if (part != null)
11714 if (obj != null) 12499 return part.ParentGroup.GetMass();
11715 return (double)obj.GetMass(); 12500
11716 // the object is null so the key is for an avatar 12501 // the object is null so the key is for an avatar
11717 ScenePresence avatar = World.GetScenePresence(key); 12502 ScenePresence avatar = World.GetScenePresence(key);
11718 if (avatar != null) 12503 if (avatar != null)
11719 if (avatar.IsChildAgent)
11720 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
11721 // child agents have a mass of 1.0
11722 return 1;
11723 else
11724 return (double)avatar.GetMass();
11725 }
11726 catch (KeyNotFoundException)
11727 { 12504 {
11728 return 0; // The Object/Agent not in the region so just return zero 12505 if (avatar.IsChildAgent)
12506 {
12507 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
12508 // child agents have a mass of 1.0
12509 return 1;
12510 }
12511 else
12512 {
12513 return (double)avatar.GetMass();
12514 }
11729 } 12515 }
11730 } 12516 }
11731 return 0; 12517 return 0;
11732 } 12518 }
11733 12519
11734 /// <summary> 12520 /// <summary>
11735 /// illListReplaceList removes the sub-list defined by the inclusive indices 12521 /// llListReplaceList removes the sub-list defined by the inclusive indices
11736 /// start and end and inserts the src list in its place. The inclusive 12522 /// start and end and inserts the src list in its place. The inclusive
11737 /// nature of the indices means that at least one element must be deleted 12523 /// nature of the indices means that at least one element must be deleted
11738 /// if the indices are within the bounds of the existing list. I.e. 2,2 12524 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -11789,16 +12575,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11789 // based upon end. Note that if end exceeds the upper 12575 // based upon end. Note that if end exceeds the upper
11790 // bound in this case, the entire destination list 12576 // bound in this case, the entire destination list
11791 // is removed. 12577 // is removed.
11792 else 12578 else if (start == 0)
11793 { 12579 {
11794 if (end + 1 < dest.Length) 12580 if (end + 1 < dest.Length)
11795 {
11796 return src + dest.GetSublist(end + 1, -1); 12581 return src + dest.GetSublist(end + 1, -1);
11797 }
11798 else 12582 else
11799 {
11800 return src; 12583 return src;
11801 } 12584 }
12585 else // Start < 0
12586 {
12587 if (end + 1 < dest.Length)
12588 return dest.GetSublist(end + 1, -1);
12589 else
12590 return new LSL_List();
11802 } 12591 }
11803 } 12592 }
11804 // Finally, if start > end, we strip away a prefix and 12593 // Finally, if start > end, we strip away a prefix and
@@ -11821,6 +12610,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11821 if (null != dm) 12610 if (null != dm)
11822 dm.SendUrlToUser( 12611 dm.SendUrlToUser(
11823 new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url); 12612 new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url);
12613
12614 ScriptSleep(m_sleepMsOnLoadURL);
11824 } 12615 }
11825 12616
11826 public void llParcelMediaCommandList(LSL_List commandList) 12617 public void llParcelMediaCommandList(LSL_List commandList)
@@ -11833,7 +12624,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11833 // according to the docs, this command only works if script owner and land owner are the same 12624 // according to the docs, this command only works if script owner and land owner are the same
11834 // lets add estate owners and gods, too, and use the generic permission check. 12625 // lets add estate owners and gods, too, and use the generic permission check.
11835 ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 12626 ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
11836 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return; 12627 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia, false)) return;
11837 12628
11838 bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? 12629 bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)?
11839 byte loop = 0; 12630 byte loop = 0;
@@ -12051,18 +12842,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12051 if (sp.currentParcelUUID == landData.GlobalID) 12842 if (sp.currentParcelUUID == landData.GlobalID)
12052 { 12843 {
12053 sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? 12844 sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this?
12054 (ParcelMediaCommandEnum)commandToSend, 12845 (ParcelMediaCommandEnum)commandToSend, time);
12055 time);
12056 } 12846 }
12057 }); 12847 });
12058 } 12848 }
12059 else if (!presence.IsChildAgent) 12849 else if (!presence.IsChildAgent)
12060 { 12850 {
12061 presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? 12851 presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this?
12062 (ParcelMediaCommandEnum)commandToSend, 12852 (ParcelMediaCommandEnum)commandToSend, time);
12063 time);
12064 } 12853 }
12065 } 12854 }
12855 ScriptSleep(m_sleepMsOnParcelMediaCommandList);
12066 } 12856 }
12067 12857
12068 public LSL_List llParcelMediaQuery(LSL_List aList) 12858 public LSL_List llParcelMediaQuery(LSL_List aList)
@@ -12076,7 +12866,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12076 12866
12077 if (aList.Data[i] != null) 12867 if (aList.Data[i] != null)
12078 { 12868 {
12079 switch ((ParcelMediaCommandEnum) aList.Data[i]) 12869 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
12080 { 12870 {
12081 case ParcelMediaCommandEnum.Url: 12871 case ParcelMediaCommandEnum.Url:
12082 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); 12872 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL));
@@ -12102,6 +12892,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12102 12892
12103 } 12893 }
12104 } 12894 }
12895 ScriptSleep(m_sleepMsOnParcelMediaQuery);
12105 return list; 12896 return list;
12106 } 12897 }
12107 12898
@@ -12110,6 +12901,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12110 m_host.AddScriptLPS(1); 12901 m_host.AddScriptLPS(1);
12111 Int64 tmp = 0; 12902 Int64 tmp = 0;
12112 Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); 12903 Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp);
12904 ScriptSleep(m_sleepMsOnModPow);
12113 return Convert.ToInt32(tmp); 12905 return Convert.ToInt32(tmp);
12114 } 12906 }
12115 12907
@@ -12131,15 +12923,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12131 12923
12132 if (quick_pay_buttons.Data.Length < 4) 12924 if (quick_pay_buttons.Data.Length < 4)
12133 { 12925 {
12134 Error("llSetPayPrice", "List must have at least 4 elements"); 12926 int x;
12135 return; 12927 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
12928 {
12929 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
12930 }
12136 } 12931 }
12137 m_host.ParentGroup.RootPart.PayPrice[0]=price; 12932 int[] nPrice = new int[5];
12138 12933 nPrice[0] = price;
12139 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 12934 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
12140 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 12935 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
12141 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 12936 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
12142 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 12937 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
12938 m_host.ParentGroup.RootPart.PayPrice = nPrice;
12143 m_host.ParentGroup.HasGroupChanged = true; 12939 m_host.ParentGroup.HasGroupChanged = true;
12144 } 12940 }
12145 12941
@@ -12156,7 +12952,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12156 return Vector3.Zero; 12952 return Vector3.Zero;
12157 } 12953 }
12158 12954
12159 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 12955// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
12956 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
12160 if (presence != null) 12957 if (presence != null)
12161 { 12958 {
12162 LSL_Vector pos = new LSL_Vector(presence.CameraPosition); 12959 LSL_Vector pos = new LSL_Vector(presence.CameraPosition);
@@ -12179,7 +12976,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12179 return Quaternion.Identity; 12976 return Quaternion.Identity;
12180 } 12977 }
12181 12978
12182 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 12979// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
12980 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
12183 if (presence != null) 12981 if (presence != null)
12184 { 12982 {
12185 return new LSL_Rotation(presence.CameraRotation); 12983 return new LSL_Rotation(presence.CameraRotation);
@@ -12192,12 +12990,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12192 { 12990 {
12193 m_host.AddScriptLPS(1); 12991 m_host.AddScriptLPS(1);
12194 Deprecated("llSetPrimURL", "Use llSetPrimMediaParams instead"); 12992 Deprecated("llSetPrimURL", "Use llSetPrimMediaParams instead");
12993 ScriptSleep(m_sleepMsOnSetPrimURL);
12195 } 12994 }
12196 12995
12197 public void llRefreshPrimURL() 12996 public void llRefreshPrimURL()
12198 { 12997 {
12199 m_host.AddScriptLPS(1); 12998 m_host.AddScriptLPS(1);
12200 Deprecated("llRefreshPrimURL"); 12999 Deprecated("llRefreshPrimURL");
13000 ScriptSleep(m_sleepMsOnRefreshPrimURL);
12201 } 13001 }
12202 13002
12203 public LSL_String llEscapeURL(string url) 13003 public LSL_String llEscapeURL(string url)
@@ -12230,7 +13030,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12230 { 13030 {
12231 m_host.AddScriptLPS(1); 13031 m_host.AddScriptLPS(1);
12232 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 13032 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
12233 if (detectedParams == null) return; // only works on the first detected avatar 13033 if (detectedParams == null)
13034 {
13035 if (m_host.ParentGroup.IsAttachment == true)
13036 {
13037 detectedParams = new DetectParams();
13038 detectedParams.Key = m_host.OwnerID;
13039 }
13040 else
13041 {
13042 return;
13043 }
13044 }
12234 13045
12235 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 13046 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
12236 if (avatar != null) 13047 if (avatar != null)
@@ -12238,6 +13049,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12238 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, 13049 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name,
12239 simname, pos, lookAt); 13050 simname, pos, lookAt);
12240 } 13051 }
13052 ScriptSleep(m_sleepMsOnMapDestination);
12241 } 13053 }
12242 13054
12243 public void llAddToLandBanList(string avatar, double hours) 13055 public void llAddToLandBanList(string avatar, double hours)
@@ -12245,7 +13057,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12245 m_host.AddScriptLPS(1); 13057 m_host.AddScriptLPS(1);
12246 UUID key; 13058 UUID key;
12247 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 13059 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12248 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) 13060 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned, false))
12249 { 13061 {
12250 int expires = 0; 13062 int expires = 0;
12251 if (hours != 0) 13063 if (hours != 0)
@@ -12278,6 +13090,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12278 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); 13090 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
12279 } 13091 }
12280 } 13092 }
13093 ScriptSleep(m_sleepMsOnAddToLandBanList);
12281 } 13094 }
12282 13095
12283 public void llRemoveFromLandPassList(string avatar) 13096 public void llRemoveFromLandPassList(string avatar)
@@ -12285,7 +13098,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12285 m_host.AddScriptLPS(1); 13098 m_host.AddScriptLPS(1);
12286 UUID key; 13099 UUID key;
12287 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 13100 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12288 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed)) 13101 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManagePasses, false))
12289 { 13102 {
12290 if (UUID.TryParse(avatar, out key)) 13103 if (UUID.TryParse(avatar, out key))
12291 { 13104 {
@@ -12304,6 +13117,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12304 } 13117 }
12305 } 13118 }
12306 } 13119 }
13120 ScriptSleep(m_sleepMsOnRemoveFromLandPassList);
12307 } 13121 }
12308 13122
12309 public void llRemoveFromLandBanList(string avatar) 13123 public void llRemoveFromLandBanList(string avatar)
@@ -12311,7 +13125,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12311 m_host.AddScriptLPS(1); 13125 m_host.AddScriptLPS(1);
12312 UUID key; 13126 UUID key;
12313 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 13127 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12314 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) 13128 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned, false))
12315 { 13129 {
12316 if (UUID.TryParse(avatar, out key)) 13130 if (UUID.TryParse(avatar, out key))
12317 { 13131 {
@@ -12330,6 +13144,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12330 } 13144 }
12331 } 13145 }
12332 } 13146 }
13147 ScriptSleep(m_sleepMsOnRemoveFromLandBanList);
12333 } 13148 }
12334 13149
12335 public void llSetCameraParams(LSL_List rules) 13150 public void llSetCameraParams(LSL_List rules)
@@ -12542,19 +13357,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12542 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 13357 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
12543 { 13358 {
12544 m_host.AddScriptLPS(1); 13359 m_host.AddScriptLPS(1);
12545 string ret = String.Empty; 13360
12546 string src1 = llBase64ToString(str1); 13361 if (str1 == String.Empty)
12547 string src2 = llBase64ToString(str2); 13362 return String.Empty;
12548 int c = 0; 13363 if (str2 == String.Empty)
12549 for (int i = 0; i < src1.Length; i++) 13364 return str1;
13365
13366 int len = str2.Length;
13367 if ((len % 4) != 0) // LL is EVIL!!!!
12550 { 13368 {
12551 ret += (char) (src1[i] ^ src2[c]); 13369 while (str2.EndsWith("="))
13370 str2 = str2.Substring(0, str2.Length - 1);
13371
13372 len = str2.Length;
13373 int mod = len % 4;
12552 13374
12553 c++; 13375 if (mod == 1)
12554 if (c >= src2.Length) 13376 str2 = str2.Substring(0, str2.Length - 1);
12555 c = 0; 13377 else if (mod == 2)
13378 str2 += "==";
13379 else if (mod == 3)
13380 str2 += "=";
12556 } 13381 }
12557 return llStringToBase64(ret); 13382
13383 byte[] data1;
13384 byte[] data2;
13385 try
13386 {
13387 data1 = Convert.FromBase64String(str1);
13388 data2 = Convert.FromBase64String(str2);
13389 }
13390 catch (Exception)
13391 {
13392 return new LSL_String(String.Empty);
13393 }
13394
13395 byte[] d2 = new Byte[data1.Length];
13396 int pos = 0;
13397
13398 if (data1.Length <= data2.Length)
13399 {
13400 Array.Copy(data2, 0, d2, 0, data1.Length);
13401 }
13402 else
13403 {
13404 while (pos < data1.Length)
13405 {
13406 len = data1.Length - pos;
13407 if (len > data2.Length)
13408 len = data2.Length;
13409
13410 Array.Copy(data2, 0, d2, pos, len);
13411 pos += len;
13412 }
13413 }
13414
13415 for (pos = 0 ; pos < data1.Length ; pos++ )
13416 data1[pos] ^= d2[pos];
13417
13418 return Convert.ToBase64String(data1);
12558 } 13419 }
12559 13420
12560 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 13421 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -12570,6 +13431,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12570 List<string> param = new List<string>(); 13431 List<string> param = new List<string>();
12571 bool ok; 13432 bool ok;
12572 Int32 flag; 13433 Int32 flag;
13434 int nCustomHeaders = 0;
12573 13435
12574 for (int i = 0; i < parameters.Data.Length; i += 2) 13436 for (int i = 0; i < parameters.Data.Length; i += 2)
12575 { 13437 {
@@ -12596,6 +13458,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12596 //Second Life documentation for llHTTPRequest. 13458 //Second Life documentation for llHTTPRequest.
12597 for (int count = 1; count <= 8; ++count) 13459 for (int count = 1; count <= 8; ++count)
12598 { 13460 {
13461 if(nCustomHeaders >= 8)
13462 {
13463 Error("llHTTPRequest", "Max number of custom headers is 8, excess ignored");
13464 break;
13465 }
13466
12599 //Enough parameters remaining for (another) header? 13467 //Enough parameters remaining for (another) header?
12600 if (parameters.Data.Length - i < 2) 13468 if (parameters.Data.Length - i < 2)
12601 { 13469 {
@@ -12610,15 +13478,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12610 13478
12611 param.Add(parameters.Data[i].ToString()); 13479 param.Add(parameters.Data[i].ToString());
12612 param.Add(parameters.Data[i+1].ToString()); 13480 param.Add(parameters.Data[i+1].ToString());
13481 nCustomHeaders++;
12613 13482
12614 //Have we reached the end of the list of headers? 13483 //Have we reached the end of the list of headers?
12615 //End is marked by a string with a single digit. 13484 //End is marked by a string with a single digit.
12616 if (i+2 >= parameters.Data.Length || 13485 if (i + 2 >= parameters.Data.Length ||
12617 Char.IsDigit(parameters.Data[i].ToString()[0])) 13486 Char.IsDigit(parameters.Data[i + 2].ToString()[0]))
12618 { 13487 {
12619 break; 13488 break;
12620 } 13489 }
12621
12622 i += 2; 13490 i += 2;
12623 } 13491 }
12624 } 13492 }
@@ -12658,16 +13526,72 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12658 if (userAgent != null) 13526 if (userAgent != null)
12659 httpHeaders["User-Agent"] = userAgent; 13527 httpHeaders["User-Agent"] = userAgent;
12660 13528
13529 // See if the URL contains any header hacks
13530 string[] urlParts = url.Split(new char[] {'\n'});
13531 if (urlParts.Length > 1)
13532 {
13533 // Iterate the passed headers and parse them
13534 for (int i = 1 ; i < urlParts.Length ; i++ )
13535 {
13536 // The rest of those would be added to the body in SL.
13537 // Let's not do that.
13538 if (urlParts[i] == String.Empty)
13539 break;
13540
13541 // See if this could be a valid header
13542 string[] headerParts = urlParts[i].Split(new char[] {':'}, 2);
13543 if (headerParts.Length != 2)
13544 continue;
13545
13546 string headerName = headerParts[0].Trim();
13547 string headerValue = headerParts[1].Trim();
13548
13549 // Filter out headers that could be used to abuse
13550 // another system or cloak the request
13551 if (headerName.ToLower() == "x-secondlife-shard" ||
13552 headerName.ToLower() == "x-secondlife-object-name" ||
13553 headerName.ToLower() == "x-secondlife-object-key" ||
13554 headerName.ToLower() == "x-secondlife-region" ||
13555 headerName.ToLower() == "x-secondlife-local-position" ||
13556 headerName.ToLower() == "x-secondlife-local-velocity" ||
13557 headerName.ToLower() == "x-secondlife-local-rotation" ||
13558 headerName.ToLower() == "x-secondlife-owner-name" ||
13559 headerName.ToLower() == "x-secondlife-owner-key" ||
13560 headerName.ToLower() == "connection" ||
13561 headerName.ToLower() == "content-length" ||
13562 headerName.ToLower() == "from" ||
13563 headerName.ToLower() == "host" ||
13564 headerName.ToLower() == "proxy-authorization" ||
13565 headerName.ToLower() == "referer" ||
13566 headerName.ToLower() == "trailer" ||
13567 headerName.ToLower() == "transfer-encoding" ||
13568 headerName.ToLower() == "via" ||
13569 headerName.ToLower() == "authorization")
13570 continue;
13571
13572 httpHeaders[headerName] = headerValue;
13573 }
13574
13575 // Finally, strip any protocol specifier from the URL
13576 url = urlParts[0].Trim();
13577 int idx = url.IndexOf(" HTTP/");
13578 if (idx != -1)
13579 url = url.Substring(0, idx);
13580 }
13581
12661 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$"; 13582 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$";
12662 Regex r = new Regex(authregex); 13583 Regex r = new Regex(authregex);
12663 int[] gnums = r.GetGroupNumbers(); 13584 int[] gnums = r.GetGroupNumbers();
12664 Match m = r.Match(url); 13585 Match m = r.Match(url);
12665 if (m.Success) { 13586 if (m.Success)
12666 for (int i = 1; i < gnums.Length; i++) { 13587 {
13588 for (int i = 1; i < gnums.Length; i++)
13589 {
12667 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 13590 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
12668 //CaptureCollection cc = g.Captures; 13591 //CaptureCollection cc = g.Captures;
12669 } 13592 }
12670 if (m.Groups.Count == 5) { 13593 if (m.Groups.Count == 5)
13594 {
12671 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 13595 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
12672 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 13596 url = m.Groups[1].ToString() + m.Groups[4].ToString();
12673 } 13597 }
@@ -12712,6 +13636,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12712 } 13636 }
12713 } 13637 }
12714 } 13638 }
13639 ScriptSleep(m_sleepMsOnResetLandBanList);
12715 } 13640 }
12716 13641
12717 public void llResetLandPassList() 13642 public void llResetLandPassList()
@@ -12728,6 +13653,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12728 } 13653 }
12729 } 13654 }
12730 } 13655 }
13656 ScriptSleep(m_sleepMsOnResetLandPassList);
12731 } 13657 }
12732 13658
12733 public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide) 13659 public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide)
@@ -12785,6 +13711,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12785 ret.Add(new LSL_Integer(detectedParams.Value)); 13711 ret.Add(new LSL_Integer(detectedParams.Value));
12786 } 13712 }
12787 } 13713 }
13714 ScriptSleep(m_sleepMsOnGetParcelPrimOwners);
12788 return ret; 13715 return ret;
12789 } 13716 }
12790 13717
@@ -12871,6 +13798,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12871 13798
12872 LSL_List ret = new LSL_List(); 13799 LSL_List ret = new LSL_List();
12873 UUID key = new UUID(); 13800 UUID key = new UUID();
13801
13802
12874 if (UUID.TryParse(id, out key)) 13803 if (UUID.TryParse(id, out key))
12875 { 13804 {
12876 ScenePresence av = World.GetScenePresence(key); 13805 ScenePresence av = World.GetScenePresence(key);
@@ -12888,13 +13817,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12888 ret.Add(new LSL_String("")); 13817 ret.Add(new LSL_String(""));
12889 break; 13818 break;
12890 case ScriptBaseClass.OBJECT_POS: 13819 case ScriptBaseClass.OBJECT_POS:
12891 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); 13820 Vector3 avpos;
13821
13822 if (av.ParentID != 0 && av.ParentPart != null &&
13823 av.ParentPart.ParentGroup != null && av.ParentPart.ParentGroup.RootPart != null )
13824 {
13825 avpos = av.OffsetPosition;
13826
13827 if(!av.LegacySitOffsets)
13828 {
13829 Vector3 sitOffset = (Zrot(av.Rotation)) * (av.Appearance.AvatarHeight * 0.02638f *2.0f);
13830 avpos -= sitOffset;
13831 }
13832
13833 SceneObjectPart sitRoot = av.ParentPart.ParentGroup.RootPart;
13834 avpos = sitRoot.GetWorldPosition() + avpos * sitRoot.GetWorldRotation();
13835 }
13836 else
13837 avpos = av.AbsolutePosition;
13838
13839 ret.Add(new LSL_Vector((double)avpos.X, (double)avpos.Y, (double)avpos.Z));
12892 break; 13840 break;
12893 case ScriptBaseClass.OBJECT_ROT: 13841 case ScriptBaseClass.OBJECT_ROT:
12894 ret.Add(new LSL_Rotation(av.GetWorldRotation())); 13842 Quaternion avrot = av.GetWorldRotation();
13843 ret.Add(new LSL_Rotation(avrot));
12895 break; 13844 break;
12896 case ScriptBaseClass.OBJECT_VELOCITY: 13845 case ScriptBaseClass.OBJECT_VELOCITY:
12897 ret.Add(new LSL_Vector(av.GetWorldVelocity())); 13846 Vector3 avvel = av.GetWorldVelocity();
13847 ret.Add(new LSL_Vector((double)avvel.X, (double)avvel.Y, (double)avvel.Z));
12898 break; 13848 break;
12899 case ScriptBaseClass.OBJECT_OWNER: 13849 case ScriptBaseClass.OBJECT_OWNER:
12900 ret.Add(new LSL_String(id)); 13850 ret.Add(new LSL_String(id));
@@ -12976,6 +13926,46 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12976 case ScriptBaseClass.OBJECT_LAST_OWNER_ID: 13926 case ScriptBaseClass.OBJECT_LAST_OWNER_ID:
12977 ret.Add(new LSL_Key(ScriptBaseClass.NULL_KEY)); 13927 ret.Add(new LSL_Key(ScriptBaseClass.NULL_KEY));
12978 break; 13928 break;
13929 case ScriptBaseClass.OBJECT_CLICK_ACTION:
13930 ret.Add(new LSL_Integer(0));
13931 break;
13932 case ScriptBaseClass.OBJECT_OMEGA:
13933 ret.Add(new LSL_Vector(Vector3.Zero));
13934 break;
13935 case ScriptBaseClass.OBJECT_PRIM_COUNT:
13936 List<SceneObjectGroup> Attachments = av.GetAttachments();
13937 int count = 0;
13938 try
13939 {
13940 foreach (SceneObjectGroup Attachment in Attachments)
13941 count += Attachment.PrimCount;
13942 } catch { };
13943 ret.Add(new LSL_Integer(count));
13944 break;
13945 case ScriptBaseClass.OBJECT_TOTAL_INVENTORY_COUNT:
13946 List<SceneObjectGroup> invAttachments = av.GetAttachments();
13947 int invcount = 0;
13948 try
13949 {
13950 foreach (SceneObjectGroup Attachment in invAttachments)
13951 {
13952 SceneObjectPart[] parts = Attachment.Parts;
13953 int nparts = parts.Count();
13954 for(int i = 0; i < nparts; i++)
13955 invcount += parts[i].Inventory.Count;
13956 }
13957 } catch { };
13958 ret.Add(new LSL_Integer(invcount));
13959 break;
13960 case ScriptBaseClass.OBJECT_REZZER_KEY:
13961 ret.Add(new LSL_Key(id));
13962 break;
13963 case ScriptBaseClass.OBJECT_GROUP_TAG:
13964 ret.Add(new LSL_String(av.Grouptitle));
13965 break;
13966 case ScriptBaseClass.OBJECT_TEMP_ATTACHED:
13967 ret.Add(new LSL_Integer(0));
13968 break;
12979 default: 13969 default:
12980 // Invalid or unhandled constant. 13970 // Invalid or unhandled constant.
12981 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 13971 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
@@ -13000,7 +13990,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13000 ret.Add(new LSL_String(obj.Description)); 13990 ret.Add(new LSL_String(obj.Description));
13001 break; 13991 break;
13002 case ScriptBaseClass.OBJECT_POS: 13992 case ScriptBaseClass.OBJECT_POS:
13003 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); 13993 Vector3 opos = obj.AbsolutePosition;
13994 ret.Add(new LSL_Vector(opos.X, opos.Y, opos.Z));
13004 break; 13995 break;
13005 case ScriptBaseClass.OBJECT_ROT: 13996 case ScriptBaseClass.OBJECT_ROT:
13006 Quaternion rot = Quaternion.Identity; 13997 Quaternion rot = Quaternion.Identity;
@@ -13036,7 +14027,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13036 } 14027 }
13037 else 14028 else
13038 { 14029 {
13039 vel = obj.Velocity; 14030 vel = obj.Velocity;
13040 } 14031 }
13041 14032
13042 ret.Add(vel); 14033 ret.Add(vel);
@@ -13073,9 +14064,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13073 // The value returned in SL for normal prims is prim count 14064 // The value returned in SL for normal prims is prim count
13074 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount)); 14065 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
13075 break; 14066 break;
13076 // The following 3 costs I have intentionaly coded to return zero. They are part of 14067
13077 // "Land Impact" calculations. These calculations are probably not applicable 14068 // costs below may need to be diferent for root parts, need to check
13078 // to OpenSim and are not yet complete in SL
13079 case ScriptBaseClass.OBJECT_SERVER_COST: 14069 case ScriptBaseClass.OBJECT_SERVER_COST:
13080 // The linden calculation is here 14070 // The linden calculation is here
13081 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight 14071 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
@@ -13083,16 +14073,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13083 ret.Add(new LSL_Float(0)); 14073 ret.Add(new LSL_Float(0));
13084 break; 14074 break;
13085 case ScriptBaseClass.OBJECT_STREAMING_COST: 14075 case ScriptBaseClass.OBJECT_STREAMING_COST:
13086 // The linden calculation is here 14076 // The value returned in SL for normal prims is prim count * 0.06
13087 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost 14077 ret.Add(new LSL_Float(obj.StreamingCost));
13088 // The value returned in SL for normal prims looks like the prim count * 0.06
13089 ret.Add(new LSL_Float(0));
13090 break; 14078 break;
13091 case ScriptBaseClass.OBJECT_PHYSICS_COST: 14079 case ScriptBaseClass.OBJECT_PHYSICS_COST:
13092 // The linden calculation is here 14080 // The value returned in SL for normal prims is prim count
13093 // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics 14081 ret.Add(new LSL_Float(obj.PhysicsCost));
13094 // The value returned in SL for normal prims looks like the prim count
13095 ret.Add(new LSL_Float(0));
13096 break; 14082 break;
13097 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding 14083 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
13098 ret.Add(new LSL_Float(0)); 14084 ret.Add(new LSL_Float(0));
@@ -13152,6 +14138,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13152 case ScriptBaseClass.OBJECT_LAST_OWNER_ID: 14138 case ScriptBaseClass.OBJECT_LAST_OWNER_ID:
13153 ret.Add(new LSL_Key(obj.ParentGroup.LastOwnerID.ToString())); 14139 ret.Add(new LSL_Key(obj.ParentGroup.LastOwnerID.ToString()));
13154 break; 14140 break;
14141 case ScriptBaseClass.OBJECT_CLICK_ACTION:
14142 ret.Add(new LSL_Integer(obj.ClickAction));
14143 break;
14144 case ScriptBaseClass.OBJECT_OMEGA:
14145 ret.Add(new LSL_Vector(obj.AngularVelocity));
14146 break;
14147 case ScriptBaseClass.OBJECT_PRIM_COUNT:
14148 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
14149 break;
14150 case ScriptBaseClass.OBJECT_TOTAL_INVENTORY_COUNT:
14151 SceneObjectPart[] parts = obj.ParentGroup.Parts;
14152 int nparts = parts.Count();
14153 int count = 0;
14154 for(int i = 0; i < nparts; i++)
14155 count += parts[i].Inventory.Count;
14156 ret.Add(new LSL_Integer(count));
14157 break;
14158 case ScriptBaseClass.OBJECT_REZZER_KEY:
14159 ret.Add(new LSL_Key(obj.ParentGroup.RezzerID.ToString()));
14160 break;
14161 case ScriptBaseClass.OBJECT_GROUP_TAG:
14162 ret.Add(new LSL_String(String.Empty));
14163 break;
14164 case ScriptBaseClass.OBJECT_TEMP_ATTACHED:
14165 if (obj.ParentGroup.AttachmentPoint != 0 && obj.ParentGroup.FromItemID == UUID.Zero)
14166 {
14167 ret.Add(new LSL_Integer(1));
14168 }
14169 else
14170 {
14171 ret.Add(new LSL_Integer(0));
14172 }
14173 break;
13155 default: 14174 default:
13156 // Invalid or unhandled constant. 14175 // Invalid or unhandled constant.
13157 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 14176 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
@@ -13286,6 +14305,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13286 { 14305 {
13287 AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(assetID).ToString()); 14306 AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(assetID).ToString());
13288 14307
14308 ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines);
13289 return tid.ToString(); 14309 return tid.ToString();
13290 } 14310 }
13291 14311
@@ -13301,6 +14321,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13301 AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(id).ToString()); 14321 AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(id).ToString());
13302 }); 14322 });
13303 14323
14324 ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines);
13304 return tid.ToString(); 14325 return tid.ToString();
13305 } 14326 }
13306 14327
@@ -13336,6 +14357,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13336 AsyncCommands.DataserverPlugin.DataserverReply( 14357 AsyncCommands.DataserverPlugin.DataserverReply(
13337 reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); 14358 reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
13338 14359
14360 ScriptSleep(m_sleepMsOnGetNotecardLine);
13339 return tid.ToString(); 14361 return tid.ToString();
13340 } 14362 }
13341 14363
@@ -13354,6 +14376,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13354 reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); 14376 reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
13355 }); 14377 });
13356 14378
14379 ScriptSleep(m_sleepMsOnGetNotecardLine);
13357 return tid.ToString(); 14380 return tid.ToString();
13358 } 14381 }
13359 14382
@@ -13371,12 +14394,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13371 14394
13372 public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) 14395 public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
13373 { 14396 {
13374 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 14397 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
14398
14399 LSL_List result = new LSL_List();
13375 14400
13376 if (obj != null && obj.OwnerID == m_host.OwnerID) 14401 if (obj != null && obj.OwnerID == m_host.OwnerID)
13377 return GetEntityParams(obj, rules); 14402 {
14403 LSL_List remaining = GetPrimParams(obj, rules, ref result);
13378 14404
13379 return new LSL_List(); 14405 while (remaining.Length > 2)
14406 {
14407 int linknumber = remaining.GetLSLIntegerItem(0);
14408 rules = remaining.GetSublist(1, -1);
14409 List<SceneObjectPart> parts = GetLinkParts(linknumber);
14410
14411 foreach (SceneObjectPart part in parts)
14412 remaining = GetPrimParams(part, rules, ref result);
14413 }
14414 }
14415
14416 return result;
13380 } 14417 }
13381 14418
13382 public void print(string str) 14419 public void print(string str)
@@ -13390,6 +14427,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13390 } 14427 }
13391 } 14428 }
13392 14429
14430 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
14431 {
14432 List<SceneObjectPart> parts = GetLinkParts(link);
14433 if (parts.Count < 1)
14434 return 0;
14435
14436 return GetNumberOfSides(parts[0]);
14437 }
14438
13393 private string Name2Username(string name) 14439 private string Name2Username(string name)
13394 { 14440 {
13395 string[] parts = name.Split(new char[] {' '}); 14441 string[] parts = name.Split(new char[] {' '});
@@ -13432,7 +14478,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13432 14478
13433 return rq.ToString(); 14479 return rq.ToString();
13434 } 14480 }
13435 14481/*
14482 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
14483 {
14484 m_SayShoutCount = 0;
14485 }
14486*/
13436 private struct Tri 14487 private struct Tri
13437 { 14488 {
13438 public Vector3 p1; 14489 public Vector3 p1;
@@ -13453,18 +14504,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13453 return false; 14504 return false;
13454 } 14505 }
13455 14506
13456 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd) 14507 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd, bool skipPhys)
13457 { 14508 {
13458 List<ContactResult> contacts = new List<ContactResult>(); 14509 List<ContactResult> contacts = new List<ContactResult>();
13459 14510
13460 Vector3 ab = rayEnd - rayStart; 14511 Vector3 ab = rayEnd - rayStart;
14512 float ablen = ab.Length();
13461 14513
13462 World.ForEachScenePresence(delegate(ScenePresence sp) 14514 World.ForEachScenePresence(delegate(ScenePresence sp)
13463 { 14515 {
14516 if(skipPhys && sp.PhysicsActor != null)
14517 return;
14518
13464 Vector3 ac = sp.AbsolutePosition - rayStart; 14519 Vector3 ac = sp.AbsolutePosition - rayStart;
13465// Vector3 bc = sp.AbsolutePosition - rayEnd;
13466 14520
13467 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); 14521 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / ablen);
13468 14522
13469 if (d > 1.5) 14523 if (d > 1.5)
13470 return; 14524 return;
@@ -13581,9 +14635,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13581 14635
13582 ContactResult result = new ContactResult (); 14636 ContactResult result = new ContactResult ();
13583 result.ConsumerID = group.LocalId; 14637 result.ConsumerID = group.LocalId;
13584 result.Depth = intersection.distance; 14638// result.Depth = intersection.distance;
13585 result.Normal = intersection.normal; 14639 result.Normal = intersection.normal;
13586 result.Pos = intersection.ipoint; 14640 result.Pos = intersection.ipoint;
14641 result.Depth = Vector3.Mag(rayStart - result.Pos);
13587 14642
13588 contacts.Add(result); 14643 contacts.Add(result);
13589 }); 14644 });
@@ -13716,6 +14771,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13716 14771
13717 return contacts[0]; 14772 return contacts[0];
13718 } 14773 }
14774/*
14775 // not done:
14776 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
14777 {
14778 ContactResult[] contacts = null;
14779 World.ForEachSOG(delegate(SceneObjectGroup group)
14780 {
14781 if (m_host.ParentGroup == group)
14782 return;
14783
14784 if (group.IsAttachment)
14785 return;
14786
14787 if(group.RootPart.PhysActor != null)
14788 return;
14789
14790 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
14791 });
14792 return contacts;
14793 }
14794*/
13719 14795
13720 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 14796 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
13721 { 14797 {
@@ -13731,7 +14807,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13731 Vector3 rayEnd = end; 14807 Vector3 rayEnd = end;
13732 Vector3 dir = rayEnd - rayStart; 14808 Vector3 dir = rayEnd - rayStart;
13733 14809
13734 float dist = Vector3.Mag(dir); 14810 float dist = dir.Length();
13735 14811
13736 int count = 1; 14812 int count = 1;
13737 bool detectPhantom = false; 14813 bool detectPhantom = false;
@@ -13760,17 +14836,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13760 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 14836 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
13761 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 14837 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
13762 14838
13763
13764 if (World.SupportsRayCastFiltered()) 14839 if (World.SupportsRayCastFiltered())
13765 { 14840 {
13766 if (dist == 0) 14841 if (dist == 0)
13767 return list; 14842 return list;
13768 14843
13769 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull; 14844 RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull;
13770 if (checkTerrain) 14845 if (checkTerrain)
13771 rayfilter |= RayFilterFlags.land; 14846 rayfilter |= RayFilterFlags.land;
13772// if (checkAgents) 14847 if (checkAgents)
13773// rayfilter |= RayFilterFlags.agent; 14848 rayfilter |= RayFilterFlags.agent;
13774 if (checkPhysical) 14849 if (checkPhysical)
13775 rayfilter |= RayFilterFlags.physical; 14850 rayfilter |= RayFilterFlags.physical;
13776 if (checkNonPhysical) 14851 if (checkNonPhysical)
@@ -13796,16 +14871,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13796 14871
13797 if (physresults == null) 14872 if (physresults == null)
13798 { 14873 {
13799 list.Add(new LSL_Integer(-3)); // timeout error 14874// list.Add(new LSL_Integer(-3)); // timeout error
13800 return list; 14875// return list;
14876 results = new List<ContactResult>();
13801 } 14877 }
13802 14878 else
13803 results = (List<ContactResult>)physresults; 14879 results = (List<ContactResult>)physresults;
13804 14880
13805 // for now physics doesn't detect sitted avatars so do it outside physics 14881 // for now physics doesn't detect sitted avatars so do it outside physics
13806 if (checkAgents) 14882 if (checkAgents)
13807 { 14883 {
13808 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); 14884 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd, true);
13809 foreach (ContactResult r in agentHits) 14885 foreach (ContactResult r in agentHits)
13810 results.Add(r); 14886 results.Add(r);
13811 } 14887 }
@@ -13821,12 +14897,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13821 foreach (ContactResult r in objectHits) 14897 foreach (ContactResult r in objectHits)
13822 results.Add(r); 14898 results.Add(r);
13823 } 14899 }
14900 // Double check this because of current ODE distance problems
14901 if (checkTerrain && dist > 60)
14902 {
14903 bool skipGroundCheck = false;
14904
14905 foreach (ContactResult c in results)
14906 {
14907 if (c.ConsumerID == 0) // Physics gave us a ground collision
14908 skipGroundCheck = true;
14909 }
14910
14911 if (!skipGroundCheck)
14912 {
14913 float tmp = dir.X * dir.X + dir.Y * dir.Y;
14914 if(tmp > 2500)
14915 {
14916 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
14917 if (groundContact != null)
14918 results.Add((ContactResult)groundContact);
14919 }
14920 }
14921 }
13824 } 14922 }
13825 else 14923 else
13826 { 14924 {
13827 if (checkAgents) 14925 if (checkAgents)
13828 { 14926 {
13829 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); 14927 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd, false);
13830 foreach (ContactResult r in agentHits) 14928 foreach (ContactResult r in agentHits)
13831 results.Add(r); 14929 results.Add(r);
13832 } 14930 }
@@ -13841,13 +14939,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13841 results.Add(objectHits[iter]); 14939 results.Add(objectHits[iter]);
13842 } 14940 }
13843 } 14941 }
13844 }
13845 14942
13846 if (checkTerrain) 14943 if (checkTerrain)
13847 { 14944 {
13848 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); 14945 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
13849 if (groundContact != null) 14946 if (groundContact != null)
13850 results.Add((ContactResult)groundContact); 14947 results.Add((ContactResult)groundContact);
14948 }
13851 } 14949 }
13852 14950
13853 results.Sort(delegate(ContactResult a, ContactResult b) 14951 results.Sort(delegate(ContactResult a, ContactResult b)
@@ -13908,10 +15006,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13908 } 15006 }
13909 15007
13910 list.Add(new LSL_Integer(values)); 15008 list.Add(new LSL_Integer(values));
13911
13912 return list; 15009 return list;
13913 } 15010 }
13914 15011
15012
13915 /// <summary> 15013 /// <summary>
13916 /// Implementation of llCastRay similar to SL 2015-04-21. 15014 /// Implementation of llCastRay similar to SL 2015-04-21.
13917 /// http://wiki.secondlife.com/wiki/LlCastRay 15015 /// http://wiki.secondlife.com/wiki/LlCastRay
@@ -13935,7 +15033,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13935 UUID userId = UUID.Zero; 15033 UUID userId = UUID.Zero;
13936 int msAvailable = 0; 15034 int msAvailable = 0;
13937 // Throttle per owner when attachment or "vehicle" (sat upon) 15035 // Throttle per owner when attachment or "vehicle" (sat upon)
13938 if (m_host.ParentGroup.IsAttachment || m_host.ParentGroup.GetSittingAvatars().Count > 0) 15036 if (m_host.ParentGroup.IsAttachment || m_host.ParentGroup.GetSittingAvatarsCount() > 0)
13939 { 15037 {
13940 userId = m_host.OwnerID; 15038 userId = m_host.OwnerID;
13941 msAvailable = m_msPerAvatarInCastRay; 15039 msAvailable = m_msPerAvatarInCastRay;
@@ -13968,13 +15066,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13968 msAvailable -= m_castRayCalls[i].UsedMs; 15066 msAvailable -= m_castRayCalls[i].UsedMs;
13969 } 15067 }
13970 } 15068 }
13971 }
13972 15069
13973 // Return failure if not enough available time 15070 // Return failure if not enough available time
13974 if (msAvailable < m_msMinInCastRay) 15071 if (msAvailable < m_msMinInCastRay)
13975 { 15072 {
13976 result.Add(new LSL_Integer(ScriptBaseClass.RCERR_CAST_TIME_EXCEEDED)); 15073 result.Add(new LSL_Integer(ScriptBaseClass.RCERR_CAST_TIME_EXCEEDED));
13977 return result; 15074 return result;
15075 }
13978 } 15076 }
13979 15077
13980 // Initialize 15078 // Initialize
@@ -13987,7 +15085,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13987 int rejectTypes = 0; 15085 int rejectTypes = 0;
13988 int dataFlags = 0; 15086 int dataFlags = 0;
13989 int maxHits = 1; 15087 int maxHits = 1;
13990 bool detectPhantom = false; 15088 bool notdetectPhantom = true;
13991 for (int i = 0; i < options.Length; i += 2) 15089 for (int i = 0; i < options.Length; i += 2)
13992 { 15090 {
13993 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 15091 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
@@ -13997,7 +15095,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13997 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 15095 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
13998 maxHits = options.GetLSLIntegerItem(i + 1); 15096 maxHits = options.GetLSLIntegerItem(i + 1);
13999 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 15097 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
14000 detectPhantom = (options.GetLSLIntegerItem(i + 1) != 0); 15098 notdetectPhantom = (options.GetLSLIntegerItem(i + 1) == 0);
14001 } 15099 }
14002 if (maxHits > m_maxHitsInCastRay) 15100 if (maxHits > m_maxHitsInCastRay)
14003 maxHits = m_maxHitsInCastRay; 15101 maxHits = m_maxHitsInCastRay;
@@ -14027,157 +15125,153 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14027 World.ForEachSOG( 15125 World.ForEachSOG(
14028 delegate(SceneObjectGroup group) 15126 delegate(SceneObjectGroup group)
14029 { 15127 {
15128 if(group.IsDeleted || group.RootPart == null)
15129 return;
14030 // Check group filters unless part filters are configured 15130 // Check group filters unless part filters are configured
14031 bool isPhysical = (group.RootPart != null && group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical); 15131 bool isPhysical = (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical);
14032 bool isNonphysical = !isPhysical; 15132 bool isNonphysical = !isPhysical;
14033 bool isPhantom = group.IsPhantom || group.IsVolumeDetect; 15133 bool isPhantom = group.IsPhantom || group.IsVolumeDetect;
14034 bool isAttachment = group.IsAttachment; 15134 bool isAttachment = group.IsAttachment;
14035 bool doGroup = true;
14036 if (isPhysical && rejectPhysical) 15135 if (isPhysical && rejectPhysical)
14037 doGroup = false; 15136 return;
14038 if (isNonphysical && rejectNonphysical) 15137 if (isNonphysical && rejectNonphysical)
14039 doGroup = false; 15138 return;
14040 if (isPhantom && detectPhantom) 15139 if (isPhantom && notdetectPhantom)
14041 doGroup = true; 15140 return;
14042 if (m_filterPartsInCastRay)
14043 doGroup = true;
14044 if (isAttachment && !m_doAttachmentsInCastRay) 15141 if (isAttachment && !m_doAttachmentsInCastRay)
14045 doGroup = false; 15142 return;
15143
14046 // Parse object/group if passed filters 15144 // Parse object/group if passed filters
14047 if (doGroup) 15145 // Iterate over all prims/parts in object/group
15146 foreach(SceneObjectPart part in group.Parts)
14048 { 15147 {
14049 // Iterate over all prims/parts in object/group 15148 // ignore PhysicsShapeType.None as physics engines do
14050 foreach(SceneObjectPart part in group.Parts) 15149 // or we will get into trouble in future
15150 if(part.PhysicsShapeType == (byte)PhysicsShapeType.None)
15151 continue;
15152 isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical);
15153 isNonphysical = !isPhysical;
15154 isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) ||
15155 (part.VolumeDetectActive);
15156
15157 if (isPhysical && rejectPhysical)
15158 continue;
15159 if (isNonphysical && rejectNonphysical)
15160 continue;
15161 if (isPhantom && notdetectPhantom)
15162 continue;
15163
15164 // Parse prim/part and project ray if passed filters
15165 Vector3 scalePart = part.Scale;
15166 Vector3 posPart = part.GetWorldPosition();
15167 Quaternion rotPart = part.GetWorldRotation();
15168 Quaternion rotPartInv = Quaternion.Inverse(rotPart);
15169 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
15170 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
15171
15172 // Filter parts by shape bounding boxes
15173 Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f);
15174 if (!part.Shape.SculptEntry)
15175 shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ));
15176 shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol));
15177 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
14051 { 15178 {
14052 // Check part filters if configured 15179 // Prepare data needed to check for ray hits
14053 if (m_filterPartsInCastRay) 15180 RayTrans rayTrans = new RayTrans();
14054 { 15181 rayTrans.PartId = part.UUID;
14055 isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical); 15182 rayTrans.GroupId = part.ParentGroup.UUID;
14056 isNonphysical = !isPhysical; 15183 rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0;
14057 isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) || (part.VolumeDetectActive); 15184 rayTrans.ScalePart = scalePart;
14058 bool doPart = true; 15185 rayTrans.PositionPart = posPart;
14059 if (isPhysical && rejectPhysical) 15186 rayTrans.RotationPart = rotPart;
14060 doPart = false; 15187 rayTrans.ShapeNeedsEnds = true;
14061 if (isNonphysical && rejectNonphysical) 15188 rayTrans.Position1Ray = pos1Ray;
14062 doPart = false; 15189 rayTrans.Position1RayProj = pos1RayProj;
14063 if (isPhantom && detectPhantom) 15190 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
14064 doPart = true; 15191
14065 if (!doPart) 15192 // Get detail level depending on type
14066 continue; 15193 int lod = 0;
14067 } 15194 // Mesh detail level
14068 15195 if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
14069 // Parse prim/part and project ray if passed filters 15196 lod = (int)m_meshLodInCastRay;
14070 Vector3 scalePart = part.Scale; 15197 // Sculpt detail level
14071 Vector3 posPart = part.GetWorldPosition(); 15198 else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
14072 Quaternion rotPart = part.GetWorldRotation(); 15199 lod = (int)m_sculptLodInCastRay;
14073 Quaternion rotPartInv = Quaternion.Inverse(rotPart); 15200 // Shape detail level
14074 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; 15201 else if (!part.Shape.SculptEntry)
14075 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; 15202 lod = (int)m_primLodInCastRay;
14076 15203
14077 // Filter parts by shape bounding boxes 15204 // Try to get cached mesh if configured
14078 Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f); 15205 ulong meshKey = 0;
14079 if (!part.Shape.SculptEntry) 15206 FacetedMesh mesh = null;
14080 shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ)); 15207 if (m_useMeshCacheInCastRay)
14081 shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol)); 15208 {
14082 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) 15209 meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod));
14083 { 15210 lock (m_cachedMeshes)
14084 // Prepare data needed to check for ray hits
14085 RayTrans rayTrans = new RayTrans();
14086 rayTrans.PartId = part.UUID;
14087 rayTrans.GroupId = part.ParentGroup.UUID;
14088 rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0;
14089 rayTrans.ScalePart = scalePart;
14090 rayTrans.PositionPart = posPart;
14091 rayTrans.RotationPart = rotPart;
14092 rayTrans.ShapeNeedsEnds = true;
14093 rayTrans.Position1Ray = pos1Ray;
14094 rayTrans.Position1RayProj = pos1RayProj;
14095 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
14096
14097 // Get detail level depending on type
14098 int lod = 0;
14099 // Mesh detail level
14100 if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
14101 lod = (int)m_meshLodInCastRay;
14102 // Sculpt detail level
14103 else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
14104 lod = (int)m_sculptLodInCastRay;
14105 // Shape detail level
14106 else if (!part.Shape.SculptEntry)
14107 lod = (int)m_primLodInCastRay;
14108
14109 // Try to get cached mesh if configured
14110 ulong meshKey = 0;
14111 FacetedMesh mesh = null;
14112 if (m_useMeshCacheInCastRay)
14113 { 15211 {
14114 meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod)); 15212 m_cachedMeshes.TryGetValue(meshKey, out mesh);
14115 lock (m_cachedMeshes)
14116 {
14117 m_cachedMeshes.TryGetValue(meshKey, out mesh);
14118 }
14119 } 15213 }
15214 }
14120 15215
14121 // Create mesh if no cached mesh 15216 // Create mesh if no cached mesh
14122 if (mesh == null) 15217 if (mesh == null)
15218 {
15219 // Make an OMV prim to be able to mesh part
15220 Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart);
15221 byte[] sculptAsset = null;
15222 if (omvPrim.Sculpt != null)
15223 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
15224
15225 // When part is mesh, get mesh
15226 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
14123 { 15227 {
14124 // Make an OMV prim to be able to mesh part 15228 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
14125 Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); 15229 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh);
14126 byte[] sculptAsset = null; 15230 meshAsset = null;
14127 if (omvPrim.Sculpt != null) 15231 }
14128 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
14129
14130 // When part is mesh, get mesh
14131 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
14132 {
14133 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
14134 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh);
14135 meshAsset = null;
14136 }
14137 15232
14138 // When part is sculpt, create mesh 15233 // When part is sculpt, create mesh
14139 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. 15234 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
14140 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) 15235 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
15236 {
15237 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>();
15238 if (imgDecoder != null)
14141 { 15239 {
14142 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); 15240 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
14143 if (imgDecoder != null) 15241 if (sculpt != null)
14144 { 15242 {
14145 Image sculpt = imgDecoder.DecodeToImage(sculptAsset); 15243 mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay);
14146 if (sculpt != null) 15244 sculpt.Dispose();
14147 {
14148 mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay);
14149 sculpt.Dispose();
14150 }
14151 } 15245 }
14152 }
14153
14154 // When part is shape, create mesh
14155 else if (omvPrim.Sculpt == null)
14156 {
14157 if (
14158 omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 &&
14159 omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 &&
14160 omvPrim.PrimData.PathSkew == 0.0 &&
14161 omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0
14162 )
14163 rayTrans.ShapeNeedsEnds = false;
14164 mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay);
14165 } 15246 }
15247 }
14166 15248
14167 // Cache mesh if configured 15249 // When part is shape, create mesh
14168 if (m_useMeshCacheInCastRay && mesh != null) 15250 else if (omvPrim.Sculpt == null)
15251 {
15252 if (
15253 omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 &&
15254 omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 &&
15255 omvPrim.PrimData.PathSkew == 0.0 &&
15256 omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0
15257 )
15258 rayTrans.ShapeNeedsEnds = false;
15259 mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay);
15260 }
15261
15262 // Cache mesh if configured
15263 if (m_useMeshCacheInCastRay && mesh != null)
15264 {
15265 lock(m_cachedMeshes)
14169 { 15266 {
14170 lock(m_cachedMeshes) 15267 if (!m_cachedMeshes.ContainsKey(meshKey))
14171 { 15268 m_cachedMeshes.Add(meshKey, mesh);
14172 if (!m_cachedMeshes.ContainsKey(meshKey))
14173 m_cachedMeshes.Add(meshKey, mesh);
14174 }
14175 } 15269 }
14176 } 15270 }
14177 // Check mesh for ray hits
14178 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
14179 mesh = null;
14180 } 15271 }
15272 // Check mesh for ray hits
15273 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
15274 mesh = null;
14181 } 15275 }
14182 } 15276 }
14183 } 15277 }
@@ -14362,13 +15456,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14362 15456
14363 // Add to throttle data 15457 // Add to throttle data
14364 stopWatch.Stop(); 15458 stopWatch.Stop();
14365 CastRayCall castRayCall = new CastRayCall();
14366 castRayCall.RegionId = regionId;
14367 castRayCall.UserId = userId;
14368 castRayCall.CalledMs = calledMs;
14369 castRayCall.UsedMs = (int)stopWatch.ElapsedMilliseconds;
14370 lock (m_castRayCalls) 15459 lock (m_castRayCalls)
14371 { 15460 {
15461 CastRayCall castRayCall = new CastRayCall();
15462 castRayCall.RegionId = regionId;
15463 castRayCall.UserId = userId;
15464 castRayCall.CalledMs = calledMs;
15465 castRayCall.UsedMs = (int)stopWatch.ElapsedMilliseconds;
14372 m_castRayCalls.Add(castRayCall); 15466 m_castRayCalls.Add(castRayCall);
14373 } 15467 }
14374 15468
@@ -14813,7 +15907,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14813 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 15907 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
14814 if (!isAccount) return 0; 15908 if (!isAccount) return 0;
14815 if (estate.HasAccess(id)) return 1; 15909 if (estate.HasAccess(id)) return 1;
14816 if (estate.IsBanned(id)) 15910 if (estate.IsBanned(id, World.GetUserFlags(id)))
14817 estate.RemoveBan(id); 15911 estate.RemoveBan(id);
14818 estate.AddEstateUser(id); 15912 estate.AddEstateUser(id);
14819 break; 15913 break;
@@ -14832,14 +15926,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14832 break; 15926 break;
14833 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 15927 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
14834 if (!isAccount) return 0; 15928 if (!isAccount) return 0;
14835 if (estate.IsBanned(id)) return 1; 15929 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
14836 EstateBan ban = new EstateBan(); 15930 EstateBan ban = new EstateBan();
14837 ban.EstateID = estate.EstateID; 15931 ban.EstateID = estate.EstateID;
14838 ban.BannedUserID = id; 15932 ban.BannedUserID = id;
14839 estate.AddBan(ban); 15933 estate.AddBan(ban);
14840 break; 15934 break;
14841 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 15935 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
14842 if (!isAccount || !estate.IsBanned(id)) return 0; 15936 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
14843 estate.RemoveBan(id); 15937 estate.RemoveBan(id);
14844 break; 15938 break;
14845 default: return 0; 15939 default: return 0;
@@ -14898,13 +15992,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14898 public void llCollisionSprite(string impact_sprite) 15992 public void llCollisionSprite(string impact_sprite)
14899 { 15993 {
14900 m_host.AddScriptLPS(1); 15994 m_host.AddScriptLPS(1);
14901 NotImplemented("llCollisionSprite"); 15995 // Viewer 2.0 broke this and it's likely LL has no intention
15996 // of fixing it. Therefore, letting this be a NOP seems appropriate.
14902 } 15997 }
14903 15998
14904 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 15999 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
14905 { 16000 {
14906 m_host.AddScriptLPS(1); 16001 m_host.AddScriptLPS(1);
14907 NotImplemented("llGodLikeRezObject"); 16002
16003 if (!World.Permissions.IsGod(m_host.OwnerID))
16004 NotImplemented("llGodLikeRezObject");
16005
16006 AssetBase rezAsset = World.AssetService.Get(inventory);
16007 if (rezAsset == null)
16008 {
16009 llSay(0, "Asset not found");
16010 return;
16011 }
16012
16013 SceneObjectGroup group = null;
16014
16015 try
16016 {
16017 string xmlData = Utils.BytesToString(rezAsset.Data);
16018 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
16019 }
16020 catch
16021 {
16022 llSay(0, "Asset not found");
16023 return;
16024 }
16025
16026 if (group == null)
16027 {
16028 llSay(0, "Asset not found");
16029 return;
16030 }
16031
16032 group.RootPart.AttachedPos = group.AbsolutePosition;
16033
16034 group.ResetIDs();
16035
16036 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
16037 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
16038 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
16039 group.ScheduleGroupForFullUpdate();
16040
16041 // objects rezzed with this method are die_at_edge by default.
16042 group.RootPart.SetDieAtEdge(true);
16043
16044 group.ResumeScripts();
16045
16046 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
16047 "object_rez", new Object[] {
16048 new LSL_String(
16049 group.RootPart.UUID.ToString()) },
16050 new DetectParams[0]));
14908 } 16051 }
14909 16052
14910 public LSL_String llTransferLindenDollars(string destination, int amount) 16053 public LSL_String llTransferLindenDollars(string destination, int amount)
@@ -14918,6 +16061,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14918 16061
14919 try 16062 try
14920 { 16063 {
16064 if (amount <= 0)
16065 {
16066 replydata = "INVALID_AMOUNT";
16067 return;
16068 }
16069
14921 TaskInventoryItem item = m_item; 16070 TaskInventoryItem item = m_item;
14922 if (item == null) 16071 if (item == null)
14923 { 16072 {
@@ -14925,6 +16074,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14925 return; 16074 return;
14926 } 16075 }
14927 16076
16077 if (m_host.OwnerID == m_host.GroupID)
16078 {
16079 replydata = "GROUP_OWNED";
16080 return;
16081 }
16082
14928 m_host.AddScriptLPS(1); 16083 m_host.AddScriptLPS(1);
14929 16084
14930 if (item.PermsGranter == UUID.Zero) 16085 if (item.PermsGranter == UUID.Zero)
@@ -14947,6 +16102,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14947 return; 16102 return;
14948 } 16103 }
14949 16104
16105 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, toID);
16106 if (account == null)
16107 {
16108 replydata = "LINDENDOLLAR_ENTITYDOESNOTEXIST";
16109 return;
16110 }
16111
14950 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>(); 16112 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
14951 16113
14952 if (money == null) 16114 if (money == null)
@@ -14955,8 +16117,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14955 return; 16117 return;
14956 } 16118 }
14957 16119
14958 bool result = money.ObjectGiveMoney( 16120 string reason;
14959 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 16121 bool result = money.ObjectGiveMoney( m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount, txn, out reason);
14960 16122
14961 if (result) 16123 if (result)
14962 { 16124 {
@@ -14964,7 +16126,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14964 return; 16126 return;
14965 } 16127 }
14966 16128
14967 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS"; 16129 replydata = reason;
14968 } 16130 }
14969 finally 16131 finally
14970 { 16132 {
@@ -14981,6 +16143,1366 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14981 } 16143 }
14982 16144
14983 #endregion 16145 #endregion
16146
16147
16148 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed)
16149 {
16150 //This is a special version of SetPrimParams to deal with avatars which are sitting on the linkset.
16151
16152 int idx = 0;
16153 int idxStart = 0;
16154
16155 bool positionChanged = false;
16156 try
16157 {
16158 while (idx < rules.Length)
16159 {
16160 ++rulesParsed;
16161 int code = rules.GetLSLIntegerItem(idx++);
16162
16163 int remain = rules.Length - idx;
16164 idxStart = idx;
16165
16166 switch (code)
16167 {
16168 case (int)ScriptBaseClass.PRIM_POSITION:
16169 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
16170 {
16171 if (remain < 1)
16172 return new LSL_List();
16173
16174 LSL_Vector v;
16175 v = rules.GetVector3Item(idx++);
16176
16177 if(!av.LegacySitOffsets)
16178 {
16179 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
16180
16181 v = v + 2 * sitOffset;
16182 }
16183
16184 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
16185 positionChanged = true;
16186 }
16187 break;
16188
16189 case (int)ScriptBaseClass.PRIM_ROTATION:
16190 {
16191 if (remain < 1)
16192 return new LSL_List();
16193
16194 Quaternion r;
16195 r = rules.GetQuaternionItem(idx++);
16196
16197 av.Rotation = m_host.GetWorldRotation() * r;
16198 positionChanged = true;
16199 }
16200 break;
16201
16202 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
16203 {
16204 if (remain < 1)
16205 return new LSL_List();
16206
16207 LSL_Rotation r;
16208 r = rules.GetQuaternionItem(idx++);
16209
16210 av.Rotation = r;
16211 positionChanged = true;
16212 }
16213 break;
16214
16215 // parse rest doing nothing but number of parameters error check
16216 case (int)ScriptBaseClass.PRIM_SIZE:
16217 case (int)ScriptBaseClass.PRIM_MATERIAL:
16218 case (int)ScriptBaseClass.PRIM_PHANTOM:
16219 case (int)ScriptBaseClass.PRIM_PHYSICS:
16220 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
16221 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
16222 case (int)ScriptBaseClass.PRIM_NAME:
16223 case (int)ScriptBaseClass.PRIM_DESC:
16224 if (remain < 1)
16225 return new LSL_List();
16226 idx++;
16227 break;
16228
16229 case (int)ScriptBaseClass.PRIM_GLOW:
16230 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
16231 case (int)ScriptBaseClass.PRIM_TEXGEN:
16232 if (remain < 2)
16233 return new LSL_List();
16234 idx += 2;
16235 break;
16236
16237 case (int)ScriptBaseClass.PRIM_TYPE:
16238 if (remain < 3)
16239 return new LSL_List();
16240 code = (int)rules.GetLSLIntegerItem(idx++);
16241 remain = rules.Length - idx;
16242 switch (code)
16243 {
16244 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
16245 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
16246 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
16247 if (remain < 6)
16248 return new LSL_List();
16249 idx += 6;
16250 break;
16251
16252 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
16253 if (remain < 5)
16254 return new LSL_List();
16255 idx += 5;
16256 break;
16257
16258 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
16259 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
16260 case (int)ScriptBaseClass.PRIM_TYPE_RING:
16261 if (remain < 11)
16262 return new LSL_List();
16263 idx += 11;
16264 break;
16265
16266 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
16267 if (remain < 2)
16268 return new LSL_List();
16269 idx += 2;
16270 break;
16271 }
16272 break;
16273
16274 case (int)ScriptBaseClass.PRIM_COLOR:
16275 case (int)ScriptBaseClass.PRIM_TEXT:
16276 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
16277 case (int)ScriptBaseClass.PRIM_OMEGA:
16278 case (int)ScriptBaseClass.PRIM_SIT_TARGET:
16279 if (remain < 3)
16280 return new LSL_List();
16281 idx += 3;
16282 break;
16283
16284 case (int)ScriptBaseClass.PRIM_TEXTURE:
16285 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
16286 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
16287 if (remain < 5)
16288 return new LSL_List();
16289 idx += 5;
16290 break;
16291
16292 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
16293 if (remain < 7)
16294 return new LSL_List();
16295
16296 idx += 7;
16297 break;
16298
16299 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
16300 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
16301 return new LSL_List();
16302
16303 return rules.GetSublist(idx, -1);
16304 }
16305 }
16306 }
16307 catch (InvalidCastException e)
16308 {
16309 Error(originFunc,string.Format(
16310 " error running rule #{0}: arg #{1} {2}",
16311 rulesParsed, idx - idxStart, e.Message));
16312 }
16313 finally
16314 {
16315 if (positionChanged)
16316 av.SendTerseUpdateToAllClients();
16317 }
16318 return new LSL_List();
16319 }
16320
16321 public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res)
16322 {
16323 // avatars case
16324 // replies as SL wiki
16325
16326// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
16327 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
16328
16329 int idx = 0;
16330 while (idx < rules.Length)
16331 {
16332 int code = (int)rules.GetLSLIntegerItem(idx++);
16333 int remain = rules.Length - idx;
16334
16335 switch (code)
16336 {
16337 case (int)ScriptBaseClass.PRIM_MATERIAL:
16338 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
16339 break;
16340
16341 case (int)ScriptBaseClass.PRIM_PHYSICS:
16342 res.Add(new LSL_Integer(0));
16343 break;
16344
16345 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
16346 res.Add(new LSL_Integer(0));
16347 break;
16348
16349 case (int)ScriptBaseClass.PRIM_PHANTOM:
16350 res.Add(new LSL_Integer(0));
16351 break;
16352
16353 case (int)ScriptBaseClass.PRIM_POSITION:
16354 Vector3 pos;
16355
16356 if (sitPart.ParentGroup.RootPart != null)
16357 {
16358 pos = avatar.OffsetPosition;
16359
16360 if(!avatar.LegacySitOffsets)
16361 {
16362 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
16363 pos -= sitOffset;
16364 }
16365
16366 SceneObjectPart sitroot = sitPart.ParentGroup.RootPart;
16367 pos = sitroot.AbsolutePosition + pos * sitroot.GetWorldRotation();
16368 }
16369 else
16370 pos = avatar.AbsolutePosition;
16371
16372 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
16373 break;
16374
16375 case (int)ScriptBaseClass.PRIM_SIZE:
16376 Vector3 s = avatar.Appearance.AvatarSize;
16377 res.Add(new LSL_Vector(s.X, s.Y, s.Z));
16378
16379 break;
16380
16381 case (int)ScriptBaseClass.PRIM_ROTATION:
16382 res.Add(new LSL_Rotation(avatar.GetWorldRotation()));
16383 break;
16384
16385 case (int)ScriptBaseClass.PRIM_TYPE:
16386 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
16387 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
16388 res.Add(new LSL_Vector(0f,1.0f,0f));
16389 res.Add(new LSL_Float(0.0f));
16390 res.Add(new LSL_Vector(0, 0, 0));
16391 res.Add(new LSL_Vector(1.0f,1.0f,0f));
16392 res.Add(new LSL_Vector(0, 0, 0));
16393 break;
16394
16395 case (int)ScriptBaseClass.PRIM_TEXTURE:
16396 if (remain < 1)
16397 return new LSL_List();
16398
16399 int face = (int)rules.GetLSLIntegerItem(idx++);
16400 if (face == ScriptBaseClass.ALL_SIDES)
16401 {
16402 for (face = 0; face < 21; face++)
16403 {
16404 res.Add(new LSL_String(""));
16405 res.Add(new LSL_Vector(0,0,0));
16406 res.Add(new LSL_Vector(0,0,0));
16407 res.Add(new LSL_Float(0.0));
16408 }
16409 }
16410 else
16411 {
16412 if (face >= 0 && face < 21)
16413 {
16414 res.Add(new LSL_String(""));
16415 res.Add(new LSL_Vector(0,0,0));
16416 res.Add(new LSL_Vector(0,0,0));
16417 res.Add(new LSL_Float(0.0));
16418 }
16419 }
16420 break;
16421
16422 case (int)ScriptBaseClass.PRIM_COLOR:
16423 if (remain < 1)
16424 return new LSL_List();
16425
16426 face = (int)rules.GetLSLIntegerItem(idx++);
16427
16428 if (face == ScriptBaseClass.ALL_SIDES)
16429 {
16430 for (face = 0; face < 21; face++)
16431 {
16432 res.Add(new LSL_Vector(0,0,0));
16433 res.Add(new LSL_Float(0));
16434 }
16435 }
16436 else
16437 {
16438 res.Add(new LSL_Vector(0,0,0));
16439 res.Add(new LSL_Float(0));
16440 }
16441 break;
16442
16443 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
16444 if (remain < 1)
16445 return new LSL_List();
16446 face = (int)rules.GetLSLIntegerItem(idx++);
16447
16448 if (face == ScriptBaseClass.ALL_SIDES)
16449 {
16450 for (face = 0; face < 21; face++)
16451 {
16452 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
16453 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
16454 }
16455 }
16456 else
16457 {
16458 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
16459 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
16460 }
16461 break;
16462
16463 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
16464 if (remain < 1)
16465 return new LSL_List();
16466 face = (int)rules.GetLSLIntegerItem(idx++);
16467
16468 if (face == ScriptBaseClass.ALL_SIDES)
16469 {
16470 for (face = 0; face < 21; face++)
16471 {
16472 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
16473 }
16474 }
16475 else
16476 {
16477 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
16478 }
16479 break;
16480
16481 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
16482 res.Add(new LSL_Integer(0));
16483 res.Add(new LSL_Integer(0));// softness
16484 res.Add(new LSL_Float(0.0f)); // gravity
16485 res.Add(new LSL_Float(0.0f)); // friction
16486 res.Add(new LSL_Float(0.0f)); // wind
16487 res.Add(new LSL_Float(0.0f)); // tension
16488 res.Add(new LSL_Vector(0f,0f,0f));
16489 break;
16490
16491 case (int)ScriptBaseClass.PRIM_TEXGEN:
16492 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
16493 if (remain < 1)
16494 return new LSL_List();
16495 face = (int)rules.GetLSLIntegerItem(idx++);
16496
16497 if (face == ScriptBaseClass.ALL_SIDES)
16498 {
16499 for (face = 0; face < 21; face++)
16500 {
16501 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
16502 }
16503 }
16504 else
16505 {
16506 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
16507 }
16508 break;
16509
16510 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
16511 res.Add(new LSL_Integer(0));
16512 res.Add(new LSL_Vector(0f,0f,0f));
16513 res.Add(new LSL_Float(0f)); // intensity
16514 res.Add(new LSL_Float(0f)); // radius
16515 res.Add(new LSL_Float(0f)); // falloff
16516 break;
16517
16518 case (int)ScriptBaseClass.PRIM_GLOW:
16519 if (remain < 1)
16520 return new LSL_List();
16521 face = (int)rules.GetLSLIntegerItem(idx++);
16522
16523 if (face == ScriptBaseClass.ALL_SIDES)
16524 {
16525 for (face = 0; face < 21; face++)
16526 {
16527 res.Add(new LSL_Float(0f));
16528 }
16529 }
16530 else
16531 {
16532 res.Add(new LSL_Float(0f));
16533 }
16534 break;
16535
16536 case (int)ScriptBaseClass.PRIM_TEXT:
16537 res.Add(new LSL_String(""));
16538 res.Add(new LSL_Vector(0f,0f,0f));
16539 res.Add(new LSL_Float(1.0f));
16540 break;
16541
16542 case (int)ScriptBaseClass.PRIM_NAME:
16543 res.Add(new LSL_String(avatar.Name));
16544 break;
16545
16546 case (int)ScriptBaseClass.PRIM_DESC:
16547 res.Add(new LSL_String(""));
16548 break;
16549
16550 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
16551 Quaternion lrot = avatar.Rotation;
16552 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
16553 break;
16554
16555 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
16556 Vector3 lpos = avatar.OffsetPosition;
16557
16558 if(!avatar.LegacySitOffsets)
16559 {
16560 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
16561 lpos -= lsitOffset;
16562 }
16563
16564 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
16565 break;
16566
16567 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
16568 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
16569 return new LSL_List();
16570
16571 return rules.GetSublist(idx, -1);
16572 }
16573 }
16574
16575 return new LSL_List();
16576 }
16577
16578 public void llSetAnimationOverride(LSL_String animState, LSL_String anim)
16579 {
16580 string state = String.Empty;
16581
16582 foreach (KeyValuePair<string, string> kvp in MovementAnimationsForLSL)
16583 {
16584 if (kvp.Value.ToLower() == ((string)animState).ToLower())
16585 {
16586 state = kvp.Key;
16587 break;
16588 }
16589 }
16590
16591 if (state == String.Empty)
16592 {
16593 llShout(ScriptBaseClass.DEBUG_CHANNEL, "Invalid animation state " + animState);
16594 return;
16595 }
16596
16597 if (m_item.PermsGranter == UUID.Zero)
16598 {
16599 llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16600 return;
16601 }
16602
16603 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_OVERRIDE_ANIMATIONS) == 0)
16604 {
16605 llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16606 return;
16607 }
16608
16609 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
16610
16611 if (presence == null)
16612 return;
16613
16614 UUID animID;
16615
16616 animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation);
16617
16618 if (animID == UUID.Zero)
16619 {
16620 String animupper = ((string)anim).ToUpperInvariant();
16621 DefaultAvatarAnimations.AnimsUUID.TryGetValue(animupper, out animID);
16622 }
16623
16624 if (animID == UUID.Zero)
16625 {
16626 llShout(ScriptBaseClass.DEBUG_CHANNEL, "Animation not found");
16627 return;
16628 }
16629
16630 presence.SetAnimationOverride(state, animID);
16631 }
16632
16633 public void llResetAnimationOverride(LSL_String animState)
16634 {
16635 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
16636 if (presence == null)
16637 return;
16638
16639 if (m_item.PermsGranter == UUID.Zero)
16640 {
16641 llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16642 return;
16643 }
16644
16645 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_OVERRIDE_ANIMATIONS) == 0)
16646 {
16647 llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16648 return;
16649 }
16650
16651 if (animState == "ALL")
16652 {
16653 presence.SetAnimationOverride("ALL", UUID.Zero);
16654 return;
16655 }
16656
16657 string state = String.Empty;
16658
16659 foreach (KeyValuePair<string, string> kvp in MovementAnimationsForLSL)
16660 {
16661 if (kvp.Value.ToLower() == ((string)animState).ToLower())
16662 {
16663 state = kvp.Key;
16664 break;
16665 }
16666 }
16667
16668 if (state == String.Empty)
16669 {
16670 return;
16671 }
16672
16673 presence.SetAnimationOverride(state, UUID.Zero);
16674 }
16675
16676 public LSL_String llGetAnimationOverride(LSL_String animState)
16677 {
16678 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
16679 if (presence == null)
16680 return String.Empty;
16681
16682 if (m_item.PermsGranter == UUID.Zero)
16683 {
16684 llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16685 return String.Empty;
16686 }
16687
16688 if ((m_item.PermsMask & (ScriptBaseClass.PERMISSION_OVERRIDE_ANIMATIONS | ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION)) == 0)
16689 {
16690 llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16691 return String.Empty;
16692 }
16693
16694 string state = String.Empty;
16695
16696 foreach (KeyValuePair<string, string> kvp in MovementAnimationsForLSL)
16697 {
16698 if (kvp.Value.ToLower() == ((string)animState).ToLower())
16699 {
16700 state = kvp.Key;
16701 break;
16702 }
16703 }
16704
16705 if (state == String.Empty)
16706 {
16707 return String.Empty;
16708 }
16709
16710 UUID animID = presence.GetAnimationOverride(state);
16711 if (animID == UUID.Zero)
16712 return animState;
16713
16714 foreach (KeyValuePair<string, UUID> kvp in DefaultAvatarAnimations.AnimsUUID)
16715 {
16716 if (kvp.Value == animID)
16717 return kvp.Key.ToLower();
16718 }
16719
16720 foreach (TaskInventoryItem item in m_host.Inventory.GetInventoryItems())
16721 {
16722 if (item.AssetID == animID)
16723 return item.Name;
16724 }
16725
16726 return String.Empty;
16727 }
16728
16729 public LSL_List llJson2List(LSL_String json)
16730 {
16731 if(String.IsNullOrEmpty(json))
16732 return new LSL_List();
16733 if(json == "[]")
16734 return new LSL_List();
16735 if(json == "{}")
16736 return new LSL_List();
16737 char first = ((string)json)[0];
16738
16739 if(first != '[' && first !='{')
16740 {
16741 // we already have a single element
16742 LSL_List l = new LSL_List();
16743 l.Add(json);
16744 return l;
16745 }
16746
16747 LitJson.JsonData jsdata;
16748 try
16749 {
16750 jsdata = LitJson.JsonMapper.ToObject(json);
16751 }
16752 catch (Exception e)
16753 {
16754 string m = e.Message; // debug point
16755 return json;
16756 }
16757 try
16758 {
16759 return JsonParseTop(jsdata);
16760 }
16761 catch (Exception e)
16762 {
16763 string m = e.Message; // debug point
16764 return (LSL_String)ScriptBaseClass.JSON_INVALID;
16765 }
16766 }
16767
16768 private LSL_List JsonParseTop(LitJson.JsonData elem)
16769 {
16770 LSL_List retl = new LSL_List();
16771 if(elem == null)
16772 retl.Add((LSL_String)ScriptBaseClass.JSON_NULL);
16773
16774 LitJson.JsonType elemType = elem.GetJsonType();
16775 switch (elemType)
16776 {
16777 case LitJson.JsonType.Int:
16778 retl.Add(new LSL_Integer((int)elem));
16779 return retl;
16780 case LitJson.JsonType.Boolean:
16781 retl.Add((LSL_String)((bool)elem ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE));
16782 return retl;
16783 case LitJson.JsonType.Double:
16784 retl.Add(new LSL_Float((double)elem));
16785 return retl;
16786 case LitJson.JsonType.None:
16787 retl.Add((LSL_String)ScriptBaseClass.JSON_NULL);
16788 return retl;
16789 case LitJson.JsonType.String:
16790 retl.Add(new LSL_String((string)elem));
16791 return retl;
16792 case LitJson.JsonType.Array:
16793 foreach (LitJson.JsonData subelem in elem)
16794 retl.Add(JsonParseTopNodes(subelem));
16795 return retl;
16796 case LitJson.JsonType.Object:
16797 IDictionaryEnumerator e = ((IOrderedDictionary)elem).GetEnumerator();
16798 while (e.MoveNext())
16799 {
16800 retl.Add(new LSL_String((string)e.Key));
16801 retl.Add(JsonParseTopNodes((LitJson.JsonData)e.Value));
16802 }
16803 return retl;
16804 default:
16805 throw new Exception(ScriptBaseClass.JSON_INVALID);
16806 }
16807 }
16808
16809 private object JsonParseTopNodes(LitJson.JsonData elem)
16810 {
16811 if(elem == null)
16812 return ((LSL_String)ScriptBaseClass.JSON_NULL);
16813
16814 LitJson.JsonType elemType = elem.GetJsonType();
16815 switch (elemType)
16816 {
16817 case LitJson.JsonType.Int:
16818 return (new LSL_Integer((int)elem));
16819 case LitJson.JsonType.Boolean:
16820 return ((bool)elem ? (LSL_String)ScriptBaseClass.JSON_TRUE : (LSL_String)ScriptBaseClass.JSON_FALSE);
16821 case LitJson.JsonType.Double:
16822 return (new LSL_Float((double)elem));
16823 case LitJson.JsonType.None:
16824 return ((LSL_String)ScriptBaseClass.JSON_NULL);
16825 case LitJson.JsonType.String:
16826 return (new LSL_String((string)elem));
16827 case LitJson.JsonType.Array:
16828 case LitJson.JsonType.Object:
16829 string s = LitJson.JsonMapper.ToJson(elem);
16830 return (LSL_String)s;
16831 default:
16832 throw new Exception(ScriptBaseClass.JSON_INVALID);
16833 }
16834 }
16835
16836 public LSL_String llList2Json(LSL_String type, LSL_List values)
16837 {
16838 try
16839 {
16840 StringBuilder sb = new StringBuilder();
16841 if (type == ScriptBaseClass.JSON_ARRAY)
16842 {
16843 sb.Append("[");
16844 int i= 0;
16845 foreach (object o in values.Data)
16846 {
16847 sb.Append(ListToJson(o));
16848 if((i++) < values.Data.Length - 1)
16849 sb.Append(",");
16850 }
16851 sb.Append("]");
16852 return (LSL_String)sb.ToString();;
16853 }
16854 else if (type == ScriptBaseClass.JSON_OBJECT)
16855 {
16856 sb.Append("{");
16857 for (int i = 0; i < values.Data.Length; i += 2)
16858 {
16859 if (!(values.Data[i] is LSL_String))
16860 return ScriptBaseClass.JSON_INVALID;
16861 string key = ((LSL_String)values.Data[i]).m_string;
16862 key = EscapeForJSON(key, true);
16863 sb.Append(key);
16864 sb.Append(":");
16865 sb.Append(ListToJson(values.Data[i+1]));
16866 if(i < values.Data.Length - 2)
16867 sb.Append(",");
16868 }
16869 sb.Append("}");
16870 return (LSL_String)sb.ToString();
16871 }
16872 return ScriptBaseClass.JSON_INVALID;
16873 }
16874 catch
16875 {
16876 return ScriptBaseClass.JSON_INVALID;
16877 }
16878 }
16879
16880 private string ListToJson(object o)
16881 {
16882 if (o is LSL_Float || o is double)
16883 {
16884 double float_val;
16885 if (o is double)
16886 float_val = ((double)o);
16887 else
16888 float_val = ((LSL_Float)o).value;
16889
16890 if(double.IsInfinity(float_val))
16891 return "\"Inf\"";
16892 if(double.IsNaN(float_val))
16893 return "\"NaN\"";
16894
16895 return ((LSL_Float)float_val).ToString();
16896 }
16897 if (o is LSL_Integer || o is int)
16898 {
16899 int i;
16900 if (o is int)
16901 i = ((int)o);
16902 else
16903 i = ((LSL_Integer)o).value;
16904 return i.ToString();
16905 }
16906 if (o is LSL_Rotation)
16907 {
16908 StringBuilder sb = new StringBuilder(128);
16909 sb.Append("\"");
16910 LSL_Rotation r = (LSL_Rotation)o;
16911 sb.Append(r.ToString());
16912 sb.Append("\"");
16913 return sb.ToString();
16914 }
16915 if (o is LSL_Vector)
16916 {
16917 StringBuilder sb = new StringBuilder(128);
16918 sb.Append("\"");
16919 LSL_Vector v = (LSL_Vector)o;
16920 sb.Append(v.ToString());
16921 sb.Append("\"");
16922 return sb.ToString();
16923 }
16924 if (o is LSL_String || o is string)
16925 {
16926 string str;
16927 if (o is string)
16928 str = ((string)o);
16929 else
16930 str = ((LSL_String)o).m_string;
16931
16932 if(str == ScriptBaseClass.JSON_TRUE || str == "true")
16933 return "true";
16934 if(str == ScriptBaseClass.JSON_FALSE ||str == "false")
16935 return "false";
16936 if(str == ScriptBaseClass.JSON_NULL || str == "null")
16937 return "null";
16938 str.Trim();
16939 if (str[0] == '{')
16940 return str;
16941 if (str[0] == '[')
16942 return str;
16943 return EscapeForJSON(str, true);
16944 }
16945 throw new IndexOutOfRangeException();
16946 }
16947
16948 private string EscapeForJSON(string s, bool AddOuter)
16949 {
16950 int i;
16951 char c;
16952 String t;
16953 int len = s.Length;
16954
16955 StringBuilder sb = new StringBuilder(len + 64);
16956 if(AddOuter)
16957 sb.Append("\"");
16958
16959 for (i = 0; i < len; i++)
16960 {
16961 c = s[i];
16962 switch (c)
16963 {
16964 case '\\':
16965 case '"':
16966 case '/':
16967 sb.Append('\\');
16968 sb.Append(c);
16969 break;
16970 case '\b':
16971 sb.Append("\\b");
16972 break;
16973 case '\t':
16974 sb.Append("\\t");
16975 break;
16976 case '\n':
16977 sb.Append("\\n");
16978 break;
16979 case '\f':
16980 sb.Append("\\f");
16981 break;
16982 case '\r':
16983 sb.Append("\\r");
16984 break;
16985 default:
16986 if (c < ' ')
16987 {
16988 t = "000" + String.Format("X", c);
16989 sb.Append("\\u" + t.Substring(t.Length - 4));
16990 }
16991 else
16992 {
16993 sb.Append(c);
16994 }
16995 break;
16996 }
16997 }
16998 if(AddOuter)
16999 sb.Append("\"");
17000 return sb.ToString();
17001 }
17002
17003 public LSL_String llJsonSetValue(LSL_String json, LSL_List specifiers, LSL_String value)
17004 {
17005 bool noSpecifiers = specifiers.Length == 0;
17006 LitJson.JsonData workData;
17007 try
17008 {
17009 if(noSpecifiers)
17010 specifiers.Add(new LSL_Integer(0));
17011
17012 if(!String.IsNullOrEmpty(json))
17013 workData = LitJson.JsonMapper.ToObject(json);
17014 else
17015 {
17016 workData = new LitJson.JsonData();
17017 workData.SetJsonType(LitJson.JsonType.Array);
17018 }
17019 }
17020 catch (Exception e)
17021 {
17022 string m = e.Message; // debug point
17023 return ScriptBaseClass.JSON_INVALID;
17024 }
17025 try
17026 {
17027 LitJson.JsonData replace = JsonSetSpecific(workData, specifiers, 0, value);
17028 if(replace != null)
17029 workData = replace;
17030 }
17031 catch (Exception e)
17032 {
17033 string m = e.Message; // debug point
17034 return ScriptBaseClass.JSON_INVALID;
17035 }
17036
17037 try
17038 {
17039 string r = LitJson.JsonMapper.ToJson(workData);
17040 if(noSpecifiers)
17041 r = r.Substring(1,r.Length -2); // strip leading and trailing brakets
17042 return r;
17043 }
17044 catch (Exception e)
17045 {
17046 string m = e.Message; // debug point
17047 }
17048 return ScriptBaseClass.JSON_INVALID;
17049 }
17050
17051 private LitJson.JsonData JsonSetSpecific(LitJson.JsonData elem, LSL_List specifiers, int level, LSL_String val)
17052 {
17053 object spec = specifiers.Data[level];
17054 if(spec is LSL_String)
17055 spec = ((LSL_String)spec).m_string;
17056 else if (spec is LSL_Integer)
17057 spec = ((LSL_Integer)spec).value;
17058
17059 if(!(spec is string || spec is int))
17060 throw new IndexOutOfRangeException();
17061
17062 int speclen = specifiers.Data.Length - 1;
17063
17064 bool hasvalue = false;
17065 LitJson.JsonData value = null;
17066
17067 LitJson.JsonType elemType = elem.GetJsonType();
17068 if (elemType == LitJson.JsonType.Array)
17069 {
17070 if (spec is int)
17071 {
17072 int v = (int)spec;
17073 int c = elem.Count;
17074 if(v < 0 || (v != 0 && v > c))
17075 throw new IndexOutOfRangeException();
17076 if(v == c)
17077 elem.Add(JsonBuildRestOfSpec(specifiers, level + 1, val));
17078 else
17079 {
17080 hasvalue = true;
17081 value = elem[v];
17082 }
17083 }
17084 else if (spec is string)
17085 {
17086 if((string)spec == ScriptBaseClass.JSON_APPEND)
17087 elem.Add(JsonBuildRestOfSpec(specifiers, level + 1, val));
17088 else if(elem.Count < 2)
17089 {
17090 // our initial guess of array was wrong
17091 LitJson.JsonData newdata = new LitJson.JsonData();
17092 newdata.SetJsonType(LitJson.JsonType.Object);
17093 IOrderedDictionary no = newdata as IOrderedDictionary;
17094 no.Add((string)spec,JsonBuildRestOfSpec(specifiers, level + 1, val));
17095 return newdata;
17096 }
17097 }
17098 }
17099 else if (elemType == LitJson.JsonType.Object)
17100 {
17101 if (spec is string)
17102 {
17103 IOrderedDictionary e = elem as IOrderedDictionary;
17104 string key = (string)spec;
17105 if(e.Contains(key))
17106 {
17107 hasvalue = true;
17108 value = (LitJson.JsonData)e[key];
17109 }
17110 else
17111 e.Add(key, JsonBuildRestOfSpec(specifiers, level + 1, val));
17112 }
17113 else if(spec is int && (int)spec == 0)
17114 {
17115 //we are replacing a object by a array
17116 LitJson.JsonData newData = new LitJson.JsonData();
17117 newData.SetJsonType(LitJson.JsonType.Array);
17118 newData.Add(JsonBuildRestOfSpec(specifiers, level + 1, val));
17119 return newData;
17120 }
17121 }
17122 else
17123 {
17124 LitJson.JsonData newData = JsonBuildRestOfSpec(specifiers, level, val);
17125 return newData;
17126 }
17127
17128 if (hasvalue)
17129 {
17130 if (level < speclen)
17131 {
17132 LitJson.JsonData replace = JsonSetSpecific(value, specifiers, level + 1, val);
17133 if(replace != null)
17134 {
17135 if(elemType == LitJson.JsonType.Array)
17136 {
17137 if(spec is int)
17138 elem[(int)spec] = replace;
17139 else if( spec is string)
17140 {
17141 LitJson.JsonData newdata = new LitJson.JsonData();
17142 newdata.SetJsonType(LitJson.JsonType.Object);
17143 IOrderedDictionary no = newdata as IOrderedDictionary;
17144 no.Add((string)spec, replace);
17145 return newdata;
17146 }
17147 }
17148 else if(elemType == LitJson.JsonType.Object)
17149 {
17150 if(spec is string)
17151 elem[(string)spec] = replace;
17152 else if(spec is int && (int)spec == 0)
17153 {
17154 LitJson.JsonData newdata = new LitJson.JsonData();
17155 newdata.SetJsonType(LitJson.JsonType.Array);
17156 newdata.Add(replace);
17157 return newdata;
17158 }
17159 }
17160 }
17161 return null;
17162 }
17163 else if(speclen == level)
17164 {
17165 if(val == ScriptBaseClass.JSON_DELETE)
17166 {
17167 if(elemType == LitJson.JsonType.Array)
17168 {
17169 if(spec is int)
17170 {
17171 IList el = elem as IList;
17172 el.RemoveAt((int)spec);
17173 }
17174 }
17175 else if(elemType == LitJson.JsonType.Object)
17176 {
17177 if(spec is string)
17178 {
17179 IOrderedDictionary eo = elem as IOrderedDictionary;
17180 eo.Remove((string) spec);
17181 }
17182 }
17183 return null;
17184 }
17185
17186 LitJson.JsonData newval = null;
17187 float num;
17188 if(val == null || val == ScriptBaseClass.JSON_NULL || val == "null")
17189 newval = null;
17190 else if(val == ScriptBaseClass.JSON_TRUE || val == "true")
17191 newval = new LitJson.JsonData(true);
17192 else if(val == ScriptBaseClass.JSON_FALSE || val == "false")
17193 newval = new LitJson.JsonData(false);
17194 else if(float.TryParse(val, out num))
17195 {
17196 // assuming we are at en.us already
17197 if(num - (int)num == 0.0f && !val.Contains("."))
17198 newval = new LitJson.JsonData((int)num);
17199 else
17200 {
17201 num = (float)Math.Round(num,6);
17202 newval = new LitJson.JsonData((double)num);
17203 }
17204 }
17205 else
17206 {
17207 string str = val.m_string;
17208 newval = new LitJson.JsonData(str);
17209 }
17210
17211 if(elemType == LitJson.JsonType.Array)
17212 {
17213 if(spec is int)
17214 elem[(int)spec] = newval;
17215 else if( spec is string)
17216 {
17217 LitJson.JsonData newdata = new LitJson.JsonData();
17218 newdata.SetJsonType(LitJson.JsonType.Object);
17219 IOrderedDictionary no = newdata as IOrderedDictionary;
17220 no.Add((string)spec,newval);
17221 return newdata;
17222 }
17223 }
17224 else if(elemType == LitJson.JsonType.Object)
17225 {
17226 if(spec is string)
17227 elem[(string)spec] = newval;
17228 else if(spec is int && (int)spec == 0)
17229 {
17230 LitJson.JsonData newdata = new LitJson.JsonData();
17231 newdata.SetJsonType(LitJson.JsonType.Array);
17232 newdata.Add(newval);
17233 return newdata;
17234 }
17235 }
17236 }
17237 }
17238 if(val == ScriptBaseClass.JSON_DELETE)
17239 throw new IndexOutOfRangeException();
17240 return null;
17241 }
17242
17243 private LitJson.JsonData JsonBuildRestOfSpec(LSL_List specifiers, int level, LSL_String val)
17244 {
17245 object spec = level >= specifiers.Data.Length ? null : specifiers.Data[level];
17246 // 20131224 not used object specNext = i+1 >= specifiers.Data.Length ? null : specifiers.Data[i+1];
17247
17248 float num;
17249 if (spec == null)
17250 {
17251 if(val == null || val == ScriptBaseClass.JSON_NULL || val == "null")
17252 return null;
17253 if(val == ScriptBaseClass.JSON_DELETE)
17254 throw new IndexOutOfRangeException();
17255 if(val == ScriptBaseClass.JSON_TRUE || val == "true")
17256 return new LitJson.JsonData(true);
17257 if(val == ScriptBaseClass.JSON_FALSE || val == "false")
17258 return new LitJson.JsonData(false);
17259 if(val == null || val == ScriptBaseClass.JSON_NULL || val == "null")
17260 return null;
17261 if(float.TryParse(val, out num))
17262 {
17263 // assuming we are at en.us already
17264 if(num - (int)num == 0.0f && !val.Contains("."))
17265 return new LitJson.JsonData((int)num);
17266 else
17267 {
17268 num = (float)Math.Round(num,6);
17269 return new LitJson.JsonData(num);
17270 }
17271 }
17272 else
17273 {
17274 string str = val.m_string;
17275 return new LitJson.JsonData(str);
17276 }
17277 throw new IndexOutOfRangeException();
17278 }
17279
17280 if(spec is LSL_String)
17281 spec = ((LSL_String)spec).m_string;
17282 else if (spec is LSL_Integer)
17283 spec = ((LSL_Integer)spec).value;
17284
17285 if (spec is int ||
17286 (spec is string && ((string)spec) == ScriptBaseClass.JSON_APPEND) )
17287 {
17288 if(spec is int && (int)spec != 0)
17289 throw new IndexOutOfRangeException();
17290 LitJson.JsonData newdata = new LitJson.JsonData();
17291 newdata.SetJsonType(LitJson.JsonType.Array);
17292 newdata.Add(JsonBuildRestOfSpec(specifiers, level + 1, val));
17293 return newdata;
17294 }
17295 else if (spec is string)
17296 {
17297 LitJson.JsonData newdata = new LitJson.JsonData();
17298 newdata.SetJsonType(LitJson.JsonType.Object);
17299 IOrderedDictionary no = newdata as IOrderedDictionary;
17300 no.Add((string)spec,JsonBuildRestOfSpec(specifiers, level + 1, val));
17301 return newdata;
17302 }
17303 throw new IndexOutOfRangeException();
17304 }
17305
17306 private bool JsonFind(LitJson.JsonData elem, LSL_List specifiers, int level, out LitJson.JsonData value)
17307 {
17308 value = null;
17309 if(elem == null)
17310 return false;
17311
17312 object spec;
17313 spec = specifiers.Data[level];
17314
17315 bool haveVal = false;
17316 LitJson.JsonData next = null;
17317
17318 if (elem.GetJsonType() == LitJson.JsonType.Array)
17319 {
17320 if (spec is LSL_Integer)
17321 {
17322 int indx = (LSL_Integer)spec;
17323 if(indx >= 0 && indx < elem.Count)
17324 {
17325 haveVal = true;
17326 next = (LitJson.JsonData)elem[indx];
17327 }
17328 }
17329 }
17330 else if (elem.GetJsonType() == LitJson.JsonType.Object)
17331 {
17332 if (spec is LSL_String)
17333 {
17334 IOrderedDictionary e = elem as IOrderedDictionary;
17335 string key = (LSL_String)spec;
17336 if(e.Contains(key))
17337 {
17338 haveVal = true;
17339 next = (LitJson.JsonData)e[key];
17340 }
17341 }
17342 }
17343
17344 if (haveVal)
17345 {
17346 if(level == specifiers.Data.Length - 1)
17347 {
17348 value = next;
17349 return true;
17350 }
17351
17352 level++;
17353 if(next == null)
17354 return false;
17355
17356 LitJson.JsonType nextType = next.GetJsonType();
17357 if(nextType != LitJson.JsonType.Object && nextType != LitJson.JsonType.Array)
17358 return false;
17359
17360 return JsonFind(next, specifiers, level, out value);
17361 }
17362 return false;
17363 }
17364
17365 public LSL_String llJsonGetValue(LSL_String json, LSL_List specifiers)
17366 {
17367 if(String.IsNullOrWhiteSpace(json))
17368 return ScriptBaseClass.JSON_INVALID;
17369
17370 if(specifiers.Length > 0 && (json == "{}" || json == "[]"))
17371 return ScriptBaseClass.JSON_INVALID;
17372
17373 char first = ((string)json)[0];
17374 if((first != '[' && first !='{'))
17375 {
17376 if(specifiers.Length > 0)
17377 return ScriptBaseClass.JSON_INVALID;
17378 json = "[" + json + "]"; // could handle single element case.. but easier like this
17379 specifiers.Add((LSL_Integer)0);
17380 }
17381
17382 LitJson.JsonData jsonData;
17383 try
17384 {
17385 jsonData = LitJson.JsonMapper.ToObject(json);
17386 }
17387 catch (Exception e)
17388 {
17389 string m = e.Message; // debug point
17390 return ScriptBaseClass.JSON_INVALID;
17391 }
17392
17393 LitJson.JsonData elem = null;
17394 if(specifiers.Length == 0)
17395 elem = jsonData;
17396 else
17397 {
17398 if(!JsonFind(jsonData, specifiers, 0, out elem))
17399 return ScriptBaseClass.JSON_INVALID;
17400 }
17401 return JsonElementToString(elem);
17402 }
17403
17404 private LSL_String JsonElementToString(LitJson.JsonData elem)
17405 {
17406 if(elem == null)
17407 return ScriptBaseClass.JSON_NULL;
17408
17409 LitJson.JsonType elemType = elem.GetJsonType();
17410 switch(elemType)
17411 {
17412 case LitJson.JsonType.Array:
17413 return new LSL_String(LitJson.JsonMapper.ToJson(elem));
17414 case LitJson.JsonType.Boolean:
17415 return new LSL_String((bool)elem ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE);
17416 case LitJson.JsonType.Double:
17417 double d= (double)elem;
17418 string sd = String.Format(Culture.FormatProvider, "{0:0.0#####}",d);
17419 return new LSL_String(sd);
17420 case LitJson.JsonType.Int:
17421 int i = (int)elem;
17422 return new LSL_String(i.ToString());
17423 case LitJson.JsonType.Long:
17424 long l = (long)elem;
17425 return new LSL_String(l.ToString());
17426 case LitJson.JsonType.Object:
17427 return new LSL_String(LitJson.JsonMapper.ToJson(elem));
17428 case LitJson.JsonType.String:
17429 string s = (string)elem;
17430 return new LSL_String(s);
17431 case LitJson.JsonType.None:
17432 return ScriptBaseClass.JSON_NULL;
17433 default:
17434 return ScriptBaseClass.JSON_INVALID;
17435 }
17436 }
17437
17438 public LSL_String llJsonValueType(LSL_String json, LSL_List specifiers)
17439 {
17440 if(String.IsNullOrWhiteSpace(json))
17441 return ScriptBaseClass.JSON_INVALID;
17442
17443 if(specifiers.Length > 0 && (json == "{}" || json == "[]"))
17444 return ScriptBaseClass.JSON_INVALID;
17445
17446 char first = ((string)json)[0];
17447 if((first != '[' && first !='{'))
17448 {
17449 if(specifiers.Length > 0)
17450 return ScriptBaseClass.JSON_INVALID;
17451 json = "[" + json + "]"; // could handle single element case.. but easier like this
17452 specifiers.Add((LSL_Integer)0);
17453 }
17454
17455 LitJson.JsonData jsonData;
17456 try
17457 {
17458 jsonData = LitJson.JsonMapper.ToObject(json);
17459 }
17460 catch (Exception e)
17461 {
17462 string m = e.Message; // debug point
17463 return ScriptBaseClass.JSON_INVALID;
17464 }
17465
17466 LitJson.JsonData elem = null;
17467 if(specifiers.Length == 0)
17468 elem = jsonData;
17469 else
17470 {
17471 if(!JsonFind(jsonData, specifiers, 0, out elem))
17472 return ScriptBaseClass.JSON_INVALID;
17473 }
17474
17475 if(elem == null)
17476 return ScriptBaseClass.JSON_NULL;
17477
17478 LitJson.JsonType elemType = elem.GetJsonType();
17479 switch(elemType)
17480 {
17481 case LitJson.JsonType.Array:
17482 return ScriptBaseClass.JSON_ARRAY;
17483 case LitJson.JsonType.Boolean:
17484 return (bool)elem ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE;
17485 case LitJson.JsonType.Double:
17486 case LitJson.JsonType.Int:
17487 case LitJson.JsonType.Long:
17488 return ScriptBaseClass.JSON_NUMBER;
17489 case LitJson.JsonType.Object:
17490 return ScriptBaseClass.JSON_OBJECT;
17491 case LitJson.JsonType.String:
17492 string s = (string)elem;
17493 if(s == ScriptBaseClass.JSON_NULL)
17494 return ScriptBaseClass.JSON_NULL;
17495 if(s == ScriptBaseClass.JSON_TRUE)
17496 return ScriptBaseClass.JSON_TRUE;
17497 if(s == ScriptBaseClass.JSON_FALSE)
17498 return ScriptBaseClass.JSON_FALSE;
17499 return ScriptBaseClass.JSON_STRING;
17500 case LitJson.JsonType.None:
17501 return ScriptBaseClass.JSON_NULL;
17502 default:
17503 return ScriptBaseClass.JSON_INVALID;
17504 }
17505 }
14984 } 17506 }
14985 17507
14986 public class NotecardCache 17508 public class NotecardCache